mjpegtools-2.1.0/0000755000175000017500000000000012224555224014214 5ustar glowwormglowwormmjpegtools-2.1.0/ChangeLog0000644000175000017500000001420511563467250015776 0ustar glowwormglowworm2000-08-15 Gernot Ziegler * Created intial automake & autoconf files (still lot of bugs, I guess ;) ) * Created libmovtar (read/write support not complete yet) * Created libmjpeg 2000-12-07 Andrew Stevens (as@comlab.ox.ac.uk) * 1.3b2 release. Tag: Rel1_3Beta2 * Initial support for Software-only mjpeg playback. * Seperated mpeg encoding tools from tools used to extract raw audio/video from mjpeg. * Initial support for transcoding using patched mpeg2dec and ac3dec packages. * Further speed and quality improvements to MPEG-1 encoding with mpeg2enc. Bugs fixed. Run-time selection of MMX/extended MMX/SSE/3D-Now! routines as appropriate. * mplex now much faster, debugged, and supports correct VCD compatible multiplexing and splitting of streams into multiple files. Initial MPEG-2 video support. Supports layer 3 audio and (hopefully) MPEG audio V2 and V2.5 though these don't look too useful... * Bug fixes and support for software-only playback of mjpeg. 2001-01-25 Andrew Stevens (as@comlab.ox.ac.uk) * 1.3b3 release. Tag: Rel1_3Beta3 * Refinement if field based motion compensation type selection. Replacing sad with variance as selection criterion. * Initial SVCD support in mplex and mpeg2enc. Initial support for handling poor chrominance matching in motion compensation. * Support for new combined LML33/buz/DC10/DC10+ driver. * Support for 422 MJPEG from xawtv capture tool. * More robust audio driver handling (SB-Live now works!). 2001-01-25 Andrew Stevens (as@comlab.ox.ac.uk) * 1.4 release Tag: Rel1_4 * Dynamic GOP sizing and SMP support in mpeg2enc. Minor refinements to motion compensation. * Signficant enhancement and bug-fixing of lavrec and lavtools. * Addition of yuvscaler and yuvplay, ypipe and yuv2lav utilities * Unified output logging format and consistent command line flags. * Lots of bug fixes. * Man pages. * Binary packages. 2001-06-21 Andrew Stevens (as@comlab.ox.ac.uk) * 1.5 series * Single pass multiplexer. VBR audio multiplexing support. * Splitting mpeg encoder into re-entrant library and front-end(s). * Switch to multi-frame ppm CVS log: $Log: ChangeLog,v $ Revision 1.16 2011/05/14 11:59:36 waldviertler documented some (hopefully most to all) changes since the last release Revision 1.15 2008/11/29 19:31:20 wackston2 Trial fix: stop sampling frames at Q floor (where Actual bits *expected* to be < Target bits) to compute mean Target/Actual ratio after pass2 reencoding. Tidying: remove some redundant inclusion of config.h Revision 1.14 2001/07/08 21:21:15 wackston Added VBR audio support. Fixed wav headers so they indicate a long not a short stream if header is aborted... Revision 1.13 2001/06/23 14:14:41 wackston First stage of single-pass muxing. Video now single-pass. Revision 1.12 2001/05/26 12:37:50 wackston Tidying doco for packaging... Revision 1.11 2001/05/10 19:52:36 wackston Tidyings and fixing up to the 1.4 release. Revision 1.10 2001/05/06 15:59:15 wackston Bug fix for m/c type select in motion.c also made field M/C use chroma info. Minor fixes elewhere related consistenct logging / command lines. Revision 1.9 2001/02/07 14:45:05 wackston Minor tidyings and bug-fixes ready for 1.3b3 release. Revision 1.8 2001/01/25 20:11:29 wackston Initial SVCD support in mplex. Update TODO files.. Revision 1.7 2000/12/19 14:34:06 wackston *** empty log message *** Revision 1.6 2000/12/19 14:29:14 wackston Tagging for beta2 release. Revision 1.5 2000/12/15 19:34:09 wackston MPEG-2 encoding has been restored to working order. Still some doubts about whether its 100% correct again but as far as I can tell any remaining bugs are just sub-optimality rather than crass errors. mplex now support MPEG-2 mux-ing *and* layer 3 audio. Revision 1.4 2000/12/07 19:09:04 wackston *** empty log message *** Revision 1.3 2000/12/07 16:44:50 wackston Still more minor updates to doco files for release. Revision 1.2 2000/12/05 09:34:05 wackston Put Log substiution into ChangeLog Changes to lavtools-1.2 - A.Stevens Merged in improvements to mpeg2enc plus useful additional tools. - G.Ziegler Initial merge of mmx-ed JPEG libs and movtar support. Detached jpeg-6b-mmx and libmovtar into own packages. Changes to lavtools-1.1 - added MPEG video and audi encoders for usage with AVI/Quicktime files and Edit lists - lavplay now can not more output files from edit lists, this is taken over by lavtrans in the utils directory - lavrec: different decimations in x and y direction possibility to capture sub areas time lapse - lavplay: "zoom to fit" - xlav: better user interface - device names for video/audio/mixer device may be set by environment variables - much more small things Changes to lavtools-1.0 - Full Quicktime support in recording and playing - Support of multiple files to overcome 2 GB limit - perfect audio/video synchronization in recording and playback for lip-synchronous videos even after hours of playing. - single frame (is it called stop motion?) capture - GUI to lavplay - use your linux PC as a great video recorder - support of (simple) editing in the GUI: cut your video clips as you like - lavplay supports concatenating video clips, splitting off audio separating video into single images - option in lavrec to wait for user input before starting - support for other audio input sources in lavrec - steering of lavplay (forward, backward, pause etc.) with commands (for real command line hardliners) Changes to lavtools 1.9.0 (in no particular order) - added changes to support the compiling for new CPUs - some autoconf/configure fixes (x11 and other libs - patch to compile png2yuv with newer png lib - clean upf for vrious compiling problems - jpegutil fix for neser libjpeg - mpeg2enc some more two-pass encoding support - mpeg2enc fixes for bit rate problems - mplex added support for subtitle streams from tcextract - mplex small fixes - y4mdenoise better, faster, fixed the problem in dark/cloudy areas - fixes for the __progname problem - yuvdenoise god speed up by a SSE2 ASM version of some code mjpegtools-2.1.0/README.transist0000644000175000017500000000775707755455400016772 0ustar glowwormglowwormThis file describes how to make a transistion from one video file to another using the current sample implementations. Especially ypipe will be replaced (hopefully) soon by a more capable program. The programs involved in this process are: - lav2yuv, which decompresses the given input files (or any portions of them) and gives us raw yuv frame streams that can be piped through the several tools. - ypipe, which starts two instances of lav2yuv and combines the two input streams into one, in which every even frame is from the first and every odd frame from the second input. - transist.flt, which takes the frame-interlaced stream from ypipe and writes out the final transistion. - yuv2lav or mpeg2enc, which compress the resulting yuv stream into an mjpeg or mpeg file. Let's assume simple this scenery: We have two input videos, intro.avi and epilogue.qt and want make intro.avi transist into epilogue.qt with a duration of one second (that is 25 frames for PAL or 30 frames for NTSC). intro.avi and epiloque.qt have to be of the same format regarding frame rate and image resolution, at the moment. In this example they are both 352x288 PAL files. intro.avi contains 250 frames and epilogue.qt is 1000 frames long. Therefor our output file will contain: - the first 225 frames of intro.avi - a 25 frame transistion containing the last 25 frames of intro.avi and the first 25 frames of epilogue.qt - the last 975 frames of epilogue.qt We could get the last 25 frames of intro.avi by calling: lav2yuv -o 225 -f 25 intro.avi (-o 225, the offset, tells lav2yuv to begin with frame # 225 and -f 25 makes it output 25 frames from there on) Another possibility is: lav2yuv -o -25 intro.avi (negative offsets are counted from the end) And the first 25 frames of epilogue.qt: lav2yuv -f 25 epilogue.qt (-o defaults to an offset of zero) But we need to combine the two streams with ypipe. So the call would be: ypipe "lav2yuv -o 255 -f 25 intro.avi" "lav2yuv -f 25 epilogue.qt" The output of this is a raw yuv stream that can be fed into transist.flt. transist.flt needs to be informed about the duration of the transistion and the opacity of the second stream at the beginning and at the end of the transistion: -o num opacity of second input at the beginning [0-255] -O num opacity of second input at the end [0-255] -d num duration of transistion in frames An opacity of 0 means that the second stream is fully transparent (only stream one visible), at 255 stream two is fully opaque. In our case the correct call (transistion from stream 1 to stream 2) would be: transist.flt -o 0 -O 255 -d 25 The -s and -n parameters equal to the -o and -f parameters of lav2yuv and are only needed if anybody wants to render only a portion of the transistion for whatever reason. Please note that this only affects the weighting calculations - none of the input is really skipped, so that if you pass the skip parameter (-s 30, for example), you also need to skip the first 30 frames in lav2yuv (-o 30) in order to get the expected result. If you didn't understand this, send an email to the authors or simply ignore -s and -n. The whole procedure will be automated later, anyway. Now we want to compress the yuv stream with yuv2lav. yuv2lav -f a -q 80 -o transistion.avi Reads the yuv stream from stdin and outputs an avi file (-f a) with compressed jpeg frames of quality 80. Now we have the whole command for creating a transistion: ypipe "lav2yuv -o 255 -f 25 intro.avi" "lav2yuv -f 25 epilogue.qt" | \ transist.flt -o 0 -O 255 -d 25 | yuv2lav -f a -q 80 -o transistion.avi (This is one line.) The resulting video can be written as a LAV Edit List, a plain text file containing the following lines: LAV Edit List PAL 3 intro.avi transistion.avi epilogue.qt 0 0 224 1 0 24 2 25 999 This file can be fed into xlav or lavplay, or you can pipe it into mpeg2enc with lav2yuv or combine the whole stuff into one single mjpeg file with lavtrans or lav2yuv|yuv2lav. mjpegtools-2.1.0/COPYING0000644000175000017500000004311010101003235015224 0ustar glowwormglowworm GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. mjpegtools-2.1.0/NEWS0000644000175000017500000000007610500162201014676 0ustar glowwormglowwormSigh - seems that this file is required for autoconf/automake mjpegtools-2.1.0/mjpegtools.pc.in0000644000175000017500000000050410300221070017305 0ustar glowwormglowwormprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@/@PACKAGE@ Name: MJPEG-tools Description: Video-recording, -editing, -filtering and -encoding tools Version: @VERSION@ Libs: -L${libdir} -lmjpegutils @ALTIVEC_EXTRA_LIBS@ Cflags: -I${includedir} -I${includedir}/mpeg2enc -I${includedir}/mplex mjpegtools-2.1.0/README.lavpipe0000644000175000017500000002423710105600610016525 0ustar glowwormglowworm This README describes the lavpipe tools: how to use them, and how they work (partially). The current implementation still is not tested very well, so be warned (and please report any errors you encounter). At the moment, there are only two filters for lavpipe, transist.flt and matteblend.flt, which means that you can use it only to make simple blending transistions between two movies or to blend one video over another using a predefined matte (yuv image or lav movie). But it is very easy to code new filters or extend existing ones. Read on. Contents: 1. What are the tools? 2. What can we do with it? 3. What else can we do with it? 4. That's all?! How can we make them do more? _____________________________________________________________________________ \ 1. What are the tools? / ____________________________________________________________________________/ The tools that are involved so far are: - lav2yuv, which decompresses the given input files (or any portions of them) and gives us raw yuv frame streams that can be piped through the several tools. - lavpipe, which reads out a "LAV Pipe List" (e.g. *.pli) file, a "recipe" which tells it how to combine several input movies using several yuv stream filters. - transist.flt and matteblend.flt, all the filters that already exist. - yuv2lav or mpeg2enc, which compress the resulting yuv stream into an mjpeg or mpeg file. _____________________________________________________________________________ \ 2. So hat can we do with it? / ____________________________________________________________________________/ Example one: Make a transistion from one movie to another one. Let's assume that we have got two 352x288 PAL files: intro.avi (1040 frames) and epilogue.qt (3920 frames). Now we want to make a transistion between them that lasts for two seconds (2 sec = 50 frames, as they are PAL movies). We also have to take care that both share the same dimensions - if they are of different sizes, we can use lavscale once it is finished. Our task now is to write a "recipe" for lavpipe and thus tell it how to do the work. If we store our work as trans.pli, the final call will simply be: "lavpipe trans.pli | yuv2lav -o result.avi" (lavpipe writes a yuv stream to stdout as lav2yuv does). The first line of trans.pli must be "LAV Pipe List". The second line contains one single number, the number of input streams that we will use. (In our case: "2") Now for each of the two input streams a line containing the command that produces the stream is added. First for intro.avi: "lav2yuv -o $o -f $n -n 1 intro.avi" The -o $o and -f $n parameters are necessary as lavpipe somehow has to inform lav2yuv which frames it should output. $o will be replaced by the offset and $n will be replaced by the number of frames that lavpipe wants lav2yuv to output. The -n 1 parameter is of course optional, and any other parameters to lav2yuv could be added. The second line for epilogue.qt might look like this: "lav2yuv -o $o -f $n epilogue.qt" Now follow all the sequences of the Pipe List, each of which consists of a listing of the input streams used and a command line to the filter program. The first sequence will simply reproduce all but the last 50 frames of intro.avi (that are 1040 - 50 = 990 frames). Its first line only contains "990", the number of frames. The second line is "1", the number of streams used. The next line contains the index of the stream to use and the offset (how many frames to skip in the beginning). In our case both index and offset are 0, so the line would be: "0 0" Now we would add the command line of the filter program, but as we don't want to invoke any filter here, this line only contains "-", which causes lavpipe to simply output the contents of the stream. The second sequence is the actual transistion. So the first line is "50" (two seconds), the second one "2" (we use both streams). The following line will be "0 990" (intro.avi will be continued at frame 990) and then "1 0" follows (epilogue.qt starts with frame 0). The next line is the filter command, in our case "transist.flt -s $o -n $n -o 0 -O 255 -d 50" The -s $o -n $n parameters equal to the -o $o -f $n parameters of lav2yuv, -o 0 means that at the beginning of the transistion, only intro.avi is visible (opacity of epilogue.qt = 0). As you would have expected, -O 255 means that at the end of the transistion, only epilogue.qt is visible (opacity of epilogue.qt = 255 = 100%) - the opacity will be linearly interpolated inbetween. And finally -d 50 is the duration of the transistion in frames and should be equal to the first line (duration in frames) of the sequence in most cases. The last sequence continues with only epilogue.qt (the last 3870 frames), thus the first line is "3870". The second line is "1" (only one stream), then "1 50" follows (epilogue.qt, beginning with frame 50). The filter command line is "-" again. Finally, our Pipe List file should look like this: --------------------< trans.pli >-------------------------- LAV Pipe List 2 lav2yuv -o $o -f $n -n 1 intro.avi lav2yuv -o $o -f $n epilogue.qt 990 1 0 0 - 50 2 0 990 1 0 transist.flt -s $o -n $n -o 0 -O 255 -d 25 3870 1 1 50 - --------------------< end of file >------------------------ Remember the call? "lavpipe trans.pli | yuv2lav -o result.avi" should now produce a nice avi file with a nice transistion. _____________________________________________________________________________ \ 3. And what else can we do with it? / ____________________________________________________________________________/ Example two: Blend one movie over another one, using a third one's luminance channel as a matte (alpha channel) for the second one. matteblend.flt has no parameters until now, as its output is independent of the actual position in the stream (only depends on the input frames it is fed). If you read the first example and have understood the pipe list format, it will be easy to write a pipe list for this task. As there still is no bluescreen.flt filter, and it is very time consuming to build an animated matte channel for a given input movie by hand, I will only describe how to blend a static picture (a title or static logo) over a movie. For this you need your input.avi, a picture with an alpha channel. Use for example the GIMP to save the image as plain yuv (pic.yuv) and save its alpha channel as a grayscale plain yuv (matte.yuv - its chrominance channels will be ignored). Of course the must be of the right size. Now create this simple shell script that will output an infinite yuv stream that only contains the given plain yuv picture: --------------------< foreveryuv >------------------------- #!/bin/sh echo "YUV4MPEG 352 288 3" while true do echo "FRAME" cat $1 done --------------------< end of file >------------------------ And write the pipe list: --------------------< title.pli >-------------------------- LAV Pipe List 3 lav2yuv -o $o -f $n input.avi foreveryuv pic.yuv foreveryuv matte.yuv 75 3 0 0 1 0 2 0 1000000 1 0 75 matteblend.flt --------------------< end of file >------------------------ As long as your input.avi is shorter than 1000076 frames, "lavpipe title.pli | yuv2lav -o result.avi" will output the whole movie with the given picture blended over it for the first three seconds. _____________________________________________________________________________ \ 4. That's all?! How can we make them do more? / ____________________________________________________________________________/ The solution is of course to code new filter programs. And of course this is very easy. I want to annote here, that the whole system is not very fool proof at the moment. So if you feed matteblend.flt the wrong number of input streams via lavpipe, you will get funny results, if you get any results at all (without any hint from the programs). Perhaps this could be improved by adding additional (optional) parameters to the YUV4MPEG header line. A filter program consists only of 4 parts: 1. Read input parameters (especially -o and -n, if the output is not only dependent on the input frames but also on some variable parameters that change over time) - optional. 2. Read in and write out the YUV headers, could look like this: int fd_in = 0, fd_out = 1; /* stdin, stdout */ y4m_stream_info_t istream, ostream; int res, width, height, frame_rate_code; y4m_init_stream_info(&istream); y4m_init_frame_info(&iframe); if (y4m_read_stream_header (fd_in, &istream) != Y4M_OK) exit (1); y4m_init_stream_info(&ostream); y4m_copy_stream_info(&ostream,&istream); y4m_write_stream_header (fd_out, width, heigth, frame_rate_code); 3. Allocate the YUV buffer(s) - one for each input stream and perhaps one for the output or an arbitrary number of temporary buffers (no bloated code, please ;-) ) char *yuv_buffer[3]; /* this is one yuv buffer */ yuv_buffer[0] = (char *) malloc(y4m_si_get_plane_length(&istream, 0)); /* Y' */ yuv_buffer[1] = (char *) malloc(y4m_si_get_plane_length(&istream, 1)); /* Cr */ yuv_buffer[2] = (char *) malloc(y4m_si_get_plane_length(&istream, 2)); /* Cb */ 4. The loop - while (number of frames processed) < (-n parameter) 4.1. Read the input frames, one of those for each input stream (e.g. yuv_buffer[123]) while (y4m_read_frame (fd_in, &istream, &iframe, yuv_buffer) == Y4M_OK) { 4.2. Process the input buffers in any way you want. 5. Write out the result: y4m_write_frame(fd_out, &ostream, &iframe, yuv_buffer); } 6. Clean up: y4m_fini_frame(&iframe); y4m_fini_stream_info(&istream); y4m_fini_stream_info(&ostream); That's all. You should in any case have a look at the existing filters, transist.flt.c and matteblend.flt.c. - pHilipp Zabel mjpegtools-2.1.0/Makefile.am0000644000175000017500000000350312052075211016241 0ustar glowwormglowworm# Process with automake to produce Makefile.in # NOTE: utils and mpeg2enc MUST be built first so that libmjpegutils AND # libmpeg2encpp exist. Then in the following Makefile.am files if # HAVE_ALTIVEC is defined libmpeg2encpp will be added to the list of # libraries dependencies. All this because utils/altivec/libaltivec.la # contains routines which which should have gone into the encoder # library libmpeg2encpp. Sigh. Feel free to do it differently if you # can come up with a better method. SUBDIRS = \ utils \ mpeg2enc \ lavtools \ aenc \ mplex \ scripts \ docs \ yuvcorrect \ yuvscaler \ yuvdenoise \ yuvfilters \ yuvdeinterlace \ y4mdenoise \ y4mscaler \ y4munsharp \ y4mutils \ debian # # Add any non autoconf'd files here, extra readmes and other misc # info to be copied into the dist # EXTRA_DIST = \ BUGS \ CHANGES \ HINTS \ PLANS \ README.AltiVec \ README.DV \ README.avilib \ README.glav \ README.lavpipe \ README.transist \ INSTALL \ INSTALL.real \ TODO \ cpuinfo.sh \ mjpeg_howto.txt \ mjpegtools.spec \ mjpegtools.spec.in \ mjpegtools.pc \ mjpegtools.pc.in \ autogen.sh pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = mjpegtools.pc DISTCLEANFILES = \ mjpegtools-config.h \ mjpegtools.pc \ confdefs.h \ config.cache \ config.status \ config.log MAINTAINERCLEANFILES = \ compile \ depcomp \ install-sh \ missing \ mkinstalldirs \ Makefile.in \ aclocal.m4 \ config.guess \ config.h.in \ config.sub \ configure \ ltmain.sh \ stamp-h.in ## make rpms rpm: Makefile $(MAKE) dist rpmbuild -ta --clean $(PACKAGE)-$(VERSION).tar.gz ## make debs deb: Makefile dist -chmod -R +w $(PACKAGE)-$(VERSION) rm -rf $(PACKAGE)-$(VERSION) tar xzf $(PACKAGE)-$(VERSION).tar.gz cd $(PACKAGE)-$(VERSION); dpkg-buildpackage -rfakeroot mjpegtools-2.1.0/scripts/0000755000175000017500000000000012217306500015674 5ustar glowwormglowwormmjpegtools-2.1.0/scripts/lav2avi.sh0000755000175000017500000000504010105041642017573 0ustar glowwormglowworm#!/bin/sh ################################################################################ ## CONFIGURATION START ######################################################### ################################################################################ # Choose between 650, 700, 800 # All other values mean maximum preferedSize=700 # Additional parameter for mencoder. For example croping. #encoderParam="-vop crop=690:570:20:6" ################################################################################ ## CONFIGURATION END ########################################################### ################################################################################ # Application variables usage=1 appB="" output=${1%.eli}.avi head "$1" 2> /dev/null | fgrep -q "LAV Edit List" && { if [ -f $output ]; then echo "ERROR: Remove $output file and restart." exit 1 fi usage=0 # # Preparation # rm -f frameno.avi lavc_stats.txt fifo.wav mkfifo fifo.wav # # Pass 1 (Audio encoding) # echo "#########################" echo "# Entering to 1st phase #" echo "#########################" lav2wav $1 > fifo.wav & lav2yuv $1 | mencoder $encoderParam -ovc frameno -oac mp3lame -audiofile fifo.wav -audio-demuxer 17 -o frameno.avi - | tee out1.txt # # Pass 2 # recomBitrate1=`cat out1.txt | fgrep "Recommended video bitrate for ${preferedSize}MB" | cut -c 41-` if [ -n "$recomBitrate1" ]; then appB=":vbitrate=$recomBitrate1" fi echo "##########################################" echo "# Entering to 2nd phase with bitrate $recomBitrate1 #" echo "##########################################" lav2yuv $1 | mencoder $encoderParam -ovc lavc -lavcopts vcodec=mpeg4:vpass=1$appB -oac copy -o /dev/null - > out2.txt | tee out2.txt # # Pass 3 # recomBitrate2=`cat out2.txt | fgrep "Recommended video bitrate for ${preferedSize}MB" | cut -c 41-` if [ -n "$recomBitrate2" ]; then recomBitrate1=$recomBitrate2 appB=":vbitrate=$recomBitrate1" fi echo "##########################################" echo "# Entering to 3rd phase with bitrate $recomBitrate1 #" echo "##########################################" rm -f $output lav2yuv $1 | mencoder $encoderParam -ovc lavc -lavcopts vcodec=mpeg4:vpass=2$appB -oac copy -o $output - rm -f fifo.wav out1.txt out2.txt } if [ $usage -eq 1 ]; then echo -e "USAGE:\t`basename $0` filename.eli" echo -e "\n\tfilename - MJPEG Tools lav editing file\n" echo -e "EXAMPLE:\n\t`basename $0` SecondFilm.eli\n" fi mjpegtools-2.1.0/scripts/anytovcd.sh0000755000175000017500000006530410375136500020076 0ustar glowwormglowworm#!/bin/sh # # anytovcd.sh # # Copyright (C) 2004,2005 Nicolas Boos # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # AUD_TRACK="1" VOLUMES="1" PREFIX_OUT="out" VCD_TYPE="dvd" DEC_TOOL="ffmpeg" ENC_TOOL="mpeg2enc" MATRICES="tmpgenc" QUALITY="best" CQMFILE="matrices.txt" STATFILE="statfile.log" BFR="bfr" FFMPEG="ffmpeg" MPEG2DEC="mpeg2dec" MPEG2ENC="mpeg2enc" MPLEX="mplex" PGMTOY4M="pgmtoy4m" SOX="sox" TCCAT="tccat" TCDEMUX="tcdemux" TCPROBE="tcprobe" TCREQUANT="tcrequant" Y4MDENOISE="y4mdenoise" Y4MSCALER="y4mscaler" Y4MSPATIALFILTER="y4mspatialfilter" Y4MUNSHARP="y4munsharp" YUVDENOISE="yuvdenoise" YUVFPS="yuvfps" YUVMEDIANFILTER="yuvmedianfilter" SCRIPT_NAME="anytovcd.sh" SCRIPT_VERSION="13" # custom quant. matrices INTRA_KVCD="8,9,12,22,26,27,29,34,9,10,14,26,27,29,34,37,12,14,18,27,29,34,37,38,22,26,27,31,36,37,38,40,26,27,29,36,39,38,40,48,27,29,34,37,38,40,48,58,29,34,37,38,40,48,58,69,34,37,38,40,48,58,69,79" INTER_KVCD="16,18,20,22,24,26,28,30,18,20,22,24,26,28,30,32,20,22,24,26,28,30,32,34,22,24,26,30,32,32,34,36,24,26,28,32,34,34,36,38,26,28,30,32,34,36,38,40,28,30,32,34,36,38,42,42,30,32,34,36,38,40,42,44" INTRA_MVCD="8,10,16,20,25,28,33,44,10,10,14,26,27,29,34,47,16,14,18,27,29,34,37,48,20,26,27,31,36,37,38,50,25,27,29,32,37,40,48,58,28,33,36,42,45,50,58,68,33,37,39,44,48,56,66,79,37,39,45,48,56,66,79,83" INTER_MVCD="16,18,20,22,23,27,32,40,18,20,22,24,26,32,36,42,20,22,24,26,33,38,42,44,22,24,26,34,38,42,44,46,23,26,33,38,42,44,46,48,27,32,38,42,44,46,48,50,32,36,42,44,46,48,50,52,40,42,44,46,48,50,52,58" INTRA_TMPGENC="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,40,58,26,27,29,34,38,46,56,69,27,29,35,38,46,56,69,83" INTER_TMPGENC="16,17,18,19,20,21,22,23,17,18,19,20,21,22,23,24,18,19,20,21,22,23,24,25,19,20,21,22,23,24,26,27,20,21,22,23,25,26,27,28,21,22,23,24,26,27,28,30,22,23,24,26,27,28,30,31,23,24,25,27,28,30,31,33" matrix_copy () { # TODO: find less ugly func. echo "`echo "$1" | \ awk -F, '{for (i=1; i<=NF; i++) {n=n$i","; z+=1; if (i==64) {z=0; sub(",$","",n)}; if (z==8) {z=0; n=n"\n"}}; print n}'`" } range_check () { # if input value < min. value if test "$1" -lt "$2"; then # = min. value echo "$2" # if input value > max. value elif test "$1" -gt "$3"; then # = max. value echo "$3" else echo "$1" fi } show_help () { echo "-a audio_track audio track number (default = \"1\")" echo "-A N:D force input pixel aspect ratio" echo "-b blind mode (no video)" echo "-c enable audio pass-through" echo "-d tool_name video decoder tool" echo " avail. : ffmpeg (default) or mpeg2dec" echo "-D deinterlace video (ffmpeg decoder only)" echo "-e tool_name video encoder tool" echo " avail. : mpeg2enc (default) or ffmpeg (experimental)" echo "-i filename input file" echo "-I flag_name force input ilace flag" echo " avail. : none, top_first and bottom_first" echo "-J flag_name force output ilace flag (if possible)" echo " avail. : none, top_first and bottom_first" echo "-f filter1[:filter1_level][,filter2:[filter2_level]]... video filter(s)" echo " avail. filters :" echo " - hqdenoise (y4mdenoise)" echo " - mean (yuvmedianfilter -f)" echo " - median (yuvmedianfilter)" echo " - spatial (y4mspatialfilter)" echo " - temporal (yuvdenoise)" echo " - unsharp (y4munsharp)" echo " avail. levels :" echo " - light (for low noise source)" echo " - medium (for middle noise)" echo " - heavy (for high noise)" echo "-m mute mode (no audio) " echo "-n norm output norm in case of input with non-standard framerate " echo " avail. norms : pal (default), ntsc or ntsc_film" echo "-o filename output files prefix (default = \"out\")" echo "-p preset_name output type (default = dvd)" echo " avail. : cvd, cvd_wide, dvd, dvd_wide, mvcd, svcd and vcd" echo "-q level quality (default = best)" echo " avail. : best, good, fair" echo "-r enable two passes encoding mode" echo "-R N:D force input framerate" echo "-T length force input length (minutes)" echo "-v show script version" echo "-V number of volumes (default = \"1\")" } show_error () { echo "**ERROR: [${SCRIPT_NAME}] $1" } show_info () { echo " INFO: [${SCRIPT_NAME}] $1" } show_warn () { echo "++ WARN: [${SCRIPT_NAME}] $1" } test_bin () { if ! which ${1} >/dev/null; then show_error "${1} binary not present." exit 2 fi } for BIN in ${FFMPEG} ${PGMTOY4M}; do test_bin ${BIN} done while getopts a:A:bcd:De:f:hi:I:J:mn:o:p:q:rR:T:vV: OPT do case ${OPT} in a) AUD_TRACK="${OPTARG}";; A) VID_SAR_SRC="${OPTARG}";; b) BLIND_MODE="1";; c) ACOPY_MODE="1";; d) DEC_TOOL="${OPTARG}";; D) DEINT_MODE="1";; e) ENC_TOOL="${OPTARG}";; h) show_help; exit 0;; i) VIDEO_SRC="${OPTARG}"; AUDIO_SRC="${VIDEO_SRC}";; I) INTERLACING="${OPTARG}";; J) INTERLACING_OUT="${OPTARG}";; f) FILTERS_CHAIN="${OPTARG}";; m) MUTE_MODE="1";; n) OUT_NORM="${OPTARG}";; o) PREFIX_OUT="${OPTARG}";; p) VCD_TYPE="${OPTARG}";; q) QUALITY="${OPTARG}";; # r) ENC_TYPE="abr";; r) REQUANT_MODE="1";; R) VID_FPS_SRC="${OPTARG}";; T) DURATION="${OPTARG}";; v) echo "${SCRIPT_NAME} version ${SCRIPT_VERSION}"; exit 0;; V) VOLUMES="${OPTARG}";; \?) show_error "Unknown or uncomplete command line option."; show_error "Use -h to get help."; exit 2;; esac done if test "${VIDEO_SRC}" = "" || ! test -r "${VIDEO_SRC}"; then show_error "input file not specified or not present." show_error "Use -h to get help." exit 2 fi FFMPEG_VERSION="`${FFMPEG} 2>&1 | awk '$4 == "build" {print $5}' | sed s/,// | head -1`" AUD_TRACK="`range_check ${AUD_TRACK} 1 99`" FFMPEG_AUD_TRACK="`${FFMPEG} -i \"${AUDIO_SRC}\" 2>&1 | awk '/Audio:/ {sub("^#","",$2); print $2}' | awk -F[ '{print $1}' | head -${AUD_TRACK} | tail -1`" AUD_BITRATE_SRC="`${FFMPEG} -i "${AUDIO_SRC}" 2>&1 | awk '/Audio:/ {print $8}' | head -${AUD_TRACK} | tail -1`" AUD_FMT_SRC="`${FFMPEG} -i "${AUDIO_SRC}" 2>&1 | awk '/Audio:/ {print $4}' | sed s/,// | head -${AUD_TRACK} | tail -1`" AUD_FREQ_SRC="`${FFMPEG} -i "${AUDIO_SRC}" 2>&1 | awk '/Audio:/ {print $5}' | sed s/,// | head -${AUD_TRACK} | tail -1`" Y4M_HEADER="`${FFMPEG} -i "${VIDEO_SRC}" -f yuv4mpegpipe -pix_fmt yuv420p -t 1 -y /dev/stdout 2>/dev/null | head -1`" VID_FMT_SRC="`${FFMPEG} -i "${VIDEO_SRC}" 2>&1 | awk '/Video:/ {print $4}' | sed s/,// | head -1`" VID_WIDTH_SRC="`echo ${Y4M_HEADER} | awk '{print $2}' | sed s/W//`" VID_HEIGHT_SRC="`echo ${Y4M_HEADER} | awk '{print $3}' | sed s/H//`" VID_SIZE_SRC="${VID_WIDTH_SRC}x${VID_HEIGHT_SRC}" FF_DEC="${FFMPEG} -i \"${VIDEO_SRC}\"" FF_DEC_AFLAGS="-map ${FFMPEG_AUD_TRACK} -i \"${AUDIO_SRC}\"" # video deinterlacing if test "${DEC_TOOL}" = "ffmpeg" && test "${DEINT_MODE}" = "1"; then INTERLACING="none" FF_DEC="${FF_DEC} -deinterlace" fi # input interlacing if test "${INTERLACING}" = "none"; then VID_ILACE_SRC="p" elif test "${INTERLACING}" = "top_first"; then VID_ILACE_SRC="t" elif test "${INTERLACING}" = "bottom_first"; then VID_ILACE_SRC="b" else VID_ILACE_SRC="`echo ${Y4M_HEADER} | awk '{print $5}' | cut -c 2-`" fi # output interlacing if test "${INTERLACING_OUT}" = "none"; then VID_ILACE_OUT="p" elif test "${INTERLACING_OUT}" = "top_first"; then VID_ILACE_OUT="t" elif test "${INTERLACING_OUT}" = "bottom_first"; then VID_ILACE_OUT="b" else VID_ILACE_OUT="${VID_ILACE_SRC}" fi # input framerate if test "${VID_FPS_SRC}" = ""; then VID_FPS_SRC="`echo ${Y4M_HEADER} | awk '{print $4}' | cut -c 2-`" fi # input pixel/sample aspect ratio if test "${VID_SAR_SRC}" = ""; then VID_SAR_SRC="`echo ${Y4M_HEADER} | awk '{print $6}' | cut -c 2-`" fi VID_SAR_N_SRC="`echo ${VID_SAR_SRC} | cut -d: -f1`" VID_SAR_D_SRC="`echo ${VID_SAR_SRC} | cut -d: -f2`" if test "${VID_SAR_N_SRC}" = "0" || test "${VID_SAR_D_SRC}" = "0"; then show_warn "Unknown pixel aspect ratio, defaulting to 1:1" VID_SAR_SRC="1:1" fi FF_ENC="${FFMPEG} -v 0 -f yuv4mpegpipe -i /dev/stdin -bf 2" MPEG2ENC="${MPEG2ENC} -v 0 -M 0 -R 2 -s -2 1 -E -5" MPLEX_FLAGS="-v 1" PGMTOY4M="${PGMTOY4M} -r ${VID_FPS_SRC} -i ${VID_ILACE_SRC} -a ${VID_SAR_SRC}" Y4MSCALER_FLAGS="-v 0 -S option=cubicCR -O infer=exact" # ffmpeg decoder version if test "${FFMPEG_VERSION}" -ge "4731"; then FF_DEC="${FF_DEC} -f image2pipe -vcodec pgmyuv" else FF_DEC="${FF_DEC} -f imagepipe -img pgmyuv" fi # quality presets if test "${QUALITY}" = "best"; then QUANT="4" elif test "${QUALITY}" = "good"; then QUANT="5" elif test "${QUALITY}" = "fair"; then QUANT="6" else show_error "the specified quality preset is inexistant." show_error "Use -h to get help." exit 2 fi # profile(s) if test "${VCD_TYPE}" = "cvd"; then FF_ENC="${FF_ENC} -vcodec mpeg2video -f rawvideo -bufsize 224" MPEG2ENC="${MPEG2ENC} -f 8" VID_FMT_OUT="m2v" VID_MINRATE_OUT="0" VID_MAXRATE_OUT="7500" VID_SAR_525_OUT="20:11" VID_SAR_625_OUT="59:27" VID_SIZE_525_OUT="352x480" VID_SIZE_625_OUT="352x576" AUD_FMT_OUT="ac3" AUD_BITRATE_OUT="192" AUD_FREQ_OUT="48000" AUD_CHANNELS_OUT="2" # default volume size in mbytes (m = 1000) VOL_SIZE="4700" MPLEX_FLAGS="${MPLEX_FLAGS} -f 8" Y4MSCALER_FLAGS="${Y4MSCALER_FLAGS} -O preset=cvd" elif test "${VCD_TYPE}" = "cvd_wide"; then FF_ENC="${FF_ENC} -vcodec mpeg2video -f rawvideo -bufsize 224" MPEG2ENC="${MPEG2ENC} -f 8" VID_FMT_OUT="m2v" VID_MINRATE_OUT="0" VID_MAXRATE_OUT="7500" VID_SAR_525_OUT="80:33" VID_SAR_625_OUT="236:81" VID_SIZE_525_OUT="352x480" VID_SIZE_625_OUT="352x576" AUD_FMT_OUT="ac3" AUD_BITRATE_OUT="192" AUD_FREQ_OUT="48000" AUD_CHANNELS_OUT="2" VOL_SIZE="4700" MPLEX_FLAGS="${MPLEX_FLAGS} -f 8" elif test "${VCD_TYPE}" = "dvd"; then FF_ENC="${FF_ENC} -target dvd -f rawvideo -dc 10" MPEG2ENC="${MPEG2ENC} -f 8 -D 10" VID_FMT_OUT="m2v" VID_MINRATE_OUT="0" VID_MAXRATE_OUT="8000" VID_SAR_525_OUT="10:11" VID_SAR_625_OUT="59:54" VID_SIZE_525_OUT="720x480" VID_SIZE_625_OUT="720x576" AUD_FMT_OUT="ac3" AUD_BITRATE_OUT="192" AUD_FREQ_OUT="48000" AUD_CHANNELS_OUT="2" VOL_SIZE="4700" MPLEX_FLAGS="${MPLEX_FLAGS} -f 8" Y4MSCALER_FLAGS="${Y4MSCALER_FLAGS} -O preset=dvd" elif test "${VCD_TYPE}" = "dvd_wide"; then FF_ENC="${FF_ENC} -target dvd -f rawvideo -dc 10" MPEG2ENC="${MPEG2ENC} -f 8 -D 10" VID_FMT_OUT="m2v" VID_MINRATE_OUT="0" VID_MAXRATE_OUT="8000" VID_SAR_525_OUT="40:33" VID_SAR_625_OUT="118:81" VID_SIZE_525_OUT="720x480" VID_SIZE_625_OUT="720x576" AUD_FMT_OUT="ac3" AUD_BITRATE_OUT="192" AUD_FREQ_OUT="48000" AUD_CHANNELS_OUT="2" VOL_SIZE="4700" MPLEX_FLAGS="${MPLEX_FLAGS} -f 8" Y4MSCALER_FLAGS="${Y4MSCALER_FLAGS} -O preset=dvd_wide" elif test "${VCD_TYPE}" = "mvcd"; then FF_ENC="${FF_ENC} -vcodec mpeg1video -f rawvideo -bufsize 40 -me_range 64" MPEG2ENC="${MPEG2ENC} -f 2 -g 12 -G 24 -B 256 -S 797" MATRICES="mvcd" VID_FMT_OUT="m1v" VID_ILACE_OUT="p" VID_MINRATE_OUT="0" VID_MAXRATE_OUT="1152" VID_SAR_525_OUT="10:11" VID_SAR_625_OUT="59:54" VID_SIZE_525_OUT="352x240" VID_SIZE_625_OUT="352x288" AUD_FMT_OUT="mp2" AUD_BITRATE_OUT="128" AUD_FREQ_OUT="44100" AUD_CHANNELS_OUT="2" # 360000 sectors * 2324 bytes per sector / 1000 / 1000 VOL_SIZE="836" MPLEX_FLAGS="${MPLEX_FLAGS} -f 2 -r 1400 -V" Y4MSCALER_FLAGS="${Y4MSCALER_FLAGS} -O preset=vcd" elif test "${VCD_TYPE}" = "svcd"; then FF_ENC="${FF_ENC} -target svcd -f rawvideo" MPEG2ENC="${MPEG2ENC} -f 4 -B 256 -S 797" VID_FMT_OUT="m2v" VID_MINRATE_OUT="0" VID_MAXRATE_OUT="2500" VID_SAR_525_OUT="15:11" VID_SAR_625_OUT="59:36" VID_SIZE_525_OUT="480x480" VID_SIZE_625_OUT="480x576" AUD_FMT_OUT="mp2" AUD_BITRATE_OUT="224" AUD_FREQ_OUT="44100" AUD_CHANNELS_OUT="2" VOL_SIZE="836" MPLEX_FLAGS="${MPLEX_FLAGS} -f 4" Y4MSCALER_FLAGS="${Y4MSCALER_FLAGS} -O preset=svcd" elif test "${VCD_TYPE}" = "vcd"; then ENC_TYPE="cbr" FF_ENC="${FF_ENC} -target vcd -f rawvideo -me_range 64" MPEG2ENC="${MPEG2ENC} -f 1 -B 256 -S 797" VID_FMT_OUT="m1v" VID_ILACE_OUT="p" VID_SAR_525_OUT="10:11" VID_SAR_625_OUT="59:54" VID_SIZE_525_OUT="352x240" VID_SIZE_625_OUT="352x288" AUD_FMT_OUT="mp2" AUD_BITRATE_OUT="224" AUD_FREQ_OUT="44100" AUD_CHANNELS_OUT="2" VOL_SIZE="836" MPLEX_FLAGS="${MPLEX_FLAGS} -f 1" Y4MSCALER_FLAGS="${Y4MSCALER_FLAGS} -O preset=vcd" else show_error "the specified output type/profile is inexistant." show_error "Use -h to get help." exit 2 fi # audio pass-through if test "${ACOPY_MODE}" = "1"; then AUD_BITRATE_OUT="${AUD_BITRATE_SRC}" AUD_FMT_OUT="${AUD_FMT_SRC}" AUD_FREQ_OUT="${AUD_FREQ_SRC}" fi # output filenames VIDEO_OUT="${PREFIX_OUT}.${VID_FMT_OUT}" AUDIO_OUT="${PREFIX_OUT}.${AUD_FMT_OUT}" MPEG_OUT="${PREFIX_OUT}-%d.mpg" # output interlacing if test "${VID_ILACE_OUT}" = "b"; then FF_ENC="${FF_ENC} -ildct -ilme -top 0" MPEG2ENC="${MPEG2ENC} -I 1 -z b" elif test "${VID_ILACE_OUT}" = "t"; then FF_ENC="${FF_ENC} -ildct -ilme -top 1" MPEG2ENC="${MPEG2ENC} -I 1 -z t" else MPEG2ENC="${MPEG2ENC} -I 0" fi # output framerate if test "${VID_FPS_SRC}" = "30000:1001" || test "${VID_FPS_SRC}" = "24000:1001" || test "${VID_FPS_SRC}" = "25:1"; then VID_FPS_OUT="${VID_FPS_SRC}" elif test "${OUT_NORM}" = "ntsc"; then VID_FPS_OUT="30000:1001" elif test "${OUT_NORM}" = "ntsc_film"; then VID_FPS_OUT="24000:1001" else VID_FPS_OUT="25:1" fi # output sar and framesize for pal/ntsc if test "${VID_FPS_OUT}" = "25:1"; then VID_SAR_OUT="${VID_SAR_625_OUT}" VID_SIZE_OUT="${VID_SIZE_625_OUT}" else VID_SAR_OUT="${VID_SAR_525_OUT}" VID_SIZE_OUT="${VID_SIZE_525_OUT}" fi # cvd_wide "preset" for y4mscaler if test "${VCD_TYPE}" = "cvd_wide"; then Y4MSCALER="${Y4MSCALER} -O sar=${VID_SAR_OUT} -O size=${VID_SIZE_OUT}" fi # pipe buffer if which ${BFR} >/dev/null; then PIPE_BUFFER="${BFR} -b 16m |" fi # video decoder if test "${DEC_TOOL}" = "mpeg2dec"; then test_bin ${MPEG2DEC} DECODER="${MPEG2DEC} -s -o pgmpipe \"${VIDEO_SRC}\" | ${PGMTOY4M} |" elif test "${DEC_TOOL}" = "ffmpeg"; then test_bin ${FFMPEG} DECODER="${FF_DEC} -y /dev/stdout | ${PGMTOY4M} |" else show_error "the specified video decoder tool is not used by this script." show_error "Use -h to get help." exit 2 fi # video framerate correction if test "${VID_FPS_SRC}" = "${VID_FPS_OUT}"; then FRC="" else test_bin ${YUVFPS} FRC="${YUVFPS} -r ${VID_FPS_OUT} |" fi # video "deinterlacer" if test "${VID_ILACE_SRC}" != "p" && test "${VID_ILACE_OUT}" = "p"; then Y4MSCALER_FLAGS="${Y4MSCALER_FLAGS} -I ilace=top_only" fi # video scaler if test "${VID_SAR_SRC}" = "${VID_SAR_OUT}" && test "${VID_SIZE_SRC}" = "${VID_SIZE_OUT}" && test "${VID_ILACE_SRC}" = "${VID_ILACE_OUT}"; then SCALER="" else test_bin ${Y4MSCALER} SCALER="${Y4MSCALER} ${Y4MSCALER_FLAGS} |" fi # video filters chain for FILTER in `echo ${FILTERS_CHAIN} | sed s/,/"\n"/g`; do FILTER_TYPE="`echo ${FILTER} | awk -F: '{print $1}'`" FILTER_LEVEL="`echo ${FILTER} | awk -F: '{print $2}'`" if test "${FILTER_LEVEL}" = ""; then FILTER_LEVEL="light" fi MEANFILTER_FLAGS="-f" Y4MDENOISE_FLAGS="-v 0" # filter level if test "${FILTER_LEVEL}" = "light"; then YUVMEDIANFILTER_FLAGS="-t 0" YUVDENOISE_FLAGS="-l 1 -t 4 -S 0" YUVDENOISE2_FLAGS="-y 4 -u 8 -v 8" YUVDENOISE3_FLAGS="" Y4MSPATIALFILTER_FLAGS="-x 0 -y 0" MEANFILTER_FLAGS="${MEANFILTER_FLAGS} -t 0" Y4MDENOISE_FLAGS="${Y4MDENOISE_FLAGS} -t 1" Y4MUNSHARP_FLAGS="-L 1.5,0.2,0" elif test "${FILTER_LEVEL}" = "medium"; then YUVMEDIANFILTER_FLAGS="-T 0" YUVDENOISE_FLAGS="-l 2 -t 6 -S 0" YUVDENOISE2_FLAGS="-y 8 -u 16 -v 16" YUVDENOISE3_FLAGS="" Y4MSPATIALFILTER_FLAGS="-X 4,0.64 -Y 4,0.8" MEANFILTER_FLAGS="${MEANFILTER_FLAGS} -r 1 -T 0 -w 12" Y4MDENOISE_FLAGS="${Y4MDENOISE_FLAGS} -t 2" Y4MUNSHARP_FLAGS="-L 2.0,0.3,0" elif test "${FILTER_LEVEL}" = "heavy"; then YUVMEDIANFILTER_FLAGS="" YUVDENOISE_FLAGS="-l 3 -t 8 -S 0" YUVDENOISE2_FLAGS="-y 16 -u 32 -v 32" YUVDENOISE3_FLAGS="" Y4MSPATIALFILTER_FLAGS="-X 4,0.5 -Y 4,0.5 -x 2,0.5 -y 2,0.5" MEANFILTER_FLAGS="${MEANFILTER_FLAGS} -r 1 -R 1" Y4MDENOISE_FLAGS="${Y4MDENOISE_FLAGS} -t 3" Y4MUNSHARP_FLAGS="-L 5.0,0.5,0" else show_error "the specified \"${FILTER_LEVEL}\" filter level is inexistant." exit 2 fi # filter type if test "${FILTER_TYPE}" = "none"; then FILTER="" elif test "${FILTER_TYPE}" = "hqdenoise"; then test_bin ${Y4MDENOISE} FILTER="${Y4MDENOISE} ${Y4MDENOISE_FLAGS} |" elif test "${FILTER_TYPE}" = "mean"; then test_bin ${YUVMEDIANFILTER} FILTER="${YUVMEDIANFILTER} ${MEANFILTER_FLAGS} |" elif test "${FILTER_TYPE}" = "median"; then test_bin ${YUVMEDIANFILTER} FILTER="${YUVMEDIANFILTER} ${YUVMEDIANFILTER_FLAGS} |" elif test "${FILTER_TYPE}" = "spatial"; then test_bin ${Y4MSPATIALFILTER} FILTER="${Y4MSPATIALFILTER} ${Y4MSPATIALFILTER_FLAGS} |" elif test "${FILTER_TYPE}" = "temporal_old"; then test_bin ${YUVDENOISE} FILTER="${YUVDENOISE} ${YUVDENOISE_FLAGS} |" elif test "${FILTER_TYPE}" = "temporal_rc1"; then test_bin ${YUVDENOISE} FILTER="${YUVDENOISE} ${YUVDENOISE2_FLAGS} |" elif test "${FILTER_TYPE}" = "temporal"; then test_bin ${YUVDENOISE} FILTER="${YUVDENOISE} ${YUVDENOISE3_FLAGS} |" elif test "${FILTER_TYPE}" = "unsharp"; then test_bin ${Y4MUNSHARP} FILTER="${Y4MUNSHARP} ${Y4MUNSHARP_FLAGS} |" else show_error "the specified \"${FILTER_TYPE}\" filter type is not used by this script." exit 2 fi FILTERS="${FILTERS} ${FILTER}" done # 3:2 pulldown if test "${VID_FPS_OUT}" = "24000:1001" && test "${VID_FMT_OUT}" = "m2v"; then FF_ENC="${FF_ENC}" MPEG2ENC="${MPEG2ENC} -p" fi # quantisation matrices if test "${MATRICES}" = "kvcd"; then FF_ENC="${FF_ENC} -intra_matrix ${INTRA_KVCD} -inter_matrix ${INTER_KVCD}" MPEG2ENC="${MPEG2ENC} -K kvcd" elif test "${MATRICES}" = "mvcd"; then echo "`matrix_copy ${INTRA_MVCD}`" > ${CQMFILE} echo "`matrix_copy ${INTER_MVCD}`" >> ${CQMFILE} FF_ENC="${FF_ENC} -intra_matrix ${INTRA_MVCD} -inter_matrix ${INTER_MVCD}" MPEG2ENC="${MPEG2ENC} -K file=${CQMFILE}" elif test "${MATRICES}" = "tmpgenc"; then FF_ENC="${FF_ENC} -intra_matrix ${INTRA_TMPGENC} -inter_matrix ${INTER_TMPGENC}" MPEG2ENC="${MPEG2ENC} -K tmpgenc" fi # video encoding mode if test "${ENC_TYPE}" = "cbr"; then # when using -q with mpeg2enc, variable bitrate is selected. # it's not ok for vcds... MPEG2ENC="${MPEG2ENC}" elif test "${ENC_TYPE}" = "abr"; then if test "${DURATION}" != ""; then # input total time (seconds) VID_TIME_SRC="`echo "${DURATION}" | \ awk '{print $1 * 60}'`" else # input length (frames) if echo "${VID_FMT_SRC}" | grep -e mpeg1 -e mpeg2 >/dev/null 2>&1; then test_bin ${TCCAT} && test_bin ${TCDEMUX} VID_LENGTH_SRC="`${TCCAT} -i "${VIDEO_SRC}" | ${TCDEMUX} -W 2>&1 | awk '/unit/ {print sum+=$2}' | tail -1`" else test_bin ${TCPROBE} VID_LENGTH_SRC="`${TCPROBE} -i "${VIDEO_SRC}" 2>/dev/null | awk '/length:/ {print $2}'`" fi # input total time (seconds) = nb of frames / fps VID_TIME_SRC="`echo "${VID_LENGTH_SRC}:${VID_FPS_SRC}" | \ awk -F: '{print $1 / $2 * $3 + 1}'`" fi test_bin bc # available kbits (k = 1000) per second = global bitrate BPS="`echo "${VOLUMES} * ${VOL_SIZE} * 1000 * 8 / ${VID_TIME_SRC}" | bc`" # muxing-overhead: 3% (0.97 * ...) VID_BITRATE_OUT="`echo "0.97 * ${BPS} - ${AUD_BITRATE_OUT}" | bc | \ awk -F. '{print $1}'`" VID_BITRATE_OUT="`range_check ${VID_BITRATE_OUT} ${VID_MINRATE_OUT} ${VID_MAXRATE_OUT}`" FF_ENC="${FF_ENC} -minrate ${VID_MINRATE_OUT} -maxrate ${VID_MAXRATE_OUT} -b ${VID_BITRATE_OUT} -passlogfile ${STATFILE}" FF_STATS="${FF_ENC} -pass 1" MPEG2ENC_STATS="${MPEG2ENC} -b ${VID_BITRATE_OUT} -q 1 -v 1 2>${STATFILE}" FF_ENC="${FF_ENC} -pass 2" MPEG2ENC="${MPEG2ENC}" else FF_ENC="${FF_ENC} -maxrate ${VID_MAXRATE_OUT} -qscale ${QUANT}" MPEG2ENC="${MPEG2ENC} -b ${VID_MAXRATE_OUT} -q ${QUANT}" fi # video encoder if test "${ENC_TOOL}" = "ffmpeg"; then test_bin ${FFMPEG} ANALYSER="${FF_STATS} -y \"${VIDEO_OUT}\"" ENCODER="${FF_ENC} -y \"${VIDEO_OUT}\"" elif test "${ENC_TOOL}" = "mpeg2enc"; then test_bin ${MPEG2ENC} ANALYSER="${MPEG2ENC_STATS} -o \"${VIDEO_OUT}\"" ENCODER="${MPEG2ENC} -o \"${VIDEO_OUT}\"" else show_error "the specified video encoder tool is not used by this script." show_error "Use -h to get help." exit 2 fi # audio resampler if test "${AUD_FREQ_SRC}" = "${AUD_FREQ_OUT}"; then AUDIO_RESAMPLER="" else test_bin ${SOX} AUDIO_RESAMPLER="${SOX} -t au /dev/stdin -r ${AUD_FREQ_OUT} -t au /dev/stdout polyphase |" fi # audio decoder/encoder if test "${ACOPY_MODE}" = "1"; then AUDIO_DECODER="${FFMPEG} ${FF_DEC_AFLAGS}" AUDIO_ENCODER="-acodec copy -y \"${AUDIO_OUT}\"" elif test "${AUD_FREQ_SRC}" = "${AUD_FREQ_OUT}"; then AUDIO_DECODER="${FFMPEG} ${FF_DEC_AFLAGS}" AUDIO_ENCODER="-ab ${AUD_BITRATE_OUT} -ac ${AUD_CHANNELS_OUT} -y \"${AUDIO_OUT}\"" else AUDIO_DECODER="${FFMPEG} ${FF_DEC_AFLAGS} -v 0 -f au -y /dev/stdout |" AUDIO_ENCODER="${FFMPEG} -f au -i /dev/stdin -ab ${AUD_BITRATE_OUT} -ac ${AUD_CHANNELS_OUT} -y \"${AUDIO_OUT}\"" fi # output some info. show_info "===== SOURCE STREAM =====================" show_info " frame size: ${VID_SIZE_SRC}" show_info " frame rate: ${VID_FPS_SRC}" show_info " interlacing: ${VID_ILACE_SRC}" show_info " pixel aspect ratio: ${VID_SAR_SRC}" show_info "===== OUTPUT STREAM =====================" show_info " frame size: ${VID_SIZE_OUT}" show_info " frame rate: ${VID_FPS_OUT}" show_info " interlacing: ${VID_ILACE_OUT}" show_info " pixel aspect ratio: ${VID_SAR_OUT}" # video "analyse" if ! test "${BLIND_MODE}" = "1" && test "${ENC_TYPE}" = "abr"; then eval "${DECODER} ${FILTERS} ${FRC} ${SCALER} ${PIPE_BUFFER} ${ANALYSER}" if test "${ENC_TOOL}" = "mpeg2enc"; then # calculate average quant value from pseudo statfile (mpeg2enc output) QUANT="`awk -F= '/quant=/ {print $2}' "${STATFILE}" | \ awk '{iquant=$1; \ oquant=iquant; \ if (iquant>= 10) {oquant=9}; \ if (iquant>= 12) {oquant=10}; \ if (iquant>= 14) {oquant=11}; \ if (iquant>= 16) {oquant=12}; \ if (iquant>= 18) {oquant=13}; \ if (iquant>= 20) {oquant=14}; \ if (iquant>= 22) {oquant=15}; \ if (iquant>= 24) {oquant=16}; \ if (iquant>= 28) {oquant=17}; \ if (iquant>= 32) {oquant=18}; \ if (iquant>= 36) {oquant=19}; \ if (iquant>= 40) {oquant=20}; \ if (iquant>= 44) {oquant=21}; \ if (iquant>= 48) {oquant=22}; \ if (iquant>= 52) {oquant=23}; \ if (iquant>= 56) {oquant=24}; \ if (iquant>= 64) {oquant=25}; \ if (iquant>= 72) {oquant=26}; \ if (iquant>= 80) {oquant=27}; \ if (iquant>= 88) {oquant=28}; \ if (iquant>= 96) {oquant=29}; \ if (iquant>= 104) {oquant=30}; \ if (iquant>= 112) {oquant=31}; \ nquant+=1; \ sum_quant+=oquant; \ print sum_quant/nquant}' | \ tail -1 | awk -F. '{print $1}'`" QUANT="`range_check $QUANT 3 31`" ENCODER="${MPEG2ENC} -b ${VID_MAXRATE_OUT} -q ${QUANT} -o ${VIDEO_OUT}" fi fi # video (de)coding if ! test "${BLIND_MODE}" = "1"; then eval "${DECODER} ${FILTERS} ${FRC} ${SCALER} ${PIPE_BUFFER} ${ENCODER}" fi # audio (de)coding if ! test "${MUTE_MODE}" = "1"; then eval "${AUDIO_DECODER} ${AUDIO_RESAMPLER} ${AUDIO_ENCODER}" fi # multiplexing if ! test "${BLIND_MODE}" = "1" && ! test "${MUTE_MODE}" = "1"; then if test "${REQUANT_MODE}" = "1"; then VID_SRC_SIZE="`ls -l ${VIDEO_OUT} | awk '{print $5}'`" AUD_SRC_SIZE="`ls -l ${AUDIO_OUT} | awk '{print $5}'`" REQUANT_FACT="`echo "scale=3; ${VID_SRC_SIZE} / (0.96 * ${VOL_SIZE} * 1000 * 1000 - ${AUD_SRC_SIZE})" | bc -l`" # sed is here to replace a "requant_fact * 1000" if test `echo ${REQUANT_FACT} | sed s/"\."//` -gt 1000; then VIDEO_SRC="${VIDEO_OUT}" VIDEO_OUT="${PREFIX_OUT}.req" show_info "Requantisation factor: ${REQUANT_FACT}" test_bin ${TCREQUANT} ${TCREQUANT} -i ${VIDEO_SRC} -o ${VIDEO_OUT} -f ${REQUANT_FACT} else show_warn "Requantisation not done. Requantisation factor lesser than 1.0." fi fi test_bin ${MPLEX} ${MPLEX} ${MPLEX_FLAGS} -o "${MPEG_OUT}" "${VIDEO_OUT}" "${AUDIO_OUT}" fi rm -f ${CQMFILE} ${STATFILE} exit 0 mjpegtools-2.1.0/scripts/frameber0000644000175000017500000000360307306727313017420 0ustar glowwormglowworm#! /bin/sh # # frameber berechnet die Frames einer editliste. # Im Falle mehrerer editlists wird filename-substitution # verwendet. # Zudem wird die Gesamtlänge bei einer SVCD-Komprimierung # mit 2500 Kbit/s in MB ausgegeben. # Damit lässt sich die Länge einer Video-CD besser vor # der Komprimierung abschätzen. # Die Schätzung der MB wurde an Hand der Längenangaben von # vcdimager gemacht. # direct="/video" #!!!!!!!! # cd $direct # # Das muss geändert werden, wenn es kein Verzeichnis dieses Namens gibt # # CHANGE if you don't have a directory named /video" # if [ -z "$1" ] then echo -e "\nWelche Liste berechnen? \c" # English: echo -e "\nProcess which editlist? \c" read teil else teil="$1" fi rm $direct/total cat ${teil}* 2>/dev/null | grep -v LAV | grep -v PAL | grep -v NTSC | grep -v video | cut -d" " -s -f2,3 >$direct/total # # tot=0 ; if [ -s $direct/total ] then cat total 2>/dev/null | while read a b do tot=$(expr $tot + $(expr $b - $a)) echo $tot >erg done else echo -e "\nKeine Liste zur Bearbeitung gefunden\n" #English echo -e "\nNo editlist to calculate\n" exit 0 fi tot=$(cat erg) totM=`expr $tot \* 13980` # Experimental value: That long will be a frame # after compression (including CD-Headers) # Again: PAL - based values. # Your mileage my vary if you use NTSC or SECAM # totM=$( expr $totM \/ 1048576 ) # convert Bytes to Mega # # This is were it's important whether you use PAL or NTSC or SECAM. # Sek=$( expr $tot \/ 25 + 1 ) Min=$( expr $Sek \/ 60 + 1) echo -e "\n61870 Frames passen auf die 700MB-CD, 825 MB, 2475 Sekunden\n" echo -e "$tot Frames sind bei 2500 Kbit/s ca. $totM MB $Sek Sek -> $Min Min\n" # English: echo -e "61870 Frames will fill a 700MB-CD 825 MB 2475 sec \n" # English: echo -e "$tot Frames at 2500 Kbit/s about $totM MB $Sek sec -> $Min min" mjpegtools-2.1.0/scripts/mpegtranscode0000755000175000017500000000314610105041642020456 0ustar glowwormglowworm#!/bin/sh usage() { echo "Usage: transcode -S|-V [-T] [-s mins] [-b bitrate] [-F framerate] [-o dstfile] srcfile ..." echo "o - output file root name" echo "b - bitrate for video in kbps" echo "s - sleep for specified number of minutes before starting work" echo "T - Use test encoder" echo "S - Transcode for SVCD or" echo "V - Transcode for VCD" echo "F - fhe frame rate can also be specified, choose one if needed: " mpeg2enc -F -h exit 0 } # Use this commented-out version if you haven't got sox and toolame #MP2ENC="nice -n 29 wav2mp2 -v -o" MPEG2ENC=mpeg2enc MPLEX=mplex if [ $# -lt 3 ] then usage fi outpat=".%d" outfile=transcoded bitrate="" sleep=0 decode="YUVh" while getopts ":o:b:s:F:SVTXh" opt do case $opt in s) sleep=$OPTARG ;; b) bitrate="-b $OPTARG" ;; o) outfile=$OPTARG ;; F) framerate="-F $OPTARG" ;; T) echo Using test encoder MPEG2ENC="mpeg2enc.test" MPLEX=mplex.test ;; h) echo hi-res mode MPEGOPTS="$MPEGOPTS -H" ;; X) echo Using test encoder max speed MPEGOPTS="$MPEGOPTS -4 1 -2 1" ;; V) echo Generating VCD stream MPEGOPTS="$MPEGOPTS -f 1" decode="YUVh" ;; S) echo Generating SVCD stream MPEGOPTS="$MPEGOPTS -f 4 -q 9 -P -V 200" bitrate="-b 2500" decode="YUVs" ;; ?) usage ;; esac done if [ x"$MPEGOPTS" = "x" ] then echo "Must specify -V or -S!" useage fi shift `expr $OPTIND - 1` sleep `expr $sleep * 60` cat $* | mpeg2dec -s -o $decode | \ ${MPEG2ENC} ${MPEGOPTS} $bitrate $framerate -o $outfile.m1v cat $* | extract_a52 - -s | a52dec -m wav | \ sox -t wav /dev/stdin -t wav -r 44100 /dev/stdout | \ toolame -p 2 -b 224 /dev/stdin $outfile.mp2 # Eventually mux-ing goes here! mjpegtools-2.1.0/scripts/Makefile.am0000644000175000017500000000041710314705373017741 0ustar glowwormglowworm# Process this file with Automake to produce Makefile.in bin_SCRIPTS = \ anytovcd.sh \ lav2avi.sh \ lav2mpeg \ lavtc.sh \ mpegtranscode EXTRA_DIST = \ $(bin_SCRIPTS) \ makePLI.py \ codiere \ berechne \ aufnahme \ frameber MAINTAINERCLEANFILES = Makefile.in mjpegtools-2.1.0/scripts/codiere0000644000175000017500000003137507307205073017251 0ustar glowwormglowworm#!/bin/sh # # codiere ist ein Shellscript das entweder AVI-files bearbeitet. # Bei AVI-Files wird der Name des AVI-Files auch für die komprimierten # Files verwendet - erweitert um entsprechende Änderungen. # AVI-Files beginnen - so setzt es das script voraus - mit # einem Grossbuchstaben und enden mit Kleinbuchstaben. # Editlisten beginnen mit Kleinbuchstaben und es wird folgendes # Schema verwendet: ja01[a - z] wird zum ersten File zusammengefasst. # Die Dateien ja02[a-7] werden zum zweiten File zusammengefasst. # # codiere is a shell-script that works with AVI-files and # editlists. In case of AVI-Files the name of the file is used # also for the output-Name. In case of editlists you are asked # for the name of the output-file. # It is mandatory that AVI-files start with a capital letter. # It is mandatory, that editlist-files don't start with capitals. # For editlists the following scheme is used: # Files ja01[a-z] will be used for the first output-file # Files ja02[a-z] will be used for the second output-file. # # If you want to get rid of the German questions: I tried to # translate everything - just browse the script for the word # English - and change it to your preferences. # # A second word of warning: Change the input- and output- directories # to your needs # Otherwise the script might not work :-) # echo -e "\n READ & ADAPT THE SHELL-SCRIPT TO YOUR NEEDS (LINE 37+38)" echo -e "After that: Delete lines 30 to 36\n" echo -e "\nBitte das Shellscript anpassen Zeile 37 und 38" echo -e "danach Zeilen 30 - 36 entfernen\n" # exit 0 directin=/video/ # CHANGE HERE and keep BOTH slashes directout=/toast2/ # CHANGE HERE and keep BOTH slashes # # The following options are for yuvscaler - not used for now # The variables are needed but have no meaning for now - # that's work in Progress. # Die folgenden Zeilen sind Arbeitsvorbereitung - die Variablen # werden gebraucht, haben aber noch keine weitere Bedeutung! # ---------------start work in progress-------------------------- yuvform="" # # yuvform="-n p" newer option - not used for now. # yuvform not used for now # yuvform="-n p" # p = PAL n = NTSC s = SECAM # # # for now: not used: yuvinform= # # yuvinform="-I INTERLACED_ODD_FIRST" # yuvinform="" # # N.B: yuvoutform new format is not used for now # # # -----------------End work in progress----------------- cd $directin echo -e "\n Ist der erste Buchstabe gross, werden avi-Files bearbeitet." echo " Ist der erste Buchstabe klein," echo " werden ohne weitere Prüfung editlisten vorausgesetzt" echo -e "\n\n Welche Dateien bearbeiten? \c" # English: # echo -e "\n If the first letter oft the filename is a capital letter # echo "I'll asume avi-files." # echo " Otherwise editlists are assumed." # echo -e "\n\n Which files should I process? \c" read c # echo -e "M = Monochrome oder ENTER = Farbe \c" # English echo -e " M = Monochrome ENTER = Colour \c" read bw if [ "$bw" = "m" ] || [ "$bw" = "M" ] then bwfilter="-m" # # yuvscoutadd="-O MONOCHROME" # not used for now yuvscoutadd="" # else yuvscoptadd="" bwfilter=" " fi # echo -e "LAV2YUVfilter: 0 = n0 d1 1 = n1 d1 2 = n1 d2 3 = n1 d3 (Enter = 2) \c" read filter if [ -z "$filter" ] then filter=2 fi # # Nun folgen - absichtlich eingerückt - die verschiedenen Filterfunktionen # Ich habe hier experimentelle Werte verwendet - bei mir ergab es so die # besten Resultate. Für Rückmeldungen bin ich dankbar. # # English # I used the values, that proofed best for my eyes. Your mileage may vary. # Feedback is very welcome. # if [ "$filter" = "0" ] then filter="-n 0 -d 1" mpegoptadd="-q 4" mplexoptadd="-V" fi if [ "$filter" = "1" ] then filter="-n 1 -d 1" mpegoptadd=" -q 5" mplexoptadd=" -V" fi if [ "$filter" = "2" ] then filter="-n 1 -d 2" mpegoptadd=" -q 5" mplexoptadd=" -V" fi if [ "$filter" = "3" ] then filter="-n 1 -d 3" mpegoptadd="-q 6" mplexoptadd="-V" fi # filter="${filter} ${bwfilter}" # # # FRAMEOFFSET # echo -e "Frameoffset in Frames? (ENTER=0) \c" read offq if [ -z "$offq" ] then offset="" else offset="-o $offset" fi echo -e "Bitrate 1152 - 2500 (ENTER=2500) \c" read brat if [ -z "$brat" ] then brat=2500 fi # Breitband-Video: Das sind die Filme, bei denen oben und unten # ein schwarzer Rand zu sehen ist und bei manchen Fernsehern # die Seiten ein wenig abgeschnitten werden. Also: Leinwandfilme, # die im Fernsehen ausgestrahlt werden. # Da empfiehlt es sich, diese fast schwarzen Ränder abzuschneiden. # Das verbessert die Kompression weil nicht im Schwarz-Flimmern # nach Veränderungen gesucht werden muss. # # Wideformat Video: Those Hollywood-Movies where you have the # bottom and top with large black stripes. # echo -e "B = Breitbandfilm V = VHS-Video ENTER = Direkt ab Tuner \c" # # English # echo -e "B = Wideformat-movie Enter = normal video \c" # read breit if [ -z "$breit" ] then BREIT=0 else if [ "$breit" = "b" ] || [ "$breit" = "B" ] then BREIT=1 else BREIT=2 fi fi # # Wurde die Aufnahme bereits als vcd gemacht und enthält die # Hinweis darauf im Namen? Dann muss nicht viel gefragt werden, # ausser nach der Bitrate. SVCD und XVCD können aus diesen # Aufnahmen sowieso nicht mehr gemacht werden :-) # Die Randbreiten wurden experimentell gewonnen, wenn jemand # das genauer machen kann: Bitte verbessern! # # Auch bei "normalen" VHS bzw. Video - Aufnahmen wird oben und # unten ein kleiner Rand abgeschnitten. Die obersten und untersten # Zeilen enthalten meistens nur Geflimmer. # # If recorded as vcd (taken from extension): # There i no need to ask for the kind of file, you want to # create :-) # No further questions necessary, assume optimal values # The values for the margins are experimental - I cut off some lines # from the recorded movie, that are normaly not useful. The amount # depends on the source you used for recording. # Improvements are welcome. # VCD="" if [ ${c} \> "Zz" ] # Dateiname mit Kleinbuchstabe First letter not a capital then VCD=$( cat ${c}* 2>/dev/null | grep vcd ) # get argument from editlist else VCD=$( ls ${c}* 2>/dev/null | grep vcd ) # get argument from filename fi if [ -n "$VCD" ] then # # Optimale Werte einstellen - Zeit spielt keine Rolle, ist # sowieso rasend schnell. # Assume optimal values - no further questions concering quality. # VCD is always very fast - if recorded as VCD quopt="-4 1 -2 1" yuvscopts="$yuvform $yuvinform $yuvoutform -k VCD" YUVMEDIAN=1 SCALER=0 if [ $BREIT = "1" ] then lavopt="-s 0 $filter -a 352x202+0+43" else if [ "$BREIT" = "2" ] then lavopt="-s 0 $filter -a 352x240+0+24" else lavopt="-s 0 $filter -a 352x270+0+9" fi fi mpegopt="-m 1 -s -h -b $brat $quopt -r 16 " mplexopt="-m 1 -f 2 -S 840" # # add="${brat}_vcd" o="VCD MPEG 1 : $brat " else # According to filenames it's no VCD-record - ask more questions. # # Ist keine VCD-Aufnahme - deshalb ist Abfrage sinnvoll # SCALER=1 echo -e 'Der yuvmedianfilter filtert zusätzlich "noise" - braucht aber Zeit' echo -e "Yuvmdianfilter einsetzen J = Ja N oder ENTER = Nein \c" read yu if [ -z "$yu" ] then YUVMEDIAN=0 else if [ $yu = "j" ] || [ "$yu" = "J" ] || [ "$yu" = "y" ] then YUVMEDIAN=1 else YUVMDEIAN=0 fi fi # End for YUVMEDIANFILTER ? # echo -e "Felddiagnose a=optimal b=schnell=ENTER ( 30% schneller, reicht meistens) \c" # English: echo -e "a = optimised for quality b = optimised=ENTER for speed in most cases ok \c" read qopt if [ -z "$qopt" ] then qopt=b fi if [ $qopt = "a" ] || [ "qopt" = "A" ] then quopt="-4 1 -2 1" else quopt=" " fi echo -e "\nA = SVCD B = XVCD C = VCD ( ENTER = SVCD ) \c" read F if [ -z "$F" ] then F="a" fi if [ "$F" = "A" ] || [ "$F" = "a" ] then d=$brat yuvtarget="-k SVCD" yuvscopts="$yuvform $yuvinform $yuvoutform $yuvtarget" f=2 if [ "$BREIT" = "1" ] then lavopt="-s 0 $filter -a 768x406+0+85" else if [ "$BREIT" = "2" ] then lavopt="-s 0 $filter -a 768x480+0+48" else lavopt="-s 0 $filter -a 768x540+0+18" fi fi mpegopt=" -m 2 -b $brat $mpegoptadd $quopt -r 16 -F 0" mplexopt="-m 2 -f 4 -S 840 $mplexoptadd" o="SVCD MPEG 2 mit $brat " add="${brat}_m2" fi if [ "$F" = "B" ] || [ "$F" = "b" ] then d=$brat f=1 yuvtarget="-k SVCD" yuvscopts="$yuvform $yuvinform $yuvoutform $yuvtarget" if [ "$BREIT" = "1" ] then lavopt="-s 0 $filter -a 768x406+0+85" else if [ "$BREIT" = "2" ] then lavopt="-s 0 $filter -a 768x480+0+48" else lavopt="-s 0 $filter -a 768x540+0+18" fi fi mpegopt="-m 1 -h -b $brat $quopt -r 16 " mplexopt="-m 2 -f 4 -S 840" # # add="${brat}_xvcd" o="XVCD MPEG 1 mit $brat " fi if [ "$F" = "C" ] || [ "$F" = "c" ] then d=$brat yuvtarget="-k VCD" yuvscopts="$yuvform $yuvinform $yuvoutform $yuvtarget" f=1 if [ $BREIT = "1" ] then lavopt="-s 0 $filter -a 768x406+0+85" else if [ "$BREIT" = "2" ] then lavopt="-s 0 $filter -a 768x480+0+48" else lavopt="-s 0 $filter -a 768x540+0+18" fi fi mpegopt="-m 1 -b $brat $quopt -r 16 " mplexopt="mplex -m 1 -f 2" add="${brat}_vcd" o="VCD MPEG 1 mit $brat " fi fi # # Ende Abfrage ob es eine VCD-Aufnahme ist # End of "Is it a VCD-record or do I need more Information" # if [ ${c} \> "Zz" ] # Dateiname mit Kleinbuchstabe First letter not a capital then echo -e "\n Bitte Ausgabe-Name angeben \c" # English echo -e "\n Enter Output-Name \c" read aus fi # # # echo -e "\nWartezeit in Minuten (Enter startet sofort, CTRL-C unterbricht) \c" # English echo -e "\n Enter delay in minutes (Just ENTER starts, CTRL-C to break \c" read warte if [ -z "$warte" ] then warte=0 else warte=`expr $warte \* 60` fi sleep $warte if [ ${c} \> "Zz" ] # Dateiname mit Kleinbuchstabe then auszahl="1" maches="ja" null=`expr $auszahl \< "10"` if [ -n $null ] then auszahl="0"$auszahl fi klein=${c}${auszahl}* machs=`ls $klein 2>/dev/null` if [ -n "$machs" ] then maches="ja" else echo "Keine Dateien zur Verarbeitung gefunden" # English echo "No files found " maches="nein" fi date >startzeit_$c while [ "$maches" = "ja" ] do if [ -f ${directout}${aus}${auszahl}_${add} ] || [ -f ${directin}${aus}${auszahl}_${add}.mpg ] then echo "MPEG-File ${directout}${aus}${auszahl}_${add} exists" else if [ "$YUVMEDIAN" = "1" ] then if [ "$SCALER" = "1" ] # And YUVMEDIAN=1 then lav2yuv $lavopt $offset $klein | yuvscaler $yuvscopts | yuvmedianfilter | mpeg2enc -h -s $mpegopt -o ${directout}${aus}${auszahl}_${add} else lav2yuv $lavopt $offset $klein | yuvmedianfilter | mpeg2enc -h -s $mpegopt -o ${directout}${aus}${auszahl}_${add} fi # end for SCALER else if [ "$SCALER" = "1" ] # And YUVMEDIAN=0 then lav2yuv $lavopt $offset $klein | yuvscaler $yuvscopts | mpeg2enc -h -s $mpegopt -o ${directout}${aus}${auszahl}_${add} else lav2yuv $lavopt $offset $klein | mpeg2enc -h -s $mpegopt -o ${directout}${aus}${auszahl}_${add} fi # End for SCALER fi # End for YUVMEDIAN fi # End: existing file if [ -f ${directout}${aus}${auszahl}.snd ] then echo "Soundfile ${directout}${aus}${auszahl}.snd exists" else lav2wav $klein | mp2enc -V -o ${directout}${aus}${auszahl}.snd fi if [ -f ${directout}${aus}${auszahl}_${add}.mpg ] then echo "${directout}${aus}${auszahl}_${add}.mpg exists" else mplex -v 0 $mplexopt $mplexoptadd -o ${directin}${aus}${auszahl}_$add.mpg ${directout}${aus}${auszahl}_$add ${directout}${aus}${auszahl}.snd fi auszahl=`expr $auszahl \+ 1` # echo $auszahl null=`expr $auszahl \< "10"` if [ $null = "1" ] then auszahl="0"$auszahl fi klein=${c}${auszahl}* # echo $klein machs=`ls $klein 2>/dev/null` if [ -n "$machs" ] then maches="ja" else maches="nein" fi done else # # Input-file-name starts with capital letter # Source-Datei beginnt mit Grossbuchstabe # for i in ${c}*avi do a=`basename $i .avi` if [ -f ${directout}${a}_${add} ] || [ -f ${directout}${a}_${add}.mpg ] then echo "MPEG-File ${a}_${add} exists" else if [ "$YUVMEDIAN" = "1" ] then if [ "$SCALER" = "1" ] then echo " lav2yuv $lavopt $offset $i | yuvscaler $yuvscopts | yuvmedianfilter | mpeg2enc $mpegopt -h -s -o ${directout}${a}_${add}" else lav2yuv $lavopt $offset $i | yuvmedianfilter | mpeg2enc $mpegopt -h -s -o ${directout}${a}_${add} fi # for SCALER else if [ "$SCALER" = "1" ] # And YUVMEDIAN = 0 then lav2yuv $lavopt $offset $i | yuvscaler $yuvscopts | mpeg2enc $mpegopt -h -s -o ${directout}${a}_${add} else # SCALER 0 0 And YUVMEDIAN = 0 lav2yuv $lavopt $offset $i | mpeg2enc $mpegopt -h -s -o ${directout}${a}_${add} fi # FOR SCALER fi # FOR YUVMEDIAN fi # For existing file if [ -f ${a}.snd ] then echo "Soundfile exists" else lav2wav $i | mp2enc -V -o ${directout}${a}${auszahl}.snd fi if [ -f ${directout}${a}_${add}.mpg ] then echo "MPLEX-File ${directout}${a}_${d}_mp${f}.mpg exists" else $mplexopt ${a}_${add} ${a}.snd ${directout}${a}_${add}.mpg if [ -f ${a}_${add}.mpg ] then rm ${a}_${add} fi fi done fi mjpegtools-2.1.0/scripts/aufnahme0000644000175000017500000000737507307205073017426 0ustar glowwormglowworm#!/bin/sh # # English text: see below! # # Veränderung: vorher wurde immer mit 720x576 bzw für VCD mit # 352x288 aufgenommen, jetzt mit lavrec -d 1. # Das bedeutet für die dc10plus: 768x576. # Für lavplay muss dann je nach Version die Option -w768x576 verwendet werden. # # Für mpeg2enc muss über yuvscaler die Grösse eingestellt werden. # "codiere" muss auch in der entsprechenden Version verwendet werden. # # CHANGES: The old script used the fixed size 720x576 for recording. # Now I use lavrec -d 1. # For the dc10plus that means: You record with 768x576. # For lavplay you need the option -w768x576. # You also need "yuvscaler" in your tree and the # correct version of "codiere" - some options have changed :-)) # # Dieses Shell-Script setzt für die AVI-files das # Verzeichnis /video voraus - bei mir ein Link auf # das tatsächliche Verzeichnis. # # This shell-sript assumes a directory /video for the AVI-files # (This might be well a link to your actual directory.) # # You can get rid of German questions by searching for the # keyword English and some little changes. echo -e "\nPlease adapt the directory, in that your movie-files will be" echo -e "That's line 38 of the script!" echo -e "After that: delete line 30 to 36 of this script\n" echo -e "\nBitte das Verzeichnis in Zeile 38 anpassen!\n" echo -e "\nDanach Zeile 30 - 36 des scripts löschen\n" # exit 0 direct=/video # !!!! # # Setzen des Mixers: lavrec kommt nicht mit jeder Soundkarte # ganz klar: Hier sollte das erfolgen, z.B. mit aumix oder # ossxmix # # Setting the mixer directly is better, than setting the volume # with lavrec - too many soundcards and drivers ... :-) # It's a good idea to do this now e.g. with aumix or ossxmix or ... # # Example: aumix -f $direct/.aumixrc # # # # I also use the following name-convention: # filesnames starting with captials are avi-files or # encoded files. # Editlists must not start with captials. # Of course it's up to you to change this :-)) # # Die Qualitätsangabe ist ein wenig obsolet: # Eigentlich ist bei Wiedergabe über einen DVD-Player # alles unter 80 wenig sinnvoll. # # mpeg 2 und SVCD verlangen 720x576 anders geht es noch nicht! # # Wegen des Shellscripts "codiere" verwende ich folgende Konvention: # Dateinamen, die mit Grossbuchstaben beginnen, sind AVI-files. # editlisten beginnen mit Kleinbuchstaben. Man kann das natürlich # auch anders machen. :-)) # echo -e "Dateiname (Bitte mit Grossbuchstaben anfangen) ?? \c" # # English: echo -e "Filename to record to (Please start with captial) ?? \c" # read titel echo -e "Qualität 30 -100 ( Enter = 100 ) \c" # # English: echo -e "Quality 30 - 100 (ENTER = 100 ) \c" # read qual if [ -z "$qual" ] then qual=100 fi # # Falls doch einmal von 768 runter gerechnet werden kann :-)) # echo -e "SVCD = A VCD = B (Enter = SVCD) \c" read format if [ -z "$format" ] || [ "$format" = "a" ] || [ "$format" = "A" ] then # format="-d 1 -g 720x576" format="-d 1" else format="-d 2" titel=${titel}_vcd fi echo -e "\n Dauer in Minuten? (Enter = 180 Min) \c" # # English: echo -e "\n Recording time in minutes (ENTER = 180 min) \c" # read minuten if [ -z "$minuten" ] then minuten=180 fi zeit=`expr $minuten \* 60` echo " Aufnahmedauer für $titel: $zeit Sekunden " # # English: echo "Recording time for $titel: $zeit seconds " # echo -e "Wartezeit (Min) or ENTER um sofort anzufangen \c" # # English: echo -e "Minutes to wait or ENTER to start recording \c" # read warte if [ -z "$warte" ] then warte=0 else warte=`expr $warte \* 60` fi sleep $warte # lavrec -f a -i p -a 16 $format -r 44100 -s -l 75 -R l -q $qual -t $zeit $direct/${titel}%03d.avi lavrec -f a -i P -n 128 -c 2 -a 16 $format -r 44100 -s -l -1 -R l -q $qual -t $zeit $direct/${titel}%03d.avi # # c = Korrektur für audio und video Sync t=sekunden # f = format ( A und a sind Avi ) # mjpegtools-2.1.0/scripts/lavtc.sh0000755000175000017500000006407011136363670017365 0ustar glowwormglowworm#!/bin/sh # # lav2tc.bash - use transcode to convert MJPEG avi files to another # video/audio format. # # copyright 2003 Shawn Sulma # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # Description: # # This is intended to be a fairly intelligent wrapper for the transcode # utility when working with mjpeg files and the lav tools. It assumes # that you have transcode and the lavtools installed and available in the # $PATH. # # Transcode can be found at: # http://www.theorie.physik.uni-goettingen.de/~ostreich/transcode/ # # It is written for bash specifically. It _should_ be fairly portable with # only minor changes to other important shells such as zsh and ksh. It is # not particularly compatible with the rather minimal sh implementation # found in some Linux distros. I don't know much about [t]csh, but doubt # it's easily portable to that. # # I'm sure there are a few naive things left in this script. Constructive # feedback is welcome. # # It doesn't do much checking for existence of codecs, or allow passing of # arbitrary parameters to transcode (including codec-specific ones). # However I think it does manage to cover most of the common ground. It # does some simple range checking on many of the parameters. # # A useful feature is the ability to specify "--two-pass". For most DIVX # codecs (and some others), two pass encoding gives better overall results. # This script manages the two pass process. It generates a log file name # for the first pass based on the output name. When the first pass is done, # it generates an md5sum of the log. This allows the second pass to be # interrupted. When the script is run on the same output file again, it # checks the md5sum of the log. If it's valid, it assumes that the first # pass is already successfully done and restarts only the second pass. Yes, # this can still break, but it's saved me much effort in converting. # # Transcode comes bundled with some plugins that are useful. In particular, # ivtc and smartdeinter. These do inverse telecine and deinterlacing (based # on SmartDub's deinterlacer which is rather nice). However, I've found # that yuvkineco and yuvdenoise sometimes (often) do a better job of inverse # telecine or deinterlacing. While there is support for some of the # yuv4mpeg utilities in transcode as plugin filters, I've added here some # additional capabilities that basically use yuvdenoise, yuvcorrect or # yuvkineco as "pre-processors" for transcode. Hiding the ugliness of this # from someone who just wants a nice conversion is a good thing. Of course, # if you want to do something more complicated, please do, but this is # intended to handle only modestly complex usage. # # As an additional "feature", this script automates the creation of an ogg # media file from the transcoded file. Ogg is a media container format, # much like AVI. Most people know ogg from Ogg Vorbis, which is a very good # lossy audio codec. The container format, though also accepts video # streams. Specifying "--ogg" on the command line will generate a separate # ogg audio file (since most avi-aware codecs in transcode cannot handle ogg # Vorbis). After processing is complete, the script uses the 'ogmmerge' # utility to combine the video and audio streams together into a single ogg # file. ogmmerge is not part of the ogg development download. You can get # it here: http://www.bunkus.org/videotools/ogmtools/ # # Determining the correct video and audio bandwith to use is a bit annoying # at times. This script attempts to help with this by having some bandwidth # estimation capabilities. "--max-length" allows you to specify the maximum # MiB to be used by the final output file. The script will figure out the # appropriate video bandwidth. It also does some automatic calculation of # audio bandwidths (essentially for mp3 56kbps for mono and 128kbps for # stereo, and for vorbis/ogg, 48 and 96 respectively (Vorbis gives similar # quality at those rates)). If you specify the video and/or audio bitrates # with -b and -a, those values are used, and not any calculated ones. Smart # users can do better than the calculation, but not too often. # # The default output codec is "xvidcvs". This is the most up-to-date # xvid/divx encoder. If you do not have the necessary xvid libs around, you # can specify another video code with "--videocodec". Other typical values # might be "odivx", "ffmpeg" or "xvid". # # I am partial to xvid. You can find it here: http://www.xvid.org/ # # Currently the script will process only one input file. If you have # multiple, you should create a edit list for them, and provide that edit # list to the script as the input file. # # Most of the script is sanity-checking. Or comments. Or logging. # # Example usage: # # simple case: # lav2tc.bash -o out.avi -b 1000 -a 128 in.eli # use lots of defaults, no clipping, or resize or deinterlace, just use # 1000kbps for video and 128kbps for audio) # # something more complicated: # lav2tc.bash -o out.avi --two-pass --max-length 700 in.eli # mostly use defaults, but do two-pass encoding, and determine the bitrates # necessary to fit the resulting output.avi onto an 80 min CDR ) # # lav2tc.bash --clip 20,20,10,10 --scale 0.75 -o out.avi -b 1000 in.eli # clip 20 pixels from the top and left and 10 from the bottom and right, # then scale the result by 75%. # # lav2tc.bash --pulldown=kineco -o out.avi --ogg --luma 75 --chroma 75 in.eli # uses yuvkineco to perform inverse telecine, adjusts the luma and chroma # contrasts, and creates an ogg media file as output. The final output is # written to "out.ogm". # # Dependencies (script checks the availability of each as needed): # (always) getopt, which, dc, cut, tr, expr, lavinfo, transcode # (for two-pass automation) md5sum # (for yuvdenoise deinterlace) yuvdenoise, yuvcorrect # (for yuvkineco inverse telecine) yuvkineco, yuvcorrect # (for "--ogg") ogmmerge # # History: # This script replaces the lav2divx utility # 2003-06-01: Initial version (Shawn Sulma) # appName=`basename ${0}` appVersion="0.1" # # Helpers. These might some day belong in an include script file themself. # assertExists () { [ -x `which ${1}` ] || log_fail ${1} not found. ${2}${2+ requires this.} } assertNumber () { if [[ `expr "${1}" : "[0-9${3}]*" 2> /dev/null` -ne ${#1} ]] ; then log_error "${2}${2+:} \"${1}\" is not a valid value" exit 1; fi } assertRange () { assertNumber ${1} ${3} if [[ ${1} -lt 0 || ${1} -gt ${2} ]] ; then log_error "${3}${3+:} \"${1}\" outside allowed range 0-${2}" exit 1 ; fi } # # parse a string into multiple parts separated by any of "xX,._+:-". This is useful # for geometry strings: "000x000+000+000". It ignores the separators. The result is # stored in the array ${geometry} # parseGeometry () { geometry=(`echo "${1}" | tr ' xX,._+:-' ' '`) } # # logging mechanism. It handles different levels of output. Yes, it's not # too efficient, but this is a wrapper script, and performance of this script # is not required to be stellar. # debug=3 info=2 warn=1 error=0 logLevelText=( "**ERROR" "## WARN" "== INFO" "--DEBUG" ) log_debug () { __log ${debug} $* ; } log_info () { __log ${info} $* ; } log_warn () { __log ${warn} $* ; } log_error () { __log ${error} $* ; } log_fail () { __log ${error} $* ; exit 1 ; } __log () { if [[ ${logLevel=2} -ge ${1} ]] ; then level=${1} shift echo "${logLevelText[${level}]}: [${appName}] $*" >&2 fi } # # Usage and Help display # usage () { cat << EOF ${appName} ${appVersion} - a transcode wrapper script for lavtools Usage: ${appName} -o [options] For help: ${appName} -h EOF } helptext () { usage cat << EOF Options: -h | --help this help output -o | --output= output to -b | --videorate= use kilobits/second as the video bitrate -a | --audiorate= use kilobits/second as the audio bitrate -m | --mono convert the audio to mono before encoding -v | --verbose= select verbosity level (0-3, higher outputs more) --maxlength= calculate video bandwidth for output size MiB --two-pass perform two-pass encoding where possible --clip=,,, clip number of pixels from top, left, bottom, right --frame=x++ use the specified frame geometry (clip to) --resize=, resize to specified width and height --scale= scale by the factor (1.00 = 100%) --deinterlace[=] set deinterlace/inverse telecine type (type is "smart", "denoise", "kineco" or "ivtc") --line-switch swap lines prior to processing --luma= set luma contrast --chroma= set chroma contrast (saturation) --frames=- only process frames through --frames= only process first frames --status-delay= update status line every frames --videocodec= use the specified codec (xvid, ffmpeg, etc) --grayscale convert to black and white --quality= use quality level (1-5, default 5) --crispness= use crispness (default 100) --ogg generate an ogg media file (use Vorbis not MP3) --norm={n,p} declare norm to be "n" or "p" (passed to preprocess) EOF } parseParams () { args=`getopt -n ${appName} -o o:b:a:mv:hV -l output:,videorate:,audiorate:,mono,verbose:,max-length:,two-pass,ogg,clip:,frame:,scale:,deinterlacer::,pulldown::,deinterlace::,line-switch,luma:,chroma:,frames:,status-delay:,grayscale,videocodec:,crispness:,quality:,resize:,scale:,help,norm:,greyscale,version,norm: -- "$@"` if [ $? != 0 ] ; then log_fail "Cannot continue." fi eval set -- "$args" while true ; do case "${1}" in -h|--help) helptext >&2 ; exit 0;; -o|--output) output="${2}" ; shift 2 ;; -b|--video-rate) assertNumber ${2} "video bandwidth" videoBW="${2}" ; shift 2 ;; -a|--audio-rate) assertNumber ${2} "audio bandwidth" ; audioBW="${2}" ; shift 2 ;; -m|--mono) audioOutChannels=1 ; shift ;; -v|--verbose) assertRange ${2} 3 "verbosity level" ; logLevel=${2} ; shift 2 ;; --max-length) assertNumber ${2} "maximum output size" ; maxlength="${2}" ; shift 2 ;; --two-pass) assertExists md5sum "${1}" ; twopass=1 ; shift ;; --ogg) assertExists ogmmerge "${1}" ; ogg=1 ; shift ;; --clip) clip="${2}" ; shift 2 ;; --frame) frame="${2}" ; shift 2 ;; --line-switch) flip=1 ; shift ;; --resize) resize="${2}" ; shift 2 ;; --scale) videoScale="${2}" ; assertNumber ${2} "video scaling factor" . ; shift 2 ;; --deinterlace*|--pulldown) case "${2}" in denoise|kineco) assertExists yuv${2} "${1} ${2}" deinterlacer="${2}" ;; smart|ivtc) deinterlacer="${2}" ;; "") deinterlacer="smart" ;; *) log_fail "Unknown deinterlacer type: ${2}" ;; esac ; shift 2 ;; --luma) assertNumber ${2} "luma contrast" ; assertExists yuvdenoise "${1}" lumaContrast="${2}" ; shift 2 ;; --chroma) assertNumber ${2} "chroma contrast" ; assertExists yuvdenoise "${1}" chromaContrast="${2}" ; shift 2 ;; --frames) frameRange="${2}" ; shift 2 ;; --status-delay) assertNumber ${2} "status display delay" ; delay="${2}" ; shift 2 ;; --grayscale|--greyscale) grayscale="1" ; shift ;; --videocodec) videoOutCodec="${2}" ; shift 2 ;; --quality) assertNumber ${2} "quality" ; quality="${2}" ; shift 2 ;; --crispness) assertNumber ${2} "crispness" ; crispness="${2}" ; shift 2 ;; --norm) norm="${2}" ; shift 2 ;; -V|--version) usage ; exit 0 ;; --) shift ; break ;; *) log_fail "Internal error at ${1}" ;; esac done # transcode can only handle one file input. This script will eventually # handle more, but for now... inFile="${1}" if [[ -z ${output} ]] ; then log_error "output file required" usage exit 1; elif [[ -z ${inFile} ]] ; then log_error "one input file required" usage exit 1; elif [ ! -e ${inFile} ] ; then log_fail "input file ${inFile} does not exist" fi } # # read information about the input file. There's probably a better way to # do this, but this works well enough. # readHeader () { header="`lavinfo ${norm++}${norm} ${inFile}`" for line in ${header} ; do value=`echo ${line} | cut -d '=' -f2` case "${line}" in video_width*) videoWidth=${value} ;; video_height*) videoHeight=${value} ;; video_fps*) videoFrameRate=${value} ;; video_inter*) videoIsInterlaced=${value} ;; video_frames*) totalFrames=${value} ;; audio_bits*) audioInBits=${value} ;; audio_chans*) audioInChannels=${value} ;; audio_rate*) audioInRate=${value} ;; num_video_files*) numVideoFiles=${value} ;; esac done videoSeconds=`dc -e "0 k ${totalFrames} ${videoFrameRate} / p"` } # # For kineco and yuvdenoise deinterlace, a fifo is required. Ensure one # exists, and clean up when we're done with it. # ensureFifo () { fifo="${outputBaseName}.fifo" if [ -p ${fifo} ] ; then log_debug "Fifo already established" elif [ -e ${fifo} ] ; then log_fail "${fifo} is not a FIFO. Cannot continue." ; else log_debug "Creating fifo ${fifo}" log_debug mkfifo ${fifo} mkfifo ${fifo} needToCleanupFifo=1 fi } cleanupFifo () { if [ -p ${fifo} ] ; then log_debug "removing fifo ${fifo}" log_debug rm ${fifo} rm ${fifo} fi } # # If we're not using a pre-processing pipe, we can perform line switching # through a filter plugin. # setFlipArgs () { if [[ ${flip=0} = 1 && ${videoIsInterlaced} = 1 ]] ; then flipArgs="-J fields=flip" fi } # # Set up for handling the different types of deinterlacers and inverse telecine # filters. Some require separate filter entries, while others need pre- # processing pipelines. The latte introduces complications because now the # audio has to be passed to transcode separately. # setDeinterlaceArgs () { # set up for deinterlacing. In some cases, the actual deinterlacing # is finally triggered elsewhere. # # get the audio and video from the input file (default case) # inputFile="${inFile}" inputVideoCodec="lav" if [[ ${videoIsInterlaced} = 0 || ${deinterlacer=none} = "none" ]] ; then deinterlacerText="No deinterlacing" setFlipArgs elif [ ${deinterlacer} = "smart" ] ; then deinterlacerText="SmartDub deinterlacer" deinterlaceArgs="-J smartdeinter=cubic=1:diffmode=2:highq=1" setFlipArgs elif [ ${deinterlacer} = "ivtc" ] ; then deinterlacerText="Transcode ivtc inverse telecine" deinterlaceArgs="-J ivtc,32detect=force_mode=5,decimate" setFlipArgs else ensureFifo # # We have to turn off auto-probing. Thus we have to provide # information about the video and audio input ourselves. # cineRate=`dc -e "6 k 24000 1001 / p"` deinterlaceArgs="-H 0 -f ${cineRate},1 -M 0 -g ${videoWidth}x${videoHeight} -e ${audioInRate},${audioInBits},${audioInChannels}" # # get the video from the fifo and the audio from the input # inputFile="${fifo} -p ${inFile}" inputVideoCodec="yuv4mpeg" inputAudioCodec=",lav" if [ ${deinterlacer} = "denoise" ] ; then # in theory, the builtin yuvdenoise filter plugin should # be able to do this. In practise, I could not find a # practical way to tell it to _only_ deinterlace. deinterlacerText="yuvdenoise deinterlacer" elif [ ${deinterlacer} = "kineco" ] ; then # # yuvkineco 1 pass inverse telecine # deinterlacerText="yuvkineco inverse telecine" # since the incoming stream is now at a different frame rate, we need # to recalculate the number of frames that can be seen and used by transcode totalFrames=`dc -e "8 k ${cineRate} ${videoFramesRate} / ${totalFrames} * 0 k 1 + 1 / p"` else log_fail "Unknown deinterlacer/pulldown: ${deinterlacer}" fi fi } setAudioArgs () { # # if there's no audio, don't bother with it. # if [[ ${audioInChannels} -gt 0 ]] ; then # # keep the same bitrate and sample size # audioOutBits=${audioInBits} audioOutRate=${audioInRate} if [[ -z ${audioOutChannels} ]] ; then audioOutChannels=${audioInChannels} fi # # If the output bitrate isn't set, determine it. # if [[ -z ${audioBW} ]] ; then if [[ -n ${ogg} ]] ; then # Ogg Vorbis compresses better let audioBW="48*${audioOutChannels}" else if [ ${audioOutChannels} = 1 ] ; then audioBW=56 else let audioBW="64*${audioOutChannels}" fi fi fi audioArgs="-E ${audioOutRate},${audioOutBits},${audioOutChannels} -b ${audioBW}" if [[ -n ${ogg} ]] ; then oggName="${outputBaseName}.audio.ogg" fi fi } setVideoBW () { if [[ -n ${maxlength} ]] ; then # # if not set, guess an appropriate bandwidth. # This is, in some ways, a voodoo calculation. Well, to be # precise, I'm guessing at the additional 6 bytes of overhead # per frame. In practise, I've found this calculation is # actually quite useful; conservative without being too much so. # let availableBytes="${maxlength}*1024*1024" # bandwidth calculation let bytesIndex="${totalFrames}*8" let bytesAudio="${videoSeconds}*${audioBW-0}*128" let bytesOverhead="${totalFrames}*6" let remainder="${availableBytes}-${bytesAudio}-${bytesIndex}-${bytesOverhead}" bandwidth=`dc -e "${remainder} ${videoSeconds} / 128 / p"` fi videoBW=${videoBW-${bandwidth-1000}} } setClipArgs () { if [[ -n ${clip} ]] ; then parseGeometry ${clip} clipTop=${geometry[0]} clipLeft=${geometry[1]} clipBottom=${geometry[2]} clipRight=${geometry[3]} elif [[ -n ${frame} ]] ; then parseGeometry ${frame} assertRange ${geometry[0]} ${videoWidth} "frame width" assertRange ${geometry[1]} ${videoHeight} "frame height" assertRange ${geometry[2]} ${videoWidth} "frame x offset" assertRange ${geometry[3]} ${videoHeight} "frame y offset" # # convert the geometry string to clipping pixels. # let clipBottom=${videoHeight}-${geometry[1]}-${geometry[3]} let clipTop=${geometry[3]} let clipRight=${videoWidth}-${geometry[0]}-${geometry[2]} let clipLeft=${geometry[2]} fi assertRange ${clipTop=0} ${videoHeight} "top clipping parameter" assertRange ${clipBottom=0} ${videoHeight} "bottom clipping parameter" assertRange ${clipLeft=0} ${videoWidth} "left clipping parameter" assertRange ${clipRight=0} ${videoWidth} "right clipping paramter" let totalClipped="${clipTop}+${clipBottom}+${clipRight}+${clipLeft}" if [ ${totalClipped} != 0 ] ; then clippingArgs="-j ${clipTop},${clipLeft},${clipBottom},${clipRight}" fi } setResizeArgs () { let clippedHeight="${videoHeight}-${clipTop}-${clipBottom}" let clippedWidth="${videoWidth}-${clipLeft}-${clipRight}" if [[ -n ${resize} ]] ; then videoOutWidth=${resize%%[x./-, ]*} videoOutHeight=${resize##*[x./-, ]} assertNumber ${videoOutWidth} "target width" assertNumber ${videoOutHeight} "target height" else assertNumber ${videoScale} "output scaling factor" . videoScale=${videoScale-1.00} videoOutWidth=`dc -e "0 k ${clippedWidth} ${videoScale} * 1 / p"` videoOutHeight=`dc -e "0 k ${clippedHeight} ${videoScale} * 1 / p"` fi if [[ ${videoOutHeight} != ${clippedHeight} || ${videoOutWidth} != ${clippedWidth} ]] ; then resizeArgs="-Z ${videoOutWidth}x${videoOutHeight}" fi } setEnhanceArgs () { [[ -n "${lumaContrast}" || -n "${chromaContrast}" ]] && enhanceArgs="-J yuvdenoise=mode=2" [[ -n ${lumaContrast} ]] && enhanceArgs="${enhanceArgs}:luma_contrast=${lumaContrast}" [[ -n ${chromaContrast} ]] && enhanceArgs="${enhanceArgs}:chroma_contrast=${chromaContrast}" [[ -n ${grayscale} ]] && enhanceArgs="-K ${enhanceArgs}" } setFramesRangeArgs () { if [[ `expr "${frameRange=0}" : "[0-9]*[^0-9][0-9]*" 2> /dev/null` -eq ${#frameRange} ]] ; then firstFrame="${frameRange%%[.,-]**}" lastFrame="${frameRange##*[.,-]}" else firstFrame=1 lastFrame=${frameRange} assertNumber ${lastFrame} "frames to encode" fi if [[ -z $firstFrame ]] ; then firstFrame=0 ; fi if [[ -z $lastFrame ]] ; then lastFrame=0 ; fi # normalise negatives if [ ${firstFrame} -lt 0 ] ; then let firstFrame=${totalFrames}${firstFrame} fi if [ ${lastFrame} -lt 0 ] ; then let lastFrame=${totalFrames}${lastFrame} fi # now check for valid ranges. if [ ${firstFrame} = 0 -a ${lastFrame} = 0 ] ; then firstFrame=1 lastFrame=${totalFrames} elif [ ${lastFrame} = 0 ] ; then lastFrame=${firstFrame} firstFrame=1 elif [ ${firstFrame} = 0 ] ; then firstFrame=1 fi # upper bounds if [ ${lastFrame} -gt ${totalFrames} ] ; then lastFrame=${totalFrames} fi if [ ${firstFrame} -gt ${lastFrame} ] ; then firstFrame=${lastFrame} fi # generate arg framesRangeArgs="-c ${firstFrame}-${lastFrame}" } setStatusArgs () { if [[ ${logLevel} -lt 2 ]] ; then statusArgs="-q 0" ; elif [[ ${logLevel} -eq 2 ]] ; then statusArgs="-q 1" ; statusOnly="1" ; else statusArgs="-q 1" ; fi if [[ ${logLevel} -gt 0 ]] ; then delayArgs=" --print_status ${delay=1} " fi } initialize () { outputBaseName="${output%.*}" readHeader setDeinterlaceArgs setAudioArgs setClipArgs setResizeArgs setEnhanceArgs setFramesRangeArgs setStatusArgs setVideoBW videoOutCodec="${videoOutCodec-xvidcvs}" quality="${quality-5}" crispness="${crispness-144}" log_info "encoding ${inFile}" log_info "input video: ${videoWidth}x${videoHeight}" log_info "input total length: ${totalFrames} frames (${videoSeconds} seconds)" log_info "deinterlace type: ${deinterlacer} (input is " `if [[ ${videoIsInterlaced} = 0 ]] ; then echo -n "not " ; fi ` " interlaced)" if [[ ${audioInChannels} = 0 ]] ; then log_info "no audio on input" else log_info "input audio: ${audioInRate},${audioInBits},${audioInChannels}" log_info "output audio: ${audioOutRate},${audioOutBits},${audioOutChannels}" log_info "output audio bandwidth: ${audioBW}" if [[ -n ${ogg} ]] ; then log_info "using ogg vorbis for audio " fi fi log_info "clipping: left ${clipLeft-0}, top ${clipTop-0}, right ${clipRight-0}, bottom ${clipBottom-0}" log_info "resize scale: ${videoScale-n/a}, result ${videoOutWidth}x${videoOutHeight}" log_info "contrast: ${lumaContrast-n/a}, saturation: ${chromaContrast-n/a}" log_info "encoding frames: ${firstFrame} to ${lastFrame}" log_info "video bandwidth: estimated ${bandwidth-n/a}, used ${videoBW}" log_info "transcode video out codec: ${videoOutCodec}" transcodeArgs="\ -i ${inputFile} \ ${clippingArgs} \ ${resizeArgs} \ ${flipArgs} \ ${deinterlaceArgs} \ ${enhanceArgs} ${audioArgs} \ -Q ${quality} \ -o ${output} \ -w ${videoBW},,${crispness} \ -V -k ${framesRangeArgs} ${statusArgs} ${delayArgs}" } # # # Main section of the script. It handles the creation of the pipeline # (if necessary) as well as the management of two pass encodings (i.e. the log # file and running the separate passes). # # for required in expr transcode dc getopt cut tr lavinfo ; do [ -x `which ${required}` ] || log_fail "${required} not found. Cannot continue." done parseParams "$@" initialize pass=1 while [ ${pass} != 2 ] ; do if [[ -n ${twopass} ]] ; then passArgs="" if ( md5sum -c ${outputBaseName}.pass1.md5sum &> /dev/null ) then # if [[ ${pass} = 3 ]] ; then pass=2 inputAudioCodec="" if [[ -n ${ogg} ]] ; then passArgs="-m ${oggName}" outputAudioCodec=",ogg" else outputAudioCodec="" fi log_info "Valid first pass log_file found" else pass=1 log_warn "First pass log_file not found or not valid" log_debug "removing spurious first pass log_file." log_debug "rm ${outputBaseName}.pass1.log &> /dev/null" rm ${outputBaseName}.pass1.log &> /dev/null passArgs="" outputAudioCodec=",null" inputAudioCodec=",null" fi passArgs="-R ${pass},${outputBaseName}.pass1.log ${passArgs}" else # single pass. log_info "single pass encoding only." >&2 fi log_info "beginning pass ${pass}" >&2 # set up pipeline if needed (using kineco or yuvdenoise deinterlacer) if [[ ${videoIsInterlaced} = 1 && ( "${deinterlacer}" = "kineco" || "${deinterlacer}" = "denoise" ) ]] ; then if [[ -n ${flip} ]] ; then corrector="yuvcorrect -v 0 -T LINE_SWITCH" else corrector="cat" fi if [ ${deinterlacer} = "kineco" ] ; then deinterlaceCmd="yuvkineco -F 1 " else deinterlaceCmd="yuvdenoise -I -v 0 " fi log_info "invoking deinterlacer/pulldown thread" log_debug "lav2yuv ${inFile} | ${corrector} | ${deinterlaceCmd} > ${fifo} &" lav2yuv ${inFile} | ${corrector} | ${deinterlaceCmd} > ${fifo} & fi if [[ "${audioInChannels}" = 0 ]] ; then inputAudioCodec=",null" outputAudioCodec=",null" elif [[ ${pass} = 2 ]] ; then inputAudioCodec=",lav" fi inputCodecArgs="-x ${inputVideoCodec}${inputAudioCodec}" outputCodecArgs="-y ${videoOutCodec}${outputAudioCodec}" # # this is the big call # log_debug `for arg in /usr/local/bin/transcode ${passArgs} ${transcodeArgs} ${inputCodecArgs} ${outputCodecArgs} ; do echo -n "${arg} " ; done` " " /usr/local/bin/transcode \ ${passArgs} \ ${transcodeArgs} \ ${inputCodecArgs} \ ${outputCodecArgs} errcode=$? # errcode=0 if [ ${errcode} != 0 ] ; then exit ${errcode} fi if [[ -n ${twopass} ]] ; then if [ ${pass} = 1 ] ; then log_debug "md5sum ${outputBaseName}.pass1.log > ${outputBaseName}.pass1.md5sum" md5sum ${outputBaseName}.pass1.log > ${outputBaseName}.pass1.md5sum else log_debug "mv ${outputBaseName}.pass1.log ${outputBaseName}.pass1.log.old" mv ${outputBaseName}.pass1.log ${outputBaseName}.pass1.log.old fi else break; fi done if [[ -n ${needToCleanupFifo} ]]; then cleanupFifo ; fi log_debug "chmod -x ${output}" chmod -x ${output} if [[ -n ${ogg} && ${audioInChannels} -gt 0 ]] ; then # need to merge the two together. log_debug "using ogmmerge to generate ogg media file" log_debug "ogmmerge -o ${outputBaseName}.ogm -D ${output} -A ${oggName}" ogmmerge -o ${outputBaseName}.ogm -A ${output} -D ${oggName} fi mjpegtools-2.1.0/scripts/Makefile.in0000644000175000017500000003432512217306407017756 0ustar glowwormglowworm# Makefile.in generated by automake 1.12.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Process this file with Automake to produce Makefile.in VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = scripts DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(bindir)" SCRIPTS = $(bin_SCRIPTS) SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALTIVEC_EXTRA_LIBS = @ALTIVEC_EXTRA_LIBS@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDV_CFLAGS = @LIBDV_CFLAGS@ LIBDV_LIBS = @LIBDV_LIBS@ LIBGETOPT_LIB = @LIBGETOPT_LIB@ LIBM_LIBS = @LIBM_LIBS@ LIBOBJS = @LIBOBJS@ LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ LIBPNG_LIBS = @LIBPNG_LIBS@ LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@ LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ LT_STATIC = @LT_STATIC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROGRAM_NOPIC = @PROGRAM_NOPIC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ SDLgfx_LIBS = @SDLgfx_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ V4LCONF_LIBS = @V4LCONF_LIBS@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ bin_SCRIPTS = \ anytovcd.sh \ lav2avi.sh \ lav2mpeg \ lavtc.sh \ mpegtranscode EXTRA_DIST = \ $(bin_SCRIPTS) \ makePLI.py \ codiere \ berechne \ aufnahme \ frameber MAINTAINERCLEANFILES = Makefile.in all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu scripts/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu scripts/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags: TAGS TAGS: ctags: CTAGS CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(SCRIPTS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binSCRIPTS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binSCRIPTS .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binSCRIPTS install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ uninstall uninstall-am uninstall-binSCRIPTS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mjpegtools-2.1.0/scripts/lav2mpeg0000755000175000017500000004260611136363671017362 0ustar glowwormglowworm#!/bin/sh # # A convenient front-end for the various mpeg encoding tools. # Allows "1 command" production of a video stream... # # Licensed under GPL (see http://www.fsf.org/licenses/gpl.html or contact # the Free Software Foundation for a copy) # Copyright Scott Moser # these can be changed with env variables, just set and export to override NICEVAL=${NICEVAL:-19} LAV2YUV=${LAV2YUV:-"lav2yuv"} YUVSCALER=${YUVSCALER:-"yuvscaler"} MPEG2ENC=${MPEG2ENC:-"mpeg2enc"} LAV2WAV=${LAV2WAV:-"lav2wav"} AUDIOENC=${AUDIOENC:-"mp2enc"} # can be "toolame" or "mp2enc" MPLEX=${MPLEX:-"mplex"} YUVDENOISE=${YUVDENOISE:-"yuvdenoise"} LAVINFO=${LAVINFO:-"lavinfo"} NOISYLOGFILE="" # if not set, will be outputfilename.log -- only used if -L flag sent QUIETLOG=${QUIETLOG:-"lav2mpeg.log"} # if set to not "" will log all normal messages to this file as well as stdout LOGDATE=${LOGDATE:-1} # whether or not to output the date in log messages LOGDATESTR=${LOGDATESTR:-"+%H:%M:%S"} # format for the date - only used if logdate!=0 LOGCOMMANDS=${LOGCOMMANDS:-0}; # if non-zero, will output the commands it runs. commands are always logged to NOISYLOGFILE if used LOGONLY=${LOGONLY:-""} # will only log the commands it would use if set (for example useage/testing) LAV2MPEGRC=${LAV2MPEGRC:-"$HOME/.lav2mpegrc"} # set this to contain your lav2mpeg rc file -- in bash sourceable syntax. # it can modify any ENV vars in this script # or set a "LAV2MPEG_OPTIONS" ENV to prepend default options that will be overridden by explicit command line options. if [ "$LOGONLY" != "" ]; then LOGCOMMANDS=1 fi VCD_MEDIUM_BR=${VCD_MEDIUM_BR:-1550} VCD_HIGH_BR=${VCD_HIGH_BR:-1800} SVCD_HIGH_BR=${SVCD_HIGH_BR:-3000} SVCD_HIGH_QUAL=${SVCD_HIGH_QUAL:-5} SVCD_HIGH_BUFFSIZE=${SVCD_HIGH_BUFFSIZE:-100} # extra flags for the encoders (will be the last thing on the line before file names) EXTRA_LAV2YUV=${EXTRA_LAV2YUV:-""} EXTRA_YUVSCALER=${EXTRA_YUVSCALER:-""} EXTRA_MPEG2ENC=${EXTRA_MPEG2ENC:-""} EXTRA_LAV2WAV=${EXTRA_LAV2WAV:-""} EXTRA_AUDIOENC=${EXTRA_AUDIOENC:-""} EXTRA_MPLEX=${EXTRA_MPLEX:-""} EXTRA_YUVDENOISE=${EXTRA_YUVDENOISE:-""} # things that can be changed with arguments # don't let an env override, to avoid confusion bitrate=1152 quality=12 saveraw=0 mode="vcd" outputres="" encode_quality=2 outfile="" stereo=1 noisy=0 logall=0 aencbpr_stereo=224 aencbpr_mono=112 use_fifo=0 # -- shouldn't have to change below here NICE="nice -n $NICEVAL" # functions logIt() { if [ $LOGDATE -ne 0 ]; then NOW=$(date $LOGDATESTR) NOW="$NOW - " fi if [ "$logfile" = "" ]; then echo "${NOW}$@" else echo "${NOW}$@" | tee -a $logfile fi if [ "$output_noisy" != "" ]; then echo "${NOW}$@" >> $noisylog fi } cleanExit() { # delete raw files if sawraw is 0 or exiting with non-zero if [ $saveraw -eq 0 -a "$1" = "0" ]; then rm -f $audio $video fi exit $1 } getTimeDiff() { if [ $# -lt 2 ]; then return fi diff=$(expr $2 - $1) hours=$(expr $diff / 3600) temp=$(expr $hours \* 3600 ) diff=$(expr $diff - $temp ) minutes=$(expr $diff / 60) sec=$(expr $diff % 60) printf "%i:%02d:%02d\n" "$hours" "$minutes" "$sec" } doStep() { if [ "$LOGCOMMANDS" = "0" ]; then echo "COMMAND=${step[$count]}" fi if [ "$LOGONLY" = "" ]; then eval ${step[$count]} fi } usage() { name=`basename $0` cat << END Usage: $name [ -s/S -k/K -f/F -l/L -n/N -y/Y ] [ -m mode ] [ -e 0|1|2 ] [ -o outputFile ] [ -b vidbitrate ] [ -a audbitrate ] [ -q 0-30 ] [ -d XxY ] srcfile... s/S - stereo : -s=off -S=on (default auto) k/K - keep raw output files (.m1v, .m2v, .mp2) : -k=no -K=yes (default no) f/F - use fifos : -f=no -F=yes (default no) l/L - log all encoding : -l=no -L=yes (default no) n/N - be noisy (don't hide output of tools) : -n=no -N=yes (default no) y/Y - yuvdenoise : -y=don't use -Y=use (default e=1|2 use e=0 dont) m - one of MODES (see below) (default $mode) e - encoding quality : 0, 1, or 2 (default $encode_quality) o - output file ( defaults to firstInputFileName.mpg ) b - video bitrate in kbps ( only used when -o is "mpeg1" or "mpeg2" ) a - audio bitrate in kpbs ( only used when -o is not "vcd*" ) q - quality for mpeg2enc ( only used when -o is "mpeg1" or "mpeg2" ) d - dimensions XxY ( only used when -o is "mpeg1" or "mpeg2" ) defaults to same as input MODES: vcd -- standard VCD (352x240 or 352x288) vcd_medium -- ${VCD_MEDIUM_BR}kbps video VCD (352x240 or 352x288) vcd_high -- ${VCD_HIGH_BR}kbps video VCD (352x240 or 352x288) svcd -- standard SVCD (480x480 or 480x576) svcd_high -- ${SVCD_HIGH_BR}kbps(max) vbr @qual=${SVCD_HIGH_QUAL} (480x480 or 480x576) mpeg1 -- honor -a -b -q -d flags default resolution same as input mpeg2 -- honor -a -b -q -d flags default resolution same as input EXAMPLE: VCD: $name file.avi - will create a VCD compatible mpeg named file.mpg mpeg2: $name -m mpeg2 -o output.mpg file.edl - will create a mpeg2 with default bitrate in same res as input mpeg1: $name -a 160 -b 2110 -d 320x240 -m mpeg1 -o output.mpg file.edl - will create a mpeg2 with videobitrate=2110 and audio=160 - and resolution 320x240 debug: export LOGONLY=1; $name -m mpeg2 -o output.mpg file.edl - will print out the commands it would use to do this, but - not do anything please see the script for more info and environment variables set/used END exit 1 } printDebugInfo() { logIt "going from ${video_width}x${video_height} ($video_norm) to ${output_width}x${output_height} in $mode with quality=$quality, bitrate=$bitrate and encodequal=${encode_quality}" logIt "outfile=$outfile audio=$audio video=$video" logIt "lav2yuv_flags=$lav2yuv_flags" logIt "yuscaler_flags=$yuvscaler_flags" logIt "mpeg2enc_flags=$mpeg2enc_flags" logIt "lav2wav_flags=$lav2wav_flags" logIt "audioenc_flags=$audioenc_flags" logIt "mplex_flags=$mplex_flags" logIt "need_scale=$needscale" logIt "downscale=$downscaling" } if [ $# -eq 0 -o "$1" = "--help" -o "$1" = "-h" ]; then usage; exit 1 fi LAVRC_COUNT=0 if [ -e $LAV2MPEGRC ]; then logIt "Sourcing lav2mpgrc file $LAV2MPEGRC (this can change defaults!)" . $LAV2MPEGRC LAVRC_COUNT=$(echo $LAV2MPEG_OPTIONS | wc -w ) fi infostr="" while getopts "sSkKfFlLnNyYb:a:q:d:m:e:o:" opt $LAV2MPEG_OPTIONS $@ do case $opt in s) userstereo=0 infostr="${infostr} using mono -" ;; S) userstereo=1 infostr="${infostr} using stereo -" ;; k) saveraw=0 infostr="${infostr} not saving raw files -" ;; K) saveraw=1 infostr="${infostr} saving raw files -" ;; f) use_fifo=0 infostr="${infostr} not using fifos-" ;; F) use_fifo=1 infostr="${infostr} using fifos-" ;; l) logall=0 infostr="${infostr} not logging all -" ;; L) logall=1 infostr="${infostr} logging all -" ;; n) noisy=0 infostr="${infostr} not being noisy -" ;; N) noisy=1 infostr="${infostr} being noisy -" ;; y) userdenoise=0 infostr="${infostr} not using yuvdenoise -" ;; Y) userdenoise=1 infostr="${infostr} using yuvdenoise -" ;; b) bitrate=$OPTARG infostr="${infostr} using video bitrate=$bitrate -" ;; a) useraencbpr=$OPTARG infostr="${infostr} using audio bitrate=$useraencbpr" ;; q) quality=$OPTARG infostr="${infostr} using quality=$quality -" ;; d) outputres=$OPTARG infostr="${infostr} using outputres=$outputres -" ;; m) mode=$OPTARG infostr="${infostr} mode=$mode -" ;; e) encode_quality=$OPTARG infostr="${infostr} encode_quality=$encode_quality -" ;; o) outfile=$OPTARG infostr="${infostr} outfile=$outfile -" ;; ?) usage ;; esac done let MOPTIND=OPTIND-LAVRC_COUNT shift `expr $MOPTIND - 1` if [ "${QUIETLOG}" != "" ]; then logfile=${QUIETLOG} else logfile="/dev/null" fi #uncomment to blank logfile #echo "" > $logfile logIt "$infostr" # lavinfo should set up video_frames, video_width # video_height, video_inter, video_norm, audio_chans eval $($LAVINFO $@ | grep "=") # grep for = to remove Warnings if [ "$video_frames" = "" ]; then logIt "'lavinfo $@' died! exiting" logIt " maybe you don't have lavinfo. or your input flags were wrong" logIt " input files must be the last input on the command line" exit 1 fi case $mode in vcd*) case $video_norm in NTSC) output_width=352; output_height=240 ;; PAL) output_width=352; output_height=288 ;; SECAM) output_width="SECAM_VCD_WIDTH???"; output_height="SECAM_VCD_HEIGHT";; esac ;; svcd*) case $video_norm in NTSC) output_width=480; output_height=480 ;; PAL) output_width=480; output_height=576;; SECAM) output_width="SECAM_SVCD_WIDTH???"; output_height="SECAM_SVCD_HEIGHT" ;; esac ;; mpeg*) if [ "$outputres" != "" ]; then temp=$outputres temp=${outputres%%[+-]*} output_width=${temp%x*} output_height=${temp#*x} logIt "using output_width=$output_width, output_height=$output_height" # these don't work yet, negative values would mess them up temp=${outputres#*+} output_xoff=${temp%%[+-]*} output_yoff=${temp##*[+-]} else output_width=$video_width output_height=$video_height fi ;; esac # hopefully sane input has been checked, lets start setting things up # simple check for logonly mode if [ "$LOGONLY" != "" -a "$LOGONLY" != "0" -a $use_fifo -eq 1 ]; then use_fifo=0 logIt "can't do logonly with fifos, turning fifos off" fi # set up extra flags as possibly given by user lav2yuv_flags=$EXTRA_LAV2YUV yuvscaler_flags=$EXTRA_YUVSCALER mpeg2enc_flags=$EXTRA_MPEG2ENC lav2wav_flags=$EXTRA_LAV2WAV audioenc_flags=$EXTRA_AUDIOENC mplex_flags=$EXTRA_MPLEX yuvdenoise_flags=$EXTRA_YUVDENOISE # get output mpeg version and output file names case $mode in vcd|vcd_medium|vcd_high|mpeg1) mpegver=1 ;; svcd|svcd_high|mpeg2) mpegver=2 ;; esac if [ "$outfile" != "" ]; then basename=${outfile%.*} else basename=${1%.*} outfile=${basename}.mpg fi video=${basename}.m${mpegver}v audio=${basename}.mp2 if [ "$NOISYLOGFILE" = "" ]; then noisylog=${basename}.log else noisylog=$NOISYLOGFILE fi # set up the audio if [ "$userstereo" = "" ]; then stereo=${audio_chans:-0} else stereo=$userstereo fi if [ $AUDIOENC = "mp2enc" ]; then nostereo_flag="-m" else nostereo_flag="-a" fi if [ "$stereo" != "0" ]; then aencbpr=$aencbpr_stereo else aencbpr=$aencbpr_mono mono_flag=$nostereo_flag fi # set useraencbpr to aencbpr unless set useraencbpr=${useraencbpr:-$aencbpr} # set up always-on flags lav2yuv_flags="$lav2yuv_flags $@" case $video_norm in PAL) ysnorm="p";; SECAM) ysnorm="s";; NTSC|*) ysnorm="n";; esac yuvscaler_flags="-n $ysnorm $yuvscaler_flags" mpeg2enc_flags="-o $video $mpeg2enc_flags" lav2wav_flags="$lav2wav_flags $@" if [ $AUDIOENC = "mp2enc" ]; then audioenc_flags="$mono_flag -r 44100 ${audioenc_flags} -o $audio" else # assume toolame audioenc_flags="$mono_flag -s 44.1 /dev/stdin ${audioenc_flags} $audio" fi mplex_flags=" -o $outfile $mplex_flags $audio $video" # input/output dependent if [ $video_width -eq $output_width -a $video_height -eq $output_height ]; then needscale=0; else needscale=1 fi downscaling=0 if [ $video_width -gt $output_width -o $video_width -eq $output_width ]; then if [ $video_height -gt $output_height -o $video_height -eq $output_height ]; then downscaling=1 fi fi if [ "$video_inter" = "1" ]; then yuvdenoise_flags="$yuvdenoise_flags -F" fi #encoder quality dependent case ${encode_quality} in 0) mpeg2enc_flags="-4 4 -2 4 ${mpeg2enc_flags}" if [ $downscaling -ne 0 ]; then yuvscaler_flags="-M RESAMPLE ${yuvscaler_flags}" fi dodenoise=0 if [ "$userdenoise" != "" -a "$userdenoise" != "0" ]; then logIt "set dodenoise to on at users request" dodenoise=1 fi ;; 2) mpeg2enc_flags="-4 1 -2 1 ${mpeg2enc_flags}" # -N here? dodenoise=1 if [ "$userdenoise" != "" -a "$userdenoise" = "0" ]; then dodenoise=0 fi ;; 1|*) dodenoise=1 if [ "$userdenoise" != "" -a "$userdenoise" = "0" ]; then dodenoise=0 fi ;; esac # output(mode) dependent case ${mode} in vcd) yuvscaler_flags="-O VCD ${yuvscaler_flags}" mpeg2enc_flags="-a 2 -f 1 ${mpeg2enc_flags}" mplex_flags="-f 1 ${mplex_flags}" ;; vcd_medium) yuvscaler_flags="-O VCD ${yuvscaler_flags}" mpeg2enc_flags="-a 2 -f 2 -b ${VCD_MEDIUM_BR} ${mpeg2enc_flags}" mplex_flags="-f 2 ${mplex_flags}" ;; vcd_high) yuvscaler_flags="-O VCD ${yuvscaler_flags}" mpeg2enc_flags="-a 2 -f 2 -b ${VCD_HIGH_BR} ${mpeg2enc_flags}" mplex_flags="-f 2 ${mplex_flags}" ;; mpeg1) yuvscaler_flags="-O SIZE_${output_width}x${output_height} ${yuvscaler_flags}" mpeg2enc_flags="-f 0 -b ${bitrate} ${mpeg2enc_flags}" mplex_flags="-f 0 ${mplex_flags}" aencbpr=$useraencbpr ;; svcd) yuvscaler_flags="-O SVCD ${yuvscaler_flags}" mpeg2enc_flags="-a 2 -f 4 ${mpeg2enc_flags}" mplex_flags="-f 4 ${mplex_flags}" aencbpr=$useraencbpr audioenc_flags="-e $audioenc_flags" ;; svcd_high) yuvscaler_flags="-O SVCD ${yuvscaler_flags}" mpeg2enc_flags="-a 2 -f 5 -b ${SVCD_HIGH_BR} -V ${SVCD_HIGH_BUFFSIZE} -q ${SVCD_HIGH_QUAL} ${mpeg2enc_flags}" mplex_flags="-f 5 ${mplex_flags}" aencbpr=$useraencbpr audioenc_flags="-e $audioenc_flags" ;; mpeg2) yuvscaler_flags="-O SIZE_${output_width}x${output_height} ${yuvscaler_flags}" mpeg2enc_flags="-f 3 -b ${bitrate} -q $quality ${mpeg2enc_flags}" mplex_flags="-V -f 3 ${mplex_flags}" aencbpr=$useraencbpr ;; esac if [ $dodenoise -ne 0 ]; then yuvdenoise_str="| $NICE $YUVDENOISE $yuvdenoise_flags" else yuvdenoise_str="" logIt "not using yuvdenoiser, dodenoise=$dodenoise" fi if [ $needscale -ne 0 ]; then yuvscale_str="| $NICE $YUVSCALER $yuvscaler_flags" else yuvscale_str="" fi #final flags -- bitrate flag is -b for both mp2enc and toolame audioenc_flags="-b $aencbpr $audioenc_flags" # this is kinda nasty, but it ends up giving a somewhat clean loop at the # bottom without a whole lot of if's and such count=1; stepdesc[$count]="video encoding" step[$count]="$NICE $LAV2YUV $lav2yuv_flags $yuvdenoise_str $yuvscale_str | $NICE $MPEG2ENC $mpeg2enc_flags" count=2; stepdesc[$count]="audio encoding" step[$count]="$NICE $LAV2WAV $lav2wav_flags | $NICE $AUDIOENC $audioenc_flags" count=3; if [ $use_fifo -eq 1 ]; then stepdesc[$count]="encoding with fifos" else stepdesc[$count]="multiplexing" fi step[$count]="$NICE $MPLEX $mplex_flags" output_noisy="" if [ $noisy -ne 0 -a $logall -ne 0 ]; then output_noisy="2>&1 | tee -a $noisylog" echo "" > $noisylog fi if [ $noisy -eq 0 ]; then if [ $logall -eq 0 ]; then noisylog="/dev/null" fi echo "" > $noisylog output_noisy=">>$noisylog 2>&1" fi detach="" if [ $use_fifo -ne 0 ]; then detach="&"; saveraw=0 rm -f $video $audio mkfifo $video mkfifo $audio fi logIt "using mode=$mode, stereo=$stereo audio bpr=$aencbpr" if [ $logall -ne 0 ]; then logIt "logging everything to $noisylog" fi logIt "beginning conversion of $@ to $outfile" logIt "had $video_frames to encode" STARTALL=$SECONDS for stepnum in 1 2 3 do count=$stepnum START=$SECONDS if [ $stepnum -eq 3 -o $use_fifo -ne 1 ]; then logIt "beginning ${stepdesc[$count]}" if [ $LOGCOMMANDS != "0" ]; then logIt "COMMAND=${step[$count]}" fi fi if [ $stepnum -eq 3 ]; then detach="" # don't detach the last stem (mplex) fi eval doStep $output_noisy $detach RET=$? if [ $RET -ne 0 ]; then logIt "ugh! ${stepdesc[$count]} failed, bailing. used command:" logIt "${step[$count]}" cleanExit $RET fi if [ $stepnum -eq 3 -o $use_fifo -ne 1 ]; then diff=$(getTimeDiff $START $SECONDS) elapsed=$(expr $SECONDS - $START) if [ "$elapsed" != "0" ]; then fps=$(echo "scale=3; $video_frames / $elapsed " | bc) logIt "finished ${stepdesc[$count]} ( took $diff - $fps fps)" else logIt "finished ${stepdesc[$count]} ( took $diff )" fi fi done END=$SECONDS diff=$(getTimeDiff $STARTALL $SECONDS) temp=$(expr $SECONDS - $STARTALL) if [ "$temp" != "0" ]; then # avoid divide by zero possibility fps=$(echo "scale=3; $video_frames / $temp" | bc) logIt "finished encoding (took $diff - $fps fps)" else logIt "finished encoding (took $diff)" fi cleanExit 0 mjpegtools-2.1.0/scripts/berechne0000644000175000017500000000556507306657270017425 0ustar glowwormglowworm#!/bin/sh # berechne # # Dieses shell-sript berechnet, welche Dateien auf eine CD passen. # Es geht von Annahmen aus, die fuer nur fuer mich gelten. # Änderungen sind leicht möglich. # # This shell-script calculates, which files will fit on a CD. # it makes some assumptions that might be wrong for your # you can easily change it according to your needs. # # direct=/video #!!!!!!!!!!! # cd $direct # # 850000000 Platinum CD 700 MB # # 770917120 = 735 MB # # Blocks: 336000 blocks - 650 MB # 360000 blocks - 700 MB # 409600 blocks - 800 MB - kann nicht jeder DVD-Player!! # Not every DVD-Player can do 800 MB CDs. Test it at your own risk. # # mach=`basename $0` echo -e "A = 650MB-CD B = 700MB-CD C = 800MB-CD A | B | C (Enter=B) \c" read a if [ -z "$a" ] then max=850000000 else if [ "$a" = "a" ] || [ "$b" = "A" ] then max="760000000" fi if [ "$a" = "b" ] || [ "$a" = "B" ] then max="850000000" # Rechnet bereits mit leichter Überkapazität # assumes the size according to my CD - yours might vary! fi if [ "$a" = "c" ] || [ "$a" = "C" ] then max="963000000" fi fi zahl="0" tun="" if [ "$mach" = "berechne" ] then echo -e "Welche Dateien berechnen? \c" # English: echo -e "What files should be calculated? \c" else echo -e "Welche Dateien mit vcdimager bearbeiten? \c" # English: echo -e "What files should vcdimager process?" fi read a echo -e "\n Ab welcher Datei? \c" # English: echo -e "\n Starting from? \c" read ab echo -e "\nWelche Datei-extension? (2500_xvcd usw.) \c" # English: echo -e "\n Which file-extension? (e.g. 2500_xvcd) \c" read add # Annahme: XVCD muss als SVCD gebrannt werden. # dann gilt folgendes: # # I must burn XVCD like SVCD so the following 8 lines are correct. # Otherwise: comment them with hash and uncomment the 8 lines # that follow later. # SV=`echo ${a}*_${add}.mpg | grep _vcd` if [ -z "$SV" ] then form="-t svcd" else form="" fi # Ende der Abfrage. End of SVCD=XVCD # Die 8 Zeilen muessen kommentiert werden # wenn XVCD alv VCD gebrannt werden muss: # The following 8 lines should be uncommented, if you # have to burn XVCD as VCD. # Start: # SV=`echo ${a}*_${add}.mpg | grep vcd` # if [ -z "$SV" ] # then # form="-t svcd" # else # form="" # fi # End # Ende der Änderung XVCD als VCD # for i in ${a}*_${add}.mpg do if [ $i \< ${a}${ab}_${add}.mpg ] then continue fi z=`du -b $i | cut -f 1` old=$zahl zahl=`expr $zahl + $z` b=`expr $zahl \> $max` if [ $b = "1" ] then if [ "$mach" = "berechne" ] then echo "Ist jetzt: $old wäre sonst: $zahl" # English: echo "Now: $old would be otherwise: $zahl" echo $tun $old fi if [ "$mach" = "mache" ] then echo "Länge = $old evtl. $zahl" # English: echo "Length = $old otherwise $zahl" vcdimager $form $tun fi exit 0 else echo $i tun="$tun $i" fi done if [ "$mach" = "berechne" ] then echo $tun $old $zahl else echo "Länge = $old evtl. $zahl" # English: echo "Length = $old otherwise $zahl" vcdimager $form $tun fi mjpegtools-2.1.0/scripts/makePLI.py0000644000175000017500000003746507633670526017571 0ustar glowwormglowworm#Make a lavpipe pli file from a simpler input file. #Use python makePLI.py --man for detailed usage. #Assumptions: # All transitions are the same length. # All transitions have the same characteristics. # All input streams have the same characteristics. # Copyright (C) 2002, Bob Matlin # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You probably received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. import os.path import sys import string class Clip: #default values __offsetUnits = 's' __lengthUnits = 's' __framesPerSec = 29.97 #NTSC __lenOrStop = 'length' #determines whether or not the lenOrStop param specifies length or stop time/position def __init__(self,fileName=None, offset=None, lenOrEnd=None): """ The default constructor permits changing default values. fileName - the name of the file; may contain path information offset - the time at which to start playing expressed in specified units; unit default is seconds lenOrStop - the length or the end position of the clip expressed in specified units; unit default is seconds """ if (fileName == None): return noffset = 0 if (Clip.__offsetUnits == 's'): noffset = float(offset) elif (Clip.__offsetUnits == 'f'): noffset = int(offset) nlenOrEnd = 0 if (Clip.__lengthUnits == 's'): nlenOrEnd = float(lenOrEnd) elif (Clip.__lengthUnits == 'f'): nlenOrEnd = int(lenOrEnd) self.fileName = fileName self.offsetTime = self.__getOffsetTime(noffset) self.lengthTime = self.__getLengthTime(nlenOrEnd) framesPerSec = self.__framesPerSec self.offsetFrames = self.__getOffsetFrames(noffset) self.lengthFrames = self.__getLengthFrames(nlenOrEnd) if (self.offsetFrames > 0): self.lastFrame = self.offsetFrames -1 else: self.lastFrame = self.offsetFrames self.clipEnd = self.offsetFrames + self.lengthFrames ##print "fileName: " + self.fileName + ", clipEnd: " + str(self.clipEnd) def setOffsetUnits(self,units): """ units - one of s (seconds) or f (frames) """ Clip.__offsetUnits = units def setLengthUnits(self,units): """ units - one of s (seconds) or f (frames) """ Clip.__lengthUnits = units def setLenOrStopType(self,lenOrStop): """ lenOrStop - either 'length' or 'stop' """ if (lenOrStop != 'length' and lenOrStop != 'stop'): raise "(makePLI.py) Invalid length/stop specifier; must be one of [length,stop]." Clip.__lenOrStopType = lenOrStop def __getOffsetTime(self,offset): """ offset - the clip offset, expressed in specified class default units """ if (Clip.__offsetUnits == 's'): return(offset) elif (Clip.__offsetUnits == 'f'): return(offset/Clip.__framesPerSec) def __getOffsetFrames(self,offset): """ offset - the clip offset, expressed in specified class default units """ if (Clip.__offsetUnits == 's'): return(int(offset * Clip.__framesPerSec)) elif (Clip.__offsetUnits == 'f'): return(offset) def __getLengthTime(self,lenOrEnd): """ lenOrEnd - the length or end of clip, expressed in class default units """ if (Clip.__lengthUnits == 's'): return(lenOrEnd) elif (Clip.__lengthUnits == 'f'): return(lenOrEnd/Clip.__framesPerSec) def __getLengthFrames(self,lenOrEnd): """ lenOrEnd - the length or end of clip, expressed in class default units """ f = 0 if (Clip.__lengthUnits == 's'): f = int(lenOrEnd * Clip.__framesPerSec) elif (Clip.__lengthUnits == 'f'): f = lenOrEnd if (Clip.__lenOrStopType == 'stop'): f = f - self.offsetFrames return(f) class PPLIFile: """ A PPLIFile is the file containing the directives and file list needed to make a pli file. """ def __init__(self): self.__lineNum = 0 def handleLine(self,line): """ Takes action on a line obtained from a ppli file. return - a Clip if the line contained clip data, None otherwise """ self.__lineNum = self.__lineNum + 1 s = line.strip() if (len(s) == 0): return(None) if (s.find('#') == 0): return(None) #comment lines start with '#'; ignore them if (s.find('$') == 0): #this is a clip directive return(self.handleDirective(s)) #else this is a clip a = s.split() if (len(a) != 3): raise Exception("(makePLI.py - definition file line " + str(self.__lineNum) + "): A clip line must look like: fileName offset length.") clip = Clip(a[0],a[1],a[2]) return(clip) def handleDirective(self,line): """ Take an action on a directive line. """ s = line a = s.split() if (a[0] == '$format'): if (len(a) != 3): raise Exception("(makePLI.py - definition file line " + str(self.__lineNum) + "): a $format directive must look like: $format offset: length:") else: clip = Clip() #get the offset units aa = a[1].split(":") if (len(aa) != 2): raise Exception("(makePLI.py - definition file line " + str(self.__lineNum) + "): a $format directive must look like: $format offset: length:") clip.setOffsetUnits(aa[1]) #get the length/stop type and units aa = a[2].split(":") if (len(aa) != 2): raise Exception("(makePLI.py - defnition file line " + str(self.__lineNum) + "): a $format directive must look like: $format offset: length:") try: clip.setLenOrStopType(aa[0]) except: (t,v,tb) = sys.exc_info() msg = "(makePLI.py - definition file line " + str(self.__lineNum) + "): " + str(t) raise msg clip.setLengthUnits(aa[1]) return(None) else: raise Exception("(makePLI.py - definition file line " + str(self.__lineNum) + "): Invalid directive; valid directives: $format.") def getUsage(): s = "\nUsage: python makePLI.py [--help] [--man] --file fileName [--transLen length]\n" s = s + "where 'fileName' is the name of the definition file \n" s = s + "and 'length' is the number of frames in each transition.\n" s = s + "--man prints a detailed usage document;\n" s = s + "--help prints this message.\n" return(s) def getMan(): s = getUsage() s = s + "\nOverview\n\n" s = s + "This program produces an output file that uses the mjpeg tools lavpipe, \n" s = s + "lav2yuv, and transist.flt. It has been used to create the video sequence\n" s = s + "for a video montage. When the output file is processed with lavpipe, the\n" s = s + "result is an avi file containing video only; audio can be added with lavaddwav.\n\n" s = s + "Assumptions:\n" s = s + "\tall transitions are the same length;\n" s = s + "\tall transitions have the same characteristics;\n" s = s + "\tall input streams have the same characteristics.\n\n" s = s + "Process\n\n" s = s + "Given an input definition file (referred to as a ppli file - pre pli), makePLI.py\n" s = s + "will produce an output file (referred to as a pli file; see man lavpipe) suitable\n" s = s + "for submission to lavpipe. The output of lavpipe will be an mjpeg avi file with\n" s = s + "equal transitions between the given video clips.\n\n" st = 1 s = s + str(st) + " Create the definition file\n\n" s = s + "The definition file consists of: directives that control the behavior of makePLI.py;\n" s = s + "clips that specify the video clip sources and order; and comments. Directives \n" s = s + "must preceed clips and comments may be placed anywhere.\n\n" sst = 1 s = s + str(st) + "." + str(sst) + " Directives\n\n" s = s + "Directives are lines that begin with '$'. Currently there is only one\n" s = s + "directive, $format:\n\n" s = s + "$format offset: :\n" s = s + "\twhere is either 's' (seconds) or 'f' (frames);\n" s = s + "\t is either 'length', meaning that the lenOrEnd value\n" s = s + "\tspecifies the clip length, or 'stop' meaning that the lenOrEnd value\n" s = s + "\tspecifies the end of the clip relative to the offset.\n" s = s + "If there is more than one $format line, the last one takes precedence.\n\n" s = s + "Format Examples:\n\n" s = s + "\t$format offset:s length:s\n" s = s + "\t$format offset:f length:s\n" s = s + "\t$format offset:f stop:f\n\n" st = st + 1 s = s + str(st) + " Clips\n\n" s = s + "Clips are lines that specify the source files, the position to start\n" s = s + "in the clip, and the position to end in the clip:\n\n" s = s + " \n" s = s + "\twhere is the name of the lav source;\n" s = s + "\t is the starting position in the clip as determined by the $format;\n" s = s + "\t is the ending position in the clip as determined by the $format.\n\n" s = s + "Both start and end may be expressed in frames or seconds as determined by the $format.\n\n" s = s + "Clip Examples:\n\n" s = s + "\tintro.avi 0 25\n" s = s + "\tmain.avi 15.37 30.25\n\n" s = s + "Note that the numeric values may be either integers or floats; the proper\n" s = s + "type is determined by the $format; if the type is frames, the value should be an int;\n" s = s + "if the type is seconds, the value can be a float.\n\n" s = s + "A full example\n\n" s = s + "Given the input file montage.ppli containing the following:\n\n" s = s + "#a sample ppli file\n" s = s + "$format offset:f length:s\n" s = s + "intro.avi 0 30\n" s = s + "clip.avi 61 25.37\n" s = s + "end.avi 0 30\n\n" s = s + "Running this command from a shell:\n\n" s = s + "\t$ python makePLI.py --file montage.ppli > montage.pli\n\n" s = s + "produces this output:\n\n" s = s + "LAV Pipe List\n" s = s + "NTSC\n" s = s + "3\n" s = s + "lav2yuv -v 0 -o $o -f $n intro.avi\n" s = s + "lav2yuv -v 0 -o $o -f $n clip.avi\n" s = s + "lav2yuv -v 0 -o $o -f $n end.avi\n" s = s + "868\n" s = s + "1\n" s = s + "0 0\n" s = s + "-\n" s = s + "30\n" s = s + "2\n" s = s + "0 869\n" s = s + "1 60\n" s = s + "transist.flt -v 0 -s $o -n $n -o 0 -O 255 -d 30\n" s = s + "699\n" s = s + "1\n" s = s + "1 90\n" s = s + "-\n" s = s + "30\n" s = s + "2\n" s = s + "1 790\n" s = s + "2 0\n" s = s + "transist.flt -v 0 -s $o -n $n -o 0 -O 255 -d 30\n" s = s + "868\n" s = s + "1\n" s = s + "2 30\n" s = s + "-\n\n" s = s + "Error reporting\n\n" s = s + "Some attempt is made to spot errors. If a specified clip is not long\n" s = s + "enough to satisfy the required lengths, you will get an error message like:\n\n" s = s + "(makePLI.py) - intro.avi is too short; total needed: 51 frames; actual length: 44 frames\n\n" s = s + "Notes\n\n" s = s + "It seems that there is a limit on the number of clips that can be\n" s = s + "processed at once. I do not know where the limitation lies. On my system\n" s = s + "the limit seems to be about 15 clips. To get around this problem\n" s = s + "I break up the lists into two files, then combine the result with\n" s = s + "another ppli and lavpipe operation.\n\n" s = s + "Author\n\n" s = s + "The program and the documentation were written by Bob Matlin .\n\n" return(s) #main if (len(sys.argv) < 2 or '--help' == sys.argv[1]): print(getUsage()) sys.exit(0) #default values fileName = None transLen = 30 #each transition is 30 frames #get arguments for i in range(len(sys.argv)): if (sys.argv[i] == '--file'): i = i + 1 fileName = sys.argv[i] elif (sys.argv[i] == '--transLen'): i = i + 1 transLen = int(sys.argv[i]) elif (sys.argv[i] == '--man'): s = getMan() print s sys.exit(0) if (fileName == None): s = "(makePLI.py) - no file specified.\n\n" s = s + getUsage() raise Exception(s) if (not os.path.exists(fileName)): s = "(makePLI.py) - given file does not exist: '" + str(fileName) + "'\n\n" s = s + getUsage() raise Exception(s) #read file f = open(fileName) flist = [] l = "a" ppliFile = PPLIFile() while (l): l = f.readline() clip = ppliFile.handleLine(l) if (clip != None): flist.append(clip) #the pli header s = 'LAV Pipe List\n' s += 'NTSC\n' s += str(len(flist)) print s #the stream list st = 'lav2yuv -v 0 -o $o -f $n ' for i in range(len(flist)): c = flist[i] s = st + c.fileName print s #build sequences #first clip idx = 0 ##print "sequence " + str(idx) c = flist[idx] if (1 + transLen >= c.lengthFrames): tot = 1 + transLen raise "(makePLI.py) - " + c.fileName + " is too short; total needed: " + str(tot) + " frames; actual length: " + str(c.lengthFrames) + " frames" l = c.lengthFrames - transLen - 1 s = str(l) + '\n' s += '1\n' s += str(idx) + ' ' + str(c.lastFrame) + '\n' c.lastFrame += l s += '-' print s #the middle sequences transist = 'transist.flt -v 0 -s $o -n $n -o 0 -O 255 -d ' seqn = -1 for idx in range(len(flist) - 1): #the transition seqn += 2 ##print "sequence " + str(seqn) l = transLen c1 = flist[idx] c2 = flist[idx + 1] if (1 + (2*transLen + 1) > c2.lengthFrames): #there is a 1 frame minimum for this clip on its own; the extra 1 is for 1 frame at the end tot = 1 + 2*transLen + 1 raise "(makePLI.py) - seq " + str(seqn) + ": " + c2.fileName + " is too short; needed: " + str(tot) + ", available: " + str(c2.lengthFrames) s = str(l) + '\n' s += '2\n' s += str(idx) + ' ' + str(c1.lastFrame + 1) + '\n' c1.lastFrame += l if (c1.lastFrame >= c1.clipEnd): raise "(makePLI.py) - " + c1.fileName + " will go past the clip end." s += str(idx + 1) + ' ' + str(c2.lastFrame) + '\n' c2.lastFrame += l s += transist + str(l) print s if (idx + 1 == len(flist) - 1): continue #the next clip ##print "sequence " + str(seqn + 1) l = c2.lengthFrames - (2*transLen + 1) s = str(l) + '\n' s += '1\n' s += str(idx + 1) + ' ' + str(c2.lastFrame) + '\n' c2.lastFrame += l if (c2.lastFrame >= c2.clipEnd): raise "(makePLI.py) - " + c2.fileName + " will go past the clip end." s += '-' print s #last frame ##print "sequence: " + str(seqn + 2) idx = len(flist) - 1 c = flist[idx] l = c.lengthFrames - transLen - 1 s = str(l) + '\n' s += '1\n' s += str(idx) + ' ' + str(c.lastFrame) + '\n' c.lastFrame += l if (c.lastFrame >= c.clipEnd): raise "(makePLI.py) - " + c.fileName + " will go past the clip end." s += '-' print s #debug ##for c in flist: ## print "file: " + c.fileName + ", end: " + str(c.clipEnd) + ", lastFrame: " + str(c.lastFrame) mjpegtools-2.1.0/lavtools/0000755000175000017500000000000012217306500016050 5ustar glowwormglowwormmjpegtools-2.1.0/lavtools/yuv2lav.c0000644000175000017500000003553111507307411017636 0ustar glowwormglowworm/* * yuv2lav - write YUV4MPEG data stream from stdin to mjpeg file * * Copyright (C) 2000, pHilipp Zabel * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include "mjpeg_logging.h" #include "yuv4mpeg.h" #include "jpegutils.h" #include "lav_io.h" #define FOURCC(a,b,c,d) ( (d<<24) | ((c&0xff)<<16) | ((b&0xff)<<8) | (a&0xff) ) #define FOURCC_RIFF FOURCC ('R', 'I', 'F', 'F') #define FOURCC_WAVE FOURCC ('W', 'A', 'V', 'E') #define FOURCC_FMT FOURCC ('f', 'm', 't', ' ') #define FOURCC_DATA FOURCC ('d', 'a', 't', 'a') static int param_quality = 80; static char param_format = 'x'; /* a format we don't know */ static char *param_output = 0; static char *param_inputwav = NULL; static int param_bufsize = 256*1024; /* 256 kBytes */ static int param_interlace = -1; static int param_maxfilesize = 0; static int got_sigint = 0; static int verbose = 1; static void usage(void) { fprintf(stderr, "Usage: yuv2lav [params] -o \n" "where possible params are:\n" " -v num Verbosity [0..2] (default 1)\n" " -f [aA" #ifdef HAVE_LIBQUICKTIME "q" #else " " #endif " " "] output format (AVI" #ifdef HAVE_LIBQUICKTIME "/Quicktime" #endif ") [%c]\n" " -I num force output interlacing 0:no 1:top 2:bottom field first\n" " -q num JPEG encoding quality [%d%%]\n" " -b num size of MJPEG buffer [%d kB]\n" " -m num maximum size per file [%d MB]\n" " -w file WAVE file - audio data to be added to output file\n" " -o file output mjpeg file (REQUIRED!)\n", param_format, param_quality, param_bufsize/1024, param_maxfilesize); } static void sigint_handler (int signal) { mjpeg_debug( "Caught SIGINT, exiting..."); got_sigint = 1; } int main(int argc, char *argv[]) { int frame; int fd_in; int wav_fd = 0; long data[64]; int fmtlen; double fps; long audio_samps = 0; long audio_rate = 0; int audio_chans = 0; int audio_bits = 0; int audio_bps = 1; double absize = 0.0; long asize = 0; uint8_t *abuff = NULL; long na_out = 0; int n; lav_file_t *output = 0; int filenum = 0; unsigned long filesize_cur = 0; char *dotptr; uint8_t *jpeg; int jpegsize = 0; unsigned char *yuv[3]; y4m_frame_info_t frameinfo; y4m_stream_info_t streaminfo; while ((n = getopt(argc, argv, "v:f:I:q:b:m:o:w:")) != -1) { switch (n) { case 'v': verbose = atoi(optarg); if (verbose < 0 || verbose > 2) { mjpeg_error( "-v option requires arg 0, 1, or 2"); usage(); } break; case 'f': switch (param_format = optarg[0]) { case 'a': case 'A': #ifdef HAVE_LIBQUICKTIME case 'q': #endif /* do interlace setting here? */ continue; default: mjpeg_error( "-f parameter must be one of [aA" #ifdef HAVE_LIBQUICKTIME "q" #endif "]"); usage (); exit (1); } break; case 'I': param_interlace = atoi(optarg); if (2 < param_interlace) { mjpeg_error("-I parameter must be one of 0,1,2"); exit (1); } break; case 'q': param_quality = atoi (optarg); if ((param_quality<24)||(param_quality>100)) { mjpeg_error( "quality parameter (%d) out of range [24..100]!", param_quality); exit (1); } break; case 'b': param_bufsize = atoi (optarg) * 1024; /* constraints? */ break; case 'm': param_maxfilesize = atoi(optarg); break; case 'o': param_output = optarg; break; case 'w': param_inputwav = optarg; break; default: usage(); exit(1); } } if (!param_output) { mjpeg_error( "yuv2lav needs an output filename"); usage (); exit (1); } if (param_interlace == 2 && param_format == 'q') { mjpeg_error("cannot use -I 2 with -f %c", param_format); usage (); exit (1); } /* * If NO limit was explicitly specified (to limit files to 2GB or less) then * allow unlimited (well, ok - 4TB ;)) size. ODML extensions will handle the * AVI files and Quicktime has had 64bit filesizes for a long time */ if (param_maxfilesize <= 0) param_maxfilesize = MAX_MBYTES_PER_FILE_64; (void)mjpeg_default_handler_verbosity(verbose); fd_in = 0; /* stdin */ y4m_accept_extensions(1); y4m_init_stream_info(&streaminfo); y4m_init_frame_info(&frameinfo); if (y4m_read_stream_header(fd_in, &streaminfo) != Y4M_OK) { mjpeg_error( "Couldn't read YUV4MPEG header!"); exit (1); } switch (y4m_si_get_interlace(&streaminfo)) { case Y4M_ILACE_NONE: case Y4M_ILACE_TOP_FIRST: case Y4M_ILACE_BOTTOM_FIRST: break; default: mjpeg_error_exit1("unsupported input interlace"); } switch (y4m_si_get_chroma(&streaminfo)) { case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_422: break; case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: mjpeg_warn("unsupported input chroma, assume '420jpeg'"); y4m_si_set_chroma(&streaminfo, Y4M_CHROMA_420JPEG); break; default: mjpeg_error_exit1("unsupported input chroma"); } if (param_interlace < 0) { param_interlace = y4m_si_get_interlace(&streaminfo); } /* If no desired format option was given, we try to detect the format with */ /* the last 4 char of the filename */ dotptr = strrchr(param_output, '.'); if (dotptr && (param_format == 'x')) { #ifdef HAVE_LIBQUICKTIME if (!strcasecmp(dotptr+1, "mov")) param_format = 'q'; #endif if (!strcasecmp(dotptr+1, "avi")) param_format = 'a'; } /* Telling the people which format we really use */ if (param_format == 'a') mjpeg_info("creating AVI output format"); else if (param_format == 'q') mjpeg_info("creating Quicktime output format"); else mjpeg_error_exit1("No format specified add the -f option"); if (param_interlace == Y4M_ILACE_TOP_FIRST && param_format == 'A') param_format = 'a'; else if (param_interlace == Y4M_ILACE_BOTTOM_FIRST && param_format == 'a') param_format = 'A'; fps = Y4M_RATIO_DBL(y4m_si_get_framerate(&streaminfo)); /* Open WAV file */ if (param_inputwav != NULL) { wav_fd = open(param_inputwav,O_RDONLY); if(wav_fd<0) { mjpeg_error_exit1("Open WAV file: %s", strerror(errno));} n = read(wav_fd,(char*)data,20); if(n!=20) { mjpeg_error_exit1("Read WAV file: %s", strerror(errno)); } if(data[0] != FOURCC_RIFF || data[2] != FOURCC_WAVE || data[3] != FOURCC_FMT || data[4] > sizeof(data) ) { mjpeg_error_exit1("Error in WAV header"); } fmtlen = data[4]; n = read(wav_fd,(char*)data,fmtlen); if(n!=fmtlen) { perror("read WAV header"); exit(1); } if( (data[0]&0xffff) != 1) { mjpeg_error_exit1("WAV file is not in PCM format"); } audio_chans = (data[0]>>16) & 0xffff; audio_rate = data[1]; audio_bits = (data[3]>>16) & 0xffff; audio_bps = (audio_chans*audio_bits+7)/8; if(audio_bps==0) audio_bps = 1; /* safety first */ n = read(wav_fd,(char*)data,8); if(n!=8) { mjpeg_error_exit1("Read WAV header: %s", strerror(errno)); } if(data[0] != FOURCC_DATA) { mjpeg_error_exit1("Error in WAV header"); } audio_samps = data[1]/audio_bps; absize = audio_rate/fps; abuff = (uint8_t*) malloc(((int)ceil(absize)+10)*audio_bps); if(abuff==0) { mjpeg_error_exit1("Out of Memory - malloc failed"); } na_out = 0; /* Debug Output */ mjpeg_debug("File: %s",param_inputwav); mjpeg_debug(" audio samps: %8ld",audio_samps); mjpeg_debug(" audio chans: %8d",audio_chans); mjpeg_debug(" audio bits: %8d",audio_bits); mjpeg_debug(" audio rate: %8ld",audio_rate); mjpeg_debug(" "); mjpeg_debug("Length of audio: %15.3f sec",(double)audio_samps/(double)audio_rate); mjpeg_debug(" "); } if (strstr(param_output,"%")) { char buff[256]; sprintf(buff, param_output, filenum++); output = lav_open_output_file (buff, param_format, y4m_si_get_width(&streaminfo), y4m_si_get_height(&streaminfo), param_interlace, fps, (param_inputwav == NULL) ? 0 : audio_bits, (param_inputwav == NULL) ? 0 : audio_chans, (param_inputwav == NULL) ? 0 : audio_rate); if (!output) { mjpeg_error( "Error opening output file %s: %s", buff, lav_strerror ()); exit(1); } } else { output = lav_open_output_file (param_output, param_format, y4m_si_get_width(&streaminfo), y4m_si_get_height(&streaminfo), param_interlace, fps, (param_inputwav == NULL) ? 0 : audio_bits, (param_inputwav == NULL) ? 0 : audio_chans, (param_inputwav == NULL) ? 0 : audio_rate); if (!output) { mjpeg_error( "Error opening output file %s: %s", param_output, lav_strerror ()); exit(1); } } yuv[0] = malloc(y4m_si_get_width(&streaminfo) * y4m_si_get_height(&streaminfo) * sizeof(unsigned char)); mjpeg_info(" Plane 0 X: %i Y: %i, Chroma %i", y4m_si_get_width(&streaminfo), y4m_si_get_height(&streaminfo), y4m_si_get_chroma(&streaminfo)); yuv[1] = malloc(y4m_si_get_width(&streaminfo) * y4m_si_get_height(&streaminfo) * sizeof(unsigned char) / ((y4m_si_get_chroma(&streaminfo) == Y4M_CHROMA_422)? 2: 4)); yuv[2] = malloc(y4m_si_get_width(&streaminfo) * y4m_si_get_height(&streaminfo) * sizeof(unsigned char) / ((y4m_si_get_chroma(&streaminfo) == Y4M_CHROMA_422)? 2: 4)); jpeg = (uint8_t*)malloc(param_bufsize); signal (SIGINT, sigint_handler); frame = 0; while (y4m_read_frame(fd_in, &streaminfo, &frameinfo, yuv)==Y4M_OK && (!got_sigint)) { fprintf (stdout, "frame %d\r", frame); fflush (stdout); jpegsize = encode_jpeg_raw (jpeg, param_bufsize, param_quality, param_interlace, y4m_si_get_chroma(&streaminfo), y4m_si_get_width(&streaminfo), y4m_si_get_height(&streaminfo), yuv[0], yuv[1], yuv[2]); if (jpegsize==-1) { mjpeg_error( "Couldn't compress YUV to JPEG"); exit(1); } if ((filesize_cur + jpegsize + (int)absize*audio_bps)>>20 > param_maxfilesize) { /* max file size reached, open a new one if possible */ if (strstr(param_output,"%")) { char buff[256]; if (lav_close (output)) { mjpeg_error("Closing output file: %s",lav_strerror()); exit(1); } sprintf(buff, param_output, filenum++); output = lav_open_output_file (buff, param_format, y4m_si_get_width(&streaminfo), y4m_si_get_height(&streaminfo), param_interlace, fps, (param_inputwav == NULL) ? 0 : audio_bits, (param_inputwav == NULL) ? 0 : audio_chans, (param_inputwav == NULL) ? 0 : audio_rate); if (!output) { mjpeg_error( "Error opening output file %s: %s", buff, lav_strerror ()); exit(1); } mjpeg_info("Maximum file size reached (%d MB), opened new file: %s", param_maxfilesize, buff); filesize_cur = 0; } else { mjpeg_warn("Maximum file size reached"); break; } } if (lav_write_frame (output, jpeg, jpegsize, 1)) { mjpeg_error( "Writing output: %s", lav_strerror()); exit(1); } filesize_cur += jpegsize; frame++; if (param_inputwav != NULL) { asize = ((int)ceil ((double)frame * absize) - (int)ceil ((double)(frame - 1) * absize)) * audio_bps; fflush (stdout); n = read(wav_fd,abuff,asize); if(n>0) { na_out += n/audio_bps; n = lav_write_audio(output,abuff,n/audio_bps); if(n<0) { mjpeg_error("Error writing audio: %s",lav_strerror()); lav_close(output); exit(1); } } } } /* copy remaining audio */ if (param_inputwav != NULL) { do { asize = (int)absize * audio_bps; n = read(wav_fd,abuff,asize); if(n>0) { na_out += n/audio_bps; n = lav_write_audio(output,abuff,n/audio_bps); if(n<0) { mjpeg_error("Error writing audio: %s",lav_strerror()); lav_close(output); exit(1); } } } while(n>0); } if(na_out != audio_samps) mjpeg_warn("audio samples expected: %ld, written: %ld", audio_samps, na_out); if (lav_close (output)) { mjpeg_error("Closing output file: %s",lav_strerror()); exit(1); } for (n=0; n<3; n++) { free(yuv[n]); } y4m_fini_frame_info(&frameinfo); y4m_fini_stream_info(&streaminfo); return 0; } mjpegtools-2.1.0/lavtools/lav_common.h0000644000175000017500000000573310351367066020376 0ustar glowwormglowworm/* lav_common - some general utility functionality used by multiple lavtool utilities. */ /* Copyright (C) 2000, Rainer Johanni, Andrew Stevens */ /* - added scene change detection code 2001, pHilipp Zabel */ /* - broke some code out to lav_common.h and lav_common.c * July 2001, Shawn Sulma . Part of these changes were * to replace the large number of globals with a handful of structs that * get passed in to the relevant functions. Some of this may be * inefficient, subtly broken, or Wrong. Helpful feedback is certainly * welcome. */ /* - removed a lot of subsumed functionality and unnecessary cruft * March 2002, Matthew Marjanovic . */ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "editlist.h" #include "yuv4mpeg.h" #include "mjpeg_logging.h" #define MAX_EDIT_LIST_FILES 256 #define MAX_JPEG_LEN (3*576*768/2) #define BUFFER_ALIGN 16 /** * (SS 2001-July-13) * The split of the globals into three structs is somewhat arbitrary, but * I've tried to do them based on role as used in lav2yuv and (my own) * lav2divx. * - LavParam handles data that is generally per-run dependent * (e.g. from the command line). * - LavBounds contains data about bounds used in processing. It is generally * not dependent on command line alteration. * - LavBuffer contains buffers used to perform various tasks. * **/ typedef struct { int offset; int frames; int mono; char *scenefile; int delta_lum_threshold; /* = 4; */ unsigned int scene_detection_decimation; /* = 2; */ int output_width; int output_height; int interlace; y4m_ratio_t sar; /* sample aspect ratio (default 0:0 == unspecified) */ y4m_ratio_t dar; /* 'suggested' display aspect ratio */ int chroma; int chroma_width; int chroma_height; int luma_size; int chroma_size; } LavParam; int luminance_mean(uint8_t *frame[], int w, int h); int readframe(int numframe, uint8_t *frame[], LavParam *param, EditList el); void writeoutYUV4MPEGheader(int out_fd, LavParam *param, EditList el, y4m_stream_info_t *streaminfo); void init(LavParam *param, uint8_t *frame[]); #ifdef HAVE_LIBDV #include void frame_YUV422_to_planar(uint8_t **output, uint8_t *input, int width, int height, int chroma); void lav_init_dv_decoder(void); #endif mjpegtools-2.1.0/lavtools/glav.c0000644000175000017500000001403510177120356017156 0ustar glowwormglowworm#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "glav.h" static GtkWidget* glav_create_button(GtkWidget * parent, const gchar * label, const gchar * tipstring, GtkSignalFunc callback, gpointer val) { GtkWidget * obj; GtkTooltips * tooltip; obj = gtk_button_new_with_label(label); gtk_box_pack_start(GTK_BOX(parent),obj, TRUE, TRUE, 0); g_signal_connect(G_OBJECT(obj),"clicked",callback,val); tooltip = gtk_tooltips_new(); gtk_tooltips_set_tip(tooltip, obj, tipstring, NULL); gtk_widget_show(obj); return obj; } static GtkWidget* glav_create_label(GtkWidget * parent, const gchar * label) { GtkWidget * obj; obj = gtk_label_new(label); gtk_box_pack_start(GTK_BOX(parent),obj, TRUE, TRUE, 0); gtk_widget_show(obj); return obj; } GTK_xlav *create_form_xlav(void) { GtkWidget *temphbox, *tempbighbox; GtkWidget *vbox; GtkWidget *obj; GTK_xlav *gui = (GTK_xlav *) malloc(sizeof(*gui)); gui->xlav = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect (G_OBJECT (gui->xlav), "key_press_event", GTK_SIGNAL_FUNC (key_press_cb), (gpointer)0); vbox = gtk_vbox_new(TRUE,4); /* first row */ temphbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), temphbox, TRUE, TRUE, 0); gui->timeslider=gtk_adjustment_new (0.0, 0.0, 100.0, 0.01, 2.0, .10); gui->timehscale=gtk_hscale_new (GTK_ADJUSTMENT (gui->timeslider)); gtk_scale_set_draw_value(GTK_SCALE(gui->timehscale),FALSE); gtk_range_set_update_policy(GTK_RANGE(gui->timehscale),GTK_UPDATE_CONTINUOUS); gtk_box_pack_start(GTK_BOX(temphbox), gui->timehscale, TRUE, TRUE, 0); gtk_widget_show(gui->timehscale); gtk_signal_connect (GTK_OBJECT (gui->timeslider), "value_changed", GTK_SIGNAL_FUNC (timeslider_cb), (gpointer)0); gtk_widget_show(temphbox); /* second row */ tempbighbox=gtk_hbox_new(FALSE,0); gtk_box_pack_start(GTK_BOX(vbox), tempbighbox, TRUE, TRUE, 0); temphbox = gtk_hbox_new(TRUE, 0); gtk_box_pack_start(GTK_BOX(tempbighbox), temphbox, TRUE, TRUE, 0); /* gtk_box_pack_start(GTK_BOX(vbox), temphbox, TRUE, TRUE, 0); */ gui->ss = obj = glav_create_button(temphbox,"|<","Skip to Start",GTK_SIGNAL_FUNC(button_cb),(gpointer)1); gui->fr = obj = glav_create_button(temphbox,"<<","Fast Reverse",GTK_SIGNAL_FUNC(rb_cb),(gpointer)1); gui->rew = obj = glav_create_button(temphbox,"<","Play Reverse",GTK_SIGNAL_FUNC(rb_cb),(gpointer)2); gui->stop = obj = glav_create_button(temphbox,"||","Pause",GTK_SIGNAL_FUNC(rb_cb),(gpointer)3); gui->play = obj = glav_create_button(temphbox,">","Play Forward",GTK_SIGNAL_FUNC(rb_cb),(gpointer)4); gui->ff = obj = glav_create_button(temphbox,">>","Fast Forward",GTK_SIGNAL_FUNC(rb_cb),(gpointer)5); gui->se = obj = glav_create_button(temphbox,">|","Skip to End",GTK_SIGNAL_FUNC(button_cb),(gpointer)2); gui->stepr = obj = glav_create_button(temphbox,"<|","Frame Reverse",GTK_SIGNAL_FUNC(rb_cb),(gpointer)0); /* unmap the click, map press and release */ g_signal_connect(G_OBJECT(obj),"pressed",G_CALLBACK(frame_skip_pressed),(gpointer)3); g_signal_connect(G_OBJECT(obj),"released",G_CALLBACK(frame_skip_released),(gpointer)3); gui->stepf = obj = glav_create_button(temphbox,"|>","Frame Forward",GTK_SIGNAL_FUNC(button_cb),(gpointer)0); /* unmap the click, map press and release */ g_signal_connect(G_OBJECT(obj),"pressed",G_CALLBACK(frame_skip_pressed),(gpointer)4); g_signal_connect(G_OBJECT(obj),"released",G_CALLBACK(frame_skip_released),(gpointer)4); /* gtk_widget_show(temphbox); temphbox = gtk_hbox_new(TRUE, 0); gtk_box_pack_start(GTK_BOX(tempbighbox), temphbox, TRUE, TRUE, 0); */ gui->StatDisp = obj = glav_create_label(tempbighbox,"Play"); gui->Timer = obj = glav_create_label(tempbighbox,"0:00:00:00"); /* temphbox = gtk_hbox_new(TRUE, 0); */ /* gtk_box_pack_start(GTK_BOX(tempbighbox), temphbox, TRUE, TRUE, 0); */ /* gui->Exit = obj = glav_create_button(temphbox,"Exit","Exit Glav",GTK_SIGNAL_FUNC(Exit_cb),(gpointer)1); */ gui->Exit = obj = glav_create_button(tempbighbox,"Exit","Exit Glav",GTK_SIGNAL_FUNC(Exit_cb),(gpointer)1); /* third row */ gtk_widget_show(temphbox); gtk_widget_show(tempbighbox); temphbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), temphbox, TRUE, TRUE, 0); gui->TSelStart = obj = glav_create_label(temphbox,"Select.\nStart:"); gui->FSelStart = obj = glav_create_label(temphbox,"-:--:--:--"); gui->TSelEnd = obj = glav_create_label(temphbox,"Select.\nEnd:"); gui->FSelEnd = obj = glav_create_label(temphbox,"-:--:--:--"); gtk_widget_set_size_request(GTK_WIDGET(gui->FSelStart), 100, -1); gtk_widget_set_size_request(GTK_WIDGET(gui->FSelEnd), 100, -1); gui->BSSelStart = obj = glav_create_button(temphbox,"|<-","Select Start",GTK_SIGNAL_FUNC(selection_cb),(gpointer)1); gui->BSSelEnd = obj = glav_create_button(temphbox,"->|","Select End",GTK_SIGNAL_FUNC(selection_cb),(gpointer)2); gui->BGotoSelStart = obj = glav_create_button(temphbox,"|<","Skip to Selected Start",GTK_SIGNAL_FUNC(selection_cb),(gpointer)11); gui->BGotoSelEnd = obj = glav_create_button(temphbox,">|","Skip to Selected End",GTK_SIGNAL_FUNC(selection_cb),(gpointer)12); gui->BClearSel = obj = glav_create_button(temphbox,"X","Clear Selection",GTK_SIGNAL_FUNC(selection_cb),(gpointer)3); gui->BECut = obj = glav_create_button(temphbox,"Cut","Cut Selected",GTK_SIGNAL_FUNC(selection_cb),(gpointer)4); gui->BECopy = obj = glav_create_button(temphbox,"Copy","Copy Selected",GTK_SIGNAL_FUNC(selection_cb),(gpointer)5); gui->BEPaste = obj = glav_create_button(temphbox,"Paste","Paste Selected",GTK_SIGNAL_FUNC(selection_cb),(gpointer)6); gui->BSaveAll = obj = glav_create_button(temphbox,"Save all ...","Save All",GTK_SIGNAL_FUNC(selection_cb),(gpointer)7); gui->BSaveSel = obj = glav_create_button(temphbox,"Save ...","Save Selected",GTK_SIGNAL_FUNC(selection_cb),(gpointer)8); /* end */ gtk_widget_show(temphbox); gtk_container_add(GTK_CONTAINER(gui->xlav),vbox); gtk_widget_show(vbox); return gui; } /*---------------------------------------*/ mjpegtools-2.1.0/lavtools/Makefile.am0000644000175000017500000001237512217305407020121 0ustar glowwormglowworm# Makefile for lavtools MAINTAINERCLEANFILES = Makefile.in AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/utils $(LIBQUICKTIME_CFLAGS) LIBMJPEGUTILS = $(top_builddir)/utils/libmjpegutils.la if HAVE_ALTIVEC LIBMJPEGUTILS += $(top_builddir)/mpeg2enc/libmpeg2encpp.la endif # ********************************************************************* # Support lib lib_LTLIBRARIES = liblavfile.la liblavjpeg.la if HAVE_V4L lib_LTLIBRARIES += liblavrec.la endif if HAVE_V4L_OR_SDL lib_LTLIBRARIES += liblavplay.la endif liblavincludedir = $(pkgincludedir) liblavinclude_HEADERS = \ avilib.h \ editlist.h \ lav_io.h \ jpegutils.h \ frequencies.h \ liblavrec.h \ liblavplay.h \ audiolib.h LAV_ALL_LIB_OPTS = \ $(LT_STATIC) \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -release $(LT_RELEASE) $(EXTRA_LDFLAGS) liblavfile_la_SOURCES = editlist.c lav_io.c avilib.c liblavfile_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBDV_CFLAGS) $(JPEG_CFLAGS) liblavfile_la_LDFLAGS = $(LAV_ALL_LIB_OPTS) liblavfile_la_LIBADD = $(LIBQUICKTIME_LIBS) $(JPEG_LIBS) $(LIBDV_LIBS) $(LIBMJPEGUTILS) liblavjpeg_la_SOURCES = jpegutils.c liblavjpeg_la_CPPFLAGS = $(AM_CPPFLAGS) $(JPEG_CFLAGS) liblavjpeg_la_LDFLAGS = $(LAV_ALL_LIB_OPTS) liblavjpeg_la_LIBADD = $(JPEG_LIBS) $(LIBMJPEGUTILS) liblavrec_la_SOURCES = liblavrec.c audiolib.c frequencies.c liblavrec_la_CPPFLAGS = $(AM_CPPFLAGS) # so automake doesn't complain about audiolib & frequencies liblavrec_la_LDFLAGS = $(LAV_ALL_LIB_OPTS) liblavrec_la_LIBADD = liblavfile.la liblavjpeg.la $(LIBMJPEGUTILS) liblavrec_la_DEPENDENCIES = liblavfile.la liblavjpeg.la liblavplay_la_SOURCES = liblavplay.c audiolib.c liblavplay_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBDV_CFLAGS) $(X_CFLAGS) $(SDL_CFLAGS) liblavplay_la_LDFLAGS = $(LAV_ALL_LIB_OPTS) liblavplay_la_LIBADD = liblavfile.la $(SDL_LIBS) liblavjpeg.la $(LIBDV_LIBS) $(LIBMJPEGUTILS) if HAVE_SDL liblavplay_la_LIBADD += ${X_LIBS} -lX11 endif liblavplay_la_DEPENDENCIES = liblavfile.la liblavjpeg.la # ********************************************************************* # The tools themselves bin_PROGRAMS = \ mjpeg_simd_helper \ lav2wav \ lav2yuv \ lavaddwav \ lavtrans \ ypipe \ yuv2lav \ transist.flt \ matteblend.flt \ multiblend.flt \ lavpipe \ jpeg2yuv \ ppmtoy4m \ pnmtoy4m \ y4mtoppm \ y4mtopnm \ y4mcolorbars \ lavinfo \ y4mstabilizer \ yuvfps \ yuvinactive if HAVE_GTK bin_PROGRAMS += glav endif if HAVE_SDL bin_PROGRAMS += yuvplay endif if HAVE_V4L bin_PROGRAMS += lavrec lavvideo endif if HAVE_V4L_OR_SDL bin_PROGRAMS += lavplay endif if HAVE_LIBPNG bin_PROGRAMS += png2yuv endif noinst_HEADERS = \ colorspace.h \ glav.h \ pipelist.h \ subsample.h \ lav_common.h mjpeg_simd_helper_SOURCES = mjpeg_simd_helper.c mjpeg_simd_helper_LDADD = $(LIBMJPEGUTILS) ypipe_SOURCES = ypipe.c ypipe_LDADD = $(LIBMJPEGUTILS) yuv2lav_SOURCES = yuv2lav.c yuv2lav_LDADD = $(LIBMJPEGUTILS) liblavfile.la liblavjpeg.la $(LIBM_LIBS) transist_flt_SOURCES = transist.flt.c transist_flt_LDADD = $(LIBMJPEGUTILS) matteblend_flt_SOURCES = matteblend.flt.c matteblend_flt_LDADD = $(LIBMJPEGUTILS) multiblend_flt_SOURCES = multiblend.flt.c multiblend_flt_LDADD = $(LIBMJPEGUTILS) lavplay_SOURCES = lavplay.c lavplay_CPPFLAGS = $(AM_CPPFLAGS) $(SDL_CFLAGS) lavplay_LDADD = $(LIBMJPEGUTILS) \ liblavplay.la liblavjpeg.la liblavfile.la \ @LIBGETOPT_LIB@ @PTHREAD_LIBS@ $(SDL_LIBS) lavrec_SOURCES = lavrec.c lavrec_LDADD = $(LIBMJPEGUTILS) \ liblavrec.la liblavfile.la liblavjpeg.la \ @LIBGETOPT_LIB@ @PTHREAD_LIBS@ lav2yuv_SOURCES = lav2yuv.c lav_common.c lav2yuv_CPPFLAGS = $(AM_CPPFLAGS) $(LIBDV_CFLAGS) lav2yuv_LDADD = $(LIBMJPEGUTILS) \ liblavfile.la liblavjpeg.la jpeg2yuv_SOURCES = jpeg2yuv.c jpeg2yuv_CPPFLAGS = $(AM_CPPFLAGS) $(JPEG_CFLAGS) jpeg2yuv_LDADD = $(LIBMJPEGUTILS) liblavjpeg.la $(JPEG_LIBS) png2yuv_SOURCES = png2yuv.c colorspace.c subsample.c png2yuv_CPPFLAGS = $(AM_CPPFLAGS) $(LIBPNG_CFLAGS) png2yuv_LDADD = $(LIBMJPEGUTILS) $(LIBPNG_LIBS) -lz -lm lavpipe_SOURCES = lavpipe.c pipelist.c lavpipe_LDADD = $(LIBMJPEGUTILS) lav2wav_SOURCES = lav2wav.c lav2wav_LDADD = $(LIBMJPEGUTILS) liblavfile.la lavtrans_SOURCES = lavtrans.c lavtrans_LDADD = $(LIBMJPEGUTILS) liblavfile.la lavaddwav_SOURCES = lavaddwav.c lavaddwav_LDADD = $(LIBMJPEGUTILS) liblavfile.la glav_SOURCES = glav.c glav_main.c glav_CPPFLAGS = $(AM_CPPFLAGS) ${GTK_CFLAGS} -DG_LOG_DOMAIN=\"lavtools\" glav_LDADD = $(LIBMJPEGUTILS) ${GTK_LIBS} lavvideo_SOURCES = lavvideo.c frequencies.c yuvplay_SOURCES = yuvplay.c yuvplay_CPPFLAGS = $(AM_CPPFLAGS) $(SDL_CFLAGS) yuvplay_LDADD = $(SDL_LIBS) $(LIBMJPEGUTILS) ppmtoy4m_SOURCES = ppmtoy4m.c colorspace.c subsample.c ppmtoy4m_LDADD = $(LIBMJPEGUTILS) pnmtoy4m_SOURCES = pnmtoy4m.c colorspace.c pnmtoy4m_LDADD = $(LIBMJPEGUTILS) y4mtoppm_SOURCES = y4mtoppm.c colorspace.c subsample.c y4mtoppm_LDADD = $(LIBMJPEGUTILS) y4mtopnm_SOURCES = y4mtopnm.c colorspace.c y4mtopnm_LDADD = $(LIBMJPEGUTILS) y4mcolorbars_SOURCES = y4mcolorbars.c colorspace.c subsample.c y4mcolorbars_LDADD = $(LIBMJPEGUTILS) lavinfo_SOURCES = lavinfo.c lavinfo_LDADD = $(LIBMJPEGUTILS) liblavfile.la y4mstabilizer_SOURCES = y4mstabilizer.c subsample.c y4mstabilizer_LDADD = $(LIBMJPEGUTILS) yuvfps_SOURCES = yuvfps.c yuvfps_LDADD = $(LIBMJPEGUTILS) yuvinactive_SOURCES = yuvinactive.c yuvinactive_LDADD = $(LIBMJPEGUTILS) mjpegtools-2.1.0/lavtools/liblavrec.h0000644000175000017500000001474310115235042020172 0ustar glowwormglowworm/* * liblavrec - a librarified Linux Audio Video RECord * * Copyright (C) 2000 Rainer Johanni * Extended by: Gernot Ziegler * & Wolfgang Scherr * & Ronald Bultje * & many others * * A library for recording MJPEG video from hardware MJPEG * video devices such as the Pinnacle/Miro DC10(+), Iomega * Buz, the Linux Media Labs LML33, the Matrox Marvel G200, * Matrox Marvel G400 and the Rainbow Runner G-series. * Can also be used for video-capture from BTTV-devices * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #define AUDIO_BUFFER_SIZE 8192 enum { LAVREC_MSG_ERROR = 0, LAVREC_MSG_WARNING = 1, LAVREC_MSG_INFO = 2, LAVREC_MSG_DEBUG = 3 }; enum { LAVREC_STATE_STOP = 0, LAVREC_STATE_PAUSED = 1, LAVREC_STATE_RECORDING = 2 }; typedef struct { int stats_changed; /* has anything bad happened? */ unsigned int num_frames; /* Number of video frames captured until now */ unsigned int num_syncs; /* Number of MJPIOC_SYNC ioctls */ unsigned int num_lost; /* Number of frames lost */ unsigned int num_asamps; /* Number of frames written to file */ unsigned int num_ins; /* Number of frames inserted for sync */ unsigned int num_del; /* Number of frames deleted for sync */ unsigned int num_aerr; /* Number of audio buffers in error */ int current_output_file; /* the number of the current file */ char output_filename[1024]; /* name of current recording file */ double tdiff1; /* Time difference (sync debug purposes only) */ double tdiff2; /* Time difference (sync debug purposes only) */ struct timeval prev_sync; struct timeval cur_sync; } video_capture_stats; typedef struct { int x; /* x-positions */ int y; /* y-position */ unsigned int w; /* width */ unsigned int h; /* height */ } rect; typedef struct { char video_format; /* [aAqm] a/A = AVI, j = JPEG, q = Quicktime */ int video_norm; /* [0-3] 0 = PAL, 1 = NTSC, 2 = SECAM, 3 = auto */ int video_src; /* [0-3] 0 = Composite, 1 = S-video, 2 = TV-tuner, 3 = auto */ int software_encoding; /* [0-1] 0 = hardware MJPEG encoding (zoran), 1 = software MJPEG encoding */ unsigned int num_encoders; /* Number of software JPEG compressor threads */ int record_time; /* time to record (in seconds). Default: -1 (unlimited) */ int horizontal_decimation; /* [1,2,4] horizontal decimation */ int vertical_decimation; /* [1,2,4] vertical decimation */ rect *geometry; /* X geometry string: what to capture */ int quality; /* [0-100] video capture quality */ int tuner_frequency; /* when using a TV-tuner, the tuner frequency can be set */ const char *video_dev; /* /dev-entry for the video device */ int audio_size; /* [0,8,16] audio sample size, 0 means no audio */ int audio_rate; /* Audio rate supported by the soundcard (e.g. 11025, 22050, 44100) */ int stereo; /* [0,1] 0 = mono, 1 = stereo */ int audio_level; /* [-1,0-100] audio volume (0-100) or -1 to use mixer defaults */ int mute; /* [0,1] 0 = don't mute, 1 = mute (e.g. for a microphone) */ char audio_src; /* [lmc] l = Line-in, m = Microphone, c = CD-ROM */ int use_read; /* whether to use 'read' (1) or mmap (0) for audio capture */ const char *audio_dev; /* /dev-entry for the audio device */ const char *mixer_dev; /* /dev-entry for the mixer device */ int single_frame; /* [0,1] lavrec_main() captures one frame and returns */ int time_lapse; /* [>=1] one out of each 'n' frames is captured (>=1) */ int sync_correction; /* [0-2] 0 = none, 1 = replicate frames, 2 = 1 + sync correction */ int MJPG_numbufs; /* Number of MJPEG-buffers */ int MJPG_bufsize; /* buffer size (in kB) per MJPEG-buffer */ char **files; /* the files where to capture the video to */ int num_files; /* number of files in the files[]-array */ int max_file_size_mb; int max_file_frames; /* maximum number of frames per file */ int flush_count; /* How often (in frames) to flush data to disk */ void (*output_statistics)(video_capture_stats *stats); /* speaks for itself */ void (*audio_captured)(uint8_t *audio, long sampes); /* callback when audio has been grabbed */ void (*video_captured)(uint8_t *video, long size, long count); /* callback when a frame has been grabbed */ void (*msg_callback)(int type, char* message); /* callback for error/info/warn messages */ void (*state_changed)(int new_state); /* changed state */ void *settings; /* private info - don't touch :-) (type video_capture_setup) */ } lavrec_t; /* malloc the pointer and set default options */ lavrec_t *lavrec_malloc(void); /* the whole video-capture cycle */ int lavrec_main(lavrec_t *info); /* start recording (only call when ready!) */ int lavrec_start(lavrec_t *info); /* pause recording (you can call play to continue) */ int lavrec_pause(lavrec_t *info); /* stop recording (which also deinitializes everything) */ int lavrec_stop(lavrec_t *info); /* free info and quit if necessary */ int lavrec_free(lavrec_t *info); /* wait until capturing is finished */ void lavrec_busy(lavrec_t *info); mjpegtools-2.1.0/lavtools/subsample.c0000644000175000017500000002520010044075466020220 0ustar glowwormglowworm/* * subsample.c: Routines to do chroma subsampling. ("Work In Progress") * * * Copyright (C) 2001 Matthew J. Marjanovic * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include #include #include #include "subsample.h" /************************************************************************* * Chroma Subsampling *************************************************************************/ /* vertical/horizontal interstitial siting * * Y Y Y Y * C C * Y Y Y Y * * Y Y Y Y * C C * Y Y Y Y * */ static void ss_444_to_420jpeg(uint8_t *buffer, int width, int height) { uint8_t *in0, *in1, *out; int x, y; in0 = buffer; in1 = buffer + width; out = buffer; for (y = 0; y < height; y += 2) { for (x = 0; x < width; x += 2) { *out = (in0[0] + in0[1] + in1[0] + in1[1]) >> 2; in0 += 2; in1 += 2; out++; } in0 += width; in1 += width; } } /* vertical/horizontal interstitial siting * * Y Y Y Y * C C C inm * Y Y Y Y * * Y Y Y - Y out0 * C | C | C in0 * Y Y Y - Y out1 * * * C C C inp * * * Each iteration through the loop reconstitutes one 2x2 block of * pixels from the "surrounding" 3x3 block of samples... * Boundary conditions are handled by cheap reflection; i.e. the * center sample is simply reused. * */ #define BLANK_CRB in0[1] #if 1 /* triangle/linear filter (otherwise, use the lame box filter) */ static void ss_420jpeg_to_444(uint8_t *buffer, int width, int height) { uint8_t *inm, *in0, *inp, *out0, *out1; uint8_t cmm, cm0, cmp, c0m, c00, c0p, cpm, cp0, cpp; int x, y; static uint8_t *saveme = NULL; static int saveme_size = 0; if (width > saveme_size) { free(saveme); saveme_size = width; saveme = malloc(saveme_size * sizeof(saveme[0])); assert(saveme != NULL); } memcpy(saveme, buffer, width); in0 = buffer + (width * height / 4) - 2; inm = in0 - width/2; inp = in0 + width/2; out1 = buffer + (width * height) - 1; out0 = out1 - width; for (y = height; y > 0; y -= 2) { if (y == 2) { in0 = saveme + width/2 - 2; inp = in0 + width/2; } for (x = width; x > 0; x -= 2) { #if 0 if ((x == 2) && (y == 2)) { cmm = in0[1]; cm0 = in0[1]; cmp = in0[2]; c0m = in0[1]; c0p = in0[2]; cpm = inp[1]; cp0 = inp[1]; cpp = inp[2]; } else if ((x == 2) && (y == height)) { cmm = inm[1]; cm0 = inm[1]; cmp = inm[2]; c0m = in0[1]; c0p = in0[2]; cpm = in0[1]; cp0 = in0[1]; cpp = in0[2]; } else if ((x == width) && (y == height)) { cmm = inm[0]; cm0 = inm[1]; cmp = inm[1]; c0m = in0[0]; c0p = in0[1]; cpm = in0[0]; cp0 = in0[1]; cpp = in0[1]; } else if ((x == width) && (y == 2)) { cmm = in0[0]; cm0 = (y == 2) ? BLANK_CRB : inm[1]; cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2]; c0m = (x == 2) ? BLANK_CRB : in0[0]; c0p = (x == width) ? BLANK_CRB : in0[2]; cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0]; cp0 = (y == height) ? BLANK_CRB : inp[1]; cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2]; } else if (x == 2) { cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0]; cm0 = (y == 2) ? BLANK_CRB : inm[1]; cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2]; c0m = (x == 2) ? BLANK_CRB : in0[0]; c0p = (x == width) ? BLANK_CRB : in0[2]; cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0]; cp0 = (y == height) ? BLANK_CRB : inp[1]; cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2]; } else if (y == 2) { cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0]; cm0 = (y == 2) ? BLANK_CRB : inm[1]; cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2]; c0m = (x == 2) ? BLANK_CRB : in0[0]; c0p = (x == width) ? BLANK_CRB : in0[2]; cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0]; cp0 = (y == height) ? BLANK_CRB : inp[1]; cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2]; } else if (x == width) { cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0]; cm0 = (y == 2) ? BLANK_CRB : inm[1]; cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2]; c0m = (x == 2) ? BLANK_CRB : in0[0]; c0p = (x == width) ? BLANK_CRB : in0[2]; cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0]; cp0 = (y == height) ? BLANK_CRB : inp[1]; cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2]; } else if (y == height) { cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0]; cm0 = (y == 2) ? BLANK_CRB : inm[1]; cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2]; c0m = (x == 2) ? BLANK_CRB : in0[0]; c0p = (x == width) ? BLANK_CRB : in0[2]; cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0]; cp0 = (y == height) ? BLANK_CRB : inp[1]; cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2]; } else { cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0]; cm0 = (y == 2) ? BLANK_CRB : inm[1]; cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2]; c0m = (x == 2) ? BLANK_CRB : in0[0]; c0p = (x == width) ? BLANK_CRB : in0[2]; cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0]; cp0 = (y == height) ? BLANK_CRB : inp[1]; cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2]; } c00 = in0[1]; cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0]; cm0 = (y == 2) ? BLANK_CRB : inm[1]; cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2]; c0m = (x == 2) ? BLANK_CRB : in0[0]; c0p = (x == width) ? BLANK_CRB : in0[2]; cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0]; cp0 = (y == height) ? BLANK_CRB : inp[1]; cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2]; #else cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0]; cm0 = (y == 2) ? BLANK_CRB : inm[1]; cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2]; c0m = (x == 2) ? BLANK_CRB : in0[0]; c00 = in0[1]; c0p = (x == width) ? BLANK_CRB : in0[2]; cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0]; cp0 = (y == height) ? BLANK_CRB : inp[1]; cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2]; #endif inm--; in0--; inp--; *(out1--) = (1*cpp + 3*(cp0+c0p) + 9*c00 + 8) >> 4; *(out1--) = (1*cpm + 3*(cp0+c0m) + 9*c00 + 8) >> 4; *(out0--) = (1*cmp + 3*(cm0+c0p) + 9*c00 + 8) >> 4; *(out0--) = (1*cmm + 3*(cm0+c0m) + 9*c00 + 8) >> 4; } out1 -= width; out0 -= width; } } #else static void ss_420jpeg_to_444(uint8_t *buffer, int width, int height) { uint8_t *in, *out0, *out1; int x, y; in = buffer + (width * height / 4) - 1; out1 = buffer + (width * height) - 1; out0 = out1 - width; for (y = height - 1; y >= 0; y -= 2) { for (x = width - 1; x >= 0; x -=2) { uint8_t val = *(in--); *(out1--) = val; *(out1--) = val; *(out0--) = val; *(out0--) = val; } out0 -= width; out1 -= width; } } #endif /* vertical intersitial siting; horizontal cositing * * Y Y Y Y * C C * Y Y Y Y * * Y Y Y Y * C C * Y Y Y Y * * [1,2,1] kernel for horizontal subsampling: * * inX[0] [1] [2] * | | | * C C C C * \ | / * \ | / * C */ static void ss_444_to_420mpeg2(uint8_t *buffer, int width, int height) { uint8_t *in0, *in1, *out; int x, y; in0 = buffer; /* points to */ in1 = buffer + width; /* second of pair of lines */ out = buffer; for (y = 0; y < height; y += 2) { /* first column boundary condition -- just repeat it to right */ *out = (in0[0] + (2 * in0[0]) + in0[1] + in1[0] + (2 * in1[0]) + in1[1]) >> 3; out++; in0++; in1++; /* rest of columns just loop */ for (x = 2; x < width; x += 2) { *out = (in0[0] + (2 * in0[1]) + in0[2] + in1[0] + (2 * in1[1]) + in1[2]) >> 3; in0 += 2; in1 += 2; out++; } in0 += width + 1; in1 += width + 1; } } int chroma_sub_implemented(int mode) { switch (mode) { case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_444: return 1; /* yes, supported */ case Y4M_CHROMA_420PALDV: case Y4M_CHROMA_422: case Y4M_CHROMA_411: case Y4M_CHROMA_444ALPHA: case Y4M_CHROMA_MONO: default: return 0; /* no, unsupported */ } } void chroma_subsample(int mode, uint8_t *ycbcr[], int width, int height) { switch (mode) { case Y4M_CHROMA_444: case Y4M_CHROMA_444ALPHA: case Y4M_CHROMA_MONO: break; case Y4M_CHROMA_420JPEG: ss_444_to_420jpeg(ycbcr[1], width, height); ss_444_to_420jpeg(ycbcr[2], width, height); break; case Y4M_CHROMA_420MPEG2: ss_444_to_420mpeg2(ycbcr[1], width, height); ss_444_to_420mpeg2(ycbcr[2], width, height); break; default: break; } } int chroma_super_implemented(int mode) { switch (mode) { case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_444: return 1; /* yes, supported */ case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: case Y4M_CHROMA_422: case Y4M_CHROMA_411: case Y4M_CHROMA_444ALPHA: case Y4M_CHROMA_MONO: default: return 0; /* no, unsupported */ } } void chroma_supersample(int mode, uint8_t *ycbcr[], int width, int height) { switch (mode) { case Y4M_CHROMA_444: case Y4M_CHROMA_444ALPHA: case Y4M_CHROMA_MONO: break; case Y4M_CHROMA_420JPEG: ss_420jpeg_to_444(ycbcr[1], width, height); ss_420jpeg_to_444(ycbcr[2], width, height); break; case Y4M_CHROMA_420MPEG2: // ss_420mpeg2_to_444(ycbcr[1], width, height); // ss_420mpeg2_to_444(ycbcr[2], width, height); // exit(4); // break; default: break; } } mjpegtools-2.1.0/lavtools/jpeg2yuv.c0000644000175000017500000004453010740045300017772 0ustar glowwormglowworm/* jpeg2yuv ======== Converts a collection of JPEG images to a YUV4MPEG stream. (see jpeg2yuv -h for help (or have a look at the function "usage")) Copyright (C) 1999 Gernot Ziegler (gz@lysator.liu.se) Copyright (C) 2001 Matthew Marjanovic (maddog@mir.com) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config.h" #include #include #include #include #include #include #include "jpegutils.h" #include "lav_io.h" #include #include "mjpeg_logging.h" #include "mjpeg_types.h" #include "yuv4mpeg.h" #include "mpegconsts.h" #define MAXPIXELS (1280*1024) /* Maximum size of final image */ /* strip string */ void strip(char *p) { while (1) { if ((*p == '\r') || (*p == '\n')) *p = '\0'; if (*p == '\0') break; p++; } } typedef struct _parameters { char *jpegformatstr; uint32_t begin; /* the video frame start */ int32_t numframes; /* -1 means: take all frames */ y4m_ratio_t framerate; y4m_ratio_t aspect_ratio; int interlace; /* will the YUV4MPEG stream be interlaced? */ int interleave; /* are the JPEG frames field-interleaved? */ int verbose; /* the verbosity of the program (see mjpeg_logging.h) */ int width; int height; int colorspace; int loop; int rescale_YUV; } parameters_t; static struct jpeg_decompress_struct dinfo; static struct jpeg_error_mgr jerr; /* * The User Interface parts */ /* usage * Prints a short description of the program, including default values * in: prog: The name of the program */ static void usage(char *prog) { char *h; if (NULL != (h = (char *)strrchr(prog,'/'))) prog = h+1; fprintf(stderr, "usage: %s [ options ]\n" "\n" "where options are ([] shows the defaults):\n" " -l num loop -1=forever, n >= 1 n-times \n" " -v num verbosity (0,1,2) [1]\n" " -b framenum starting frame number [0]\n" " -f framerate framerate for output stream (fps) \n" " -A sar output sample aspect ratio [1:1]\n" " -n numframes number of frames to process [-1 = all]\n" " -j {1}%%{2}d{3} Read JPEG frames with the name components as follows:\n" " {1} JPEG filename prefix (e g rendered_ )\n" " {2} Counting placeholder (like in C, printf, eg 06 ))\n" " -I x interlacing mode: p = none/progressive\n" " t = top-field-first\n" " b = bottom-field-first\n" " -L x interleaving mode: 0 = non-interleaved (two successive\n" " fields per JPEG file)\n" " 1 = interleaved fields\n" " -R 1/0 ... 1: rescale YUV color values from 0-255 to 16-235 (default: 1)\n" "\n" "%s pipes a sequence of JPEG files to stdout,\n" "making the direct encoding of MPEG files possible under mpeg2enc.\n" "Any JPEG format supported by libjpeg can be read.\n" "stdout will be filled with the YUV4MPEG movie data stream,\n" "so be prepared to pipe it on to mpeg2enc or to write it into a file.\n" "\n" "If -j option is omited, filenames are read from stdin.\n" "\n" "examples:\n" " ls *jpg | %s -f 25 -I p > result.yuv\n" " | convert all jpg files in curent directory \n" " %s -j in_%%06d.jpeg -b 100000 > result.yuv\n" " | combines all the available JPEGs that match \n" " in_??????.jpeg, starting with 100000 (in_100000.jpeg, \n" " in_100001.jpeg, etc...) into the uncompressed YUV4MPEG videofile result.yuv\n" " %s -It -L0 -j abc_%%04d.jpeg | mpeg2enc -f3 -o out.m2v\n" " | combines all the available JPEGs that match \n" " abc_??????.jpeg, starting with 0000 (abc_0000.jpeg, \n" " abc_0001.jpeg, etc...) and pipes it to mpeg2enc which encodes\n" " an MPEG2-file called out.m2v out of it\n" "\n", prog, prog, prog, prog, prog); } /* parse_commandline * Parses the commandline for the supplied parameters. * in: argc, argv: the classic commandline parameters */ static void parse_commandline(int argc, char ** argv, parameters_t *param) { int c, sts; param->jpegformatstr = NULL; param->begin = 0; param->numframes = -1; param->framerate = y4m_fps_UNKNOWN; param->interlace = Y4M_UNKNOWN; param->aspect_ratio = y4m_sar_SQUARE; param->interleave = -1; param->verbose = 1; param->loop = 1; param->rescale_YUV = 1; /* parse options */ for (;;) { if (-1 == (c = getopt(argc, argv, "I:hv:L:b:j:n:f:l:R:A:"))) break; switch (c) { case 'A': sts = y4m_parse_ratio(¶m->aspect_ratio, optarg); if (sts != Y4M_OK) mjpeg_error_exit1("Invalid aspect ratio: %s", optarg); break; case 'j': param->jpegformatstr = strdup(optarg); break; case 'b': param->begin = atol(optarg); break; case 'n': param->numframes = atol(optarg); break; case 'R': param->rescale_YUV = atoi(optarg); break; case 'f': param->framerate = mpeg_conform_framerate(atof(optarg)); break; case 'I': switch (optarg[0]) { case 'p': param->interlace = Y4M_ILACE_NONE; break; case 't': param->interlace = Y4M_ILACE_TOP_FIRST; break; case 'b': param->interlace = Y4M_ILACE_BOTTOM_FIRST; break; default: mjpeg_error_exit1 ("-I option requires arg p, t, or b"); } break; case 'L': param->interleave = atoi(optarg); if ((param->interleave != 0) && (param->interleave != 1)) mjpeg_error_exit1 ("-L option requires arg 0 or 1"); break; case 'v': param->verbose = atoi(optarg); if (param->verbose < 0 || param->verbose > 2) mjpeg_error_exit1( "-v option requires arg 0, 1, or 2"); break; case 'l': param->loop = atoi(optarg); if (param->loop == 0 || param->loop < -1 ) mjpeg_error_exit1( "-l option requires a number greater than 0 or -1 to loop forever "); break; case 'h': default: mjpeg_info("Wp x, char %c\n", c); usage(argv[0]); exit(1); } } if (param->jpegformatstr == NULL) mjpeg_info("Reading jpeg filenames from stdin."); if (Y4M_RATIO_EQL(param->framerate, y4m_fps_UNKNOWN)) { mjpeg_error("%s: framerate not specified. (Use -f option)", argv[0]); usage(argv[0]); exit(1); } } /* * The file handling parts */ /** init_parse_files * Verifies the JPEG input files and prepares YUV4MPEG header information. * remember first filename for later * @returns 0 on success */ static int init_parse_files(parameters_t *param, char *jpegname) { FILE *jpegfile; if (param->jpegformatstr) { snprintf(jpegname, FILENAME_MAX, param->jpegformatstr, param->begin); jpegfile = fopen(jpegname, "rb"); } else { char *p; p = fgets(jpegname, FILENAME_MAX, stdin); if (p) { strip(jpegname); jpegfile = fopen(jpegname, "rb"); } else { jpegfile = NULL; } } mjpeg_debug("Analyzing %s to get the right pic params", jpegname); if (jpegfile == NULL) mjpeg_error_exit1("System error while opening: \"%s\": %s", jpegname, strerror(errno)); /* Now open this JPEG file, and examine its header to retrieve the YUV4MPEG info that shall be written */ dinfo.err = jpeg_std_error(&jerr); /* ?????????? */ jpeg_create_decompress(&dinfo); jpeg_stdio_src(&dinfo, jpegfile); jpeg_read_header(&dinfo, 1); switch (dinfo.jpeg_color_space) { case JCS_YCbCr: mjpeg_info("YUV colorspace detected.\n"); dinfo.out_color_space = JCS_YCbCr; break; case JCS_GRAYSCALE: mjpeg_info("Grayscale colorspace detected.\n"); dinfo.out_color_space = JCS_GRAYSCALE; break; default: mjpeg_error("Unsupported colorspace detected.\n"); break; } mjpeg_info("Starting decompression"); jpeg_start_decompress(&dinfo); if (dinfo.output_components != 3 && dinfo.out_color_space == JCS_YCbCr) mjpeg_error_exit1("Output components of color JPEG image = %d, must be 3.", dinfo.output_components); if (dinfo.output_components != 1 && dinfo.out_color_space == JCS_GRAYSCALE) mjpeg_error_exit1("Output components of grayscale JPEG image = %d, must be 1.", dinfo.output_components); mjpeg_info("Image dimensions are %dx%d", dinfo.image_width, dinfo.image_height); /* picture size check */ if ( (dinfo.image_width % 16) != 0 ) mjpeg_error_exit1("The image width isn't a multiple of 16, rescale the image"); if ( (dinfo.image_height % 16) != 0 ) mjpeg_error_exit1("The image height isn't a multiple of 16, rescale the image"); param->width = dinfo.image_width; param->height = dinfo.image_height; param->colorspace = dinfo.jpeg_color_space; jpeg_destroy_decompress(&dinfo); fclose(jpegfile); mjpeg_info("Movie frame rate is: %f frames/second", Y4M_RATIO_DBL(param->framerate)); switch (param->interlace) { case Y4M_ILACE_NONE: mjpeg_info("Non-interlaced/progressive frames."); break; case Y4M_ILACE_BOTTOM_FIRST: mjpeg_info("Interlaced frames, bottom field first."); break; case Y4M_ILACE_TOP_FIRST: mjpeg_info("Interlaced frames, top field first."); break; default: mjpeg_error_exit1("Interlace has not been specified (use -I option)"); break; } if ((param->interlace != Y4M_ILACE_NONE) && (param->interleave == -1)) mjpeg_error_exit1("Interleave has not been specified (use -L option)"); if (!(param->interleave) && (param->interlace != Y4M_ILACE_NONE)) { param->height *= 2; mjpeg_info("Non-interleaved fields (image height doubled)"); } mjpeg_info("Frame size: %d x %d", param->width, param->height); return 0; } /** Rescales the YUV values from the range 0..255 to the range 16..235 @param yp: buffer for Y plane of decoded JPEG @param up: buffer for U plane of decoded JPEG @param vp: buffer for V plane of decoded JPEG */ static void rescale_color_vals(int width, int height, uint8_t *yp, uint8_t *up, uint8_t *vp) { int x,y; for (y = 0; y < height; y++) for (x = 0; x < width; x++) yp[x+y*width] = (float)(yp[x+y*width]) * ((235.0 - 16.0)/255.0) + 16.0; for (y = 0; y < height/2; y++) for (x = 0; x < width/2; x++) { up[x+y*width/2] = (float)(up[x+y*width/2]) * ((240.0 - 16.0)/255.0) + 16.0; vp[x+y*width/2] = (float)(vp[x+y*width/2]) * ((240.0 - 16.0)/255.0) + 16.0; } } /** Open and read a file if the file name is not the same as the previous file name. @param jpegdata: buffer where the JPEG data will be read into @param jpegname: JPEG file name @param prev_jpegname: previous JPEG file name @returns 0 if the previous read data is still valid. -1 if the file could not be opened. >0 the number of bytes read into jpegdata. */ static ssize_t read_jpeg_data(uint8_t *jpegdata, char *jpegname, char *prev_jpegname) { FILE *jpegfile; ssize_t jpegsize; if (strncmp(jpegname, prev_jpegname, strlen(jpegname)) != 0) { strncpy(prev_jpegname, jpegname, strlen(jpegname)); jpegfile = fopen(jpegname, "rb"); if (jpegfile == NULL) { jpegsize = -1; mjpeg_info("Read from '%s' failed: %s", jpegname, strerror(errno)); } else { jpegsize = fread(jpegdata, sizeof(unsigned char), MAXPIXELS, jpegfile); fclose(jpegfile); } } else { jpegsize = 0; } return jpegsize; } static int generate_YUV4MPEG(parameters_t *param, char *firstjpeg) { uint32_t frame; ssize_t jpegsize; char jpegname[FILENAME_MAX]; char prev_jpegname[FILENAME_MAX]; int loops; /* number of loops to go */ uint8_t *yuv[3]; /* buffer for Y/U/V planes of decoded JPEG */ static uint8_t jpegdata[MAXPIXELS]; /* that ought to be enough */ y4m_stream_info_t streaminfo; y4m_frame_info_t frameinfo; jpegsize = 0; loops = param->loop; mjpeg_info("Number of Loops %i", loops); mjpeg_info("Number of Frames %i", param->numframes); mjpeg_info("Start at frame %i", param->begin); mjpeg_info("Now generating YUV4MPEG stream."); y4m_init_stream_info(&streaminfo); y4m_init_frame_info(&frameinfo); y4m_si_set_width(&streaminfo, param->width); y4m_si_set_height(&streaminfo, param->height); y4m_si_set_interlace(&streaminfo, param->interlace); y4m_si_set_framerate(&streaminfo, param->framerate); y4m_si_set_sampleaspect(&streaminfo, param->aspect_ratio); yuv[0] = malloc(param->width * param->height * sizeof(yuv[0][0])); yuv[1] = malloc(param->width * param->height / 4 * sizeof(yuv[1][0])); yuv[2] = malloc(param->width * param->height / 4 * sizeof(yuv[2][0])); y4m_write_stream_header(STDOUT_FILENO, &streaminfo); prev_jpegname[0] = 0; do { for (frame = param->begin; (frame < param->numframes + param->begin) || (param->numframes == -1); frame++) { if (param->jpegformatstr) { snprintf(jpegname, sizeof(jpegname), param->jpegformatstr, frame); jpegsize = read_jpeg_data(jpegdata, jpegname, prev_jpegname); } else { char *p; if (firstjpeg) { p = firstjpeg; sprintf(jpegname, firstjpeg); firstjpeg = NULL; } else { p = fgets(jpegname, FILENAME_MAX, stdin); } if (p) { strip(jpegname); jpegsize = read_jpeg_data(jpegdata, jpegname, prev_jpegname); } else { jpegsize = -1; } } mjpeg_debug("Numframes %i jpegsize %d", param->numframes, (int)jpegsize); if (jpegsize <= 0) { mjpeg_debug("in jpegsize <= 0"); if (param->numframes == -1) { mjpeg_info("No more frames. Stopping."); break; /* we are done; leave 'while' loop */ } else mjpeg_info("Rewriting latest frame instead."); } if (jpegsize > 0) { mjpeg_debug("Preparing frame"); /* decode_jpeg_raw:s parameters from 20010826 * jpeg_data: buffer with input / output jpeg * len: Length of jpeg buffer * itype: 0: Interleaved/Progressive * 1: Not-interleaved, Top field first * 2: Not-interleaved, Bottom field first * ctype Chroma format for decompression. * Currently always 420 and hence ignored. * raw0 buffer with input / output raw Y channel * raw1 buffer with input / output raw U/Cb channel * raw2 buffer with input / output raw V/Cr channel * width width of Y channel (width of U/V is width/2) * height height of Y channel (height of U/V is height/2) */ if ((param->interlace == Y4M_ILACE_NONE) || (param->interleave == 1)) { mjpeg_info("Processing non-interlaced/interleaved %s, size %d", jpegname, (int)jpegsize); if (param->colorspace == JCS_GRAYSCALE) decode_jpeg_gray_raw(jpegdata, jpegsize, 0, 420, param->width, param->height, yuv[0], yuv[1], yuv[2]); else decode_jpeg_raw(jpegdata, jpegsize, 0, 420, param->width, param->height, yuv[0], yuv[1], yuv[2]); } else { switch (param->interlace) { case Y4M_ILACE_TOP_FIRST: mjpeg_info("Processing interlaced, top-first %s, size %d", jpegname, (int)jpegsize); if (param->colorspace == JCS_GRAYSCALE) decode_jpeg_gray_raw(jpegdata, jpegsize, Y4M_ILACE_TOP_FIRST, 420, param->width, param->height, yuv[0], yuv[1], yuv[2]); else decode_jpeg_raw(jpegdata, jpegsize, Y4M_ILACE_TOP_FIRST, 420, param->width, param->height, yuv[0], yuv[1], yuv[2]); break; case Y4M_ILACE_BOTTOM_FIRST: mjpeg_info("Processing interlaced, bottom-first %s, size %d", jpegname, (int)jpegsize); if (param->colorspace == JCS_GRAYSCALE) decode_jpeg_gray_raw(jpegdata, jpegsize, Y4M_ILACE_BOTTOM_FIRST, 420, param->width, param->height, yuv[0], yuv[1], yuv[2]); else decode_jpeg_raw(jpegdata, jpegsize, Y4M_ILACE_BOTTOM_FIRST, 420, param->width, param->height, yuv[0], yuv[1], yuv[2]); break; default: mjpeg_error_exit1("FATAL logic error?!?"); break; } } if (param->rescale_YUV) { mjpeg_info("Rescaling color values."); rescale_color_vals(param->width, param->height, yuv[0], yuv[1], yuv[2]); } mjpeg_debug("Frame decoded, now writing to output stream."); } y4m_write_frame(STDOUT_FILENO, &streaminfo, &frameinfo, yuv); } if (param->loop != -1) loops--; } while( loops >=1 || loops == -1 ); y4m_fini_stream_info(&streaminfo); y4m_fini_frame_info(&frameinfo); free(yuv[0]); free(yuv[1]); free(yuv[2]); return 0; } /* main * in: argc, argv: Classic commandline parameters. * returns: int: 0: success, !0: !success :-) */ int main(int argc, char ** argv) { parameters_t param; char first_jpegname[FILENAME_MAX]; *first_jpegname = '\0'; parse_commandline(argc, argv, ¶m); mjpeg_default_handler_verbosity(param.verbose); mjpeg_info("Parsing & checking input files."); if (init_parse_files(¶m, first_jpegname)) { mjpeg_error_exit1("* Error processing the JPEG input."); } if (generate_YUV4MPEG(¶m, first_jpegname)) { mjpeg_error_exit1("* Error processing the input files."); } return 0; } mjpegtools-2.1.0/lavtools/liblavrec.c0000644000175000017500000025765011622176510020203 0ustar glowwormglowworm/* * liblavrec - a librarified Linux Audio Video Record-application * * Copyright (C) 2000 Rainer Johanni * Extended by: Gernot Ziegler * & Wolfgang Scherr * & Ronald Bultje * & many others * * A library for recording MJPEG video from hardware MJPEG * video devices such as the Pinnacle/Miro DC10(+), Iomega * Buz, the Linux Media Labs LML33, the Matrox Marvel G200, * Matrox Marvel G400 and the Rainbow Runner G-series. * Can also be used for video-capture from BTTV-devices * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Because of some really cool feature in video4linux1, also known as * 'not including sys/types.h and sys/time.h', we had to include it * ourselves. In all their intelligence, these people decided to fix * this in the next version (video4linux2) in such a cool way that it * breaks all compilations of old stuff... * The real problem is actually that linux/time.h doesn't use proper * macro checks before defining types like struct timeval. The proper * fix here is to either fuck the kernel header (which is what we do * by defining _LINUX_TIME_H, an innocent little hack) or by fixing it * upstream, which I'll consider doing later on. If you get compiler * errors here, check your linux/time.h && sys/time.h header setup. */ #define _LINUX_TIME_H #include #ifdef HAVE_SYS_SOUNDCARD_H #include #endif #include #include #include "mjpeg_logging.h" #include "liblavrec.h" #include "lav_io.h" #include "audiolib.h" #include "jpegutils.h" /* On some systems MAP_FAILED seems to be missing */ #ifndef MAP_FAILED #define MAP_FAILED ( (caddr_t) -1 ) #endif #define MJPEG_MAX_BUF 256 #define MIN_QUEUES_NEEDED 2 /* minimal number of queues needed to sync */ #define NUM_AUDIO_TRIES 500 /* makes 10 seconds with 20 ms pause beetween tries */ #define MIN_MBYTES_FREE 10 /* Minimum number of Mbytes that should stay free on the file system, this is also only a guess */ #define MIN_MBYTES_FREE_OPEN 20 /* Minimum number of Mbytes that have to be free in the filesystem when opening a new file */ #define CHECK_INTERVAL 50 /* Interval for checking free space on file system */ #define VALUE_NOT_FILLED -10000 struct YUVP_convert { unsigned char *mmap; unsigned char *YUVP_buff; }; typedef struct { int interlaced; /* is the video interlaced (even/odd-first)? */ int width; /* width of the captured frames */ int height; /* height of the captured frames */ double spvf; /* seconds per video frame */ int video_fd; /* file descriptor of open("/dev/video") */ int has_audio; /* whether it has an audio ability */ struct mjpeg_requestbuffers breq; /* buffer requests */ struct mjpeg_sync bsync; struct video_mbuf softreq; /* Software capture (YUV) buffer requests */ uint8_t *MJPG_buff; /* the MJPEG buffer */ struct video_mmap mm; /* software (YUV) capture info */ struct YUVP_convert *YUVP_convert; /* Software (YUVP) info */ unsigned char *YUV_buff; /* in case of software encoding: the YUV buffer */ lav_file_t *video_file; /* current lav_io.c file we're recording to */ lav_file_t *video_file_old; /* previous lav_io.c file we're recording to (finish audio/close) */ int num_frames_old; uint8_t AUDIO_buff[AUDIO_BUFFER_SIZE]; /* the audio buffer */ struct timeval audio_t0; int astat; long audio_offset; struct timeval audio_tmstmp; int mixer_set; /* whether the mixer settings were changed */ int audio_bps; /* bytes per second for audio stream */ long audio_buffer_size; /* audio stream buffer size */ double spas; /* seconds per audio sample */ double sync_lim; /* upper limit of 'out-of-sync' - if higher, quit */ video_capture_stats* stats; /* the stats */ uint64_t MBytes_fs_free; /* Free disk space when that was last checked */ uint64_t bytes_output_cur; /* Bytes output to the current output file */ uint64_t bytes_last_checked; /* Number of bytes that were output when the free space was last checked */ int mixer_volume_saved; /* saved recording volume before setting mixer */ int mixer_recsrc_saved; /* saved recording source before setting mixer */ int mixer_inplev_saved; /* saved output volume before setting mixer */ /* the JPEG video encoding thread mess */ struct encoder_info_s * encoders; /* for software encoding recording */ pthread_mutex_t encoding_mutex; /* for software encoding recording */ int buffer_valid[MJPEG_MAX_BUF]; /* Non-zero if buffer has been filled */ int buffer_completed[MJPEG_MAX_BUF]; /* Non-zero if buffer has been compressed/written */ pthread_cond_t buffer_filled[MJPEG_MAX_BUF]; pthread_cond_t buffer_completion[MJPEG_MAX_BUF]; /* thread for correctly timestamping the V4L/YUV buffers */ pthread_t software_sync_thread; /* the thread */ pthread_mutex_t software_sync_mutex; /* the mutex */ sig_atomic_t please_stop_syncing; unsigned long buffers_queued; /* evil hack for BTTV-0.8 */ int software_sync_ready[MJPEG_MAX_BUF]; /* whether the frame has already been synced on */ pthread_cond_t software_sync_wait[MJPEG_MAX_BUF]; /* wait for frame to be synced on */ struct timeval software_sync_timestamp[MJPEG_MAX_BUF]; /* some mutex/cond stuff to make sure we have enough queues left */ pthread_mutex_t queue_mutex; unsigned short queue_left; short is_queued[MJPEG_MAX_BUF]; pthread_cond_t queue_wait; int output_status; pthread_mutex_t state_mutex; int state; /* recording, paused or stoppped */ pthread_t capture_thread; } video_capture_setup; /* Identity record for software encoding worker thread... * Given N workers Worker i compresses frame i,i+n,i+2N and so on. * There may not be more workers than there are capture buffers - 1. */ typedef struct encoder_info_s { lavrec_t *info; unsigned int encoder_id; unsigned int num_encoders; pthread_t thread; } encoder_info_t; /* Forward definitions */ static int lavrec_queue_buffer (lavrec_t *info, unsigned long *num); static int lavrec_handle_audio (lavrec_t *info, struct timeval *timestamp); /****************************************************** * lavrec_msg() * simplicity function which will give messages ******************************************************/ static void lavrec_msg(int type, lavrec_t *info, const char format[], ...) GNUC_PRINTF(3,4); static void lavrec_msg(int type, lavrec_t *info, const char format[], ...) { char buf[1024]; va_list args; va_start(args, format); vsnprintf(buf, sizeof(buf)-1, format, args); va_end(args); if (!info) /* we can't let errors pass without giving notice */ mjpeg_error("%s", buf); else if (info->msg_callback) info->msg_callback(type, buf); else if (type == LAVREC_MSG_ERROR) mjpeg_error("%s", buf); } /****************************************************** * lavrec_change_state() * changes the recording state ******************************************************/ static int lavrec_change_state_if(lavrec_t *info, int new_state, int require_state) { int okay; video_capture_setup *settings = (video_capture_setup *)info->settings; pthread_mutex_lock(&settings->state_mutex); if ((okay = settings->state == require_state) != 0) { settings->state = new_state; if (info->state_changed) info->state_changed(new_state); } pthread_mutex_unlock(&settings->state_mutex); return okay; } static void lavrec_change_state(lavrec_t *info, int new_state) { video_capture_setup *settings = (video_capture_setup *)info->settings; pthread_mutex_lock(&settings->state_mutex); settings->state = new_state; if (info->state_changed) info->state_changed(new_state); pthread_mutex_unlock(&settings->state_mutex); } /****************************************************** * set_mixer() * set the sound mixer: * flag = 1 : set for recording from the line input * flag = 0 : restore previously saved values * * return value: 1 on success, 0 on error ******************************************************/ static int lavrec_set_mixer(lavrec_t *info, int flag) { int fd, var; unsigned int sound_mixer_read_input; unsigned int sound_mixer_write_input; unsigned int sound_mask_input; video_capture_setup *settings = (video_capture_setup *)info->settings; /* Avoid restoring anything when nothing was set */ if (flag==0 && settings->mixer_set==0) return 1; /* Open the audio device */ fd = open(info->mixer_dev, O_RDONLY); if (fd == -1) { lavrec_msg(LAVREC_MSG_WARNING, info, "Unable to open sound mixer \'%s\', try setting the sound mixer with another tool!!!", info->mixer_dev); return 1; /* 0 means error, so although we failed return 1 */ } switch(info->audio_src) { case 'm': sound_mixer_read_input = SOUND_MIXER_READ_MIC; sound_mixer_write_input = SOUND_MIXER_WRITE_MIC; sound_mask_input = SOUND_MASK_MIC; break; case 'c': sound_mixer_read_input = SOUND_MIXER_READ_CD; sound_mixer_write_input = SOUND_MIXER_WRITE_CD; sound_mask_input = SOUND_MASK_CD; break; case 'l': sound_mixer_read_input = SOUND_MIXER_READ_LINE; sound_mixer_write_input = SOUND_MIXER_WRITE_LINE; sound_mask_input = SOUND_MASK_LINE; break; case '1': sound_mixer_read_input = SOUND_MIXER_READ_LINE1; sound_mixer_write_input = SOUND_MIXER_WRITE_LINE1; sound_mask_input = SOUND_MASK_LINE1; break; case '2': sound_mixer_read_input = SOUND_MIXER_READ_LINE2; sound_mixer_write_input = SOUND_MIXER_WRITE_LINE2; sound_mask_input = SOUND_MASK_LINE2; break; case '3': sound_mixer_read_input = SOUND_MIXER_READ_LINE3; sound_mixer_write_input = SOUND_MIXER_WRITE_LINE3; sound_mask_input = SOUND_MASK_LINE3; break; default: lavrec_msg(LAVREC_MSG_WARNING, info, "Unknown sound source: \'%c\'", info->audio_src); close(fd); return 1; /* 0 means error, so although we failed return 1 */ } if(flag==1) { int nerr = 0; /* Save the values we are going to change */ if (settings->mixer_set == 0) { if (ioctl(fd, SOUND_MIXER_READ_VOLUME, &(settings->mixer_volume_saved)) == -1) nerr++; if (ioctl(fd, SOUND_MIXER_READ_RECSRC, &(settings->mixer_recsrc_saved)) == -1) nerr++; if (ioctl(fd, sound_mixer_read_input , &(settings->mixer_inplev_saved)) == -1) nerr++; settings->mixer_set = 1; if (nerr) { lavrec_msg (LAVREC_MSG_WARNING, info, "Unable to save sound mixer settings"); lavrec_msg (LAVREC_MSG_WARNING, info, "Restore your favorite setting with another tool after capture"); settings->mixer_set = 0; /* prevent us from resetting nonsense settings */ } } /* Set the recording source, audio-level and (if wanted) mute */ nerr = 0; var = sound_mask_input; if (ioctl(fd, SOUND_MIXER_WRITE_RECSRC, &var) == -1) nerr++; var = 256*info->audio_level + info->audio_level; /* left and right channel */ if (ioctl(fd, sound_mixer_write_input, &var) == -1) nerr++; if(info->mute) { var = 0; if (ioctl(fd, SOUND_MIXER_WRITE_VOLUME, &var) == -1) nerr++; } if (nerr) { lavrec_msg (LAVREC_MSG_WARNING, info, "Unable to set the sound mixer correctly"); lavrec_msg (LAVREC_MSG_WARNING, info, "Audio capture might not be successfull (try another mixer tool!)"); } } else { int nerr = 0; /* Restore previously saved settings */ if (ioctl(fd, SOUND_MIXER_WRITE_RECSRC, &(settings->mixer_recsrc_saved)) == -1) nerr++; if (ioctl(fd, sound_mixer_write_input, &(settings->mixer_inplev_saved)) == -1) nerr++; if(info->mute) if (ioctl(fd, SOUND_MIXER_WRITE_VOLUME, &(settings->mixer_volume_saved)) == -1) nerr++; if (nerr) { lavrec_msg (LAVREC_MSG_WARNING, info, "Unable to restore sound mixer settings"); lavrec_msg (LAVREC_MSG_WARNING, info, "Restore your favorite setting with another tool"); } settings->mixer_set = 0; } close(fd); return 1; } /****************************************************** * lavrec_autodetect_signal() * (try to) autodetect signal/norm * * return value: 1 on success, 0 on error ******************************************************/ static int lavrec_autodetect_signal(lavrec_t *info) { struct mjpeg_status bstat; int i; video_capture_setup *settings = (video_capture_setup *)info->settings; lavrec_msg(LAVREC_MSG_INFO, info, "Auto detecting input and norm ..."); if (info->software_encoding && (info->video_norm==3 || info->video_src==-1)) { lavrec_msg(LAVREC_MSG_DEBUG, info, "Using current input signal settings for non-MJPEG card"); return 1; } if (info->video_src == -1) /* detect video_src && norm */ { int n = 0; for(i=0;i<2;i++) { lavrec_msg (LAVREC_MSG_INFO, info, "Trying %s ...", (i==2)?"TV tuner":(i==0?"Composite":"S-Video")); bstat.input = i; if (ioctl(settings->video_fd,MJPIOC_G_STATUS,&bstat) < 0) { lavrec_msg (LAVREC_MSG_ERROR, info, "Error getting video input status: %s", (const char*)strerror(errno)); return 0; } if (bstat.signal) { lavrec_msg (LAVREC_MSG_INFO, info, "Input present: %s %s", bstat.norm==0? "PAL":(info->video_norm==1?"NTSC":"SECAM"), bstat.color?"color":"no color"); info->video_src = i; info->video_norm = bstat.norm; n++; } else { lavrec_msg (LAVREC_MSG_INFO, info, "No signal ion specified input"); } } switch(n) { case 0: lavrec_msg (LAVREC_MSG_ERROR, info, "No input signal ... exiting"); return 0; case 1: lavrec_msg (LAVREC_MSG_INFO, info, "Detected %s %s", info->video_norm==0? "PAL":(info->video_norm==1?"NTSC":"SECAM"), info->video_src==0?"Composite":(info->video_src==1?"S-Video":"TV tuner")); break; default: lavrec_msg (LAVREC_MSG_ERROR, info, "Input signal on more thn one input source... exiting"); return 0; } } else if (info->video_norm == 3) /* detect norm only */ { lavrec_msg (LAVREC_MSG_INFO, info, "Trying to detect norm for %s ...", (info->video_src==2) ? "TV tuner" : (info->video_src==0?"Composite":"S-Video")); bstat.input = info->video_src; if (ioctl(settings->video_fd,MJPIOC_G_STATUS,&bstat) < 0) { lavrec_msg (LAVREC_MSG_ERROR, info, "Error getting video input status: %s",strerror(errno)); return 0; } info->video_norm = bstat.norm; lavrec_msg (LAVREC_MSG_INFO, info, "Detected %s", info->video_norm==0? "PAL":(info->video_norm==1?"NTSC":"SECAM")); } return 1; } /****************************************************** * lavrec_get_free_space() * get the amount of free disk space * * return value: 1 on success, 0 on error ******************************************************/ static uint64_t lavrec_get_free_space(video_capture_setup *settings) { uint64_t blocks_per_MB; struct statfs statfs_buf; uint64_t MBytes_fs_free; /* check the disk space again */ if (statfs(settings->stats->output_filename, &statfs_buf)) MBytes_fs_free = 2047; /* some fake value */ else { blocks_per_MB = (1024*1024) / statfs_buf.f_bsize; MBytes_fs_free = statfs_buf.f_bavail/blocks_per_MB; } settings->bytes_last_checked = settings->bytes_output_cur; return MBytes_fs_free; } /****************************************************** * lavrec_close_files_on_error() * Close the output file(s) if an error occured. * We don't care about further errors. ******************************************************/ static void lavrec_close_files_on_error(lavrec_t *info) { video_capture_setup *settings = (video_capture_setup *)info->settings; if(settings->output_status > 0 && settings->video_file) { lav_close(settings->video_file); settings->video_file = NULL; } if(settings->output_status > 1 && settings->video_file_old) { lav_close(settings->video_file_old); settings->video_file_old = NULL; } lavrec_msg(LAVREC_MSG_WARNING, info, "Closing file(s) and exiting - " "output file(s) my not be readable due to error"); } /****************************************************** * lavrec_output_video_frame() * outputs a video frame and does all the file handling * necessary like opening new files and closing old ones. * * return value: 1 on success, 0 on error ******************************************************/ #define OUTPUT_VIDEO_ERROR_RETURN \ if (settings->output_status==2) \ { \ settings->output_status = 3; \ return 1; \ } \ else \ return 0; static int lavrec_output_video_frame(lavrec_t *info, uint8_t *buff, long size, long count) { int n; int OpenNewFlag = 0; video_capture_setup *settings = (video_capture_setup *)info->settings; if(settings->output_status == 3) return 1; /* Only audio is still active */ /* Check space on filesystem if we have filled it up * or if we have written more than CHECK_INTERVAL bytes since last check */ if (settings->output_status > 0) { n = (settings->bytes_output_cur - settings->bytes_last_checked)>>20; /* in MBytes */ if( n > CHECK_INTERVAL || n > settings->MBytes_fs_free - MIN_MBYTES_FREE ) settings->MBytes_fs_free = lavrec_get_free_space(settings); } /* Check if it is time to exit */ if (settings->state == LAVREC_STATE_STOP) lavrec_msg(LAVREC_MSG_INFO, info, "Signal caught, stopping recording"); if (settings->stats->num_frames * settings->spvf > info->record_time && info->record_time >= 0) { lavrec_msg(LAVREC_MSG_INFO, info, "Recording time reached, stopping"); lavrec_change_state(info, LAVREC_STATE_STOP); } /* Check if we have to open a new output file */ if (settings->output_status > 0 && (settings->bytes_output_cur>>20) > info->max_file_size_mb) { lavrec_msg(LAVREC_MSG_INFO, info, "Max filesize reached, opening next output file"); OpenNewFlag = 1; } if( info->max_file_frames > 0 && settings->stats->num_frames % info->max_file_frames == 0) { lavrec_msg(LAVREC_MSG_INFO, info, "Max number of frames reached, opening next output file"); OpenNewFlag = 1; } if (settings->output_status > 0 && settings->MBytes_fs_free < MIN_MBYTES_FREE) { lavrec_msg(LAVREC_MSG_INFO, info, "File system is nearly full, trying to open next output file"); OpenNewFlag = 1; } /* JPEG = always open new file */ if (info->video_format == 'j') OpenNewFlag = 1; /* If a file is open and we should open a new one or exit, close current file */ if (settings->output_status > 0 && (OpenNewFlag || settings->state == LAVREC_STATE_STOP)) { if (info->audio_size) { /* Audio is running - flag that the old file should be closed */ if(settings->output_status != 1) { /* There happened something bad - the old output file from the * last file change is not closed. We try to close all files and exit */ lavrec_msg(LAVREC_MSG_ERROR, info, "Audio too far behind video. Check if audio works correctly!"); lavrec_close_files_on_error(info); return -1; } lavrec_msg(LAVREC_MSG_DEBUG, info, "Closing current output file for video, waiting for audio to be filled"); settings->video_file_old = settings->video_file; settings->video_file = NULL; settings->num_frames_old = settings->stats->num_frames; if (settings->state == LAVREC_STATE_STOP) { settings->output_status = 3; return 1; } else settings->output_status = 2; } else { if (settings->video_file) { if (lav_close(settings->video_file)) { settings->video_file = NULL; lavrec_msg(LAVREC_MSG_ERROR, info, "Error closing video output file %s, may be unuseable due to error", settings->stats->output_filename); return 0; } settings->video_file = NULL; } if (settings->state == LAVREC_STATE_STOP) return 0; } } /* Open new output file if needed */ if (settings->output_status==0 || OpenNewFlag ) { /* Get next filename */ if (info->num_files == 0) { sprintf(settings->stats->output_filename, info->files[0], ++settings->stats->current_output_file); } else { if (settings->stats->current_output_file >= info->num_files) { if (info->video_format == 'j') { settings->stats->current_output_file = 0; } else { lavrec_msg(LAVREC_MSG_WARNING, info, "Number of given output files reached"); OUTPUT_VIDEO_ERROR_RETURN; } } strncpy(settings->stats->output_filename, info->files[settings->stats->current_output_file++], sizeof(settings->stats->output_filename)); } lavrec_msg(LAVREC_MSG_INFO, info, "Opening output file %s", settings->stats->output_filename); /* Open next file */ settings->video_file = lav_open_output_file(settings->stats->output_filename, info->video_format, settings->width, settings->height, settings->interlaced, (info->video_norm==1? 30000.0/1001.0 : 25.0), info->audio_size, (info->stereo ? 2 : 1), info->audio_rate); if (!settings->video_file) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error opening output file %s: %s", settings->stats->output_filename, lav_strerror()); OUTPUT_VIDEO_ERROR_RETURN; } if (settings->output_status == 0) settings->output_status = 1; /* Check space on filesystem. Exit if not enough space */ settings->bytes_output_cur = 0; settings->MBytes_fs_free = lavrec_get_free_space(settings); if(settings->MBytes_fs_free < MIN_MBYTES_FREE_OPEN) { lavrec_msg(LAVREC_MSG_ERROR, info, "Not enough space for opening new output file"); /* try to close and remove file, don't care about errors */ if (settings->video_file) { lav_close(settings->video_file); settings->video_file = NULL; remove(settings->stats->output_filename); } OUTPUT_VIDEO_ERROR_RETURN; } } /* Output the frame count times */ if (lav_write_frame(settings->video_file,buff,size,count)) { /* If an error happened, try to close output files and exit */ lavrec_msg(LAVREC_MSG_ERROR, info, "Error writing to output file %s: %s", settings->stats->output_filename, lav_strerror()); lavrec_close_files_on_error(info); return 0; } /* Update counters. Maybe frame its written only once, * but size*count is the save guess */ settings->bytes_output_cur += size*count; settings->stats->num_frames += count; /* * If the user has specified flushing of file buffers * flush every time the specified number of unflushed frames has * been reached. */ if( info->flush_count > 0 && settings->stats->num_frames % info->flush_count == 0) { int fd = lav_fileno( settings->video_file ); if( fd >= 0 ) fdatasync(fd); } return 1; } static int video_captured(lavrec_t *info, uint8_t *buff, long size, long count) { if (info->files) return lavrec_output_video_frame(info, buff, size, count); else info->video_captured(buff, size, count); return 1; } /****************************************************** * lavrec_output_audio_to_file() * writes audio data to a file * * return value: 1 on success, 0 on error ******************************************************/ static int lavrec_output_audio_to_file(lavrec_t *info, uint8_t *buff, long samps, int old) { video_capture_setup *settings = (video_capture_setup *)info->settings; if(samps==0) return 1; /* Output data */ if (lav_write_audio(old?settings->video_file_old:settings->video_file,buff,samps)) { /* If an error happened, try to close output files and exit */ lavrec_msg(LAVREC_MSG_ERROR, info, "Error writing to output file: %s", lav_strerror()); lavrec_close_files_on_error(info); return 0; } /* update counters */ settings->stats->num_asamps += samps; if (!old) settings->bytes_output_cur += samps * settings->audio_bps; return 1; } /****************************************************** * lavrec_output_audio_samples() * outputs audio samples to files * * return value: 1 on success, 0 or -1 on error ******************************************************/ static int lavrec_output_audio_samples(lavrec_t *info, uint8_t *buff, long samps) { long diff = 0; video_capture_setup *settings = (video_capture_setup *)info->settings; /* Safety first */ if(!settings->output_status) { lavrec_msg(LAVREC_MSG_ERROR, info, "**INTERNAL ERROR: Output audio but no file open"); return -1; } if(settings->output_status<2) { /* Normal mode, just output the sample */ return lavrec_output_audio_to_file(info, buff, samps, 0); } /* if we come here, we have to fill up the old file first */ diff = (settings->num_frames_old * settings->spvf - settings->stats->num_asamps * settings->spas) * info->audio_rate; if(diff<0) { lavrec_msg(LAVREC_MSG_ERROR, info, "**INTERNAL ERROR: Audio output ahead video output"); return -1; } if(diff >= samps) { /* All goes to old file */ return lavrec_output_audio_to_file(info, buff, samps, 1); } /* diff samples go to old file */ if (!lavrec_output_audio_to_file(info, buff, diff, 1)) return 0; /* close old file */ lavrec_msg(LAVREC_MSG_DEBUG, info, "Audio is filled - closing old file"); if (settings->video_file_old) { if (lav_close(settings->video_file_old)) { settings->video_file_old = NULL; lavrec_msg(LAVREC_MSG_ERROR, info, "Error closing video output file, may be unuseable due to error: %s", lav_strerror()); return 0; } settings->video_file_old = NULL; } /* Check if we are ready */ if (settings->output_status==3) return 0; /* remaining samples go to new file */ settings->output_status = 1; return lavrec_output_audio_to_file(info, buff+diff*settings->audio_bps, samps-diff, 0); } static int audio_captured(lavrec_t *info, uint8_t *buff, long samps) { if (info->files) return lavrec_output_audio_samples(info, buff, samps); else info->audio_captured(buff, samps); return 1; } static void frame_YUV422_to_planar_42x(uint8_t *output, uint8_t *input, int width, int height, int chroma) { int i, j, w2; uint8_t *y, *cb, *cr; w2 = width/2; y=output; cb=(output + width*height); cr=(output + (3*width*height)/2); for (i=0; iinfo; video_capture_setup *settings = (video_capture_setup *)info->settings; struct timeval timestamp[MJPEG_MAX_BUF]; int jpegsize; unsigned long current_frame = w_info->encoder_id; unsigned long predecessor_frame; uint8_t * source; uint8_t * buffer=NULL; lavrec_msg(LAVREC_MSG_DEBUG, info, "Starting software encoding thread"); /* Allow easy shutting down by other processes... */ /* PTHREAD_CANCEL_ASYNCHRONOUS is evil pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL ); pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL ); */ while (settings->state == LAVREC_STATE_RECORDING) { pthread_cleanup_push((void (*)(void*))pthread_mutex_unlock, &settings->encoding_mutex); pthread_mutex_lock(&(settings->encoding_mutex)); while (settings->buffer_valid[current_frame] == -1) { lavrec_msg(LAVREC_MSG_DEBUG, info, "Encoding thread: sleeping for new frames (waiting for frame %ld)", current_frame); pthread_cond_wait(&(settings->buffer_filled[current_frame]), &(settings->encoding_mutex)); if (settings->please_stop_syncing) { pthread_mutex_unlock(&(settings->encoding_mutex)); pthread_exit(NULL); } } memcpy(&(timestamp[current_frame]), &(settings->bsync.timestamp), sizeof(struct timeval)); if (settings->buffer_valid[current_frame] > 0) { /* There is no cancellation point in this block, but just to make sure... */ pthread_cleanup_push((void (*)(void*))pthread_mutex_lock, &settings->encoding_mutex); pthread_mutex_unlock(&(settings->encoding_mutex)); if( settings->YUVP_convert ) { memcpy( settings->YUVP_convert[current_frame].YUVP_buff, settings->YUVP_convert[current_frame].mmap, (info->geometry->h * info->geometry->w * 2) ); source=settings->YUV_buff + (info->geometry->h * info->geometry->w * 2)*current_frame; frame_YUV422_to_planar_42x( source, settings->YUVP_convert[current_frame].YUVP_buff, info->geometry->w, info->geometry->h, Y4M_CHROMA_422 ); } else { source=settings->YUV_buff+settings->softreq.offsets[current_frame]; } jpegsize = encode_jpeg_raw(settings->MJPG_buff+current_frame*settings->breq.size, settings->breq.size, info->quality, settings->interlaced, Y4M_CHROMA_422, info->geometry->w, info->geometry->h, source, source+(info->geometry->w*info->geometry->h), source+(info->geometry->w*info->geometry->h*3/2)); if (jpegsize<0) { if( buffer != NULL ) { free( buffer ); buffer=NULL; } lavrec_msg(LAVREC_MSG_ERROR, info, "Error encoding frame to JPEG"); lavrec_change_state(info, LAVREC_STATE_STOP); pthread_exit(0); } pthread_cleanup_pop(1); } else { jpegsize = 0; /* Just toss the frame */ } /* Writing of video and audio data is non-reentrant and must * occur in-order - acquire lock and wait for preceding * frame's encoder to have completed writing that frames data * * Note that we need to queue the buffers in order, too, * so we need to sync up here even if we're discarding * the frame. */ predecessor_frame = ( (current_frame + settings->softreq.frames-1) % settings->softreq.frames ); while( !settings->buffer_completed[predecessor_frame] ) { pthread_cond_wait(&(settings->buffer_completion[predecessor_frame]), &(settings->encoding_mutex)); } if (jpegsize > 0) { if (video_captured(info, settings->MJPG_buff+(settings->breq.size*current_frame), jpegsize, settings->buffer_valid[current_frame]) != 1) { if( buffer != NULL ) { free( buffer ); buffer=NULL; } lavrec_msg(LAVREC_MSG_ERROR, info, "Error writing the frame"); lavrec_change_state(info, LAVREC_STATE_STOP); pthread_exit(0); } } #if 0 if (!lavrec_queue_buffer(info, ¤t_frame)) { if( buffer != NULL ) { free( buffer ); buffer=NULL; } if (info->files) lavrec_close_files_on_error(info); lavrec_msg(LAVREC_MSG_ERROR, info, "Error re-queuing buffer: %s", strerror(errno)); lavrec_change_state(info, LAVREC_STATE_STOP); pthread_exit(0); } /* Mark the capture buffer as once again as in progress for capture */ settings->buffer_valid[current_frame] = -1; #endif /* hack for BTTV-0.8 - give it a status that tells us to queue it in another thread */ settings->buffer_valid[current_frame] = -2; if (!lavrec_handle_audio(info, &(timestamp[current_frame]))) lavrec_change_state(info, LAVREC_STATE_STOP); /* Mark this frame as having completed compression and writing, * signal any encoders waiting for this completion so they can write * out their own results, and release lock. */ settings->buffer_completed[current_frame] = 1; pthread_cond_broadcast(&(settings->buffer_completion[current_frame])); current_frame = (current_frame+w_info->num_encoders)%settings->softreq.frames; pthread_cleanup_pop(1); } if( buffer != NULL ) { free( buffer ); buffer=NULL; } pthread_exit(NULL); return(NULL); } int get_size_offset( int fd, size_t *length, off_t *offset, unsigned int frame ) { struct v4l2_buffer buf; int retval; buf.index=frame; buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE; retval=ioctl( fd, VIDIOC_QUERYBUF, &buf ); if( retval != 0 ) return retval; *length=buf.length; *offset=buf.m.offset; return 0; } int set_format_part1( int fd, uint16_t width, uint16_t height ) { struct v4l2_format format; int retval; memset( &format, 0, sizeof( format ) ); format.type=V4L2_BUF_TYPE_VIDEO_CAPTURE; retval=ioctl( fd, VIDIOC_G_FMT, &format ); if( retval != 0 ) return retval; format.fmt.pix.width=width; format.fmt.pix.height=height; format.fmt.pix.pixelformat=V4L2_PIX_FMT_YUYV; format.fmt.pix.field=V4L2_FIELD_ANY; format.fmt.pix.bytesperline=0; retval=ioctl( fd, VIDIOC_S_FMT, &format ); if( retval != 0 ) return retval; return 0; } int set_format_part2( int fd, unsigned int frame ) { struct v4l2_buffer buf; int retval; enum v4l2_buf_type captype=V4L2_BUF_TYPE_VIDEO_CAPTURE; memset( &buf, 0, sizeof( buf ) ); buf.index=frame; buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE; retval=ioctl( fd, VIDIOC_QUERYBUF, &buf ); if( retval != 0 ) return retval; retval=ioctl(fd, VIDIOC_QBUF, &buf); if( retval != 0 ) return retval; retval=ioctl( fd, VIDIOC_STREAMON, &captype ); if( retval != 0 ) return retval; return 0; } /****************************************************** * lavrec_software_init() * Some software-MJPEG encoding specific initialization * * return value: 1 on success, 0 on error ******************************************************/ static int lavrec_software_init(lavrec_t *info) { struct video_capability vc; int i; video_capture_setup *settings = (video_capture_setup *)info->settings; if (ioctl(settings->video_fd, VIDIOCGCAP, &vc) < 0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error getting device capabilities: %s", strerror(errno)); return 0; } /* vc.maxwidth is often reported wrong - let's just keep it broken (sigh) */ /*if (vc.maxwidth != 768 && vc.maxwidth != 640) vc.maxwidth = 720;*/ /* set some "subcapture" options - cropping is done later on (during capture) */ if(!info->geometry->w) info->geometry->w = ((vc.maxwidth==720&&info->horizontal_decimation!=1)?704:vc.maxwidth)/4; if(!info->geometry->h) info->geometry->h = (info->video_norm==1 ? 480 : 576)/4; if (info->geometry->w > vc.maxwidth) { lavrec_msg(LAVREC_MSG_ERROR, info, "Image width (%d) bigger than maximum (%d)!", info->geometry->w, vc.maxwidth); return 0; } if ((info->geometry->w%16)!=0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Image width (%d) not multiple of 16 (required for JPEG encoding)!", info->geometry->w); return 0; } if (info->geometry->h > (info->video_norm==1 ? 480 : 576)) { lavrec_msg(LAVREC_MSG_ERROR, info, "Image height (%d) bigger than maximum (%d)!", info->geometry->h, (info->video_norm==1 ? 480 : 576)); return 0; } /* RJ: Image height must only be a multiple of 8, but geom_height * is double the field height */ if ((info->geometry->h%16)!=0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Image height (%d) not multiple of 16 (required for JPEG encoding)!", info->geometry->h); return 0; } settings->mm.width = settings->width = info->geometry->w; settings->mm.height = settings->height = info->geometry->h; settings->mm.format = VIDEO_PALETTE_YUV422P; if (info->geometry->h > (info->video_norm==1?320:384)) settings->interlaced = Y4M_ILACE_TOP_FIRST; /* all interlaced BT8x8 capture seems top-first ?? */ else settings->interlaced = Y4M_ILACE_NONE; lavrec_msg(LAVREC_MSG_INFO, info, "Image size will be %dx%d, %d field(s) per buffer", info->geometry->w, info->geometry->h, (settings->interlaced == Y4M_ILACE_NONE)?1:2); /* request buffer info */ if (ioctl(settings->video_fd, VIDIOCGMBUF, &(settings->softreq)) < 0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error getting buffer information: %s", strerror(errno)); return 0; } if (settings->softreq.frames < MIN_QUEUES_NEEDED) { lavrec_msg(LAVREC_MSG_ERROR, info, "We need at least %d buffers, but we only got %d", MIN_QUEUES_NEEDED, settings->softreq.frames); return 0; } lavrec_msg(LAVREC_MSG_INFO, info, "Got %d YUV-buffers of size %d KB", settings->softreq.frames, settings->softreq.size/(1024*settings->softreq.frames)); if( info->software_encoding == 2 ) { int loop; size_t size; off_t offset; settings->YUVP_convert=(struct YUVP_convert *) malloc( settings->softreq.frames * sizeof( struct YUVP_convert ) ); if( settings->YUVP_convert == NULL ) { lavrec_msg (LAVREC_MSG_ERROR, info, "Malloc error, you\'re probably out of memory"); return 0; } settings->YUVP_convert[0].YUVP_buff=(unsigned char *) malloc( settings->mm.width * settings->mm.height * 2 * settings->softreq.frames ); if( settings->YUVP_convert[0].YUVP_buff == NULL ) { lavrec_msg (LAVREC_MSG_ERROR, info, "Malloc error for temp buffers, you\'re probably out of memory"); free( settings->YUVP_convert ); return 0; } for( loop=1; loop < settings->softreq.frames; loop++ ) settings->YUVP_convert[loop].YUVP_buff=settings->YUVP_convert[0].YUVP_buff + (loop * settings->mm.width * settings->mm.height * 2); if( set_format_part1( settings->video_fd, settings->mm.width, settings->mm.height ) ) { free( settings->YUVP_convert[0].YUVP_buff ); free( settings->YUVP_convert ); lavrec_msg( LAVREC_MSG_ERROR, info, "ioctl error on set_format_part1.\n" ); return 0; } for( loop=0; loop < settings->softreq.frames; loop++ ) { if( get_size_offset( settings->video_fd, &size, &offset, loop ) ) { lavrec_msg( LAVREC_MSG_ERROR, info, "Can't get mmap settings" ); free( settings->YUVP_convert[0].YUVP_buff ); free( settings->YUVP_convert ); return 0; } settings->YUVP_convert[loop].mmap=mmap( 0, size, PROT_READ|PROT_WRITE, MAP_SHARED, settings->video_fd, offset ); if( settings->YUVP_convert[loop].mmap == NULL ) { lavrec_msg (LAVREC_MSG_ERROR, info, "Packed YUV mmap error"); free( settings->YUVP_convert[0].YUVP_buff ); free( settings->YUVP_convert ); return 0; } } settings->YUV_buff=(uint8_t *) malloc( settings->softreq.size * info->num_encoders ); if( settings->YUV_buff == NULL ) { free( settings->YUVP_convert[0].YUVP_buff ); free( settings->YUVP_convert ); lavrec_msg( LAVREC_MSG_ERROR, info, "malloc error on YUV_buff.\n" ); return 0; } } else { settings->YUVP_convert=NULL; /* Map the buffers */ settings->YUV_buff = mmap(0, settings->softreq.size, PROT_READ|PROT_WRITE, MAP_SHARED, settings->video_fd, 0); if (settings->YUV_buff == MAP_FAILED) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error mapping video buffers: %s", strerror(errno)); return 0; } } /* set up buffers for software encoding thread */ if (info->MJPG_numbufs > MJPEG_MAX_BUF) { lavrec_msg(LAVREC_MSG_ERROR, info, "Too many buffers (%d) requested, maximum is %d", info->MJPG_numbufs, MJPEG_MAX_BUF); return 0; } /* Check number of JPEG compression worker threads is consistent with * with the number of buffers available */ if (info->num_encoders > info->MJPG_numbufs-1 ) { lavrec_msg(LAVREC_MSG_ERROR, info, "More encoding workers (%d) than number of buffers-1 (%d)", info->num_encoders, info->MJPG_numbufs-1); return 0; } settings->breq.count = info->MJPG_numbufs; settings->breq.size = info->MJPG_bufsize*1024; settings->MJPG_buff = (uint8_t *) malloc(sizeof(uint8_t)*settings->breq.size*settings->breq.count); if (!settings->MJPG_buff) { if( settings->YUVP_convert ) { free( settings->YUVP_convert[0].YUVP_buff ); free( settings->YUVP_convert ); } lavrec_msg (LAVREC_MSG_ERROR, info, "Malloc error, you\'re probably out of memory"); return 0; } lavrec_msg(LAVREC_MSG_INFO, info, "Created %ld MJPEG-buffers of size %ld KB", settings->breq.count, settings->breq.size/1024); /* set up software JPEG-encoding thread */ pthread_mutex_init(&(settings->encoding_mutex), NULL); for (i=0;ibuffer_filled[i]), NULL); pthread_cond_init(&(settings->buffer_completion[i]), NULL); } /* queue setup */ pthread_mutex_init(&(settings->queue_mutex), NULL); pthread_cond_init(&(settings->queue_wait), NULL); return 1; } /****************************************************** * lavrec_hardware_init() * Some hardware-MJPEG encoding specific initialization * * return value: 1 on success, 0 on error ******************************************************/ static int lavrec_hardware_init(lavrec_t *info) { struct video_capability vc; struct mjpeg_params bparm; video_capture_setup *settings = (video_capture_setup *)info->settings; if (ioctl(settings->video_fd, VIDIOCGCAP, &vc) < 0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error getting device capabilities: %s", strerror(errno)); return 0; } /* vc.maxwidth is often reported wrong - let's just keep it broken (sigh) */ if (vc.maxwidth != 768 && vc.maxwidth != 640) vc.maxwidth = 720; /* Query and set params for capture */ if (ioctl(settings->video_fd, MJPIOC_G_PARAMS, &bparm) < 0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error getting video parameters: %s", strerror(errno)); return 0; } bparm.input = info->video_src; bparm.norm = info->video_norm; bparm.quality = info->quality; /* Set decimation and image geometry params - only if we have weird options */ if (info->geometry->x != VALUE_NOT_FILLED || info->geometry->y != VALUE_NOT_FILLED || (info->geometry->h != 0 && info->geometry->h != (info->video_norm==1 ? 480 : 576)) || (info->geometry->w != 0 && info->geometry->w != vc.maxwidth) || info->horizontal_decimation != info->vertical_decimation) { bparm.decimation = 0; if(!info->geometry->w) info->geometry->w = ((vc.maxwidth==720&&info->horizontal_decimation!=1)?704:vc.maxwidth); if(!info->geometry->h) info->geometry->h = info->video_norm==1 ? 480 : 576; bparm.HorDcm = info->horizontal_decimation; bparm.VerDcm = (info->vertical_decimation==4) ? 2 : 1; bparm.TmpDcm = (info->vertical_decimation==1) ? 1 : 2; bparm.field_per_buff = (info->vertical_decimation==1) ? 2 : 1; bparm.img_width = info->geometry->w; bparm.img_height = info->geometry->h/2; if (info->geometry->x != VALUE_NOT_FILLED) bparm.img_x = info->geometry->x; else bparm.img_x = (vc.maxwidth - bparm.img_width)/2; if (info->geometry->y != VALUE_NOT_FILLED) bparm.img_y = info->geometry->y/2; else bparm.img_y = ( (info->video_norm==1 ? 240 : 288) - bparm.img_height)/2; if (info->geometry->w + bparm.img_x > vc.maxwidth) { lavrec_msg(LAVREC_MSG_ERROR, info, "Image width+offset (%d) bigger than maximum (%d)!", info->geometry->w + bparm.img_x, vc.maxwidth); return 0; } if ((info->geometry->w%(bparm.HorDcm*16))!=0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Image width (%d) not multiple of %d (required for JPEG)!", info->geometry->w, bparm.HorDcm*16); return 0; } if (info->geometry->h + bparm.img_y > (info->video_norm==1 ? 480 : 576)) { lavrec_msg(LAVREC_MSG_ERROR, info, "Image height+offset (%d) bigger than maximum (%d)!", info->geometry->h + info->geometry->y, (info->video_norm==1 ? 480 : 576)); return 0; } /* RJ: Image height must only be a multiple of 8, but geom_height * is double the field height */ if ((info->geometry->h%(bparm.VerDcm*16))!=0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Image height (%d) not multiple of %d (required for JPEG)!", info->geometry->h, bparm.VerDcm*16); return 0; } } else { bparm.decimation = info->horizontal_decimation; } /* Care about field polarity and APP Markers which are needed for AVI * and Quicktime and may be for other video formats as well */ if(info->vertical_decimation > 1) { /* for vertical decimation > 1 no known video format needs app markers, * we need also not to care about field polarity */ bparm.APP_len = 0; /* No markers */ } else { int n; bparm.APPn = lav_query_APP_marker(info->video_format); bparm.APP_len = lav_query_APP_length(info->video_format); /* There seems to be some confusion about what is the even and odd field ... */ /* madmac: 20010810: According to Ronald, this is wrong - changed now to EVEN */ bparm.odd_even = lav_query_polarity(info->video_format) == Y4M_ILACE_TOP_FIRST; for(n=0; nvideo_fd, MJPIOC_S_PARAMS, &bparm) < 0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error setting video parameters: %s", strerror(errno)); return 0; } settings->width = bparm.img_width/bparm.HorDcm; settings->height = bparm.img_height/bparm.VerDcm*bparm.field_per_buff; settings->interlaced = (bparm.field_per_buff>1); lavrec_msg(LAVREC_MSG_INFO, info, "Image size will be %dx%d, %d field(s) per buffer", settings->width, settings->height, bparm.field_per_buff); /* Request buffers */ settings->breq.count = info->MJPG_numbufs; settings->breq.size = info->MJPG_bufsize*1024; if (ioctl(settings->video_fd, MJPIOC_REQBUFS,&(settings->breq)) < 0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error requesting video buffers: %s", strerror(errno)); return 0; } lavrec_msg(LAVREC_MSG_INFO, info, "Got %ld buffers of size %ld KB", settings->breq.count, settings->breq.size/1024); /* Map the buffers */ settings->MJPG_buff = mmap(0, settings->breq.count*settings->breq.size, PROT_READ|PROT_WRITE, MAP_SHARED, settings->video_fd, 0); if (settings->MJPG_buff == MAP_FAILED) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error mapping video buffers: %s", strerror(errno)); return 0; } return 1; } /****************************************************** * lavrec_init() * initialize, open devices and start streaming * * return value: 1 on success, 0 on error ******************************************************/ static int lavrec_init(lavrec_t *info) { struct video_channel vch; video_capture_setup *settings = (video_capture_setup *)info->settings; /* are there files to capture to? */ if (info->files) /* yes */ { /* * If NO filesize limit was specifically given then allow unlimited size. * ODML extensions will handle the AVI files and Quicktime has had 64bit * filesizes for a long time */ if (info->max_file_size_mb < 0) info->max_file_size_mb = MAX_MBYTES_PER_FILE_64; lavrec_msg(LAVREC_MSG_DEBUG, info, "Maximum size per file will be %d MB", info->max_file_size_mb); if (info->video_captured || info->audio_captured) { lavrec_msg(LAVREC_MSG_DEBUG, info, "Custom audio-/video-capture functions are being ignored for file-capture"); } } else /* no, so we need the custom actions */ { if (!info->video_captured || (!info->audio_captured && info->audio_size)) { lavrec_msg(LAVREC_MSG_ERROR, info, "No video files or custom video-/audio-capture functions given"); return 0; } } /* Special settings for single frame captures */ if(info->single_frame) info->MJPG_numbufs = 4; /* time lapse/single frame captures don't want audio */ if((info->time_lapse > 1 || info->single_frame) && info->audio_size) { lavrec_msg(LAVREC_MSG_DEBUG, info, "Time lapse or single frame capture mode - audio disabled"); info->audio_size = 0; } /* set the sound mixer */ if (info->audio_size && info->audio_level >= 0) lavrec_set_mixer(info, 1); /* Initialize the audio system if audio is wanted. * This involves a fork of the audio task and is done before * the video device and the output file is opened */ settings->audio_bps = 0; if (info->audio_size) { if (audio_init(1,info->use_read, info->stereo,info->audio_size,info->audio_rate)) { lavrec_set_mixer(info, 0); lavrec_msg(LAVREC_MSG_ERROR, info, "Error initializing Audio: %s",audio_strerror()); return 0; } settings->audio_bps = info->audio_size / 8; if (info->stereo) settings->audio_bps *= 2; settings->audio_buffer_size = audio_get_buffer_size(); } /* back to normal user - only root needed during audio setup */ if (getuid() != geteuid()) { if (setuid(getuid()) < 0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Failed to set effective user-ID: %s", strerror(errno)); return 0; } } /* open the video device */ settings->video_fd = open(info->video_dev, O_RDWR); if (settings->video_fd < 0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error opening video-device (%s): %s", info->video_dev, strerror(errno)); return 0; } /* we might have to autodetect the video-src/norm */ if (lavrec_autodetect_signal(info) == 0) return 0; if (info->software_encoding && info->video_src == -1) vch.channel = 0; else vch.channel = info->video_src; vch.norm = info->video_norm; if (info->video_norm != 3 && info->video_src != -1) { if (ioctl(settings->video_fd, VIDIOCSCHAN, &vch) < 0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error setting channel: %s", strerror(errno)); return 0; } } if (ioctl(settings->video_fd, VIDIOCGCHAN, &vch) < 0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error getting channel info: %s", strerror(errno)); return 0; } settings->has_audio = (vch.flags & VIDEO_VC_AUDIO); info->video_norm = vch.norm; /* the final norm */ /* set channel if we're tuning */ if (vch.flags & VIDEO_VC_TUNER && info->tuner_frequency) { unsigned long outfreq; outfreq = info->tuner_frequency*16/1000; if (ioctl(settings->video_fd, VIDIOCSFREQ, &outfreq) < 0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error setting tuner frequency: %s", strerror(errno)); return 0; } } /* Set up tuner audio if this is a tuner. I think this should be done * AFTER the tuner device is selected */ if (settings->has_audio) { struct video_audio vau; /* get current */ if (ioctl(settings->video_fd,VIDIOCGAUDIO, &vau) < 0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error getting tuner audio params: %s", strerror(errno)); return 0; } /* unmute so we get sound to record * this is done without checking current state because the * current mga driver doesn't report mute state accurately */ lavrec_msg(LAVREC_MSG_INFO, info, "Unmuting tuner audio..."); vau.flags &= (~VIDEO_AUDIO_MUTE); if (ioctl(settings->video_fd,VIDIOCSAUDIO, &vau) < 0) { lavrec_msg(LAVREC_MSG_INFO, info, "Error setting tuner audio params: %s", strerror(errno)); return 0; } } /* set state to paused... ugly, but we need it for the software thread */ settings->state = LAVREC_STATE_PAUSED; /* set up some hardware/software-specific stuff */ if (info->software_encoding) { if (!lavrec_software_init(info)) return 0; } else { if (!lavrec_hardware_init(info)) return 0; } /* Try to get a reliable timestamp for Audio */ if (info->audio_size && info->sync_correction > 1) { int n,res; lavrec_msg(LAVREC_MSG_INFO, info, "Getting audio ..."); for(n=0;;n++) { if(n > NUM_AUDIO_TRIES) { lavrec_msg(LAVREC_MSG_ERROR, info, "Unable to get audio - exiting ...."); return 0; } res = audio_read((unsigned char*)settings->AUDIO_buff,AUDIO_BUFFER_SIZE,0, &(settings->audio_t0),&(settings->astat)); if (res < 0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error reading audio: %s",audio_strerror()); return 0; } if(res && settings->audio_t0.tv_sec ) break; usleep(20000); } } /* If we can increase process priority ... no need for R/T though... * This is mainly useful for running using "at" which otherwise drops the * priority which causes sporadic audio buffer over-runs */ if( getpriority(PRIO_PROCESS, 0) > -5 ) setpriority(PRIO_PROCESS, 0, -5 ); /* Seconds per video frame: */ settings->spvf = (info->video_norm==VIDEO_MODE_NTSC) ? 1001./30000. : 0.040; settings->sync_lim = settings->spvf*1.5; /* Seconds per audio sample: */ if(info->audio_size) settings->spas = 1.0/info->audio_rate; else settings->spas = 0.; return 1; } /****************************************************** * lavrec_wait_for_start() * catch audio until we have to stop or record ******************************************************/ static void lavrec_wait_for_start(lavrec_t *info) { int res; video_capture_setup *settings = (video_capture_setup *)info->settings; while(settings->state == LAVREC_STATE_PAUSED) { usleep(10000); /* Audio (if on) is allready running, empty buffer to avoid overflow */ if (info->audio_size) { while( (res=audio_read((unsigned char*)settings->AUDIO_buff,AUDIO_BUFFER_SIZE, 0,&settings->audio_t0,&settings->astat)) >0 ) /*noop*/; if(res==0) continue; if(res<0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error reading audio: %s", audio_strerror()); lavrec_change_state(info, LAVREC_STATE_STOP); /* stop */ return; } } } } /****************************************************** * lavrec_queue_buffer() * queues a buffer (either MJPEG or YUV) * * return value: 1 on success, 0 on error ******************************************************/ static int lavrec_queue_buffer(lavrec_t *info, unsigned long *num) { video_capture_setup *settings = (video_capture_setup *)info->settings; lavrec_msg(LAVREC_MSG_DEBUG, info, "Queueing frame %lu", *num); if (info->software_encoding) { settings->mm.frame = *num; pthread_mutex_lock(&(settings->queue_mutex)); if (settings->is_queued[*num] < 0) { pthread_mutex_unlock(&(settings->queue_mutex)); return 1; } pthread_mutex_unlock(&(settings->queue_mutex)); if( info->software_encoding == 2 ) { if( set_format_part2( settings->video_fd, *num ) ) return 0; } else { if (ioctl(settings->video_fd, VIDIOCMCAPTURE, &(settings->mm)) < 0) return 0; } pthread_mutex_lock(&(settings->queue_mutex)); settings->queue_left++; settings->is_queued[*num] = 1; settings->buffers_queued++; pthread_cond_broadcast(&(settings->queue_wait)); pthread_mutex_unlock(&(settings->queue_mutex)); } else { if (ioctl(settings->video_fd, MJPIOC_QBUF_CAPT, num) < 0) return 0; } return 1; } /****************************************************** * lavrec_software_sync_thread () * software syncing to get correct timestamps ******************************************************/ static void *lavrec_software_sync_thread(void* arg) { lavrec_t *info = (lavrec_t *) arg; video_capture_setup *settings = (video_capture_setup *)info->settings; int frame = 0; /* framenum to sync on */ #if 1 unsigned long qframe, i; #endif /* Allow easy shutting down by other processes... */ /* PTHREAD_CANCEL_ASYNCHRONOUS is evil pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL ); pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL ); */ /* FIXME: is the right? Or can we just stop. * Don't allow cancellation. We need to shutdown in an orderly * fashion (by noticing that settings->state has changed, to make * sure we dequeue all queued buffers. */ pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, NULL ); while (1) { /* evil hack for BTTV-0.8 - we need to queue frames here */ /* this cycle is non-onbligatory - we just queue frames as they become available, * below, we'll wait for queues if we don't have enough of them */ for (i=0;isoftreq.frames;i++) { qframe = settings->buffers_queued % settings->softreq.frames; if (settings->buffer_valid[qframe] == -2) { if (!lavrec_queue_buffer(info, &qframe)) { pthread_mutex_lock(&(settings->software_sync_mutex)); settings->software_sync_ready[qframe] = -1; pthread_cond_broadcast(&(settings->software_sync_wait[qframe])); pthread_mutex_unlock(&(settings->software_sync_mutex)); lavrec_msg(LAVREC_MSG_ERROR, info, "Error re-queueing a buffer (%lu): %s", qframe, strerror(errno)); lavrec_change_state(info, LAVREC_STATE_STOP); pthread_exit(0); } settings->buffer_valid[qframe] = -1; } else break; } pthread_mutex_lock(&(settings->encoding_mutex)); while (settings->queue_left < MIN_QUEUES_NEEDED) { if (settings->is_queued[frame] <= 0 || settings->please_stop_syncing) break; /* sync on all remaining frames */ #if 0 lavrec_msg(LAVREC_MSG_DEBUG, info, "Software sync thread: sleeping for new queues (%d)", frame); pthread_cond_wait(&(settings->queue_wait), &(settings->queue_mutex)); #else /* sleep for new buffers to be completed encoding. After that, * requeue them so we have more than MIN_QUEUES_NEEDED buffers * free */ qframe = settings->buffers_queued % settings->softreq.frames; lavrec_msg(LAVREC_MSG_DEBUG, info, "Software sync thread: sleeping for new queues (%lu) to become available", qframe); while (settings->buffer_valid[qframe] != -2) { pthread_cond_wait(&(settings->buffer_completion[qframe]), &(settings->encoding_mutex)); if (settings->please_stop_syncing) { pthread_mutex_unlock(&(settings->encoding_mutex)); pthread_exit(0); } } if (!lavrec_queue_buffer(info, &qframe)) { pthread_mutex_unlock(&(settings->encoding_mutex)); pthread_mutex_lock(&(settings->software_sync_mutex)); settings->software_sync_ready[qframe] = -1; pthread_cond_broadcast(&(settings->software_sync_wait[qframe])); pthread_mutex_unlock(&(settings->software_sync_mutex)); lavrec_msg(LAVREC_MSG_ERROR, info, "Error re-queueing a buffer (%lu): %s", qframe, strerror(errno)); lavrec_change_state(info, LAVREC_STATE_STOP); pthread_exit(0); } settings->buffer_valid[qframe] = -1; #endif } if (!settings->queue_left) { lavrec_msg(LAVREC_MSG_DEBUG, info, "Software sync thread stopped"); pthread_mutex_unlock(&settings->encoding_mutex); pthread_exit(NULL); } pthread_mutex_unlock(&settings->encoding_mutex); retry: if (ioctl(settings->video_fd, VIDIOCSYNC, &frame) < 0) { if( errno==EINTR && info->software_encoding ) goto retry; /* BTTV sync got interrupted */ pthread_mutex_lock(&(settings->software_sync_mutex)); settings->software_sync_ready[frame] = -1; pthread_cond_broadcast(&(settings->software_sync_wait[frame])); pthread_mutex_unlock(&(settings->software_sync_mutex)); lavrec_msg(LAVREC_MSG_ERROR, info, "Error syncing on a buffer: %s", strerror(errno)); lavrec_change_state(info, LAVREC_STATE_STOP); pthread_exit(0); } else { pthread_mutex_lock(&(settings->software_sync_mutex)); gettimeofday(&(settings->software_sync_timestamp[frame]), NULL); settings->software_sync_ready[frame] = 1; pthread_cond_broadcast(&(settings->software_sync_wait[frame])); pthread_mutex_unlock(&(settings->software_sync_mutex)); } pthread_mutex_lock(&(settings->queue_mutex)); settings->queue_left--; settings->is_queued[frame] = 0; pthread_mutex_unlock(&(settings->queue_mutex)); frame = (frame+1)%settings->softreq.frames; } return NULL; } /****************************************************** * lavrec_sync_buffer() * sync on a buffer (either MJPIOC_SYNC or VIDIOCSYNC) * * return value: 1 on success, 0 on error ******************************************************/ static int lavrec_sync_buffer(lavrec_t *info, struct mjpeg_sync *bsync) { video_capture_setup *settings = (video_capture_setup *)info->settings; if (info->software_encoding) { bsync->frame = (bsync->frame+1)%settings->softreq.frames; bsync->seq++; pthread_mutex_lock(&(settings->software_sync_mutex)); while (settings->software_sync_ready[bsync->frame] == 0) { lavrec_msg(LAVREC_MSG_DEBUG, info, "Software sync client: sleeping for new frames (waiting for frame %ld)", bsync->frame); pthread_cond_wait(&(settings->software_sync_wait[bsync->frame]), &(settings->software_sync_mutex)); } pthread_mutex_unlock(&(settings->software_sync_mutex)); if (settings->software_sync_ready[bsync->frame] < 0) { return 0; } memcpy(&(bsync->timestamp), &(settings->software_sync_timestamp[bsync->frame]), sizeof(struct timeval)); settings->software_sync_ready[bsync->frame] = 0; } else { if (ioctl(settings->video_fd, MJPIOC_SYNC, bsync) < 0) { return 0; } } lavrec_msg(LAVREC_MSG_DEBUG, info, "Syncing on frame %ld", bsync->frame); return 1; } /****************************************************** * lavrec_handle_audio() * handle audio and output stats * * return value: 1 on success, 0 on error ******************************************************/ static int lavrec_handle_audio(lavrec_t *info, struct timeval *timestamp) { int x; int nerr = 0; video_capture_setup *settings = (video_capture_setup *)info->settings; video_capture_stats *stats = settings->stats; while (info->audio_size) { /* Only try to read a audio sample if video is ahead - else we might * get into difficulties when writing the last samples */ if (settings->output_status < 3 && stats->num_frames * settings->spvf < (stats->num_asamps + settings->audio_buffer_size / settings->audio_bps) * settings->spas) break; x = audio_read((unsigned char*)settings->AUDIO_buff, sizeof(settings->AUDIO_buff), 0, &(settings->audio_tmstmp), &(settings->astat)); if (x == 0) break; if (x < 0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error reading audio: %s", audio_strerror()); if (info->files) lavrec_close_files_on_error(info); nerr++; break; } if (!(settings->astat)) { stats->num_aerr++; stats->stats_changed = 1; } /* Adjust for difference at start */ if (settings->audio_offset >= x) { settings->audio_offset -= x; continue; } x -= settings->audio_offset; /* Got an audio sample, write it out */ if (audio_captured(info, settings->AUDIO_buff+settings->audio_offset, x/settings->audio_bps) != 1) { nerr++; break; /* Done or error occured */ } settings->audio_offset = 0; /* calculate time differences beetween audio and video * tdiff1 is the difference according to the number of frames/samples written * tdiff2 is the difference according to the timestamps * (only if audio timestamp is not zero) */ if(settings->audio_tmstmp.tv_sec) { stats->tdiff1 = stats->num_frames * settings->spvf - stats->num_asamps * settings->spas; stats->tdiff2 = (timestamp->tv_sec - settings->audio_tmstmp.tv_sec) + (timestamp->tv_usec - settings->audio_tmstmp.tv_usec) * 1.e-6; } } /* output_statistics */ if (info->output_statistics) info->output_statistics(stats); stats->stats_changed = 0; stats->prev_sync = stats->cur_sync; if (nerr) return 0; return 1; } /****************************************************** * lavrec_record() * record and process video and audio ******************************************************/ static void lavrec_record(lavrec_t *info) { unsigned long frame_cnt; int x, write_frame, nerr, nfout; video_capture_stats stats; unsigned int first_lost; double time; struct timeval first_time; video_capture_setup *settings = (video_capture_setup *)info->settings; settings->stats = &stats; settings->queue_left = 0; /* basically, this could be done on init, but we need to * reset some variables when going from pause to play and * the other way around, so we need to restart it when we * enter he playing state */ if (info->software_encoding) { for (x=0;xis_queued[x] = 0; settings->buffer_valid[x] = -1; /* 0 means to just omit the frame, -1 means "in progress", -2 is an evil hack for BTTV-0.8 */ settings->buffer_completed[x] = 1; /* 1 means compression and writing completed, 0 means in progress */ } settings->buffers_queued = 0; if( !(settings->encoders = malloc(info->num_encoders * sizeof(encoder_info_t))) ) { lavrec_msg (LAVREC_MSG_ERROR, info, "Malloc error, you\'re probably out of memory"); return; } for (x=0; x < info->num_encoders; ++x ) { settings->encoders[x].info = info; settings->encoders[x].encoder_id = x; settings->encoders[x].num_encoders = info->num_encoders; if ( pthread_create( &(settings->encoders[x].thread), NULL, lavrec_encoding_thread, (void *) &settings->encoders[x] ) ) { lavrec_msg(LAVREC_MSG_ERROR, info, "Failed to create software encoding thread"); lavrec_change_state(info, LAVREC_STATE_STOP); return; } } lavrec_msg(LAVREC_MSG_INFO, info, "Created %d software JPEG-encoding process(es)\n", info->num_encoders); settings->audio_offset = 0; } /* Queue all buffers, this also starts streaming capture */ for (frame_cnt=0; frame_cnt<(info->software_encoding?settings->softreq.frames:settings->breq.count); frame_cnt++) { if (!lavrec_queue_buffer(info, &frame_cnt)) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error queuing buffers: %s", strerror(errno)); lavrec_change_state(info, LAVREC_STATE_STOP); return; } } /* if we're doing software-encoding, start up the software-sync thread */ if (info->software_encoding) { pthread_mutex_init(&(settings->software_sync_mutex), NULL); for (x=0;xsoftware_sync_ready[x] = 0; pthread_cond_init(&(settings->software_sync_wait[x]), NULL); } settings->please_stop_syncing = 0; if ( pthread_create( &(settings->software_sync_thread), NULL, lavrec_software_sync_thread, (void *) info ) ) { lavrec_msg(LAVREC_MSG_ERROR, info, "Failed to create software sync thread"); lavrec_change_state(info, LAVREC_STATE_STOP); } } /* reset the counter(s) */ nerr = 0; write_frame = 1; first_lost = 0; stats.stats_changed = 0; stats.num_syncs = 0; stats.num_lost = 0; stats.num_frames = 0; stats.num_asamps = 0; stats.num_ins = 0; stats.num_del = 0; stats.num_aerr = 0; stats.tdiff1 = 0.; stats.tdiff2 = 0.; if (info->software_encoding); settings->bsync.frame = -1; gettimeofday( &(stats.prev_sync), NULL ); /* The video capture loop */ while (settings->state == LAVREC_STATE_RECORDING) { /* sync on a frame */ if (!lavrec_sync_buffer(info, &(settings->bsync))) { if (info->files) lavrec_close_files_on_error(info); lavrec_msg(LAVREC_MSG_ERROR, info, "Error syncing on a buffer: %s", strerror(errno)); nerr++; } stats.num_syncs++; gettimeofday( &(stats.cur_sync), NULL ); if(stats.num_syncs==1) { first_time = settings->bsync.timestamp; first_lost = settings->bsync.seq; if(info->audio_size && info->sync_correction > 1) { /* Get time difference beetween audio and video in bytes */ settings->audio_offset = ((first_time.tv_usec-settings->audio_t0.tv_usec)*1.e-6 + first_time.tv_sec-settings->audio_t0.tv_sec - settings->spvf)*info->audio_rate; settings->audio_offset *= settings->audio_bps; /* convert to bytes */ } else settings->audio_offset = 0; } time = settings->bsync.timestamp.tv_sec - first_time.tv_sec + 1.e-6*(settings->bsync.timestamp.tv_usec - first_time.tv_usec) + settings->spvf; /* for first frame */ /* Should we write a frame? */ if(info->single_frame) { lavrec_change_state_if(info, LAVREC_STATE_PAUSED, LAVREC_STATE_RECORDING); write_frame = 1; nfout = 1; /* always output frame only once */ } else if(info->time_lapse > 1) { write_frame = (stats.num_syncs % info->time_lapse) == 0; nfout = 1; /* always output frame only once */ } else /* normal capture */ { nfout = 1; frame_cnt = settings->bsync.seq - stats.num_syncs - first_lost + 1; /* total lost frames */ if (info->sync_correction > 0) nfout += frame_cnt - stats.num_lost; /* lost since last sync */ stats.stats_changed = (stats.num_lost != frame_cnt); stats.num_lost = frame_cnt; /* Check if we have to insert/delete frames to stay in sync */ if (info->sync_correction > 1) { if( stats.tdiff1 - stats.tdiff2 < -settings->sync_lim) { nfout++; stats.num_ins++; stats.stats_changed = 1; stats.tdiff1 += settings->spvf; } if( stats.tdiff1 - stats.tdiff2 > settings->sync_lim) { nfout--; stats.num_del++; stats.stats_changed = 1; stats.tdiff1 -= settings->spvf; } } } /* write it out */ if (info->software_encoding) { pthread_mutex_lock(&(settings->encoding_mutex)); settings->buffer_valid[settings->bsync.frame] = write_frame?nfout:0; settings->buffer_completed[settings->bsync.frame] = 0; pthread_cond_broadcast(&(settings->buffer_filled[settings->bsync.frame])); pthread_mutex_unlock(&(settings->encoding_mutex)); } else if(write_frame && nfout > 0) { if (video_captured(info, settings->MJPG_buff+settings->bsync.frame*settings->breq.size, settings->bsync.length, nfout) != 1) nerr++; /* Done or error occured */ /* Re-queue the buffer */ if (!lavrec_queue_buffer(info, &(settings->bsync.frame))) { if (info->files) lavrec_close_files_on_error(info); lavrec_msg(LAVREC_MSG_ERROR, info, "Error re-queuing buffer: %s", strerror(errno)); nerr++; } if (!lavrec_handle_audio(info, &(settings->bsync.timestamp))) nerr++; } /* if (nerr++) we need to stop and quit */ if (nerr) lavrec_change_state(info, LAVREC_STATE_STOP); } if (info->software_encoding) { pthread_mutex_lock(&settings->encoding_mutex); settings->please_stop_syncing = 1; /* Ask the software sync thread to stop */ for (x=0;xsoftreq.frames;x++) pthread_cond_broadcast(&settings->buffer_completion[x]); pthread_mutex_unlock(&settings->encoding_mutex); for (x = 0; x < info->num_encoders; x++) { lavrec_msg(LAVREC_MSG_DEBUG, info, "Joining encoding thread %d", x); pthread_cancel( settings->encoders[x].thread ); pthread_join( settings->encoders[x].thread, NULL ); } free(settings->encoders); lavrec_msg(LAVREC_MSG_DEBUG, info, "Joining software sync thread"); pthread_join(settings->software_sync_thread, NULL); for (x=0;xsoftware_sync_wait[x])); } pthread_mutex_destroy(&(settings->software_sync_mutex)); } else { /* cancel all queued buffers (now this is much nicer!) */ x = -1; if (ioctl(settings->video_fd, MJPIOC_QBUF_CAPT, &x) < 0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error resetting buffer-queue: %s", strerror(errno)); } } } /****************************************************** * lavrec_recording_cycle() * the main cycle for recording video ******************************************************/ static void lavrec_recording_cycle(lavrec_t *info) { video_capture_setup *settings = (video_capture_setup *)info->settings; while (1) { if (settings->state == LAVREC_STATE_PAUSED) lavrec_wait_for_start(info); else if (settings->state == LAVREC_STATE_RECORDING) lavrec_record(info); else break; } } /****************************************************** * lavrec_capture_thread() * the video/audio capture thread ******************************************************/ static void *lavrec_capture_thread(void *arg) { lavrec_t *info = (lavrec_t*)arg; video_capture_setup *settings = (video_capture_setup *)info->settings; lavrec_recording_cycle(info); /* shutdown video/audio and close */ if (info->audio_size) audio_shutdown(); /* certainty for all :-) */ if (settings->video_file) { lav_close(settings->video_file); settings->video_file = NULL; } if (settings->video_file_old) { lav_close(settings->video_file_old); settings->video_file_old = NULL; } /* reset mixer */ if (info->audio_size) lavrec_set_mixer(info, 0); /* Re-mute tuner audio if this is a tuner */ if (settings->has_audio) { struct video_audio vau; lavrec_msg(LAVREC_MSG_INFO, info, "Re-muting tuner audio..."); vau.flags |= VIDEO_AUDIO_MUTE; if (ioctl(settings->video_fd,VIDIOCSAUDIO,&vau) < 0) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error resetting tuner audio params: %s", strerror(errno)); } } /* and at last, we need to get rid of the video device */ close(settings->video_fd); /* just to be sure */ if (settings->state != LAVREC_STATE_STOP) lavrec_change_state(info, LAVREC_STATE_STOP); pthread_exit(NULL); return NULL; } /****************************************************** * lavrec_malloc() * malloc a pointer and set default options * * return value: a pointer to lavrec_t or NULL ******************************************************/ lavrec_t *lavrec_malloc(void) { lavrec_t *info; video_capture_setup * settings; info = (lavrec_t *)malloc(sizeof(lavrec_t)); if (!info) { lavrec_msg (LAVREC_MSG_ERROR, NULL, "Malloc error, you\'re probably out of memory"); return NULL; } /* let's set some default values now */ info->video_format = '\0'; info->video_norm = 3; info->video_src = -1; info->software_encoding = 0; info->num_encoders = 0; /* this should be set to the number of processors */ info->horizontal_decimation = 4; info->vertical_decimation = 4; info->geometry = (rect *)malloc(sizeof(rect)); if (!(info->geometry)) { lavrec_msg (LAVREC_MSG_ERROR, NULL, "Malloc error, you\'re probably out of memory"); return NULL; } info->geometry->x = VALUE_NOT_FILLED; info->geometry->y = VALUE_NOT_FILLED; info->geometry->w = 0; info->geometry->h = 0; info->quality = 50; info->record_time = -1; info->tuner_frequency = 0; info->video_dev = "/dev/video"; info->audio_size = 16; info->audio_rate = 44100; info->stereo = 0; info->audio_level = -1; info->mute = 0; info->audio_src = 'l'; info->use_read = 0; info->audio_dev = "/dev/dsp"; info->mixer_dev = "/dev/mixer"; info->single_frame = 0; info->time_lapse = 1; info->sync_correction = 2; info->MJPG_numbufs = 64; info->MJPG_bufsize = 256; info->files = NULL; info->num_files = 0; info->flush_count = 60; info->output_statistics = NULL; info->audio_captured = NULL; info->video_captured = NULL; info->msg_callback = NULL; info->state_changed = NULL; info->max_file_size_mb = -1; /*(0x4000000>>20);*/ /* Safety first ;-) */ info->settings = (void *)malloc(sizeof(video_capture_setup)); if (!(info->settings)) { lavrec_msg (LAVREC_MSG_ERROR, NULL, "Malloc error, you\'re probably out of memory"); return NULL; } settings = (video_capture_setup*)(info->settings); pthread_mutex_init(&settings->state_mutex, 0); settings->state = LAVREC_STATE_STOP; settings->output_status = 0; settings->video_file = NULL; settings->video_file_old = NULL; return info; } /****************************************************** * lavrec_main() * the whole video-capture cycle * * Basic setup: * * this function initializes the devices, * sets up the whole thing and then forks * the main task and returns control to the * main app. It can then start recording by * calling lavrec_start(): * * 1) setup/initialize/open devices (state: STOP) * 2) wait for lavrec_start() (state: PAUSE) * 3) record (state: RECORD) * 4) stop/deinitialize/close (state: STOP) * * * it should be possible to switch from RECORD * to PAUSE and the other way around. When * STOP, we stop and close the devices, so * then you need to re-call this function. * * return value: 1 on succes, 0 on error ******************************************************/ int lavrec_main(lavrec_t *info) { video_capture_setup *settings = (video_capture_setup *)info->settings; int ret; struct sched_param schedparam; /* Flush the Linux File buffers to disk */ sync(); /* start with initing */ if (!lavrec_init(info)) return 0; /* Now we're ready to go move to Real-time scheduling... */ schedparam.sched_priority = 1; if(setpriority(PRIO_PROCESS, 0, -15)) { /* Give myself maximum priority */ lavrec_msg(LAVREC_MSG_WARNING, info, "Unable to set negative priority for main thread"); } if( (ret = pthread_setschedparam( pthread_self(), SCHED_FIFO, &schedparam ) ) ) { lavrec_msg(LAVREC_MSG_WARNING, info, "Pthread Real-time scheduling for main thread could not be enabled"); } /* now, set state to pause and catch audio until started */ /* lavrec_change_state(info, LAVREC_STATE_PAUSED); */ settings->state = LAVREC_STATE_PAUSED; /* fork ourselves to return control to the main app */ if( pthread_create( &(settings->capture_thread), NULL, lavrec_capture_thread, (void*)info) ) { lavrec_msg(LAVREC_MSG_ERROR, info, "Failed to create thread"); return 0; } return 1; } /****************************************************** * lavrec_start() * start recording (only call when ready!) * * return value: 1 on succes, 0 on error ******************************************************/ int lavrec_start(lavrec_t *info) { video_capture_setup *settings = (video_capture_setup *)info->settings; if (!lavrec_change_state_if(info, LAVREC_STATE_RECORDING, LAVREC_STATE_PAUSED)) { lavrec_msg(LAVREC_MSG_WARNING, info, "Not ready for capture (state = %d)!", settings->state); return 0; } return 1; } /****************************************************** * lavrec_pause() * pause recording (you can call play to continue) * * return value: 1 on succes, 0 on error ******************************************************/ int lavrec_pause(lavrec_t *info) { if (!lavrec_change_state_if(info, LAVREC_STATE_PAUSED, LAVREC_STATE_RECORDING)) { lavrec_msg(LAVREC_MSG_WARNING, info, "Not recording!"); return 0; } return 1; } /****************************************************** * lavrec_stop() * stop recording * * return value: 1 on succes, 0 on error ******************************************************/ int lavrec_stop(lavrec_t *info) { video_capture_setup *settings = (video_capture_setup *)info->settings; int okay = lavrec_change_state_if(info, LAVREC_STATE_STOP, LAVREC_STATE_RECORDING) || lavrec_change_state_if(info, LAVREC_STATE_STOP, LAVREC_STATE_PAUSED); if (!okay) { lavrec_msg(LAVREC_MSG_DEBUG, info, "We weren't even initialized!"); lavrec_change_state(info, LAVREC_STATE_STOP); return 0; } lavrec_change_state(info, LAVREC_STATE_STOP); pthread_join( settings->capture_thread, NULL ); return 1; } /****************************************************** * lavrec_free() * free() the struct * * return value: 1 on succes, 0 on error ******************************************************/ int lavrec_free(lavrec_t *info) { video_capture_setup *settings = (video_capture_setup *)info->settings; if (settings->state != LAVREC_STATE_STOP) { lavrec_msg(LAVREC_MSG_WARNING, info, "We're not stopped yet, use lavrec_stop() first!"); return 0; } pthread_mutex_destroy(&settings->state_mutex); free(settings); free(info->geometry); free(info); return 1; } /****************************************************** * lavrec_busy() * Wait until capturing is finished ******************************************************/ void lavrec_busy(lavrec_t *info) { pthread_join( ((video_capture_setup*)(info->settings))->capture_thread, NULL); } mjpegtools-2.1.0/lavtools/y4mcolorbars.c0000644000175000017500000003554510603772216020660 0ustar glowwormglowworm/* * y4mcolorbars.c: Generate real, standard colorbars in POG form * (where "POG" == "YUV4MPEG2 stream"). * * * Copyright (C) 2004 Matthew J. Marjanovic * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include #include #include #include #include #include #include "subsample.h" #include "colorspace.h" #define DEFAULT_CHROMA_MODE Y4M_CHROMA_444 #define IQ_MODE_IQ20 0 /* 20 percent -I,+Q */ #define IQ_MODE_IQ50 1 /* 50 percent -I,+Q */ #define IQ_MODE_CBCR100 2 /* 100 percent -Cb,+Cr (original behavior) */ typedef struct _cl_info { y4m_ratio_t aspect; int interlace; y4m_ratio_t framerate; int framecount; int ss_mode; int width; int height; int verbosity; int iq_mode; } cl_info_t; static void usage(const char *progname) { fprintf(stderr, "usage: %s [options]\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "Creates a YUV4MPEG2 stream consisting of frames containing a standard\n"); fprintf(stderr, " colorbar test pattern (SMPTE, 75%%).\n"); fprintf(stderr, "\n"); fprintf(stderr, "Options: (defaults specified in [])\n"); fprintf(stderr, "\n"); fprintf(stderr, " -n n frame count (output n frames) [1]\n"); fprintf(stderr, "\n"); fprintf(stderr, " -W w frame width [720]\n"); fprintf(stderr, " -H h frame height [480]\n"); fprintf(stderr, " -F n:d framerate (as ratio) [30000:1001]\n"); fprintf(stderr, " -A w:h pixel aspect ratio [10:11]\n"); fprintf(stderr, " -I x interlacing [p]\n"); fprintf(stderr, " p = none/progressive\n"); fprintf(stderr, " t = top-field-first\n"); fprintf(stderr, " b = bottom-field-first\n"); fprintf(stderr, " -Q n content of -I/Q areas: [0]\n"); fprintf(stderr, " 0 = 20%% -I,+Q\n"); fprintf(stderr, " 1 = 50%% -I,+Q\n"); fprintf(stderr, " 2 = 100%% +Cb,+Cr\n"); fprintf(stderr, "\n"); { int m; const char *keyword; fprintf(stderr, " -S mode chroma subsampling mode [%s]\n", y4m_chroma_keyword(DEFAULT_CHROMA_MODE)); for (m = 0; (keyword = y4m_chroma_keyword(m)) != NULL; m++) if (chroma_sub_implemented(m)) fprintf(stderr, " '%s' -> %s\n", keyword, y4m_chroma_description(m)); } fprintf(stderr, "\n"); fprintf(stderr, " -v n verbosity (0,1,2) [1]\n"); } static void parse_args(cl_info_t *cl, int argc, char **argv) { int c; cl->interlace = Y4M_ILACE_NONE; cl->framerate = y4m_fps_NTSC; cl->framecount = 1; cl->ss_mode = DEFAULT_CHROMA_MODE; cl->width = 720; cl->height = 480; cl->aspect = y4m_sar_NTSC_CCIR601; cl->verbosity = 1; cl->iq_mode = IQ_MODE_IQ20; while ((c = getopt(argc, argv, "A:F:I:W:H:n:S:Q:v:h")) != -1) { switch (c) { case 'W': if ((cl->width = atoi(optarg)) <= 0) { mjpeg_error("Invalid width: '%s'", optarg); goto ERROR_EXIT; } break; case 'H': if ((cl->height = atoi(optarg)) <= 0) { mjpeg_error("Invalid height: '%s'", optarg); goto ERROR_EXIT; } break; case 'A': if (y4m_parse_ratio(&(cl->aspect), optarg) != Y4M_OK) { mjpeg_error("Could not parse ratio: '%s'", optarg); goto ERROR_EXIT; } break; case 'F': if (y4m_parse_ratio(&(cl->framerate), optarg) != Y4M_OK) { mjpeg_error("Could not parse framerate: '%s'", optarg); goto ERROR_EXIT; } break; case 'I': switch (optarg[0]) { case 'p': cl->interlace = Y4M_ILACE_NONE; break; case 't': cl->interlace = Y4M_ILACE_TOP_FIRST; break; case 'b': cl->interlace = Y4M_ILACE_BOTTOM_FIRST; break; default: mjpeg_error("Unknown value for interlace: '%c'", optarg[0]); goto ERROR_EXIT; break; } break; case 'n': if ((cl->framecount = atoi(optarg)) <= 0) { mjpeg_error("Invalid frame count: '%s'", optarg); goto ERROR_EXIT; } break; case 'S': cl->ss_mode = y4m_chroma_parse_keyword(optarg); if (cl->ss_mode == Y4M_UNKNOWN) { mjpeg_error("Unknown subsampling mode option: %s", optarg); goto ERROR_EXIT; } else if (!chroma_sub_implemented(cl->ss_mode)) { mjpeg_error("Unsupported subsampling mode option: %s", optarg); goto ERROR_EXIT; } break; case 'Q': switch (atoi(optarg)) { case 0: cl->iq_mode = IQ_MODE_IQ20; break; case 1: cl->iq_mode = IQ_MODE_IQ50; break; case 2: cl->iq_mode = IQ_MODE_CBCR100; break; default: mjpeg_error("Unknown -I/+Q mode: %d", atoi(optarg)); goto ERROR_EXIT; } break; case 'v': cl->verbosity = atoi(optarg); break; case 'h': usage(argv[0]); exit(0); break; case '?': default: mjpeg_error("Unknown option: '-%c'", optopt); goto ERROR_EXIT; break; } } mjpeg_default_handler_verbosity(cl->verbosity); mjpeg_info("Colorbar Command-line Parameters:"); mjpeg_info(" frame size: %dx%d", cl->width, cl->height); mjpeg_info(" framerate: %d:%d", cl->framerate.n, cl->framerate.d); mjpeg_info(" pixel aspect ratio: %d:%d", cl->aspect.n, cl->aspect.d); mjpeg_info(" interlace: %s", mpeg_interlace_code_definition(cl->interlace)); mjpeg_info(" # of frames: %d", cl->framecount); mjpeg_info(" chroma subsampling: %s", y4m_chroma_description(cl->ss_mode)); return; ERROR_EXIT: mjpeg_error("For usage hints, use option '-h': '%s -h'", argv[0]); exit(1); } /* * Color Bars: * * top 2/3: 75% white, followed by 75% binary combinations * of R', G', and B' with decreasing luma * * middle 1/12: reverse order of above, but with 75% white and * alternating black * * bottom 1/4: -I, 100% white, +Q, black, PLUGE, black, * where PLUGE is (black - 4 IRE), black, (black + 4 IRE) * */ /* 75% white */ /* 75% yellow */ /* 75% cyan */ /* 75% green */ /* 75% magenta */ /* 75% red */ /* 75% blue */ static uint8_t rainbowRGB[][7] = { { 191, 191, 0, 0, 191, 191, 0 }, { 191, 191, 191, 191, 0, 0, 0 }, { 191, 0, 191, 0, 191, 0, 191 } }; static uint8_t *rainbow[3] = { rainbowRGB[0], rainbowRGB[1], rainbowRGB[2] }; /* 75% blue */ /* black */ /* 75% magenta */ /* black */ /* 75% cyan */ /* black */ /* 75% white */ static uint8_t wobnairRGB[][7] = { { 0, 0, 191, 0, 0, 0, 191 }, { 0, 0, 0, 0, 191, 0, 191 }, { 191, 0, 191, 0, 191, 0, 191 } }; static uint8_t *wobnair[3] = { wobnairRGB[0], wobnairRGB[1], wobnairRGB[2] }; /* The ancient Y'IQ * * Classic colorbars have -I and +Q in the PLUGE section. * * Following Poynton, "Digital Video and HDTV", p367: * * -I = (-0.955987, +0.272013, +1.106740) R'G'B' * +Q = (+0.620825, -0.647204, +1.704231) R'G'B' * * Converting to Y'PbPr and Y'CbCr: * * -I = (0, 0.624571 -0.681873) -> (16, 268, -25) * +Q = (0, 0.961755 0.442815) -> (16, 343, 227) * * Uh, oh: these are outside of the Y'CbCr gamut. * We can get around this, kind of, by reducing the magnitude until they * fit, keeping the phase the same. Q is the worst offender, and a factor * of 0.5 does the trick: * * (0.5)*(-I) = (0 0.312286 -0.340937) -> (16, 198, 52) * (0.5)*(+Q) = (0 0.480878 0.221407) -> (16, 236, 178) * * (0.2)*(-I) = (0 0.124914 -0.136375) -> (16 156 97) * (0.2)*(+Q) = (0 0.192351 0.088563) -> (16 171 148) 10, 9E, 5F 16, 158, 95 10, AE, 95 16, 174, 149 i 244 612 395 61 153 99 q 141 697 606 35 174 151 -4 29 512 512 7.25 128 128 +4 99 512 512 24.75 128 128 AD-723: burst ampl: 185-250-315 mV Bt860: 285.7 mV --> 40 IRE (per RS-170A -- 40 IRE top-bottom?) Maxim app notes: NTSC: 286mV peak-to-peak PAL: 300mV peak-to-peak * */ static uint8_t negI_50percent[] = { 16, 198, 52 }; static uint8_t posQ_50percent[] = { 16, 236, 178 }; static uint8_t negI_20percent[] = { 16, 156, 97 }; static uint8_t posQ_20percent[] = { 16, 171, 148 }; /* static uint8_t negCb_100percent[] = { 16, 16, 128 }; */ static uint8_t posCb_100percent[] = { 16, 240, 128 }; /* static uint8_t negCr_100percent[] = { 16, 128, 16 }; */ static uint8_t posCr_100percent[] = { 16, 128, 240 }; /* PLUGE (SMPTE EG-1-1990) * * This part of the signal can never be truly synthesized in Y'CbCr space, * because it is fundamentally tied to the analog signal specification. * * The two main components are a (Black - 4 IRE) and (Black + 4 IRE). * Simple enough, except that the relation between "IRE" and Y' units depends * on the specific analog output format, which sets the black-white range: * * Y': 16-235 -> excursion of 219 * NTSC with 0% setup: 0-100 IRE -> excursion of 100 IRE * NTSC with 7.5% setup: 7.5-100 IRE -> excursion of 92.5 IRE * * It's the analog output stage (e.g. graphics card, decoder chip) that * converts the Y'CbCr digital values to an analog voltage appropriate * for whatever analog equipment comes next. * To perfectly synthesize a 4-IRE signal in a 0% setup system, we'd * want 8.76 "Y' units". For a 7.5% setup system, we'd want 9.47. * Lucky for us, we're not allowed to use fractions anyway, so we * just split the difference and settle for "9". * */ static uint8_t neg4IRE[] = { (16 - 9), 128, 128 }; static uint8_t pos4IRE[] = { (16 + 9), 128, 128 }; static uint8_t black[] = { 16, 128, 128 }; static uint8_t white[] = { 235, 128, 128 }; static void create_bars(uint8_t *ycbcr[], int width, int height, int iq_mode) { int i, x, y, w; int bnb_start; int pluge_start; int stripe_width; int pl_width; uint8_t *lineY; uint8_t *lineCb; uint8_t *lineCr; uint8_t *Y = ycbcr[0]; uint8_t *Cb = ycbcr[1]; uint8_t *Cr = ycbcr[2]; uint8_t *i_pixel; uint8_t *q_pixel; convert_RGB_to_YCbCr(rainbow, 7); convert_RGB_to_YCbCr(wobnair, 7); switch (iq_mode) { case IQ_MODE_CBCR100: i_pixel = posCb_100percent; q_pixel = posCr_100percent; break; case IQ_MODE_IQ50: i_pixel = negI_50percent; q_pixel = posQ_50percent; break; case IQ_MODE_IQ20: default: i_pixel = negI_20percent; q_pixel = posQ_20percent; break; } bnb_start = height * 2 / 3; pluge_start = height * 3 / 4; stripe_width = (width + 6) / 7; lineY = malloc(width * sizeof(lineY[0])); lineCb = malloc(width * sizeof(lineCb[0])); lineCr = malloc(width * sizeof(lineCr[0])); /* Top: Rainbow */ for (i = 0, x = 0; i < 7; i++) { for (w = 0; (w < stripe_width) && (x < width); w++, x++) { lineY[x] = rainbow[0][i]; lineCb[x] = rainbow[1][i]; lineCr[x] = rainbow[2][i]; } } for (y = 0; y < bnb_start; y++) { memcpy(Y, lineY, width); memcpy(Cb, lineCb, width); memcpy(Cr, lineCr, width); Y += width; Cb += width; Cr += width; } /* Middle: Wobnair */ for (i = 0, x = 0; i < 7; i++) { for (w = 0; (w < stripe_width) && (x < width); w++, x++) { lineY[x] = wobnair[0][i]; lineCb[x] = wobnair[1][i]; lineCr[x] = wobnair[2][i]; } } for (; y < pluge_start; y++) { memcpy(Y, lineY, width); memcpy(Cb, lineCb, width); memcpy(Cr, lineCr, width); Y += width; Cb += width; Cr += width; } /* Bottom: PLUGE */ pl_width = 5 * stripe_width / 4; /* -I patch */ for (x = 0; x < pl_width; x++) { lineY[x] = i_pixel[0]; lineCb[x] = i_pixel[1]; lineCr[x] = i_pixel[2]; } /* white */ for (; x < (2 * pl_width); x++) { lineY[x] = white[0]; lineCb[x] = white[1]; lineCr[x] = white[2]; } /* +Q patch */ for (; x < (3 * pl_width); x++) { lineY[x] = q_pixel[0]; lineCb[x] = q_pixel[1]; lineCr[x] = q_pixel[2]; } /* black */ for (; x < (5 * stripe_width); x++) { lineY[x] = black[0]; lineCb[x] = black[1]; lineCr[x] = black[2]; } /* (black - 4IRE) | black | (black + 4IRE) */ for (; x < (5 * stripe_width) + (stripe_width / 3); x++) { lineY[x] = neg4IRE[0]; lineCb[x] = neg4IRE[1]; lineCr[x] = neg4IRE[2]; } for (; x < (5 * stripe_width) + (2 * (stripe_width / 3)); x++) { lineY[x] = black[0]; lineCb[x] = black[1]; lineCr[x] = black[2]; } for (; x < (6 * stripe_width); x++) { lineY[x] = pos4IRE[0]; lineCb[x] = pos4IRE[1]; lineCr[x] = pos4IRE[2]; } /* black */ for (; x < width; x++) { lineY[x] = black[0]; lineCb[x] = black[1]; lineCr[x] = black[2]; } for (; y < height; y++) { memcpy(Y, lineY, width); memcpy(Cb, lineCb, width); memcpy(Cr, lineCr, width); Y += width; Cb += width; Cr += width; } free(lineY); free(lineCb); free(lineCr); } int main(int argc, char **argv) { cl_info_t cl; y4m_stream_info_t sinfo; y4m_frame_info_t finfo; uint8_t *planes[Y4M_MAX_NUM_PLANES]; /* Y'CbCr frame buffer */ int fdout = fileno(stdout); int i; int err; y4m_accept_extensions(1); y4m_init_stream_info(&sinfo); y4m_init_frame_info(&finfo); parse_args(&cl, argc, argv); /* Setup streaminfo and write output header */ y4m_si_set_width(&sinfo, cl.width); y4m_si_set_height(&sinfo, cl.height); y4m_si_set_sampleaspect(&sinfo, cl.aspect); y4m_si_set_interlace(&sinfo, cl.interlace); y4m_si_set_framerate(&sinfo, cl.framerate); y4m_si_set_chroma(&sinfo, cl.ss_mode); if ((err = y4m_write_stream_header(fdout, &sinfo)) != Y4M_OK) mjpeg_error_exit1("Write header failed: %s", y4m_strerr(err)); mjpeg_info("Colorbar Stream parameters:"); y4m_log_stream_info(mjpeg_loglev_t("info"), " ", &sinfo); /* Create the colorbars frame */ for (i = 0; i < 3; i++) planes[i] = malloc(cl.width * cl.height * sizeof(planes[i][0])); create_bars(planes, cl.width, cl.height, cl.iq_mode); chroma_subsample(cl.ss_mode, planes, cl.width, cl.height); /* We're on the air! */ for (i = 0; i < cl.framecount; i++) { if ((err = y4m_write_frame(fdout, &sinfo, &finfo, planes)) != Y4M_OK) mjpeg_error_exit1("Write frame failed: %s", y4m_strerr(err)); } /* We're off the air. :( */ for (i = 0; i < 3; i++) free(planes[i]); y4m_fini_stream_info(&sinfo); y4m_fini_frame_info(&finfo); return 0; } mjpegtools-2.1.0/lavtools/transist.flt.c0000644000175000017500000001373310560144261020661 0ustar glowwormglowworm/* * transist - reads two frame-interlaced YUV4MPEG streams from stdin * and writes out a transistion from one to the other * * Copyright (C) 2000, pHilipp Zabel * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "mjpeg_logging.h" #include "yuv4mpeg.h" static void usage (void) { fprintf(stderr, "usage: transist.flt [params]\n" "params: -o num opacity of second input at the beginning [0-255]\n" " -O num opacity of second input at the end [0-255]\n" " -d num duration of transistion in frames (REQUIRED!)\n" " -s num skip first num frames of transistion\n" " -n num only process num frames of the transistion\n" " -r num repeat each frame 'num' times. (default = 1)\n" " -v num verbosity [0..2]\n"); } static void blend (unsigned char *src0[3], unsigned char *src1[3], unsigned int opacity1, unsigned int len, unsigned char *dst[3]) { register unsigned int i = 0; register unsigned int j = 0; register unsigned int op1 = opacity1 & 0xFF; register unsigned int op0 = 0x100 - op1; do { dst[2][j] = (op0 * src0[2][j] + op1 * src1[2][j]) >> 8; dst[1][j] = (op0 * src0[1][j] + op1 * src1[1][j]) >> 8; j++; dst[0][i] = (op0 * src0[0][i] + op1 * src1[0][i]) >> 8; i++; dst[0][i] = (op0 * src0[0][i] + op1 * src1[0][i]) >> 8; i++; dst[0][i] = (op0 * src0[0][i] + op1 * src1[0][i]) >> 8; i++; dst[0][i] = (op0 * src0[0][i] + op1 * src1[0][i]) >> 8; i++; } while (i < len); } int main (int argc, char *argv[]) { int verbose = 1; int in_fd = 0; /* stdin */ int out_fd = 1; /* stdout */ unsigned char *yuv0[3]; /* input 0 */ unsigned char *yuv1[3]; /* input 1 */ unsigned char *yuv[3]; /* output */ int w, h, len, lensr2; int i, j, opacity, opacity_range, frame, numframes, r = 0; unsigned int param_opacity0 = 0; /* opacity of input1 at the beginning */ unsigned int param_opacity1 = 255; /* opacity of input1 at the end */ unsigned int param_duration = 0; /* duration of transistion effect */ unsigned int param_skipframes = 0; /* # of frames to skip */ unsigned int param_numframes = 0; /* # of frames to (process - skip+num) * framerepeat <= duration */ unsigned int param_framerep = 1; /* # of repititions per frame */ y4m_stream_info_t streaminfo; y4m_frame_info_t frameinfo; y4m_init_stream_info (&streaminfo); y4m_init_frame_info (&frameinfo); while ((i = getopt(argc, argv, "v:o:O:d:s:n:r:")) != -1) { switch (i) { case 'v': verbose = atoi (optarg); if( verbose < 0 || verbose >2 ) { usage (); exit (1); } break; case 'o': param_opacity0 = atoi (optarg); if (param_opacity0 > 255) { mjpeg_warn( "start opacity > 255"); param_opacity0 = 255; } break; case 'O': param_opacity1 = atoi (optarg); if (param_opacity1 > 255) { mjpeg_warn( "end opacity > 255"); param_opacity1 = 255; } break; case 'd': param_duration = atoi (optarg); if (param_duration == 0) { mjpeg_error_exit1( "error: duration = 0 frames"); } break; case 's': param_skipframes = atoi (optarg); break; case 'n': param_numframes = atoi (optarg); break; case 'r': param_framerep = atoi (optarg); break; } } if (param_numframes == 0) param_numframes = (param_duration - param_skipframes) / param_framerep; if (param_duration == 0) { usage (); exit (1); } numframes = (param_skipframes + param_numframes) * param_framerep; if (numframes > param_duration) { mjpeg_error_exit1( "skip + num > duration"); } (void)mjpeg_default_handler_verbosity(verbose); i = y4m_read_stream_header (in_fd, &streaminfo); if (i != Y4M_OK) { fprintf (stderr, "%s: input stream error - %s\n", argv[0], y4m_strerr(i)); exit (1); } w = y4m_si_get_width(&streaminfo); h = y4m_si_get_height(&streaminfo); len = w*h; lensr2 = len >> 2; yuv[0] = malloc (len); yuv0[0] = malloc (len); yuv1[0] = malloc (len); yuv[1] = malloc (lensr2); yuv0[1] = malloc (lensr2); yuv1[1] = malloc (lensr2); yuv[2] = malloc (lensr2); yuv0[2] = malloc (lensr2); yuv1[2] = malloc (lensr2); y4m_write_stream_header (out_fd, &streaminfo); frame = param_skipframes; param_duration--; opacity_range = param_opacity1 - param_opacity0; while (1) { if (!r) { r = param_framerep; i = y4m_read_frame(in_fd, &streaminfo, &frameinfo, yuv0); if (i != Y4M_OK) exit (frame < numframes); j = y4m_read_frame(in_fd, &streaminfo, &frameinfo, yuv1); if (j != Y4M_OK) exit (frame < numframes); } r--; opacity = param_opacity0 + ((frame * opacity_range) / param_duration); blend (yuv0, yuv1, opacity, len, yuv); y4m_write_frame (out_fd, &streaminfo, &frameinfo, yuv); if (++frame == numframes) exit (0); } } mjpegtools-2.1.0/lavtools/lav2yuv.c0000644000175000017500000002314310351367066017642 0ustar glowwormglowworm/* lav2yuv - stream any lav input file to stdout as YUV4MPEG data */ /* Copyright (C) 2000, Rainer Johanni, Andrew Stevens */ /* - added scene change detection code 2001, pHilipp Zabel */ /* - broke some common code out to lav_common.c and lav_common.h, * July 2001, Shawn Sulma . In doing this, I * repackaged the numerous globals into three structs that get passed into * the relevant functions. See lav_common.h for a bit more information. * Helpful feedback is welcome. */ /* - removed a lot of subsumed functionality and unnecessary cruft * March 2002, Matthew Marjanovic . */ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "lav_common.h" #include void error(char *text); void Usage(char *str); void streamout(void); int verbose = 1; EditList el; void Usage(char *str) { fprintf(stderr, "Usage: %s [params] inputfiles\n" " where possible params are:\n" " -m Force mono-chrome\n" " -S list.el Output a scene list with scene detection\n" " -T num Set scene detection threshold to num (default: 4)\n" " -D num Width decimation to use for scene detection (default: 2)\n" " -A w:h Set output sample aspect ratio\n" " (default: read from DV files, or guess for MJPEG)\n" " -P w:h Declare the intended display aspect ratio (used to guess\n" " the sample aspect ratio). Common values are 4:3 and 16:9.\n" " (default: read from DV files, or assume 4:3 for MJPEG)\n" " -C chroma Set output chroma (default: '420jpeg')\n" " '420jpeg', '420mpeg2', '420paldv', '422', '411' are available\n" " -o num Frame offset - skip num frames in the beginning\n" " if num is negative, all but the last num frames are skipped\n" " -f num Only num frames are written to stdout (0 means all frames)\n" " -c Conceal corrupt jpeg frames by repeating previous frame\n" " -x Exchange fields\n", str); exit(0); } static int lum_mean; static int last_lum_mean; static int delta_lum; static int scene_num; static int scene_start; LavParam param; uint8_t *frame_bufs[6]; static int conceal_errframes; static int altbuf; void streamout(void) { int framenum, movie_num=0, index[MAX_EDIT_LIST_FILES]; int concealnum = 0; long int oldframe=N_EL_FRAME(el.frame_list[0])-1; FILE *fd=NULL; int fd_out = 1; /* stdout. */ char temp[32]; y4m_stream_info_t streaminfo; y4m_frame_info_t frameinfo; y4m_init_stream_info(&streaminfo); y4m_init_frame_info(&frameinfo); if (!param.scenefile) writeoutYUV4MPEGheader(fd_out, ¶m, el, &streaminfo); scene_num = scene_start = 0; if (param.scenefile) { int num_files; int i; param.output_width = param.output_width / param.scene_detection_decimation; /* Output file */ unlink(param.scenefile); fd = fopen(param.scenefile,"w"); if(fd==0) { mjpeg_error_exit1("Can not open %s - no edit list written!",param.scenefile); } fprintf(fd,"LAV Edit List\n"); fprintf(fd,"%s\n",el.video_norm=='n'?"NTSC":"PAL"); for(i=0;i=0) fprintf(fd,"%s\n",el.video_file_list[i]); sprintf(temp,"%d %ld", index[N_EL_FILE(el.frame_list[0])], N_EL_FRAME(el.frame_list[0])); } for (framenum = param.offset; framenum < (param.offset + param.frames); ++framenum) { int rf; uint8_t **read_buf; uint8_t **frame_buf; if(conceal_errframes) read_buf = &frame_bufs[4 * (altbuf ^ 1)]; else read_buf = &frame_bufs[0]; rf = readframe(framenum, read_buf, ¶m, el); if(conceal_errframes) { if(rf == 2) { // corrupt frame; repeat previous mjpeg_debug("corrupt jpeg data in frame %d; repeating previous frame.", framenum); frame_buf = &frame_bufs[4 * altbuf]; concealnum++; } else { // use new frame frame_buf = read_buf; altbuf ^= 1; } } else { if(rf == 2) mjpeg_debug("corrupt jpeg data in frame %d", framenum); frame_buf = &frame_bufs[0]; } if (param.scenefile) { lum_mean = luminance_mean(frame_buf, param.output_width, param.output_height ); if (framenum == 0) { delta_lum = 0; movie_num = N_EL_FILE(el.frame_list[0]); } else delta_lum = abs(lum_mean - last_lum_mean); last_lum_mean = lum_mean; mjpeg_debug( "frame %d/%ld, lum_mean %d, delta_lum %d ", framenum, el.video_frames, lum_mean, delta_lum); if (delta_lum > param.delta_lum_threshold || index[N_EL_FILE(el.frame_list[framenum])] != movie_num || oldframe+1 != N_EL_FRAME(el.frame_list[framenum])) { if (delta_lum <= param.delta_lum_threshold) fprintf(fd,"%c",'+'); /* Same scene, new file */ fprintf(fd,"%s %ld\n", temp, N_EL_FRAME(el.frame_list[framenum-1])); sprintf(temp,"%d %ld",index[N_EL_FILE(el.frame_list[framenum])], N_EL_FRAME(el.frame_list[framenum])); scene_start = framenum; scene_num++; } oldframe = N_EL_FRAME(el.frame_list[framenum]); movie_num = N_EL_FILE(el.frame_list[framenum]); } else { int i; i = y4m_write_frame(fd_out, &streaminfo, &frameinfo, frame_buf); if (i != Y4M_OK) mjpeg_error("Failed to write frame: %s", y4m_strerr(i)); } } mjpeg_info( "Repeated frames (for error concealment): %d", concealnum); if (param.scenefile) { fprintf(fd, "%s %ld\n", temp, N_EL_FRAME(el.video_frames-1)); fclose(fd); mjpeg_info( "Editlist written to %s", param.scenefile); } y4m_fini_frame_info(&frameinfo); } int main(argc, argv) int argc; char *argv[]; { int n, nerr = 0; int exchange_fields = 0; y4m_accept_extensions(1); param.offset = 0; param.frames = 0; param.mono = 0; param.scenefile = NULL; param.delta_lum_threshold = 4; param.scene_detection_decimation = 2; param.output_width = 0; param.output_height = 0; param.interlace = -1; param.sar = y4m_sar_UNKNOWN; param.dar = y4m_dar_4_3; param.chroma = Y4M_UNKNOWN; while ((n = getopt(argc, argv, "xmYv:S:T:D:o:f:P:A:C:c")) != EOF) { switch (n) { case 'v': verbose = atoi(optarg); if (verbose < 0 ||verbose > 2) { mjpeg_error( "-v option requires arg 0, 1, or 2"); nerr++; } break; case 'm': param.mono = 1; break; case 'x': exchange_fields = 1; break; case 'c': conceal_errframes = 1; break; case 'S': param.scenefile = optarg; break; case 'T': param.delta_lum_threshold = atoi(optarg); break; case 'D': param.scene_detection_decimation = atoi(optarg); break; case 'o': param.offset = atoi(optarg); break; case 'f': param.frames = atoi(optarg); break; case 'A': if (y4m_parse_ratio(&(param.sar), optarg)) { mjpeg_error("Couldn't parse ratio '%s'", optarg); nerr++; } break; case 'P': if (y4m_parse_ratio(&(param.dar), optarg)) { mjpeg_error("Couldn't parse ratio '%s'", optarg); nerr++; } break; case 'C': param.chroma = y4m_chroma_parse_keyword(optarg); switch (param.chroma) { case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: case Y4M_CHROMA_422: case Y4M_CHROMA_411: break; default: mjpeg_error("Unsupported chroma '%s'", optarg); nerr++; break; } break; default: nerr++; } } if (optind >= argc) nerr++; if (nerr) Usage(argv[0]); (void)mjpeg_default_handler_verbosity(verbose); /* Open editlist */ read_video_files(argv + optind, argc - optind, &el,0); param.output_width = el.video_width; param.output_height = el.video_height; if(exchange_fields) { if(el.video_inter == Y4M_ILACE_BOTTOM_FIRST) { mjpeg_info("Exchange from BOTTOM_FIRST to TOP_FIRST"); el.video_inter = Y4M_ILACE_TOP_FIRST; } else if(el.video_inter == Y4M_ILACE_TOP_FIRST) { mjpeg_info("Exchange from TOP_FIRST to BOTTOM_FIRST"); el.video_inter = Y4M_ILACE_BOTTOM_FIRST; } else { mjpeg_warn("Video NOT INTERLACED! Could not exchange fields"); } } if (param.offset < 0) { param.offset = el.video_frames + param.offset; } if (param.offset >= el.video_frames) { mjpeg_error_exit1("offset greater than # of frames in input"); } if ((param.offset + param.frames) > el.video_frames) { mjpeg_warn("input too short for -f %d", param.frames); param.frames = el.video_frames - param.offset; } if (param.frames == 0) { param.frames = el.video_frames - param.offset; } param.interlace = el.video_inter; init(¶m, &frame_bufs[0] /*&buffer*/); if(conceal_errframes) init(¶m, &frame_bufs[4] /*&buffer*/); #ifdef HAVE_LIBDV lav_init_dv_decoder(); #endif if (param.delta_lum_threshold != -1) { streamout(); } else { write_edit_list(param.scenefile, 0, el.video_frames, &el); } return 0; } mjpegtools-2.1.0/lavtools/lav_common.c0000644000175000017500000004536410363240744020371 0ustar glowwormglowworm/* lav_common - some general utility functionality used by multiple lavtool utilities. */ /* Copyright (C) 2000, Rainer Johanni, Andrew Stevens */ /* - added scene change detection code 2001, pHilipp Zabel */ /* - broke some code out to lav_common.h and lav_common.c * July 2001, Shawn Sulma . In doing this, * I replaced the large number of globals with a handful of structs * that are passed into the appropriate methods. Check lav_common.h * for the structs. I'm sure some of what I've done is inefficient, * subtly incorrect or just plain Wrong. Feedback is welcome. */ /* - removed a lot of subsumed functionality and unnecessary cruft * March 2002, Matthew Marjanovic . */ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include "lav_common.h" #include "jpegutils.h" #include "mpegconsts.h" #include "cpu_accel.h" static uint8_t jpeg_data[MAX_JPEG_LEN]; #ifdef HAVE_LIBDV dv_decoder_t *decoder; uint16_t pitches[3]; uint8_t *dv_frame[3] = {NULL,NULL,NULL}; /* * As far as I (maddog) can tell, this is what is going on with libdv-0.9 * and the unpacking routine... * o Ft/Fb refer to top/bottom scanlines (interleaved) --- each sample * is implicitly tagged by 't' or 'b' (samples are not mixed between * fields) * o Indices on Cb and Cr samples indicate the Y sample with which * they are co-sited. * o '^' indicates which samples are preserved by the unpacking * * libdv packs both NTSC 4:1:1 and PAL 4:2:0 into a common frame format of * packed 4:2:2 pixels as follows: * * ***** NTSC 4:1:1 ***** * * libdv's 4:2:2-packed representation (chroma repeated horizontally) * *Ft Y00.Cb00.Y01.Cr00.Y02.Cb00.Y03.Cr00 Y04.Cb04.Y05.Cr04.Y06.Cb04.Y07.Cr04 * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ *Fb Y00.Cb00.Y01.Cr00.Y02.Cb00.Y03.Cr00 Y04.Cb04.Y05.Cr04.Y06.Cb04.Y07.Cr04 * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ *Ft Y10.Cb10.Y11.Cr10.Y12.Cb10.Y13.Cr10 Y14.Cb14.Y15.Cr14.Y16.Cb14.Y17.Cr14 * ^ ^ ^ ^ ^ ^ ^ ^ *Fb Y10.Cb10.Y11.Cr10.Y12.Cb10.Y13.Cr10 Y14.Cb14.Y15.Cr14.Y16.Cb14.Y17.Cr14 * ^ ^ ^ ^ ^ ^ ^ ^ * * lavtools unpacking into 4:2:0-planar (note lossiness) * *Ft Y00.Y01.Y02.Y03.Y04.Y05.Y06.Y07... *Fb Y00.Y01.Y02.Y03.Y04.Y05.Y06.Y07... *Ft Y10.Y11.Y12.Y13.Y14.Y15.Y16.Y17... *Fb Y10.Y11.Y12.Y13.Y14.Y15.Y16.Y17... * *Ft Cb00.Cb00.Cb04.Cb04... Cb00,Cb04... are doubled *Fb Cb00.Cb00.Cb04.Cb04... Cb10,Cb14... are ignored * *Ft Cr00.Cr00.Cr04.Cr04... *Fb Cr00.Cr00.Cr04.Cr04... * * ***** PAL 4:2:0 ***** * * libdv's 4:2:2-packed representation (chroma repeated vertically) * *Ft Y00.Cb00.Y01.Cr10.Y02.Cb02.Y03.Cr12 Y04.Cb04.Y05.Cr14.Y06.Cb06.Y07.Cr16 * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ *Fb Y00.Cb00.Y01.Cr10.Y02.Cb02.Y03.Cr12 Y04.Cb04.Y05.Cr14.Y06.Cb06.Y07.Cr16 * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ *Ft Y10.Cb00.Y11.Cr10.Y12.Cb02.Y13.Cr12 Y14.Cb04.Y15.Cr14.Y16.Cb06.Y17.Cr16 * ^ ^ ^ ^ ^ ^ ^ ^ *Fb Y10.Cb00.Y11.Cr10.Y12.Cb02.Y13.Cr12 Y14.Cb04.Y15.Cr14.Y16.Cb06.Y17.Cr16 * ^ ^ ^ ^ ^ ^ ^ ^ * * lavtools unpacking into 4:2:0-planar * *Ft Y00.Y01.Y02.Y03.Y04.Y05.Y06.Y07... *Fb Y00.Y01.Y02.Y03.Y04.Y05.Y06.Y07... *Ft Y10.Y11.Y12.Y13.Y14.Y15.Y16.Y17... *Fb Y10.Y11.Y12.Y13.Y14.Y15.Y16.Y17... * *Ft Cb00.Cb02.Cb04.Cb06... *Fb Cb00.Cb02.Cb04.Cb06... * *Ft Cr10.Cr12.Cr14.Cr16... *Fb Cr10.Cr12.Cr14.Cr16... * */ /* * Unpack libdv's 4:2:2-packed into our 4:2:0-planar or 4:2:2-planar, * treating each interlaced field independently * */ static void frame_YUV422_to_planar_42x(uint8_t **output, uint8_t *input, int width, int height, int chroma) { int i, j, w2; uint8_t *y, *cb, *cr; w2 = width/2; y = output[0]; cb = output[1]; cr = output[2]; for (i=0; iluma_size = param->output_width * param->output_height; switch (param->chroma) { default: mjpeg_warn("unsupported chroma (%d), assume '420jpeg'", param->chroma); param->chroma = Y4M_UNKNOWN; /* will update in writeoutYUV4MPEGheader() */ /* and do same as case Y4M_CHROMA_420JPEG... */ case Y4M_UNKNOWN: case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: param->chroma_width = param->output_width / 2; param->chroma_height = param->output_height / 2; break; case Y4M_CHROMA_422: param->chroma_width = param->output_width / 2; param->chroma_height = param->output_height; break; case Y4M_CHROMA_411: param->chroma_width = param->output_width / 4; param->chroma_height = param->output_height; break; } param->chroma_size = param->chroma_height * param->chroma_width; buffer[0] = (uint8_t *)bufalloc(param->luma_size); buffer[1] = (uint8_t *)bufalloc(param->chroma_size); buffer[2] = (uint8_t *)bufalloc(param->chroma_size); #ifdef HAVE_LIBDV dv_frame[0] = (uint8_t *)bufalloc(3 * param->output_width * param->output_height); dv_frame[1] = buffer[1]; dv_frame[2] = buffer[2]; #endif } /* * readframe - read jpeg or dv frame into yuv buffer * * returns: * 0 success * 1 fatal error * 2 corrupt data encountered; * decoding can continue, but this frame may be damaged */ int readframe(int numframe, uint8_t *frame[], LavParam *param, EditList el) { int len, i, res, data_format; uint8_t *frame_tmp; int warn; warn = 0; if (MAX_JPEG_LEN < el.max_frame_size) { mjpeg_error_exit1( "Max size of JPEG frame = %ld: too big", el.max_frame_size); } len = el_get_video_frame(jpeg_data, numframe, &el); data_format = el_video_frame_data_format(numframe, &el); switch(data_format) { case DATAFORMAT_DV2 : #ifndef HAVE_LIBDV mjpeg_error("DV input was not configured at compile time"); res = 1; #else mjpeg_debug("DV frame %d len %d",numframe,len); res = 0; dv_parse_header(decoder, jpeg_data); switch(decoder->sampling) { case e_dv_sample_420: /* libdv decodes PAL DV directly as planar YUV 420 * (YV12 or 4CC 0x32315659) if configured with the flag * --with-pal-yuv=YV12 which is not (!) the default */ if (libdv_pal_yv12 == 1) { pitches[0] = decoder->width; pitches[1] = decoder->width / 2; pitches[2] = decoder->width / 2; if (pitches[0] != param->output_width || pitches[1] != param->chroma_width) { mjpeg_error("for DV 4:2:0 only full width output is supported"); res = 1; } else { dv_decode_full_frame(decoder, jpeg_data, e_dv_color_yuv, frame, (int *)pitches); /* swap the U and V components */ frame_tmp = frame[2]; frame[2] = frame[1]; frame[1] = frame_tmp; } break; } case e_dv_sample_411: case e_dv_sample_422: /* libdv decodes NTSC DV (native 411) and by default also PAL * DV (native 420) as packed YUV 422 (YUY2 or 4CC 0x32595559) * where the U and V information is repeated. This can be * transformed to planar 420 (YV12 or 4CC 0x32315659). * For NTSC DV this transformation is lossy. */ pitches[0] = decoder->width * 2; pitches[1] = 0; pitches[2] = 0; if (decoder->width != param->output_width) { mjpeg_error("for DV only full width output is supported"); res = 1; } else { dv_decode_full_frame(decoder, jpeg_data, e_dv_color_yuv, dv_frame, (int *)pitches); frame_YUV422_to_planar(frame, dv_frame[0], decoder->width, decoder->height, param->chroma); } break; default: res = 1; break; } #endif /* HAVE_LIBDV */ break; case DATAFORMAT_YUV420 : case DATAFORMAT_YUV422 : mjpeg_debug("raw YUV frame %d len %d",numframe,len); frame_tmp = jpeg_data; memcpy(frame[0], frame_tmp, param->luma_size); frame_tmp += param->luma_size; memcpy(frame[1], frame_tmp, param->chroma_size); frame_tmp += param->chroma_size; memcpy(frame[2], frame_tmp, param->chroma_size); res = 0; break; default: mjpeg_debug("MJPEG frame %d len %d",numframe,len); res = decode_jpeg_raw(jpeg_data, len, el.video_inter, param->chroma, param->output_width, param->output_height, frame[0], frame[1], frame[2]); } if (res < 0) { mjpeg_warn( "Fatal Error Decoding Frame %d", numframe); return 1; } else if (res == 1) { mjpeg_warn( "Decoding of Frame %d failed", numframe); warn = 1; res = 0; } if (param->mono) { for (i = 0; i < param->chroma_size; ++i) { frame[1][i] = 0x80; frame[2][i] = 0x80; } } if(warn) return 2; else return 0; } void writeoutYUV4MPEGheader(int out_fd, LavParam *param, EditList el, y4m_stream_info_t *streaminfo) { int n; y4m_si_set_width(streaminfo, param->output_width); y4m_si_set_height(streaminfo, param->output_height); y4m_si_set_interlace(streaminfo, param->interlace); y4m_si_set_framerate(streaminfo, mpeg_conform_framerate(el.video_fps)); if (!Y4M_RATIO_EQL(param->sar, y4m_sar_UNKNOWN)) { y4m_si_set_sampleaspect(streaminfo, param->sar); } else if ((el.video_sar_width != 0) || (el.video_sar_height != 0)) { y4m_ratio_t sar; sar.n = el.video_sar_width; sar.d = el.video_sar_height; y4m_si_set_sampleaspect(streaminfo, sar); } else { /* no idea! ...eh, just guess. */ mjpeg_warn("unspecified sample-aspect-ratio --- taking a guess..."); y4m_si_set_sampleaspect(streaminfo, y4m_guess_sar(param->output_width, param->output_height, param->dar)); } switch (el_video_frame_data_format(0, &el)) { /* FIXME: checking only 0-th frame. */ case DATAFORMAT_YUV420: switch (param->chroma) { case Y4M_UNKNOWN: case Y4M_CHROMA_420JPEG: break; case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: mjpeg_warn("4:2:0 chroma should be '420jpeg' with this input"); break; default: mjpeg_error_exit1("must specify 4:2:0 chroma (should be '420jpeg') with this input"); break; } break; case DATAFORMAT_YUV422: switch (param->chroma) { case Y4M_CHROMA_422: break; default: mjpeg_error_exit1("must specify chroma '422' with this input"); break; } break; case DATAFORMAT_DV2: #ifndef HAVE_LIBDV mjpeg_error_exit1("DV input was not configured at compile time"); #else el_get_video_frame(jpeg_data, 0, &el); /* FIXME: checking only 0-th frame. */ dv_parse_header(decoder, jpeg_data); switch(decoder->sampling) { case e_dv_sample_420: switch (param->chroma) { case Y4M_UNKNOWN: mjpeg_info("set chroma '420paldv' from input"); param->chroma = Y4M_CHROMA_420PALDV; break; case Y4M_CHROMA_420PALDV: break; case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: mjpeg_warn("4:2:0 chroma should be '420paldv' with this input"); break; case Y4M_CHROMA_422: if(libdv_pal_yv12 == 1 ) mjpeg_error_exit1("must specify 4:2:0 chroma (should be '420paldv') with this input"); break; default: mjpeg_error_exit1("must specify 4:2:0 chroma (should be '420paldv') with this input"); break; } break; case e_dv_sample_411: if (param->chroma != Y4M_CHROMA_411) mjpeg_info("chroma '411' recommended with this input"); switch (param->chroma) { case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: mjpeg_warn("4:2:0 chroma should be '420jpeg' with this input"); break; } break; case e_dv_sample_422: if (param->chroma != Y4M_CHROMA_422) mjpeg_info("chroma '422' recommended with this input"); switch (param->chroma) { case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: mjpeg_warn("4:2:0 chroma should be '420jpeg' with this input"); break; } break; default: break; } #endif break; case DATAFORMAT_MJPG: if (param->chroma != Y4M_CHROMA_422 && el.chroma == Y4M_CHROMA_422) mjpeg_info("chroma '422' recommended with this input"); switch (param->chroma) { case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: mjpeg_warn("4:2:0 chroma should be '420jpeg' with this input"); break; } break; } if (param->chroma == Y4M_UNKNOWN) { mjpeg_info("set default chroma '420jpeg'"); param->chroma = Y4M_CHROMA_420JPEG; } y4m_si_set_chroma(streaminfo, param->chroma); n = y4m_write_stream_header(out_fd, streaminfo); if (n != Y4M_OK) mjpeg_error("Failed to write stream header: %s", y4m_strerr(n)); } #ifdef HAVE_LIBDV void lav_init_dv_decoder() { decoder = dv_decoder_new(0,0,0); decoder->quality = DV_QUALITY_BEST; } #endif mjpegtools-2.1.0/lavtools/png2yuv.c0000644000175000017500000004060611525450335017643 0ustar glowwormglowworm/* png2yuv ======== Converts a collection of PNG images to a YUV4MPEG stream. (see png2yuv -h for help (or have a look at the function "usage")) PNG (Portable Network Graphics) is a lossless 2D image format. See www.libpng.org for more information. Based on rpf2yuv.c. Copyright (C) 1999, 2002 Gernot Ziegler (gz@lysator.liu.se) Copyright (C) 2001, 2004 Matthew Marjanovic (maddog@mir.com) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include "mjpeg_logging.h" #include "mjpeg_types.h" #include "yuv4mpeg.h" #include "mpegconsts.h" #include "subsample.h" #include "colorspace.h" #define DEFAULT_CHROMA_MODE Y4M_CHROMA_420JPEG typedef struct _parameters { char *pngformatstr; uint32_t begin; /**< the video frame start */ int32_t numframes; /**< -1 means: take all frames */ y4m_ratio_t framerate; int interlace; /**< will the YUV4MPEG stream be interlaced? */ int interleave; /**< are the PNG frames field-interleaved? */ int verbose; /**< the verbosity of the program (see mjpeg_logging.h) */ png_uint_32 width; png_uint_32 height; int ss_mode; /**< subsampling mode (based on ssm_id from subsample.h) */ int new_width; /// new MPEG2 width, in case the original one is uneven int new_height; /// new MPEG2 width, in case the original one is uneven } parameters_t; /* * The User Interface parts */ /* usage * Prints a short description of the program, including default values * in: prog: The name of the program */ static void usage(char *prog) { char *h; if (NULL != (h = (char *)strrchr(prog,'/'))) prog = h+1; fprintf(stderr, "usage: %s [ options ]\n" "\n" "where options are ([] shows the defaults):\n" " -v num verbosity (0,1,2) [1]\n" " -b framenum starting frame number [0]\n" " -f framerate framerate for output stream (fps) \n" " -n numframes number of frames to process [-1 = all]\n" " -j {1}%%{2}d{3} Read PNG frames with the name components as follows:\n" " {1} PNG filename prefix (e g rendered_ )\n" " {2} Counting placeholder (like in C, printf, eg 06 ))\n" " -I x interlacing mode: p = none/progressive\n" " t = top-field-first\n" " b = bottom-field-first\n" " -L x interleaving mode: 0 = non-interleaved (two successive\n" " fields per PNG file)\n" " 1 = interleaved fields\n" " -S mode chroma subsampling mode [%s]\n" "\n" "%s pipes a sequence of PNG files to stdout,\n" "making the direct encoding of MPEG files possible under mpeg2enc.\n" "Any 8bit PNG format supported by libpng can be read.\n" "stdout will be filled with the YUV4MPEG movie data stream,\n" "so be prepared to pipe it on to mpeg2enc or to write it into a file.\n" "\n" "\n" "examples:\n" " %s -j in_%%06d.png -f 25 -I p -b 100000 > result.yuv\n" " | combines all the available PNGs that match \n" " in_??????.png, starting with 100000 (in_100000.png, \n" " in_100001.png, etc...) into the uncompressed YUV4MPEG videofile result.yuv\n" " The videofile has 25 frames per second and does not use any interlacing.\n" " %s -Ip -L0 -j abc_%%04d.png | mpeg2enc -f3 -o out.m2v\n" " | combines all the available PNGs that match \n" " abc_??????.png, starting with 0000 (abc_0000.png, \n" " abc_0001.png, etc...) and pipes it to mpeg2enc which encodes\n" " an MPEG2-file called out.m2v out of it\n" "\n", prog, y4m_chroma_keyword(DEFAULT_CHROMA_MODE), prog, prog, prog); } /** parse_commandline * Parses the commandline for the supplied parameters. * in: argc, argv: the classic commandline parameters */ static void parse_commandline(int argc, char ** argv, parameters_t *param) { int c; param->pngformatstr = NULL; param->begin = 0; param->numframes = -1; param->framerate = y4m_fps_UNKNOWN; param->interlace = Y4M_UNKNOWN; param->interleave = -1; param->verbose = 1; param->ss_mode = DEFAULT_CHROMA_MODE; /* parse options */ for (;;) { if (-1 == (c = getopt(argc, argv, "I:hv:L:b:j:n:f:z:S:"))) break; switch (c) { case 'j': param->pngformatstr = strdup(optarg); break; #if 0 case 'z': param->mza_filename = strdup(optarg); param->make_z_alpha = 1; break; #else case 'z': mjpeg_error("Z encoding currently unsupported !\n"); exit(-1); break; #endif case 'S': param->ss_mode = y4m_chroma_parse_keyword(optarg); if (param->ss_mode == Y4M_UNKNOWN) { mjpeg_error_exit1("Unknown subsampling mode option: %s", optarg); } else if (!chroma_sub_implemented(param->ss_mode)) { mjpeg_error_exit1("Unsupported subsampling mode option: %s", optarg); } break; case 'b': param->begin = atol(optarg); break; case 'n': param->numframes = atol(optarg); break; case 'f': param->framerate = mpeg_conform_framerate(atof(optarg)); break; case 'I': switch (optarg[0]) { case 'p': param->interlace = Y4M_ILACE_NONE; break; case 't': param->interlace = Y4M_ILACE_TOP_FIRST; break; case 'b': param->interlace = Y4M_ILACE_BOTTOM_FIRST; break; default: mjpeg_error_exit1 ("-I option requires arg p, t, or b"); } break; case 'L': param->interleave = atoi(optarg); if ((param->interleave != 0) && (param->interleave != 1)) mjpeg_error_exit1 ("-L option requires arg 0 or 1"); break; case 'v': param->verbose = atoi(optarg); if (param->verbose < 0 || param->verbose > 2) mjpeg_error_exit1( "-v option requires arg 0, 1, or 2"); break; case 'h': default: usage(argv[0]); exit(1); } } if (param->pngformatstr == NULL) { mjpeg_error("%s: input format string not specified. (Use -j option.)", argv[0]); usage(argv[0]); exit(1); } if (Y4M_RATIO_EQL(param->framerate, y4m_fps_UNKNOWN)) { mjpeg_error("%s: framerate not specified. (Use -f option)", argv[0]); usage(argv[0]); exit(1); } } /* * The file handling parts */ /** Reads one PNG file. @param process Process the image data (NULL for initial parameter determination) @returns -1 on failure, 1 on sucess @on success returns RGB data in the second, yuv, parameter */ int decode_png(const char *pngname, uint8_t *yuv[], parameters_t *param) { png_structp png_ptr; png_infop info_ptr; FILE *pngfile; /* libpng needs two structs - a png_struct and a png_info, there is no * need to make the third, another png_info, because that is only used * to store data (such as textual information) that can come after the * PNG image. This code only cares about the image. */ info_ptr = NULL; pngfile = NULL; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) mjpeg_error_exit1("%s: Could not allocate PNG read struct !", pngname); /* This needs to be done immediately after creation of the png_struct * because storage allocation failures will longjmp back to here: */ if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, 0); if (pngfile) (void)fclose(pngfile); mjpeg_error("%s: Corrupted PNG file !", pngname); return -1; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); mjpeg_error_exit1("%s: Could not allocate PNG info struct !", pngname); } /* Now open this PNG file, and examine its header to retrieve the * YUV4MPEG info that shall be written */ pngfile = fopen(pngname, "rb"); if (!pngfile) { perror(pngname); png_error(png_ptr, "PNG file open failed"); } png_init_io(png_ptr, pngfile); if (yuv) { png_uint_32 nr, input_height, input_width, output_height, output_width; uint8_t *r, *g, *b; png_bytepp rows; /* The code uses png_read_png to obtain a complete buffered copy of the * PNG file reduced (or expanded) to 8 bit RGB. This is a little wasteful * in the case of a non-interlaced image - the code could work row by * row without buffering the whole image - but the interlaced case is * almost impossible to handle this way so it is better to be simple and * correct. */ # if PNG_LIBPNG_VER >= 10500 && PNG_LIBPNG_VER < 10502 /* There is a bug in 1.5 before 1.5.2 which causes png_read_png to * whine most terribly on interlaced images, this stops it: */ (void)png_set_interlace_handling(png_ptr); # endif png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_STRIP_ALPHA | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_GRAY_TO_RGB /* requires libpng 1.4 or later */, 0); /* And return the separated data to the parameters. */ rows = png_get_rows(png_ptr, info_ptr); /* Since the PNG files for the frames are separate the actual PNG file * that was read could be unrelated - a random width and height. Because * the output may be interleaved the output height may be twice the input * PNG height. Because the MPEG code requires an even width the output * width may be one more than the original frame width. * * For the interleaving the PNG data is smashed into the lower half of * the yuv rows. For the other cases the input data is cropped or * top-lefted as appropriate. */ output_height = param->new_height; input_height = png_get_image_height(png_ptr, info_ptr); if (input_height > output_height) input_height = output_height; output_width = param->new_width; input_width = png_get_image_width(png_ptr, info_ptr); if (input_width > output_width) input_width = output_width; /* Breaking up the RGB data is not hard to do, the separated channels are * simply packed into the three raw yuv arrays with new_width values per * row. */ r = yuv[0]; g = yuv[1]; b = yuv[2]; for (nr=0; nrwidth = png_get_image_width(png_ptr, info_ptr); param->height = png_get_image_height(png_ptr, info_ptr); } /* Successful exit: */ png_destroy_read_struct(&png_ptr, &info_ptr, 0); fclose(pngfile); return 1; } /** init_parse_files * Verifies the PNG input files and prepares YUV4MPEG header information. * @returns 0 on success */ static int init_parse_files(parameters_t *param) { char pngname[PATH_MAX+1]; /* See POSIX 1003.1 section 2.9.5 */ snprintf(pngname, sizeof(pngname), param->pngformatstr, param->begin); mjpeg_debug("Analyzing %s to get the right pic params", pngname); /* The first frame (the param->begin frame) determines the height and * width of the output. Passing NULL instead of yuv (see below) causes * decode_png to fill in param with the image dimensions. */ if (decode_png(pngname, NULL, param) == -1) mjpeg_error_exit1("Reading of %s failed.\n", pngname); mjpeg_info("Image dimensions are %ux%u", param->width, param->height); mjpeg_info("Movie frame rate is: %f frames/second", Y4M_RATIO_DBL(param->framerate)); switch (param->interlace) { case Y4M_ILACE_NONE: mjpeg_info("Non-interlaced/progressive frames."); break; case Y4M_ILACE_BOTTOM_FIRST: mjpeg_info("Interlaced frames, bottom field first."); break; case Y4M_ILACE_TOP_FIRST: mjpeg_info("Interlaced frames, top field first."); break; default: mjpeg_error_exit1("Interlace has not been specified (use -I option)"); break; } if ((param->interlace != Y4M_ILACE_NONE) && (param->interleave == -1)) mjpeg_error_exit1("Interleave has not been specified (use -L option)"); if (!(param->interleave) && (param->interlace != Y4M_ILACE_NONE)) { /* So the height in 'param' might be twice the PNG input height:*/ param->height *= 2; mjpeg_info("Non-interleaved fields (image height doubled)"); } mjpeg_info("Frame size: %u x %u", param->width, param->height); return 0; } static int generate_YUV4MPEG(parameters_t *param) { uint32_t frame; uint8_t *yuv[3]; /* Buffers, initially for R,G,B then Y,Cb,Cr */ y4m_stream_info_t streaminfo; y4m_frame_info_t frameinfo; /* Make the output even, so the output may be one larger than the * original PNG image width. */ param->new_width = param->width + (param->width & 1); param->new_height = param->height + (param->height & 1); mjpeg_info("Now generating YUV4MPEG stream."); y4m_init_stream_info(&streaminfo); y4m_init_frame_info(&frameinfo); y4m_si_set_width(&streaminfo, param->new_width); y4m_si_set_height(&streaminfo, param->new_height); y4m_si_set_interlace(&streaminfo, param->interlace); y4m_si_set_framerate(&streaminfo, param->framerate); y4m_si_set_chroma(&streaminfo, param->ss_mode); yuv[0] = (uint8_t *)malloc(param->new_width * param->new_height * sizeof(yuv[0][0])); yuv[1] = (uint8_t *)malloc(param->new_width * param->new_height * sizeof(yuv[1][0])); yuv[2] = (uint8_t *)malloc(param->new_width * param->new_height * sizeof(yuv[2][0])); y4m_write_stream_header(STDOUT_FILENO, &streaminfo); for (frame = param->begin; (frame < param->numframes + param->begin) || (param->numframes == -1); frame++) { char pngname[PATH_MAX+1]; snprintf(pngname, sizeof(pngname), param->pngformatstr, frame); /* decode_png reads the PNG into the yuv buffers as r,g,b [0..255] * values. */ if (decode_png(pngname, yuv, param) == -1) { mjpeg_info("Read from '%s' failed: %s", pngname, strerror(errno)); if (param->numframes == -1) { mjpeg_info("No more frames. Stopping."); break; /* we are done; leave 'while' loop */ } else { mjpeg_info("Rewriting latest frame instead."); } } else { mjpeg_debug("Converting frame to YUV format."); /* Transform colorspace, then subsample (in place) */ convert_RGB_to_YCbCr(yuv, param->new_height * param->new_width); chroma_subsample(param->ss_mode, yuv, param->new_width, param->new_height); mjpeg_debug("Frame decoded, now writing to output stream."); } mjpeg_debug("Frame decoded, now writing to output stream."); y4m_write_frame(STDOUT_FILENO, &streaminfo, &frameinfo, yuv); } y4m_fini_stream_info(&streaminfo); y4m_fini_frame_info(&frameinfo); free(yuv[0]); free(yuv[1]); free(yuv[2]); return 0; } /* main * in: argc, argv: Classic commandline parameters. * returns: int: 0: success, !0: !success :-) */ int main(int argc, char ** argv) { parameters_t param; y4m_accept_extensions(1); parse_commandline(argc, argv, ¶m); mjpeg_default_handler_verbosity(param.verbose); mjpeg_info("Parsing & checking input files."); if (init_parse_files(¶m)) { mjpeg_error_exit1("* Error processing the PNG input."); } if (generate_YUV4MPEG(¶m)) { mjpeg_error_exit1("* Error processing the input files."); } return 0; } mjpegtools-2.1.0/lavtools/avilib.c0000644000175000017500000031772310321521361017475 0ustar glowwormglowworm/* * avilib.c * * Copyright (C) Thomas Östreich - June 2001 * multiple audio track support Copyright (C) 2002 Thomas Östreich * * Original code: * Copyright (C) 1999 Rainer Johanni * * This file is part of transcode, a video stream processing tool * * transcode is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * transcode is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Make; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #ifndef O_BINARY #define O_BINARY 0 #endif extern int lav_detect_endian(void); #include "avilib.h" #define INFO_LIST // add a new riff chunk after XX MB //#define NEW_RIFF_THRES (1900*1024*1024) #define NEW_RIFF_THRES (1900*1024*1024) //#define NEW_RIFF_THRES (10*1024*1024) // Maximum number of indices per stream #define NR_IXNN_CHUNKS 32 #define DEBUG_ODML #undef DEBUG_ODML /* The following variable indicates the kind of error */ long AVI_errno = 0; #define MAX_INFO_STRLEN 64 static char id_str[MAX_INFO_STRLEN]; #define FRAME_RATE_SCALE 1000000 /******************************************************************* * * * Utilities for writing an AVI File * * * *******************************************************************/ static ssize_t avi_read(int fd, char *buf, size_t len) { ssize_t n = 0; ssize_t r = 0; while (r < len) { n = read (fd, buf + r, len - r); if (n == 0) break; if (n < 0) { if (errno == EINTR) continue; else break; } r += n; } return r; } static ssize_t avi_write (int fd, char *buf, size_t len) { ssize_t n = 0; ssize_t r = 0; while (r < len) { n = write (fd, buf + r, len - r); if (n < 0) return n; r += n; } return r; } /* HEADERBYTES: The number of bytes to reserve for the header */ #define HEADERBYTES 2048 /* AVI_MAX_LEN: The maximum length of an AVI file, we stay a bit below the 2GB limit (Remember: 2*10^9 is smaller than 2 GB) */ #define AVI_MAX_LEN (UINT_MAX-(1<<20)*16-HEADERBYTES) #define PAD_EVEN(x) ( ((x)+1) & ~1 ) /* Copy n into dst as a 4 or 2 byte, little endian number. Should also work on big endian machines */ static void long2str(unsigned char *dst, int32_t n) { dst[0] = (n )&0xff; dst[1] = (n>> 8)&0xff; dst[2] = (n>>16)&0xff; dst[3] = (n>>24)&0xff; } static void short2str(unsigned char *dst, int32_t n) { dst[0] = (n )&0xff; dst[1] = (n>> 8)&0xff; } /* Convert a string of 4 or 2 bytes to a number, also working on big endian machines */ static uint64_t str2ullong(unsigned char *str) { uint64_t r = (str[0] | (str[1]<<8) | (str[2]<<16) | (str[3]<<24)); uint64_t s = (str[4] | (str[5]<<8) | (str[6]<<16) | (str[7]<<24)); return ((s<<32)&0xffffffff00000000ULL)|(r&0xffffffffULL); } static uint32_t str2ulong(unsigned char *str) { return ( str[0] | (str[1]<<8) | (str[2]<<16) | (str[3]<<24) ); } static uint32_t str2ushort(unsigned char *str) { return ( str[0] | (str[1]<<8) ); } // bit 31 denotes a keyframe static uint32_t str2ulong_len (unsigned char *str) { return str2ulong(str) & 0x7fffffff; } // if bit 31 is 0, its a keyframe static uint32_t str2ulong_key (unsigned char *str) { uint32_t c = str2ulong(str); c &= 0x80000000; if (c == 0) return 0x10; else return 0; } /* Calculate audio sample size from number of bits and number of channels. This may have to be adjusted for eg. 12 bits and stereo */ static int avi_sampsize(avi_t *AVI, int j) { int s; s = ((AVI->track[j].a_bits+7)/8)*AVI->track[j].a_chans; // if(s==0) s=1; /* avoid possible zero divisions */ if(s<4) s=4; /* avoid possible zero divisions */ return s; } /* Add a chunk (=tag and data) to the AVI file, returns -1 on write error, 0 on success */ static int avi_add_chunk(avi_t *AVI, unsigned char *tag, unsigned char *data, int length) { unsigned char c[8]; char p=0; /* Copy tag and length int c, so that we need only 1 write system call for these two values */ memcpy(c,tag,4); long2str(c+4,length); /* Output tag, length and data, restore previous position if the write fails */ if( avi_write(AVI->fdes,(char *)c,8) != 8 || avi_write(AVI->fdes,(char *)data,length) != length || avi_write(AVI->fdes,&p,length&1) != (length&1)) // if len is uneven, write a pad byte { lseek(AVI->fdes,AVI->pos,SEEK_SET); AVI_errno = AVI_ERR_WRITE; return -1; } /* Update file position */ AVI->pos += 8 + PAD_EVEN(length); //fprintf(stderr, "pos=%lu %s\n", AVI->pos, tag); return 0; } #define OUTD(n) long2str(ix00+bl,n); bl+=4 #define OUTW(n) ix00[bl] = (n)&0xff; ix00[bl+1] = (n>>8)&0xff; bl+=2 #define OUTC(n) ix00[bl] = (n)&0xff; bl+=1 #define OUTS(s) memcpy(ix00+bl,s,4); bl+=4 // this does the physical writeout of the ix## structure static int avi_ixnn_entry(avi_t *AVI, avistdindex_chunk *ch, avisuperindex_entry *en) { int bl, k; unsigned int max = ch->nEntriesInUse * sizeof (uint32_t) * ch->wLongsPerEntry + 24; // header char *ix00 = malloc (max); char dfcc[5]; memcpy (dfcc, ch->fcc, 4); dfcc[4] = 0; bl = 0; if (en) { en->qwOffset = AVI->pos; en->dwSize = max; //en->dwDuration = ch->nEntriesInUse -1; // NUMBER OF stream ticks == frames for video/samples for audio } #ifdef DEBUG_ODML //printf ("ODML Write %s: Entries %ld size %d \n", dfcc, ch->nEntriesInUse, max); #endif //OUTS(ch->fcc); //OUTD(max); OUTW(ch->wLongsPerEntry); OUTC(ch->bIndexSubType); OUTC(ch->bIndexType); OUTD(ch->nEntriesInUse); OUTS(ch->dwChunkId); OUTD(ch->qwBaseOffset&0xffffffff); OUTD((ch->qwBaseOffset>>32)&0xffffffff); OUTD(ch->dwReserved3); for (k = 0; k < ch->nEntriesInUse; k++) { OUTD(ch->aIndex[k].dwOffset); OUTD(ch->aIndex[k].dwSize); } avi_add_chunk (AVI, ch->fcc, ix00, max); free(ix00); return 0; } #undef OUTS #undef OUTW #undef OUTD #undef OUTC // inits a super index structure including its enclosed stdindex static int avi_init_super_index(avi_t *AVI, unsigned char *idxtag, avisuperindex_chunk **si) { int k; avisuperindex_chunk *sil = NULL; if ((sil = (avisuperindex_chunk *) malloc (sizeof (avisuperindex_chunk))) == NULL) { AVI_errno = AVI_ERR_NO_MEM; return -1; } memset(sil, 0, sizeof (avisuperindex_chunk)); memcpy (sil->fcc, "indx", 4); sil->dwSize = 0; // size of this chunk sil->wLongsPerEntry = 4; sil->bIndexSubType = 0; sil->bIndexType = AVI_INDEX_OF_INDEXES; sil->nEntriesInUse = 0; // none are in use memcpy (sil->dwChunkId, idxtag, 4); memset (sil->dwReserved, 0, sizeof (sil->dwReserved)); // NR_IXNN_CHUNKS == allow 32 indices which means 32 GB files -- arbitrary sil->aIndex = malloc (sil->wLongsPerEntry * NR_IXNN_CHUNKS * sizeof (uint32_t)); if (!sil->aIndex) { AVI_errno = AVI_ERR_NO_MEM; return -1; } memset (sil->aIndex, 0, sil->wLongsPerEntry * NR_IXNN_CHUNKS * sizeof (uint32_t)); sil->stdindex = malloc (NR_IXNN_CHUNKS * sizeof (avistdindex_chunk *)); if (!sil->stdindex) { AVI_errno = AVI_ERR_NO_MEM; return -1; } for (k = 0; k < NR_IXNN_CHUNKS; k++) { sil->stdindex[k] = malloc (sizeof (avistdindex_chunk)); memset(sil->stdindex[k], 0, sizeof (avistdindex_chunk)); // gets rewritten later sil->stdindex[k]->qwBaseOffset = (uint64_t)k * NEW_RIFF_THRES; } *si = sil; return 0; } // fills an alloc'ed stdindex structure and mallocs some entries for the actual chunks static int avi_add_std_index(avi_t *AVI, unsigned char *idxtag, unsigned char *strtag, avistdindex_chunk *stdil) { memcpy (stdil->fcc, idxtag, 4); stdil->dwSize = 4096; stdil->wLongsPerEntry = 2; //sizeof(avistdindex_entry)/sizeof(uint32_t); stdil->bIndexSubType = 0; stdil->bIndexType = AVI_INDEX_OF_CHUNKS; stdil->nEntriesInUse = 0; // cp 00db ChunkId memcpy(stdil->dwChunkId, strtag, 4); //stdil->qwBaseOffset = AVI->video_superindex->aIndex[ cur_std_idx ]->qwOffset; stdil->aIndex = malloc(stdil->dwSize * sizeof (uint32_t) * stdil->wLongsPerEntry); if (!stdil->aIndex) { AVI_errno = AVI_ERR_NO_MEM; return -1; } return 0; } static int avi_add_odml_index_entry_core(avi_t *AVI, long flags, off_t pos, unsigned long len, avistdindex_chunk *si) { int cur_chunk_idx; // put new chunk into index si->nEntriesInUse++; cur_chunk_idx = si->nEntriesInUse-1; // need to fetch more memory if (cur_chunk_idx >= si->dwSize) { si->dwSize += 4096; si->aIndex = realloc ( si->aIndex, si->dwSize * sizeof (uint32_t) * si->wLongsPerEntry); } if(len>AVI->max_len) AVI->max_len=len; // if bit 31 is set, it is NOT a keyframe if (flags != 0x10) { len |= 0x80000000; } si->aIndex [ cur_chunk_idx ].dwSize = len; si->aIndex [ cur_chunk_idx ].dwOffset = pos - si->qwBaseOffset + 8; //printf("ODML: POS: 0x%lX\n", si->aIndex [ cur_chunk_idx ].dwOffset); return 0; } static int avi_add_odml_index_entry(avi_t *AVI, unsigned char *tag, long flags, off_t pos, unsigned long len) { char fcc[5]; int audio = (strchr (tag, 'w')?1:0); int video = !audio; unsigned int cur_std_idx; int audtr; off_t towrite = 0LL; if (video) { if (!AVI->video_superindex) { if (avi_init_super_index(AVI, "ix00", &AVI->video_superindex) < 0) return -1; AVI->video_superindex->nEntriesInUse++; cur_std_idx = AVI->video_superindex->nEntriesInUse-1; if (avi_add_std_index (AVI, "ix00", "00db", AVI->video_superindex->stdindex[ cur_std_idx ]) < 0) return -1; } // init } // video if (audio) { fcc[0] = 'i'; fcc[1] = 'x'; fcc[2] = tag[0]; fcc[3] = tag[1]; fcc[4] = '\0'; if (!AVI->track[AVI->aptr].audio_superindex) { #ifdef DEBUG_ODML printf("ODML: fcc = %s\n", fcc); #endif if (avi_init_super_index(AVI, fcc, &AVI->track[AVI->aptr].audio_superindex) < 0) return -1; AVI->track[AVI->aptr].audio_superindex->nEntriesInUse++; snprintf(fcc, sizeof(fcc), "ix%02d", AVI->aptr+1); if (avi_add_std_index (AVI, fcc, tag, AVI->track[AVI->aptr].audio_superindex->stdindex[ AVI->track[AVI->aptr].audio_superindex->nEntriesInUse - 1 ]) < 0 ) return -1; } // init } towrite = 0; if (AVI->video_superindex) { cur_std_idx = AVI->video_superindex->nEntriesInUse-1; towrite += AVI->video_superindex->stdindex[cur_std_idx]->nEntriesInUse*8 + 4+4+2+1+1+4+4+8+4; if (cur_std_idx == 0) { towrite += AVI->n_idx*16 + 8; towrite += HEADERBYTES; } } for (audtr=0; audtranum; audtr++) { if (AVI->track[audtr].audio_superindex) { cur_std_idx = AVI->track[audtr].audio_superindex->nEntriesInUse-1; towrite += AVI->track[audtr].audio_superindex->stdindex[cur_std_idx]->nEntriesInUse*8 + 4+4+2+1+1+4+4+8+4; } } towrite += len + (len&1) + 8; //printf("ODML: towrite = 0x%llX = %lld\n", towrite, towrite); if (AVI->video_superindex && (off_t)(AVI->pos+towrite) > (off_t)((off_t)NEW_RIFF_THRES*AVI->video_superindex->nEntriesInUse)) { fprintf(stderr, "Adding a new RIFF chunk: %d\n", AVI->video_superindex->nEntriesInUse); // rotate ALL indices AVI->video_superindex->nEntriesInUse++; cur_std_idx = AVI->video_superindex->nEntriesInUse-1; if (AVI->video_superindex->nEntriesInUse > NR_IXNN_CHUNKS) { fprintf (stderr, "Internal error in avilib - redefine NR_IXNN_CHUNKS\n"); fprintf (stderr, "[avilib dump] cur_std_idx=%d NR_IXNN_CHUNKS=%d" "POS=%lld towrite=%lld\n", cur_std_idx,NR_IXNN_CHUNKS, AVI->pos, towrite); return -1; } if (avi_add_std_index (AVI, "ix00", "00db", AVI->video_superindex->stdindex[ cur_std_idx ]) < 0) return -1; for (audtr = 0; audtr < AVI->anum; audtr++) { char aud[5]; if (!AVI->track[audtr].audio_superindex) { // not initialized -> no index continue; } AVI->track[audtr].audio_superindex->nEntriesInUse++; snprintf(fcc, sizeof(fcc), "ix%02d", audtr+1); snprintf(aud, sizeof(aud), "0%01dwb", audtr+1); if (avi_add_std_index (AVI, fcc, aud, AVI->track[audtr].audio_superindex->stdindex[ AVI->track[audtr].audio_superindex->nEntriesInUse - 1 ]) < 0 ) return -1; } // write the new riff; if (cur_std_idx > 0) { // dump the _previous_ == already finished index avi_ixnn_entry (AVI, AVI->video_superindex->stdindex[cur_std_idx - 1], &AVI->video_superindex->aIndex[cur_std_idx - 1]); AVI->video_superindex->aIndex[cur_std_idx - 1].dwDuration = AVI->video_superindex->stdindex[cur_std_idx - 1]->nEntriesInUse - 1; for (audtr = 0; audtr < AVI->anum; audtr++) { if (!AVI->track[audtr].audio_superindex) { // not initialized -> no index continue; } avi_ixnn_entry (AVI, AVI->track[audtr].audio_superindex->stdindex[cur_std_idx - 1], &AVI->track[audtr].audio_superindex->aIndex[cur_std_idx - 1]); AVI->track[audtr].audio_superindex->aIndex[cur_std_idx - 1].dwDuration = AVI->track[audtr].audio_superindex->stdindex[cur_std_idx - 1]->nEntriesInUse - 1; if (AVI->track[audtr].a_fmt == 0x1) { AVI->track[audtr].audio_superindex->aIndex[cur_std_idx - 1].dwDuration *= AVI->track[audtr].a_bits*AVI->track[audtr].a_rate*AVI->track[audtr].a_chans/800; } } // XXX: dump idx1 structure if (cur_std_idx == 1) { avi_add_chunk(AVI, (unsigned char *)"idx1", (unsigned char *)AVI->idx, AVI->n_idx*16); // qwBaseOffset will contain the start of the second riff chunk } // Fix the Offsets later at closing time avi_add_chunk(AVI, (unsigned char *)"RIFF", "AVIXLIST\0\0\0\0movi", 16); AVI->video_superindex->stdindex[ cur_std_idx ]->qwBaseOffset = AVI->pos -16 -8; #ifdef DEBUG_ODML printf("ODML: RIFF No.%02d at Offset 0x%llX\n", cur_std_idx, AVI->pos -16 -8); #endif for (audtr = 0; audtr < AVI->anum; audtr++) { if (AVI->track[audtr].audio_superindex) AVI->track[audtr].audio_superindex->stdindex[ cur_std_idx ]->qwBaseOffset = AVI->pos -16 -8; } // now we can be sure AVI->is_opendml++; } } if (video) { avi_add_odml_index_entry_core(AVI, flags, AVI->pos, len, AVI->video_superindex->stdindex[ AVI->video_superindex->nEntriesInUse-1 ]); AVI->total_frames++; } // video if (audio) { avi_add_odml_index_entry_core(AVI, flags, AVI->pos, len, AVI->track[AVI->aptr].audio_superindex->stdindex[ AVI->track[AVI->aptr].audio_superindex->nEntriesInUse-1 ]); } return 0; } // #undef NR_IXNN_CHUNKS static int avi_add_index_entry(avi_t *AVI, unsigned char *tag, long flags, unsigned long pos, unsigned long len) { void *ptr; if(AVI->n_idx>=AVI->max_idx) { ptr = realloc((void *)AVI->idx,(AVI->max_idx+4096)*16); if(ptr == 0) { AVI_errno = AVI_ERR_NO_MEM; return -1; } AVI->max_idx += 4096; AVI->idx = (unsigned char((*)[16]) ) ptr; } /* Add index entry */ // fprintf(stderr, "INDEX %s %ld %lu %lu\n", tag, flags, pos, len); memcpy(AVI->idx[AVI->n_idx],tag,4); long2str(AVI->idx[AVI->n_idx]+ 4,flags); long2str(AVI->idx[AVI->n_idx]+ 8, pos); long2str(AVI->idx[AVI->n_idx]+12, len); /* Update counter */ AVI->n_idx++; if(len>AVI->max_len) AVI->max_len=len; return 0; } /* Returns 1 if more audio is in that video junk */ int AVI_can_read_audio(avi_t *AVI) { if(AVI->mode==AVI_MODE_WRITE) { return -1; } if(!AVI->video_index) { return -1; } if(!AVI->track[AVI->aptr].audio_index) { return -1; } // is it -1? the last ones got left out --tibit //if (AVI->track[AVI->aptr].audio_posc>=AVI->track[AVI->aptr].audio_chunks-1) { if (AVI->track[AVI->aptr].audio_posc>=AVI->track[AVI->aptr].audio_chunks) { return 0; } if (AVI->video_pos >= AVI->video_frames) return 1; if (AVI->track[AVI->aptr].audio_index[AVI->track[AVI->aptr].audio_posc].pos < AVI->video_index[AVI->video_pos].pos) return 1; else return 0; } /* AVI_open_output_file: Open an AVI File and write a bunch of zero bytes as space for the header. returns a pointer to avi_t on success, a zero pointer on error */ avi_t* AVI_open_output_file(char * filename) { avi_t *AVI; int i; unsigned char AVI_header[HEADERBYTES]; /* Allocate the avi_t struct and zero it */ AVI = (avi_t *) malloc(sizeof(avi_t)); if(AVI==0) { AVI_errno = AVI_ERR_NO_MEM; return 0; } memset((void *)AVI,0,sizeof(avi_t)); /* Since Linux needs a long time when deleting big files, we do not truncate the file when we open it. Instead it is truncated when the AVI file is closed */ AVI->fdes = open(filename, O_RDWR|O_CREAT|O_BINARY, 0664); if (AVI->fdes < 0) { AVI_errno = AVI_ERR_OPEN; free(AVI); return 0; } /* Write out HEADERBYTES bytes, the header will go here when we are finished with writing */ for (i=0;ifdes,(char *)AVI_header,HEADERBYTES); if (i != HEADERBYTES) { close(AVI->fdes); AVI_errno = AVI_ERR_WRITE; free(AVI); return 0; } AVI->pos = HEADERBYTES; AVI->mode = AVI_MODE_WRITE; /* open for writing */ //init AVI->anum = 0; AVI->aptr = 0; return AVI; } void AVI_set_video(avi_t *AVI, int width, int height, double fps, char *compressor) { /* may only be called if file is open for writing */ if(AVI->mode==AVI_MODE_READ) return; AVI->width = width; AVI->height = height; AVI->fps = fps; if(strncmp(compressor, "RGB", 3)==0) { memset(AVI->compressor, 0, 4); } else { memcpy(AVI->compressor,compressor,4); } AVI->compressor[4] = 0; avi_update_header(AVI); } void AVI_set_audio(avi_t *AVI, int channels, long rate, int bits, int format, long mp3rate) { /* may only be called if file is open for writing */ if(AVI->mode==AVI_MODE_READ) return; //inc audio tracks AVI->aptr=AVI->anum; ++AVI->anum; if(AVI->anum > AVI_MAX_TRACKS) { fprintf(stderr, "error - only %d audio tracks supported\n", AVI_MAX_TRACKS); exit(1); } AVI->track[AVI->aptr].a_chans = channels; AVI->track[AVI->aptr].a_rate = rate; AVI->track[AVI->aptr].a_bits = bits; AVI->track[AVI->aptr].a_fmt = format; AVI->track[AVI->aptr].mp3rate = mp3rate; avi_update_header(AVI); } #define OUT4CC(s) \ if(nhb<=HEADERBYTES-4) memcpy(AVI_header+nhb,s,4); nhb += 4 #define OUTLONG(n) \ if(nhb<=HEADERBYTES-4) long2str(AVI_header+nhb,n); nhb += 4 #define OUTSHRT(n) \ if(nhb<=HEADERBYTES-2) { \ AVI_header[nhb ] = (n )&0xff; \ AVI_header[nhb+1] = (n>>8)&0xff; \ } \ nhb += 2 #define OUTCHR(n) \ if(nhb<=HEADERBYTES-1) { \ AVI_header[nhb ] = (n )&0xff; \ } \ nhb += 1 #define OUTMEM(d, s) \ { \ unsigned int s_ = (s); \ if(nhb <= HEADERBYTES-s_) \ memcpy(AVI_header+nhb, (d), s_); \ nhb += s_; \ } //ThOe write preliminary AVI file header: 0 frames, max vid/aud size int avi_update_header(avi_t *AVI) { int njunk, sampsize, hasIndex, ms_per_frame, frate, flag; int movi_len, hdrl_start, strl_start, j; unsigned char AVI_header[HEADERBYTES]; long nhb; unsigned long xd_size, xd_size_align2; //assume max size movi_len = AVI_MAX_LEN - HEADERBYTES + 4; //assume index will be written hasIndex=1; if(AVI->fps < 0.001) { frate=0; ms_per_frame=0; } else { frate = (int) (FRAME_RATE_SCALE*AVI->fps + 0.5); ms_per_frame=(int) (1000000/AVI->fps + 0.5); } /* Prepare the file header */ nhb = 0; /* The RIFF header */ OUT4CC ("RIFF"); OUTLONG(movi_len); // assume max size OUT4CC ("AVI "); /* Start the header list */ OUT4CC ("LIST"); OUTLONG(0); /* Length of list in bytes, don't know yet */ hdrl_start = nhb; /* Store start position */ OUT4CC ("hdrl"); /* The main AVI header */ /* The Flags in AVI File header */ #define AVIF_HASINDEX 0x00000010 /* Index at end of file */ #define AVIF_MUSTUSEINDEX 0x00000020 #define AVIF_ISINTERLEAVED 0x00000100 #define AVIF_TRUSTCKTYPE 0x00000800 /* Use CKType to find key frames */ #define AVIF_WASCAPTUREFILE 0x00010000 #define AVIF_COPYRIGHTED 0x00020000 OUT4CC ("avih"); OUTLONG(56); /* # of bytes to follow */ OUTLONG(ms_per_frame); /* Microseconds per frame */ //ThOe ->0 // OUTLONG(10000000); /* MaxBytesPerSec, I hope this will never be used */ OUTLONG(0); OUTLONG(0); /* PaddingGranularity (whatever that might be) */ /* Other sources call it 'reserved' */ flag = AVIF_ISINTERLEAVED; if(hasIndex) flag |= AVIF_HASINDEX; if(hasIndex && AVI->must_use_index) flag |= AVIF_MUSTUSEINDEX; OUTLONG(flag); /* Flags */ OUTLONG(0); // no frames yet OUTLONG(0); /* InitialFrames */ OUTLONG(AVI->anum+1); OUTLONG(0); /* SuggestedBufferSize */ OUTLONG(AVI->width); /* Width */ OUTLONG(AVI->height); /* Height */ /* MS calls the following 'reserved': */ OUTLONG(0); /* TimeScale: Unit used to measure time */ OUTLONG(0); /* DataRate: Data rate of playback */ OUTLONG(0); /* StartTime: Starting time of AVI data */ OUTLONG(0); /* DataLength: Size of AVI data chunk */ /* Start the video stream list ---------------------------------- */ OUT4CC ("LIST"); OUTLONG(0); /* Length of list in bytes, don't know yet */ strl_start = nhb; /* Store start position */ OUT4CC ("strl"); /* The video stream header */ OUT4CC ("strh"); OUTLONG(56); /* # of bytes to follow */ OUT4CC ("vids"); /* Type */ OUT4CC (AVI->compressor); /* Handler */ OUTLONG(0); /* Flags */ OUTLONG(0); /* Reserved, MS says: wPriority, wLanguage */ OUTLONG(0); /* InitialFrames */ OUTLONG(FRAME_RATE_SCALE); /* Scale */ OUTLONG(frate); /* Rate: Rate/Scale == samples/second */ OUTLONG(0); /* Start */ OUTLONG(0); // no frames yet OUTLONG(0); /* SuggestedBufferSize */ OUTLONG(-1); /* Quality */ OUTLONG(0); /* SampleSize */ OUTLONG(0); /* Frame */ OUTLONG(0); /* Frame */ // OUTLONG(0); /* Frame */ //OUTLONG(0); /* Frame */ /* The video stream format */ xd_size = AVI->extradata_size; xd_size_align2 = (AVI->extradata_size+1) & ~1; OUT4CC ("strf"); OUTLONG(40 + xd_size_align2);/* # of bytes to follow */ OUTLONG(40 + xd_size); /* Size */ OUTLONG(AVI->width); /* Width */ OUTLONG(AVI->height); /* Height */ OUTSHRT(1); OUTSHRT(24); /* Planes, Count */ OUT4CC (AVI->compressor); /* Compression */ // ThOe (*3) OUTLONG(AVI->width*AVI->height*3); /* SizeImage (in bytes?) */ OUTLONG(0); /* XPelsPerMeter */ OUTLONG(0); /* YPelsPerMeter */ OUTLONG(0); /* ClrUsed: Number of colors used */ OUTLONG(0); /* ClrImportant: Number of colors important */ // write extradata if (xd_size > 0 && AVI->extradata) { OUTMEM(AVI->extradata, xd_size); if (xd_size != xd_size_align2) { OUTCHR(0); } } /* Finish stream list, i.e. put number of bytes in the list to proper pos */ long2str(AVI_header+strl_start-4,nhb-strl_start); /* Start the audio stream list ---------------------------------- */ for(j=0; janum; ++j) { sampsize = avi_sampsize(AVI, j); OUT4CC ("LIST"); OUTLONG(0); /* Length of list in bytes, don't know yet */ strl_start = nhb; /* Store start position */ OUT4CC ("strl"); /* The audio stream header */ OUT4CC ("strh"); OUTLONG(56); /* # of bytes to follow */ OUT4CC ("auds"); // ----------- // ThOe OUTLONG(0); /* Format (Optionally) */ // ----------- OUTLONG(0); /* Flags */ OUTLONG(0); /* Reserved, MS says: wPriority, wLanguage */ OUTLONG(0); /* InitialFrames */ // ThOe /4 OUTLONG(sampsize/4); /* Scale */ OUTLONG(1000*AVI->track[j].mp3rate/8); OUTLONG(0); /* Start */ OUTLONG(4*AVI->track[j].audio_bytes/sampsize); /* Length */ OUTLONG(0); /* SuggestedBufferSize */ OUTLONG(-1); /* Quality */ // ThOe /4 OUTLONG(sampsize/4); /* SampleSize */ OUTLONG(0); /* Frame */ OUTLONG(0); /* Frame */ // OUTLONG(0); /* Frame */ //OUTLONG(0); /* Frame */ /* The audio stream format */ OUT4CC ("strf"); OUTLONG(16); /* # of bytes to follow */ OUTSHRT(AVI->track[j].a_fmt); /* Format */ OUTSHRT(AVI->track[j].a_chans); /* Number of channels */ OUTLONG(AVI->track[j].a_rate); /* SamplesPerSec */ // ThOe OUTLONG(1000*AVI->track[j].mp3rate/8); //ThOe (/4) OUTSHRT(sampsize/4); /* BlockAlign */ OUTSHRT(AVI->track[j].a_bits); /* BitsPerSample */ /* Finish stream list, i.e. put number of bytes in the list to proper pos */ long2str(AVI_header+strl_start-4,nhb-strl_start); } /* Finish header list */ long2str(AVI_header+hdrl_start-4,nhb-hdrl_start); /* Calculate the needed amount of junk bytes, output junk */ njunk = HEADERBYTES - nhb - 8 - 12; /* Safety first: if njunk <= 0, somebody has played with HEADERBYTES without knowing what (s)he did. This is a fatal error */ if(njunk<=0) { fprintf(stderr,"AVI_close_output_file: # of header bytes too small\n"); exit(1); } OUT4CC ("JUNK"); OUTLONG(njunk); memset(AVI_header+nhb,0,njunk); nhb += njunk; /* Start the movi list */ OUT4CC ("LIST"); OUTLONG(movi_len); /* Length of list in bytes */ OUT4CC ("movi"); /* Output the header, truncate the file to the number of bytes actually written, report an error if someting goes wrong */ if ( lseek(AVI->fdes,0,SEEK_SET)<0 || avi_write(AVI->fdes,(char *)AVI_header,HEADERBYTES)!=HEADERBYTES || lseek(AVI->fdes,AVI->pos,SEEK_SET)<0) { AVI_errno = AVI_ERR_CLOSE; return -1; } return 0; } static int valid_info_tag(char *c) { if (!strncmp(c, "IARL", 4)) return 1; else if (!strncmp(c, "IART", 4)) return 1; else if (!strncmp(c, "ICMS", 4)) return 1; else if (!strncmp(c, "ICMT", 4)) return 1; else if (!strncmp(c, "ICOP", 4)) return 1; else if (!strncmp(c, "ICRD", 4)) return 1; else if (!strncmp(c, "ICRP", 4)) return 1; else if (!strncmp(c, "IDIM", 4)) return 1; else if (!strncmp(c, "IDPI", 4)) return 1; else if (!strncmp(c, "IENG", 4)) return 1; else if (!strncmp(c, "IGNR", 4)) return 1; else if (!strncmp(c, "IKEY", 4)) return 1; else if (!strncmp(c, "ILGT", 4)) return 1; else if (!strncmp(c, "IMED", 4)) return 1; else if (!strncmp(c, "INAM", 4)) return 1; else if (!strncmp(c, "IPLT", 4)) return 1; else if (!strncmp(c, "IPRD", 4)) return 1; else if (!strncmp(c, "ISBJ", 4)) return 1; else if (!strncmp(c, "ISHP", 4)) return 1; else if (!strncmp(c, "ISRC", 4)) return 1; else if (!strncmp(c, "ISRF", 4)) return 1; else if (!strncmp(c, "ITCH", 4)) return 1; else return 0; return 0; } // see ../docs/avi_comments.txt // returns the length of written stream (-1 on error) static int avi_parse_comments (int fd, char *buf, int space_left) { int len=0, readlen=0, k; char *data, *c, *d; struct stat st; // safety checks if (fd<=0 || !buf || space_left<=0) return -1; memset (buf, 0, space_left); if (fstat (fd, &st) == -1) { perror ("stat"); return -1; } if ( !(data = malloc(st.st_size*sizeof(char)+1)) ) { fprintf(stderr, "malloc failed\n"); return -1; } readlen = avi_read ( fd, data, st.st_size); //printf("Read %d bytes from %d\n", readlen, fd); c = data; space_left--; while (len < space_left) { if ( !c || *c == '\0') break; // eof; else if (*c == '#') { // comment, ignore c = strchr(c, '\n')+1; } else if (*c == '\n') { // empty, ignore c++; } else if (*c == 'I') { // do not write ISFT -- this is written by transcode // and important for debugging. if (!valid_info_tag(c)) { // skip this line while (c && *c && *c != '\n' ) { c++; } continue; } // set d after TAG d = c+4; // find first non-blank (!space or !TAB) while ( d && *d && (*d == ' ' || *d == ' ')) ++d; if (!d) break; // TAG without argument is fine but ignored if (*d == '\n' || *d == '\r') { c = d+1; if (*c == '\n') ++c; continue; } k = 0; while (d[k] != '\r' && d[k] != '\n' && d[k] != '\0') ++k; if (k>=space_left) return len; // write TAG memcpy(buf+len,c,4); len += 4; // write length + '\0' long2str(buf+len, k+1); len += 4; // write comment string memcpy (buf+len, d, k); // must be null terminated *(buf+len+k+1) = '\0'; // PAD if ((k+1)&1) { k++; *(buf+len+k+1) = '\0'; } len += k+1; // advance c while (*c != '\n' && *c != '\0') ++c; if (*c != '\0') ++c; else break; } else { // ignore junk lines while (c && *c && *c != '\n' ) { if (*c == ' ' || *c == ' ') { c++; break; } c++; } if (!c) break; } } free(data); return len; } //SLM #ifndef S_IRUSR #define S_IRWXU 00700 /* read, write, execute: owner */ #define S_IRUSR 00400 /* read permission: owner */ #define S_IWUSR 00200 /* write permission: owner */ #define S_IXUSR 00100 /* execute permission: owner */ #define S_IRWXG 00070 /* read, write, execute: group */ #define S_IRGRP 00040 /* read permission: group */ #define S_IWGRP 00020 /* write permission: group */ #define S_IXGRP 00010 /* execute permission: group */ #define S_IRWXO 00007 /* read, write, execute: other */ #define S_IROTH 00004 /* read permission: other */ #define S_IWOTH 00002 /* write permission: other */ #define S_IXOTH 00001 /* execute permission: other */ #endif /* Write the header of an AVI file and close it. returns 0 on success, -1 on write error. */ static int avi_close_output_file(avi_t *AVI) { int ret, njunk, sampsize, hasIndex, ms_per_frame, frate, idxerror, flag; unsigned long movi_len; int hdrl_start, strl_start, j; unsigned char AVI_header[HEADERBYTES]; long nhb; unsigned long xd_size, xd_size_align2; #ifdef INFO_LIST long info_len; long id_len, real_id_len; long info_start_pos; // time_t calptr; #endif /* Calculate length of movi list */ // dump the rest of the index if (AVI->is_opendml) { int cur_std_idx = AVI->video_superindex->nEntriesInUse-1; int audtr; #ifdef DEBUG_ODML printf("ODML dump the rest indices\n"); #endif avi_ixnn_entry (AVI, AVI->video_superindex->stdindex[cur_std_idx], &AVI->video_superindex->aIndex[cur_std_idx]); AVI->video_superindex->aIndex[cur_std_idx].dwDuration = AVI->video_superindex->stdindex[cur_std_idx]->nEntriesInUse - 1; for (audtr = 0; audtr < AVI->anum; audtr++) { if (!AVI->track[audtr].audio_superindex) { // not initialized -> no index continue; } avi_ixnn_entry (AVI, AVI->track[audtr].audio_superindex->stdindex[cur_std_idx], &AVI->track[audtr].audio_superindex->aIndex[cur_std_idx]); AVI->track[audtr].audio_superindex->aIndex[cur_std_idx].dwDuration = AVI->track[audtr].audio_superindex->stdindex[cur_std_idx]->nEntriesInUse - 1; if (AVI->track[audtr].a_fmt == 0x1) { AVI->track[audtr].audio_superindex->aIndex[cur_std_idx].dwDuration *= AVI->track[audtr].a_bits*AVI->track[audtr].a_rate*AVI->track[audtr].a_chans/800; } } // The AVI->video_superindex->nEntriesInUse contains the offset AVI->video_superindex->stdindex[ cur_std_idx+1 ]->qwBaseOffset = AVI->pos; } if (AVI->is_opendml) { // Correct! movi_len = AVI->video_superindex->stdindex[ 1 ]->qwBaseOffset - HEADERBYTES+4 - AVI->n_idx*16 - 8; } else { movi_len = AVI->pos - HEADERBYTES + 4; } /* Try to ouput the index entries. This may fail e.g. if no space is left on device. We will report this as an error, but we still try to write the header correctly (so that the file still may be readable in the most cases */ idxerror = 0; hasIndex = 1; if (!AVI->is_opendml) { // fprintf(stderr, "pos=%lu, index_len=%ld \n", AVI->pos, AVI->n_idx*16); ret = avi_add_chunk(AVI, (unsigned char *)"idx1", (unsigned char *)AVI->idx, AVI->n_idx*16); hasIndex = (ret==0); //fprintf(stderr, "pos=%lu, index_len=%d\n", AVI->pos, hasIndex); if(ret) { idxerror = 1; AVI_errno = AVI_ERR_WRITE_INDEX; } } /* Calculate Microseconds per frame */ if(AVI->fps < 0.001) { frate=0; ms_per_frame=0; } else { frate = (int) (FRAME_RATE_SCALE*AVI->fps + 0.5); ms_per_frame=(int) (1000000/AVI->fps + 0.5); } /* Prepare the file header */ nhb = 0; /* The RIFF header */ OUT4CC ("RIFF"); if (AVI->is_opendml) { OUTLONG(AVI->video_superindex->stdindex[ 1 ]->qwBaseOffset - 8); /* # of bytes to follow */ } else { OUTLONG(AVI->pos - 8); /* # of bytes to follow */ } OUT4CC ("AVI "); /* Start the header list */ OUT4CC ("LIST"); OUTLONG(0); /* Length of list in bytes, don't know yet */ hdrl_start = nhb; /* Store start position */ OUT4CC ("hdrl"); /* The main AVI header */ /* The Flags in AVI File header */ #define AVIF_HASINDEX 0x00000010 /* Index at end of file */ #define AVIF_MUSTUSEINDEX 0x00000020 #define AVIF_ISINTERLEAVED 0x00000100 #define AVIF_TRUSTCKTYPE 0x00000800 /* Use CKType to find key frames */ #define AVIF_WASCAPTUREFILE 0x00010000 #define AVIF_COPYRIGHTED 0x00020000 OUT4CC ("avih"); OUTLONG(56); /* # of bytes to follow */ OUTLONG(ms_per_frame); /* Microseconds per frame */ //ThOe ->0 // OUTLONG(10000000); /* MaxBytesPerSec, I hope this will never be used */ OUTLONG(0); OUTLONG(0); /* PaddingGranularity (whatever that might be) */ /* Other sources call it 'reserved' */ flag = AVIF_ISINTERLEAVED; if(hasIndex) flag |= AVIF_HASINDEX; if(hasIndex && AVI->must_use_index) flag |= AVIF_MUSTUSEINDEX; OUTLONG(flag); /* Flags */ OUTLONG(AVI->video_frames); /* TotalFrames */ OUTLONG(0); /* InitialFrames */ OUTLONG(AVI->anum+1); // if (AVI->track[0].audio_bytes) // { OUTLONG(2); } /* Streams */ // else // { OUTLONG(1); } /* Streams */ OUTLONG(0); /* SuggestedBufferSize */ OUTLONG(AVI->width); /* Width */ OUTLONG(AVI->height); /* Height */ /* MS calls the following 'reserved': */ OUTLONG(0); /* TimeScale: Unit used to measure time */ OUTLONG(0); /* DataRate: Data rate of playback */ OUTLONG(0); /* StartTime: Starting time of AVI data */ OUTLONG(0); /* DataLength: Size of AVI data chunk */ /* Start the video stream list ---------------------------------- */ OUT4CC ("LIST"); OUTLONG(0); /* Length of list in bytes, don't know yet */ strl_start = nhb; /* Store start position */ OUT4CC ("strl"); /* The video stream header */ OUT4CC ("strh"); OUTLONG(56); /* # of bytes to follow */ OUT4CC ("vids"); /* Type */ OUT4CC (AVI->compressor); /* Handler */ OUTLONG(0); /* Flags */ OUTLONG(0); /* Reserved, MS says: wPriority, wLanguage */ OUTLONG(0); /* InitialFrames */ OUTLONG(FRAME_RATE_SCALE); /* Scale */ OUTLONG(frate); /* Rate: Rate/Scale == samples/second */ OUTLONG(0); /* Start */ OUTLONG(AVI->video_frames); /* Length */ OUTLONG(AVI->max_len); /* SuggestedBufferSize */ OUTLONG(0); /* Quality */ OUTLONG(0); /* SampleSize */ OUTLONG(0); /* Frame */ OUTLONG(0); /* Frame */ //OUTLONG(0); /* Frame */ //OUTLONG(0); /* Frame */ /* The video stream format */ xd_size = AVI->extradata_size; xd_size_align2 = (AVI->extradata_size+1) & ~1; OUT4CC ("strf"); OUTLONG(40 + xd_size_align2);/* # of bytes to follow */ OUTLONG(40 + xd_size); /* Size */ OUTLONG(AVI->width); /* Width */ OUTLONG(AVI->height); /* Height */ OUTSHRT(1); OUTSHRT(24); /* Planes, Count */ OUT4CC (AVI->compressor); /* Compression */ // ThOe (*3) OUTLONG(AVI->width*AVI->height*3); /* SizeImage (in bytes?) */ OUTLONG(0); /* XPelsPerMeter */ OUTLONG(0); /* YPelsPerMeter */ OUTLONG(0); /* ClrUsed: Number of colors used */ OUTLONG(0); /* ClrImportant: Number of colors important */ // write extradata if present if (xd_size > 0 && AVI->extradata) { OUTMEM(AVI->extradata, xd_size); if (xd_size != xd_size_align2) { OUTCHR(0); } } // dump index of indices for audio if (AVI->is_opendml) { int k; OUT4CC(AVI->video_superindex->fcc); OUTLONG(2+1+1+4+4+3*4 + AVI->video_superindex->nEntriesInUse * (8+4+4)); OUTSHRT(AVI->video_superindex->wLongsPerEntry); OUTCHR(AVI->video_superindex->bIndexSubType); OUTCHR(AVI->video_superindex->bIndexType); OUTLONG(AVI->video_superindex->nEntriesInUse); OUT4CC(AVI->video_superindex->dwChunkId); OUTLONG(0); OUTLONG(0); OUTLONG(0); for (k = 0; k < AVI->video_superindex->nEntriesInUse; k++) { uint32_t r = (AVI->video_superindex->aIndex[k].qwOffset >> 32) & 0xffffffff; uint32_t s = (AVI->video_superindex->aIndex[k].qwOffset) & 0xffffffff; printf("VID NrEntries %d/%ld (%c%c%c%c) |0x%llX|%ld|%ld|\n", k, (unsigned long)AVI->video_superindex->nEntriesInUse, AVI->video_superindex->dwChunkId[0], AVI->video_superindex->dwChunkId[1], AVI->video_superindex->dwChunkId[2], AVI->video_superindex->dwChunkId[3], (unsigned long long)AVI->video_superindex->aIndex[k].qwOffset, (unsigned long)AVI->video_superindex->aIndex[k].dwSize, (unsigned long)AVI->video_superindex->aIndex[k].dwDuration ); /* */ OUTLONG(s); OUTLONG(r); OUTLONG(AVI->video_superindex->aIndex[k].dwSize); OUTLONG(AVI->video_superindex->aIndex[k].dwDuration); } } /* Finish stream list, i.e. put number of bytes in the list to proper pos */ long2str(AVI_header+strl_start-4,nhb-strl_start); /* Start the audio stream list ---------------------------------- */ for(j=0; janum; ++j) { //if (AVI->track[j].a_chans && AVI->track[j].audio_bytes) { unsigned long nBlockAlign = 0; unsigned long avgbsec = 0; unsigned long scalerate = 0; sampsize = avi_sampsize(AVI, j); sampsize = AVI->track[j].a_fmt==0x1?sampsize*4:sampsize; nBlockAlign = (AVI->track[j].a_rate<32000)?576:1152; /* printf("XXX sampsize (%d) block (%ld) rate (%ld) audio_bytes (%ld) mp3rate(%ld,%ld)\n", sampsize, nBlockAlign, AVI->track[j].a_rate, (long int)AVI->track[j].audio_bytes, 1000*AVI->track[j].mp3rate/8, AVI->track[j].mp3rate); */ if (AVI->track[j].a_fmt==0x1) { sampsize = (AVI->track[j].a_chans<2)?sampsize/2:sampsize; avgbsec = AVI->track[j].a_rate*sampsize/4; scalerate = AVI->track[j].a_rate*sampsize/4; } else { avgbsec = 1000*AVI->track[j].mp3rate/8; scalerate = 1000*AVI->track[j].mp3rate/8; } OUT4CC ("LIST"); OUTLONG(0); /* Length of list in bytes, don't know yet */ strl_start = nhb; /* Store start position */ OUT4CC ("strl"); /* The audio stream header */ OUT4CC ("strh"); OUTLONG(56); /* # of bytes to follow */ OUT4CC ("auds"); // ----------- // ThOe OUTLONG(0); /* Format (Optionally) */ // ----------- OUTLONG(0); /* Flags */ OUTLONG(0); /* Reserved, MS says: wPriority, wLanguage */ OUTLONG(0); /* InitialFrames */ // VBR if (AVI->track[j].a_fmt == 0x55 && AVI->track[j].a_vbr) { OUTLONG(nBlockAlign); /* Scale */ OUTLONG(AVI->track[j].a_rate); /* Rate */ OUTLONG(0); /* Start */ OUTLONG(AVI->track[j].audio_chunks); /* Length */ OUTLONG(0); /* SuggestedBufferSize */ OUTLONG(0); /* Quality */ OUTLONG(0); /* SampleSize */ OUTLONG(0); /* Frame */ OUTLONG(0); /* Frame */ } else { OUTLONG(sampsize/4); /* Scale */ OUTLONG(scalerate); /* Rate */ OUTLONG(0); /* Start */ OUTLONG(4*AVI->track[j].audio_bytes/sampsize); /* Length */ OUTLONG(0); /* SuggestedBufferSize */ OUTLONG(0xffffffff); /* Quality */ OUTLONG(sampsize/4); /* SampleSize */ OUTLONG(0); /* Frame */ OUTLONG(0); /* Frame */ } /* The audio stream format */ OUT4CC ("strf"); if (AVI->track[j].a_fmt == 0x55 && AVI->track[j].a_vbr) { OUTLONG(30); /* # of bytes to follow */ // mplayer writes 28 OUTSHRT(AVI->track[j].a_fmt); /* Format */ // 2 OUTSHRT(AVI->track[j].a_chans); /* Number of channels */ // 2 OUTLONG(AVI->track[j].a_rate); /* SamplesPerSec */ // 4 //ThOe/tibit OUTLONG(1000*AVI->track[j].mp3rate/8); /* maybe we should write an avg. */ // 4 OUTSHRT(nBlockAlign); /* BlockAlign */ // 2 OUTSHRT(AVI->track[j].a_bits); /* BitsPerSample */ // 2 OUTSHRT(12); /* cbSize */ // 2 OUTSHRT(1); /* wID */ // 2 OUTLONG(2); /* fdwFlags */ // 4 OUTSHRT(nBlockAlign); /* nBlockSize */ // 2 OUTSHRT(1); /* nFramesPerBlock */ // 2 OUTSHRT(0); /* nCodecDelay */ // 2 } else if (AVI->track[j].a_fmt == 0x55 && !AVI->track[j].a_vbr) { OUTLONG(30); /* # of bytes to follow */ OUTSHRT(AVI->track[j].a_fmt); /* Format */ OUTSHRT(AVI->track[j].a_chans); /* Number of channels */ OUTLONG(AVI->track[j].a_rate); /* SamplesPerSec */ //ThOe/tibit OUTLONG(1000*AVI->track[j].mp3rate/8); OUTSHRT(sampsize/4); /* BlockAlign */ OUTSHRT(AVI->track[j].a_bits); /* BitsPerSample */ OUTSHRT(12); /* cbSize */ OUTSHRT(1); /* wID */ OUTLONG(2); /* fdwFlags */ OUTSHRT(nBlockAlign); /* nBlockSize */ OUTSHRT(1); /* nFramesPerBlock */ OUTSHRT(0); /* nCodecDelay */ } else { OUTLONG(18); /* # of bytes to follow */ OUTSHRT(AVI->track[j].a_fmt); /* Format */ OUTSHRT(AVI->track[j].a_chans); /* Number of channels */ OUTLONG(AVI->track[j].a_rate); /* SamplesPerSec */ //ThOe/tibit OUTLONG(avgbsec); /* Avg bytes/sec */ OUTSHRT(sampsize/4); /* BlockAlign */ OUTSHRT(AVI->track[j].a_bits); /* BitsPerSample */ OUTSHRT(0); /* cbSize */ } } if (AVI->is_opendml) { int k ; if (!AVI->track[j].audio_superindex) { // not initialized -> no index continue; } OUT4CC(AVI->track[j].audio_superindex->fcc); /* "indx" */ OUTLONG(2+1+1+4+4+3*4 + AVI->track[j].audio_superindex->nEntriesInUse * (8+4+4)); OUTSHRT(AVI->track[j].audio_superindex->wLongsPerEntry); OUTCHR(AVI->track[j].audio_superindex->bIndexSubType); OUTCHR(AVI->track[j].audio_superindex->bIndexType); OUTLONG(AVI->track[j].audio_superindex->nEntriesInUse); OUT4CC(AVI->track[j].audio_superindex->dwChunkId); OUTLONG(0); OUTLONG(0); OUTLONG(0); for (k = 0; k < AVI->track[j].audio_superindex->nEntriesInUse; k++) { uint32_t r = (AVI->track[j].audio_superindex->aIndex[k].qwOffset >> 32) & 0xffffffff; uint32_t s = (AVI->track[j].audio_superindex->aIndex[k].qwOffset) & 0xffffffff; /* printf("AUD[%d] NrEntries %d/%ld (%c%c%c%c) |0x%llX|%ld|%ld| \n", j, k, AVI->track[j].audio_superindex->nEntriesInUse, AVI->track[j].audio_superindex->dwChunkId[0], AVI->track[j].audio_superindex->dwChunkId[1], AVI->track[j].audio_superindex->dwChunkId[2], AVI->track[j].audio_superindex->dwChunkId[3], AVI->track[j].audio_superindex->aIndex[k].qwOffset, AVI->track[j].audio_superindex->aIndex[k].dwSize, AVI->track[j].audio_superindex->aIndex[k].dwDuration ); */ OUTLONG(s); OUTLONG(r); OUTLONG(AVI->track[j].audio_superindex->aIndex[k].dwSize); OUTLONG(AVI->track[j].audio_superindex->aIndex[k].dwDuration); } } /* Finish stream list, i.e. put number of bytes in the list to proper pos */ long2str(AVI_header+strl_start-4,nhb-strl_start); } if (AVI->is_opendml) { OUT4CC("LIST"); OUTLONG(16); OUT4CC("odml"); OUT4CC("dmlh"); OUTLONG(4); OUTLONG(AVI->total_frames); } /* Finish header list */ long2str(AVI_header+hdrl_start-4,nhb-hdrl_start); // add INFO list --- (0.6.0pre4) #ifdef INFO_LIST OUT4CC ("LIST"); info_start_pos = nhb; info_len = MAX_INFO_STRLEN + 12; OUTLONG(info_len); // rewritten later OUT4CC ("INFO"); OUT4CC ("ISFT"); //OUTLONG(MAX_INFO_STRLEN); memset(id_str, 0, MAX_INFO_STRLEN); snprintf(id_str, sizeof(id_str), "%s-%s", PACKAGE, VERSION); real_id_len = id_len = strlen(id_str)+1; if (id_len&1) id_len++; OUTLONG(real_id_len); memset(AVI_header+nhb, 0, id_len); memcpy(AVI_header+nhb, id_str, id_len); nhb += id_len; info_len = avi_parse_comments (AVI->comment_fd, AVI_header+nhb, HEADERBYTES - nhb - 8 - 12); if (info_len <= 0) info_len=0; // write correct len long2str(AVI_header+info_start_pos, info_len + id_len + 4+4+4); nhb += info_len; // OUT4CC ("ICMT"); // OUTLONG(MAX_INFO_STRLEN); // calptr=time(NULL); // snprintf(id_str, sizeof(id_str), "\t%s %s", ctime(&calptr), ""); // memset(AVI_header+nhb, 0, MAX_INFO_STRLEN); // memcpy(AVI_header+nhb, id_str, 25); // nhb += MAX_INFO_STRLEN; #endif // ---------------------------- /* Calculate the needed amount of junk bytes, output junk */ njunk = HEADERBYTES - nhb - 8 - 12; /* Safety first: if njunk <= 0, somebody has played with HEADERBYTES without knowing what (s)he did. This is a fatal error */ if(njunk<=0) { fprintf(stderr,"AVI_close_output_file: # of header bytes too small\n"); exit(1); } OUT4CC ("JUNK"); OUTLONG(njunk); memset(AVI_header+nhb,0,njunk); nhb += njunk; /* Start the movi list */ OUT4CC ("LIST"); OUTLONG(movi_len); /* Length of list in bytes */ OUT4CC ("movi"); /* Output the header, truncate the file to the number of bytes actually written, report an error if someting goes wrong */ if ( lseek(AVI->fdes,0,SEEK_SET)<0 || avi_write(AVI->fdes,(char *)AVI_header,HEADERBYTES)!=HEADERBYTES || ftruncate(AVI->fdes,AVI->pos)<0 ) { AVI_errno = AVI_ERR_CLOSE; return -1; } // Fix up the empty additional RIFF and LIST chunks if (AVI->is_opendml) { int k = 0; char f[4]; unsigned int len; for (k=1; kvideo_superindex->nEntriesInUse; k++) { // the len of the RIFF Chunk lseek(AVI->fdes, AVI->video_superindex->stdindex[k]->qwBaseOffset+4, SEEK_SET); len = AVI->video_superindex->stdindex[k+1]->qwBaseOffset - AVI->video_superindex->stdindex[k]->qwBaseOffset - 8; long2str(f, len); avi_write(AVI->fdes, f, 4); // len of the LIST/movi chunk lseek(AVI->fdes, 8, SEEK_CUR); len -= 12; long2str(f, len); avi_write(AVI->fdes, f, 4); } } if(idxerror) return -1; return 0; } /* AVI_write_data: Add video or audio data to the file; Return values: 0 No error; -1 Error, AVI_errno is set appropriatly; */ static int avi_write_data(avi_t *AVI, char *data, unsigned long length, int audio, int keyframe) { int n = 0; unsigned char astr[5]; // transcode core itself checks for the size -- unneeded and // does harm to xvid 2pass encodes where the first pass can get // _very_ large -- tibit. #if 0 /* Check for maximum file length */ if ( (AVI->pos + 8 + length + 8 + (AVI->n_idx+1)*16) > AVI_MAX_LEN ) { AVI_errno = AVI_ERR_SIZELIM; return -1; } #endif /* Add index entry */ //set tag for current audio track snprintf((char *)astr, sizeof(astr), "0%1dwb", (int)(AVI->aptr+1)); if(audio) { if (!AVI->is_opendml) n = avi_add_index_entry(AVI,astr,0x10,AVI->pos,length); n += avi_add_odml_index_entry(AVI,astr,0x10,AVI->pos,length); } else { if (!AVI->is_opendml) n = avi_add_index_entry(AVI,(unsigned char *)"00db",((keyframe)?0x10:0x0),AVI->pos,length); n += avi_add_odml_index_entry(AVI,(unsigned char *)"00db",((keyframe)?0x10:0x0),AVI->pos,length); } if(n) return -1; /* Output tag and data */ if(audio) n = avi_add_chunk(AVI,(unsigned char *)astr,data,length); else n = avi_add_chunk(AVI,(unsigned char *)"00db",data,length); if (n) return -1; return 0; } int AVI_write_frame(avi_t *AVI, char *data, long bytes, int keyframe) { off_t pos; if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } pos = AVI->pos; if(avi_write_data(AVI,data,bytes,0,keyframe)) return -1; AVI->last_pos = pos; AVI->last_len = bytes; AVI->video_frames++; return 0; } int AVI_dup_frame(avi_t *AVI) { if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } if(AVI->last_pos==0) return 0; /* No previous real frame */ if(avi_add_index_entry(AVI,(unsigned char *)"00db",0x10,AVI->last_pos,AVI->last_len)) return -1; AVI->video_frames++; AVI->must_use_index = 1; return 0; } int AVI_write_audio(avi_t *AVI, char *data, long bytes) { if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } if( avi_write_data(AVI,data,bytes,1,0) ) return -1; AVI->track[AVI->aptr].audio_bytes += bytes; AVI->track[AVI->aptr].audio_chunks++; return 0; } int AVI_append_audio(avi_t *AVI, char *data, long bytes) { // won't work for >2gb long i, length, pos; unsigned char c[4]; if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } // update last index entry: --AVI->n_idx; length = str2ulong(AVI->idx[AVI->n_idx]+12); pos = str2ulong(AVI->idx[AVI->n_idx]+8); //update; long2str(AVI->idx[AVI->n_idx]+12,length+bytes); ++AVI->n_idx; AVI->track[AVI->aptr].audio_bytes += bytes; //update chunk header lseek(AVI->fdes, pos+4, SEEK_SET); long2str(c, length+bytes); avi_write(AVI->fdes, (char *)c, 4); lseek(AVI->fdes, pos+8+length, SEEK_SET); i=PAD_EVEN(length + bytes); bytes = i - length; avi_write(AVI->fdes, data, bytes); AVI->pos = pos + 8 + i; return 0; } long AVI_bytes_remain(avi_t *AVI) { if(AVI->mode==AVI_MODE_READ) return 0; return ( AVI_MAX_LEN - (AVI->pos + 8 + 16*AVI->n_idx)); } long AVI_bytes_written(avi_t *AVI) { if(AVI->mode==AVI_MODE_READ) return 0; return (AVI->pos + 8 + 16*AVI->n_idx); } int AVI_set_audio_track(avi_t *AVI, int track) { if(track < 0 || track + 1 > AVI->anum) return(-1); //this info is not written to file anyway AVI->aptr=track; return 0; } int AVI_get_audio_track(avi_t *AVI) { return(AVI->aptr); } void AVI_set_audio_vbr(avi_t *AVI, long is_vbr) { AVI->track[AVI->aptr].a_vbr = is_vbr; } long AVI_get_audio_vbr(avi_t *AVI) { return(AVI->track[AVI->aptr].a_vbr); } void AVI_set_comment_fd(avi_t *AVI, int fd) { AVI->comment_fd = fd; } int AVI_get_comment_fd(avi_t *AVI) { return AVI->comment_fd; } /******************************************************************* * * * Utilities for reading video and audio from an AVI File * * * *******************************************************************/ int AVI_close(avi_t *AVI) { int ret; int j,k; /* If the file was open for writing, the header and index still have to be written */ if(AVI->mode == AVI_MODE_WRITE) ret = avi_close_output_file(AVI); else ret = 0; /* Even if there happened an error, we first clean up */ if (AVI->comment_fd>0) close(AVI->comment_fd); AVI->comment_fd = -1; close(AVI->fdes); if(AVI->idx) free(AVI->idx); if(AVI->video_index) free(AVI->video_index); if(AVI->video_superindex) { for (j = 0; j < NR_IXNN_CHUNKS; j++) { if (AVI->video_superindex->stdindex[j]) { if (AVI->video_superindex->stdindex[j]->aIndex) { free(AVI->video_superindex->stdindex[j]->aIndex); } free(AVI->video_superindex->stdindex[j]); } } if(AVI->video_superindex->stdindex) free(AVI->video_superindex->stdindex); if(AVI->video_superindex->aIndex) free(AVI->video_superindex->aIndex); free(AVI->video_superindex); } for (j=0; janum; j++) { if(AVI->track[j].audio_index) free(AVI->track[j].audio_index); if(AVI->track[j].audio_superindex) { // shortcut avisuperindex_chunk *a = AVI->track[j].audio_superindex; for (k = 0; k < NR_IXNN_CHUNKS; k++) { if (a->stdindex[k]) { if (a->stdindex[k]->aIndex) { free(a->stdindex[k]->aIndex); } free(a->stdindex[k]); } } if(a->stdindex) free(a->stdindex); if(a->aIndex) free(a->aIndex); free(a); } } if (AVI->bitmap_info_header) free(AVI->bitmap_info_header); for (j = 0; j < AVI->anum; j++) if (AVI->wave_format_ex[j]) free(AVI->wave_format_ex[j]); free(AVI); AVI=NULL; return ret; } #define ERR_EXIT(x) \ { \ AVI_close(AVI); \ AVI_errno = x; \ return 0; \ } avi_t *AVI_open_input_indexfile(char *filename, int getIndex, char *indexfile) { avi_t *AVI=NULL; /* Create avi_t structure */ AVI = (avi_t *) malloc(sizeof(avi_t)); if(AVI==NULL) { AVI_errno = AVI_ERR_NO_MEM; return 0; } memset((void *)AVI,0,sizeof(avi_t)); AVI->mode = AVI_MODE_READ; /* open for reading */ /* Open the file */ AVI->fdes = open(filename,O_RDONLY|O_BINARY); if(AVI->fdes < 0) { AVI_errno = AVI_ERR_OPEN; free(AVI); return 0; } AVI->index_file=strdup(indexfile); AVI_errno = 0; avi_parse_input_file(AVI, getIndex); if (AVI != NULL && !AVI_errno) { AVI->aptr=0; //reset } if (AVI_errno) return AVI=NULL; else return AVI; } avi_t *AVI_open_indexfd(int fd, int getIndex, char *indexfile) { avi_t *AVI=NULL; /* Create avi_t structure */ AVI = (avi_t *) malloc(sizeof(avi_t)); if(AVI==NULL) { AVI_errno = AVI_ERR_NO_MEM; return 0; } memset((void *)AVI,0,sizeof(avi_t)); AVI->mode = AVI_MODE_READ; /* open for reading */ // file alread open AVI->fdes = fd; AVI->index_file=strdup(indexfile); AVI_errno = 0; avi_parse_input_file(AVI, getIndex); if (AVI != NULL && !AVI_errno) { AVI->aptr=0; //reset } if (AVI_errno) return AVI=NULL; else return AVI; } avi_t *AVI_open_input_file(char *filename, int getIndex) { avi_t *AVI=NULL; /* Create avi_t structure */ AVI = (avi_t *) malloc(sizeof(avi_t)); if(AVI==NULL) { AVI_errno = AVI_ERR_NO_MEM; return 0; } memset((void *)AVI,0,sizeof(avi_t)); AVI->mode = AVI_MODE_READ; /* open for reading */ /* Open the file */ AVI->fdes = open(filename,O_RDONLY); if(AVI->fdes < 0) { AVI_errno = AVI_ERR_OPEN; free(AVI); return 0; } AVI_errno = 0; avi_parse_input_file(AVI, getIndex); if (AVI != NULL && !AVI_errno) { AVI->aptr=0; //reset } if (AVI_errno) return AVI=NULL; else return AVI; } avi_t *AVI_open_fd(int fd, int getIndex) { avi_t *AVI=NULL; /* Create avi_t structure */ AVI = (avi_t *) malloc(sizeof(avi_t)); if(AVI==NULL) { AVI_errno = AVI_ERR_NO_MEM; return 0; } memset((void *)AVI,0,sizeof(avi_t)); AVI->mode = AVI_MODE_READ; /* open for reading */ // file alread open AVI->fdes = fd; AVI_errno = 0; avi_parse_input_file(AVI, getIndex); if (AVI != NULL && !AVI_errno) { AVI->aptr=0; //reset } if (AVI_errno) return AVI=NULL; else return AVI; } // transcode-0.6.8 // reads a file generated by aviindex and builds the index out of it. int avi_parse_index_from_file(avi_t *AVI, char *filename) { char data[100]; // line buffer FILE *fd = NULL; // read from off_t pos, len, f_pos, tot_chunks[AVI_MAX_TRACKS]; int key=0, type; int vid_chunks=0, aud_chunks[AVI_MAX_TRACKS]; long line_count=0; char *c, d; int i,j; for (i=0; ivideo_index) { free(AVI->video_index); AVI->video_index = NULL; } for(j=0; janum; ++j) { if(AVI->track[j].audio_index) { free(AVI->track[j].audio_index); } AVI->track[j].audio_index = NULL; AVI->track[j].audio_chunks = 0; } if (!(fd = fopen(filename, "r"))) { perror ("avi_parse_index_from_file: fopen"); return -1; } // read header fgets(data, 100, fd); if ( strncasecmp(data, "AVIIDX1", 7) != 0) { fprintf(stderr, "%s: Not an AVI index file\n", filename); return -1; } // read comment fgets(data, 100, fd); f_pos = ftell(fd); while (fgets(data, 100, fd)) { d = data[5] - '1'; if (d == 0) { vid_chunks++; } else if (d == 1 || d == 2 || d == 3 || d == 4 || d == 5 || d == 6 || d == 7 || d == 8 ) { aud_chunks[d-1]++; } else continue; line_count++; } AVI->video_frames = vid_chunks; for(j=0; janum; ++j) AVI->track[j].audio_chunks = aud_chunks[j]; if(AVI->video_frames==0) ERR_EXIT(AVI_ERR_NO_VIDS); AVI->video_index = (video_index_entry *) malloc(vid_chunks*sizeof(video_index_entry)); if(AVI->video_index==0) ERR_EXIT(AVI_ERR_NO_MEM); for(j=0; janum; ++j) { if(AVI->track[j].audio_chunks) { AVI->track[j].audio_index = (audio_index_entry *) malloc(aud_chunks[j]*sizeof(audio_index_entry)); if(AVI->track[j].audio_index==0) ERR_EXIT(AVI_ERR_NO_MEM); } } // reset after header fseek(fd, f_pos, SEEK_SET); vid_chunks = 0; for(j=0; janum; ++j) aud_chunks[j] = tot_chunks[j] = 0; while (fgets(data, 100, fd)) { // this is very slow // sscanf(data, "%*s %d %*d %*d %lld %lld %d %*f", &type, &pos, &len, &key); c = strchr (data, ' '); type = strtol(c+1, &c, 10); //ch = strtol(c+1, &c, 10); c = strchr(c+1, ' '); //chtype= strtol(c+1, &c, 10); c = strchr(c+1, ' '); pos = strtoll(c+1, &c, 10); len = strtol(c+1, &c, 10); key = strtol(c+1, &c, 10); //ms = strtod(c+1, NULL); i = type-1; switch (i) { case 0: // video AVI->video_index[vid_chunks].key = (off_t)(key?0x10:0); AVI->video_index[vid_chunks].pos = pos+8; AVI->video_index[vid_chunks].len = len; vid_chunks++; break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: j=i-1; AVI->track[j].audio_index[aud_chunks[j]].pos = pos+8; AVI->track[j].audio_index[aud_chunks[j]].len = len; AVI->track[j].audio_index[aud_chunks[j]].tot = tot_chunks[j]; tot_chunks[j] += AVI->track[j].audio_index[aud_chunks[j]].len; aud_chunks[j]++; break; default: continue; } } for(j=0; janum; ++j) AVI->track[j].audio_bytes = tot_chunks[j]; fclose (fd); return 0; } int avi_parse_input_file(avi_t *AVI, int getIndex) { long i, rate, scale, idx_type; off_t n; unsigned char *hdrl_data; long header_offset=0, hdrl_len=0; long nvi, nai[AVI_MAX_TRACKS], ioff; long tot[AVI_MAX_TRACKS]; int j; int lasttag = 0; int vids_strh_seen = 0; int vids_strf_seen = 0; int auds_strh_seen = 0; // int auds_strf_seen = 0; int num_stream = 0; char data[256]; off_t oldpos=-1, newpos=-1; /* Read first 12 bytes and check that this is an AVI file */ if( avi_read(AVI->fdes,data,12) != 12 ) ERR_EXIT(AVI_ERR_READ) if( strncasecmp(data ,"RIFF",4) !=0 || strncasecmp(data+8,"AVI ",4) !=0 ) ERR_EXIT(AVI_ERR_NO_AVI) /* Go through the AVI file and extract the header list, the start position of the 'movi' list and an optionally present idx1 tag */ hdrl_data = 0; while(1) { if( avi_read(AVI->fdes,data,8) != 8 ) break; /* We assume it's EOF */ newpos = lseek(AVI->fdes,0,SEEK_CUR); if(oldpos==newpos) { /* This is a broken AVI stream... */ return -1; } oldpos=newpos; n = str2ulong((unsigned char *)data+4); n = PAD_EVEN(n); if(strncasecmp(data,"LIST",4) == 0) { if( avi_read(AVI->fdes,data,4) != 4 ) ERR_EXIT(AVI_ERR_READ) n -= 4; if(strncasecmp(data,"hdrl",4) == 0) { hdrl_len = n; hdrl_data = (unsigned char *) malloc(n); if(hdrl_data==0) ERR_EXIT(AVI_ERR_NO_MEM); // offset of header header_offset = lseek(AVI->fdes,0,SEEK_CUR); if( avi_read(AVI->fdes,(char *)hdrl_data,n) != n ) ERR_EXIT(AVI_ERR_READ) } else if(strncasecmp(data,"movi",4) == 0) { AVI->movi_start = lseek(AVI->fdes,0,SEEK_CUR); if (lseek(AVI->fdes,n,SEEK_CUR)==(off_t)-1) break; } else if (lseek(AVI->fdes,n,SEEK_CUR)==(off_t)-1) break; } else if(strncasecmp(data,"idx1",4) == 0) { /* n must be a multiple of 16, but the reading does not break if this is not the case */ AVI->n_idx = AVI->max_idx = n/16; AVI->idx = (unsigned char((*)[16]) ) malloc(n); if(AVI->idx==0) ERR_EXIT(AVI_ERR_NO_MEM) if(avi_read(AVI->fdes, (char *) AVI->idx, n) != n ) { free ( AVI->idx); AVI->idx=NULL; AVI->n_idx = 0; } } else lseek(AVI->fdes,n,SEEK_CUR); } if(!hdrl_data ) ERR_EXIT(AVI_ERR_NO_HDRL) if(!AVI->movi_start) ERR_EXIT(AVI_ERR_NO_MOVI) /* Interpret the header list */ for(i=0;icompressor,hdrl_data+i+4,4); AVI->compressor[4] = 0; // ThOe AVI->v_codech_off = header_offset + i+4; scale = str2ulong(hdrl_data+i+20); rate = str2ulong(hdrl_data+i+24); if(scale!=0) AVI->fps = (double)rate/(double)scale; AVI->video_frames = str2ulong(hdrl_data+i+32); AVI->video_strn = num_stream; AVI->max_len = 0; vids_strh_seen = 1; lasttag = 1; /* vids */ } else if (strncasecmp ((char *)hdrl_data+i,"auds",4) ==0 && ! auds_strh_seen) { //inc audio tracks AVI->aptr=AVI->anum; ++AVI->anum; if(AVI->anum > AVI_MAX_TRACKS) { fprintf(stderr, "error - only %d audio tracks supported\n", AVI_MAX_TRACKS); return(-1); } AVI->track[AVI->aptr].audio_bytes = str2ulong(hdrl_data+i+32)*avi_sampsize(AVI, 0); AVI->track[AVI->aptr].audio_strn = num_stream; // if samplesize==0 -> vbr AVI->track[AVI->aptr].a_vbr = !str2ulong(hdrl_data+i+44); AVI->track[AVI->aptr].padrate = str2ulong(hdrl_data+i+24); // auds_strh_seen = 1; lasttag = 2; /* auds */ // ThOe AVI->track[AVI->aptr].a_codech_off = header_offset + i; } else if (strncasecmp (hdrl_data+i,"iavs",4) ==0 && ! auds_strh_seen) { fprintf(stderr, "AVILIB: error - DV AVI Type 1 no supported\n"); return (-1); } else lasttag = 0; num_stream++; } else if(strncasecmp(hdrl_data+i,"dmlh",4) == 0) { AVI->total_frames = str2ulong(hdrl_data+i+8); #ifdef DEBUG_ODML fprintf(stderr, "real number of frames %d\n", AVI->total_frames); #endif i += 8; } else if(strncasecmp((char *)hdrl_data+i,"strf",4)==0) { i += 8; if(lasttag == 1) { alBITMAPINFOHEADER bih; memcpy(&bih, hdrl_data + i, sizeof(alBITMAPINFOHEADER)); AVI->bitmap_info_header = (alBITMAPINFOHEADER *) malloc(str2ulong((unsigned char *)&bih.bi_size)); if (AVI->bitmap_info_header != NULL) memcpy(AVI->bitmap_info_header, hdrl_data + i, str2ulong((unsigned char *)&bih.bi_size)); AVI->width = str2ulong(hdrl_data+i+4); AVI->height = str2ulong(hdrl_data+i+8); vids_strf_seen = 1; //ThOe AVI->v_codecf_off = header_offset + i+16; memcpy(AVI->compressor2, hdrl_data+i+16, 4); AVI->compressor2[4] = 0; } else if(lasttag == 2) { alWAVEFORMATEX *wfe; char *nwfe; int wfes; if ((hdrl_len - i) < sizeof(alWAVEFORMATEX)) wfes = hdrl_len - i; else wfes = sizeof(alWAVEFORMATEX); wfe = (alWAVEFORMATEX *)malloc(sizeof(alWAVEFORMATEX)); if (wfe != NULL) { memset(wfe, 0, sizeof(alWAVEFORMATEX)); memcpy(wfe, hdrl_data + i, wfes); if (str2ushort((unsigned char *)&wfe->cb_size) != 0) { nwfe = (char *) realloc(wfe, sizeof(alWAVEFORMATEX) + str2ushort((unsigned char *)&wfe->cb_size)); if (nwfe != 0) { off_t lpos = lseek(AVI->fdes, 0, SEEK_CUR); lseek(AVI->fdes, header_offset + i + sizeof(alWAVEFORMATEX), SEEK_SET); wfe = (alWAVEFORMATEX *)nwfe; nwfe = &nwfe[sizeof(alWAVEFORMATEX)]; avi_read(AVI->fdes, nwfe, str2ushort((unsigned char *)&wfe->cb_size)); lseek(AVI->fdes, lpos, SEEK_SET); } } AVI->wave_format_ex[AVI->aptr] = wfe; } AVI->track[AVI->aptr].a_fmt = str2ushort(hdrl_data+i ); //ThOe AVI->track[AVI->aptr].a_codecf_off = header_offset + i; AVI->track[AVI->aptr].a_chans = str2ushort(hdrl_data+i+2); AVI->track[AVI->aptr].a_rate = str2ulong (hdrl_data+i+4); //ThOe: read mp3bitrate AVI->track[AVI->aptr].mp3rate = 8*str2ulong(hdrl_data+i+8)/1000; //:ThOe AVI->track[AVI->aptr].a_bits = str2ushort(hdrl_data+i+14); // auds_strf_seen = 1; } } else if(strncasecmp(hdrl_data+i,"indx",4) == 0) { char *a; int j; if(lasttag == 1) // V I D E O { a = hdrl_data+i; AVI->video_superindex = (avisuperindex_chunk *) malloc (sizeof (avisuperindex_chunk)); memcpy (AVI->video_superindex->fcc, a, 4); a += 4; AVI->video_superindex->dwSize = str2ulong(a); a += 4; AVI->video_superindex->wLongsPerEntry = str2ushort(a); a += 2; AVI->video_superindex->bIndexSubType = *a; a += 1; AVI->video_superindex->bIndexType = *a; a += 1; AVI->video_superindex->nEntriesInUse = str2ulong(a); a += 4; memcpy (AVI->video_superindex->dwChunkId, a, 4); a += 4; // 3 * reserved a += 4; a += 4; a += 4; if (AVI->video_superindex->bIndexSubType != 0) {fprintf(stderr, "Invalid Header, bIndexSubType != 0\n"); } AVI->video_superindex->aIndex = malloc (AVI->video_superindex->wLongsPerEntry * AVI->video_superindex->nEntriesInUse * sizeof (uint32_t)); // position of ix## chunks for (j=0; jvideo_superindex->nEntriesInUse; ++j) { AVI->video_superindex->aIndex[j].qwOffset = str2ullong (a); a += 8; AVI->video_superindex->aIndex[j].dwSize = str2ulong (a); a += 4; AVI->video_superindex->aIndex[j].dwDuration = str2ulong (a); a += 4; #ifdef DEBUG_ODML printf("[%d] 0x%llx 0x%lx %lu\n", j, (unsigned long long)AVI->video_superindex->aIndex[j].qwOffset, (unsigned long)AVI->video_superindex->aIndex[j].dwSize, (unsigned long)AVI->video_superindex->aIndex[j].dwDuration); #endif } #ifdef DEBUG_ODML printf("FOURCC \"%c%c%c%c\"\n", AVI->video_superindex->fcc[0], AVI->video_superindex->fcc[1], AVI->video_superindex->fcc[2], AVI->video_superindex->fcc[3]); printf("LEN \"%ld\"\n", (long)AVI->video_superindex->dwSize); printf("wLongsPerEntry \"%d\"\n", AVI->video_superindex->wLongsPerEntry); printf("bIndexSubType \"%d\"\n", AVI->video_superindex->bIndexSubType); printf("bIndexType \"%d\"\n", AVI->video_superindex->bIndexType); printf("nEntriesInUse \"%ld\"\n", (long)AVI->video_superindex->nEntriesInUse); printf("dwChunkId \"%c%c%c%c\"\n", AVI->video_superindex->dwChunkId[0], AVI->video_superindex->dwChunkId[1], AVI->video_superindex->dwChunkId[2], AVI->video_superindex->dwChunkId[3]); printf("--\n"); #endif AVI->is_opendml = 1; } else if(lasttag == 2) // A U D I O { a = hdrl_data+i; AVI->track[AVI->aptr].audio_superindex = (avisuperindex_chunk *) malloc (sizeof (avisuperindex_chunk)); memcpy (AVI->track[AVI->aptr].audio_superindex->fcc, a, 4); a += 4; AVI->track[AVI->aptr].audio_superindex->dwSize = str2ulong(a); a += 4; AVI->track[AVI->aptr].audio_superindex->wLongsPerEntry = str2ushort(a); a += 2; AVI->track[AVI->aptr].audio_superindex->bIndexSubType = *a; a += 1; AVI->track[AVI->aptr].audio_superindex->bIndexType = *a; a += 1; AVI->track[AVI->aptr].audio_superindex->nEntriesInUse = str2ulong(a); a += 4; memcpy (AVI->track[AVI->aptr].audio_superindex->dwChunkId, a, 4); a += 4; // 3 * reserved a += 4; a += 4; a += 4; if (AVI->track[AVI->aptr].audio_superindex->bIndexSubType != 0) {fprintf(stderr, "Invalid Header, bIndexSubType != 0\n"); } AVI->track[AVI->aptr].audio_superindex->aIndex = malloc (AVI->track[AVI->aptr].audio_superindex->wLongsPerEntry * AVI->track[AVI->aptr].audio_superindex->nEntriesInUse * sizeof (uint32_t)); // position of ix## chunks for (j=0; jtrack[AVI->aptr].audio_superindex->nEntriesInUse; ++j) { AVI->track[AVI->aptr].audio_superindex->aIndex[j].qwOffset = str2ullong (a); a += 8; AVI->track[AVI->aptr].audio_superindex->aIndex[j].dwSize = str2ulong (a); a += 4; AVI->track[AVI->aptr].audio_superindex->aIndex[j].dwDuration = str2ulong (a); a += 4; #ifdef DEBUG_ODML printf("[%d] 0x%llx 0x%lx %lu\n", j, (unsigned long long)AVI->track[AVI->aptr].audio_superindex->aIndex[j].qwOffset, (unsigned long)AVI->track[AVI->aptr].audio_superindex->aIndex[j].dwSize, (unsigned long)AVI->track[AVI->aptr].audio_superindex->aIndex[j].dwDuration); #endif } #ifdef DEBUG_ODML printf("FOURCC \"%.4s\"\n", AVI->track[AVI->aptr].audio_superindex->fcc); printf("LEN \"%ld\"\n", (long)AVI->track[AVI->aptr].audio_superindex->dwSize); printf("wLongsPerEntry \"%d\"\n", AVI->track[AVI->aptr].audio_superindex->wLongsPerEntry); printf("bIndexSubType \"%d\"\n", AVI->track[AVI->aptr].audio_superindex->bIndexSubType); printf("bIndexType \"%d\"\n", AVI->track[AVI->aptr].audio_superindex->bIndexType); printf("nEntriesInUse \"%ld\"\n", (long)AVI->track[AVI->aptr].audio_superindex->nEntriesInUse); printf("dwChunkId \"%.4s\"\n", AVI->track[AVI->aptr].audio_superindex->dwChunkId[0]); printf("--\n"); #endif } i += 8; } else if((strncasecmp(hdrl_data+i,"JUNK",4) == 0) || (strncasecmp(hdrl_data+i,"strn",4) == 0) || (strncasecmp(hdrl_data+i,"vprp",4) == 0)){ i += 8; // do not reset lasttag } else { i += 8; lasttag = 0; } //printf("adding %ld bytes\n", (long int)n); i += n; } free(hdrl_data); if(!vids_strh_seen || !vids_strf_seen) ERR_EXIT(AVI_ERR_NO_VIDS) AVI->video_tag[0] = AVI->video_strn/10 + '0'; AVI->video_tag[1] = AVI->video_strn%10 + '0'; AVI->video_tag[2] = 'd'; AVI->video_tag[3] = 'b'; /* Audio tag is set to "99wb" if no audio present */ if(!AVI->track[0].a_chans) AVI->track[0].audio_strn = 99; { int i=0; for(j=0; janum+1; ++j) { if (j == AVI->video_strn) continue; AVI->track[i].audio_tag[0] = j/10 + '0'; AVI->track[i].audio_tag[1] = j%10 + '0'; AVI->track[i].audio_tag[2] = 'w'; AVI->track[i].audio_tag[3] = 'b'; ++i; } } lseek(AVI->fdes,AVI->movi_start,SEEK_SET); /* get index if wanted */ if(AVI->index_file && !getIndex) { int ret; ret = avi_parse_index_from_file(AVI, AVI->index_file); /* Reposition the file */ lseek(AVI->fdes,AVI->movi_start,SEEK_SET); AVI->video_pos = 0; return (ret); } if(!getIndex) return(0); /* if the file has an idx1, check if this is relative to the start of the file or to the start of the movi list */ idx_type = 0; if(AVI->idx) { off_t pos, len; /* Search the first videoframe in the idx1 and look where it is in the file */ for(i=0;in_idx;i++) if( strncasecmp((char *)AVI->idx[i],(char *)AVI->video_tag,3)==0 ) break; if(i>=AVI->n_idx) ERR_EXIT(AVI_ERR_NO_VIDS) pos = str2ulong(AVI->idx[i]+ 8); len = str2ulong(AVI->idx[i]+12); lseek(AVI->fdes,pos,SEEK_SET); if(avi_read(AVI->fdes,data,8)!=8) ERR_EXIT(AVI_ERR_READ) if( strncasecmp(data,(char *)AVI->idx[i],4)==0 && str2ulong((unsigned char *)data+4)==len ) { idx_type = 1; /* Index from start of file */ } else { lseek(AVI->fdes,pos+AVI->movi_start-4,SEEK_SET); if(avi_read(AVI->fdes,data,8)!=8) ERR_EXIT(AVI_ERR_READ) if( strncasecmp(data,(char *)AVI->idx[i],4)==0 && str2ulong((unsigned char *)data+4)==len ) { idx_type = 2; /* Index from start of movi list */ } } /* idx_type remains 0 if neither of the two tests above succeeds */ } if(idx_type == 0 && !AVI->is_opendml && !AVI->total_frames) { /* we must search through the file to get the index */ lseek(AVI->fdes, AVI->movi_start, SEEK_SET); AVI->n_idx = 0; while(1) { if( avi_read(AVI->fdes,data,8) != 8 ) break; n = str2ulong((unsigned char *)data+4); /* The movi list may contain sub-lists, ignore them */ if(strncasecmp(data,"LIST",4)==0) { lseek(AVI->fdes,4,SEEK_CUR); continue; } /* Check if we got a tag ##db, ##dc or ##wb */ if( ( (data[2]=='d' || data[2]=='D') && (data[3]=='b' || data[3]=='B' || data[3]=='c' || data[3]=='C') ) || ( (data[2]=='w' || data[2]=='W') && (data[3]=='b' || data[3]=='B') ) ) { avi_add_index_entry(AVI,(unsigned char *)data,0, lseek(AVI->fdes,0,SEEK_CUR)-8,n); } lseek(AVI->fdes,PAD_EVEN(n),SEEK_CUR); } idx_type = 1; } // ************************ // OPENDML // ************************ // read extended index chunks if (AVI->is_opendml) { uint64_t offset = 0; int hdrl_len = 4+4+2+1+1+4+4+8+4; char *en, *chunk_start; int k = 0, audtr = 0; uint32_t nrEntries = 0; AVI->video_index = NULL; nvi = 0; for(audtr=0; audtranum; ++audtr) nai[audtr] = tot[audtr] = 0; // ************************ // VIDEO // ************************ for (j=0; jvideo_superindex->nEntriesInUse; j++) { // read from file chunk_start = en = malloc (AVI->video_superindex->aIndex[j].dwSize+hdrl_len); if (lseek(AVI->fdes, AVI->video_superindex->aIndex[j].qwOffset, SEEK_SET) == (off_t)-1) { fprintf(stderr, "(%s) cannot seek to 0x%llx\n", __FILE__, (unsigned long long)AVI->video_superindex->aIndex[j].qwOffset); free(chunk_start); continue; } if (avi_read(AVI->fdes, en, AVI->video_superindex->aIndex[j].dwSize+hdrl_len) <= 0) { fprintf(stderr, "(%s) cannot read from offset 0x%llx %ld bytes; broken (incomplete) file?\n", __FILE__, (unsigned long long)AVI->video_superindex->aIndex[j].qwOffset, (unsigned long)AVI->video_superindex->aIndex[j].dwSize+hdrl_len); free(chunk_start); continue; } nrEntries = str2ulong(en + 12); #ifdef DEBUG_ODML //printf("[%d:0] Video nrEntries %ld\n", j, nrEntries); #endif offset = str2ullong(en + 20); // skip header en += hdrl_len; nvi += nrEntries; AVI->video_index = (video_index_entry *) realloc (AVI->video_index, nvi * sizeof (video_index_entry)); if (!AVI->video_index) { fprintf(stderr, "AVILIB: out of mem (size = %ld)\n", nvi * sizeof (video_index_entry)); exit(1); } while (k < nvi) { AVI->video_index[k].pos = offset + str2ulong(en); en += 4; AVI->video_index[k].len = str2ulong_len(en); AVI->video_index[k].key = str2ulong_key(en); en += 4; // completely empty chunk if (AVI->video_index[k].pos-offset == 0 && AVI->video_index[k].len == 0) { k--; nvi--; } #ifdef DEBUG_ODML /* printf("[%d] POS 0x%llX len=%d key=%s offset (%llx) (%ld)\n", k, AVI->video_index[k].pos, (int)AVI->video_index[k].len, AVI->video_index[k].key?"yes":"no ", offset, AVI->video_superindex->aIndex[j].dwSize); */ #endif k++; } free(chunk_start); } AVI->video_frames = nvi; // this should deal with broken 'rec ' odml files. if (AVI->video_frames == 0) { AVI->is_opendml=0; goto multiple_riff; } // ************************ // AUDIO // ************************ for(audtr=0; audtranum; ++audtr) { k = 0; if (!AVI->track[audtr].audio_superindex) { fprintf(stderr, "(%s) cannot read audio index for track %d\n", __FILE__, audtr); continue; } for (j=0; jtrack[audtr].audio_superindex->nEntriesInUse; j++) { // read from file chunk_start = en = malloc (AVI->track[audtr].audio_superindex->aIndex[j].dwSize+hdrl_len); if (lseek(AVI->fdes, AVI->track[audtr].audio_superindex->aIndex[j].qwOffset, SEEK_SET) == (off_t)-1) { fprintf(stderr, "(%s) cannot seek to 0x%llx\n", __FILE__, (unsigned long long)AVI->track[audtr].audio_superindex->aIndex[j].qwOffset); free(chunk_start); continue; } if (avi_read(AVI->fdes, en, AVI->track[audtr].audio_superindex->aIndex[j].dwSize+hdrl_len) <= 0) { fprintf(stderr, "(%s) cannot read from offset 0x%llx; broken (incomplete) file?\n", __FILE__,(unsigned long long) AVI->track[audtr].audio_superindex->aIndex[j].qwOffset); free(chunk_start); continue; } nrEntries = str2ulong(en + 12); //if (nrEntries > 50) nrEntries = 2; // XXX #ifdef DEBUG_ODML //printf("[%d:%d] Audio nrEntries %ld\n", j, audtr, nrEntries); #endif offset = str2ullong(en + 20); // skip header en += hdrl_len; nai[audtr] += nrEntries; AVI->track[audtr].audio_index = (audio_index_entry *) realloc (AVI->track[audtr].audio_index, nai[audtr] * sizeof (audio_index_entry)); while (k < nai[audtr]) { AVI->track[audtr].audio_index[k].pos = offset + str2ulong(en); en += 4; AVI->track[audtr].audio_index[k].len = str2ulong_len(en); en += 4; AVI->track[audtr].audio_index[k].tot = tot[audtr]; tot[audtr] += AVI->track[audtr].audio_index[k].len; #ifdef DEBUG_ODML /* printf("[%d:%d] POS 0x%llX len=%d offset (%llx) (%ld)\n", k, audtr, AVI->track[audtr].audio_index[k].pos, (int)AVI->track[audtr].audio_index[k].len, offset, AVI->track[audtr].audio_superindex->aIndex[j].dwSize); */ #endif ++k; } free(chunk_start); } AVI->track[audtr].audio_chunks = nai[audtr]; AVI->track[audtr].audio_bytes = tot[audtr]; } } // is opendml else if (AVI->total_frames && !AVI->is_opendml && idx_type==0) { // ********************* // MULTIPLE RIFF CHUNKS (and no index) // ********************* long aud_chunks = 0; multiple_riff: lseek(AVI->fdes, AVI->movi_start, SEEK_SET); AVI->n_idx = 0; fprintf(stderr, "[avilib] Reconstructing index..."); // Number of frames; only one audio track supported nvi = AVI->video_frames = AVI->total_frames; nai[0] = AVI->track[0].audio_chunks = AVI->total_frames; for(j=1; janum; ++j) AVI->track[j].audio_chunks = 0; AVI->video_index = (video_index_entry *) malloc(nvi*sizeof(video_index_entry)); if(AVI->video_index==0) ERR_EXIT(AVI_ERR_NO_MEM); for(j=0; janum; ++j) { if(AVI->track[j].audio_chunks) { AVI->track[j].audio_index = (audio_index_entry *) malloc((nai[j]+1)*sizeof(audio_index_entry)); memset(AVI->track[j].audio_index, 0, (nai[j]+1)*(sizeof(audio_index_entry))); if(AVI->track[j].audio_index==0) ERR_EXIT(AVI_ERR_NO_MEM); } } nvi = 0; for(j=0; janum; ++j) nai[j] = tot[j] = 0; aud_chunks = AVI->total_frames; while(1) { if (nvi >= AVI->total_frames) break; if( avi_read(AVI->fdes,data,8) != 8 ) break; n = str2ulong((unsigned char *)data+4); j=0; if (aud_chunks - nai[j] -1 <= 0) { aud_chunks += AVI->total_frames; AVI->track[j].audio_index = (audio_index_entry *) realloc( AVI->track[j].audio_index, (aud_chunks+1)*sizeof(audio_index_entry)); if (!AVI->track[j].audio_index) { fprintf(stderr, "Internal error in avilib -- no mem\n"); AVI_errno = AVI_ERR_NO_MEM; return -1; } } /* Check if we got a tag ##db, ##dc or ##wb */ // VIDEO if( (data[0]=='0' || data[1]=='0') && (data[2]=='d' || data[2]=='D') && (data[3]=='b' || data[3]=='B' || data[3]=='c' || data[3]=='C') ) { AVI->video_index[nvi].key = 0x0; AVI->video_index[nvi].pos = lseek(AVI->fdes,0,SEEK_CUR); AVI->video_index[nvi].len = n; /* fprintf(stderr, "Frame %ld pos %lld len %lld key %ld\n", nvi, AVI->video_index[nvi].pos, AVI->video_index[nvi].len, (long)AVI->video_index[nvi].key); */ nvi++; lseek(AVI->fdes,PAD_EVEN(n),SEEK_CUR); } //AUDIO else if( (data[0]=='0' || data[1]=='1') && (data[2]=='w' || data[2]=='W') && (data[3]=='b' || data[3]=='B') ) { AVI->track[j].audio_index[nai[j]].pos = lseek(AVI->fdes,0,SEEK_CUR); AVI->track[j].audio_index[nai[j]].len = n; AVI->track[j].audio_index[nai[j]].tot = tot[j]; tot[j] += AVI->track[j].audio_index[nai[j]].len; nai[j]++; lseek(AVI->fdes,PAD_EVEN(n),SEEK_CUR); } else { lseek(AVI->fdes,-4,SEEK_CUR); } } if (nvi < AVI->total_frames) { fprintf(stderr, "\n[avilib] Uh? Some frames seems missing (%ld/%d)\n", nvi, AVI->total_frames); } AVI->video_frames = nvi; AVI->track[0].audio_chunks = nai[0]; for(j=0; janum; ++j) AVI->track[j].audio_bytes = tot[j]; idx_type = 1; fprintf(stderr, "done. nvi=%ld nai=%ld tot=%ld\n", nvi, nai[0], tot[0]); } // total_frames but no indx chunk (xawtv does this) else { // ****************** // NO OPENDML // ****************** /* Now generate the video index and audio index arrays */ nvi = 0; for(j=0; janum; ++j) nai[j] = 0; for(i=0;in_idx;i++) { if(strncasecmp((char *)AVI->idx[i],AVI->video_tag,3) == 0) nvi++; for(j=0; janum; ++j) if(strncasecmp((char *)AVI->idx[i], AVI->track[j].audio_tag,4) == 0) nai[j]++; } AVI->video_frames = nvi; for(j=0; janum; ++j) AVI->track[j].audio_chunks = nai[j]; if(AVI->video_frames==0) ERR_EXIT(AVI_ERR_NO_VIDS); AVI->video_index = (video_index_entry *) malloc(nvi*sizeof(video_index_entry)); if(AVI->video_index==0) ERR_EXIT(AVI_ERR_NO_MEM); for(j=0; janum; ++j) { if(AVI->track[j].audio_chunks) { AVI->track[j].audio_index = (audio_index_entry *) malloc((nai[j]+1)*sizeof(audio_index_entry)); memset(AVI->track[j].audio_index, 0, (nai[j]+1)*(sizeof(audio_index_entry))); if(AVI->track[j].audio_index==0) ERR_EXIT(AVI_ERR_NO_MEM); } } nvi = 0; for(j=0; janum; ++j) nai[j] = tot[j] = 0; ioff = idx_type == 1 ? 8 : AVI->movi_start+4; for(i=0;in_idx;i++) { //video if(strncasecmp((char *)AVI->idx[i],AVI->video_tag,3) == 0) { AVI->video_index[nvi].key = str2ulong(AVI->idx[i]+ 4); AVI->video_index[nvi].pos = str2ulong(AVI->idx[i]+ 8)+ioff; AVI->video_index[nvi].len = str2ulong(AVI->idx[i]+12); nvi++; } //audio for(j=0; janum; ++j) { if(strncasecmp((char *)AVI->idx[i],AVI->track[j].audio_tag,4) == 0) { AVI->track[j].audio_index[nai[j]].pos = str2ulong(AVI->idx[i]+ 8)+ioff; AVI->track[j].audio_index[nai[j]].len = str2ulong(AVI->idx[i]+12); AVI->track[j].audio_index[nai[j]].tot = tot[j]; tot[j] += AVI->track[j].audio_index[nai[j]].len; nai[j]++; } } } for(j=0; janum; ++j) AVI->track[j].audio_bytes = tot[j]; } // is no opendml /* Reposition the file */ lseek(AVI->fdes,AVI->movi_start,SEEK_SET); AVI->video_pos = 0; return(0); } long AVI_video_frames(avi_t *AVI) { return AVI->video_frames; } int AVI_video_width(avi_t *AVI) { return AVI->width; } int AVI_video_height(avi_t *AVI) { return AVI->height; } double AVI_frame_rate(avi_t *AVI) { return AVI->fps; } char* AVI_video_compressor(avi_t *AVI) { return AVI->compressor2; } long AVI_max_video_chunk(avi_t *AVI) { return AVI->max_len; } int AVI_audio_tracks(avi_t *AVI) { return(AVI->anum); } int AVI_audio_channels(avi_t *AVI) { return AVI->track[AVI->aptr].a_chans; } long AVI_audio_mp3rate(avi_t *AVI) { return AVI->track[AVI->aptr].mp3rate; } long AVI_audio_padrate(avi_t *AVI) { return AVI->track[AVI->aptr].padrate; } int AVI_audio_bits(avi_t *AVI) { return AVI->track[AVI->aptr].a_bits; } int AVI_audio_format(avi_t *AVI) { return AVI->track[AVI->aptr].a_fmt; } long AVI_audio_rate(avi_t *AVI) { return AVI->track[AVI->aptr].a_rate; } long AVI_audio_bytes(avi_t *AVI) { return AVI->track[AVI->aptr].audio_bytes; } long AVI_audio_chunks(avi_t *AVI) { return AVI->track[AVI->aptr].audio_chunks; } long AVI_audio_codech_offset(avi_t *AVI) { return AVI->track[AVI->aptr].a_codech_off; } long AVI_audio_codecf_offset(avi_t *AVI) { return AVI->track[AVI->aptr].a_codecf_off; } long AVI_video_codech_offset(avi_t *AVI) { return AVI->v_codech_off; } long AVI_video_codecf_offset(avi_t *AVI) { return AVI->v_codecf_off; } long AVI_frame_size(avi_t *AVI, long frame) { if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } if(!AVI->video_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } if(frame < 0 || frame >= AVI->video_frames) return 0; return(AVI->video_index[frame].len); } long AVI_audio_size(avi_t *AVI, long frame) { if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } if(frame < 0 || frame >= AVI->track[AVI->aptr].audio_chunks) return -1; return(AVI->track[AVI->aptr].audio_index[frame].len); } long AVI_get_video_position(avi_t *AVI, long frame) { if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } if(!AVI->video_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } if(frame < 0 || frame >= AVI->video_frames) return 0; return(AVI->video_index[frame].pos); } int AVI_seek_start(avi_t *AVI) { if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } lseek(AVI->fdes,AVI->movi_start,SEEK_SET); AVI->video_pos = 0; return 0; } int AVI_set_video_position(avi_t *AVI, long frame) { if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } if(!AVI->video_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } if (frame < 0 ) frame = 0; AVI->video_pos = frame; return 0; } int AVI_set_audio_bitrate(avi_t *AVI, long bitrate) { if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } AVI->track[AVI->aptr].mp3rate = bitrate; return 0; } long AVI_read_frame(avi_t *AVI, char *vidbuf, int *keyframe) { long n; if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } if(!AVI->video_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } if(AVI->video_pos < 0 || AVI->video_pos >= AVI->video_frames) return -1; n = AVI->video_index[AVI->video_pos].len; *keyframe = (AVI->video_index[AVI->video_pos].key==0x10) ? 1:0; if (vidbuf == NULL) { AVI->video_pos++; return n; } lseek(AVI->fdes, AVI->video_index[AVI->video_pos].pos, SEEK_SET); if (avi_read(AVI->fdes,vidbuf,n) != n) { AVI_errno = AVI_ERR_READ; return -1; } AVI->video_pos++; return n; } long AVI_get_audio_position_index(avi_t *AVI) { if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } return (AVI->track[AVI->aptr].audio_posc); } int AVI_set_audio_position_index(avi_t *AVI, long indexpos) { if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } if(indexpos > AVI->track[AVI->aptr].audio_chunks) { AVI_errno = AVI_ERR_NO_IDX; return -1; } AVI->track[AVI->aptr].audio_posc = indexpos; AVI->track[AVI->aptr].audio_posb = 0; return 0; } int AVI_set_audio_position(avi_t *AVI, long byte) { long n0, n1, n; if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } if(byte < 0) byte = 0; /* Binary search in the audio chunks */ n0 = 0; n1 = AVI->track[AVI->aptr].audio_chunks; while(n0track[AVI->aptr].audio_index[n].tot>byte) n1 = n; else n0 = n; } AVI->track[AVI->aptr].audio_posc = n0; AVI->track[AVI->aptr].audio_posb = byte - AVI->track[AVI->aptr].audio_index[n0].tot; return 0; } long AVI_read_audio(avi_t *AVI, char *audbuf, long bytes) { long nr, left, todo; off_t pos; if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } nr = 0; /* total number of bytes read */ if (bytes==0) { AVI->track[AVI->aptr].audio_posc++; AVI->track[AVI->aptr].audio_posb = 0; lseek(AVI->fdes, 0LL, SEEK_CUR); } while(bytes>0) { off_t ret; left = AVI->track[AVI->aptr].audio_index[AVI->track[AVI->aptr].audio_posc].len - AVI->track[AVI->aptr].audio_posb; if(left==0) { if(AVI->track[AVI->aptr].audio_posc>=AVI->track[AVI->aptr].audio_chunks-1) return nr; AVI->track[AVI->aptr].audio_posc++; AVI->track[AVI->aptr].audio_posb = 0; continue; } if(bytestrack[AVI->aptr].audio_index[AVI->track[AVI->aptr].audio_posc].pos + AVI->track[AVI->aptr].audio_posb; lseek(AVI->fdes, pos, SEEK_SET); if ( (ret = avi_read(AVI->fdes,audbuf+nr,todo)) != todo) { fprintf(stderr, "XXX pos = %lld, ret = %lld, todo = %ld\n", pos, ret, todo); AVI_errno = AVI_ERR_READ; return -1; } bytes -= todo; nr += todo; AVI->track[AVI->aptr].audio_posb += todo; } return nr; } long AVI_read_audio_chunk(avi_t *AVI, char *audbuf) { long left; off_t pos; if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } if (AVI->track[AVI->aptr].audio_posc+1>AVI->track[AVI->aptr].audio_chunks) return -1; left = AVI->track[AVI->aptr].audio_index[AVI->track[AVI->aptr].audio_posc].len - AVI->track[AVI->aptr].audio_posb; if (audbuf == NULL) return left; if(left==0) { AVI->track[AVI->aptr].audio_posc++; AVI->track[AVI->aptr].audio_posb = 0; return 0; } pos = AVI->track[AVI->aptr].audio_index[AVI->track[AVI->aptr].audio_posc].pos + AVI->track[AVI->aptr].audio_posb; lseek(AVI->fdes, pos, SEEK_SET); if (avi_read(AVI->fdes,audbuf,left) != left) { AVI_errno = AVI_ERR_READ; return -1; } AVI->track[AVI->aptr].audio_posc++; AVI->track[AVI->aptr].audio_posb = 0; return left; } /* AVI_read_data: Special routine for reading the next audio or video chunk without having an index of the file. */ int AVI_read_data(avi_t *AVI, char *vidbuf, long max_vidbuf, char *audbuf, long max_audbuf, long *len) { /* * Return codes: * * 1 = video data read * 2 = audio data read * 0 = reached EOF * -1 = video buffer too small * -2 = audio buffer too small */ off_t n; char data[8]; if(AVI->mode==AVI_MODE_WRITE) return 0; while(1) { /* Read tag and length */ if( avi_read(AVI->fdes,data,8) != 8 ) return 0; /* if we got a list tag, ignore it */ if(strncasecmp(data,"LIST",4) == 0) { lseek(AVI->fdes,4,SEEK_CUR); continue; } n = PAD_EVEN(str2ulong((unsigned char *)data+4)); if(strncasecmp(data,AVI->video_tag,3) == 0) { *len = n; AVI->video_pos++; if(n>max_vidbuf) { lseek(AVI->fdes,n,SEEK_CUR); return -1; } if(avi_read(AVI->fdes,vidbuf,n) != n ) return 0; return 1; } else if(strncasecmp(data,AVI->track[AVI->aptr].audio_tag,4) == 0) { *len = n; if(n>max_audbuf) { lseek(AVI->fdes,n,SEEK_CUR); return -2; } if(avi_read(AVI->fdes,audbuf,n) != n ) return 0; return 2; break; } else if(lseek(AVI->fdes,n,SEEK_CUR)<0) return 0; } } /* AVI_print_error: Print most recent error (similar to perror) */ char *(avi_errors[]) = { /* 0 */ "avilib - No Error", /* 1 */ "avilib - AVI file size limit reached", /* 2 */ "avilib - Error opening AVI file", /* 3 */ "avilib - Error reading from AVI file", /* 4 */ "avilib - Error writing to AVI file", /* 5 */ "avilib - Error writing index (file may still be useable)", /* 6 */ "avilib - Error closing AVI file", /* 7 */ "avilib - Operation (read/write) not permitted", /* 8 */ "avilib - Out of memory (malloc failed)", /* 9 */ "avilib - Not an AVI file", /* 10 */ "avilib - AVI file has no header list (corrupted?)", /* 11 */ "avilib - AVI file has no MOVI list (corrupted?)", /* 12 */ "avilib - AVI file has no video data", /* 13 */ "avilib - operation needs an index", /* 14 */ "avilib - Unkown Error" }; static int num_avi_errors = sizeof(avi_errors)/sizeof(char*); static char error_string[4096]; void AVI_print_error(char *str) { int aerrno; aerrno = (AVI_errno>=0 && AVI_errno=0 && AVI_errnoriff.id ,buf+0, 4); memcpy(&wave->riff.len ,buf+4, 4); memcpy(&wave->riff.wave_id ,buf+8, 4); memcpy(&wave->format.id ,buf+12, 4); memcpy(&wave->format.len ,buf+16, 4); memcpy(&wave->common.wFormatTag ,buf+20, 2); memcpy(&wave->common.wChannels ,buf+22, 2); memcpy(&wave->common.dwSamplesPerSec ,buf+24, 4); memcpy(&wave->common.dwAvgBytesPerSec ,buf+28, 4); memcpy(&wave->common.wBlockAlign ,buf+32, 2); memcpy(&wave->common.wBitsPerSample ,buf+34, 2); memcpy(&wave->data.id ,buf+36, 4); memcpy(&wave->data.len ,buf+40, 4); /* fprintf(stderr, "RIFF: %c%c%c%c| (%d) (%d)\n", wave->riff.id[0], wave->riff.id[1], wave->riff.id[2], wave->riff.id[3], sizeof (*wave), sizeof (struct wave_header)); fprintf(stderr, "WAVE: %c%c%c%c|\n", wave->riff.wave_id[0], wave->riff.wave_id[1], wave->riff.wave_id[2], wave->riff.wave_id[3]); fprintf(stderr, "fmt : %c%c%c%c|\n", wave->format.id[0], wave->format.id[1], wave->format.id[2], wave->format.id[3]); fprintf(stderr, "data: %c%c%c%c|\n", wave->data.id[0], wave->data.id[1], wave->data.id[2], wave->data.id[3]); */ if( strncasecmp(wave->riff.id , "RIFF",4) != 0 || strncasecmp(wave->riff.wave_id, "WAVE",4) != 0 || strncasecmp(wave->format.id , "fmt ",4) != 0 ) { AVI_errno = AVI_ERR_NO_AVI; return -1; } #define x_FIXUP(field) \ ((field) = (sizeof(field) == 4 ? str2ulong((unsigned char*)&(field)) \ : str2ushort((unsigned char*)&(field)))) if (lav_detect_endian()) { x_FIXUP(wave->riff.len); x_FIXUP(wave->format.len); x_FIXUP(wave->common.wFormatTag); x_FIXUP(wave->common.wChannels); x_FIXUP(wave->common.dwSamplesPerSec); x_FIXUP(wave->common.dwAvgBytesPerSec); x_FIXUP(wave->common.wBlockAlign); x_FIXUP(wave->common.wBitsPerSample); x_FIXUP(wave->data.len); } #undef x_FIXUP return 0; } int AVI_write_wave_header( int fd, const struct wave_header * wave ) { char buf[44]; struct wave_header buffer = *wave; #define x_FIXUP(field) \ ((sizeof(field) == 4 ? long2str((unsigned char*)&(field),(field)) \ : short2str((unsigned char*)&(field),(field)))) if (lav_detect_endian()) { x_FIXUP(buffer.riff.len); x_FIXUP(buffer.format.len); x_FIXUP(buffer.common.wFormatTag); x_FIXUP(buffer.common.wChannels); x_FIXUP(buffer.common.dwSamplesPerSec); x_FIXUP(buffer.common.dwAvgBytesPerSec); x_FIXUP(buffer.common.wBlockAlign); x_FIXUP(buffer.common.wBitsPerSample); x_FIXUP(buffer.data.len); } #undef x_FIXUP memcpy(buf+ 0, &buffer.riff.id, 4); memcpy(buf+ 4, &buffer.riff.len, 4); memcpy(buf+ 8, &buffer.riff.wave_id, 4); memcpy(buf+12, &buffer.format.id, 4); memcpy(buf+16, &buffer.format.len, 4); memcpy(buf+20, &buffer.common.wFormatTag, 2); memcpy(buf+22, &buffer.common.wChannels, 2); memcpy(buf+24, &buffer.common.dwSamplesPerSec, 4); memcpy(buf+28, &buffer.common.dwAvgBytesPerSec, 4); memcpy(buf+32, &buffer.common.wBlockAlign, 2); memcpy(buf+34, &buffer.common.wBitsPerSample, 2); memcpy(buf+36, &buffer.data.id, 4); memcpy(buf+40, &buffer.data.len, 4); // write raw data if( avi_write (fd, buf, sizeof(buf)) != sizeof(buf) ) { AVI_errno = AVI_ERR_WRITE; return -1; } return 0; } size_t AVI_read_wave_pcm_data( int fd, void * buffer, size_t buflen ) { int doneread = avi_read(fd, buffer, buflen); char * bufptr = buffer; size_t i; char tmp; if (lav_detect_endian()) { for ( i=0; i 0) { buflen = datalen; if( buflen > sizeof(buffer) ) buflen = sizeof(buffer); for ( i=0; i int main() { const char **dft; printf("The MJPEGTOOLS_SIMD_DISABLE environment variable is a comma sep list of:\n\n"); for (dft = disable_simd_flags; *dft; dft++) printf("%s\n", *dft); printf("\nall\n"); exit(0); } mjpegtools-2.1.0/lavtools/subsample.h0000644000175000017500000000216410044075466020231 0ustar glowwormglowworm/* * subsample.h: Routines to do chroma subsampling. ("Work In Progress") * * * Copyright (C) 2001 Matthew J. Marjanovic * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "yuv4mpeg.h" int chroma_sub_implemented(int mode); void chroma_subsample(int mode, uint8_t *ycbcr[], int width, int height); int chroma_super_implemented(int mode); void chroma_supersample(int mode, uint8_t *ycbcr[], int width, int height); mjpegtools-2.1.0/lavtools/multiblend.flt.c0000644000175000017500000002437607543667643021203 0ustar glowwormglowworm/* * multiblend - reads two frame-interlaced YUV4MPEG streams from stdin * and blends the second over the first. * * derived from mattblend.flt.c. Added more blending stuff. * Copyright (C) 2001, pHilipp Zabel * Copyright (C) 2002 , Niels Elburg elburg@hio.hen.nl * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "yuv4mpeg.h" /* * Note: for all _yuvdata methods, * I want to blend on Luminance only, * and keep the Cb and Cr channels of the original frame * If you want to blend over Cb and Cr too, uncomment the lines of code. * */ static void usage (void) { fprintf (stderr, "usage: multiblend.flt\n" "params: -t num type of overlay [1-10]\n" " 1 = additive\n" " 2 = substractive\n" " 3 = multiply\n" " 4 = divide\n" " 5 = difference\n" " 6 = difference negate\n" " 7 = freeze\n" " 8 = unfreeze\n" " 9 = hardlight\n" " 10 = lighten only\n" "\n"); } static void overlay_lighten_yuvdata(uint8_t *src1[3], uint8_t *src2[3], int width, int height) { register unsigned int i; register unsigned int len = width * height; register int a,b,c; for(i=0; i < len; i++) { a = src1[0][i]; b = src2[0][i]; if ( a > b ) c = a; else c = b; src1[0][i]=c; } } static void overlay_hardlight_yuvdata(uint8_t *src1[3], uint8_t *src2[3], int width, int height) { register unsigned int i; register unsigned int len = width * height; register int a,b,c; for(i=0; i < len; i++) { a = src1[0][i]; b = src2[0][i]; if ( b < 128 ) c = (a*b)>>7; else c = 235 - ( (235-b)*(235-a)>>7); if (c <16) c = 16; src1[0][i] = c; } } static void overlay_unfreeze_yuvdata(uint8_t *src1[3], uint8_t *src2[3], int width, int height) { register unsigned int i; register unsigned int len = width * height; register int a,b,c; for(i=0; i < len; i++) { a = src1[0][i]; b = src2[0][i]; if ( a < 16 ) c = 16; else c = 235 - ( (235-b)*(235-b))/a; if (c <16) c = 16; src1[0][i] = c; } } static void overlay_freeze_yuvdata(uint8_t *src1[3], uint8_t *src2[3], int width, int height) { register unsigned int i; register unsigned int len = width * height; register int a,b,c; for(i=0; i < len; i++) { a = src1[0][i]; b = src2[0][i]; if ( b < 16 ) c = 16; else c = 235 - ( (235-a)*(235-a))/b; if (c <16) c = 16; src1[0][i] = c; } } static void overlay_diffnegate_yuvdata(uint8_t *src1[3], uint8_t *src2[3], int width, int height) { register unsigned int i; register unsigned int len = width * height; for(i=0; i < len; i++) { src1[0][i] = 235 - abs( 235 - src1[0][i] - src2[0][i] ); } } static void overlay_difference_yuvdata(uint8_t *src1[3], uint8_t *src2[3], int width, int height) { register unsigned int i; register unsigned int len = width * height; for(i=0; i < len; i++) { src1[0][i] = abs( src1[0][i] - src2[0][i] ); } } static void overlay_divide_yuvdata(uint8_t *src1[3], uint8_t *src2[3], int width, int height) { register unsigned int i; register unsigned int len = width * height; register int a,b,c; for(i=0; i < len; i++) { b = src1[0][i]*src2[0][i]; c = 255 - src2[0][i]; if(c==0)c=16; a = b/c; if ( a > 235 ) a = 235; if ( a < 16 ) a = 16; src1[0][i] = a; } /* for Cb and Cr len >>=2; for(i=0; i < len; i++) { b = src1[1][i]*src2[1][i]; c = 255 - src2[1][i]; if(c==0)c=16; a = b/c; if ( a > 235 ) a = 235; if ( a < 16 ) a = 16; src1[1][i] = a; b = src1[2][i]*src2[2][i]; c = 255 - src2[2][i]; if(c==0)c=16; a = b/c; if ( a > 235 ) a = 235; if ( a < 16 ) a = 16; src1[2][i] = a; } */ } static void overlay_add_yuvdata(uint8_t *src1[3], uint8_t *src2[3], int width, int height) { register unsigned int i; register unsigned int len = width * height; register int a; for(i=0; i < len; i++) { a = src1[0][i] + (2*src2[0][i]) - 235; if (a < 16) a = 16; if (a > 235) a = 235; src1[0][i]=a; } /* for Cb and Cr len>>=2; for(i=0; i < len; i++) { a = src1[1][i] + (2*src2[1][i]) - 235; if (a < 16) a = 16; if (a > 235) a = 235; src1[1][i]=a; a = src1[2][i] + (2*src2[2][i]) - 235; if (a < 16) a = 16; if (a > 235) a = 235; src1[2][i]=a; } */ } static void overlay_sub_yuvdata(uint8_t *src1[3], uint8_t *src2[3], int width, int height) { register unsigned int i; register unsigned int len = width * height; register int a; for(i=0; i < len; i++) { a = src1[0][i]+src2[0][i] - 235; if (a < 16) a = 16; src1[0][i]=a; } } static void overlay_multiply_yuvdata(uint8_t *src1[3], uint8_t *src2[3], int width, int height) { register unsigned int i; register unsigned int len = width * height; for(i=0; i < len; i++) { src1[0][i]=(src1[0][i]*src2[0][i])>>8; } } static void multiblend(uint8_t *src1[3], uint8_t *src2[3], int width, int height, int type) { switch(type) { case 1: overlay_add_yuvdata(src1,src2,width,height); break; case 2: overlay_sub_yuvdata(src1,src2,width,height); break; case 3: overlay_multiply_yuvdata(src1,src2,width,height); break; case 4: overlay_divide_yuvdata(src1,src2,width,height); break; case 5: overlay_difference_yuvdata(src1,src2,width,height); break; case 6: overlay_diffnegate_yuvdata(src1,src2,width,height); break; case 7: overlay_freeze_yuvdata(src1,src2,width,height); break; case 8: overlay_unfreeze_yuvdata(src1,src2,width,height); break; case 9: overlay_hardlight_yuvdata(src1,src2,width,height); break; case 10: overlay_lighten_yuvdata(src1,src2,width,height); break; } } int main (int argc, char *argv[]) { int in_fd = 0; /* stdin */ int out_fd = 1; /* stdout */ unsigned char *yuv0[3]; /* input 0 */ unsigned char *yuv1[3]; /* input 1 */ y4m_stream_info_t streaminfo; y4m_frame_info_t frameinfo; int i; int w, h; int which_overlay=0; if (argc < 1) { usage (); exit (1); } y4m_init_stream_info (&streaminfo); y4m_init_frame_info (&frameinfo); while( ( i = getopt(argc,argv, "t:"))!=-1) { switch(i) { case 't': which_overlay = atoi(optarg); if (which_overlay < 1 || which_overlay > 10) { usage(); exit(1); } break; } } i = y4m_read_stream_header (in_fd, &streaminfo); if (i != Y4M_OK) { fprintf (stderr, "%s: input stream error - %s\n", argv[0], y4m_strerr(i)); exit (1); } w = y4m_si_get_width(&streaminfo); h = y4m_si_get_height(&streaminfo); yuv0[0] = malloc (w * h); yuv1[0] = malloc (w * h); yuv0[1] = malloc (w * h / 4); yuv1[1] = malloc (w * h / 4); yuv0[2] = malloc (w * h / 4); yuv1[2] = malloc (w * h / 4); y4m_write_stream_header (out_fd, &streaminfo); while (1) { i = y4m_read_frame(in_fd, &streaminfo, &frameinfo, yuv0); if (i == Y4M_ERR_EOF) exit (0); else if (i != Y4M_OK) exit (1); i = y4m_read_frame(in_fd, &streaminfo, &frameinfo, yuv1); if (i != Y4M_OK) exit (1); multiblend (yuv0, yuv1,w, h, which_overlay); y4m_write_frame (out_fd, &streaminfo, &frameinfo, yuv0); } } mjpegtools-2.1.0/lavtools/glav.h0000644000175000017500000000332507441737224017173 0ustar glowwormglowworm/** Header file generated with fdesign on Sun Mar 5 18:11:00 2000.**/ #ifndef GTK_xlav_h_ #define GTK_xlav_h_ /** Callbacks, globals and object handlers **/ extern void timeslider_cb(GtkAdjustment *, gpointer ); extern void timehscale_button_pressed_cb(GtkAdjustment *, gpointer ); extern void timehscale_button_released_cb(GtkAdjustment *, gpointer ); /* extern void timeslider_cb(GtkWidget*, long); */ extern void button_cb(GtkWidget*, long); extern void rb_cb(GtkWidget *, long); extern void Exit_cb(GtkWidget *, long); extern void selection_cb(GtkWidget *, long); extern void frame_skip_released(GtkWidget *, long ); extern void frame_skip_pressed(GtkWidget *, long ); extern gint key_press_cb(GtkWidget * , GdkEventKey* , gpointer data ); extern GtkWidget* glav_add_button(GtkWidget *, gchar *, GtkSignalFunc , gpointer); /**** Forms and Objects ****/ typedef struct { GtkWidget *xlav; void *vdata; char *cdata; long ldata; GtkObject *timeslider; GtkWidget *timehscale; GtkWidget *ss; GtkWidget *se; GtkWidget *stepr; GtkWidget *stepf; GtkWidget *fr; GtkWidget *rew; GtkWidget *stop; GtkWidget *play; GtkWidget *ff; GtkWidget *Timer; GtkWidget *Exit; GtkWidget *EditFrame; GtkWidget *TSelStart; GtkWidget *TSelEnd; GtkWidget *FSelStart; GtkWidget *FSelEnd; GtkWidget *BSSelStart; GtkWidget *BSSelEnd; GtkWidget *BClearSel; GtkWidget *BECut; GtkWidget *BECopy; GtkWidget *BEPaste; GtkWidget *BSaveAll; GtkWidget *BSaveSel; GtkWidget *StatDisp; GtkWidget *BGotoSelStart; GtkWidget *BGotoSelEnd; } GTK_xlav; extern GTK_xlav * create_form_xlav(void); extern void dispatch_input(void); extern void do_real_exit(int ID, void *data); extern void signal_cb(int signum, void *data); #endif /* GTK_xlav_h_ */ mjpegtools-2.1.0/lavtools/lavaddwav.c0000644000175000017500000007227410340526634020210 0ustar glowwormglowworm/* lavaddwav: Add a WAV file as soundtrack to an AVI or QT file Usage: lavaddwav AVI_or_QT_file WAV_file Output_file Multiple output file version by Nicholas Redgrave 8th January 2005 Use "%02d" style output filenames for multiple files. Parameter options added by Nicholas Redgrave 15th January 2005 Major rewrite to add lists of AVI/QT and WAV files by Nicholas Redgrave 2nd February 2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include "lav_io.h" #include "mjpeg_logging.h" #define FOURCC(a,b,c,d) ( (d<<24) | ((c&0xff)<<16) | ((b&0xff)<<8) | (a&0xff) ) #define FOURCC_RIFF FOURCC ('R', 'I', 'F', 'F') #define FOURCC_WAVE FOURCC ('W', 'A', 'V', 'E') #define FOURCC_FMT FOURCC ('f', 'm', 't', ' ') #define FOURCC_DATA FOURCC ('d', 'a', 't', 'a') #define MAX_FILE_NAME 127 /* Structures */ typedef struct { char chFileName[MAX_FILE_NAME+1]; long video_frames; int width; int height; int interlacing; double fps; double time_length; int format; long max_frame_size; }videoparams; typedef struct { char chFileName[MAX_FILE_NAME+1]; long data_length; long audio_samps; long audio_rate; int audio_chans; int audio_bits; int audio_bps; double time_length; }audioparams; /* Prototypes */ static void usage(void); void handle_args(int argc, char **argv); int main(int argc, char **argv); int open_lav_file(lav_file_t **lav_fd, char *chLavFile, int ientry, int iscan); int open_wav_file(int *wav_fd, char *chWavFile, int ientry, int iscan); int count_list_entries(char *chFile); int fill_video_list_entries(char *chFile); int fill_audio_list_entries(char *chFile); void display_video_params(int ientry); void display_audio_params(int ientry); int allocate_video_memory(int ientries); int allocate_audio_memory(int ientries); void free_video_memory(int ientries); void free_audio_memory(int ientries); int compare_input_files(int iVidEntries, int iAudEntries); long find_max_frame_size(int ientries); /* Global variables */ int verbose = 1; static int big_endian = 0; static int param_maxfilesize = MAX_MBYTES_PER_FILE_32; static int list_mode = 0; static videoparams **vp = NULL; static audioparams **ap = NULL; static void usage(void) { fprintf(stderr, "Usage: lavaddwav [params] \n" " where possible params are:\n" " -m num maximum size per file [%d MB]\n" " -l list mode (input files are text lists of AVI//QT and WAV files)\n", param_maxfilesize); fprintf(stderr," If the output file is too large for one AVI use %%0xd in\n"); fprintf(stderr," the output filename so that lavaddwav creates several files.\n"); fprintf(stderr," e.g. lavaddwav video.avi sound.wav output%%02d.avi\n"); } void handle_args(int argc, char **argv) { int p; /* disable error messages from getopt */ opterr = 0; /* Parse options */ while( (p = getopt(argc, argv, "lm:")) != -1 ) { switch(p) { case 'l': { list_mode = 1; break; } case 'm': { param_maxfilesize = atoi(optarg); break; } default: { usage(); exit(1); } } } /* check validity of options */ if( (param_maxfilesize <= 0) || (param_maxfilesize > MAX_MBYTES_PER_FILE_32) ) { param_maxfilesize = MAX_MBYTES_PER_FILE_32; fprintf(stderr,"Maximum size per file out of range - resetting to maximum\n"); } } /* * Main */ int main(int argc, char **argv) { int n; int wav_fd; long i, res, frame_size, max_frame_size; long absize, lRemBytes; uint8_t *vbuff = NULL; uint8_t *abuff = NULL; lav_file_t *lav_fd = NULL; lav_file_t *lav_out = NULL; unsigned long ulOutputBytes; int iLavFiles, iWavFiles; int iTotBytes; char *chOutFile; int iOutNum = 1; int iCurLav = 0; int iCurWav = 0; int imulti_out = 0; double total_video_duration = 0.0; double total_audio_duration = 0.0; if(argc < 4) { /* Show usage */ usage(); exit(1); } /* Handle command line arguments */ handle_args(argc, argv); /* Are we big or little endian? */ big_endian = lav_detect_endian(); if( big_endian < 0 ) exit(1); chOutFile = malloc(strlen(argv[optind+2]) + 8 + 1); /* Extra for safety */ if (chOutFile == NULL) mjpeg_error_exit1("Could not malloc space for output filename"); /* Process according to mode */ if( list_mode ) { /* Open and count file entries in lav list file */ iLavFiles = count_list_entries(argv[optind]); if( !iLavFiles ) { mjpeg_error("No entries found in video list file %s", argv[optind]); exit(1); } /* Open and count file entries in wav list file */ iWavFiles = count_list_entries(argv[optind+1]); if( !iWavFiles ) { mjpeg_error("No entries found in audio list file %s", argv[optind+1]); exit(1); } } else { iLavFiles = 1; iWavFiles = 1; } /* Allocate memory for list entry structures */ if( !allocate_video_memory(iLavFiles) ) { mjpeg_error("Unable to allocate memory for video file list structures"); exit(1); } if( !allocate_audio_memory(iWavFiles) ) { mjpeg_error("Unable to allocate memory for audio file list structures"); free_video_memory(iLavFiles); exit(1); } /* Fill structures with data */ if( list_mode ) { if( !fill_video_list_entries(argv[optind]) ) { free_audio_memory(iWavFiles); free_video_memory(iLavFiles); mjpeg_error("Unable to fill video file list structures"); exit(1); } if( !fill_audio_list_entries(argv[optind+1]) ) { free_audio_memory(iWavFiles); free_video_memory(iLavFiles); mjpeg_error("Unable to fill audio file list structures"); exit(1); } } else { if( !open_lav_file(&lav_fd, argv[optind], 0, 1) ) { free_audio_memory(iWavFiles); free_video_memory(iLavFiles); mjpeg_error("Unable to fill video file structure"); exit(1); } lav_close(lav_fd); display_video_params(0); if( !open_wav_file(&wav_fd, argv[optind+1], 0, 1) ) { free_audio_memory(iWavFiles); free_video_memory(iLavFiles); mjpeg_error("Unable to fill audio file structure"); exit(1); } close(wav_fd); display_audio_params(0); } /* Check that input files are compatible */ if( list_mode ) { if( !compare_input_files(iLavFiles, iWavFiles) ) { mjpeg_error("Input files are not compatible"); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(1); } } /* Find largest frame size */ max_frame_size = find_max_frame_size(iLavFiles); mjpeg_debug(" Max frame size: %ld", max_frame_size); /* Rough check for "%d" style output filename */ if( strchr(argv[optind+2], 37) != NULL ) imulti_out = 1; else /* Copy output filename for non-%d style names */ strcpy(chOutFile, argv[optind+2]); /* Allocate video and audio buffers */ vbuff = (uint8_t*) malloc(max_frame_size); absize = (ap[0]->audio_rate / vp[0]->fps) + 0.5; absize *= ap[0]->audio_bps; abuff = (uint8_t*) malloc(absize); if( (vbuff == NULL) || (abuff == NULL) ) { mjpeg_error("Out of Memory - malloc failed"); if( vbuff != NULL ){ free(vbuff); } if( abuff != NULL ){ free(abuff); } free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(1); } /* Open first video and audio file */ if( !open_lav_file(&lav_fd, vp[iCurLav]->chFileName, iCurLav, 0) ) { mjpeg_error("Error opening %s", vp[iCurLav]->chFileName); free(abuff); free(vbuff); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(1); } total_video_duration += vp[iCurLav]->time_length; if( !open_wav_file(&wav_fd, ap[iCurWav]->chFileName, iCurWav, 0) ) { mjpeg_error("Error opening %s", ap[iCurWav]->chFileName); free(abuff); free(vbuff); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(1); } total_audio_duration += ap[iCurWav]->time_length; /* (First) video and audio file are open - we are ready to multiplex */ ulOutputBytes = 0; i = 0; /* Outer loop */ while( iCurLav < iLavFiles ) { if( imulti_out ) /* build output filename */ sprintf(chOutFile, argv[optind+2], iOutNum++); /* Create output file */ lav_out = lav_open_output_file(chOutFile, vp[0]->format, vp[0]->width, vp[0]->height, vp[0]->interlacing, vp[0]->fps, ap[0]->audio_bits, ap[0]->audio_chans, ap[0]->audio_rate); if(!lav_out) { mjpeg_error("Error creating %s: %s", chOutFile, lav_strerror()); lav_close(lav_fd); if( wav_fd >= 0 ) { close(wav_fd); } free(abuff); free(vbuff); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); free(chOutFile); exit(1); } /* Loop reading and writing video and audio */ while(1) { /* Video loop */ while( i < vp[iCurLav]->video_frames ) { /* read video frame */ res = lav_read_frame(lav_fd,vbuff); if( res < 0 ) { mjpeg_error("File: %s Reading video frame: %s",vp[iCurLav]->chFileName,lav_strerror()); lav_close(lav_out); lav_close(lav_fd); if( wav_fd >= 0 ) { close(wav_fd); } free(abuff); free(vbuff); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(1); } frame_size = lav_frame_size(lav_fd,i); /* write video frame */ res = lav_write_frame(lav_out, vbuff, frame_size, 1); if( res < 0 ) { mjpeg_error("Writing video frame: %s", lav_strerror()); lav_close(lav_out); lav_close(lav_fd); if( wav_fd >= 0 ) { close(wav_fd); } free(abuff); free(vbuff); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(1); } ulOutputBytes += (unsigned long)frame_size; /* Audio loop */ lRemBytes = absize; iTotBytes = 0; while( iCurWav < iWavFiles ) { n = read(wav_fd, &abuff[iTotBytes], lRemBytes); iTotBytes += n; lRemBytes -= n; if( n < 0 ) { /* read error */ mjpeg_error("Error reading audio from file %s: %s", ap[iCurWav]->chFileName, lav_strerror()); lav_close(lav_out); lav_close(lav_fd); close(wav_fd); free(abuff); free(vbuff); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(1); } if( iTotBytes < absize ) { /* we need more data from next audio file if possible */ close(wav_fd); wav_fd = -1; iCurWav++; if( iCurWav == iWavFiles ) { /* no more audio files - make next if block write out data now */ absize = iTotBytes; } } if( iTotBytes == absize ) { /* got all the bytes we wanted - write them out */ res = lav_write_audio(lav_out, abuff, iTotBytes/ap[0]->audio_bps); if( res < 0 ) { mjpeg_error("Error writing audio: %s",lav_strerror()); lav_close(lav_out); lav_close(lav_fd); close(wav_fd); free(abuff); free(vbuff); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(1); } ulOutputBytes += (unsigned long)iTotBytes; /* we're done for this frame */ break; } /* end of if( iTotBytes == absize ) */ /* we need more data from next audio file */ if( !open_wav_file(&wav_fd, ap[iCurWav]->chFileName, iCurWav, 0) ) { mjpeg_error("Error opening %s", ap[iCurWav]->chFileName); lav_close(lav_out); lav_close(lav_fd); free(abuff); free(vbuff); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(1); } total_audio_duration += ap[iCurWav]->time_length; } /* end of while( iCurWav < iWavFiles ) */ /* Increment video frame counter */ i++; /* Check for exceeding maximum output file size */ if( (ulOutputBytes >> 20) >= (unsigned long)param_maxfilesize ) { if( imulti_out ) { mjpeg_debug(" Starting new sequence: %d",iOutNum); lav_close(lav_out); ulOutputBytes = 0; break; } /* No limit on QT files */ if( vp[0]->format != 113 ) { mjpeg_error("Max file size reached use %%0xd in your output filename"); lav_close(lav_out); lav_close(lav_fd); if( wav_fd >= 0 ) { close(wav_fd); } free(abuff); free(vbuff); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(0); } } } /* end of while( i < vp[iCurLav]->video_frames ) */ /* Do we need to go on to the next video file? */ if( i == vp[iCurLav]->video_frames ) { iCurLav++; if( iCurLav < iLavFiles ) { /* Open next video file */ lav_close(lav_fd); if( !open_lav_file(&lav_fd, vp[iCurLav]->chFileName, iCurLav, 0) ) { mjpeg_error("Error opening %s", vp[iCurLav]->chFileName); if( lav_out != NULL ) { lav_close(lav_out); } if( wav_fd >= 0 ) { close(wav_fd); } free(abuff); free(vbuff); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(1); } total_video_duration += vp[iCurLav]->time_length; /* reset video frame counter */ i = 0; } else { /* we've run out of video */ break; } } /* end of if( i == vp[iCurLav]->video_frames ) */ /* Do we need to create a new output file? */ if( ulOutputBytes == 0 ) { break; } }/* end of while(1) (Loop reading and writing video and audio) */ } /* end of while( iCurLav < iLavFiles ) */ /* Copy remaining audio if required */ /* Outer loop */ while( iCurWav < iWavFiles ) { if( ulOutputBytes == 0 ) { /* build output filename */ sprintf(chOutFile, argv[optind+2], iOutNum++); /* Create output file */ lav_out = lav_open_output_file(chOutFile, vp[0]->format, vp[0]->width, vp[0]->height, vp[0]->interlacing, vp[0]->fps, ap[0]->audio_bits, ap[0]->audio_chans, ap[0]->audio_rate); if(!lav_out) { mjpeg_error("Error creating %s: %s", chOutFile, lav_strerror()); if( wav_fd >= 0 ) { close(wav_fd); } free(abuff); free(vbuff); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); free(chOutFile); exit(1); } } /* end of if( lav_out == NULL ) */ /* Audio loop */ while(1) { lRemBytes = absize; iTotBytes = 0; while( iCurWav < iWavFiles ) { n = read(wav_fd, &abuff[iTotBytes], lRemBytes); iTotBytes += n; lRemBytes -= n; if( n < 0 ) { /* read error */ mjpeg_error("Error reading audio from file %s: %s", ap[iCurWav]->chFileName, lav_strerror()); lav_close(lav_out); close(wav_fd); free(abuff); free(vbuff); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(1); } if( iTotBytes < absize ) { /* we need more data from next audio file if possible */ close(wav_fd); wav_fd = -1; iCurWav++; if( iCurWav == iWavFiles ) { /* no more audio files - make next if block write out data now */ absize = iTotBytes; } } if( iTotBytes == absize ) { /* got all the bytes we wanted - write them out */ res = lav_write_audio(lav_out, abuff, iTotBytes/ap[0]->audio_bps); if( res < 0 ) { mjpeg_error("Error writing audio: %s",lav_strerror()); lav_close(lav_out); close(wav_fd); free(abuff); free(vbuff); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(1); } ulOutputBytes += (unsigned long)iTotBytes; /* we're done for this frame */ break; } /* end of if( iTotBytes == absize ) */ /* we need more data from next audio file */ if( !open_wav_file(&wav_fd, ap[iCurWav]->chFileName, iCurWav, 0) ) { mjpeg_error("Error opening %s", ap[iCurWav]->chFileName); lav_close(lav_out); free(abuff); free(vbuff); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(1); } total_audio_duration += ap[iCurWav]->time_length; } /* end of while( iCurWav < iWavFiles ) */ /* Check for exceeding maximum output file size */ if( (ulOutputBytes >> 20) >= (unsigned long)param_maxfilesize ) { if( imulti_out ) { mjpeg_debug(" Starting new sequence: %d",iOutNum); ulOutputBytes = 0; break; } /* No limit on QT files */ if( vp[0]->format != 113 ) { mjpeg_error("Max file size reached use %%0xd in your output filename"); lav_close(lav_out); if( wav_fd >= 0 ) { close(wav_fd); } free(abuff); free(vbuff); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(0); } } if( iCurWav == iWavFiles ) { /* no more audio files */ break; } } /* end of while(1) (Audio loop) */ lav_close(lav_out); lav_out = NULL; } /* end of while( iCurWav < iWavFiles ) */ /* Tidy up and exit */ if( lav_out != NULL ) { lav_close(lav_out); } free(abuff); free(vbuff); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); free(chOutFile); mjpeg_debug(" Total Video Duration: %8.3f sec", total_video_duration); mjpeg_debug(" Total Audio Duration: %8.3f sec", total_audio_duration); mjpeg_debug(" "); /* Success */ return 0; } int open_lav_file(lav_file_t **lav_fd, char *chLavFile, int ientry, int iscan) { long i; long max_frame_size = 0; lav_file_t *lav_tmp; *lav_fd = lav_open_input_file(chLavFile); if(!*lav_fd) { mjpeg_error("Error opening %s", chLavFile); return 0; } if( iscan ) { strncpy(&vp[ientry]->chFileName[0], chLavFile, MAX_FILE_NAME); vp[ientry]->video_frames = lav_video_frames(*lav_fd); vp[ientry]->width = lav_video_width(*lav_fd); vp[ientry]->height = lav_video_height(*lav_fd); vp[ientry]->interlacing = lav_video_interlacing(*lav_fd); vp[ientry]->fps = lav_frame_rate(*lav_fd); if( vp[ientry]->fps <= 0.0 ) { lav_close(*lav_fd); mjpeg_error("Framerate illegal"); return 0; } vp[ientry]->time_length = vp[ientry]->video_frames / vp[ientry]->fps; lav_tmp = *lav_fd; vp[ientry]->format = lav_tmp->format; /* find maximum frame size */ for(i=0; ivideo_frames; i++) { if( lav_frame_size(*lav_fd, i) > max_frame_size ) { max_frame_size = lav_frame_size(*lav_fd, i); } } vp[ientry]->max_frame_size = max_frame_size; } /* success */ return 1; } int open_wav_file(int *wav_fd, char *chWavFile, int ientry, int iscan) { int n; uint32_t fmtlen; uint32_t data[64]; off_t cur_off = 0; off_t cur_end = 0; *wav_fd = open(chWavFile, O_RDONLY); if( *wav_fd < 0 ) { mjpeg_error("Error opening WAV file %s :%s", chWavFile, strerror(errno)); return 0; } n = read(*wav_fd,(char*)data,20); if( n != 20 ) { mjpeg_error("Error reading WAV file %s :%s", chWavFile, strerror(errno)); close(*wav_fd); return 0; } /* Make endian safe */ data[0] = reorder_32(data[0], big_endian); data[2] = reorder_32(data[2], big_endian); data[3] = reorder_32(data[3], big_endian); data[4] = reorder_32(data[4], big_endian); if( data[0] != FOURCC_RIFF || data[2] != FOURCC_WAVE || data[3] != FOURCC_FMT || data[4] > sizeof(data) ) { mjpeg_error("Error in WAV header of %s", chWavFile); close(*wav_fd); return 0; } fmtlen = data[4]; n = read(*wav_fd, (char*)data, fmtlen); if( n !=fmtlen ) { perror("open_wav_file"); close(*wav_fd); return 0; } /* Make endian safe */ data[0] = reorder_32(data[0], big_endian); data[1] = reorder_32(data[1], big_endian); data[3] = reorder_32(data[3], big_endian); if( (data[0]&0xffff) != 1 ) { mjpeg_error("WAV file is not in PCM format %s", chWavFile); close(*wav_fd); return 0; } if( iscan ) { strncpy(ap[ientry]->chFileName, chWavFile, MAX_FILE_NAME); ap[ientry]->audio_chans = (data[0]>>16) & 0xffff; ap[ientry]->audio_rate = data[1]; ap[ientry]->audio_bits = (data[3]>>16) & 0xffff; ap[ientry]->audio_bps = (ap[ientry]->audio_chans * ap[ientry]->audio_bits + 7) / 8; if( ap[ientry]->audio_bps == 0 ) { ap[ientry]->audio_bps = 1; } /* safety first */ } n = read(*wav_fd,(char*)data,8); if( n != 8 ) { mjpeg_error("Read WAV header %s :%s", chWavFile, strerror(errno)); close(*wav_fd); return 0; } /* Make endian safe */ data[0] = reorder_32(data[0], big_endian); data[1] = reorder_32(data[1], big_endian); if( data[0] != FOURCC_DATA ) { mjpeg_error("Error in WAV header %s", chWavFile); close(*wav_fd); return 0; } if( iscan ) { /* check length of Wav file - update structure with correct length */ cur_off = lseek(*wav_fd, 0, SEEK_CUR); cur_end = lseek(*wav_fd, 0, SEEK_END); if( (long)(cur_end - cur_off) != data[1] ) { mjpeg_warn("Repairing data length mismatch with WAV header %s", chWavFile); data[1] = (long)(cur_end - cur_off); } cur_off = lseek(*wav_fd, cur_off, SEEK_SET); ap[ientry]->data_length = data[1]; ap[ientry]->audio_samps = data[1] / ap[ientry]->audio_bps; ap[ientry]->time_length = (double)ap[ientry]->audio_samps / (double)ap[ientry]->audio_rate; } /* success */ return 1; } int count_list_entries(char *chFile) { FILE *fp; int ientries = 0; char chformat[10]; char chtmp[MAX_FILE_NAME+1] = "\0"; sprintf(chformat, "%%%ds",MAX_FILE_NAME); fp = fopen(chFile, "rt"); if( fp == NULL ) { mjpeg_error("Unable to open file list %s", chFile); return 0; } while (fscanf(fp, chformat, chtmp) == 1) ientries++; fclose(fp); /* return the number of entries */ return ientries; } int fill_video_list_entries(char *chFile) { FILE *fp; int ientry = 0; char chformat[10]; char chtmp[MAX_FILE_NAME+1] = "\0"; lav_file_t *lav_tmp = NULL; sprintf(chformat, "%%%ds",MAX_FILE_NAME); fp = fopen(chFile, "rt"); if( fp == NULL ) { mjpeg_error("Unable to open video file list %s", chFile); return 0; } while( fscanf(fp, chformat, chtmp) == 1) { if( !open_lav_file(&lav_tmp, chtmp, ientry, 1) ) { fclose(fp); return 0; } display_video_params(ientry); ientry++; lav_close(lav_tmp); } fclose(fp); return 1; } int fill_audio_list_entries(char *chFile) { FILE *fp; int ientry = 0; char chformat[10]; char chtmp[MAX_FILE_NAME+1] = "\0"; int wav_tmp; sprintf(chformat, "%%%ds",MAX_FILE_NAME); fp = fopen(chFile, "rt"); if( fp == NULL ) { mjpeg_error("Unable to open audio file list %s", chFile); return 0; } while( fscanf(fp, chformat, chtmp) == 1) { if( !open_wav_file(&wav_tmp, chtmp, ientry, 1) ) { fclose(fp); return 0; } display_audio_params(ientry); ientry++; close(wav_tmp); } fclose(fp); return 1; } void display_video_params(int ientry) { mjpeg_debug("File: %s", vp[ientry]->chFileName); mjpeg_debug(" format: %8c", vp[ientry]->format); mjpeg_debug(" frames: %8ld", vp[ientry]->video_frames); mjpeg_debug(" width: %8d", vp[ientry]->width); mjpeg_debug(" height: %8d", vp[ientry]->height); mjpeg_debug(" interlacing: %8d", vp[ientry]->interlacing); mjpeg_debug(" frames/sec: %8.3f", vp[ientry]->fps); mjpeg_debug(" duration: %8.3f sec", vp[ientry]->time_length); mjpeg_debug(" "); } void display_audio_params(int ientry) { mjpeg_debug("File: %s", ap[ientry]->chFileName); mjpeg_debug(" audio samps: %8ld", ap[ientry]->audio_samps); mjpeg_debug(" audio chans: %8d", ap[ientry]->audio_chans); mjpeg_debug(" audio bits: %8d", ap[ientry]->audio_bits); mjpeg_debug(" audio rate: %8ld", ap[ientry]->audio_rate); mjpeg_debug(" duration: %8.3f sec",(double)ap[ientry]->audio_samps/(double)ap[ientry]->audio_rate); mjpeg_debug(" "); } int allocate_video_memory(int ientries) { int i; /* allocate memory for array of pointers */ vp = malloc(ientries * sizeof(videoparams *)); if( vp == NULL ) { mjpeg_error("Unable to allocate memory for video file list structure array"); return 0; } memset(vp, 0 , ientries * sizeof(videoparams*)); /* allocate memory for each structure */ for(i=0; iformat != vp[i]->format) || (vp[0]->width != vp[i]->width) || (vp[0]->height != vp[i]->height) || (vp[0]->interlacing != vp[i]->interlacing) || (vp[0]->fps != vp[i]->fps) ) { /* mismatch */ return 0; } } /* compare audio files */ for(i=0; iaudio_chans != ap[i]->audio_chans) || (ap[0]->audio_bits != ap[i]->audio_bits) || (ap[0]->audio_rate != ap[i]->audio_rate) ) { /* mismatch */ return 0; } } /* file formats match */ return 1; } long find_max_frame_size(int ientries) { int i; long max_frame_size = vp[0]->max_frame_size; for(i=0; imax_frame_size ) { max_frame_size = vp[i]->max_frame_size; } } return max_frame_size; } mjpegtools-2.1.0/lavtools/lavrec.c0000644000175000017500000011540711606231110017473 0ustar glowwormglowworm/* * lavrec - Linux Audio Video RECord * * Copyright (C) 2000 Rainer Johanni * Extended by: Gernot Ziegler * & Wolfgang Scherr * & Ronald Bultje * & many others * * A library for recording MJPEG video from hardware MJPEG * video devices such as the Pinnacle/Miro DC10(+), Iomega * Buz, the Linux Media Labs LML33, the Matrox Marvel G200, * Matrox Marvel G400 and the Rainbow Runner G-series. * Can also be used for video-capture from BTTV-devices * * Usage: lavrec [options] filename [filename ...] * where options are as follows: * * -f/--format [aAqm] --- Output file format: * 'a': AVI (default) * 'A': AVI with fields exchanged * 'j': JPEG image(s) * 'q': quicktime (if compiled with quicktime support) * Hint: If your AVI video looks strange, try 'A' instead 'a' * and vice versa. * * -i/--input [pPnNsStTa] --- Input Source: * -i/--input input[:norm] * 'p': PAL Composite Input or first Bt8x8 input * 'P': PAL SVHS-Input or second Bt8x8 input * 't': PAL TV tuner input or third Bt8x8 input * 'n': NTSC Composite Input or first Bt8x8 input * 'N': NTSC SVHS-Input or second Bt8x8 input * 'T': NTSC TV tuner input or third Bt8x8 input * 's': SECAM Composite Input or first Bt8x8 input * 'S': SECAM SVHS-Input or second Bt8x8 input * 'f': SECAM TV tuner input or third Bt8x8 input * 'a': Autosense (default) * input - a number, 1-10 * norm - pal, ntsc or secam * * -d/--decimation num --- Frame recording decimation: * must be either 1, 2 or 4 for identical decimation * in horizontal and vertical direction (mostly used) or a * two digit letter with the first digit specifying horizontal * decimation and the second digit specifying vertical decimation * (more exotic usages). Not supported for BTTV. * * -g/--geometry WxH+X+Y --- An X-style geometry string (capturing area): * Even if a decimation > 1 is used, these values are always * coordinates in the undecimated frame. * For DC10: 768/640x{576 or 480}. * For others: 720x{576 or 480}. * Also, unlike in X-Window, negative values for X and Y * really mean negative offsets (if this feature is enabled * in the driver) which lets you fine tune the position of the * image caught. * The horizontal resolution of the DECIMATED frame must * allways be a multiple of 16, the vertical resolution * of the DECIMATED frame must be a multiple of 16 for decimation 1 * and a multiple of 8 for decimations 2 and 4 * * If not offset (X and Y values) is given, the capture area * is centered in the frame. * * For BTTV-capuring (--software-encoding), X and Y are omitted * and W and H are the video-capture-size (so decimation is omitted) * too). BTTV does not support subframe-capture. * * -q/--quality num --- quality: * must be between 0 and 100, default is 50 * * -t/--time num -- capturing time: * Time to capture in seconds, default is unlimited * (use ^C to stop capture!) * * -S/--single-frame --- enables single-frame capturing mode * * -T/--time-lapse num --- time-lapse mode: * Time lapse factor: Video will be played back times * faster, audio is switched off. * This means that only every th frame is recorded. * If num==1 it is silently ignored. * * -w/--wait --- Wait for user confirmation to start * * -B/--batch --- Batch mode recording. Minimal error logging, no * interaction, works when output is redirected to files. * Intended for use when doing unattended script-controlled * recording. * * --software-encoding --- encode frames in software-mode: * Mainly intended to make it possible to use lavrec with BTTV * cards too. Should work for V4L-capture with zoran cards too * but that's only for testing - you really don't want to use * this option for zoran-devices since they have hardware-encoding * possibilities * * --max-file-size --- The maximum size (in MB) per video file * Intended for those that would like to record video in MJPEG * format and need a specific filesize limit, for example to be * able to burn the video files to CD (650 MB). * * --max-file-frames --- The maximum number of frames per video file * Intended for those that would like to record video in MJPEG * format and need a specific number of frames per file, for * example to be able to perform easy file and frame number * arithmetics when cutting video manually. * * --file-flush --- How often (in frames) the current output * file (if any) should be flushed to disk. (default:60). * Set to 0 if your chosen file-system and system tuning * ensures you don't get lengthy periods of disk activity * during which lavrec writing is held up. * **** Audio settings *** * * -a/--audio-bitsize num --- audio bitsize: * Audio size in bits, must be 0 (no audio), 8 or 16 (default) * * -r/--audio_bitrate num --- audio-bitrate: * Audio rate (in Hz), must be a permitted sampling rate for * your soundcard. Default is 22050. * * -s/--stereo --- enable stereo (disabled by default) * * -l/--audio-volume num --- audio recording level/volume: * Audio level to use for recording, must be between 0 and 100 * or -1 (for not touching the mixer settings at all), default * is 100. * * -m/--mute --- mute output during recording: * Mute audio output during recording (default is to let it enabled). * This is particularly usefull if you are recording with a * microphone to avoid feedback. * * -R/--audio-source [lmc] --- Audio recording source: * 'l': line-in * 'm': microphone * 'c': cdrom * '1': line1 * '2': line2 * '3': line3 * **** Audio/Video synchronization *** * * -c/--synchronization num --- Level of corrections for synchronization: * 0: Neither try to replicate lost frames nor any sync correction * 1: Replicate frames for lost frames, but no sync correction * 2. lost frames replication + sync correction * **** Special capture settings *** * * -n/--mjpeg-buffers num --- Number of MJPEG capture buffers (default 64) * * -b/--mjpeg-buffer-size num --- Size of MJPEG buffers in KB (default 256) * **** Environment variables *** * * Recognized environment variables: * LAV_VIDEO_DEV: Name of video device (default: "/dev/video") * LAV_AUDIO_DEV: Name of audio device (default: "/dev/dsp") * LAV_MIXER_DEV: Name of mixer device (default: "/dev/mixer") * * To overcome the AVI (and linux-2.2 ext2fs) 2 GB filesize limit, you can: * - give multiple filenames on the command-line * - give one filename which contains a '%' sign. This name is then * interpreted as the format argument to sprintf() to form multiple * file names * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "liblavrec.h" #include "mjpeg_logging.h" #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_GETOPT_H #include #endif #include #include #include static lavrec_t *info; static int num_frames, num_lost, num_ins, num_del, num_aerr; static int show_stats = 0; static int state; static sem_t state_changed; static int verbose = 0; static int wait_for_start = 0; static int batch_mode = 0; static char input_source; static pthread_t signal_thread; static void Usage(char *progname) { fprintf(stderr, "lavtools version " VERSION ": lavrec\n"); fprintf(stderr, "Usage: %s [options] [ ...]\n", progname); fprintf(stderr, "where options are:\n"); fprintf(stderr, " -f/--format [aAj" #ifdef HAVE_LIBQUICKTIME "q" #else "" #endif "] Format AVI/Quicktime\n"); fprintf(stderr, " -i/--input [pPnNsStTfa] Input Source or 1-10:norm see manpage\n"); fprintf(stderr, " -d/--decimation num Decimation (either 1,2,4 or two digit number)\n"); fprintf(stderr, " -g/--geometry WxH+X+Y X-style geometry string (part of 768/720x576/480)\n"); fprintf(stderr, " -q/--quality num Quality [%%]\n"); fprintf(stderr, " -t/--time num Capture time (default: unlimited - Ctrl-C to stop\n"); fprintf(stderr, " -S/--single-frame Single frame capture mode\n"); fprintf(stderr, " -T/--time-lapse num Time lapse, capture only every th frame\n"); fprintf(stderr, " -w/--wait Wait for user confirmation to start\n"); fprintf(stderr, " -B/--batch Batch mode for recording non-interactively\n"); fprintf(stderr, " -a/--audio-bitsize num Audio size, 0 for no audio, 8 or 16\n"); fprintf(stderr, " -r/--audio-bitrate num Audio rate [Hz]\n"); fprintf(stderr, " -s/--stereo Stereo (default: mono)\n"); fprintf(stderr, " -l/--audio-volume num Recording level [%%], -1 for mixers not touched\n"); fprintf(stderr, " -m/--mute Mute audio output during recording\n"); fprintf(stderr, " -R/--audio-source [lmc123] Set recording source: (l)ine, (m)icro, (c)d,\n"); fprintf(stderr, " line(1), line(2), line(3\n"); fprintf(stderr, " -c/--synchronization [012] Level of corrections for synchronization\n"); fprintf(stderr, " -n/--mjpeg-buffers num Number of MJPEG buffers (default: 64)\n"); fprintf(stderr, " -b/--mjpeg-buffer-size num Size of MJPEG buffers [Kb] (default: 256)\n"); fprintf(stderr, " -C/--channel LIST:CHAN When using a TV tuner, channel list/number\n"); fprintf(stderr, " -F/--frequency KHz When using a TV tuner, frequency in KHz\n"); fprintf(stderr, " -U/--use-read Use read instead of mmap for recording\n"); fprintf(stderr, " --software-encoding Use software JPEG-encoding (for BTTV-capture)\n"); fprintf(stderr, " --software-encoding-yuvp Use software JPEG-encoding (for EM28XX-capture)\n"); fprintf(stderr, " --num-procs num Number of encoding processes (default: 1)\n"); fprintf(stderr, " --max-file-size num Maximum size per file (in MB)\n"); fprintf(stderr, " --max-file-frames num Maximum number of frames per file\n"); fprintf(stderr, " --file-flush num Flush capture file to disk every num frames\n"); fprintf(stderr, " -v/--verbose [012] verbose level (default: 0)\n"); fprintf(stderr, "Environment variables recognized:\n"); fprintf(stderr, " LAV_VIDEO_DEV, LAV_AUDIO_DEV, LAV_MIXER_DEV\n"); exit(1); } /* RJ: The following stuff thanks to Philipp Zabel: */ /* pH5 - the following was stolen from glut (that stole the code from X): */ /* * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding * value (x, y, width, height) was found in the parsed string. */ #define NoValue 0x0000 #define XValue 0x0001 #define YValue 0x0002 #define WidthValue 0x0004 #define HeightValue 0x0008 #define AllValues 0x000F #define XNegative 0x0010 #define YNegative 0x0020 /* the following function was stolen from the X sources as indicated. */ /* Copyright Massachusetts Institute of Technology 1985, 1986, 1987 */ /* $XConsortium: XParseGeom.c,v 11.18 91/02/21 17:23:05 rws Exp $ */ /* Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of M.I.T. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. M.I.T. makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. */ /* * XParseGeometry parses strings of the form * "=x{+-}{+-}", where * width, height, xoffset, and yoffset are unsigned integers. * Example: "=80x24+300-49" * The equal sign is optional. * It returns a bitmask that indicates which of the four values * were actually found in the string. For each value found, * the corresponding argument is updated; for each value * not found, the corresponding argument is left unchanged. */ static int ReadInteger(char *string, char **NextString) { register int Result = 0; int Sign = 1; if (*string == '+') string++; else if (*string == '-') { string++; Sign = -1; } for (; (*string >= '0') && (*string <= '9'); string++) { Result = (Result * 10) + (*string - '0'); } *NextString = string; if (Sign >= 0) return (Result); else return (-Result); } static int XParseGeometry(char *string, int *x, int *y, unsigned int *width, unsigned int *height) { int mask = NoValue; register char *strind; unsigned int tempWidth, tempHeight; int tempX, tempY; char *nextCharacter; if ( (string == NULL) || (*string == '\0')) return(mask); if (*string == '=') string++; /* ignore possible '=' at beg of geometry spec */ strind = (char *)string; tempWidth = 0; if (*strind != '+' && *strind != '-' && *strind != 'x') { tempWidth = ReadInteger(strind, &nextCharacter); if (strind == nextCharacter) return (0); strind = nextCharacter; mask |= WidthValue; } tempHeight = 0; if (*strind == 'x' || *strind == 'X') { strind++; tempHeight = ReadInteger(strind, &nextCharacter); if (strind == nextCharacter) return (0); strind = nextCharacter; mask |= HeightValue; } tempX = tempY = 0; if ((*strind == '+') || (*strind == '-')) { if (*strind == '-') { strind++; tempX = -ReadInteger(strind, &nextCharacter); if (strind == nextCharacter) return (0); strind = nextCharacter; mask |= XNegative; } else { strind++; tempX = ReadInteger(strind, &nextCharacter); if (strind == nextCharacter) return(0); strind = nextCharacter; } mask |= XValue; if ((*strind == '+') || (*strind == '-')) { if (*strind == '-') { strind++; tempY = -ReadInteger(strind, &nextCharacter); if (strind == nextCharacter) return(0); strind = nextCharacter; mask |= YNegative; } else { strind++; tempY = ReadInteger(strind, &nextCharacter); if (strind == nextCharacter) return(0); strind = nextCharacter; } mask |= YValue; } } /* If strind isn't at the end of the string the it's an invalid geometry specification. */ if (*strind != '\0') return (0); if (mask & XValue) *x = tempX; if (mask & YValue) *y = tempY; if (mask & WidthValue) *width = tempWidth; if (mask & HeightValue) *height = tempHeight; return (mask); } /* =========================================================================== Parse the X-style geometry string */ static int parse_geometry (char *geom, int *x, int *y, unsigned int *width, unsigned int *height) { return XParseGeometry (geom, x, y, width, height); } static void input(int type, char *message) { switch (type) { case LAVREC_MSG_ERROR: mjpeg_error("%s", message); break; case LAVREC_MSG_WARNING: mjpeg_warn("%s", message); break; case LAVREC_MSG_INFO: mjpeg_info("%s", message); break; case LAVREC_MSG_DEBUG: mjpeg_debug("%s", message); break; } } static void * user_input_thread (void * arg) { fd_set rfds; struct timeval timeout; char input_buffer[256]; if (state == LAVREC_STATE_PAUSED) { printf("Press enter to start recording>"); fflush(stdout); } while (state != LAVREC_STATE_STOP) { pthread_testcancel(); /* wait for input */ FD_ZERO(&rfds); FD_SET(0, &rfds); timeout.tv_sec = 0; timeout.tv_usec = 500000; if (select(1, &rfds, 0, 0, &timeout) == 0) continue; /* input timeout */ read(0, input_buffer, sizeof(input_buffer)); switch (state) { case LAVREC_STATE_PAUSED: lavrec_start(info); printf("Press enter to pause recording\n"); break; case LAVREC_STATE_RECORDING: lavrec_pause(info); printf("Press enter to start recording>"); fflush(stdout); break; } } return 0; } static void statechanged(int new) { show_stats = (new == LAVREC_STATE_RECORDING); state = new; sem_post(&state_changed); } #if 0 static void batch_stats(video_capture_stats *stats) { MPEG_timecode_t tc; static int first_stats = 1; static video_capture_stats prev_stats; return; if( first_stats ) { first_stats = 0; prev_stats = *stats; return; } if( stats->num_lost == prev_stats.num_lost && stats->num_ins == prev_stats.num_ins && stats->num_del == prev_stats.num_del && stats->num_aerr == prev_stats.num_aerr ) { return; } prev_stats = *stats; mpeg_timecode(&tc, stats->num_frames, ((info->video_norm!=1)? 3: 4), ((info->video_norm!=1)? 25.: 30000./1001.)); fprintf(stdout, "%2d.%2.2d.%2.2d:%2.2d int: %05ld lst:%4d ins:%3d del:%3d " "ae:%3d td1=%.3f td2=%.3f\n", tc.h, tc.m, tc.s, tc.f, (stats->cur_sync.tv_usec - stats->prev_sync.tv_usec)/1000, stats->num_lost, stats->num_ins, stats->num_del, stats->num_aerr, stats->tdiff1, stats->tdiff2); fflush(stdout); } #endif static void output_stats(video_capture_stats *stats) { num_frames = stats->num_frames; num_lost = stats->num_lost; num_ins = stats->num_ins; num_del = stats->num_del; num_aerr = stats->num_aerr; if (show_stats > 0 && !batch_mode) { MPEG_timecode_t tc; mpeg_timecode(&tc, stats->num_frames, ((info->video_norm!=1)? 3: 4), ((info->video_norm!=1)? 25.: 30000./1001.)); if( stats->prev_sync.tv_usec > stats->cur_sync.tv_usec ) stats->prev_sync.tv_usec -= 1000000; if (info->single_frame) printf("%06d frames captured, press enter for more>", stats->num_frames); else { printf( "%d.%2.2d.%2.2d:%2.2d int:%03ld lst:%3d ins:%3d del:%3d " "ae:%3d td1=%.3f td2=%.3f\r", tc.h, tc.m, tc.s, tc.f, (stats->cur_sync.tv_usec - stats->prev_sync.tv_usec)/1000, stats->num_lost, stats->num_ins, stats->num_del, stats->num_aerr, stats->tdiff1, stats->tdiff2); if(verbose) printf("\n"); // Keep lines from overlapping } fflush(stdout); } } static int set_option(const char *name, char *value) { /* return 1 means error, return 0 means okay */ int nerr = 0; int i = 0; char *norm_i = NULL; if (strcmp(name, "format")==0 || strcmp(name, "f")==0) { info->video_format = value[0]; if(value[0]!='a' && value[0]!='A' && value[0]!='j' #ifdef HAVE_LIBQUICKTIME && value[0]!='q' #endif ) { #ifdef HAVE_LIBQUICKTIME mjpeg_error("Format (-f/--format) must be j, a, A or q"); #else mjpeg_error("Format (-f/--format) must be j, a or A"); #endif nerr++; } } else if (strcmp(name, "input")==0 || strcmp(name, "i")==0) { switch(value[0]) { case 'p': info->video_norm = 0 /* PAL */; info->video_src = 0 /* composite */; break; case 'P': info->video_norm = 0 /* PAL */; info->video_src = 1 /* S-Video */; break; case 'n': info->video_norm = 1 /* NTSC */; info->video_src = 0 /* composite */; break; case 'N': info->video_norm = 1 /* NTSC */; info->video_src = 1 /* S-Video */; break; case 's': info->video_norm = 2 /* SECAM */; info->video_src = 0 /* composite */; break; case 'S': info->video_norm = 2 /* SECAM */; info->video_src = 1 /* S-Video */; break; case 't': info->video_norm = 0 /* PAL */; info->video_src = 2 /* TV-tuner */; break; case 'T': info->video_norm = 1 /* NTSC */; info->video_src = 2 /* TV-tuner */; break; case 'f': info->video_norm = 2 /* SECAM */; info->video_src = 2 /* TV-tuner */; break; case 'a': info->video_norm = 3 /* auto */; info->video_src = -1 /* auto */; break; default: i = atoi(value); if (i>0 && i<11) { info->video_norm = 3 /* auto */; info->video_src = i - 1 /* input */; norm_i = strstr(value, ":"); if(norm_i != NULL && strlen(norm_i) > 1) { if (strcasecmp(norm_i + 1, "pal") == 0) { info->video_norm = 0; } else if (strcasecmp(norm_i + 1, "ntsc") == 0) { info->video_norm = 1; } else if (strcasecmp(norm_i + 1, "secam") == 0) { info->video_norm = 0; } else { mjpeg_error("unknown norm: '%s'", norm_i + 1); nerr++; break; } } } else { mjpeg_error("numeric input must be between 1 and 10"); nerr++; } break; } input_source = value[0]; } else if (strcmp(name, "decimation")==0 || strcmp(name, "d")==0) { int i = atoi(value); if(i<10) { info->horizontal_decimation = info->vertical_decimation = i; } else { info->horizontal_decimation = i/10; info->vertical_decimation = i%10; } if( (info->horizontal_decimation != 1 && info->horizontal_decimation != 2 && info->horizontal_decimation != 4) || (info->vertical_decimation != 1 && info->vertical_decimation != 2 && info->vertical_decimation != 4) ) { mjpeg_error("decimation (-d/--decimation) = %d invalid",i); mjpeg_error(" must be one of 1,2,4,11,12,14,21,22,24,41,42,44"); nerr++; } } else if (strcmp(name, "verbose")==0 || strcmp(name, "v")==0) { verbose = atoi(value); } else if (strcmp(name, "quality")==0 || strcmp(name, "q")==0) { info->quality = atoi(value); if(info->quality<0 || info->quality>100) { mjpeg_error("quality (-q/--quality) = %d invalid (must be 0 ... 100)",info->quality); nerr++; } } else if (strcmp(name, "geometry")==0 || strcmp(name, "g")==0) { parse_geometry (value, &info->geometry->x, &info->geometry->y, &info->geometry->w, &info->geometry->h); } else if (strcmp(name, "time")==0 || strcmp(name, "t")==0) { info->record_time = atoi(value); if(info->record_time<=0) { mjpeg_error("record_time (-t/--time) = %d invalid",info->record_time); nerr++; } } else if (strcmp(name, "batch")==0 || strcmp(name, "B")==0) { batch_mode = 1; } else if (strcmp(name, "single-frame")==0 || strcmp(name, "S")==0) { info->single_frame = 1; } else if (strcmp(name, "use-read")==0 || strcmp(name, "U")==0) { info->use_read = 1; } else if (strcmp(name, "time-lapse")==0 || strcmp(name, "T")==0) { info->time_lapse = atoi(value); if(info->time_lapse<=1) info->time_lapse = 1; } else if (strcmp(name, "wait")==0 || strcmp(name, "w")==0) { wait_for_start = 1; } else if (strcmp(name, "audio-bitsize")==0 || strcmp(name, "a")==0) { info->audio_size = atoi(value); if(info->audio_size != 0 && info->audio_size != 8 && info->audio_size != 16) { mjpeg_error("audio_size (-a/--audio-bitsize) =" " %d invalid (must be 0, 8 or 16)", info->audio_size); nerr++; } } else if (strcmp(name, "audio-bitrate")==0 || strcmp(name, "r")==0) { info->audio_rate = atoi(value); if(info->audio_rate<=0) { mjpeg_error("audio_rate (-r/--audio-bitrate) = %d invalid",info->audio_rate); nerr++; } } else if (strcmp(name, "stereo")==0 || strcmp(name, "s")==0) { info->stereo = 1; } else if (strcmp(name, "audio-volume")==0 || strcmp(name, "l")==0) { info->audio_level = atoi(value); if(info->audio_level<-1 || info->audio_level>100) { mjpeg_error("recording level (-l/--audio-volume)" " = %d invalid (must be 0 ... 100 or -1)", info->audio_level); nerr++; } } else if (strcmp(name, "mute")==0 || strcmp(name, "m")==0) { info->mute = 1; } else if (strcmp(name, "audio-source")==0 || strcmp(name, "R")==0) { info->audio_src = value[0]; if(info->audio_src!='l' && info->audio_src!='m' && info->audio_src!='c' && info->audio_src!='1'&& info->audio_src!='2'&& info->audio_src!='3') { mjpeg_error("Recording source (-R/--audio-source)" " must be l,m,c,1,2, or 3\n"); nerr++; } } else if (strcmp(name, "synchronization")==0 || strcmp(name, "c")==0) { info->sync_correction = atoi(value); if(info->sync_correction<0 || info->sync_correction>2) { mjpeg_error("Synchronization (-c/--synchronization) =" " %d invalid (must be 0, 1 or 2)", info->sync_correction); nerr++; } } else if (strcmp(name, "mjpeg-buffers")==0 || strcmp(name, "n")==0) { info->MJPG_numbufs = atoi(value); } else if (strcmp(name, "mjpeg-buffer-size")==0 || strcmp(name, "b")==0) { info->MJPG_bufsize = atoi(value); } else if (strcmp(name, "frequency")==0 || strcmp(name,"F")==0) { info->tuner_frequency = atoi(value); } else if (strcmp(name, "channel")==0 || strcmp(name,"C")==0) { int colin=0; int chlist=0; int chan=0; /* First look for the colon mark */ while ( value[colin] && value[colin]!=':') colin++; if (value[colin]==0) /* didn't find the colin */ { mjpeg_error("malformed channel parameter (-C/--channel) - example: -C europe-west:SE20"); nerr++; } if (nerr==0) /* Now search for the given channel list in frequencies.c */ while (strncmp(chanlists[chlist].name,value,colin)!=0) { chlist++; /* madmac debug: printf("Searching for channel list: chlist = %d, value=%s\n", chlist, value); */ if (chanlists[chlist].name==NULL) { mjpeg_error("bad frequency map"); nerr++; break; /* bail out */ } } if (nerr==0) /* channel list - get the channel spec */ { /*printf("channel list count is %d\n", chanlists[chlist].count); */ while (strcmp((chanlists[chlist].list)[chan].name, &(value[colin+1]))!=0) { chan++; if (chan > (chanlists[chlist].count)) { mjpeg_error("bad channel spec (see e g xawtv, channel editor, for channel spec)"); nerr++; break; } /*printf("Searching for channel: chan: %d %s\n", chan, (chanlists[chlist].list)[chan].name);*/ } } if (nerr==0) while (strcmp((chanlists[chlist].list)[chan].name, &(value[colin+1]))!=0) { if ((chanlists[chlist].list)[chan++].name==NULL) { mjpeg_error("bad channel spec"); nerr++; } } if (nerr==0) { printf("Ok, found channel %s with frequency %d\n", (chanlists[chlist].list)[chan].name, (chanlists[chlist].list)[chan].freq); info->tuner_frequency=(chanlists[chlist].list)[chan].freq; } } else if (strcmp(name, "software-encoding")==0) { info->software_encoding = 1; /* set the number of enoding processes to the number of processors */ if (info->num_encoders == 0) info->num_encoders = sysconf(_SC_NPROCESSORS_ONLN); } else if( strcmp(name, "software-encoding-yuvp")==0) { info->software_encoding = 2; /* set the number of enoding processes to the number of processors */ if (info->num_encoders == 0) info->num_encoders = sysconf(_SC_NPROCESSORS_ONLN); } else if (strcmp(name, "num-procs")==0) { info->num_encoders = atoi(value); } else if (strcmp(name, "max-file-size")==0) { info->max_file_size_mb = atoi(optarg); } else if (strcmp(name, "max-file-frames")==0) { info->max_file_frames = atoi(optarg); } else if (strcmp(name, "file-flush")==0) { info->flush_count = atoi(optarg); if( info->flush_count < 0 ) info->flush_count = 0; } else nerr++; /* unknown option - error */ return nerr; } static void check_command_line_options(int argc, char *argv[]) { int n, nerr, option_index = 0; char option[2]; char* dotptr; #ifdef HAVE_GETOPT_LONG /* getopt_long options */ static struct option long_options[]={ {"format" ,1,0,0}, /* -f/--format */ {"input" ,1,0,0}, /* -i/--input */ {"decimation" ,1,0,0}, /* -d/--decimation */ {"verbose" ,1,0,0}, /* -v/--verbose */ {"quality" ,1,0,0}, /* -q/--quality */ {"geometry" ,1,0,0}, /* -g/--geometry */ {"time" ,1,0,0}, /* -t/--time */ {"single-frame" ,1,0,0}, /* -S/--single-frame */ {"time-lapse" ,1,0,0}, /* -T/--time-lapse */ {"wait" ,0,0,0}, /* -w/--wait */ {"batch" ,0,0,0}, /* -b/--batch */ {"audio-bitsize" ,1,0,0}, /* -a/--audio-size */ {"audio-bitrate" ,1,0,0}, /* -r/--audio-rate */ {"stereo" ,0,0,0}, /* -s/--stereo */ {"audio-volume" ,1,0,0}, /* -l/--audio-volume */ {"mute" ,0,0,0}, /* -m/--mute */ {"audio-source" ,1,0,0}, /* -R/--audio-source */ {"synchronization" ,1,0,0}, /* -c/--synchronization */ {"mjpeg-buffers" ,1,0,0}, /* -n/--mjpeg_buffers */ {"mjpeg-buffer-size",1,0,0}, /* -b/--mjpeg-buffer-size */ {"channel" ,1,0,0}, /* -C/--channel */ {"use-read" ,0,0,0}, /* -U/--use-read */ {"software-encoding",0,0,0}, /* --software-encoding */ {"software-encoding-yuvp",0,0,0}, /* --software-encoding-yuvp */ {"num-procs" ,1,0,0}, /* --num-procs */ {"max-file-size" ,1,0,0}, /* --max-file-size */ {"max-file-frames" ,1,0,0}, /* --max-file-frames */ {"file-flush" ,1,0,0}, /* --file-flush */ {"frequency" ,1,0,0}, /* --frequency/-F */ {0,0,0,0} }; #endif /* check usage */ if (argc < 2) Usage(argv[0]); /* Get options */ nerr = 0; #ifdef HAVE_GETOPT_LONG while( (n=getopt_long(argc,argv,"v:f:i:d:g:q:t:ST:wa:r:sl:mUBR:c:n:b:C:F:", long_options, &option_index)) != EOF) #else while( (n=getopt(argc,argv,"v:f:i:d:g:q:t:ST:wa:r:sl:mUBR:c:n:b:C:F:")) != EOF) #endif { switch(n) { #ifdef HAVE_GETOPT_LONG /* getopt_long values */ case 0: nerr += set_option(long_options[option_index].name, optarg); break; #endif /* These are the old getopt-values (non-long) */ default: sprintf(option, "%c", n); nerr += set_option(option, optarg); break; } } if (getenv("LAV_VIDEO_DEV")) info->video_dev = getenv("LAV_VIDEO_DEV"); else { struct stat vstat; if((stat("/dev/video", &vstat) == 0) && S_ISCHR(vstat.st_mode)) info->video_dev = "/dev/video"; else if(stat("/dev/video0", &vstat) == 0 && S_ISCHR(vstat.st_mode)) info->video_dev = "/dev/video0"; else if(stat("/dev/v4l/video0", &vstat) == 0 && S_ISCHR(vstat.st_mode)) info->video_dev = "/dev/v4l/video0"; else if(stat("/dev/v4l0", &vstat) == 0 && S_ISCHR(vstat.st_mode)) info->video_dev = "/dev/v4l0"; else if(stat("/dev/v4l", &vstat) == 0 && S_ISCHR(vstat.st_mode)) info->video_dev = "/dev/v4l"; } if (getenv("LAV_AUDIO_DEV")) info->audio_dev = getenv("LAV_AUDIO_DEV"); else { struct stat astat; if(stat("/dev/dsp", &astat) == 0 && S_ISCHR(astat.st_mode)) info->audio_dev = "/dev/dsp"; else if(stat("/dev/sound/dsp", &astat) == 0 && S_ISCHR(astat.st_mode)) info->audio_dev = "/dev/sound/dsp"; else if(stat("/dev/audio", &astat) == 0 && S_ISCHR(astat.st_mode)) info->audio_dev = "/dev/audio"; } if (getenv("LAV_MIXER_DEV")) info->mixer_dev = getenv("LAV_MIXER_DEV"); else { struct stat mstat; if(stat("/dev/mixer", &mstat) == 0 && S_ISCHR(mstat.st_mode)) info->mixer_dev = "/dev/mixer"; else if(stat("/dev/sound/mixer", &mstat) == 0 && S_ISCHR(mstat.st_mode)) info->mixer_dev = "/dev/sound/mixer"; } if(optind>=argc) nerr++; if(nerr) Usage(argv[0]); mjpeg_default_handler_verbosity(verbose); /* disable audio for jpeg */ if (info->video_format == 'j') info->audio_size = 0; info->num_files = argc - optind; info->files = argv + optind; /* If the first filename contains a '%', the user wants file patterns */ if(strstr(argv[optind],"%")) info->num_files = 0; /* Try to guess the file type by looking at the extension. */ if(info->video_format == '\0') { if((dotptr = strrchr(argv[optind], '.'))) { #ifdef HAVE_LIBQUICKTIME if (!strcasecmp(dotptr+1, "mov")) info->video_format = 'q'; #endif if (!strcasecmp(dotptr+1, "avi")) info->video_format = 'a'; } if(info->video_format == '\0') info->video_format = 'a'; } } /* Simply prints recording parameters */ static void lavrec_print_properties(void) { const char *source; char *tmsg; mjpeg_info("Recording parameters:"); if (info->video_format=='q') tmsg = "Quicktime"; else if (info->video_format=='j') tmsg = "JPEG"; else tmsg = "AVI"; mjpeg_info("Output format: %s", tmsg); switch(input_source) { case 'p': source = info->software_encoding?"BT8x8 1st input PAL\n":"Composite PAL\n"; break; case 'P': source = info->software_encoding?"BT8x8 2nd input PAL\n":"S-Video PAL\n"; break; case 'n': source = info->software_encoding?"BT8x8 1st input NTSC\n":"Composite NTSC\n"; break; case 'N': source = info->software_encoding?"BT8x8 2nd input PAL\n":"S-Video NTSC\n"; break; case 's': source = info->software_encoding?"BT8x8 1st input SECAM\n":"Composite SECAM\n"; break; case 'S': source = info->software_encoding?"BT8x8 2nd input PAL\n":"S-Video SECAM\n"; break; case 't': source = info->software_encoding?"BT8x8 3rd input PAL\n":"PAL TV-tuner\n"; break; case 'T': source = info->software_encoding?"BT8x8 3rd input PAL\n":"NTSC TV-tuner\n"; break; case 'f': source = info->software_encoding?"BT8x8 3rd input PAL\n":"SECAM TV-tuner\n"; break; //sam Fix numeric source default: source = "Auto detect\n"; } mjpeg_info("Input Source: %s", source); if(info->horizontal_decimation == info->vertical_decimation) mjpeg_info("Decimation: %d", info->horizontal_decimation); else mjpeg_info("Decimation: %d (hor) x %d (ver)", info->horizontal_decimation, info->vertical_decimation); mjpeg_info("Quality: %d",info->quality); mjpeg_info("Recording time: %d sec",info->record_time); if(info->time_lapse>1) mjpeg_info("Time lapse factor: %d",info->time_lapse); mjpeg_info(" "); mjpeg_info("MJPEG buffer size: %d KB",info->MJPG_bufsize); mjpeg_info("# of MJPEG buffers: %d",info->MJPG_numbufs); if(info->audio_size) { mjpeg_info("Audio parameters:"); mjpeg_info("Audio sample size: %d bit",info->audio_size); mjpeg_info("Audio sampling rate: %d Hz",info->audio_rate); mjpeg_info("Audio is %s",info->stereo ? "STEREO" : "MONO"); if(info->audio_level!=-1) { mjpeg_info("Audio input recording level: %d%%", info->audio_level); mjpeg_info("%s audio output during recording", info->mute?"Mute":"Don\'t mute"); mjpeg_info("Recording source: %c",info->audio_src); } else mjpeg_info("Audio input recording level: Use mixer setting"); mjpeg_info("Level of correction for Audio/Video synchronization:"); switch(info->sync_correction) { case 0: mjpeg_info("No lost frame compensation, No frame drop/insert"); break; case 1: mjpeg_info("Lost frame compensation, No frame drop/insert"); break; case 2: mjpeg_info("Lost frame compensation and frame drop/insert"); break; } } else mjpeg_info("Audio disabled"); } static void print_summary(void) { MPEG_timecode_t tc; mpeg_timecode(&tc, num_frames, ((info->video_norm==1)?4:3), ((info->video_norm==1)?(30000/1001):25.)); printf("Recording time : %2d.%2.2d.%2.2d:%2.2d\n" "Lost frames : %d\n" "A/V sync ins/del: %d/%d\n" "Audio errors : %d\n", tc.h, tc.m, tc.s, tc.f, num_lost, num_ins, num_del, num_aerr); } static void * signal_catcher_thread (void * arg) { sigset_t * sigs = arg; int sig; sigwait(sigs, &sig); lavrec_stop(info); return 0; } static void signal_forwarder (int sig) { pthread_kill(signal_thread, sig); } static void forward_signals (sigset_t * sigs) { struct sigaction sa; int sig; sa.sa_handler = signal_forwarder; sigfillset(&sa.sa_mask); sa.sa_flags = SA_RESTART; for (sig = 1; sig < 32; sig++) if (sigismember(sigs, sig) > 0) sigaction(sig, &sa, 0); pthread_sigmask(SIG_UNBLOCK, sigs, 0); } int main(int argc, char **argv) { sigset_t sigmask; pthread_t input_thread; /* no root please (only during audio setup) */ if (getuid() != geteuid()) { if (setfsuid(getuid()) < 0) { mjpeg_error("Failed to set filesystem user ID: %s", strerror(errno)); return 0; } } info = lavrec_malloc(); info->state_changed = statechanged; info->msg_callback = input; check_command_line_options(argc, argv); lavrec_print_properties(); /* if( batch_mode ) */ /* info->output_statistics = batch_stats; */ /* else */ info->output_statistics = output_stats; sem_init(&state_changed, 0, 0); state = LAVREC_STATE_PAUSED; /* Block all signals */ sigfillset(&sigmask); pthread_sigmask(SIG_SETMASK, &sigmask, 0); sigemptyset(&sigmask); sigaddset(&sigmask, SIGHUP); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); sigaddset(&sigmask, SIGTERM); /* Start signal catching thread */ pthread_create(&signal_thread, NULL, signal_catcher_thread, &sigmask); /* Catch and forward selected signals to the signal catcher */ forward_signals(&sigmask); if ((lavrec_main(info)) != 1) { mjpeg_error_exit1("Something went wrong while setting up the card"); print_summary(); lavrec_free(info); } if (!wait_for_start) lavrec_start(info); if (!batch_mode) pthread_create(&input_thread, NULL, user_input_thread, NULL); lavrec_busy(info); pthread_cancel(signal_thread); pthread_join(signal_thread, 0); if (!batch_mode) { pthread_cancel(input_thread); pthread_join(input_thread, 0); } sem_destroy(&state_changed); fprintf(stderr, "\n"); print_summary(); lavrec_free(info); return 0; } mjpegtools-2.1.0/lavtools/avilib.h0000644000175000017500000003562610325233740017506 0ustar glowwormglowworm/* * avilib.h * * Copyright (C) Thomas Östreich - June 2001 * multiple audio track support Copyright (C) 2002 Thomas Östreich * * Original code: * Copyright (C) 1999 Rainer Johanni * * This file is part of transcode, a video stream processing tool * * transcode is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * transcode is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Make; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include #include #include #include #include #include #include #ifndef AVILIB_H #define AVILIB_H #define AVI_MAX_TRACKS 8 typedef struct { off_t key; off_t pos; off_t len; } video_index_entry; typedef struct { off_t pos; off_t len; off_t tot; } audio_index_entry; // Index types #define AVI_INDEX_OF_INDEXES 0x00 // when each entry in aIndex // array points to an index chunk #define AVI_INDEX_OF_CHUNKS 0x01 // when each entry in aIndex // array points to a chunk in the file #define AVI_INDEX_IS_DATA 0x80 // when each entry is aIndex is // really the data // bIndexSubtype codes for INDEX_OF_CHUNKS // #define AVI_INDEX_2FIELD 0x01 // when fields within frames // are also indexed typedef struct _avisuperindex_entry { uint64_t qwOffset; // absolute file offset uint32_t dwSize; // size of index chunk at this offset uint32_t dwDuration; // time span in stream ticks } avisuperindex_entry; typedef struct _avistdindex_entry { uint32_t dwOffset; // qwBaseOffset + this is absolute file offset uint32_t dwSize; // bit 31 is set if this is NOT a keyframe } avistdindex_entry; // Standard index typedef struct _avistdindex_chunk { char fcc[4]; // ix## uint32_t dwSize; // size of this chunk uint16_t wLongsPerEntry; // must be sizeof(aIndex[0])/sizeof(DWORD) uint8_t bIndexSubType; // must be 0 uint8_t bIndexType; // must be AVI_INDEX_OF_CHUNKS uint32_t nEntriesInUse; // char dwChunkId[4]; // '##dc' or '##db' or '##wb' etc.. uint64_t qwBaseOffset; // all dwOffsets in aIndex array are relative to this uint32_t dwReserved3; // must be 0 avistdindex_entry *aIndex; } avistdindex_chunk; // Base Index Form 'indx' typedef struct _avisuperindex_chunk { char fcc[4]; uint32_t dwSize; // size of this chunk uint16_t wLongsPerEntry; // size of each entry in aIndex array (must be 8 for us) uint8_t bIndexSubType; // future use. must be 0 uint8_t bIndexType; // one of AVI_INDEX_* codes uint32_t nEntriesInUse; // index of first unused member in aIndex array char dwChunkId[4]; // fcc of what is indexed uint32_t dwReserved[3]; // meaning differs for each index type/subtype. // 0 if unused avisuperindex_entry *aIndex; // where are the ix## chunks avistdindex_chunk **stdindex; // the ix## chunks itself (array) } avisuperindex_chunk; typedef struct track_s { long a_fmt; /* Audio format, see #defines below */ long a_chans; /* Audio channels, 0 for no audio */ long a_rate; /* Rate in Hz */ long a_bits; /* bits per audio sample */ long mp3rate; /* mp3 bitrate kbs*/ long a_vbr; /* 0 == no Variable BitRate */ long padrate; /* byte rate used for zero padding */ long audio_strn; /* Audio stream number */ off_t audio_bytes; /* Total number of bytes of audio data */ long audio_chunks; /* Chunks of audio data in the file */ char audio_tag[4]; /* Tag of audio data */ long audio_posc; /* Audio position: chunk */ long audio_posb; /* Audio position: byte within chunk */ off_t a_codech_off; /* absolut offset of audio codec information */ off_t a_codecf_off; /* absolut offset of audio codec information */ audio_index_entry *audio_index; avisuperindex_chunk *audio_superindex; } track_t; typedef struct { uint32_t bi_size; uint32_t bi_width; uint32_t bi_height; uint16_t bi_planes; uint16_t bi_bit_count; uint32_t bi_compression; uint32_t bi_size_image; uint32_t bi_x_pels_per_meter; uint32_t bi_y_pels_per_meter; uint32_t bi_clr_used; uint32_t bi_clr_important; } alBITMAPINFOHEADER; typedef struct __attribute__((__packed__)) { uint16_t w_format_tag; uint16_t n_channels; uint32_t n_samples_per_sec; uint32_t n_avg_bytes_per_sec; uint16_t n_block_align; uint16_t w_bits_per_sample; uint16_t cb_size; } alWAVEFORMATEX; typedef struct __attribute__((__packed__)) { uint32_t fcc_type; uint32_t fcc_handler; uint32_t dw_flags; uint32_t dw_caps; uint16_t w_priority; uint16_t w_language; uint32_t dw_scale; uint32_t dw_rate; uint32_t dw_start; uint32_t dw_length; uint32_t dw_initial_frames; uint32_t dw_suggested_buffer_size; uint32_t dw_quality; uint32_t dw_sample_size; uint32_t dw_left; uint32_t dw_top; uint32_t dw_right; uint32_t dw_bottom; uint32_t dw_edit_count; uint32_t dw_format_change_count; char sz_name[64]; } alAVISTREAMINFO; typedef struct { long fdes; /* File descriptor of AVI file */ long mode; /* 0 for reading, 1 for writing */ long width; /* Width of a video frame */ long height; /* Height of a video frame */ double fps; /* Frames per second */ char compressor[8]; /* Type of compressor, 4 bytes + padding for 0 byte */ char compressor2[8]; /* Type of compressor, 4 bytes + padding for 0 byte */ long video_strn; /* Video stream number */ long video_frames; /* Number of video frames */ char video_tag[4]; /* Tag of video data */ long video_pos; /* Number of next frame to be read (if index present) */ uint32_t max_len; /* maximum video chunk present */ track_t track[AVI_MAX_TRACKS]; // up to AVI_MAX_TRACKS audio tracks supported off_t pos; /* position in file */ long n_idx; /* number of index entries actually filled */ long max_idx; /* number of index entries actually allocated */ off_t v_codech_off; /* absolut offset of video codec (strh) info */ off_t v_codecf_off; /* absolut offset of video codec (strf) info */ uint8_t (*idx)[16]; /* index entries (AVI idx1 tag) */ video_index_entry *video_index; avisuperindex_chunk *video_superindex; /* index of indices */ int is_opendml; /* set to 1 if this is an odml file with multiple index chunks */ off_t last_pos; /* Position of last frame written */ uint32_t last_len; /* Length of last frame written */ int must_use_index; /* Flag if frames are duplicated */ off_t movi_start; int total_frames; /* total number of frames if dmlh is present */ int anum; // total number of audio tracks int aptr; // current audio working track int comment_fd; // Read avi header comments from this fd char *index_file; // read the avi index from this file alBITMAPINFOHEADER *bitmap_info_header; alWAVEFORMATEX *wave_format_ex[AVI_MAX_TRACKS]; void* extradata; unsigned long extradata_size; } avi_t; #define AVI_fileno(a) (a->fdes) #define AVI_MODE_WRITE 0 #define AVI_MODE_READ 1 /* The error codes delivered by avi_open_input_file */ #define AVI_ERR_SIZELIM 1 /* The write of the data would exceed the maximum size of the AVI file. This is more a warning than an error since the file may be closed safely */ #define AVI_ERR_OPEN 2 /* Error opening the AVI file - wrong path name or file nor readable/writable */ #define AVI_ERR_READ 3 /* Error reading from AVI File */ #define AVI_ERR_WRITE 4 /* Error writing to AVI File, disk full ??? */ #define AVI_ERR_WRITE_INDEX 5 /* Could not write index to AVI file during close, file may still be usable */ #define AVI_ERR_CLOSE 6 /* Could not write header to AVI file or not truncate the file during close, file is most probably corrupted */ #define AVI_ERR_NOT_PERM 7 /* Operation not permitted: trying to read from a file open for writing or vice versa */ #define AVI_ERR_NO_MEM 8 /* malloc failed */ #define AVI_ERR_NO_AVI 9 /* Not an AVI file */ #define AVI_ERR_NO_HDRL 10 /* AVI file has no has no header list, corrupted ??? */ #define AVI_ERR_NO_MOVI 11 /* AVI file has no has no MOVI list, corrupted ??? */ #define AVI_ERR_NO_VIDS 12 /* AVI file contains no video data */ #define AVI_ERR_NO_IDX 13 /* The file has been opened with getIndex==0, but an operation has been performed that needs an index */ /* Possible Audio formats */ #ifndef WAVE_FORMAT_PCM #define WAVE_FORMAT_UNKNOWN (0x0000) #define WAVE_FORMAT_PCM (0x0001) #define WAVE_FORMAT_ADPCM (0x0002) #define WAVE_FORMAT_IBM_CVSD (0x0005) #define WAVE_FORMAT_ALAW (0x0006) #define WAVE_FORMAT_MULAW (0x0007) #define WAVE_FORMAT_OKI_ADPCM (0x0010) #define WAVE_FORMAT_DVI_ADPCM (0x0011) #define WAVE_FORMAT_DIGISTD (0x0015) #define WAVE_FORMAT_DIGIFIX (0x0016) #define WAVE_FORMAT_YAMAHA_ADPCM (0x0020) #define WAVE_FORMAT_DSP_TRUESPEECH (0x0022) #define WAVE_FORMAT_GSM610 (0x0031) #define IBM_FORMAT_MULAW (0x0101) #define IBM_FORMAT_ALAW (0x0102) #define IBM_FORMAT_ADPCM (0x0103) #endif avi_t* AVI_open_output_file(char * filename); void AVI_set_video(avi_t *AVI, int width, int height, double fps, char *compressor); void AVI_set_audio(avi_t *AVI, int channels, long rate, int bits, int format, long mp3rate); int AVI_write_frame(avi_t *AVI, char *data, long bytes, int keyframe); int AVI_dup_frame(avi_t *AVI); int AVI_write_audio(avi_t *AVI, char *data, long bytes); int AVI_append_audio(avi_t *AVI, char *data, long bytes); long AVI_bytes_remain(avi_t *AVI); int AVI_close(avi_t *AVI); long AVI_bytes_written(avi_t *AVI); avi_t *AVI_open_input_file(char *filename, int getIndex); avi_t *AVI_open_input_indexfile(char *filename, int getIndex, char *indexfile); avi_t *AVI_open_fd(int fd, int getIndex); avi_t *AVI_open_indexfd(int fd, int getIndex, char *indexfile); int avi_parse_input_file(avi_t *AVI, int getIndex); int avi_parse_index_from_file(avi_t *AVI, char *filename); long AVI_audio_mp3rate(avi_t *AVI); long AVI_audio_padrate(avi_t *AVI); long AVI_video_frames(avi_t *AVI); int AVI_video_width(avi_t *AVI); int AVI_video_height(avi_t *AVI); double AVI_frame_rate(avi_t *AVI); char* AVI_video_compressor(avi_t *AVI); int AVI_audio_channels(avi_t *AVI); int AVI_audio_bits(avi_t *AVI); int AVI_audio_format(avi_t *AVI); long AVI_audio_rate(avi_t *AVI); long AVI_audio_bytes(avi_t *AVI); long AVI_audio_chunks(avi_t *AVI); int AVI_can_read_audio(avi_t *AVI); long AVI_max_video_chunk(avi_t *AVI); long AVI_frame_size(avi_t *AVI, long frame); long AVI_audio_size(avi_t *AVI, long frame); int AVI_seek_start(avi_t *AVI); int AVI_set_video_position(avi_t *AVI, long frame); long AVI_get_video_position(avi_t *AVI, long frame); long AVI_read_frame(avi_t *AVI, char *vidbuf, int *keyframe); int AVI_set_audio_position(avi_t *AVI, long byte); int AVI_set_audio_bitrate(avi_t *AVI, long bitrate); long AVI_get_audio_position_index(avi_t *AVI); int AVI_set_audio_position_index(avi_t *AVI, long indexpos); long AVI_read_audio(avi_t *AVI, char *audbuf, long bytes); long AVI_read_audio_chunk(avi_t *AVI, char *audbuf); long AVI_audio_codech_offset(avi_t *AVI); long AVI_audio_codecf_offset(avi_t *AVI); long AVI_video_codech_offset(avi_t *AVI); long AVI_video_codecf_offset(avi_t *AVI); int AVI_read_data(avi_t *AVI, char *vidbuf, long max_vidbuf, char *audbuf, long max_audbuf, long *len); void AVI_print_error(char *str); char *AVI_strerror(void); char *AVI_syserror(void); int AVI_scan(char *name); int AVI_dump(char *name, int mode); char *AVI_codec2str(short cc); int AVI_file_check(char *import_file); void AVI_info(avi_t *avifile); uint64_t AVI_max_size(void); int avi_update_header(avi_t *AVI); int AVI_set_audio_track(avi_t *AVI, int track); int AVI_get_audio_track(avi_t *AVI); int AVI_audio_tracks(avi_t *AVI); void AVI_set_audio_vbr(avi_t *AVI, long is_vbr); long AVI_get_audio_vbr(avi_t *AVI); void AVI_set_comment_fd(avi_t *AVI, int fd); int AVI_get_comment_fd(avi_t *AVI); struct riff_struct { uint8_t id[4]; /* RIFF */ uint32_t len; uint8_t wave_id[4]; /* WAVE */ }; struct chunk_struct { uint8_t id[4]; uint32_t len; }; struct common_struct { uint16_t wFormatTag; uint16_t wChannels; uint32_t dwSamplesPerSec; uint32_t dwAvgBytesPerSec; uint16_t wBlockAlign; uint16_t wBitsPerSample; /* Only for PCM */ }; struct wave_header { struct riff_struct riff; struct chunk_struct format; struct common_struct common; struct chunk_struct data; }; // Simple WAV IO int AVI_read_wave_header( int fd, struct wave_header * wave ); int AVI_write_wave_header( int fd, const struct wave_header * wave ); size_t AVI_read_wave_pcm_data( int fd, void * buffer, size_t buflen ); size_t AVI_write_wave_pcm_data( int fd, const void * buffer, size_t buflen ); #endif mjpegtools-2.1.0/lavtools/lavinfo.c0000644000175000017500000000474210570657730017677 0ustar glowwormglowworm/* lavinfo - give info * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include int verbose = -1; EditList el; int main(int argc, char *argv[]) { const char *p; if(argc <=1) { printf("Usage: %s file1 [ file2 file3 ... ]\n",argv[0]); printf("\ttakes a list of editlist or lav files, and prints out info about them\n"); printf("\tmust all be of same dimensions\n"); exit(1); } (void)mjpeg_default_handler_verbosity(verbose); read_video_files(argv+1, argc-1, &el,0); /* Video */ printf("video_frames=%li\n",el.video_frames); printf("video_width=%li\n",el.video_width); printf("video_height=%li\n",el.video_height); switch (el.video_inter) { case Y4M_ILACE_NONE: p = "p"; break; case Y4M_ILACE_BOTTOM_FIRST: p = "b"; break; case Y4M_ILACE_TOP_FIRST: p = "t"; break; case Y4M_ILACE_MIXED: p = "m"; break; default: p = "***BOGUS/UNKNOWN***"; break; } printf("video_inter=%s\n", p); printf("video_norm=%s\n",el.video_norm=='n'?"NTSC":"PAL"); printf("video_fps=%f\n",el.video_fps); printf("video_sar_width=%i\n",el.video_sar_width); printf("video_sar_height=%i\n",el.video_sar_height); printf("max_frame_size=%li\n",el.max_frame_size); p = y4m_chroma_keyword(el.chroma); if (p == NULL) p = "Bogus/unknown chroma sampling"; printf("chroma=%s\n", p); /* Audio */ printf("has_audio=%i\n",el.has_audio); printf("audio_bps=%i\n",el.audio_bps); printf("audio_chans=%i\n",el.audio_chans); printf("audio_bits=%i\n",el.audio_bits); printf("audio_rate=%ld\n",el.audio_rate); /* Misc */ printf("num_video_files=%li\n",el.num_video_files); exit(0); } mjpegtools-2.1.0/lavtools/ppmtoy4m.c0000644000175000017500000004404610603772216020025 0ustar glowwormglowworm/* * ppmtoy4m.c: Generate a YUV4MPEG2 stream from one or more PPM images * * Converts R'G'B' to ITU-Rec.601 Y'CbCr colorspace and * performs 4:2:0 chroma subsampling. * * * Copyright (C) 2004 Matthew J. Marjanovic * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include #include #include #include #include #include #include #include "subsample.h" #include "colorspace.h" #ifndef O_BINARY # define O_BINARY 0 #endif #define DEFAULT_CHROMA_MODE Y4M_CHROMA_444 /* command-line parameters */ typedef struct _cl_info { y4m_ratio_t aspect; y4m_ratio_t framerate; int interlace; int interleave; int offset; int framecount; int repeatlast; int ss_mode; int verbosity; int fdin; int bgr; } cl_info_t; /* PPM image information */ typedef struct _ppm_info { int width; int height; } ppm_info_t; static void usage(const char *progname) { fprintf(stderr, "\n"); fprintf(stderr, "usage: %s [options] [ppm-file]\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "Reads RAW PPM image(s), and produces YUV4MPEG2 stream on stdout.\n"); fprintf(stderr, "Converts computer graphics R'G'B' colorspace to digital video Y'CbCr,\n"); fprintf(stderr, " and performs chroma subsampling.\n"); fprintf(stderr, "\n"); fprintf(stderr, "If 'ppm-file' is not specified, reads from stdin.\n"); fprintf(stderr, "\n"); fprintf(stderr, " options: (defaults specified in [])\n"); fprintf(stderr, "\n"); fprintf(stderr, " -o n frame offset (skip n input frames) [0]\n"); fprintf(stderr, " -n n frame count (output n frames; 0 == all of them) [0]\n"); fprintf(stderr, " -F n:d framerate [30000:1001 = NTSC]\n"); fprintf(stderr, " -A w:h pixel aspect ratio [1:1]\n"); fprintf(stderr, " -I x interlacing [p]\n"); fprintf(stderr, " p = none/progressive\n"); fprintf(stderr, " t = top-field-first\n"); fprintf(stderr, " b = bottom-field-first\n"); fprintf(stderr, " -L treat PPM images as 2-field interleaved\n"); fprintf(stderr, " -r repeat last input frame\n"); { int m; const char *keyword; fprintf(stderr, " -S mode chroma subsampling mode [%s]\n", y4m_chroma_keyword(DEFAULT_CHROMA_MODE)); for (m = 0; (keyword = y4m_chroma_keyword(m)) != NULL; m++) if (chroma_sub_implemented(m)) fprintf(stderr, " '%s' -> %s\n", keyword, y4m_chroma_description(m)); } /* fprintf(stderr, " -R type subsampling filter type\n");*/ fprintf(stderr, " -v n verbosity (0,1,2) [1]\n"); fprintf(stderr, " -B PPM image is packed with BGR pixels [RGB]\n"); } static void parse_args(cl_info_t *cl, int argc, char **argv) { int c; cl->offset = 0; cl->framecount = 0; cl->aspect = y4m_sar_SQUARE; cl->interlace = Y4M_ILACE_NONE; cl->framerate = y4m_fps_NTSC; cl->interleave = 0; cl->repeatlast = 0; cl->ss_mode = DEFAULT_CHROMA_MODE; cl->verbosity = 1; cl->bgr = 0; cl->fdin = fileno(stdin); /* default to stdin */ while ((c = getopt(argc, argv, "BA:F:I:Lo:n:rS:v:h")) != -1) { switch (c) { case 'A': if (y4m_parse_ratio(&(cl->aspect), optarg) != Y4M_OK) { mjpeg_error("Could not parse ratio: '%s'", optarg); goto ERROR_EXIT; } break; case 'F': if (y4m_parse_ratio(&(cl->framerate), optarg) != Y4M_OK) { mjpeg_error("Could not parse ratio: '%s'", optarg); goto ERROR_EXIT; } break; case 'I': switch (optarg[0]) { case 'p': cl->interlace = Y4M_ILACE_NONE; break; case 't': cl->interlace = Y4M_ILACE_TOP_FIRST; break; case 'b': cl->interlace = Y4M_ILACE_BOTTOM_FIRST; break; default: mjpeg_error("Unknown value for interlace: '%c'", optarg[0]); goto ERROR_EXIT; break; } break; case 'L': cl->interleave = 1; break; case 'B': cl->bgr = 1; break; case 'o': if ((cl->offset = atoi(optarg)) < 0) mjpeg_error_exit1("Offset must be >= 0: '%s'", optarg); break; case 'n': if ((cl->framecount = atoi(optarg)) < 0) mjpeg_error_exit1("Frame count must be >= 0: '%s'", optarg); break; case 'r': cl->repeatlast = 1; break; case 'S': cl->ss_mode = y4m_chroma_parse_keyword(optarg); if (cl->ss_mode == Y4M_UNKNOWN) { mjpeg_error("Unknown subsampling mode option: %s", optarg); goto ERROR_EXIT; } else if (!chroma_sub_implemented(cl->ss_mode)) { mjpeg_error("Unsupported subsampling mode option: %s", optarg); goto ERROR_EXIT; } break; case 'v': cl->verbosity = atoi(optarg); if ((cl->verbosity < 0) || (cl->verbosity > 2)) mjpeg_error("Verbosity must be 0, 1, or 2: '%s'", optarg); break; case 'h': usage(argv[0]); exit(0); break; case '?': default: goto ERROR_EXIT; break; } } /* optional remaining argument is a filename */ if (optind == (argc - 1)) { if ((cl->fdin = open(argv[optind], O_RDONLY | O_BINARY)) == -1) mjpeg_error_exit1("Failed to open '%s': %s", argv[optind], strerror(errno)); } else if (optind != argc) goto ERROR_EXIT; mjpeg_default_handler_verbosity(cl->verbosity); mjpeg_info("Command-line Parameters:"); mjpeg_info(" framerate: %d:%d", cl->framerate.n, cl->framerate.d); mjpeg_info(" pixel aspect ratio: %d:%d", cl->aspect.n, cl->aspect.d); mjpeg_info(" pixel packing: %s", cl->bgr?"BGR":"RGB"); mjpeg_info(" interlace: %s%s", mpeg_interlace_code_definition(cl->interlace), (cl->interlace == Y4M_ILACE_NONE) ? "" : (cl->interleave) ? " (interleaved PPM input)" : " (field-sequential PPM input)"); mjpeg_info(" starting frame: %d", cl->offset); if (cl->framecount == 0) mjpeg_info(" # of frames: all%s", (cl->repeatlast) ? ", repeat last frame forever" : ", until input exhausted"); else mjpeg_info(" # of frames: %d%s", cl->framecount, (cl->repeatlast) ? ", repeat last frame until done" : ", or until input exhausted"); mjpeg_info(" chroma subsampling: %s", y4m_chroma_description(cl->ss_mode)); /* DONE! */ return; ERROR_EXIT: mjpeg_error("For usage hints, use option '-h'. Please take a hint."); exit(1); } /* * returns: 0 - success, got header * 1 - EOF, no new frame * -1 - failure */ #define DO_READ_NUMBER(var) \ do { \ if (!isdigit(s[0])) \ mjpeg_error_exit1("PPM read error: bad char"); \ (var) = ((var) * 10) + (s[0] - '0'); \ } while (((n = read(fd, s, 1)) == 1) && (!isspace(s[0]))); \ if (n <= 0) return -1; #define DO_SKIP_WHITESPACE() \ incomment = 0; \ while ( ((n = read(fd, s, 1)) == 1) && \ ((isspace(s[0])) || (s[0] == '#') || (incomment)) ) { \ if (s[0] == '#') incomment = 1; \ if (s[0] == '\n') incomment = 0; \ } \ if (n <= 0) return -1; static int read_ppm_header(int fd, int *width, int *height) { char s[6]; int incomment; int n; int maxval = 0; *width = 0; *height = 0; /* look for "P6" */ n = y4m_read(fd, s, 3); if (n > 0) return 1; /* EOF */ if ((n < 0) || (strncmp(s, "P6", 2))) mjpeg_error_exit1("Bad Raw PPM magic!"); incomment = 0; DO_SKIP_WHITESPACE(); DO_READ_NUMBER(*width); DO_SKIP_WHITESPACE(); DO_READ_NUMBER(*height); DO_SKIP_WHITESPACE(); DO_READ_NUMBER(maxval); if (maxval != 255) mjpeg_error_exit1("Expecting maxval == 255, not %d!", maxval); return 0; } static void alloc_buffers(uint8_t *buffers[], int width, int height) { mjpeg_debug("Alloc'ing buffers"); buffers[0] = malloc(width * height * 2 * sizeof(buffers[0][0])); buffers[1] = malloc(width * height * 2 * sizeof(buffers[1][0])); buffers[2] = malloc(width * height * 2 * sizeof(buffers[2][0])); } static void read_ppm_into_two_buffers(int fd, uint8_t *buffers[], uint8_t *buffers2[], uint8_t *rowbuffer, int width, int height, int bgr) { int x, y; uint8_t *pixels; uint8_t *R = buffers[0]; uint8_t *G = buffers[1]; uint8_t *B = buffers[2]; uint8_t *R2 = buffers2[0]; uint8_t *G2 = buffers2[1]; uint8_t *B2 = buffers2[2]; mjpeg_debug("read into two buffers, %dx%d", width, height); height /= 2; for (y = 0; y < height; y++) { pixels = rowbuffer; if (y4m_read(fd, pixels, width * 3)) mjpeg_error_exit1("read error A y=%d", y); if (bgr) { for (x = 0; x < width; x++) { *(B++) = *(pixels++); *(G++) = *(pixels++); *(R++) = *(pixels++); } } else { for (x = 0; x < width; x++) { *(R++) = *(pixels++); *(G++) = *(pixels++); *(B++) = *(pixels++); } } pixels = rowbuffer; if (y4m_read(fd, pixels, width * 3)) mjpeg_error_exit1("read error B y=%d", y); if (bgr) { for (x = 0; x < width; x++) { *(B2++) = *(pixels++); *(G2++) = *(pixels++); *(R2++) = *(pixels++); } } else { for (x = 0; x < width; x++) { *(R2++) = *(pixels++); *(G2++) = *(pixels++); *(B2++) = *(pixels++); } } } } static void read_ppm_into_one_buffer(int fd, uint8_t *buffers[], uint8_t *rowbuffer, int width, int height, int bgr) { int x, y; uint8_t *pixels; uint8_t *R = buffers[0]; uint8_t *G = buffers[1]; uint8_t *B = buffers[2]; for (y = 0; y < height; y++) { pixels = rowbuffer; y4m_read(fd, pixels, width * 3); if (bgr) { for (x = 0; x < width; x++) { *(B++) = *(pixels++); *(G++) = *(pixels++); *(R++) = *(pixels++); } } else { for (x = 0; x < width; x++) { *(R++) = *(pixels++); *(G++) = *(pixels++); *(B++) = *(pixels++); } } } } /* * read one whole frame * if field-sequential interlaced, this requires reading two PPM images * * if interlaced, fields are written into separate buffers * * ppm.width/height refer to image dimensions */ static int read_ppm_frame(int fd, ppm_info_t *ppm, uint8_t *buffers[], uint8_t *buffers2[], int ilace, int ileave, int bgr) { int width, height; static uint8_t *rowbuffer = NULL; int err; err = read_ppm_header(fd, &width, &height); if (err > 0) return 1; /* EOF */ if (err < 0) return -1; /* error */ mjpeg_debug("Got PPM header: %dx%d", width, height); if (ppm->width == 0) { /* first time */ mjpeg_debug("Initializing PPM read_frame"); ppm->width = width; ppm->height = height; rowbuffer = malloc(width * 3 * sizeof(rowbuffer[0])); } else { /* make sure everything matches */ if ( (ppm->width != width) || (ppm->height != height) ) mjpeg_error_exit1("One of these frames is not like the others!"); } if (buffers[0] == NULL) alloc_buffers(buffers, width, height); if ((buffers2[0] == NULL) && (ilace != Y4M_ILACE_NONE)) alloc_buffers(buffers2, width, height); mjpeg_debug("Reading rows"); if ((ilace != Y4M_ILACE_NONE) && (ileave)) { /* Interlaced and Interleaved: --> read image and deinterleave fields at same time */ if (ilace == Y4M_ILACE_TOP_FIRST) { /* 1st buff arg == top field == temporally first == "buffers" */ read_ppm_into_two_buffers(fd, buffers, buffers2, rowbuffer, width, height, bgr); } else { /* bottom-field-first */ /* 1st buff art == top field == temporally second == "buffers2" */ read_ppm_into_two_buffers(fd, buffers2, buffers, rowbuffer, width, height, bgr); } } else if ((ilace == Y4M_ILACE_NONE) || (!ileave)) { /* Not Interlaced, or Not Interleaved: --> read image into first buffer... */ read_ppm_into_one_buffer(fd, buffers, rowbuffer, width, height, bgr); if ((ilace != Y4M_ILACE_NONE) && (!ileave)) { /* ...Actually Interlaced: --> read the second image/field into second buffer */ err = read_ppm_header(fd, &width, &height); if (err > 0) return 1; /* EOF */ if (err < 0) return -1; /* error */ mjpeg_debug("Got PPM header: %dx%d", width, height); /* make sure everything matches */ if ( (ppm->width != width) || (ppm->height != height) ) mjpeg_error_exit1("One of these frames is not like the others!"); read_ppm_into_one_buffer(fd, buffers2, rowbuffer, width, height, bgr); } } return 0; } static void setup_output_stream(int fdout, cl_info_t *cl, y4m_stream_info_t *sinfo, ppm_info_t *ppm, int *field_height) { int err; int x_alignment = y4m_chroma_ss_x_ratio(cl->ss_mode).d; int y_alignment = y4m_chroma_ss_y_ratio(cl->ss_mode).d; if (cl->interlace != Y4M_ILACE_NONE) y_alignment *= 2; if ((ppm->width % x_alignment) != 0) { mjpeg_error_exit1("PPM width (%d) is not a multiple of %d!", ppm->width, x_alignment); } if ((ppm->height % y_alignment) != 0) { mjpeg_error_exit1("PPM height (%d) is not a multiple of %d!", ppm->height, y_alignment); } y4m_si_set_width(sinfo, ppm->width); if (cl->interlace == Y4M_ILACE_NONE) { y4m_si_set_height(sinfo, ppm->height); *field_height = ppm->height; } else if (cl->interleave) { y4m_si_set_height(sinfo, ppm->height); *field_height = ppm->height / 2; } else { y4m_si_set_height(sinfo, ppm->height * 2); *field_height = ppm->height; } y4m_si_set_sampleaspect(sinfo, cl->aspect); y4m_si_set_interlace(sinfo, cl->interlace); y4m_si_set_framerate(sinfo, cl->framerate); y4m_si_set_chroma(sinfo, cl->ss_mode); if ((err = y4m_write_stream_header(fdout, sinfo)) != Y4M_OK) mjpeg_error_exit1("Write header failed: %s", y4m_strerr(err)); mjpeg_info("Output Stream parameters:"); y4m_log_stream_info(mjpeg_loglev_t("info"), " ", sinfo); } int main(int argc, char **argv) { cl_info_t cl; y4m_stream_info_t sinfo; y4m_frame_info_t finfo; uint8_t *buffers[Y4M_MAX_NUM_PLANES]; /* R'G'B' or Y'CbCr */ uint8_t *buffers2[Y4M_MAX_NUM_PLANES]; /* R'G'B' or Y'CbCr */ ppm_info_t ppm; int field_height; int fdout = 1; int err, i, count, repeating_last; y4m_accept_extensions(1); y4m_init_stream_info(&sinfo); y4m_init_frame_info(&finfo); parse_args(&cl, argc, argv); ppm.width = 0; ppm.height = 0; for (i = 0; i < 3; i++) { buffers[i] = NULL; buffers2[i] = NULL; } /* Read first PPM frame/field-pair, to get dimensions */ if (read_ppm_frame(cl.fdin, &ppm, buffers, buffers2, cl.interlace, cl.interleave, cl.bgr)) mjpeg_error_exit1("Failed to read first frame."); /* Setup streaminfo and write output header */ setup_output_stream(fdout, &cl, &sinfo, &ppm, &field_height); /* Loop 'framecount' times, or possibly forever... */ for (count = 0, repeating_last = 0; (count < (cl.offset + cl.framecount)) || (cl.framecount == 0); count++) { if (repeating_last) goto WRITE_FRAME; /* Read PPM frame/field */ /* ...but skip reading very first frame, already read prior to loop */ if (count > 0) { err = read_ppm_frame(cl.fdin, &ppm, buffers, buffers2, cl.interlace, cl.interleave, cl.bgr); if (err == 1) { /* clean input EOF */ if (cl.repeatlast) { repeating_last = 1; goto WRITE_FRAME; } else if (cl.framecount != 0) { mjpeg_error_exit1("Input frame shortfall (only %d converted).", count - cl.offset); } else { break; /* input is exhausted; we are done! time to go home! */ } } else if (err) mjpeg_error_exit1("Error reading ppm frame"); } /* ...skip transforms if we are just going to skip this frame anyway. BUT, if 'cl.repeatlast' is on, we must process/buffer every frame, because we don't know when we will see the last one. */ if ((count >= cl.offset) || (cl.repeatlast)) { /* Transform colorspace, then subsample (in place) */ convert_RGB_to_YCbCr(buffers, ppm.width * field_height); chroma_subsample(cl.ss_mode, buffers, ppm.width, field_height); if (cl.interlace != Y4M_ILACE_NONE) { convert_RGB_to_YCbCr(buffers2, ppm.width * field_height); chroma_subsample(cl.ss_mode, buffers2, ppm.width, field_height); } } WRITE_FRAME: /* Write converted frame to output */ if (count >= cl.offset) { switch (cl.interlace) { case Y4M_ILACE_NONE: if ((err = y4m_write_frame(fdout, &sinfo, &finfo, buffers)) != Y4M_OK) mjpeg_error_exit1("Write frame failed: %s", y4m_strerr(err)); break; case Y4M_ILACE_TOP_FIRST: if ((err = y4m_write_fields(fdout, &sinfo, &finfo, buffers, buffers2)) != Y4M_OK) mjpeg_error_exit1("Write fields failed: %s", y4m_strerr(err)); break; case Y4M_ILACE_BOTTOM_FIRST: if ((err = y4m_write_fields(fdout, &sinfo, &finfo, buffers2, buffers)) != Y4M_OK) mjpeg_error_exit1("Write fields failed: %s", y4m_strerr(err)); break; default: mjpeg_error_exit1("Unknown ilace type! %d", cl.interlace); break; } } } for (i = 0; i < 3; i++) { free(buffers[i]); free(buffers2[i]); } y4m_fini_stream_info(&sinfo); y4m_fini_frame_info(&finfo); mjpeg_debug("Done."); return 0; } mjpegtools-2.1.0/lavtools/y4mtopnm.c0000644000175000017500000004406410603772216020023 0ustar glowwormglowworm/* * y4mtopnm.c: Convert a YUV4MPEG2 stream into one or more PPM/PGM/PAM images. * * Converts ITU-Rec.601 Y'CbCr to R'G'B' colorspace * (or Rec.601 Y' to [0,255] grayscale, for PGM). * * * Copyright (C) 2005 Matthew J. Marjanovic * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "colorspace.h" /* command-line parameters */ typedef struct _cl_info { int make_pam; int make_flat; int deinterleave; int verbosity; FILE *outfp; } cl_info_t; static void usage(const char *progname) { fprintf(stderr, "\n"); fprintf(stderr, "usage: %s [options]\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "Reads YUV4MPEG2 stream from stdin and produces RAW PPM, PGM\n"); fprintf(stderr, " or PAM image(s) on stdout. Converts digital video Y'CbCr colorspace\n"); fprintf(stderr, " to computer graphics R'G'B'.\n"); fprintf(stderr, "\n"); fprintf(stderr, " options: (defaults specified in [])\n"); fprintf(stderr, "\n"); fprintf(stderr, " -P produce PAM output instead of PPM/PGM\n"); fprintf(stderr, " -D de-interleave fields into two PNM images\n"); fprintf(stderr, " -f 'flatten' multiplane frames/fields in raw composite grayscale images\n"); fprintf(stderr, " (for stream debugging, see manpage for details)\n"); fprintf(stderr, " -v n verbosity (0,1,2) [1]\n"); fprintf(stderr, " -h print this help message\n"); } static void parse_args(cl_info_t *cl, int argc, char **argv) { int c; cl->make_pam = 0; cl->make_flat = 0; cl->deinterleave = 0; cl->verbosity = 1; cl->outfp = stdout; /* default to stdout */ while ((c = getopt(argc, argv, "PDfv:h")) != -1) { switch (c) { case 'P': cl->make_pam = 1; break; case 'D': cl->deinterleave = 1; break; case 'f': cl->make_flat = 1; break; case 'v': cl->verbosity = atoi(optarg); if ((cl->verbosity < 0) || (cl->verbosity > 2)) mjpeg_error("Verbosity must be 0, 1, or 2: '%s'", optarg); break; case 'h': usage(argv[0]); exit(0); break; case '?': default: goto ERROR_EXIT; break; } } if (optind != argc) goto ERROR_EXIT; mjpeg_default_handler_verbosity(cl->verbosity); /* DONE! */ return; ERROR_EXIT: mjpeg_error("For usage hints, use option '-h'. Please take a hint."); exit(1); } /* Write a single PAM image. */ static void write_pam(FILE *fp, int chroma, uint8_t *buffers[], uint8_t *rowbuffer, int width, int height) { mjpeg_debug("write raw PAM image from one buffer, %dx%d", width, height); fprintf(fp, "P7\n"); fprintf(fp, "WIDTH %d\n", width); fprintf(fp, "HEIGHT %d\n", height); fprintf(fp, "MAXVAL 255\n"); switch (chroma) { case Y4M_CHROMA_444: fprintf(fp, "DEPTH 3\n"); fprintf(fp, "TUPLTYPE RGB\n"); fprintf(fp, "ENDHDR\n"); { int x, y; uint8_t *pixels; uint8_t *R = buffers[0]; uint8_t *G = buffers[1]; uint8_t *B = buffers[2]; assert(rowbuffer != NULL); for (y = 0; y < height; y++) { pixels = rowbuffer; for (x = 0; x < width; x++) { *(pixels++) = *(R++); *(pixels++) = *(G++); *(pixels++) = *(B++); } fwrite(rowbuffer, sizeof(rowbuffer[0]), width * 3, fp); } } break; case Y4M_CHROMA_444ALPHA: fprintf(fp, "DEPTH 4\n"); fprintf(fp, "TUPLTYPE RGB_ALPHA\n"); fprintf(fp, "ENDHDR\n"); { int x, y; uint8_t *pixels; uint8_t *R = buffers[0]; uint8_t *G = buffers[1]; uint8_t *B = buffers[2]; uint8_t *A = buffers[3]; assert(rowbuffer != NULL); for (y = 0; y < height; y++) { pixels = rowbuffer; for (x = 0; x < width; x++) { *(pixels++) = *(R++); *(pixels++) = *(G++); *(pixels++) = *(B++); *(pixels++) = *(A++); } fwrite(rowbuffer, sizeof(rowbuffer[0]), width * 4, fp); } } break; case Y4M_CHROMA_MONO: fprintf(fp, "DEPTH 1\n"); fprintf(fp, "TUPLTYPE GRAYSCALE\n"); fprintf(fp, "ENDHDR\n"); fwrite(buffers[0], sizeof(buffers[0][0]), width * height, fp); break; } } /* Write a single PPM image. */ static void write_ppm(FILE *fp, uint8_t *buffers[], uint8_t *rowbuffer, int width, int height) { int x, y; uint8_t *pixels; uint8_t *R = buffers[0]; uint8_t *G = buffers[1]; uint8_t *B = buffers[2]; mjpeg_debug("write raw PPM image from one buffer, %dx%d", width, height); fprintf(fp, "P6\n%d %d 255\n", width, height); assert(rowbuffer != NULL); for (y = 0; y < height; y++) { pixels = rowbuffer; for (x = 0; x < width; x++) { *(pixels++) = *(R++); *(pixels++) = *(G++); *(pixels++) = *(B++); } fwrite(rowbuffer, sizeof(rowbuffer[0]), width * 3, fp); } } /* Write a single PGM image. */ static void write_pgm(FILE *fp, uint8_t *buffer, int width, int height) { mjpeg_debug("write raw PGM image from one buffer, %dx%d", width, height); fprintf(fp, "P5\n%d %d 255\n", width, height); fwrite(buffer, sizeof(buffer[0]), width * height, fp); } /* Write a frame or field out as "an image". A frame/field with an alpha channel may become two images... */ static void write_image(FILE *fp, int make_pam, int chroma, uint8_t *buffers[], uint8_t *rowbuffer, int width, int height) { if (make_pam) { write_pam(fp, chroma, buffers, rowbuffer, width, height); } else { switch (chroma) { case Y4M_CHROMA_444: write_ppm(fp, buffers, rowbuffer, width, height); break; case Y4M_CHROMA_444ALPHA: write_ppm(fp, buffers, rowbuffer, width, height); write_pgm(fp, buffers[3], width, height); break; case Y4M_CHROMA_MONO: write_pgm(fp, buffers[0], width, height); break; default: assert(0); break; } } } /************************************************************************/ /************** Structure/code for 'flattening' images ******************/ /************************************************************************/ typedef struct { int chroma; int planes; int image_w; int image_h; int flat_w; int flat_h; uint8_t *flat_buffer; } flattener_t; static void init_flattener(flattener_t *fl, int chroma, int planes, int width, int height) { fl->chroma = chroma; fl->planes = planes; fl->image_w = width; fl->image_h = height; switch (chroma) { case Y4M_CHROMA_444: case Y4M_CHROMA_444ALPHA: case Y4M_CHROMA_MONO: case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: case Y4M_CHROMA_422: fl->flat_w = width; break; case Y4M_CHROMA_411: fl->flat_w = 3 * width / 2; break; default: assert(0); break; } switch (chroma) { case Y4M_CHROMA_444: fl->flat_h = 3 * height; break; case Y4M_CHROMA_444ALPHA: fl->flat_h = 4 * height; break; case Y4M_CHROMA_MONO: fl->flat_h = height; break; case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: fl->flat_h = 3 * height / 2; break; case Y4M_CHROMA_422: fl->flat_h = 2 * height; break; case Y4M_CHROMA_411: fl->flat_h = height; break; default: assert(0); break; } fl->flat_buffer = (uint8_t *) malloc(fl->flat_w * fl->flat_h); assert(fl->flat_buffer != NULL); } static void fini_flattener(flattener_t *fl) { if (fl->flat_buffer != NULL) { free(fl->flat_buffer); fl->flat_buffer = NULL; } } static void flatten(flattener_t *fl, uint8_t *img_buffers[]) { switch (fl->chroma) { /* Non-subsampled: Y, Cb, Cr, (A) vertically appended */ case Y4M_CHROMA_444ALPHA: case Y4M_CHROMA_444: case Y4M_CHROMA_MONO: { int planesize = fl->image_w * fl->image_h; uint8_t *fbuf = fl->flat_buffer; int p; for (p = 0; p < fl->planes; p++) { memcpy(fbuf, img_buffers[p], planesize); fbuf += planesize; } } break; /* 1/2 horizontal: Y followed by (Cb,Cr) */ case Y4M_CHROMA_422: { uint8_t *fbuf = fl->flat_buffer; uint8_t *ib1 = img_buffers[1]; uint8_t *ib2 = img_buffers[2]; int planesize = fl->image_w * fl->image_h; int halfwidth = fl->image_w / 2; int y; memcpy(fbuf, img_buffers[0], planesize); fbuf += planesize; for (y = 0; y < fl->image_h; y++) { memcpy(fbuf, ib1, halfwidth); fbuf += halfwidth; ib1 += halfwidth; memcpy(fbuf, ib2, halfwidth); fbuf += halfwidth; ib2 += halfwidth; } } break; /* 1/2 horizontal, 1/2 vertical: Y followed by (Cb,Cr) */ case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: { uint8_t *fbuf = fl->flat_buffer; uint8_t *ib1 = img_buffers[1]; uint8_t *ib2 = img_buffers[2]; int planesize = fl->image_w * fl->image_h; int halfwidth = fl->image_w / 2; int y; memcpy(fbuf, img_buffers[0], planesize); fbuf += planesize; for (y = 0; y < fl->image_h / 2; y++) { memcpy(fbuf, ib1, halfwidth); fbuf += halfwidth; ib1 += halfwidth; memcpy(fbuf, ib2, halfwidth); fbuf += halfwidth; ib2 += halfwidth; } } break; /* 1/4 horizontal: Y, Cb, Cr horizontally appended */ case Y4M_CHROMA_411: { uint8_t *fbuf = fl->flat_buffer; uint8_t *ib0 = img_buffers[0]; uint8_t *ib1 = img_buffers[1]; uint8_t *ib2 = img_buffers[2]; int qtrwidth = fl->image_w / 4; int y; for (y = 0; y < fl->image_h; y++) { memcpy(fbuf, ib0, fl->image_w); fbuf += fl->image_w; ib0 += fl->image_w; memcpy(fbuf, ib1, qtrwidth); fbuf += qtrwidth; ib1 += qtrwidth; memcpy(fbuf, ib2, qtrwidth); fbuf += qtrwidth; ib2 += qtrwidth; } } break; default: assert(0); break; } } static void write_flattened(flattener_t *fl, FILE *fp, int make_pam) { write_image(fp, make_pam, Y4M_CHROMA_MONO, &(fl->flat_buffer), NULL /* rowbuffer */, fl->flat_w, fl->flat_h); } static void convert_chroma(int chroma, uint8_t *buffers[], int width, int height) { switch (chroma) { case Y4M_CHROMA_444: convert_YCbCr_to_RGB(buffers, width * height); break; case Y4M_CHROMA_444ALPHA: convert_YCbCr_to_RGB(buffers, width * height); convert_Y219_to_Y255(buffers[3], width * height); break; case Y4M_CHROMA_MONO: convert_Y219_to_Y255(buffers[0], width * height); break; default: assert(0); break; } } int main(int argc, char **argv) { int in_fd = 0; cl_info_t cl; y4m_stream_info_t streaminfo; y4m_frame_info_t frameinfo; uint8_t *buffers[Y4M_MAX_NUM_PLANES]; /* R'G'B' or Y'CbCr */ uint8_t *buffers2[Y4M_MAX_NUM_PLANES]; /* R'G'B' or Y'CbCr */ int err, i; int width, height; int interlace, chroma, planes; uint8_t *rowbuffer = NULL; int frame_count; flattener_t fl; y4m_accept_extensions(1); /* allow non-4:2:0 chroma */ y4m_init_stream_info(&streaminfo); y4m_init_frame_info(&frameinfo); parse_args(&cl, argc, argv); if ((err = y4m_read_stream_header(in_fd, &streaminfo)) != Y4M_OK) { mjpeg_error("Couldn't read YUV4MPEG2 header: %s!", y4m_strerr(err)); exit(1); } mjpeg_info("Input stream parameters:"); y4m_log_stream_info(mjpeg_loglev_t("info"), "<<<", &streaminfo); width = y4m_si_get_width(&streaminfo); height = y4m_si_get_height(&streaminfo); interlace = y4m_si_get_interlace(&streaminfo); chroma = y4m_si_get_chroma(&streaminfo); planes = y4m_si_get_plane_count(&streaminfo); switch (chroma) { case Y4M_CHROMA_444: case Y4M_CHROMA_444ALPHA: case Y4M_CHROMA_MONO: break; default: if (!cl.make_flat) { mjpeg_error("Cannot handle input stream's chroma mode!"); mjpeg_error_exit1("Input must be non-subsampled (e.g. 4:4:4)."); } } /*** Tell the user what is going to happen ***/ mjpeg_info("Output image parameters:"); mjpeg_info(" format: %s", (cl.make_pam) ? "PAM" : (cl.make_flat) ? "PGM" : (chroma == Y4M_CHROMA_444) ? "PPM" : (chroma == Y4M_CHROMA_444ALPHA) ? "PPM+PGM" : (chroma == Y4M_CHROMA_MONO) ? "PGM" : "???"); mjpeg_info(" framing: %s", (cl.deinterleave) ? "two images per frame (deinterleaved)" : "one image per frame (interleaved)"); if (cl.deinterleave) { mjpeg_info(" order: %s", (interlace == Y4M_ILACE_BOTTOM_FIRST) ? "bottom field first" : "top field first"); } if (cl.make_flat) mjpeg_info(" 'flattened' --> all planes in one image"); /*** Allocate buffers ***/ mjpeg_debug("allocating buffers..."); if (cl.make_flat) { if (!cl.deinterleave) init_flattener(&fl, chroma, planes, width, height); else init_flattener(&fl, chroma, planes, width, height / 2); rowbuffer = NULL; } else { rowbuffer = malloc(width * planes * sizeof(rowbuffer[0])); } mjpeg_debug(" rowbuffer %p", rowbuffer); for (i = 0; i < planes; i++) { switch (interlace) { case Y4M_ILACE_NONE: buffers[i] = malloc(width * height * sizeof(buffers[i][0])); buffers2[i] = NULL; break; case Y4M_ILACE_TOP_FIRST: case Y4M_ILACE_BOTTOM_FIRST: case Y4M_ILACE_MIXED: /* 'buffers' may hold whole frame or one field... */ buffers[i] = malloc(width * height * sizeof(buffers[i][0])); /* ... but 'buffers2' will never hold more than one field. */ buffers2[i] = malloc(width * height / 2 * sizeof(buffers[i][0])); break; default: assert(0); break; } mjpeg_debug(" buffers[%d] %p buffers2[%d] %p", i, buffers[i], i, buffers2[i]); } /*** Process frames ***/ frame_count = 0; while (1) { err = y4m_read_frame_header(in_fd, &streaminfo, &frameinfo); if (err != Y4M_OK) break; frame_count++; if (!cl.deinterleave) { mjpeg_debug("reading whole frame..."); err = y4m_read_frame_data(in_fd, &streaminfo, &frameinfo, buffers); if (err != Y4M_OK) break; if (cl.make_flat) { flatten(&fl, buffers); write_flattened(&fl, cl.outfp, cl.make_pam); } else { convert_chroma(chroma, buffers, width, height); write_image(cl.outfp, cl.make_pam, chroma, buffers, rowbuffer, width, height); } } else { mjpeg_debug("reading separate fields..."); err = y4m_read_fields_data(in_fd, &streaminfo, &frameinfo, buffers, buffers2); if (err != Y4M_OK) break; if (cl.make_flat) { switch (interlace) { case Y4M_ILACE_NONE: /* ambiguous temporal order */ case Y4M_ILACE_MIXED: /* ambiguous temporal order */ case Y4M_ILACE_TOP_FIRST: /* write top field first */ flatten(&fl, buffers); write_flattened(&fl, cl.outfp, cl.make_pam); flatten(&fl, buffers2); write_flattened(&fl, cl.outfp, cl.make_pam); break; case Y4M_ILACE_BOTTOM_FIRST: /* write bottom field first */ flatten(&fl, buffers2); write_flattened(&fl, cl.outfp, cl.make_pam); flatten(&fl, buffers); write_flattened(&fl, cl.outfp, cl.make_pam); break; default: mjpeg_error_exit1("Unknown input interlacing mode (%d).\n", interlace); break; } } else { convert_chroma(chroma, buffers, width, height / 2); convert_chroma(chroma, buffers2, width, height / 2); switch (interlace) { case Y4M_ILACE_NONE: /* ambiguous temporal order */ case Y4M_ILACE_MIXED: /* ambiguous temporal order */ case Y4M_ILACE_TOP_FIRST: /* write top field first */ write_image(cl.outfp, cl.make_pam, chroma, buffers, rowbuffer, width, height / 2); write_image(cl.outfp, cl.make_pam, chroma, buffers2, rowbuffer, width, height / 2); break; case Y4M_ILACE_BOTTOM_FIRST: /* write bottom field first */ write_image(cl.outfp, cl.make_pam, chroma, buffers2, rowbuffer, width, height / 2); write_image(cl.outfp, cl.make_pam, chroma, buffers, rowbuffer, width, height / 2); break; default: mjpeg_error_exit1("Unknown input interlacing mode (%d).\n", interlace); break; } } } } if ((err != Y4M_OK) && (err != Y4M_ERR_EOF)) mjpeg_error("Couldn't read frame: %s", y4m_strerr(err)); mjpeg_info("Processed %d frames.", frame_count); /*** Clean-up after ourselves ***/ mjpeg_debug("freeing buffers; cleaning up"); if (rowbuffer != NULL) free(rowbuffer); for (i = 0; i < planes; i++) { free(buffers[i]); if (buffers2[i] != NULL) free(buffers2[i]); } y4m_fini_stream_info(&streaminfo); y4m_fini_frame_info(&frameinfo); if (cl.make_flat) fini_flattener(&fl); mjpeg_debug("Done."); return 0; } mjpegtools-2.1.0/lavtools/yuvfps.c0000644000175000017500000005606510737763142017602 0ustar glowwormglowworm/* * yuvfps.c * Copyright (C) 2002 Alfonso Garcia-Patiño Barbolani * * Weighted average resampling * Copyright (C) 2006 Johannes Lehtinen * * Upsamples or downsamples a yuv stream to a specified frame rate * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include "yuv4mpeg.h" #include "mpegconsts.h" #define YUVFPS_VERSION "0.2" static void print_usage() { fprintf (stderr, "usage: yuvfps -r [NewFpsNum:NewFpsDen] [-s [InputFpsNum:InputFpsDen]] [-i NewInterlacing] [-I InputInterlacing] [-c] [-n] [-w] [-v -h]\n" "yuvfps resamples a yuv video stream read from stdin to a new stream, identical\n" "to the source with frames repeated/copied/removed written to stdout.\n" "Alternatively each output frame/field can be produced as a weighted average\n" "of two temporally closest input frames/fields.\n" "\n" "\t -r Frame rate for the resulting stream (in X:Y fractional form)\n" "\t -w Use weighted average of two temporally closest input frames/fields\n" "\t -c Change only the output header, does not modify stream\n" "\t -s Assume this source frame rate ignoring source YUV header\n" "\t -i Interlacing for the resulting stream ('p', 't' or 'b')\n" "\t -I Assume this source interlacing ignoring source YUV header\n" "\t -n don't try to normalize the input framerate\n" "\t -v Verbosity degree : 0=quiet, 1=normal, 2=verbose/debug\n" "\t -h print this help\n" ); } // Does malloc and checks that the allocation is successful before returning // the pointer. If allocation fails, prints an error message and exits. static void *checked_malloc(size_t size) { void *p; if ((p = malloc(size)) == NULL) mjpeg_error_exit1("Memory allocation failed (%lu bytes needed)", (unsigned long) size); return p; } /* ----------------------------------------------------------------------- * Drop/duplicate resampling code * ---------------------------------------------------------------------*/ // // Resamples the video stream coming from fdIn and writes it // to fdOut. // There are two variations of the same theme: // // Upsampling: frames are duplicated when needed // Downsampling: frames from the original are skipped // // Parameters: // // fdIn,fdOut : File descriptors for reading and writing the stream // inStream, outStream: stream handlers for the source and destination streams. // It is assumed that they are correctly initialized from/to // their respective file I/O streams with the desired sample rates. // // src_frame_rate, frame_rate: ratios for source and destination frame rate // (note that this may not match the information contained // in the stream itself due to command line options) // // In both cases a Bresenham - style algorithm is used. // static void resample( int fdIn , y4m_stream_info_t *inStrInfo , y4m_ratio_t src_frame_rate , int fdOut , y4m_stream_info_t *outStrInfo , y4m_ratio_t frame_rate ) { y4m_frame_info_t in_frame ; uint8_t *yuv_data[Y4M_MAX_NUM_PLANES] ; int read_error_code ; int write_error_code ; int src_frame_counter ; int dest_frame_counter ; // To perform bresenham resampling long long srcInc ; long long dstInc ; long long currCount ; int i; // Allocate memory for the YUV channels for (i = 0; i < y4m_si_get_plane_count(inStrInfo); i++) yuv_data[i] = (uint8_t *) checked_malloc(y4m_si_get_plane_length(inStrInfo, i)); /* Initialize counters */ srcInc = (long long)src_frame_rate.n * (long long)frame_rate.d ; dstInc = (long long)frame_rate.n * (long long)src_frame_rate.d ; write_error_code = Y4M_OK ; src_frame_counter = 0 ; dest_frame_counter = 0 ; y4m_init_frame_info( &in_frame ); read_error_code = y4m_read_frame(fdIn,inStrInfo,&in_frame,yuv_data ); ++src_frame_counter ; currCount = 0 ; while( Y4M_ERR_EOF != read_error_code && write_error_code == Y4M_OK ) { write_error_code = y4m_write_frame( fdOut, outStrInfo, &in_frame, yuv_data ); mjpeg_info( "Writing source frame %d at dest frame %d", src_frame_counter,++dest_frame_counter ); currCount += srcInc ; while( currCount >= dstInc && Y4M_ERR_EOF != read_error_code ) { currCount -= dstInc ; ++src_frame_counter ; y4m_fini_frame_info( &in_frame ); y4m_init_frame_info( &in_frame ); read_error_code = y4m_read_frame(fdIn, inStrInfo,&in_frame,yuv_data ); } } // Clean-up regardless an error happened or not y4m_fini_frame_info( &in_frame ); for (i = 0; i < y4m_si_get_plane_count(inStrInfo); i++) { free( yuv_data[i] ); } if( read_error_code != Y4M_ERR_EOF ) mjpeg_error_exit1 ("Error reading from input stream!"); if( write_error_code != Y4M_OK ) mjpeg_error_exit1 ("Error writing output stream!"); } /* ----------------------------------------------------------------------- * Weighted average resampling code * ---------------------------------------------------------------------*/ // // Returns the greatest common divisor (GCD) of the input parameters. // static int gcd(int a, int b) { if (b == 0) return a; else return gcd(b, a % b); } // // Resamples a video stream by producing each output frame/field as the // weighted average of the two temporally closest input frames/fields. // If the stream is interlaced and the input field does not match the output // field then the input lines are produced as average of the surrounding lines. // // Parameters: // in_fd, out_fd: File descriptors for reading and writing the stream // in_si, out_si: stream info for the source and destination streams. // It is assumed that they are correctly initialized from/to // their respective file I/O streams with the desired sample rates. // in_frame_rate, out_frame_rate: ratios for input and output frame rate // (note that this may not match the information contained // in the stream itself due to command line options) // in_interlacing, out_interlacing: interlacing modes for input and output // (note that this may not match the information contained // in the stream itself due to command line options) // static void resample_wa( int in_fd , y4m_stream_info_t *in_si , y4m_ratio_t in_frame_rate , int in_interlacing , int out_fd , y4m_stream_info_t *out_si , y4m_ratio_t out_frame_rate , int out_interlacing ) { y4m_frame_info_t fi; int num_planes; int plane_width[Y4M_MAX_NUM_PLANES]; int plane_height[Y4M_MAX_NUM_PLANES]; int plane_length[Y4M_MAX_NUM_PLANES]; int max_plane_width; uint8_t *in_planes[2][Y4M_MAX_NUM_PLANES]; uint8_t *out_planes[Y4M_MAX_NUM_PLANES]; uint8_t *intermediate_data[2]; int in_frame_time, out_frame_time; int in_pos = 0, out_pos = 0; int num_buffered_frames = 0, buffer_head = 1, buffer_tail = 0; int in_frame_count = 0, out_frame_count = 0; int out_field = 0; int eos = 0; int i, j; /* Initialize frame info structure */ y4m_init_frame_info(&fi); /* Read and check plane information */ num_planes = y4m_si_get_plane_count(in_si); max_plane_width = 0; for (i = 0; i < num_planes; i++) { plane_width[i] = y4m_si_get_plane_width(in_si, i); plane_height[i] = y4m_si_get_plane_height(in_si, i); plane_length[i] = y4m_si_get_plane_length(in_si, i); if (plane_width[i] * plane_height[i] != plane_length[i]) mjpeg_error_exit1("Only 8 bits per plane chroma modes are supported"); if ((in_interlacing != Y4M_ILACE_NONE || out_interlacing != Y4M_ILACE_NONE) && (plane_height[i] & 1)) mjpeg_error_exit1("Interlaced planes must have even height"); if (plane_width[i] > max_plane_width) max_plane_width = plane_width[i]; } /* Allocate memory buffers for processing */ for (j = 0; j < 2; j++) for (i = 0; i < num_planes; i++) in_planes[j][i] = checked_malloc(plane_length[i]); for (i = 0; i < num_planes; i++) out_planes[i] = checked_malloc(plane_length[i]); for (i = 0; i < 2; i++) intermediate_data[i] = checked_malloc(max_plane_width); /* Determine exact relative input and output frame (and field) times * * in_time_sec = 1 / in_rate = in_rate_D / in_rate_N * out_time_sec = 1 / out_rate = out_rate_D / out_rate_N * * Let us scale the time by in_rate_N * out_rate_N to get integer times * * in_time_int = in_rate_D * out_rate_N * out_time_int = out_rate_D * in_rate_N * * Finally divide by the greatest common divisor. If necessary, make sure * that field time (= frame time / 2) is an integer as well. */ in_frame_time = in_frame_rate.d * out_frame_rate.n; out_frame_time = out_frame_rate.d * in_frame_rate.n; i = gcd(in_frame_time, out_frame_time); in_frame_time /= i; out_frame_time /= i; if ((in_interlacing != Y4M_ILACE_NONE && (in_frame_time & 1)) || (out_interlacing != Y4M_ILACE_NONE && (out_frame_time & 1))) { in_frame_time *= 2; out_frame_time *= 2; } mjpeg_debug("Relative input frame time is %d and output frame time is %d.", in_frame_time, out_frame_time); /* Resample until end-of-stream, one output frame/field at a time */ while (!eos) { /* Buffer input frames surrounding the current output position */ while (num_buffered_frames == 0 || in_pos + in_frame_time <= out_pos || (num_buffered_frames < 2 && (in_interlacing != Y4M_ILACE_NONE ? in_pos + in_frame_time / 2 < out_pos : in_pos != out_pos))) { /* Try to buffer next frame, if available */ if ((i = y4m_read_frame(in_fd, in_si, &fi, in_planes[1 - buffer_head])) == Y4M_OK) { y4m_clear_frame_info(&fi); if (num_buffered_frames < 2) num_buffered_frames++; else { buffer_tail = 1 - buffer_tail; in_pos += in_frame_time; } buffer_head = 1 - buffer_head; in_frame_count++; } else if (i != Y4M_ERR_EOF) mjpeg_error_exit1("Error reading from input stream!"); else { /* End of input reached, try with one frame (might do) or give up */ if (num_buffered_frames > 1) { buffer_tail = 1 - buffer_tail; num_buffered_frames--; in_pos += in_frame_time; } else { eos = 1; break; } } } /* Produce the output field at the current position if input available */ if (!eos) { int src_frame[2] = { -1, -1 }; int src_field[2] = { -1, -1 }; int src_time[2] = { 0, 0 }; /* Choose one or two source frames/fields for this output position */ src_frame[0] = buffer_tail; if (in_interlacing == Y4M_ILACE_NONE) { src_time[0] = in_pos; if (out_pos != src_time[0]) { src_frame[1] = buffer_head; src_time[1] = in_pos + in_frame_time; } } else /* interlaced input */ { if (in_pos + in_frame_time / 2 > out_pos) { src_field[0] = 0; src_time[0] = in_pos; if (out_pos != src_time[0]) { src_frame[1] = buffer_tail; src_field[1] = 1; src_time[1] = in_pos + in_frame_time / 2; } } else { src_field[0] = 1; src_time[0] = in_pos + in_frame_time / 2; if (out_pos != src_time[0]) { src_frame[1] = buffer_head; src_field[1] = 0; src_time[1] = in_pos + in_frame_time; } } } mjpeg_debug("Producing output frame %d%s", out_frame_count + 1, (out_interlacing == Y4M_ILACE_NONE ? "" : (out_field == 0 ? ", 1st field" : ", 2nd field"))); mjpeg_debug(" %s source is input frame %d%s", (src_frame[1] == -1 ? "only" : "1st"), in_frame_count - num_buffered_frames + 1, (src_field[0] == -1 ? "" : (src_field[0] == 0 ? ", 1st field" : ", 2nd field"))); if (src_frame[1] != -1) mjpeg_debug(" 2nd source is input frame %d%s", in_frame_count - (src_frame[1] == buffer_tail ? num_buffered_frames - 1 : 0), (src_field[1] == -1 ? "" : (src_field[1] == 0 ? ", 1st field" : ", 2nd field"))); /* Produce the frame/field */ for (i = 0; i < num_planes; i++) { int y; for (y = (out_interlacing == Y4M_ILACE_NONE || (out_interlacing == Y4M_ILACE_TOP_FIRST ? out_field == 0 : out_field == 1) ? 0 : 1); y < plane_height[i]; y += (out_interlacing == Y4M_ILACE_NONE ? 1 : 2)) { uint8_t *dst_line = out_planes[i] + y * plane_width[i]; uint8_t *src_line[2] = { NULL, NULL }; /* Determine or produce the source line(s) */ for (j = 0; j < (src_frame[1] == -1 ? 1 : 2); j++) { if (in_interlacing == Y4M_ILACE_NONE || ((in_interlacing == Y4M_ILACE_TOP_FIRST ? !src_field[j] : src_field[j]) ? !(y & 1) : (y & 1))) src_line[j] = in_planes[src_frame[j]][i] + y * plane_width[i]; else if (y == 0) src_line[j] = in_planes[src_frame[j]][i] + plane_width[i]; else if (y == plane_height[i] - 1) src_line[j] = in_planes[src_frame[j]][i] + (y - 1) * plane_width[i]; else { uint8_t *l1, *l2, *sl; int k; /* Produce source line by averaging the surrounding lines */ sl = src_line[j] = intermediate_data[j]; l1 = in_planes[src_frame[j]][i] + (y - 1) * plane_width[i]; l2 = l1 + 2 * plane_width[i]; for (k = plane_width[i]; k != 0; k--) *(sl++) = (uint8_t) (((int) *(l1++) + *(l2++)) / 2); } } /* If only one source line, just copy it */ if (src_line[1] == NULL) memcpy(dst_line, src_line[0], plane_width[i]); /* Otherwise calculate weighted average of the source lines */ else { int w1 = src_time[1] - out_pos; int w2 = out_pos - src_time[0]; int wsum = w1 + w2; for (j = plane_width[i]; j != 0; j--) *(dst_line++) = (w1 * *(src_line[0]++) + w2 * *(src_line[1]++)) / wsum; } } } /* Write the current frame if ready (progressive or both fields done) */ if (out_interlacing == Y4M_ILACE_NONE || out_field == 1) { mjpeg_info("Writing output frame %d", ++out_frame_count); if (y4m_write_frame(out_fd, out_si, &fi, out_planes) != Y4M_OK) mjpeg_error_exit1("Error writing output stream!"); } /* Advance to the next output frame/field position */ if (out_interlacing == Y4M_ILACE_NONE) out_pos += out_frame_time; else { out_field = 1 - out_field; out_pos += out_frame_time / 2; } } } if (out_field == 1) mjpeg_debug("Discarding unfinished output frame %d", out_frame_count + 1); /* Finalize frame info structure */ y4m_fini_frame_info(&fi); } /* ----------------------------------------------------------------------- * Common initialization and user interface code * ---------------------------------------------------------------------*/ // // Parse interlacing mode keyword into interlacing mode value. // "p" -> progressive, Y4M_ILACE_NONE // "t" -> top-field first, Y4M_ILACE_TOP_FIRST // "b" -> bottom-field first, Y4M_ILACE_BOTTOM_FIRST // // Exits with an error message if the specified argument is invalid. // static int parse_interlacing(char *str) { if (str[0] != '\0' && str[1] == '\0') { switch (str[0]) { case 'p': return Y4M_ILACE_NONE; case 't': return Y4M_ILACE_TOP_FIRST; case 'b': return Y4M_ILACE_BOTTOM_FIRST; } } mjpeg_error_exit1("Valid interlacing modes are: p - progressive, t - top-field first, b - bottom-field first"); return Y4M_UNKNOWN; /* to avoid compiler warnings */ } // *************************************************************************** // MAIN // *************************************************************************** int main (int argc, char *argv[]) { int verbose = mjpeg_loglev_t("error"); int change_header_only = 0 ; int not_normalize = 0; int use_weighted_average = 0; int fdIn = 0 ; int fdOut = 1 ; y4m_stream_info_t in_streaminfo, out_streaminfo ; y4m_ratio_t frame_rate, src_frame_rate, normalized_ratio ; int src_interlacing = Y4M_UNKNOWN; int interlacing = Y4M_UNKNOWN; const static char *legal_flags = "r:s:i:I:cnwv:h"; int c ; src_frame_rate.d = 0; frame_rate.d = 0; while ((c = getopt (argc, argv, legal_flags)) != -1) { switch (c) { /* New frame rate */ case 'r': if( Y4M_OK != y4m_parse_ratio(&frame_rate, optarg) ) mjpeg_error_exit1 ("Syntax for frame rate should be Numerator:Denominator"); break; /* Assumed frame rate for source (useful when the header contains an invalid frame rate) */ case 's': if( Y4M_OK != y4m_parse_ratio(&src_frame_rate,optarg) ) mjpeg_error_exit1 ("Syntax for frame rate should be Numerator:Denominator"); break ; /* New interlacing */ case 'i': interlacing = parse_interlacing(optarg); break; /* Assumed interlacing for source */ case 'I': src_interlacing = parse_interlacing(optarg); break; /* Only change header frame-rate, not the stream itself */ case 'c': change_header_only = 1 ; case 'n': not_normalize = 1; break; case 'w': use_weighted_average = 1; break; case 'v': verbose = atoi (optarg); if (verbose < 0 || verbose > 2) mjpeg_error_exit1 ("Verbose level must be [0..2]"); break; case 'h': case '?': print_usage (argv); return 0 ; break; } } /* Check that frame rate was specified */ if (frame_rate.d == 0) mjpeg_error_exit1("Output frame rate must be specified"); y4m_accept_extensions(1); /* mjpeg tools global initialisations */ mjpeg_default_handler_verbosity (verbose); /* Initialize input streams */ y4m_init_stream_info (&in_streaminfo); y4m_init_stream_info (&out_streaminfo); // *************************************************************** // Get video stream informations (size, framerate, interlacing, aspect ratio). // The streaminfo structure is filled in // *************************************************************** // INPUT comes from stdin, we check for a correct file header if (y4m_read_stream_header (fdIn, &in_streaminfo) != Y4M_OK) mjpeg_error_exit1 ("Could'nt read YUV4MPEG header!"); /* Determine input/output interlacing and check for conflicts */ if (src_interlacing == Y4M_UNKNOWN) src_interlacing = y4m_si_get_interlace(&in_streaminfo); if (interlacing == Y4M_UNKNOWN) interlacing = src_interlacing; if (interlacing != src_interlacing && !use_weighted_average && !change_header_only) mjpeg_error_exit1("Interlacing mode can be changed only when using weighted average resampling (-w)"); if (src_interlacing != Y4M_ILACE_NONE && src_interlacing != Y4M_ILACE_TOP_FIRST && src_interlacing != Y4M_ILACE_BOTTOM_FIRST) mjpeg_error_exit1("Unsupported interlacing mode"); /* Prepare output stream */ if (src_frame_rate.d == 0) src_frame_rate = y4m_si_get_framerate( &in_streaminfo ); y4m_copy_stream_info( &out_streaminfo, &in_streaminfo ); /* Information output */ mjpeg_info ("yuv2fps (version " YUVFPS_VERSION ") is a general frame resampling utility for yuv streams"); mjpeg_info ("(C) 2002 Alfonso Garcia-Patino Barbolani "); mjpeg_info ("yuvfps -h for help, or man yuvfps"); y4m_si_set_framerate( &out_streaminfo, frame_rate ); y4m_si_set_interlace( &out_streaminfo, interlacing ); y4m_write_stream_header(fdOut,&out_streaminfo); if (not_normalize == 0) { /* Trying to normalize the values */ normalized_ratio = mpeg_conform_framerate( (double)src_frame_rate.n/(double)src_frame_rate.d ); mjpeg_warn( "Original framerate: %d:%d, Normalized framerate: %d:%d", src_frame_rate.n, src_frame_rate.d, normalized_ratio.n, normalized_ratio.d ); src_frame_rate.n = normalized_ratio.n; src_frame_rate.d = normalized_ratio.d; } /* * Do this BEFORE clobbering frame_rate below!! Otherwise the wrong * value is printed because the src_rate is copied over to the -r value */ mjpeg_warn( "Converting from %d:%d to %d:%d", src_frame_rate.n,src_frame_rate.d,frame_rate.n,frame_rate.d ); if( change_header_only ) { frame_rate = src_frame_rate; interlacing = src_interlacing; use_weighted_average = 0; } /* in that function we do all the important work */ if (use_weighted_average) resample_wa( fdIn, &in_streaminfo, src_frame_rate, src_interlacing, fdOut, &out_streaminfo, frame_rate, interlacing ); else resample( fdIn, &in_streaminfo, src_frame_rate, fdOut, &out_streaminfo, frame_rate ); y4m_fini_stream_info (&in_streaminfo); y4m_fini_stream_info (&out_streaminfo); return 0; } /* * Local variables: * tab-width: 8 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/lavtools/lavpipe.c0000644000175000017500000004722410603772216017675 0ustar glowwormglowworm/* * lavpipe - combines several input streams and pipes them trough * arbitrary filters in order to finally output a resulting * video stream based on a given "recipe" (pipe list) * * Copyright (C) 2001, pHilipp Zabel * Copyright (C) 2001, Matthew Marjanovic * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include "mjpeg_logging.h" #include "pipelist.h" #include "yuv4mpeg.h" static void usage(void) { fprintf( stderr, "Usage: lavpipe [options] \n" "Options: -o num Frame offset - skip num frames in the beginning\n" " if num is negative, all but the last num frames are skipped\n" " -n num Only num frames are processed (0 means all frames)\n" " -v num Verbosity of output [0..2]\n" ); } static char **parse_spawn_command(char *cmdline) { char **argv; char *p = cmdline; int i, argc = 0; if (p == NULL) return NULL; if (*p == '\0') return NULL; argc = 0; while (*p != '\0') { while (!isspace(*p)) { p++; if (*p == '\0') { argc++; goto END_OF_LINE; } } argc++; while (isspace(*p)) { p++; if (*p == '\0') goto END_OF_LINE; } } END_OF_LINE: argv = malloc(argc+1 * sizeof(argv[0])); for (p = cmdline, i=0; i < argc; i++) { argv[i] = p; while (!isspace(*(++p))); p[0] = '\0'; while (isspace(*(++p))) if (p[0] == '\0') break; } argv[argc] = NULL; return argv; } static pid_t fork_child_sub(char *command, int *fd_in, int *fd_out) { int n; int pipe_in[2]; int pipe_out[2]; char **myargv; pid_t pid; if (fd_in) { if (pipe(pipe_in)) { mjpeg_error_exit1( "Couldn't create input pipe from %s", command); } } if (fd_out) { if (pipe(pipe_out)) { mjpeg_error_exit1( "Couldn't create output pipe to %s", command); } } if ((pid = fork ()) < 0) { mjpeg_error_exit1("Couldn't fork %s", command); } if (pid == 0) { /* child redirects stdout to pipe_in */ if (fd_in) { close(pipe_in[0]); close(1); n = dup(pipe_in[1]); if (n != 1) exit (1); } /* child redirects stdin to pipe_out */ if (fd_out) { close(pipe_out[1]); close(0); n = dup(pipe_out[0]); if (n != 0) exit(1); } myargv = parse_spawn_command(command); execvp(myargv[0], myargv); return -1; } else { /* parent */ if (fd_in != NULL) { close(pipe_in[1]); *fd_in = pipe_in[0]; } if (fd_out != NULL) { close(pipe_out[0]); *fd_out = pipe_out[1]; } return pid; } } static pid_t fork_child(const char *command, int offset, int num, int *fd_in, int *fd_out) { char tmp1[1024], tmp2[1024]; char *current = tmp1; char *next = tmp2; char *p; strncpy(current, command, 1024); /* replace $o by offset */ p = strstr(current, "$o"); if (p) { p[0] = '\0'; p += 2; snprintf(next, 1024, "%s%d%s", current, offset, p); p = current; current = next; next = p; } /* replace $n by number of frames */ p = strstr(current, "$n"); if (p) { p[0] = '\0'; p += 2; snprintf(next, 1024, "%s%d%s", current, num, p); p = current; current = next; next = p; } mjpeg_debug( "Executing: '%s'", current); return fork_child_sub(current, fd_in, fd_out); } static void alloc_yuv_buffers(unsigned char *yuv[3], y4m_stream_info_t *si) { int chroma_ss, ss_v, ss_h, w, h; w = y4m_si_get_width(si); h = y4m_si_get_height(si); chroma_ss = y4m_si_get_chroma(si); ss_h = y4m_chroma_ss_x_ratio(chroma_ss).d; ss_v = y4m_chroma_ss_y_ratio(chroma_ss).d; yuv[0] = malloc (w * h * sizeof(yuv[0][0])); yuv[1] = malloc ((w / ss_h) * (h / ss_v) * sizeof(yuv[1][0])); yuv[2] = malloc ((w / ss_h) * (h / ss_v) * sizeof(yuv[2][0])); } static void free_yuv_buffers(unsigned char *yuv[3]) { free(yuv[0]); free(yuv[1]); free(yuv[2]); yuv[0] = yuv[1] = yuv[2] = NULL; } static void init_pipe_source(pipe_source_t *ps, char *command) { ps->command = strdup(command); y4m_init_stream_info(&(ps->streaminfo)); y4m_init_frame_info(&(ps->frameinfo)); ps->pid = -1; ps->fd = -1; ps->frame_num = 0; } static void fini_pipe_source(pipe_source_t *ps) { free(ps->command); y4m_fini_stream_info(&(ps->streaminfo)); y4m_fini_frame_info(&(ps->frameinfo)); } static void spawn_pipe_source(pipe_source_t *ps, int offset, int count) { ps->pid = fork_child(ps->command, offset, count, &(ps->fd), NULL); ps->frame_num = offset; mjpeg_debug("spawned source '%s'", ps->command); } static void decommission_pipe_source(pipe_source_t *source) { if (source->fd >= 0) { close(source->fd); source->fd = -1; } if (source->pid > 0) { mjpeg_debug("DIE DIE DIE pid %d", source->pid); kill(source->pid, SIGINT); source->pid = -1; } } static void init_pipe_filter(pipe_filter_t *pf, const char *command) { pf->command = strdup(command); y4m_init_stream_info(&(pf->out_streaminfo)); y4m_init_stream_info(&(pf->in_streaminfo)); y4m_init_frame_info(&(pf->frameinfo)); pf->yuv[0] = pf->yuv[1] = pf->yuv[2] = NULL; pf->pid = -1; pf->out_fd = -1; pf->in_fd = -1; } static void fini_pipe_filter(pipe_filter_t *pf) { free(pf->command); free_yuv_buffers(pf->yuv); y4m_fini_stream_info(&(pf->out_streaminfo)); y4m_fini_stream_info(&(pf->in_streaminfo)); y4m_fini_frame_info(&(pf->frameinfo)); } static void spawn_pipe_filter(pipe_filter_t *pf, int offset, int count) { pf->pid = fork_child(pf->command, offset, count, &(pf->in_fd), &(pf->out_fd)); mjpeg_debug("spawned filter '%s'", pf->command); } static void decommission_pipe_filter(pipe_filter_t *filt) { if (filt->in_fd >= 0) { close(filt->in_fd); filt->in_fd = -1; } if (filt->out_fd >= 0) { close(filt->out_fd); filt->out_fd = -1; } if (filt->pid > 0) { mjpeg_debug("DIE DIE DIE pid %d", filt->pid); kill(filt->pid, SIGINT); filt->pid = -1; } free_yuv_buffers(filt->yuv); } /* * make sure all the sources needed for this segment are cued up * and ready to produce frames * */ static void open_segment_inputs(PipeSegment *seg, pipe_filter_t *filt, int frame, int segnum, int total_frames, PipeList *pl, commandline_params_t *cl, pipe_source_t *sources) { int i, j, k; for (i = 0; i < seg->input_count; i++) { int in_index = seg->input_index[i]; int in_offset = seg->input_offset[i]; pipe_source_t *source = &(sources[in_index]); mjpeg_debug("OSI: input %d == source %d: '%s'", i, in_index, source->command); /* spawn the source if not already running */ if (source->fd < 0) { /* calculate # of frames we want to get from this stream */ /* need to look if we can use this in successive sequences and what param_frames is */ int offset = in_offset + frame; int count = seg->frame_count - frame; /* until end of sequence */ for (j = segnum + 1; j < pl->segment_count; j++) { PipeSegment *other = pl->segments[j]; /* mjpeg_debug("checking i %d j %d", i, j); */ for (k = 0; k < other->input_count; k++) { /* mjpeg_debug("checking i %d j %d k %d", i, j, k); */ if (in_index == other->input_index[k]) { if ((offset + count) == other->input_offset[k]) { count += other->frame_count; /* add another sequence */ } else goto FINISH_CHECK; /* need to reopen with other offset */ } else goto FINISH_CHECK; /* stream will not be used in segment j anymore */ } } FINISH_CHECK: /* mjpeg_debug("finish-check i %d j %d k %d", i, j, k); */ if (count > cl->frames - total_frames) { count = cl->frames - total_frames; } /******** why have 'count'? let the source keep making frames... ...we'll just kill it when we are done anyway! *********/ /* spawn_pipe_source(source, offset, count);*/ spawn_pipe_source(source, offset, 0); if (y4m_read_stream_header(source->fd, &(source->streaminfo)) != Y4M_OK) mjpeg_error_exit1("Bad source header!"); mjpeg_debug("read header"); y4m_log_stream_info(mjpeg_loglev_t("debug"), "src: ", &(source->streaminfo)); } else { mjpeg_debug("...source %d is still alive.", in_index); } if (i == 0) { /* first time: copy stream info to filter */ y4m_copy_stream_info(&(filt->out_streaminfo), &(source->streaminfo)); mjpeg_debug("copied info"); } else { /* n-th time: make sure source streams match */ if (y4m_si_get_width(&(filt->out_streaminfo)) != y4m_si_get_width(&(source->streaminfo))) mjpeg_error_exit1("Stream mismatch: frame width"); if (y4m_si_get_height(&(filt->out_streaminfo)) != y4m_si_get_height(&(source->streaminfo))) mjpeg_error_exit1("Stream mismatch: frame height"); if (y4m_si_get_interlace(&(filt->out_streaminfo)) != y4m_si_get_interlace(&(source->streaminfo))) mjpeg_error_exit1("Stream mismatch: interlace"); mjpeg_debug("verified info"); } } } static void setup_segment_filter(PipeSegment *seg, pipe_filter_t *filt, int frame) { mjpeg_debug("OSO: '%s'", filt->command); if (strcmp(filt->command, "-")) { /* ...via a filter command: * o spawn filter process * o write source stream info to filter * o read filter's result stream info * o alloc yuv buffers for source->filter transfers */ /* ... why does the 'count' matter, if lavpipe controls the frame * flow anyway???????? */ spawn_pipe_filter(filt, frame, (seg->frame_count - frame)); y4m_write_stream_header(filt->out_fd, &(filt->out_streaminfo)); y4m_read_stream_header(filt->in_fd, &(filt->in_streaminfo)); mjpeg_debug("SSF: read filter result stream header"); y4m_log_stream_info(mjpeg_loglev_t("debug"), "result: ", &(filt->in_streaminfo)); alloc_yuv_buffers(filt->yuv, &(filt->out_streaminfo)); } else { /* ...no filter; direct output: * o result stream info is just a copy of the source stream info */ filt->out_fd = filt->in_fd = -1; y4m_copy_stream_info(&(filt->in_streaminfo), &(filt->out_streaminfo)); mjpeg_debug("SSF: copied source header"); } } static void process_segment_frames(pipe_sequence_t *ps, int segnum, int *frame, int *total_frames) { pipe_source_t *sources = ps->sources; pipe_filter_t *the_output = &(ps->output); PipeList *pl = &(ps->pl); commandline_params_t *cl = &(ps->cl); PipeSegment *seg = ps->pl.segments[segnum]; pipe_filter_t *filt = &(ps->filters[segnum]); mjpeg_debug("PSF: segment %d, initial frame = %d", segnum, *frame); while (*frame < seg->frame_count) { int i; for (i = 0; i < seg->input_count; i++) { int in_index = seg->input_index[i]; pipe_source_t *source = &(sources[in_index]); unsigned char **yuv; if (filt->out_fd >= 0) /* filter present; write/read through filter's buffer first */ yuv = filt->yuv; else /* no filter present; source -> direct to output buffer */ yuv = the_output->yuv; mjpeg_debug("read frame %03d > input %d, src %d fd = %d", *frame, i, in_index, source->fd); if (y4m_read_frame(source->fd, &(source->streaminfo), &(source->frameinfo), yuv) != Y4M_OK) { int err = errno; mjpeg_error("ERRNO says: %s", strerror(err)); mjpeg_error_exit1("lavpipe: input stream error in stream %d," "sequence %d, frame %d", i, segnum, *frame); } source->frame_num += 1; if (filt->out_fd >= 0) y4m_write_frame(filt->out_fd, &(filt->out_streaminfo), &(filt->frameinfo), yuv); } if (filt->in_fd >= 0) { if (y4m_read_frame(filt->in_fd, &(filt->in_streaminfo), &(filt->frameinfo), the_output->yuv) != Y4M_OK) { mjpeg_error_exit1( "lavpipe: filter stream error in sequence %d," "frame %d", segnum, *frame); } } /* output result */ y4m_write_frame(the_output->out_fd, &(the_output->out_streaminfo), &(the_output->frameinfo), the_output->yuv); (*frame)++; if (++(*total_frames) == cl->frames) { segnum = pl->segment_count - 1; /* = close all input files below */ break; } } } /* * this is just being picky, but... * * Close all sources used by current segment, but only if they will * cannot be used in current state by upcoming segments. * */ static void close_segment_inputs(pipe_sequence_t *ps, int segnum, int frame) { PipeList *pl = &(ps->pl); pipe_source_t *sources = ps->sources; PipeSegment *seg = pl->segments[segnum]; int i; for (i = 0; i < seg->input_count; i++) { int current_index = seg->input_index[i]; pipe_source_t *source = &(sources[current_index]); if (source->fd >= 0) { /* if it's still alive... * ...iterate over remaining segments, and see if they can * use this source. */ int s; for (s = segnum + 1; s < pl->segment_count; s++) { int j; PipeSegment *next_seg = pl->segments[s]; for (j = 0; j < next_seg->input_count; j++) { int index = next_seg->input_index[j]; int offset = next_seg->input_offset[j]; if ( (index == current_index) && (offset == source->frame_num) ) { /* A segment input offset matches the current frame... * ...this source can still be used. */ mjpeg_info("allowing input %d (source %d) to live", i, current_index); goto KEEP_SOURCE; } } } mjpeg_info( "closing input %d (source %d)", i, current_index); decommission_pipe_source(source); KEEP_SOURCE: ; } } } static void parse_command_line(int argc, char *argv[], commandline_params_t *cl) { char c; int err; cl->verbose = 1; cl->offset = 0; cl->frames = 0; cl->listfile = NULL; err = 0; while ((c = getopt(argc, argv, "o:n:v:")) != EOF) { switch (c) { case 'o': cl->offset = atoi(optarg); break; case 'n': cl->frames = atoi(optarg); break; case 'v': cl->verbose = atoi(optarg); if ( (cl->verbose < 0) || (cl->verbose > 2) ) { usage(); exit(1); } break; default: err++; } } if ((optind >= argc) || (err)) { usage(); exit(1); } cl->listfile = strdup(argv[optind]); } static void initialize_pipe_sequence(pipe_sequence_t *ps, int argc, char **argv) { int i; commandline_params_t *cl = &(ps->cl); PipeList *pl = &(ps->pl); init_pipe_filter(&(ps->output), ""); ps->output.out_fd = 1; /* parse command-line arguments */ parse_command_line(argc, argv, cl); /* set-up logging */ (void)mjpeg_default_handler_verbosity(cl->verbose); /* read pipe 'recipe' */ if (read_pipe_list(cl->listfile, pl) < 0) { mjpeg_error_exit1( "lavpipe: couldn't open \"%s\"", cl->listfile); } /* a negative offset means "from the end" */ if (cl->offset < 0) { cl->offset = pl->frame_count + cl->offset; } if ((cl->offset >= pl->frame_count) || (cl->offset < 0)) { mjpeg_error_exit1( "error: offset greater than # of frames in input"); } /* zero frame count means "all frames" */ if (cl->frames == 0) { cl->frames = pl->frame_count - cl->offset; } if ((cl->offset + cl->frames) > pl->frame_count) { mjpeg_warn( "input too short for -n %d", cl->frames); cl->frames = pl->frame_count - cl->offset; } /* initialize pipe sources */ ps->sources = malloc(pl->source_count * sizeof(ps->sources[0])); for (i = 0; i < pl->source_count; i++) init_pipe_source(&(ps->sources[i]), pl->source_cmd[i]); /* initialize pipe filters */ ps->filters = malloc(pl->segment_count * sizeof(ps->filters[0])); for (i = 0; i < pl->segment_count; i++) init_pipe_filter(&(ps->filters[i]), pl->segments[i]->output_cmd); } static void process_pipe_sequence(pipe_sequence_t *ps) { int segm_num; /* current segment number */ int segm_frame; /* frame number, within a segment */ int sequ_frame; /* cumulative/total frame number */ int first_iteration; /* find start segment/frame, given overall lavpipe offset ("-o") */ segm_frame = ps->cl.offset; for (segm_num = 0; segm_frame >= ps->pl.segments[segm_num]->frame_count; segm_num++) { segm_frame -= ps->pl.segments[segm_num]->frame_count; } /* process the segments */ first_iteration = 1; sequ_frame = 0; while ( (segm_num < ps->pl.segment_count) && (sequ_frame < ps->cl.frames) ) { PipeSegment *seg = ps->pl.segments[segm_num]; pipe_filter_t *filt = &(ps->filters[segm_num]); mjpeg_debug("starting segment %d, frame %d", segm_num, segm_frame); open_segment_inputs(seg, filt, segm_frame, segm_num, sequ_frame, &ps->pl, &ps->cl, ps->sources); setup_segment_filter(seg, filt, segm_frame); if (first_iteration) { /* Initialize the final output stream, just once */ /* The final output stream parameters are taken from the output * parameters of the first segment's output filter. * (If there is no filter (i.e. "-", direct output), then the * parameters will end up coming from the first segment's source * stream.) */ y4m_copy_stream_info(&(ps->output.out_streaminfo), &(filt->in_streaminfo)); y4m_write_stream_header(ps->output.out_fd, &(ps->output.out_streaminfo)); alloc_yuv_buffers(ps->output.yuv, &(ps->output.out_streaminfo)); mjpeg_debug("output stream initialized"); first_iteration = 0; } else { /* For succeeding segments, make sure that the new filter's stream is * consistent with the final output stream. */ if (y4m_si_get_width(&(filt->in_streaminfo)) != y4m_si_get_width(&(ps->output.out_streaminfo))) mjpeg_error_exit1("Stream mismatch: frame width"); if (y4m_si_get_height(&(filt->in_streaminfo)) != y4m_si_get_height(&(ps->output.out_streaminfo))) mjpeg_error_exit1("Stream mismatch: frame height"); if (y4m_si_get_interlace(&(filt->in_streaminfo)) != y4m_si_get_interlace(&(ps->output.out_streaminfo))) mjpeg_error_exit1("Stream mismatch: interlace"); mjpeg_debug("filter stream verified"); } process_segment_frames(ps, segm_num, &segm_frame, &sequ_frame); decommission_pipe_filter(filt); close_segment_inputs(ps, segm_num, segm_frame); /* prepare for next sequence */ segm_num++; segm_frame = 0; } } static void cleanup_pipe_sequence(pipe_sequence_t *ps) { int i; PipeList *pl = &(ps->pl); /* free/fini everything */ fini_pipe_filter(&ps->output); for (i = 0; i < pl->source_count; i++) fini_pipe_source(&(ps->sources[i])); free(ps->sources); for (i = 0; i < pl->segment_count; i++) fini_pipe_filter(&(ps->filters[i])); free(ps->filters); } int main (int argc, char *argv[]) { pipe_sequence_t ps; initialize_pipe_sequence(&ps, argc, argv); process_pipe_sequence(&ps); cleanup_pipe_sequence(&ps); return 0; } mjpegtools-2.1.0/lavtools/editlist.h0000644000175000017500000000415010245660615020053 0ustar glowwormglowworm/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef EDITLIST_H #define EDITLIST_H #include /* If changing MAX_EDIT_LIST_FILES, the macros below also have to be adapted. */ #define MAX_EDIT_LIST_FILES 256 #define N_EL_FRAME(x) ( (x)&0xffffff ) #define N_EL_FILE(x) ( ((x)>>24)&0xff ) #define EL_ENTRY(file,frame) ( ((file)<<24) | ((frame)&0xffffff) ) typedef struct { long video_frames; long video_width; long video_height; long video_inter; long video_norm; double video_fps; int video_sar_width; /* sample aspect ratio */ int video_sar_height; long max_frame_size; int chroma; /* TODO: Need to flag mixed chroma model files? */ int has_audio; long audio_rate; int audio_chans; int audio_bits; int audio_bps; long num_video_files; char *(video_file_list[MAX_EDIT_LIST_FILES]); lav_file_t *(lav_fd[MAX_EDIT_LIST_FILES]); long num_frames[MAX_EDIT_LIST_FILES]; long *frame_list; int last_afile; long last_apos; } EditList; int el_get_video_frame(uint8_t *vbuff, long nframe, EditList *el); int el_get_audio_data(uint8_t *abuff, long nframe, EditList *el, int mute); void read_video_files(char **filename, int num_files, EditList *el, int preserve_pathnames); int write_edit_list(char *name, long n1, long n2, EditList *el); int open_video_file(char *filename, EditList *el, int preserve_pathname); int el_video_frame_data_format(long nframe, EditList *el); #endif /* ifndef EDITLIST_H */ mjpegtools-2.1.0/lavtools/lavvideo.c0000644000175000017500000002357710102256530020041 0ustar glowwormglowworm/* lavvideo (V1.0) =============== Small tool for showing a realtime video window on the screen, but (simplification) _ignoring_ all window managing. Usage: lavvideo [options] Have a look at the options below. Nothing is guaranteed to be working. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Copyright by Gernot Ziegler. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #define DEBUG(x) x #define VERBOSE(x) x /* Here you can enter your own framebuffer address, * NULL means autodetect by V4L driver */ #define FRAMEBUFFERADDRESS NULL #include #include #include #include #include #include #include #include #include #include #include #include /* Because of some really cool feature in video4linux1, also known as * 'not including sys/types.h and sys/time.h', we had to include it * ourselves. In all their intelligence, these people decided to fix * this in the next version (video4linux2) in such a cool way that it * breaks all compilations of old stuff... * The real problem is actually that linux/time.h doesn't use proper * macro checks before defining types like struct timeval. The proper * fix here is to either fuck the kernel header (which is what we do * by defining _LINUX_TIME_H, an innocent little hack) or by fixing it * upstream, which I'll consider doing later on. If you get compiler * errors here, check your linux/time.h && sys/time.h header setup. */ #define _LINUX_TIME_H #include #include #include #include #define DEVNAME "/dev/video0" static const char *device = DEVNAME; int v4ldev; int file; int res; int frame; int chlist = -1; struct video_window vw; struct video_channel vc; struct video_mbuf vb; struct video_mmap vm; struct video_buffer vv; char * buff; static int norm = VIDEO_MODE_PAL; static int wait = -1; static int input = 0; static int xres = 800; static int pixbits = 32; static int width = 400; static int height = 300; static int xoffset = 5; static int yoffset = 5; static int verbose = 0; static int debug = 0; void usage(char *prog); int doIt(void); void tune_to_channel(int channel); void tune_to_channel(int channel) { unsigned long outfreq; /* if we are a tuner set the channel */ if (vc.flags & VIDEO_VC_TUNER) { if (chlist >= 0) { outfreq = (chanlists[chlist].list)[channel-1].freq*16/1000; fprintf(stdout, "Setting channel to %d frequency %d\n", channel, (chanlists[chlist].list)[channel-1].freq); /* Tune to channel */ if (ioctl(v4ldev, VIDIOCSFREQ, &outfreq) < 0) { perror("VIDIOCSFREQ failed."); exit(1); } } else fprintf(stderr, "No channel list selected!\n"); } else fprintf(stderr, "Not a tunable device!\n"); } void usage(char *prog) { char *h; if (NULL != (h = (char *)strrchr(prog,'/'))) prog = h+1; fprintf(stderr, "%s shows an overlay video window on the screen.\n" "\n" "usage: %s [ options ]\n" "\n" "options: [defaults]\n" " -h help \n" " -v verbose operation \n" " -d debug information \n" " -c device specify device [%s]\n" " -t seconds the time the video window shows [infinite]\n" " -s size specify size [%dx%d]\n" " -o offset displacement on screen [%dx%d]\n" " -x xres screen x resolution [%d]\n" " -b pixbits Bits per pixel (15,16,24,32) [%d]\n" " -n tvnorm set pal/ntsc/secam [pal]\n" " -i input set input source (int) [%d]\n" " -C chanlist channel list \n" "\n" "NOTE: lavvideo makes your V4L card write _directly_ into the frame buffer, " "ignoring\n _everything_ that lies under it. It is far from being as " "comfortable as \ne.g. xawtv is, and just serving as a simple test and " "demo program." "\n" "examples:\n" " %s | shows a video window with the default config.\n" " %s -c /dev/v4l0 -n ntsc | utilizes the device v4l0 for V4L I/O\n" " communication, and expects the signal being NTSC standard.\n" "\n" "--\n" "(c) 2000 Gernot Ziegler\n", prog, prog, device, width, height, xoffset, yoffset, xres, pixbits, input, prog, prog); } int doIt(void) { int turnon; /* V4l initialization */ /* Figure out which device to use */ struct stat vstat; if((stat("/dev/video", &vstat) == 0) && S_ISCHR(vstat.st_mode)) device = "/dev/video"; else if(stat("/dev/video0", &vstat) == 0 && S_ISCHR(vstat.st_mode)) device = "/dev/video0"; else if(stat("/dev/v4l/video0", &vstat) == 0 && S_ISCHR(vstat.st_mode)) device = "/dev/v4l/video0"; else if(stat("/dev/v4l0", &vstat) == 0 && S_ISCHR(vstat.st_mode)) device = "/dev/v4l0"; else if(stat("/dev/v4l", &vstat) == 0 && S_ISCHR(vstat.st_mode)) device = "/dev/v4l"; /* open device */ if (verbose) printf("Opening device %s\n", device); v4ldev = open(device, O_RDWR); if (v4ldev < 0) { perror("Error opening video device."); exit(1); } /* select input */ if (verbose) printf("Selecting input %d\n", input); vc.channel = input; vc.norm = norm; res = ioctl(v4ldev, VIDIOCSCHAN, &vc); if (res < 0) { perror("VIDIOCSCHAN failed."); exit(1); } if (verbose) printf("Choosing window width [%dx%d] and offset [%dx%d]\n, " "bitdepth %d", width, height, xoffset, yoffset, pixbits); vv.width = width; vv.height = height; if (pixbits == 15) vv.bytesperline = xres*16/8; else vv.bytesperline = xres*pixbits/8; vv.depth = pixbits; vv.base = NULL; res = ioctl(v4ldev, VIDIOCSFBUF, &vv); if (res < 0) { perror("VIDIOCSFBUF failed."); exit(1); } /* set up window parameters */ vw.x = xoffset; vw.y = yoffset; vw.width = width; vw.height = height; vw.chromakey = 0; vw.flags = 0; vw.clips = NULL; vw.clipcount = 0; res = ioctl(v4ldev, VIDIOCSWIN, &vw); if (res < 0) { perror("VIDIOCSWIN"); printf("\n(Is your videocard listed in videodev.h in the v4l driver ?\n"); exit(1); } if (verbose) printf("Turning on the video window !\n"); turnon = 1; res = ioctl(v4ldev, VIDIOCCAPTURE, &turnon); if (res < 0) { perror("v4l: VIDIOCCAPTURE"); exit(1); } if (wait == -1) { unsigned char input; struct timeval tv; fd_set rfds; int channel = 2; struct termios modes, savemodes; if (verbose) printf("Changing keyboard mode.\n"); /* save old keyboard mode and set new one */ tcgetattr(0,&modes); savemodes = modes; modes.c_lflag &= ~ICANON; modes.c_lflag &= ~ECHO; tcsetattr(0,0,&modes); printf("Entering read loop, press q or [ESC] to quit.\n"); while(read(0, &input, 1) > 0) { if (input == 'q') break; if (input == 0x1B) /* ESC */ { /* Since up and down are escaped, we have to read again */ FD_ZERO(&rfds); FD_SET(0, &rfds); tv.tv_sec= 0; tv.tv_usec = 500; if (select(1, &rfds, NULL, NULL, &tv)) { if (read(0, &input, 1) < 0) break; if (read(0, &input, 1) < 0) break; if (input == 0x41) tune_to_channel(++channel); else if (input == 0x42) { if (channel > 2) tune_to_channel(--channel); } } else /* If the just hit escape, then exit */ break; } } if (verbose) printf("Restoring keyboard mode.\n"); /* restore keyboard mode */ tcsetattr(0,0,&savemodes); } else { if (verbose) printf("Alright, waiting %d seconds.", wait); usleep(wait*1000000); } if (verbose) printf("Turning off the video window.\n"); turnon = 0; res = ioctl(v4ldev, VIDIOCCAPTURE, &turnon); if (res < 0) { perror("v4l: VIDIOCCAPTURE"); exit(1); } return 1; } int main(int argc,char *argv[]) { int c; /* parse options */ for (;;) { if (-1 == (c = getopt(argc, argv, "Svds:o:m:c:n:i:t:b:x:C:h"))) break; switch (c) { case 'v': verbose = 1; break; case 'd': debug = 1; break; case 's': if (2 != sscanf(optarg,"%dx%d",&width,&height)) { width = 400; height = 300; } break; case 'o': if (2 != sscanf(optarg,"%dx%d",&xoffset,&yoffset)) { width = 5; height = 5; } break; case 'c': device = optarg; break; case 'n': if (0 == strcasecmp(optarg,"pal")) norm = VIDEO_MODE_PAL; else if (0 == strcasecmp(optarg,"ntsc")) norm = VIDEO_MODE_NTSC; else if (0 == strcasecmp(optarg,"secam")) norm = VIDEO_MODE_SECAM; else { fprintf(stderr,"unknown tv norm %s\n",optarg); exit(1); } break; case 'i': input = atoi(optarg); break; case 't': wait = atoi(optarg); break; case 'b': pixbits = atoi(optarg); break; case 'x': xres = atoi(optarg); break; case 'C': chlist = 0; while (strcmp(chanlists[chlist].name, optarg)!=0) { chlist++; if (chanlists[chlist].name == NULL) { fprintf(stderr, "unable to find channel list for %s\n", optarg); exit(1); } } break; case 'h': default: usage(argv[0]); exit(1); } } doIt(); return 0; } mjpegtools-2.1.0/lavtools/y4mstabilizer.c0000644000175000017500000005375111255225227021040 0ustar glowwormglowworm/* * $Id: y4mstabilizer.c,v 1.12 2009/09/19 19:01:43 sms00 Exp $ * * written by J. Macropol * Framework and shifting code adapted from y4mshift by Steve Schultz. * Motion detection was adapted from yuvdenoise. * * Program to stabilize a video stream. * Works only non-interlaced yuv4mpeg streams for now. * * Usage: y4mstabilizer [-v] [-a ] [-r ] * * -v Verbose. Add additional -v to increase verbosity/debug * -a The alpha value is a "viscosity" measure (see below). * -r How far to look for movement. * -s How far apart the motion search points are. * -n Do not supersample the chroma to get 1-pixel shifts. * -i Try alternate interlaced mode (does not work yet) * * Legal values are beween 0 and 1. * Useful values are beween 0.7 (or so) and .95. * Higher values resist panning more at the expense of greater * shifting. defaults to 0.95, a fairly high value, on the theory * that you probably have some significant vibrations that need smoothing. * Separate alpha values for the X- and Y-axes can be specified by separating * them with a colon. For example, * -a 0.7:0.9 * would set the X-axis alpha to 0.7, and the Y-axis alpha to 0.9. Thus, * the stabilizer would be much more responsive to side-to-side movement, * while resisting up-and-down motion. * * The defaults to 15. Smaller values speed things up, * but won't be able to cope with large/fast movements as well. * * The defaults to 48 pixels. Giving a larger number here will * speed the process tremendously, but makes it easier for the motion search * to be fooled by local movement. Use a smaller number if the search seems * to be following local movements. * * No file arguments are needed since this is a filter only program. * * TODO: * Get alternate interlace method working. * Get chroma super/subsampleing working better. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include "yuv4mpeg.h" #include "subsample.h" struct { int verbose; /* Talkative flag */ int nosuper; /* Flag not to supersample chroma on shift */ int rad, diam; /* Search radius and diameter */ int stride; /* Stride between motion points */ float alphax; /* X Viscosity */ float alphay; /* Y Viscosity */ float gsX, gsY; /* Accumulated shift */ int ss_h, ss_v; /* UV decimation factors */ } Stab; #define SS_H Stab.ss_h #define SS_V Stab.ss_v typedef struct { int x, y; } vec; static void usage(void); static void alloc_yuv(u_char**, int, int); static void subsample(uint8_t*, uint8_t*, int, int); static void gmotion(u_char**, u_char**, int, int, int, vec*); static void motion(u_char*, u_char*, int, int, int, int, vec*); static void motion0(u_char*, u_char*, int, int, int, vec*); static uint32_t calc_SAD_noaccel(uint8_t*, uint8_t*, int, int); static uint32_t calc_SAD_half_noaccel(uint8_t*, uint8_t*, uint8_t*, int, int); static void calcshift(vec*, vec*); static int xround(float, int); static void doshift(u_char**, u_char**, int, int, int, vec*); static void hshift(u_char*, u_char*, int, int, int, int, int); static void vertical_shift(u_char*, int, int, int, int, int); int main (int argc, char **argv) { int i, c, width, height, frames, err; vec g, shift; int interlace, iflag = 0, chroma_ss; u_char *yuv0[10], *yuv1[10], *yuv2[10], *line1; y4m_stream_info_t istream, ostream; y4m_frame_info_t iframe; int fdin = fileno(stdin); Stab.rad = 15; /* Default search radius */ Stab.stride = 48; /* Default stride between motion points */ Stab.alphax = Stab.alphay = 0.95; /* Default viscosity */ y4m_accept_extensions(1); opterr = 0; while ((c = getopt(argc, argv, "va:r:bis:n")) != EOF) switch (c) { case 'n': Stab.nosuper = 1; break; case 'i': iflag |= 0200; break; case 'v': Stab.verbose++; break; case 's': Stab.stride = atoi(optarg); break; case 'a': if (strchr(optarg, ':')) { if (sscanf(optarg, "%g:%g", &Stab.alphax, &Stab.alphay) != 2) usage(); } else { if (sscanf(optarg, "%g", &Stab.alphax) != 1) usage(); Stab.alphay = Stab.alphax; } break; case 'r': Stab.rad = atoi(optarg); break; case '?': case 'h': default: usage(); } /* Initialize your input stream */ y4m_init_stream_info(&istream); y4m_init_frame_info(&iframe); err = y4m_read_stream_header(fdin, &istream); if (err != Y4M_OK) mjpeg_error_exit1("Input stream error: %s\n", y4m_strerr(err)); if (y4m_si_get_plane_count(&istream) != 3) mjpeg_error_exit1("Only 3 plane formats supported"); switch (interlace = y4m_si_get_interlace(&istream)) { case Y4M_ILACE_NONE: break; case Y4M_ILACE_TOP_FIRST: case Y4M_ILACE_BOTTOM_FIRST: interlace |= iflag; break; case Y4M_ILACE_MIXED: mjpeg_error_exit1("No mixed-interlaced streams!\n"); default: mjpeg_error_exit1("Unknown interlace!\n"); } chroma_ss = y4m_si_get_chroma(&istream); SS_H = y4m_chroma_ss_x_ratio(chroma_ss).d; SS_V = y4m_chroma_ss_y_ratio(chroma_ss).d; switch (chroma_ss) { case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_444: break; case Y4M_CHROMA_MONO: mjpeg_error_exit1("MONO (1 plane) chroma not supported!\n"); case Y4M_CHROMA_444ALPHA: mjpeg_error_exit1("444ALPHA (4 plane) chroma not supported!\n"); default: if (!Stab.nosuper) mjpeg_info("Cannot supersample %s chroma", y4m_chroma_description(chroma_ss)); Stab.nosuper = 1; break; } width = y4m_si_get_width(&istream); height = y4m_si_get_height(&istream); if (Stab.verbose) y4m_log_stream_info(mjpeg_loglev_t("info"), "", &istream); /* Initialize output stream */ y4m_init_stream_info(&ostream); y4m_copy_stream_info(&ostream, &istream); y4m_write_stream_header(fileno(stdout), &ostream); /* Allocate our frame arrays */ alloc_yuv(yuv0, height, width); alloc_yuv(yuv1, height, width); alloc_yuv(yuv2, height, width); /* Set up the search diameter. */ Stab.diam = Stab.rad + Stab.rad + 1; /* Fetch 1st frame - nothing to compare, so just copy it out. * (Note that this is not strictly true if we have interlace * and use the -i modified mode where we treat the fields separately. * But I am *SURE* nobody will notice... err...) */ frames = 1; if (y4m_read_frame(fdin,&istream,&iframe,yuv0) != Y4M_OK) goto endit; subsample(yuv0[0], yuv0[3], width, height); subsample(yuv0[3], yuv0[4], width/2, height/2); y4m_write_frame(fileno(stdout), &ostream, &iframe, yuv0); for (; y4m_read_frame(fdin,&istream,&iframe,yuv1) == Y4M_OK; frames++) { if ((Stab.verbose > 1) || (Stab.verbose && ((frames % 100) == 0))) mjpeg_info("Frame %d", frames); subsample(yuv1[0], yuv1[3], width, height); subsample(yuv1[3], yuv1[4], width/2, height/2); switch (interlace) { /* Easy - non-interlaced */ case Y4M_ILACE_NONE: /* Find out how much this frame has changed from the previous */ gmotion(yuv0, yuv1, width, width, height, &g); /* Figure out how much to shift this frame to compensate */ calcshift(&g, &shift); /* If nothing to shift, just dump this frame and continue */ if ((shift.x == 0) && (shift.y == 0)) y4m_write_frame(fileno(stdout), &ostream, &iframe, yuv1); /* Else shift frame & write it out */ else { doshift(yuv1, yuv2, height, width, width, &shift); y4m_write_frame(fileno(stdout), &ostream, &iframe, yuv2); } break; /* Default interlaced method. * Treat fields as one wide field & shift both the same. */ case Y4M_ILACE_TOP_FIRST | 0: case Y4M_ILACE_BOTTOM_FIRST | 0: /* Find out how much this frame has changed from the previous */ gmotion(yuv0, yuv1, width*2, width*2, height/2, &g); /* Figure out how much to shift this frame to compensate */ calcshift(&g, &shift); /* If nothing to shift, just dump this frame and continue */ if ((shift.x == 0) && (shift.y == 0)) y4m_write_frame(fileno(stdout), &ostream, &iframe, yuv1); /* Shift the fields separately & write the frame */ else { doshift(yuv1, yuv2, height/2, width,width*2,&shift); doshift(yuv1+5, yuv2+5, height/2, width,width*2,&shift); y4m_write_frame(fileno(stdout), &ostream, &iframe, yuv2); } break; /* Alternate interlaced method: * Treat fields as separate frames, one half pixel apart vertically. */ case Y4M_ILACE_TOP_FIRST | 0200: /* Last bottom half -> Top half */ gmotion(yuv0+5, yuv1, width, width*2, height/2, &g); g.y += 0.5; calcshift(&g, &shift); doshift(yuv1, yuv2, height/2, width, width*2, &shift); /* Top half -> Bottom half */ gmotion(yuv1, yuv1+5, width, width*2, height/2, &g); g.y -= 0.5; calcshift(&g, &shift); doshift(yuv1+5, yuv2+5, height/2, width, width*2, &shift); y4m_write_frame(fileno(stdout), &ostream, &iframe, yuv2); break; case Y4M_ILACE_BOTTOM_FIRST | 0200: /* Last top half -> Bottom half */ gmotion(yuv0, yuv1+5, width, width*2, height/2, &g); g.y -= 0.5; calcshift(&g, &shift); doshift(yuv1+5, yuv2+5, height/2, width, width*2, &shift); /* Bottom half -> Top half */ gmotion(yuv1+5, yuv1, width, width*2, height/2, &g); g.y += 0.5; calcshift(&g, &shift); doshift(yuv1, yuv2, height/2, width, width*2, &shift); y4m_write_frame(fileno(stdout), &ostream, &iframe, yuv2); break; } /* swap yuv0 and yuv1, so yuv1 becomes the old reference frame * for the motion search. */ for (i = 0; i < 10; i++) { line1 = yuv0[i]; yuv0[i] = yuv1[i]; yuv1[i] = line1; } } /* All done - close out the streams and exit */ endit: y4m_fini_frame_info(&iframe); y4m_fini_stream_info(&istream); y4m_fini_stream_info(&ostream); exit(0); } static void usage (void) { fputs( "Program to stabilize a video stream.\n" "Works only non-interlaced yuv4mpeg streams for now.\n" "\n" "Usage: y4mstabilizer [-v] [-a ] [-r ]\n" "\n" " -v Verbose. Repeat -v to increase verbosity/debug info\n" " -a A \"viscosity\" measure (see below).\n" " -r How far to look for movement.\n" " -s How far apart the motion search points are.\n" " -n Do not supersample the chroma to get 1-pixel shifts.\n" " -i Try alternate interlaced mode (does not work yet)\n" "\n" "Legal values are beween 0 and 1.\n" "Useful values are beween 0.7 (or so) and .95.\n" "Higher values resist panning more at the expense of greater\n" "shifting. defaults to 0.95, a fairly high value, on the theory\n" "that you probably have some significant vibrations that need smoothing.\n" "Separate alpha values for the X- and Y-axes can be specified by separating\n" "them with a colon. For example,\n" " -a 0.7:0.9\n" "would set the X-axis alpha to 0.7, and the Y-axis alpha to 0.9. Thus,\n" "the stabilizer would be much more responsive to side-to-side movement,\n" "while resisting up-and-down motion.\n" "\n" "The defaults to 15. Smaller values speed things up,\n" "but won't be able to cope with large/fast movements as well.\n" "\n" "The defaults to 48 pixels. Giving a larger number here will\n" "speed the process tremendously, but makes it easier for the motion search\n" "to be fooled by local movement. Use a smaller number if the search seems\n" "to be following local movements.\n" "\n" "No file arguments are needed since this is a filter only program.\n" "\n" "This program presently works best when given 444, deinterlaced input.\n" "Very good results can be obtained with the following pipeline:\n" " ... | yuvdeinterlace | \\\n" " y4mscaler -v 0 -O sar=src -O chromass=444 | \\\n" " y4mstabilizer | \\\n" " y4mscaler -v 0 -O sar=src -O chromass=420_MPEG2 | ...\n" , stderr); exit(1); } static void alloc_yuv (u_char **yuv, int h, int w) { int len = h * w * 2; /* Double the amount - overkill but it's easier than figuring out how much (off by one?) is really needed */ int uvlen = Stab.nosuper ? (len / (SS_H * SS_V)) : len; yuv[0] = malloc(len); if (yuv[0] == NULL) mjpeg_error_exit1(" malloc(%d) failed\n", len); yuv[1] = malloc(uvlen); if (yuv[1] == NULL) mjpeg_error_exit1(" malloc(%d) failed\n", uvlen); yuv[2] = malloc(uvlen); if (yuv[2] == NULL) mjpeg_error_exit1(" malloc(%d) failed\n", uvlen); yuv[3] = malloc(len/4); if (yuv[3] == NULL) mjpeg_error_exit1(" malloc(%d) failed\n", len/4); yuv[4] = malloc(len/16); if (yuv[4] == NULL) mjpeg_error_exit1(" malloc(%d) failed\n", len/16); yuv[5] = yuv[0] + w; yuv[6] = yuv[1] + w/SS_H; yuv[7] = yuv[2] + w/SS_H; yuv[8] = yuv[3] + w/2; yuv[9] = yuv[3] + w/4; } /***************************************************************************** * generate a lowpassfiltered and subsampled copy * * of the source image (src) at the destination * * image location. * * Lowpass-filtering is important, as this subsampled * * image is used for motion estimation and the result * * is more reliable when filtered. * * only subsample actual data, but keeping full buffer size for simplicity * *****************************************************************************/ static void subsample (uint8_t *src, uint8_t *dst, int w, int h) { int c, x, w2 = w / 2; uint8_t *s1 = src; uint8_t *s2 = src + w; for (h /= 2; h >= 0; h--) { for (x = 0; x < w2; x++) { c = *s1++ + *s2++; c += *s1++ + *s2++; *dst++ = c >> 2; } s1 += w; s2 += w; } } /* * Determine global motion. * Note that only the Y-plane is used. * The global motion is taken as the median of the individual motions. * * Note that w (frame width) should equal ws (frame width stride) unless * we are treating an interlaced frame as two subframes, in which case * ws should be twice w. */ static void gmotion (u_char **y0, u_char **y1, int w, int ws, int h, vec *dij) { int i, j, di, dj; int we = w - (Stab.rad+8); int he = h - (Stab.rad+8); int xs[Stab.diam+Stab.diam], ys[Stab.diam+Stab.diam], t = 0; vec ij; bzero(xs, sizeof xs); bzero(ys, sizeof ys); /* Determine local motions for all blocks */ for (i = Stab.rad; i < we; i += Stab.stride) for (j = Stab.rad; j < he; j += Stab.stride) { ij.x = i/4; ij.y = j/4; motion(y0[4], y1[4], ws/4, Stab.rad/4, i/4, j/4, &ij); ij.x += ij.x; ij.y += ij.y; motion(y0[3], y1[3], ws/2, 3, i/2, j/2, &ij); ij.x += ij.x; ij.y += ij.y; motion(y0[0], y1[0], ws, 3, i, j, &ij); motion0(y0[0],y1[0], ws, i, j, &ij); di = ij.x - (i+i); dj = ij.y - (j+j); /*if ((abs(di) <= Stab.rad) && (abs(dj) <= Stab.rad))*/ { xs[di+Stab.diam]++; ys[dj+Stab.diam]++; t++; } } /* Determine median motions */ t /= 2; for (di = i = 0; di < Stab.diam+Stab.diam; i += xs[di++]) if (i >= t) break; dij->x = di - Stab.diam; for (dj = j = 0; dj < Stab.diam+Stab.diam; j += ys[dj++]) if (j >= t) break; dij->y = dj - Stab.diam; } /********************************************************************* * * * Estimate Motion Vectors * * * *********************************************************************/ static void motion (u_char *y0, u_char *y1, int w, int r, int ri, int rj, vec *dij) { uint32_t best_SAD=INT_MAX, SAD=INT_MAX; int i = dij->x, j = dij->y; int ii, jj; y0 += (rj * w) + ri; for (ii = -r; ii <= r; ii++) for (jj = -r; jj <= r; jj++) { SAD = calc_SAD_noaccel(y0, y1 + (j+jj) * w + i+ii, w, best_SAD); SAD += ii*ii + jj*jj; /* favour center matches... */ if (SAD <= best_SAD) { best_SAD = SAD; dij->x = i + ii; dij->y = j + jj; } } } /********************************************************************* * * * Estimate Motion Vectors in not subsampled frames * * * *********************************************************************/ static void motion0 (u_char *y0, u_char *y1, int w, int ri, int rj, vec *dij) { uint32_t SAD, best_SAD = INT_MAX; int adjw; int i = dij->x, j = dij->y; int ii, jj; u_char *y1r = y1 + j*w + i; y0 += rj*w + ri; y1 += (j-1)*w + i - 1; adjw = w - 3; for (jj = -1; jj <= 1; jj++, y1 += adjw) for (ii = -1; ii <= 1; ii++, y1++) { SAD = calc_SAD_half_noaccel(y0, y1r, y1, w, best_SAD); if (SAD < best_SAD) { best_SAD = SAD; dij->x = ii+i+i-1; dij->y = jj+j+j-1; } } } /********************************************************************* * * * SAD-function for Y without MMX/MMXE * * * *********************************************************************/ static uint32_t calc_SAD_noaccel (uint8_t *frm, uint8_t *ref, int w, int limit) { uint32_t d = 0; uint32_t adj = w - 8; #define LINE \ d += abs(*frm++ - *ref++); d += abs(*frm++ - *ref++); \ d += abs(*frm++ - *ref++); d += abs(*frm++ - *ref++); \ d += abs(*frm++ - *ref++); d += abs(*frm++ - *ref++); \ d += abs(*frm++ - *ref++); d += abs(*frm++ - *ref++); \ if (d > limit) \ return INT_MAX; \ frm += adj; ref += adj LINE; LINE; LINE; LINE; LINE; LINE; LINE; LINE; #undef LINE return d; } /********************************************************************* * * * halfpel SAD-function for Y without MMX/MMXE * * * *********************************************************************/ static uint32_t calc_SAD_half_noaccel(uint8_t*ref, uint8_t*frm1, uint8_t*frm2, int w, int limit) { uint32_t d = 0; uint32_t adj = w - 8; #define LINE \ d += abs(((*frm1++ + *frm2++) >> 1) - *ref++); \ d += abs(((*frm1++ + *frm2++) >> 1) - *ref++); \ d += abs(((*frm1++ + *frm2++) >> 1) - *ref++); \ d += abs(((*frm1++ + *frm2++) >> 1) - *ref++); \ d += abs(((*frm1++ + *frm2++) >> 1) - *ref++); \ d += abs(((*frm1++ + *frm2++) >> 1) - *ref++); \ d += abs(((*frm1++ + *frm2++) >> 1) - *ref++); \ d += abs(((*frm1++ + *frm2++) >> 1) - *ref++); \ if (d > limit) \ return INT_MAX; \ frm1 += adj; frm2 += adj; ref += adj LINE; LINE; LINE; LINE; LINE; LINE; LINE; LINE; #undef LINE return d; } static void calcshift (vec *gp, vec *shftp) { int ss_h = Stab.nosuper ? SS_H : 1; int ss_v = Stab.nosuper ? SS_V : 1; /* gmotion() returns motion in half-pixels */ /* Factor in the "viscosity"... */ Stab.gsX = (Stab.gsX * Stab.alphax) + gp->x/2.0; Stab.gsY = (Stab.gsY * Stab.alphay) + gp->y/2.0; /* Now that we know the movement, shift to counteract it */ shftp->x = -xround(Stab.gsX, ss_h); shftp->y = -xround(Stab.gsY, ss_v); if (Stab.verbose > 1) mjpeg_info("global motion xy*2=<%d,%d>" " Accumulated xy=<%g,%g> shift xy=%d,%d>\n", gp->x, gp->y, Stab.gsX, Stab.gsY, shftp->x, shftp->y); } /* Round the given float value to the nearest multiple of . */ static int xround (float v, int r) { if (v < 0) return (-xround(-v, r)); return (((int)((v + r/2.0) / r)) * r); } /* * Shift a frame. * The frame is always copied to the destination. * * Note that w (frame width) should equal ws (frame width stride) unless * we are treating an interlaced frame as two subframes, in which case * ws should be twice w. */ static void doshift (u_char**yuv1, u_char**yuv2, int h, int w, int ws, vec *shift) { int dosuper = (shift->x % SS_H) | (shift->y % SS_V); int ss_h = dosuper ? 1 : SS_H; int ss_v = dosuper ? 1 : SS_V; /* If we have to supersample the chroma, then do it now, before shifting */ if (dosuper) chroma_supersample(Y4M_CHROMA_420JPEG, yuv1, w, h); /* Do the horizontal shifting first. The frame is shifted into * the yuv2 frame. Even if there is no horizontal shifting to do, * we copy the frame because the vertical shift is desctructive, * and we want to preserve the yuv1 frame to compare against the * next one. */ hshift(yuv1[0],yuv2[0],h, w, shift->x, 16, ws); hshift(yuv1[1],yuv2[1],h/ss_v,w/ss_h,shift->x/ss_h,128, ws/ss_h); hshift(yuv1[2],yuv2[2],h/ss_v,w/ss_h,shift->x/ss_h,128, ws/ss_h); /* Vertical shift, then write the frame */ if (shift->y) { vertical_shift(yuv2[0], shift->y, w, ws, h, 16); vertical_shift(yuv2[1], shift->y/ss_v, w/ss_h, ws/ss_h, h/ss_v, 128); vertical_shift(yuv2[2], shift->y/ss_v, w/ss_h, ws/ss_h, h/ss_v, 128); } /* Undo the supersampling */ if (dosuper) chroma_subsample(Y4M_CHROMA_420JPEG, yuv1, w, h); } /* * Shift one plane of the frame by the given horizontal shift amount. * The shifted frame is left in the buffer. */ static void hshift (u_char *vsrc, u_char *vdst, int h, int w, int shift, int blk,int ws) { int i; for (i = 0; i < h; i++) { if (shift > 0) { memmove(vdst + shift, vsrc, w - shift); memset(vdst, blk, shift); /* black */ } else if (shift < 0) { memmove(vdst, vsrc - shift, w + shift); memset(vdst+w+shift, blk, -shift); } else memmove(vdst, vsrc, w); vsrc += ws; vdst += ws; } } /* * Shift the frame vertically. The frame data is modified in place. */ static void vertical_shift(u_char *y, int vshift, int w, int ws, int h, int blk) { /* Easy case - we can shift everything at once */ if (w == ws) { if (vshift > 0) { memmove(y + vshift*ws, y, (h-vshift) * ws); memset(y, blk, vshift * ws); } else { memmove(y, y - vshift * ws, (h+vshift) * ws); memset(y + (h + vshift) * ws, blk, -vshift * w); } } /* Must go line-by-line */ else { u_char *dst, *src; int i, n; if (vshift > 0) { dst = y + (h - 1) * ws; src = dst - vshift * ws; n = h - vshift; for (i = 0; i < n; i++, (dst -= ws), (src -= ws)) memcpy(dst, src, w); for ( ; i < h; i++, dst -= ws) memset(dst, blk, w); } else { dst = y; src = y - vshift * ws; n = h + vshift; for (i = 0; i < n; i++, (dst += ws), (src += ws)) memcpy(dst, src, w); for ( ; i < h; i++, dst += ws) memset(dst, blk, w); } } } mjpegtools-2.1.0/lavtools/pipelist.c0000644000175000017500000001501311240763641020055 0ustar glowwormglowworm/* * pipelist.[ch] - provides two functions to read / write pipe * list files, the "recipes" for lavpipe * * Copyright (C) 2001, pHilipp Zabel * Copyright (C) 2001, Matthew Marjanovic * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "mjpeg_logging.h" #include "pipelist.h" extern int verbose; int read_pipe_list (char *name, PipeList *pl) { FILE *fd; char line[1024]; PipeSegment *seq; int i, j, n; fd = fopen (name, "r"); fgets (line, 1024, fd); if (strcmp (line, "LAV Pipe List\n") == 0) { /* 1. video norm */ fgets (line, 1024, fd); if(line[0]!='N' && line[0]!='n' && line[0]!='P' && line[0]!='p') { fclose(fd); mjpeg_error_exit1("Pipe list second line is not NTSC/PAL"); } mjpeg_debug("Pipelist norm is %s",line[0]=='N'||line[0]=='n'?"NTSC":"PAL"); if(line[0]=='N'||line[0]=='n') pl->video_norm = 'n'; else pl->video_norm = 'p'; /* 2. input streams */ fgets (line, 1024, fd); if (sscanf (line, "%d", &(pl->source_count)) != 1) { fclose(fd); mjpeg_error_exit1( "pipelist: # of input streams expected, \"%s\" found", line); } mjpeg_info( "Pipe list contains %d input streams", pl->source_count); pl->source_cmd = (char **) malloc (pl->source_count * sizeof (char *)); for (i=0; isource_count; i++) { fgets(line,1024,fd); n = strlen(line); if(line[n-1]!='\n') { fclose(fd); mjpeg_error_exit1("Input cmdline in pipe list too long"); } line[n-1] = 0; /* Get rid of \n at end */ pl->source_cmd[i] = (char *) malloc (n); strncpy (pl->source_cmd[i], line, n); } /* 3. sequences */ pl->frame_count = 0; pl->segment_count = 0; pl->segments = (PipeSegment **) malloc (32 * sizeof (PipeSegment *)); while (fgets (line, 1024, fd)) { seq = (PipeSegment *) malloc (sizeof (PipeSegment)); /* 3.1. frames in sequence */ if (sscanf (line, "%d", &(seq->frame_count)) != 1) { fclose(fd); mjpeg_error_exit1( "pipelist: # of frames in sequence expected, \"%s\" found", line); } if (seq->frame_count < 1) { fclose(fd); mjpeg_error_exit1( "Pipe list contains sequence of length < 1 frame"); } mjpeg_debug( "Pipe list sequence %d contains %d frames", pl->segment_count, seq->frame_count); pl->frame_count += seq->frame_count; /* 3.2. input streams */ if (fgets (line, 1024, fd) == NULL) { fclose(fd); mjpeg_error_exit1("pipelist: end of file reading # of streams"); } if (sscanf (line, "%d", &(seq->input_count)) != 1) { fclose(fd); mjpeg_error_exit1( "pipelist: # of streams in sequence expected, \"%s\" found", line); } seq->input_index = (int *) malloc (seq->input_count * sizeof (int)); seq->input_offset = (unsigned long *) malloc (seq->input_count * sizeof (unsigned long)); for (i=0; iinput_count; i++) { fgets (line, 1024, fd); /* ignore eof - will detect later */ j = sscanf (line, "%d %lud", &(seq->input_index[i]), &(seq->input_offset[i])); if (j == 1) { /* if no offset is given, assume ofs = 0 */ seq->input_offset[i] = 0; j++; } if (j != 2) { fclose(fd); mjpeg_error( "pipelist: input stream index & offset expected, \"%s\" found", line); return -1; } if (seq->input_index[i] >= pl->source_count) { fclose(fd); mjpeg_error( "Sequence requests input stream that is not contained in pipe list"); return(-1); } } /* 3.3. output cmd */ if (fgets(line, 1024, fd) == NULL) { fclose(fd); mjpeg_error_exit1( "Error in pipe list: Unexpected end"); } n = strlen(line); if(line[n-1]!='\n') { fclose(fd); mjpeg_error("Output cmdline in pipe list too long"); return(-1); } line[n-1] = 0; /* Get rid of \n at end */ seq->output_cmd = (char *) malloc (n); strncpy (seq->output_cmd, line, n); pl->segments[pl->segment_count++] = seq; if ((pl->segment_count % 32) == 0) pl->segments = (PipeSegment **) realloc (pl->segments, (pl->segment_count + 32) * sizeof (PipeSegment *)); pl->segments = (PipeSegment **) realloc (pl->segments, sizeof (pl->segments) + 32 * sizeof (PipeSegment *)); } fclose(fd); return 0; } /* errno = EBADMSG; */ fclose(fd); return -1; } int write_pipe_list (char *name, PipeList *pl) { FILE *fd; int i, n; fd = fopen (name, "w"); fprintf (fd, "LAV Pipe List\n"); /* 1. video norm */ fprintf (fd, "%s\n", (pl->video_norm == 'n') ? "NTSC" : "PAL"); /* 2. input streams */ fprintf (fd, "%d\n", pl->source_count); for (i=0; isource_count; i++) fprintf (fd, "%s\n", pl->source_cmd[i]); /* 3. sequences */ for (i=0; isegment_count; i++) { PipeSegment *seq = pl->segments[i]; /* 3.1. frames in sequence */ fprintf (fd, "%d\n", seq->frame_count); /* 3.2. input streams */ fprintf (fd, "%d\n", seq->input_count); for (n=0; ninput_count; n++) fprintf (fd, "%d %lud\n", seq->input_index[n], seq->input_offset[n]); /* 3.3. output cmd */ fprintf (fd, "%s\n", seq->output_cmd); } fclose(fd); return 0; } mjpegtools-2.1.0/lavtools/pnmtoy4m.c0000644000175000017500000006732310603772216020026 0ustar glowwormglowworm/* * pnmtoy4m.c: Generate a YUV4MPEG2 stream from one or more PNM/PAM images. * * Converts R'G'B' to ITU-Rec.601 Y'CbCr colorspace, and/or * converts [0,255] grayscale to Rec.601 Y' luma. * * * Copyright (C) 2004 Matthew J. Marjanovic * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include #include #include #include #include #include #include #include #include "colorspace.h" #ifndef O_BINARY # define O_BINARY 0 #endif /* command-line parameters */ typedef struct _cl_info { y4m_ratio_t output_aspect; y4m_ratio_t output_framerate; int output_interlace; int input_interlace; int deinterleave; int offset; int framecount; int repeatlast; int verbosity; int fdin; int bgr; } cl_info_t; static void usage(const char *progname) { fprintf(stderr, "\n"); fprintf(stderr, "usage: %s [options] [pnm-file]\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "Reads RAW PNM/PAM image(s), and produces YUV4MPEG2 stream on stdout.\n"); fprintf(stderr, "Converts computer graphics R'G'B' colorspace to digital video Y'CbCr.\n"); fprintf(stderr, "\n"); fprintf(stderr, "If 'pnm-file' is not specified, reads from stdin.\n"); fprintf(stderr, "\n"); fprintf(stderr, " options: (defaults specified in [])\n"); fprintf(stderr, "\n"); fprintf(stderr, " -o n frame offset (skip n input frames) [0]\n"); fprintf(stderr, " -n n frame count (output n frames; 0 == all of them) [0]\n"); fprintf(stderr, " -r repeat last input frame\n"); fprintf(stderr, " -D x treat PNM images as de-interleaved fields, with:\n"); fprintf(stderr, " t = first-image-is-top-field\n"); fprintf(stderr, " b = first-image-is-bottom-field\n"); fprintf(stderr, " -F n:d output framerate [30000:1001 = NTSC]\n"); fprintf(stderr, " -A w:h output pixel aspect ratio [1:1]\n"); fprintf(stderr, " -I x output interlacing [from -D, or p]\n"); fprintf(stderr, " p = none/progressive\n"); fprintf(stderr, " t = top-field-first\n"); fprintf(stderr, " b = bottom-field-first\n"); fprintf(stderr, " -v n verbosity (0,1,2) [1]\n"); fprintf(stderr, " -B pixels are packed in BGR(A) format [RGB(A)]\n"); } static void parse_args(cl_info_t *cl, int argc, char **argv) { int c; cl->offset = 0; cl->framecount = 0; cl->output_aspect = y4m_sar_SQUARE; cl->output_interlace = Y4M_UNKNOWN; cl->output_framerate = y4m_fps_NTSC; cl->deinterleave = 0; cl->input_interlace = Y4M_ILACE_NONE; cl->repeatlast = 0; cl->verbosity = 1; cl->fdin = fileno(stdin); /* default to stdin */ cl->bgr = 0; while ((c = getopt(argc, argv, "A:F:I:D:o:n:rv:Bh")) != -1) { switch (c) { case 'A': if (y4m_parse_ratio(&(cl->output_aspect), optarg) != Y4M_OK) { mjpeg_error("Could not parse ratio: '%s'", optarg); goto ERROR_EXIT; } break; case 'F': if (y4m_parse_ratio(&(cl->output_framerate), optarg) != Y4M_OK) { mjpeg_error("Could not parse ratio: '%s'", optarg); goto ERROR_EXIT; } break; case 'I': switch (optarg[0]) { case 'p': cl->output_interlace = Y4M_ILACE_NONE; break; case 't': cl->output_interlace = Y4M_ILACE_TOP_FIRST; break; case 'b': cl->output_interlace = Y4M_ILACE_BOTTOM_FIRST; break; default: mjpeg_error("Unknown value for output interlace: '%c'", optarg[0]); goto ERROR_EXIT; break; } break; case 'D': cl->deinterleave = 1; switch (optarg[0]) { case 't': cl->input_interlace = Y4M_ILACE_TOP_FIRST; break; case 'b': cl->input_interlace = Y4M_ILACE_BOTTOM_FIRST; break; default: mjpeg_error("Unknown value for input interlace: '%c'", optarg[0]); goto ERROR_EXIT; break; } break; case 'o': if ((cl->offset = atoi(optarg)) < 0) mjpeg_error_exit1("Offset must be >= 0: '%s'", optarg); break; case 'n': if ((cl->framecount = atoi(optarg)) < 0) mjpeg_error_exit1("Frame count must be >= 0: '%s'", optarg); break; case 'r': cl->repeatlast = 1; break; case 'v': cl->verbosity = atoi(optarg); if ((cl->verbosity < 0) || (cl->verbosity > 2)) mjpeg_error("Verbosity must be 0, 1, or 2: '%s'", optarg); break; case 'h': usage(argv[0]); exit(0); break; case 'B': cl->bgr = 1; break; case '?': default: goto ERROR_EXIT; break; } } /* optional remaining argument is a filename */ if (optind == (argc - 1)) { if ((cl->fdin = open(argv[optind], O_RDONLY | O_BINARY)) == -1) mjpeg_error_exit1("Failed to open '%s': %s", argv[optind], strerror(errno)); } else if (optind != argc) goto ERROR_EXIT; mjpeg_default_handler_verbosity(cl->verbosity); /* output ilace defaults to match input (or none if input is interleaved) */ if (cl->output_interlace == Y4M_UNKNOWN) { if (cl->deinterleave) cl->output_interlace = cl->input_interlace; else cl->output_interlace = Y4M_ILACE_NONE; } mjpeg_info("Command-line Parameters:"); if (!cl->deinterleave) { mjpeg_info(" input format: interleaved"); } else { mjpeg_info(" input format: field-sequential, %s", (cl->input_interlace == Y4M_ILACE_TOP_FIRST) ? "first-image-is-top" : "first-image-is-bottom"); } mjpeg_info(" pixel packing: %s", (cl->bgr?"BGR(A)":"RGB(A)")); mjpeg_info(" output framerate: %d:%d", cl->output_framerate.n, cl->output_framerate.d); mjpeg_info(" output SAR: %d:%d", cl->output_aspect.n, cl->output_aspect.d); mjpeg_info(" output interlace: %s", mpeg_interlace_code_definition(cl->output_interlace)); mjpeg_info(" starting frame: %d", cl->offset); if (cl->framecount == 0) mjpeg_info(" # of frames: all%s", (cl->repeatlast) ? ", repeat last frame forever" : ", until input exhausted"); else mjpeg_info(" # of frames: %d%s", cl->framecount, (cl->repeatlast) ? ", repeat last frame until done" : ", or until input exhausted"); /* DONE! */ return; ERROR_EXIT: mjpeg_error("For usage hints, use option '-h'. Please take a hint."); exit(1); } /* the various PNM formats we handle */ typedef enum { FMT_PAM = 0, FMT_PPM_RAW, FMT_PGM_RAW, FMT_PBM_RAW, FMT_PPM_PLAIN, FMT_PGM_PLAIN, FMT_PBM_PLAIN, FMT_UNKNOWN } pnm_format_t; #define FMT_FIRST FMT_PAM #define FMT_COUNT FMT_UNKNOWN /* 'magic numbers' of the PNM formats (corresponding to enum above) */ const char *magics[FMT_COUNT+1] = { "P7", "P6", "P5", "P4", "P3", "P2", "P1", "*UNKNOWN*" }; /* the various PAM "tupls" we handle */ typedef enum { TUPL_RGB = 0, TUPL_GRAY, TUPL_RGB_ALPHA, TUPL_GRAY_ALPHA, TUPL_BW, TUPL_BW_ALPHA, TUPL_UNKNOWN } pam_tupl_t; #define TUPL_FIRST TUPL_RGB #define TUPL_COUNT TUPL_UNKNOWN struct tupl_info { const char *tag; int depth; }; /* descriptions of the PAM tupls (corresponding to enum above) */ const struct tupl_info tupls[TUPL_COUNT+1] = { { "RGB", 3 }, { "GRAYSCALE", 1 }, { "RGB_ALPHA", 4 }, { "GRAYSCALE_ALPHA", 2 }, { "BLACKANDWHITE", 1 }, { "BLACKANDWHITE_ALPHA", 2 }, { "*UNKNOWN*", 0 } }; /* PNM image information */ typedef struct _pnm_info { pnm_format_t format; int width; int height; int depth; pam_tupl_t tupl; } pnm_info_t; static int pnm_info_equal(pnm_info_t *a, pnm_info_t *b) { return ((a->format == b->format) && (a->width == b->width) && (a->height == b->height) && (a->depth == b->depth) && (a->tupl == b->tupl)); } static void pnm_info_copy(pnm_info_t *dst, pnm_info_t *src) { dst->format = src->format; dst->width = src->width; dst->height = src->height; dst->depth = src->depth; dst->tupl = src->tupl; } static char *read_tag_and_value(int fd, char *line, int maxlen) { int found_end_of_tag = 0; char *v = NULL; int n; while ( (maxlen > 0) && ((n = read(fd, line, 1)) == 1) && (*line != '\n') ) { if (!found_end_of_tag) { if (isspace(*line)) { *line = '\0'; found_end_of_tag = 1; } } else if (v == NULL) { if (!isspace(*line)) v = line; } line++; } if (maxlen <= 0) return NULL; if (n != 1) return NULL; *line = '\0'; if (v == NULL) return line; return v; } static int read_pam_header(int fd, pnm_info_t *pnm) { char line[128]; int done = 0; int maxval = 0; char *val; pnm->width = 0; pnm->height = 0; pnm->depth = 0; pnm->tupl = TUPL_UNKNOWN; while (!done && ((val = read_tag_and_value(fd, line, 128)) != NULL)) { if (!strcmp(line, "ENDHDR")) { done = 1; } else if (!strcmp(line, "HEIGHT")) { pnm->height = atoi(val); } else if (!strcmp(line, "WIDTH")) { pnm->width = atoi(val); } else if (!strcmp(line, "DEPTH")) { pnm->depth = atoi(val); } else if (!strcmp(line, "MAXVAL")) { maxval = atoi(val); } else if (!strcmp(line, "TUPLTYPE")) { if (pnm->tupl != TUPL_UNKNOWN) mjpeg_error_exit1("Too many PAM TUPLTYPE's: %s", val); for (pnm->tupl = TUPL_FIRST; pnm->tupl < TUPL_UNKNOWN; (pnm->tupl)++) { if (!(strcmp(val, tupls[pnm->tupl].tag))) break; } if (pnm->tupl == TUPL_UNKNOWN) mjpeg_error_exit1("Unknown PAM TUPLTYPE: %s", val); } } if ( (pnm->width == 0) || (pnm->height == 0) || (pnm->depth == 0) || (maxval == 0) ) mjpeg_error_exit1("Bad PAM header!\n"); if (pnm->tupl == TUPL_UNKNOWN) { for (pnm->tupl = TUPL_FIRST; pnm->tupl < TUPL_UNKNOWN; (pnm->tupl)++) { if (pnm->depth == tupls[pnm->tupl].depth) break; } if (pnm->tupl == TUPL_UNKNOWN) mjpeg_error_exit1("No PAM TUPL for depth %d!", pnm->depth); } else { if (pnm->depth != tupls[pnm->tupl].depth) mjpeg_error_exit1("PAM depth mismatch: %d != %d for %s.", pnm->depth, tupls[pnm->tupl].depth, tupls[pnm->tupl].tag); } if (maxval != 255) mjpeg_error_exit1("Expecting maxval == 255, not %d!", maxval); return 0; } #define DO_READ_NUMBER(var) \ do { \ if (!isdigit(s[0])) \ mjpeg_error_exit1("PNM read error: bad char %d", s[0]); \ (var) = ((var) * 10) + (s[0] - '0'); \ } while (((n = read(fd, s, 1)) == 1) && (!isspace(s[0]))); \ if (n <= 0) return -1; #define DO_SKIP_WHITESPACE() \ incomment = 0; \ while ( ((n = read(fd, s, 1)) == 1) && \ ((isspace(s[0])) || (s[0] == '#') || (incomment)) ) { \ if (s[0] == '#') incomment = 1; \ if (s[0] == '\n') incomment = 0; \ } \ if (n <= 0) return -1; /* * returns: 0 - success, got header * 1 - EOF, no new frame * -1 - failure (actually, just errors out...) */ static int read_pnm_header(int fd, pnm_info_t *pnm) { char s[6]; int incomment; int n; int maxval = 0; pnm->width = 0; pnm->height = 0; pnm->depth = 0; /* look for MAGIC */ n = y4m_read(fd, s, 3); if (n > 0) return 1; /* EOF */ if (n < 0) mjpeg_error_exit1("Bad PNM header magic!"); for (pnm->format = FMT_FIRST; pnm->format < FMT_UNKNOWN; (pnm->format)++) { if (!(strncmp(s, magics[pnm->format], 2))) break; } if ( (pnm->format == FMT_UNKNOWN) || (!isspace(s[2])) ) mjpeg_error_exit1("Bad PNM magic!"); if (pnm->format == FMT_PAM) { if (s[2] != '\n') mjpeg_error_exit1("Bad PAM magic!"); return read_pam_header(fd, pnm); } else { pnm->tupl = TUPL_UNKNOWN; incomment = 0; DO_SKIP_WHITESPACE(); DO_READ_NUMBER(pnm->width); DO_SKIP_WHITESPACE(); DO_READ_NUMBER(pnm->height); if ((pnm->format != FMT_PBM_RAW) && (pnm->format != FMT_PBM_PLAIN)) { DO_SKIP_WHITESPACE(); DO_READ_NUMBER(maxval); if (maxval != 255) mjpeg_error_exit1("Expecting maxval == 255, not %d!", maxval); } switch (pnm->format) { case FMT_PPM_RAW: case FMT_PPM_PLAIN: pnm->depth = 3; break; case FMT_PGM_RAW: case FMT_PBM_RAW: case FMT_PGM_PLAIN: case FMT_PBM_PLAIN: pnm->depth = 1; break; default: assert(0); break; } } return 0; } static void alloc_buffers(uint8_t *buffers[], int width, int height, int depth) { mjpeg_debug("Alloc'ing buffers"); buffers[0] = malloc(width * height * sizeof(buffers[0][0])); if (depth > 1) { buffers[1] = malloc(width * height * sizeof(buffers[1][0])); buffers[2] = malloc(width * height * sizeof(buffers[2][0])); } if (depth > 3) buffers[3] = malloc(width * height * sizeof(buffers[3][0])); } static void read_rgba_raw(int fd, uint8_t *buffers[], uint8_t *rowbuffer, int width, int height, int bgra) { int x, y; uint8_t *pixels; uint8_t *R = buffers[0]; uint8_t *G = buffers[1]; uint8_t *B = buffers[2]; uint8_t *A = buffers[3]; for (y = 0; y < height; y++) { pixels = rowbuffer; y4m_read(fd, pixels, width * 4); if (!bgra) { for (x = 0; x < width; x++) { *(R++) = *(pixels++); *(G++) = *(pixels++); *(B++) = *(pixels++); *(A++) = *(pixels++); } } else { for (x = 0; x < width; x++) { *(B++) = *(pixels++); *(G++) = *(pixels++); *(R++) = *(pixels++); *(A++) = *(pixels++); } } } } static void read_ppm_raw(int fd, uint8_t *buffers[], uint8_t *rowbuffer, int width, int height, int bgr) { int x, y; uint8_t *pixels; uint8_t *R = buffers[0]; uint8_t *G = buffers[1]; uint8_t *B = buffers[2]; for (y = 0; y < height; y++) { pixels = rowbuffer; y4m_read(fd, pixels, width * 3); if (!bgr) { for (x = 0; x < width; x++) { *(R++) = *(pixels++); *(G++) = *(pixels++); *(B++) = *(pixels++); } } else { for (x = 0; x < width; x++) { *(B++) = *(pixels++); *(G++) = *(pixels++); *(R++) = *(pixels++); } } } } static void read_pgm_raw(int fd, uint8_t *buffer, int width, int height) { mjpeg_debug("read PGM into one buffer, %dx%d", width, height); y4m_read(fd, buffer, width * height); } #define Y_BLACK 16 #define Y_WHITE 219 /* 000000000011111111112222222222 012345678901234567890123456789 76543210765432107654321076543210 */ static void read_pbm_raw(int fd, uint8_t *buffer, int width, int height) { int row_bytes = (width + 7) >> 3; int total_bytes = row_bytes * height; uint8_t *pbm = buffer + total_bytes - 1; uint8_t *luma = buffer + (width * height) - 1; int x, y; mjpeg_debug("read PBM into one buffer, %dx%d", width, height); y4m_read(fd, buffer, total_bytes); for (y = height - 1; y >= 0; y--) { for (x = width - 1; x >= 0; ) { int shift = 7 - (x % 8); uint8_t bits = *(pbm--) >> shift; while (shift < 8) { *(luma--) = (bits & 0x1) ? Y_BLACK : Y_WHITE; bits >>= 1; shift++; x--; } } } } static void read_pnm_data(int fd, uint8_t *planes[], uint8_t *rowbuffer, pnm_info_t *pnm, int bgr) { switch (pnm->format) { case FMT_PPM_RAW: read_ppm_raw(fd, planes, rowbuffer, pnm->width, pnm->height, bgr); break; case FMT_PGM_RAW: read_pgm_raw(fd, planes[0], pnm->width, pnm->height); break; case FMT_PBM_RAW: read_pbm_raw(fd, planes[0], pnm->width, pnm->height); break; case FMT_PAM: switch (pnm->tupl) { case TUPL_RGB: read_ppm_raw(fd, planes, rowbuffer, pnm->width, pnm->height, bgr); break; case TUPL_GRAY: read_pgm_raw(fd, planes[0], pnm->width, pnm->height); break; case TUPL_RGB_ALPHA: read_rgba_raw(fd, planes, rowbuffer, pnm->width, pnm->height, bgr); break; case TUPL_GRAY_ALPHA: case TUPL_BW: case TUPL_BW_ALPHA: case TUPL_UNKNOWN: mjpeg_error_exit1("Unknown/unhandled PAM tuple/format."); break; } break; case FMT_PBM_PLAIN: case FMT_PGM_PLAIN: case FMT_PPM_PLAIN: case FMT_UNKNOWN: mjpeg_error_exit1("Unknown/unhandled PNM format."); break; } } /* * Read one whole frame. * * If non-interleaved fields, this requires reading two PNM images. * */ static int read_pnm_frame(int fd, pnm_info_t *pnm, uint8_t *buffers[], uint8_t *buffers2[], int de_leaved, int bgr) { static uint8_t *rowbuffer = NULL; pnm_info_t new_pnm; int err; err = read_pnm_header(fd, &new_pnm); //&format, &width, &height); if (err > 0) return 1; /* EOF */ if (err < 0) return -1; /* error */ mjpeg_debug("Got PNM header: [%s%s%s] %dx%d", magics[new_pnm.format], (new_pnm.format == FMT_PAM) ? " " : "", (new_pnm.format == FMT_PAM) ? tupls[new_pnm.tupl].tag : "", new_pnm.width, new_pnm.height); if (pnm->width == 0) { /* first time */ mjpeg_debug("Initializing PNM read_frame"); pnm_info_copy(pnm, &new_pnm); rowbuffer = malloc(new_pnm.width * new_pnm.depth * sizeof(rowbuffer[0])); } else { /* make sure everything matches */ if ( !pnm_info_equal(pnm, &new_pnm) ) mjpeg_error_exit1("One of these frames is not like the others!"); } if (buffers[0] == NULL) alloc_buffers(buffers, new_pnm.width, new_pnm.height, new_pnm.depth); if ((buffers2[0] == NULL) && (de_leaved)) alloc_buffers(buffers2, new_pnm.width, new_pnm.height, new_pnm.depth); /* Interleaved or not --> read image into first buffer... */ read_pnm_data(fd, buffers, rowbuffer, pnm, bgr); if (de_leaved) { /* Really Non-Interleaved: --> read second field into second buffer */ err = read_pnm_header(fd, &new_pnm); //&format, &width, &height); if (err > 0) return 1; /* EOF */ if (err < 0) return -1; /* error */ mjpeg_debug("Got second PNM header: [%s] %dx%d", magics[new_pnm.format], new_pnm.width, new_pnm.height); /* make sure everything matches */ if ( !pnm_info_equal(pnm, &new_pnm) ) mjpeg_error_exit1("One of these fields is not like the others!"); read_pnm_data(fd, buffers2, rowbuffer, pnm, bgr); } return 0; } static void setup_output_stream(int fdout, cl_info_t *cl, y4m_stream_info_t *sinfo, pnm_info_t *pnm, int *field_height) { int err; int ss_mode = Y4M_UNKNOWN; if ( (cl->output_interlace != Y4M_ILACE_NONE) && (!cl->deinterleave) && ((pnm->height % 2) != 0) ) mjpeg_error_exit1("Frame height (%d) is not a multiple of 2!", pnm->height); y4m_si_set_width(sinfo, pnm->width); if (cl->deinterleave) y4m_si_set_height(sinfo, pnm->height * 2); else y4m_si_set_height(sinfo, pnm->height); y4m_si_set_sampleaspect(sinfo, cl->output_aspect); y4m_si_set_interlace(sinfo, cl->output_interlace); y4m_si_set_framerate(sinfo, cl->output_framerate); switch (pnm->format) { case FMT_PPM_RAW: case FMT_PPM_PLAIN: ss_mode = Y4M_CHROMA_444; break; case FMT_PGM_RAW: case FMT_PGM_PLAIN: case FMT_PBM_RAW: case FMT_PBM_PLAIN: ss_mode = Y4M_CHROMA_MONO; break; case FMT_PAM: switch (pnm->tupl) { case TUPL_RGB: ss_mode = Y4M_CHROMA_444; break; case TUPL_GRAY: ss_mode = Y4M_CHROMA_MONO; break; case TUPL_RGB_ALPHA: ss_mode = Y4M_CHROMA_444ALPHA; break; case TUPL_GRAY_ALPHA: case TUPL_BW: case TUPL_BW_ALPHA: case TUPL_UNKNOWN: assert(0); break; } break; case FMT_UNKNOWN: assert(0); break; } y4m_si_set_chroma(sinfo, ss_mode); if ((err = y4m_write_stream_header(fdout, sinfo)) != Y4M_OK) mjpeg_error_exit1("Write header failed: %s", y4m_strerr(err)); mjpeg_info("Output Stream parameters:"); y4m_log_stream_info(mjpeg_loglev_t("info"), " ", sinfo); } int main(int argc, char **argv) { cl_info_t cl; y4m_stream_info_t sinfo; y4m_frame_info_t finfo; uint8_t *planes[Y4M_MAX_NUM_PLANES]; /* R'G'B' or Y'CbCr */ uint8_t *planes2[Y4M_MAX_NUM_PLANES]; /* R'G'B' or Y'CbCr */ pnm_info_t pnm; int field_height; int fdout = fileno(stdout); int err, i, count, repeating_last; y4m_accept_extensions(1); y4m_init_stream_info(&sinfo); y4m_init_frame_info(&finfo); parse_args(&cl, argc, argv); pnm.width = 0; pnm.height = 0; for (i = 0; i < Y4M_MAX_NUM_PLANES; i++) { planes[i] = NULL; planes2[i] = NULL; } /* Read first PPM frame/field-pair, to get dimensions/format. */ if (read_pnm_frame(cl.fdin, &pnm, planes, planes2, cl.deinterleave, cl.bgr)) mjpeg_error_exit1("Failed to read first frame."); /* Setup streaminfo and write output header */ setup_output_stream(fdout, &cl, &sinfo, &pnm, &field_height); /* Loop 'framecount' times, or possibly forever... */ for (count = 0, repeating_last = 0; (count < (cl.offset + cl.framecount)) || (cl.framecount == 0); count++) { if (repeating_last) goto WRITE_FRAME; /* Read PPM frame/field */ /* ...but skip reading very first frame, already read prior to loop */ if (count > 0) { err = read_pnm_frame(cl.fdin, &pnm, planes, planes2, cl.deinterleave, cl.bgr); if (err == 1) { /* clean input EOF */ if (cl.repeatlast) { repeating_last = 1; goto WRITE_FRAME; } else if (cl.framecount != 0) { mjpeg_error_exit1("Input frame shortfall (only %d converted).", count - cl.offset); } else { break; /* input is exhausted; we are done! time to go home! */ } } else if (err) mjpeg_error_exit1("Error reading pnm frame"); } /* ...skip transforms if we are just going to skip this frame anyway. BUT, if 'cl.repeatlast' is on, we must process/buffer every frame, because we don't know when we will see the last one. */ if ((count >= cl.offset) || (cl.repeatlast)) { /* Transform colorspace. */ switch (pnm.format) { case FMT_PPM_PLAIN: case FMT_PPM_RAW: convert_RGB_to_YCbCr(planes, pnm.width * pnm.height); if (cl.deinterleave) convert_RGB_to_YCbCr(planes2, pnm.width * pnm.height); break; case FMT_PGM_PLAIN: case FMT_PGM_RAW: convert_Y255_to_Y219(planes[0], pnm.width * pnm.height); if (cl.deinterleave) convert_Y255_to_Y219(planes2[0], pnm.width * pnm.height); break; case FMT_PBM_PLAIN: case FMT_PBM_RAW: /* all set. (converted at read time) */ break; case FMT_PAM: switch (pnm.tupl) { case TUPL_RGB: convert_RGB_to_YCbCr(planes, pnm.width * pnm.height); if (cl.deinterleave) convert_RGB_to_YCbCr(planes2, pnm.width * pnm.height); break; case TUPL_GRAY: convert_Y255_to_Y219(planes[0], pnm.width * pnm.height); if (cl.deinterleave) convert_Y255_to_Y219(planes2[0], pnm.width * pnm.height); break; case TUPL_RGB_ALPHA: convert_RGB_to_YCbCr(planes, pnm.width * pnm.height); convert_Y255_to_Y219(planes[3], pnm.width * pnm.height); if (cl.deinterleave) { convert_RGB_to_YCbCr(planes2, pnm.width * pnm.height); convert_Y255_to_Y219(planes2[3], pnm.width * pnm.height); } break; case TUPL_GRAY_ALPHA: case TUPL_BW: case TUPL_BW_ALPHA: case TUPL_UNKNOWN: assert(0); break; } break; case FMT_UNKNOWN: assert(0); break; } } WRITE_FRAME: /* Write converted frame to output */ if (count >= cl.offset) { if (cl.deinterleave) { switch (cl.input_interlace) { case Y4M_ILACE_TOP_FIRST: err = y4m_write_fields(fdout, &sinfo, &finfo, planes, planes2); break; case Y4M_ILACE_BOTTOM_FIRST: err = y4m_write_fields(fdout, &sinfo, &finfo, planes2, planes); break; case Y4M_ILACE_NONE: default: assert(0); break; } } else { err = y4m_write_frame(fdout, &sinfo, &finfo, planes); } if (err != Y4M_OK) mjpeg_error_exit1("Write frame/fields failed: %s", y4m_strerr(err)); } } for (i = 0; i < Y4M_MAX_NUM_PLANES; i++) { if (planes[i] != NULL) free(planes[i]); if (planes2[i] != NULL) free(planes2[i]); } y4m_fini_stream_info(&sinfo); y4m_fini_frame_info(&finfo); mjpeg_debug("Done."); return 0; } #if 0 static void read_two_ppm_raw(int fd, uint8_t *buffers[], uint8_t *buffers2[], uint8_t *rowbuffer, int width, int height, int bgr) { int x, y; uint8_t *pixels; uint8_t *R = buffers[0]; uint8_t *G = buffers[1]; uint8_t *B = buffers[2]; uint8_t *R2 = buffers2[0]; uint8_t *G2 = buffers2[1]; uint8_t *B2 = buffers2[2]; mjpeg_debug("read into two buffers, %dx%d", width, height); height /= 2; for (y = 0; y < height; y++) { pixels = rowbuffer; if (y4m_read(fd, pixels, width * 3)) mjpeg_error_exit1("read error A y=%d", y); if (!bgr) { for (x = 0; x < width; x++) { *(R++) = *(pixels++); *(G++) = *(pixels++); *(B++) = *(pixels++); } } else { for (x = 0; x < width; x++) { *(B++) = *(pixels++); *(G++) = *(pixels++); *(R++) = *(pixels++); } } pixels = rowbuffer; if (y4m_read(fd, pixels, width * 3)) mjpeg_error_exit1("read error B y=%d", y); if (!bgr) { for (x = 0; x < width; x++) { *(R2++) = *(pixels++); *(G2++) = *(pixels++); *(B2++) = *(pixels++); } } else { for (x = 0; x < width; x++) { *(B2++) = *(pixels++); *(G2++) = *(pixels++); *(R2++) = *(pixels++); } } } } static void read_two_pgm_raw(int fd, uint8_t *buffer, uint8_t *buffer2, int width, int height) { int y; mjpeg_debug("read PGM into two buffers, %dx%d", width, height); for (y = 0; y < height; y += 2) { if (y4m_read(fd, buffer, width)) mjpeg_error_exit1("read error A y=%d", y); buffer += width; if (y4m_read(fd, buffer2, width)) mjpeg_error_exit1("read error B y=%d", y); buffer2 += width; } } static void read_pnm_into_two_buffers(int fd, uint8_t *planes[], uint8_t *planes2[], uint8_t *rowbuffer, pnm_info_t *pnm, int bgr) { switch (pnm->format) { case FMT_PPM_RAW: read_two_ppm_raw(fd, planes, planes2, rowbuffer, pnm->width, pnm->height, bgr); break; case FMT_PGM_RAW: read_two_pgm_raw(fd, planes[0], planes2[0], pnm->width, pnm->height); break; case FMT_PBM_RAW: // read_two_pbm_raw(fd, planes[0], planes2[0], pnm->width, pnm->height); break; case FMT_PBM_PLAIN: case FMT_PGM_PLAIN: case FMT_PPM_PLAIN: case FMT_UNKNOWN: assert(0); break; } } #endif mjpegtools-2.1.0/lavtools/Makefile.in0000644000175000017500000021006312217306407020125 0ustar glowwormglowworm# Makefile.in generated by automake 1.12.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Makefile for lavtools VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @HAVE_ALTIVEC_TRUE@am__append_1 = $(top_builddir)/mpeg2enc/libmpeg2encpp.la @HAVE_V4L_TRUE@am__append_2 = liblavrec.la @HAVE_V4L_OR_SDL_TRUE@am__append_3 = liblavplay.la @HAVE_SDL_TRUE@am__append_4 = ${X_LIBS} -lX11 bin_PROGRAMS = mjpeg_simd_helper$(EXEEXT) lav2wav$(EXEEXT) \ lav2yuv$(EXEEXT) lavaddwav$(EXEEXT) lavtrans$(EXEEXT) \ ypipe$(EXEEXT) yuv2lav$(EXEEXT) transist.flt$(EXEEXT) \ matteblend.flt$(EXEEXT) multiblend.flt$(EXEEXT) \ lavpipe$(EXEEXT) jpeg2yuv$(EXEEXT) ppmtoy4m$(EXEEXT) \ pnmtoy4m$(EXEEXT) y4mtoppm$(EXEEXT) y4mtopnm$(EXEEXT) \ y4mcolorbars$(EXEEXT) lavinfo$(EXEEXT) y4mstabilizer$(EXEEXT) \ yuvfps$(EXEEXT) yuvinactive$(EXEEXT) $(am__EXEEXT_1) \ $(am__EXEEXT_2) $(am__EXEEXT_3) $(am__EXEEXT_4) \ $(am__EXEEXT_5) @HAVE_GTK_TRUE@am__append_5 = glav @HAVE_SDL_TRUE@am__append_6 = yuvplay @HAVE_V4L_TRUE@am__append_7 = lavrec lavvideo @HAVE_V4L_OR_SDL_TRUE@am__append_8 = lavplay @HAVE_LIBPNG_TRUE@am__append_9 = png2yuv subdir = lavtools DIST_COMMON = $(liblavinclude_HEADERS) $(noinst_HEADERS) \ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(liblavincludedir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = liblavfile_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) $(LIBMJPEGUTILS) am_liblavfile_la_OBJECTS = liblavfile_la-editlist.lo \ liblavfile_la-lav_io.lo liblavfile_la-avilib.lo liblavfile_la_OBJECTS = $(am_liblavfile_la_OBJECTS) liblavfile_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(liblavfile_la_LDFLAGS) $(LDFLAGS) -o $@ liblavjpeg_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(LIBMJPEGUTILS) am_liblavjpeg_la_OBJECTS = liblavjpeg_la-jpegutils.lo liblavjpeg_la_OBJECTS = $(am_liblavjpeg_la_OBJECTS) liblavjpeg_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(liblavjpeg_la_LDFLAGS) $(LDFLAGS) -o $@ @HAVE_SDL_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) am_liblavplay_la_OBJECTS = liblavplay_la-liblavplay.lo \ liblavplay_la-audiolib.lo liblavplay_la_OBJECTS = $(am_liblavplay_la_OBJECTS) liblavplay_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(liblavplay_la_LDFLAGS) $(LDFLAGS) -o $@ @HAVE_V4L_OR_SDL_TRUE@am_liblavplay_la_rpath = -rpath $(libdir) am_liblavrec_la_OBJECTS = liblavrec_la-liblavrec.lo \ liblavrec_la-audiolib.lo liblavrec_la-frequencies.lo liblavrec_la_OBJECTS = $(am_liblavrec_la_OBJECTS) liblavrec_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(liblavrec_la_LDFLAGS) $(LDFLAGS) -o $@ @HAVE_V4L_TRUE@am_liblavrec_la_rpath = -rpath $(libdir) @HAVE_GTK_TRUE@am__EXEEXT_1 = glav$(EXEEXT) @HAVE_SDL_TRUE@am__EXEEXT_2 = yuvplay$(EXEEXT) @HAVE_V4L_TRUE@am__EXEEXT_3 = lavrec$(EXEEXT) lavvideo$(EXEEXT) @HAVE_V4L_OR_SDL_TRUE@am__EXEEXT_4 = lavplay$(EXEEXT) @HAVE_LIBPNG_TRUE@am__EXEEXT_5 = png2yuv$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) am_glav_OBJECTS = glav-glav.$(OBJEXT) glav-glav_main.$(OBJEXT) glav_OBJECTS = $(am_glav_OBJECTS) glav_DEPENDENCIES = $(LIBMJPEGUTILS) $(am__DEPENDENCIES_1) am_jpeg2yuv_OBJECTS = jpeg2yuv-jpeg2yuv.$(OBJEXT) jpeg2yuv_OBJECTS = $(am_jpeg2yuv_OBJECTS) jpeg2yuv_DEPENDENCIES = $(LIBMJPEGUTILS) liblavjpeg.la \ $(am__DEPENDENCIES_1) am_lav2wav_OBJECTS = lav2wav.$(OBJEXT) lav2wav_OBJECTS = $(am_lav2wav_OBJECTS) lav2wav_DEPENDENCIES = $(LIBMJPEGUTILS) liblavfile.la am_lav2yuv_OBJECTS = lav2yuv-lav2yuv.$(OBJEXT) \ lav2yuv-lav_common.$(OBJEXT) lav2yuv_OBJECTS = $(am_lav2yuv_OBJECTS) lav2yuv_DEPENDENCIES = $(LIBMJPEGUTILS) liblavfile.la liblavjpeg.la am_lavaddwav_OBJECTS = lavaddwav.$(OBJEXT) lavaddwav_OBJECTS = $(am_lavaddwav_OBJECTS) lavaddwav_DEPENDENCIES = $(LIBMJPEGUTILS) liblavfile.la am_lavinfo_OBJECTS = lavinfo.$(OBJEXT) lavinfo_OBJECTS = $(am_lavinfo_OBJECTS) lavinfo_DEPENDENCIES = $(LIBMJPEGUTILS) liblavfile.la am_lavpipe_OBJECTS = lavpipe.$(OBJEXT) pipelist.$(OBJEXT) lavpipe_OBJECTS = $(am_lavpipe_OBJECTS) lavpipe_DEPENDENCIES = $(LIBMJPEGUTILS) am_lavplay_OBJECTS = lavplay-lavplay.$(OBJEXT) lavplay_OBJECTS = $(am_lavplay_OBJECTS) lavplay_DEPENDENCIES = $(LIBMJPEGUTILS) liblavplay.la liblavjpeg.la \ liblavfile.la $(am__DEPENDENCIES_1) am_lavrec_OBJECTS = lavrec.$(OBJEXT) lavrec_OBJECTS = $(am_lavrec_OBJECTS) lavrec_DEPENDENCIES = $(LIBMJPEGUTILS) liblavrec.la liblavfile.la \ liblavjpeg.la am_lavtrans_OBJECTS = lavtrans.$(OBJEXT) lavtrans_OBJECTS = $(am_lavtrans_OBJECTS) lavtrans_DEPENDENCIES = $(LIBMJPEGUTILS) liblavfile.la am_lavvideo_OBJECTS = lavvideo.$(OBJEXT) frequencies.$(OBJEXT) lavvideo_OBJECTS = $(am_lavvideo_OBJECTS) lavvideo_LDADD = $(LDADD) am_matteblend_flt_OBJECTS = matteblend.flt.$(OBJEXT) matteblend_flt_OBJECTS = $(am_matteblend_flt_OBJECTS) matteblend_flt_DEPENDENCIES = $(LIBMJPEGUTILS) am_mjpeg_simd_helper_OBJECTS = mjpeg_simd_helper.$(OBJEXT) mjpeg_simd_helper_OBJECTS = $(am_mjpeg_simd_helper_OBJECTS) mjpeg_simd_helper_DEPENDENCIES = $(LIBMJPEGUTILS) am_multiblend_flt_OBJECTS = multiblend.flt.$(OBJEXT) multiblend_flt_OBJECTS = $(am_multiblend_flt_OBJECTS) multiblend_flt_DEPENDENCIES = $(LIBMJPEGUTILS) am_png2yuv_OBJECTS = png2yuv-png2yuv.$(OBJEXT) \ png2yuv-colorspace.$(OBJEXT) png2yuv-subsample.$(OBJEXT) png2yuv_OBJECTS = $(am_png2yuv_OBJECTS) png2yuv_DEPENDENCIES = $(LIBMJPEGUTILS) $(am__DEPENDENCIES_1) am_pnmtoy4m_OBJECTS = pnmtoy4m.$(OBJEXT) colorspace.$(OBJEXT) pnmtoy4m_OBJECTS = $(am_pnmtoy4m_OBJECTS) pnmtoy4m_DEPENDENCIES = $(LIBMJPEGUTILS) am_ppmtoy4m_OBJECTS = ppmtoy4m.$(OBJEXT) colorspace.$(OBJEXT) \ subsample.$(OBJEXT) ppmtoy4m_OBJECTS = $(am_ppmtoy4m_OBJECTS) ppmtoy4m_DEPENDENCIES = $(LIBMJPEGUTILS) am_transist_flt_OBJECTS = transist.flt.$(OBJEXT) transist_flt_OBJECTS = $(am_transist_flt_OBJECTS) transist_flt_DEPENDENCIES = $(LIBMJPEGUTILS) am_y4mcolorbars_OBJECTS = y4mcolorbars.$(OBJEXT) colorspace.$(OBJEXT) \ subsample.$(OBJEXT) y4mcolorbars_OBJECTS = $(am_y4mcolorbars_OBJECTS) y4mcolorbars_DEPENDENCIES = $(LIBMJPEGUTILS) am_y4mstabilizer_OBJECTS = y4mstabilizer.$(OBJEXT) subsample.$(OBJEXT) y4mstabilizer_OBJECTS = $(am_y4mstabilizer_OBJECTS) y4mstabilizer_DEPENDENCIES = $(LIBMJPEGUTILS) am_y4mtopnm_OBJECTS = y4mtopnm.$(OBJEXT) colorspace.$(OBJEXT) y4mtopnm_OBJECTS = $(am_y4mtopnm_OBJECTS) y4mtopnm_DEPENDENCIES = $(LIBMJPEGUTILS) am_y4mtoppm_OBJECTS = y4mtoppm.$(OBJEXT) colorspace.$(OBJEXT) \ subsample.$(OBJEXT) y4mtoppm_OBJECTS = $(am_y4mtoppm_OBJECTS) y4mtoppm_DEPENDENCIES = $(LIBMJPEGUTILS) am_ypipe_OBJECTS = ypipe.$(OBJEXT) ypipe_OBJECTS = $(am_ypipe_OBJECTS) ypipe_DEPENDENCIES = $(LIBMJPEGUTILS) am_yuv2lav_OBJECTS = yuv2lav.$(OBJEXT) yuv2lav_OBJECTS = $(am_yuv2lav_OBJECTS) yuv2lav_DEPENDENCIES = $(LIBMJPEGUTILS) liblavfile.la liblavjpeg.la \ $(am__DEPENDENCIES_1) am_yuvfps_OBJECTS = yuvfps.$(OBJEXT) yuvfps_OBJECTS = $(am_yuvfps_OBJECTS) yuvfps_DEPENDENCIES = $(LIBMJPEGUTILS) am_yuvinactive_OBJECTS = yuvinactive.$(OBJEXT) yuvinactive_OBJECTS = $(am_yuvinactive_OBJECTS) yuvinactive_DEPENDENCIES = $(LIBMJPEGUTILS) am_yuvplay_OBJECTS = yuvplay-yuvplay.$(OBJEXT) yuvplay_OBJECTS = $(am_yuvplay_OBJECTS) yuvplay_DEPENDENCIES = $(am__DEPENDENCIES_1) $(LIBMJPEGUTILS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(liblavfile_la_SOURCES) $(liblavjpeg_la_SOURCES) \ $(liblavplay_la_SOURCES) $(liblavrec_la_SOURCES) \ $(glav_SOURCES) $(jpeg2yuv_SOURCES) $(lav2wav_SOURCES) \ $(lav2yuv_SOURCES) $(lavaddwav_SOURCES) $(lavinfo_SOURCES) \ $(lavpipe_SOURCES) $(lavplay_SOURCES) $(lavrec_SOURCES) \ $(lavtrans_SOURCES) $(lavvideo_SOURCES) \ $(matteblend_flt_SOURCES) $(mjpeg_simd_helper_SOURCES) \ $(multiblend_flt_SOURCES) $(png2yuv_SOURCES) \ $(pnmtoy4m_SOURCES) $(ppmtoy4m_SOURCES) \ $(transist_flt_SOURCES) $(y4mcolorbars_SOURCES) \ $(y4mstabilizer_SOURCES) $(y4mtopnm_SOURCES) \ $(y4mtoppm_SOURCES) $(ypipe_SOURCES) $(yuv2lav_SOURCES) \ $(yuvfps_SOURCES) $(yuvinactive_SOURCES) $(yuvplay_SOURCES) DIST_SOURCES = $(liblavfile_la_SOURCES) $(liblavjpeg_la_SOURCES) \ $(liblavplay_la_SOURCES) $(liblavrec_la_SOURCES) \ $(glav_SOURCES) $(jpeg2yuv_SOURCES) $(lav2wav_SOURCES) \ $(lav2yuv_SOURCES) $(lavaddwav_SOURCES) $(lavinfo_SOURCES) \ $(lavpipe_SOURCES) $(lavplay_SOURCES) $(lavrec_SOURCES) \ $(lavtrans_SOURCES) $(lavvideo_SOURCES) \ $(matteblend_flt_SOURCES) $(mjpeg_simd_helper_SOURCES) \ $(multiblend_flt_SOURCES) $(png2yuv_SOURCES) \ $(pnmtoy4m_SOURCES) $(ppmtoy4m_SOURCES) \ $(transist_flt_SOURCES) $(y4mcolorbars_SOURCES) \ $(y4mstabilizer_SOURCES) $(y4mtopnm_SOURCES) \ $(y4mtoppm_SOURCES) $(ypipe_SOURCES) $(yuv2lav_SOURCES) \ $(yuvfps_SOURCES) $(yuvinactive_SOURCES) $(yuvplay_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(liblavinclude_HEADERS) $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALTIVEC_EXTRA_LIBS = @ALTIVEC_EXTRA_LIBS@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDV_CFLAGS = @LIBDV_CFLAGS@ LIBDV_LIBS = @LIBDV_LIBS@ LIBGETOPT_LIB = @LIBGETOPT_LIB@ LIBM_LIBS = @LIBM_LIBS@ LIBOBJS = @LIBOBJS@ LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ LIBPNG_LIBS = @LIBPNG_LIBS@ LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@ LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ LT_STATIC = @LT_STATIC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROGRAM_NOPIC = @PROGRAM_NOPIC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ SDLgfx_LIBS = @SDLgfx_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ V4LCONF_LIBS = @V4LCONF_LIBS@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAINTAINERCLEANFILES = Makefile.in AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/utils $(LIBQUICKTIME_CFLAGS) LIBMJPEGUTILS = $(top_builddir)/utils/libmjpegutils.la $(am__append_1) # ********************************************************************* # Support lib lib_LTLIBRARIES = liblavfile.la liblavjpeg.la $(am__append_2) \ $(am__append_3) liblavincludedir = $(pkgincludedir) liblavinclude_HEADERS = \ avilib.h \ editlist.h \ lav_io.h \ jpegutils.h \ frequencies.h \ liblavrec.h \ liblavplay.h \ audiolib.h LAV_ALL_LIB_OPTS = \ $(LT_STATIC) \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -release $(LT_RELEASE) $(EXTRA_LDFLAGS) liblavfile_la_SOURCES = editlist.c lav_io.c avilib.c liblavfile_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBDV_CFLAGS) $(JPEG_CFLAGS) liblavfile_la_LDFLAGS = $(LAV_ALL_LIB_OPTS) liblavfile_la_LIBADD = $(LIBQUICKTIME_LIBS) $(JPEG_LIBS) $(LIBDV_LIBS) $(LIBMJPEGUTILS) liblavjpeg_la_SOURCES = jpegutils.c liblavjpeg_la_CPPFLAGS = $(AM_CPPFLAGS) $(JPEG_CFLAGS) liblavjpeg_la_LDFLAGS = $(LAV_ALL_LIB_OPTS) liblavjpeg_la_LIBADD = $(JPEG_LIBS) $(LIBMJPEGUTILS) liblavrec_la_SOURCES = liblavrec.c audiolib.c frequencies.c liblavrec_la_CPPFLAGS = $(AM_CPPFLAGS) # so automake doesn't complain about audiolib & frequencies liblavrec_la_LDFLAGS = $(LAV_ALL_LIB_OPTS) liblavrec_la_LIBADD = liblavfile.la liblavjpeg.la $(LIBMJPEGUTILS) liblavrec_la_DEPENDENCIES = liblavfile.la liblavjpeg.la liblavplay_la_SOURCES = liblavplay.c audiolib.c liblavplay_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBDV_CFLAGS) $(X_CFLAGS) $(SDL_CFLAGS) liblavplay_la_LDFLAGS = $(LAV_ALL_LIB_OPTS) liblavplay_la_LIBADD = liblavfile.la $(SDL_LIBS) liblavjpeg.la \ $(LIBDV_LIBS) $(LIBMJPEGUTILS) $(am__append_4) liblavplay_la_DEPENDENCIES = liblavfile.la liblavjpeg.la noinst_HEADERS = \ colorspace.h \ glav.h \ pipelist.h \ subsample.h \ lav_common.h mjpeg_simd_helper_SOURCES = mjpeg_simd_helper.c mjpeg_simd_helper_LDADD = $(LIBMJPEGUTILS) ypipe_SOURCES = ypipe.c ypipe_LDADD = $(LIBMJPEGUTILS) yuv2lav_SOURCES = yuv2lav.c yuv2lav_LDADD = $(LIBMJPEGUTILS) liblavfile.la liblavjpeg.la $(LIBM_LIBS) transist_flt_SOURCES = transist.flt.c transist_flt_LDADD = $(LIBMJPEGUTILS) matteblend_flt_SOURCES = matteblend.flt.c matteblend_flt_LDADD = $(LIBMJPEGUTILS) multiblend_flt_SOURCES = multiblend.flt.c multiblend_flt_LDADD = $(LIBMJPEGUTILS) lavplay_SOURCES = lavplay.c lavplay_CPPFLAGS = $(AM_CPPFLAGS) $(SDL_CFLAGS) lavplay_LDADD = $(LIBMJPEGUTILS) \ liblavplay.la liblavjpeg.la liblavfile.la \ @LIBGETOPT_LIB@ @PTHREAD_LIBS@ $(SDL_LIBS) lavrec_SOURCES = lavrec.c lavrec_LDADD = $(LIBMJPEGUTILS) \ liblavrec.la liblavfile.la liblavjpeg.la \ @LIBGETOPT_LIB@ @PTHREAD_LIBS@ lav2yuv_SOURCES = lav2yuv.c lav_common.c lav2yuv_CPPFLAGS = $(AM_CPPFLAGS) $(LIBDV_CFLAGS) lav2yuv_LDADD = $(LIBMJPEGUTILS) \ liblavfile.la liblavjpeg.la jpeg2yuv_SOURCES = jpeg2yuv.c jpeg2yuv_CPPFLAGS = $(AM_CPPFLAGS) $(JPEG_CFLAGS) jpeg2yuv_LDADD = $(LIBMJPEGUTILS) liblavjpeg.la $(JPEG_LIBS) png2yuv_SOURCES = png2yuv.c colorspace.c subsample.c png2yuv_CPPFLAGS = $(AM_CPPFLAGS) $(LIBPNG_CFLAGS) png2yuv_LDADD = $(LIBMJPEGUTILS) $(LIBPNG_LIBS) -lz -lm lavpipe_SOURCES = lavpipe.c pipelist.c lavpipe_LDADD = $(LIBMJPEGUTILS) lav2wav_SOURCES = lav2wav.c lav2wav_LDADD = $(LIBMJPEGUTILS) liblavfile.la lavtrans_SOURCES = lavtrans.c lavtrans_LDADD = $(LIBMJPEGUTILS) liblavfile.la lavaddwav_SOURCES = lavaddwav.c lavaddwav_LDADD = $(LIBMJPEGUTILS) liblavfile.la glav_SOURCES = glav.c glav_main.c glav_CPPFLAGS = $(AM_CPPFLAGS) ${GTK_CFLAGS} -DG_LOG_DOMAIN=\"lavtools\" glav_LDADD = $(LIBMJPEGUTILS) ${GTK_LIBS} lavvideo_SOURCES = lavvideo.c frequencies.c yuvplay_SOURCES = yuvplay.c yuvplay_CPPFLAGS = $(AM_CPPFLAGS) $(SDL_CFLAGS) yuvplay_LDADD = $(SDL_LIBS) $(LIBMJPEGUTILS) ppmtoy4m_SOURCES = ppmtoy4m.c colorspace.c subsample.c ppmtoy4m_LDADD = $(LIBMJPEGUTILS) pnmtoy4m_SOURCES = pnmtoy4m.c colorspace.c pnmtoy4m_LDADD = $(LIBMJPEGUTILS) y4mtoppm_SOURCES = y4mtoppm.c colorspace.c subsample.c y4mtoppm_LDADD = $(LIBMJPEGUTILS) y4mtopnm_SOURCES = y4mtopnm.c colorspace.c y4mtopnm_LDADD = $(LIBMJPEGUTILS) y4mcolorbars_SOURCES = y4mcolorbars.c colorspace.c subsample.c y4mcolorbars_LDADD = $(LIBMJPEGUTILS) lavinfo_SOURCES = lavinfo.c lavinfo_LDADD = $(LIBMJPEGUTILS) liblavfile.la y4mstabilizer_SOURCES = y4mstabilizer.c subsample.c y4mstabilizer_LDADD = $(LIBMJPEGUTILS) yuvfps_SOURCES = yuvfps.c yuvfps_LDADD = $(LIBMJPEGUTILS) yuvinactive_SOURCES = yuvinactive.c yuvinactive_LDADD = $(LIBMJPEGUTILS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lavtools/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu lavtools/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } liblavfile.la: $(liblavfile_la_OBJECTS) $(liblavfile_la_DEPENDENCIES) $(EXTRA_liblavfile_la_DEPENDENCIES) $(liblavfile_la_LINK) -rpath $(libdir) $(liblavfile_la_OBJECTS) $(liblavfile_la_LIBADD) $(LIBS) liblavjpeg.la: $(liblavjpeg_la_OBJECTS) $(liblavjpeg_la_DEPENDENCIES) $(EXTRA_liblavjpeg_la_DEPENDENCIES) $(liblavjpeg_la_LINK) -rpath $(libdir) $(liblavjpeg_la_OBJECTS) $(liblavjpeg_la_LIBADD) $(LIBS) liblavplay.la: $(liblavplay_la_OBJECTS) $(liblavplay_la_DEPENDENCIES) $(EXTRA_liblavplay_la_DEPENDENCIES) $(liblavplay_la_LINK) $(am_liblavplay_la_rpath) $(liblavplay_la_OBJECTS) $(liblavplay_la_LIBADD) $(LIBS) liblavrec.la: $(liblavrec_la_OBJECTS) $(liblavrec_la_DEPENDENCIES) $(EXTRA_liblavrec_la_DEPENDENCIES) $(liblavrec_la_LINK) $(am_liblavrec_la_rpath) $(liblavrec_la_OBJECTS) $(liblavrec_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list glav$(EXEEXT): $(glav_OBJECTS) $(glav_DEPENDENCIES) $(EXTRA_glav_DEPENDENCIES) @rm -f glav$(EXEEXT) $(LINK) $(glav_OBJECTS) $(glav_LDADD) $(LIBS) jpeg2yuv$(EXEEXT): $(jpeg2yuv_OBJECTS) $(jpeg2yuv_DEPENDENCIES) $(EXTRA_jpeg2yuv_DEPENDENCIES) @rm -f jpeg2yuv$(EXEEXT) $(LINK) $(jpeg2yuv_OBJECTS) $(jpeg2yuv_LDADD) $(LIBS) lav2wav$(EXEEXT): $(lav2wav_OBJECTS) $(lav2wav_DEPENDENCIES) $(EXTRA_lav2wav_DEPENDENCIES) @rm -f lav2wav$(EXEEXT) $(LINK) $(lav2wav_OBJECTS) $(lav2wav_LDADD) $(LIBS) lav2yuv$(EXEEXT): $(lav2yuv_OBJECTS) $(lav2yuv_DEPENDENCIES) $(EXTRA_lav2yuv_DEPENDENCIES) @rm -f lav2yuv$(EXEEXT) $(LINK) $(lav2yuv_OBJECTS) $(lav2yuv_LDADD) $(LIBS) lavaddwav$(EXEEXT): $(lavaddwav_OBJECTS) $(lavaddwav_DEPENDENCIES) $(EXTRA_lavaddwav_DEPENDENCIES) @rm -f lavaddwav$(EXEEXT) $(LINK) $(lavaddwav_OBJECTS) $(lavaddwav_LDADD) $(LIBS) lavinfo$(EXEEXT): $(lavinfo_OBJECTS) $(lavinfo_DEPENDENCIES) $(EXTRA_lavinfo_DEPENDENCIES) @rm -f lavinfo$(EXEEXT) $(LINK) $(lavinfo_OBJECTS) $(lavinfo_LDADD) $(LIBS) lavpipe$(EXEEXT): $(lavpipe_OBJECTS) $(lavpipe_DEPENDENCIES) $(EXTRA_lavpipe_DEPENDENCIES) @rm -f lavpipe$(EXEEXT) $(LINK) $(lavpipe_OBJECTS) $(lavpipe_LDADD) $(LIBS) lavplay$(EXEEXT): $(lavplay_OBJECTS) $(lavplay_DEPENDENCIES) $(EXTRA_lavplay_DEPENDENCIES) @rm -f lavplay$(EXEEXT) $(LINK) $(lavplay_OBJECTS) $(lavplay_LDADD) $(LIBS) lavrec$(EXEEXT): $(lavrec_OBJECTS) $(lavrec_DEPENDENCIES) $(EXTRA_lavrec_DEPENDENCIES) @rm -f lavrec$(EXEEXT) $(LINK) $(lavrec_OBJECTS) $(lavrec_LDADD) $(LIBS) lavtrans$(EXEEXT): $(lavtrans_OBJECTS) $(lavtrans_DEPENDENCIES) $(EXTRA_lavtrans_DEPENDENCIES) @rm -f lavtrans$(EXEEXT) $(LINK) $(lavtrans_OBJECTS) $(lavtrans_LDADD) $(LIBS) lavvideo$(EXEEXT): $(lavvideo_OBJECTS) $(lavvideo_DEPENDENCIES) $(EXTRA_lavvideo_DEPENDENCIES) @rm -f lavvideo$(EXEEXT) $(LINK) $(lavvideo_OBJECTS) $(lavvideo_LDADD) $(LIBS) matteblend.flt$(EXEEXT): $(matteblend_flt_OBJECTS) $(matteblend_flt_DEPENDENCIES) $(EXTRA_matteblend_flt_DEPENDENCIES) @rm -f matteblend.flt$(EXEEXT) $(LINK) $(matteblend_flt_OBJECTS) $(matteblend_flt_LDADD) $(LIBS) mjpeg_simd_helper$(EXEEXT): $(mjpeg_simd_helper_OBJECTS) $(mjpeg_simd_helper_DEPENDENCIES) $(EXTRA_mjpeg_simd_helper_DEPENDENCIES) @rm -f mjpeg_simd_helper$(EXEEXT) $(LINK) $(mjpeg_simd_helper_OBJECTS) $(mjpeg_simd_helper_LDADD) $(LIBS) multiblend.flt$(EXEEXT): $(multiblend_flt_OBJECTS) $(multiblend_flt_DEPENDENCIES) $(EXTRA_multiblend_flt_DEPENDENCIES) @rm -f multiblend.flt$(EXEEXT) $(LINK) $(multiblend_flt_OBJECTS) $(multiblend_flt_LDADD) $(LIBS) png2yuv$(EXEEXT): $(png2yuv_OBJECTS) $(png2yuv_DEPENDENCIES) $(EXTRA_png2yuv_DEPENDENCIES) @rm -f png2yuv$(EXEEXT) $(LINK) $(png2yuv_OBJECTS) $(png2yuv_LDADD) $(LIBS) pnmtoy4m$(EXEEXT): $(pnmtoy4m_OBJECTS) $(pnmtoy4m_DEPENDENCIES) $(EXTRA_pnmtoy4m_DEPENDENCIES) @rm -f pnmtoy4m$(EXEEXT) $(LINK) $(pnmtoy4m_OBJECTS) $(pnmtoy4m_LDADD) $(LIBS) ppmtoy4m$(EXEEXT): $(ppmtoy4m_OBJECTS) $(ppmtoy4m_DEPENDENCIES) $(EXTRA_ppmtoy4m_DEPENDENCIES) @rm -f ppmtoy4m$(EXEEXT) $(LINK) $(ppmtoy4m_OBJECTS) $(ppmtoy4m_LDADD) $(LIBS) transist.flt$(EXEEXT): $(transist_flt_OBJECTS) $(transist_flt_DEPENDENCIES) $(EXTRA_transist_flt_DEPENDENCIES) @rm -f transist.flt$(EXEEXT) $(LINK) $(transist_flt_OBJECTS) $(transist_flt_LDADD) $(LIBS) y4mcolorbars$(EXEEXT): $(y4mcolorbars_OBJECTS) $(y4mcolorbars_DEPENDENCIES) $(EXTRA_y4mcolorbars_DEPENDENCIES) @rm -f y4mcolorbars$(EXEEXT) $(LINK) $(y4mcolorbars_OBJECTS) $(y4mcolorbars_LDADD) $(LIBS) y4mstabilizer$(EXEEXT): $(y4mstabilizer_OBJECTS) $(y4mstabilizer_DEPENDENCIES) $(EXTRA_y4mstabilizer_DEPENDENCIES) @rm -f y4mstabilizer$(EXEEXT) $(LINK) $(y4mstabilizer_OBJECTS) $(y4mstabilizer_LDADD) $(LIBS) y4mtopnm$(EXEEXT): $(y4mtopnm_OBJECTS) $(y4mtopnm_DEPENDENCIES) $(EXTRA_y4mtopnm_DEPENDENCIES) @rm -f y4mtopnm$(EXEEXT) $(LINK) $(y4mtopnm_OBJECTS) $(y4mtopnm_LDADD) $(LIBS) y4mtoppm$(EXEEXT): $(y4mtoppm_OBJECTS) $(y4mtoppm_DEPENDENCIES) $(EXTRA_y4mtoppm_DEPENDENCIES) @rm -f y4mtoppm$(EXEEXT) $(LINK) $(y4mtoppm_OBJECTS) $(y4mtoppm_LDADD) $(LIBS) ypipe$(EXEEXT): $(ypipe_OBJECTS) $(ypipe_DEPENDENCIES) $(EXTRA_ypipe_DEPENDENCIES) @rm -f ypipe$(EXEEXT) $(LINK) $(ypipe_OBJECTS) $(ypipe_LDADD) $(LIBS) yuv2lav$(EXEEXT): $(yuv2lav_OBJECTS) $(yuv2lav_DEPENDENCIES) $(EXTRA_yuv2lav_DEPENDENCIES) @rm -f yuv2lav$(EXEEXT) $(LINK) $(yuv2lav_OBJECTS) $(yuv2lav_LDADD) $(LIBS) yuvfps$(EXEEXT): $(yuvfps_OBJECTS) $(yuvfps_DEPENDENCIES) $(EXTRA_yuvfps_DEPENDENCIES) @rm -f yuvfps$(EXEEXT) $(LINK) $(yuvfps_OBJECTS) $(yuvfps_LDADD) $(LIBS) yuvinactive$(EXEEXT): $(yuvinactive_OBJECTS) $(yuvinactive_DEPENDENCIES) $(EXTRA_yuvinactive_DEPENDENCIES) @rm -f yuvinactive$(EXEEXT) $(LINK) $(yuvinactive_OBJECTS) $(yuvinactive_LDADD) $(LIBS) yuvplay$(EXEEXT): $(yuvplay_OBJECTS) $(yuvplay_DEPENDENCIES) $(EXTRA_yuvplay_DEPENDENCIES) @rm -f yuvplay$(EXEEXT) $(LINK) $(yuvplay_OBJECTS) $(yuvplay_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/colorspace.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/frequencies.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glav-glav.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glav-glav_main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jpeg2yuv-jpeg2yuv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lav2wav.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lav2yuv-lav2yuv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lav2yuv-lav_common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lavaddwav.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lavinfo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lavpipe.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lavplay-lavplay.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lavrec.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lavtrans.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lavvideo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblavfile_la-avilib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblavfile_la-editlist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblavfile_la-lav_io.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblavjpeg_la-jpegutils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblavplay_la-audiolib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblavplay_la-liblavplay.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblavrec_la-audiolib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblavrec_la-frequencies.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblavrec_la-liblavrec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/matteblend.flt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mjpeg_simd_helper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multiblend.flt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pipelist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/png2yuv-colorspace.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/png2yuv-png2yuv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/png2yuv-subsample.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pnmtoy4m.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ppmtoy4m.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subsample.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transist.flt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/y4mcolorbars.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/y4mstabilizer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/y4mtopnm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/y4mtoppm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ypipe.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuv2lav.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuvfps.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuvinactive.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuvplay-yuvplay.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< liblavfile_la-editlist.lo: editlist.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblavfile_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT liblavfile_la-editlist.lo -MD -MP -MF $(DEPDIR)/liblavfile_la-editlist.Tpo -c -o liblavfile_la-editlist.lo `test -f 'editlist.c' || echo '$(srcdir)/'`editlist.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liblavfile_la-editlist.Tpo $(DEPDIR)/liblavfile_la-editlist.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='editlist.c' object='liblavfile_la-editlist.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblavfile_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o liblavfile_la-editlist.lo `test -f 'editlist.c' || echo '$(srcdir)/'`editlist.c liblavfile_la-lav_io.lo: lav_io.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblavfile_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT liblavfile_la-lav_io.lo -MD -MP -MF $(DEPDIR)/liblavfile_la-lav_io.Tpo -c -o liblavfile_la-lav_io.lo `test -f 'lav_io.c' || echo '$(srcdir)/'`lav_io.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liblavfile_la-lav_io.Tpo $(DEPDIR)/liblavfile_la-lav_io.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='lav_io.c' object='liblavfile_la-lav_io.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblavfile_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o liblavfile_la-lav_io.lo `test -f 'lav_io.c' || echo '$(srcdir)/'`lav_io.c liblavfile_la-avilib.lo: avilib.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblavfile_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT liblavfile_la-avilib.lo -MD -MP -MF $(DEPDIR)/liblavfile_la-avilib.Tpo -c -o liblavfile_la-avilib.lo `test -f 'avilib.c' || echo '$(srcdir)/'`avilib.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liblavfile_la-avilib.Tpo $(DEPDIR)/liblavfile_la-avilib.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='avilib.c' object='liblavfile_la-avilib.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblavfile_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o liblavfile_la-avilib.lo `test -f 'avilib.c' || echo '$(srcdir)/'`avilib.c liblavjpeg_la-jpegutils.lo: jpegutils.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblavjpeg_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT liblavjpeg_la-jpegutils.lo -MD -MP -MF $(DEPDIR)/liblavjpeg_la-jpegutils.Tpo -c -o liblavjpeg_la-jpegutils.lo `test -f 'jpegutils.c' || echo '$(srcdir)/'`jpegutils.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liblavjpeg_la-jpegutils.Tpo $(DEPDIR)/liblavjpeg_la-jpegutils.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='jpegutils.c' object='liblavjpeg_la-jpegutils.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblavjpeg_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o liblavjpeg_la-jpegutils.lo `test -f 'jpegutils.c' || echo '$(srcdir)/'`jpegutils.c liblavplay_la-liblavplay.lo: liblavplay.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblavplay_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT liblavplay_la-liblavplay.lo -MD -MP -MF $(DEPDIR)/liblavplay_la-liblavplay.Tpo -c -o liblavplay_la-liblavplay.lo `test -f 'liblavplay.c' || echo '$(srcdir)/'`liblavplay.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liblavplay_la-liblavplay.Tpo $(DEPDIR)/liblavplay_la-liblavplay.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='liblavplay.c' object='liblavplay_la-liblavplay.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblavplay_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o liblavplay_la-liblavplay.lo `test -f 'liblavplay.c' || echo '$(srcdir)/'`liblavplay.c liblavplay_la-audiolib.lo: audiolib.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblavplay_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT liblavplay_la-audiolib.lo -MD -MP -MF $(DEPDIR)/liblavplay_la-audiolib.Tpo -c -o liblavplay_la-audiolib.lo `test -f 'audiolib.c' || echo '$(srcdir)/'`audiolib.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liblavplay_la-audiolib.Tpo $(DEPDIR)/liblavplay_la-audiolib.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='audiolib.c' object='liblavplay_la-audiolib.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblavplay_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o liblavplay_la-audiolib.lo `test -f 'audiolib.c' || echo '$(srcdir)/'`audiolib.c liblavrec_la-liblavrec.lo: liblavrec.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblavrec_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT liblavrec_la-liblavrec.lo -MD -MP -MF $(DEPDIR)/liblavrec_la-liblavrec.Tpo -c -o liblavrec_la-liblavrec.lo `test -f 'liblavrec.c' || echo '$(srcdir)/'`liblavrec.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liblavrec_la-liblavrec.Tpo $(DEPDIR)/liblavrec_la-liblavrec.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='liblavrec.c' object='liblavrec_la-liblavrec.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblavrec_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o liblavrec_la-liblavrec.lo `test -f 'liblavrec.c' || echo '$(srcdir)/'`liblavrec.c liblavrec_la-audiolib.lo: audiolib.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblavrec_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT liblavrec_la-audiolib.lo -MD -MP -MF $(DEPDIR)/liblavrec_la-audiolib.Tpo -c -o liblavrec_la-audiolib.lo `test -f 'audiolib.c' || echo '$(srcdir)/'`audiolib.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liblavrec_la-audiolib.Tpo $(DEPDIR)/liblavrec_la-audiolib.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='audiolib.c' object='liblavrec_la-audiolib.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblavrec_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o liblavrec_la-audiolib.lo `test -f 'audiolib.c' || echo '$(srcdir)/'`audiolib.c liblavrec_la-frequencies.lo: frequencies.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblavrec_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT liblavrec_la-frequencies.lo -MD -MP -MF $(DEPDIR)/liblavrec_la-frequencies.Tpo -c -o liblavrec_la-frequencies.lo `test -f 'frequencies.c' || echo '$(srcdir)/'`frequencies.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liblavrec_la-frequencies.Tpo $(DEPDIR)/liblavrec_la-frequencies.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='frequencies.c' object='liblavrec_la-frequencies.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblavrec_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o liblavrec_la-frequencies.lo `test -f 'frequencies.c' || echo '$(srcdir)/'`frequencies.c glav-glav.o: glav.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(glav_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT glav-glav.o -MD -MP -MF $(DEPDIR)/glav-glav.Tpo -c -o glav-glav.o `test -f 'glav.c' || echo '$(srcdir)/'`glav.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/glav-glav.Tpo $(DEPDIR)/glav-glav.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glav.c' object='glav-glav.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(glav_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o glav-glav.o `test -f 'glav.c' || echo '$(srcdir)/'`glav.c glav-glav.obj: glav.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(glav_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT glav-glav.obj -MD -MP -MF $(DEPDIR)/glav-glav.Tpo -c -o glav-glav.obj `if test -f 'glav.c'; then $(CYGPATH_W) 'glav.c'; else $(CYGPATH_W) '$(srcdir)/glav.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/glav-glav.Tpo $(DEPDIR)/glav-glav.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glav.c' object='glav-glav.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(glav_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o glav-glav.obj `if test -f 'glav.c'; then $(CYGPATH_W) 'glav.c'; else $(CYGPATH_W) '$(srcdir)/glav.c'; fi` glav-glav_main.o: glav_main.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(glav_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT glav-glav_main.o -MD -MP -MF $(DEPDIR)/glav-glav_main.Tpo -c -o glav-glav_main.o `test -f 'glav_main.c' || echo '$(srcdir)/'`glav_main.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/glav-glav_main.Tpo $(DEPDIR)/glav-glav_main.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glav_main.c' object='glav-glav_main.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(glav_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o glav-glav_main.o `test -f 'glav_main.c' || echo '$(srcdir)/'`glav_main.c glav-glav_main.obj: glav_main.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(glav_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT glav-glav_main.obj -MD -MP -MF $(DEPDIR)/glav-glav_main.Tpo -c -o glav-glav_main.obj `if test -f 'glav_main.c'; then $(CYGPATH_W) 'glav_main.c'; else $(CYGPATH_W) '$(srcdir)/glav_main.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/glav-glav_main.Tpo $(DEPDIR)/glav-glav_main.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glav_main.c' object='glav-glav_main.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(glav_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o glav-glav_main.obj `if test -f 'glav_main.c'; then $(CYGPATH_W) 'glav_main.c'; else $(CYGPATH_W) '$(srcdir)/glav_main.c'; fi` jpeg2yuv-jpeg2yuv.o: jpeg2yuv.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(jpeg2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT jpeg2yuv-jpeg2yuv.o -MD -MP -MF $(DEPDIR)/jpeg2yuv-jpeg2yuv.Tpo -c -o jpeg2yuv-jpeg2yuv.o `test -f 'jpeg2yuv.c' || echo '$(srcdir)/'`jpeg2yuv.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/jpeg2yuv-jpeg2yuv.Tpo $(DEPDIR)/jpeg2yuv-jpeg2yuv.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='jpeg2yuv.c' object='jpeg2yuv-jpeg2yuv.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(jpeg2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o jpeg2yuv-jpeg2yuv.o `test -f 'jpeg2yuv.c' || echo '$(srcdir)/'`jpeg2yuv.c jpeg2yuv-jpeg2yuv.obj: jpeg2yuv.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(jpeg2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT jpeg2yuv-jpeg2yuv.obj -MD -MP -MF $(DEPDIR)/jpeg2yuv-jpeg2yuv.Tpo -c -o jpeg2yuv-jpeg2yuv.obj `if test -f 'jpeg2yuv.c'; then $(CYGPATH_W) 'jpeg2yuv.c'; else $(CYGPATH_W) '$(srcdir)/jpeg2yuv.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/jpeg2yuv-jpeg2yuv.Tpo $(DEPDIR)/jpeg2yuv-jpeg2yuv.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='jpeg2yuv.c' object='jpeg2yuv-jpeg2yuv.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(jpeg2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o jpeg2yuv-jpeg2yuv.obj `if test -f 'jpeg2yuv.c'; then $(CYGPATH_W) 'jpeg2yuv.c'; else $(CYGPATH_W) '$(srcdir)/jpeg2yuv.c'; fi` lav2yuv-lav2yuv.o: lav2yuv.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lav2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lav2yuv-lav2yuv.o -MD -MP -MF $(DEPDIR)/lav2yuv-lav2yuv.Tpo -c -o lav2yuv-lav2yuv.o `test -f 'lav2yuv.c' || echo '$(srcdir)/'`lav2yuv.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lav2yuv-lav2yuv.Tpo $(DEPDIR)/lav2yuv-lav2yuv.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='lav2yuv.c' object='lav2yuv-lav2yuv.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lav2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lav2yuv-lav2yuv.o `test -f 'lav2yuv.c' || echo '$(srcdir)/'`lav2yuv.c lav2yuv-lav2yuv.obj: lav2yuv.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lav2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lav2yuv-lav2yuv.obj -MD -MP -MF $(DEPDIR)/lav2yuv-lav2yuv.Tpo -c -o lav2yuv-lav2yuv.obj `if test -f 'lav2yuv.c'; then $(CYGPATH_W) 'lav2yuv.c'; else $(CYGPATH_W) '$(srcdir)/lav2yuv.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lav2yuv-lav2yuv.Tpo $(DEPDIR)/lav2yuv-lav2yuv.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='lav2yuv.c' object='lav2yuv-lav2yuv.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lav2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lav2yuv-lav2yuv.obj `if test -f 'lav2yuv.c'; then $(CYGPATH_W) 'lav2yuv.c'; else $(CYGPATH_W) '$(srcdir)/lav2yuv.c'; fi` lav2yuv-lav_common.o: lav_common.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lav2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lav2yuv-lav_common.o -MD -MP -MF $(DEPDIR)/lav2yuv-lav_common.Tpo -c -o lav2yuv-lav_common.o `test -f 'lav_common.c' || echo '$(srcdir)/'`lav_common.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lav2yuv-lav_common.Tpo $(DEPDIR)/lav2yuv-lav_common.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='lav_common.c' object='lav2yuv-lav_common.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lav2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lav2yuv-lav_common.o `test -f 'lav_common.c' || echo '$(srcdir)/'`lav_common.c lav2yuv-lav_common.obj: lav_common.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lav2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lav2yuv-lav_common.obj -MD -MP -MF $(DEPDIR)/lav2yuv-lav_common.Tpo -c -o lav2yuv-lav_common.obj `if test -f 'lav_common.c'; then $(CYGPATH_W) 'lav_common.c'; else $(CYGPATH_W) '$(srcdir)/lav_common.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lav2yuv-lav_common.Tpo $(DEPDIR)/lav2yuv-lav_common.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='lav_common.c' object='lav2yuv-lav_common.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lav2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lav2yuv-lav_common.obj `if test -f 'lav_common.c'; then $(CYGPATH_W) 'lav_common.c'; else $(CYGPATH_W) '$(srcdir)/lav_common.c'; fi` lavplay-lavplay.o: lavplay.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lavplay_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lavplay-lavplay.o -MD -MP -MF $(DEPDIR)/lavplay-lavplay.Tpo -c -o lavplay-lavplay.o `test -f 'lavplay.c' || echo '$(srcdir)/'`lavplay.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lavplay-lavplay.Tpo $(DEPDIR)/lavplay-lavplay.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='lavplay.c' object='lavplay-lavplay.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lavplay_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lavplay-lavplay.o `test -f 'lavplay.c' || echo '$(srcdir)/'`lavplay.c lavplay-lavplay.obj: lavplay.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lavplay_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lavplay-lavplay.obj -MD -MP -MF $(DEPDIR)/lavplay-lavplay.Tpo -c -o lavplay-lavplay.obj `if test -f 'lavplay.c'; then $(CYGPATH_W) 'lavplay.c'; else $(CYGPATH_W) '$(srcdir)/lavplay.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lavplay-lavplay.Tpo $(DEPDIR)/lavplay-lavplay.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='lavplay.c' object='lavplay-lavplay.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lavplay_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lavplay-lavplay.obj `if test -f 'lavplay.c'; then $(CYGPATH_W) 'lavplay.c'; else $(CYGPATH_W) '$(srcdir)/lavplay.c'; fi` png2yuv-png2yuv.o: png2yuv.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(png2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT png2yuv-png2yuv.o -MD -MP -MF $(DEPDIR)/png2yuv-png2yuv.Tpo -c -o png2yuv-png2yuv.o `test -f 'png2yuv.c' || echo '$(srcdir)/'`png2yuv.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/png2yuv-png2yuv.Tpo $(DEPDIR)/png2yuv-png2yuv.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='png2yuv.c' object='png2yuv-png2yuv.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(png2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o png2yuv-png2yuv.o `test -f 'png2yuv.c' || echo '$(srcdir)/'`png2yuv.c png2yuv-png2yuv.obj: png2yuv.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(png2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT png2yuv-png2yuv.obj -MD -MP -MF $(DEPDIR)/png2yuv-png2yuv.Tpo -c -o png2yuv-png2yuv.obj `if test -f 'png2yuv.c'; then $(CYGPATH_W) 'png2yuv.c'; else $(CYGPATH_W) '$(srcdir)/png2yuv.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/png2yuv-png2yuv.Tpo $(DEPDIR)/png2yuv-png2yuv.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='png2yuv.c' object='png2yuv-png2yuv.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(png2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o png2yuv-png2yuv.obj `if test -f 'png2yuv.c'; then $(CYGPATH_W) 'png2yuv.c'; else $(CYGPATH_W) '$(srcdir)/png2yuv.c'; fi` png2yuv-colorspace.o: colorspace.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(png2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT png2yuv-colorspace.o -MD -MP -MF $(DEPDIR)/png2yuv-colorspace.Tpo -c -o png2yuv-colorspace.o `test -f 'colorspace.c' || echo '$(srcdir)/'`colorspace.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/png2yuv-colorspace.Tpo $(DEPDIR)/png2yuv-colorspace.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='colorspace.c' object='png2yuv-colorspace.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(png2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o png2yuv-colorspace.o `test -f 'colorspace.c' || echo '$(srcdir)/'`colorspace.c png2yuv-colorspace.obj: colorspace.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(png2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT png2yuv-colorspace.obj -MD -MP -MF $(DEPDIR)/png2yuv-colorspace.Tpo -c -o png2yuv-colorspace.obj `if test -f 'colorspace.c'; then $(CYGPATH_W) 'colorspace.c'; else $(CYGPATH_W) '$(srcdir)/colorspace.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/png2yuv-colorspace.Tpo $(DEPDIR)/png2yuv-colorspace.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='colorspace.c' object='png2yuv-colorspace.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(png2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o png2yuv-colorspace.obj `if test -f 'colorspace.c'; then $(CYGPATH_W) 'colorspace.c'; else $(CYGPATH_W) '$(srcdir)/colorspace.c'; fi` png2yuv-subsample.o: subsample.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(png2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT png2yuv-subsample.o -MD -MP -MF $(DEPDIR)/png2yuv-subsample.Tpo -c -o png2yuv-subsample.o `test -f 'subsample.c' || echo '$(srcdir)/'`subsample.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/png2yuv-subsample.Tpo $(DEPDIR)/png2yuv-subsample.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='subsample.c' object='png2yuv-subsample.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(png2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o png2yuv-subsample.o `test -f 'subsample.c' || echo '$(srcdir)/'`subsample.c png2yuv-subsample.obj: subsample.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(png2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT png2yuv-subsample.obj -MD -MP -MF $(DEPDIR)/png2yuv-subsample.Tpo -c -o png2yuv-subsample.obj `if test -f 'subsample.c'; then $(CYGPATH_W) 'subsample.c'; else $(CYGPATH_W) '$(srcdir)/subsample.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/png2yuv-subsample.Tpo $(DEPDIR)/png2yuv-subsample.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='subsample.c' object='png2yuv-subsample.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(png2yuv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o png2yuv-subsample.obj `if test -f 'subsample.c'; then $(CYGPATH_W) 'subsample.c'; else $(CYGPATH_W) '$(srcdir)/subsample.c'; fi` yuvplay-yuvplay.o: yuvplay.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yuvplay_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT yuvplay-yuvplay.o -MD -MP -MF $(DEPDIR)/yuvplay-yuvplay.Tpo -c -o yuvplay-yuvplay.o `test -f 'yuvplay.c' || echo '$(srcdir)/'`yuvplay.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/yuvplay-yuvplay.Tpo $(DEPDIR)/yuvplay-yuvplay.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='yuvplay.c' object='yuvplay-yuvplay.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yuvplay_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o yuvplay-yuvplay.o `test -f 'yuvplay.c' || echo '$(srcdir)/'`yuvplay.c yuvplay-yuvplay.obj: yuvplay.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yuvplay_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT yuvplay-yuvplay.obj -MD -MP -MF $(DEPDIR)/yuvplay-yuvplay.Tpo -c -o yuvplay-yuvplay.obj `if test -f 'yuvplay.c'; then $(CYGPATH_W) 'yuvplay.c'; else $(CYGPATH_W) '$(srcdir)/yuvplay.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/yuvplay-yuvplay.Tpo $(DEPDIR)/yuvplay-yuvplay.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='yuvplay.c' object='yuvplay-yuvplay.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yuvplay_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o yuvplay-yuvplay.obj `if test -f 'yuvplay.c'; then $(CYGPATH_W) 'yuvplay.c'; else $(CYGPATH_W) '$(srcdir)/yuvplay.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-liblavincludeHEADERS: $(liblavinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(liblavinclude_HEADERS)'; test -n "$(liblavincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(liblavincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(liblavincludedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(liblavincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(liblavincludedir)" || exit $$?; \ done uninstall-liblavincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(liblavinclude_HEADERS)'; test -n "$(liblavincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(liblavincludedir)'; $(am__uninstall_files_from_dir) ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(liblavincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-liblavincludeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-liblavincludeHEADERS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libLTLIBRARIES clean-libtool cscopelist \ ctags distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-liblavincludeHEADERS install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-libLTLIBRARIES uninstall-liblavincludeHEADERS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mjpegtools-2.1.0/lavtools/pipelist.h0000644000175000017500000000467207363242745020103 0ustar glowwormglowworm/* * pipelist.[ch] - provides two functions to read / write pipe * list files, the "recipes" for lavpipe * * Copyright (C) 2001, pHilipp Zabel * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __PIPELIST_H__ #define __PIPELIST_H__ #include "yuv4mpeg.h" typedef struct { int frame_count; /* frame_num; */ int input_count; /* input_num */ int *input_index; /* input_ptr */ unsigned long *input_offset; /* input_ofs */ char *output_cmd; } PipeSegment; /* PipeSequence */ typedef struct { char video_norm; int frame_count; /* frame_num; */ int source_count; /*input_num; */ char **source_cmd; /* input_cmd */ int segment_count; /* seq_num; */ PipeSegment **segments; /* seq_ptr; */ } PipeList; typedef struct _commandline_params { int verbose; int offset; int frames; char *listfile; } commandline_params_t; typedef struct _pipe_source { int pid; int fd; char *command; y4m_stream_info_t streaminfo; y4m_frame_info_t frameinfo; int frame_num; /* number of next frame to be read from source */ } pipe_source_t; typedef struct _pipe_filter { int pid; int out_fd; /* out -to- filter */ int in_fd; /* in -from- filter */ char *command; y4m_stream_info_t out_streaminfo; y4m_stream_info_t in_streaminfo; y4m_frame_info_t frameinfo; unsigned char *yuv[3]; /* buffers for output -to- filter */ } pipe_filter_t; typedef struct _pipe_sequence { PipeList pl; commandline_params_t cl; pipe_source_t *sources; pipe_filter_t *filters; pipe_filter_t output; } pipe_sequence_t; int read_pipe_list (char *name, PipeList *pl); int write_pipe_list (char *name, PipeList *pl); #endif mjpegtools-2.1.0/lavtools/lav_io.c0000644000175000017500000011315110671070325017474 0ustar glowwormglowworm/* * Some routines for handling I/O from/to different video * file formats (currently AVI, Quicktime) * * These routines are isolated here in an extra file * in order to be able to handle more formats in the future. * * Copyright (C) 2000 Rainer Johanni * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include "lav_io.h" #ifdef HAVE_LIBDV #include #endif extern int AVI_errno; static char video_format=' '; static int internal_error=0; int libdv_pal_yv12 = -1; uint16_t reorder_16(uint16_t todo, int big_endian); #define ERROR_JPEG 1 #define ERROR_MALLOC 2 #define ERROR_FORMAT 3 #define ERROR_NOAUDIO 4 static unsigned long jpeg_field_size = 0; static unsigned long jpeg_quant_offset = 0; static unsigned long jpeg_huffman_offset = 0; static unsigned long jpeg_image_offset = 0; static unsigned long jpeg_scan_offset = 0; static unsigned long jpeg_data_offset = 0; static unsigned long jpeg_padded_len = 0; static unsigned long jpeg_app0_offset = 0; static unsigned long jpeg_app1_offset = 0; #define M_SOF0 0xC0 #define M_SOF1 0xC1 #define M_DHT 0xC4 #define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */ #define M_EOI 0xD9 /* End Of Image (end of datastream) */ #define M_SOS 0xDA /* Start Of Scan (begins compressed data) */ #define M_DQT 0xDB #define M_APP0 0xE0 #define M_APP1 0xE1 #define QUICKTIME_MJPG_TAG 0x6d6a7067 /* 'mjpg' */ #ifdef HAVE_LIBDV static int check_DV2_input(lav_file_t *lav_fd); #endif #define TMP_EXTENSION ".tmp" #ifdef HAVE_LIBQUICKTIME /* put_int4: Put a 4 byte integer value into a character array as big endian number */ static void put_int4(unsigned char *buf, int val) { buf[0] = (val >> 24); buf[1] = (val >> 16); buf[2] = (val >> 8 ); buf[3] = (val ); } #endif /* get_int2: get a 2 byte integer value from a character array as big endian number */ static int get_int2(unsigned char *buff) { return (buff[0]*256 + buff[1]); } /* scan_jpeg: Scan jpeg data for markers, needed for Quicktime MJPA format and partly for AVI files. Taken mostly from Adam Williams' quicktime library */ static int scan_jpeg(unsigned char * jpegdata, long jpeglen, int header_only) { int marker, length; long p; jpeg_field_size = 0; jpeg_quant_offset = 0; jpeg_huffman_offset = 0; jpeg_image_offset = 0; jpeg_scan_offset = 0; jpeg_data_offset = 0; jpeg_padded_len = 0; jpeg_app0_offset = 0; jpeg_app1_offset = 0; /* The initial marker must be SOI */ if (jpegdata[0] != 0xFF || jpegdata[1] != M_SOI) return -1; /* p is the pointer within the jpeg data */ p = 2; /* scan through the jpeg data */ while(p=jpeglen) return -1; } /* Get marker code byte, swallowing any duplicate FF bytes */ while(jpegdata[p] == 0xFF) { p++; if(p>=jpeglen) return -1; } marker = jpegdata[p++]; if(p<=jpeglen-2) length = get_int2(jpegdata+p); else length = 0; /* We found a marker - check it */ if(marker == M_EOI) { jpeg_field_size = p; break; } switch(marker) { case M_SOF0: case M_SOF1: jpeg_image_offset = p-2; break; case M_DQT: if(jpeg_quant_offset==0) jpeg_quant_offset = p-2; break; case M_DHT: if(jpeg_huffman_offset==0) jpeg_huffman_offset = p-2; break; case M_SOS: jpeg_scan_offset = p-2; jpeg_data_offset = p+length; if(header_only) return 0; /* we are done with the headers */ break; case M_APP0: if(jpeg_app0_offset==0) jpeg_app0_offset = p-2; break; case M_APP1: if(jpeg_app1_offset==0) jpeg_app1_offset = p-2; break; } /* The pseudo marker as well as the markers M_TEM (0x01) and M_RST0 ... M_RST7 (0xd0 ... 0xd7) have no paramters. M_SOI and M_EOI also have no parameters, but we should never come here in that case */ if(marker == 0 || marker == 1 || (marker >= 0xd0 && marker <= 0xd7)) continue; /* skip length bytes */ if(p+length<=jpeglen) p += length; else return -1; } /* We are through parsing the jpeg data, we should have seen M_EOI */ if(!jpeg_field_size) return -1; /* Check for trailing garbage until jpeglen is reached or a new M_SOI is seen */ while(pavi_fd = 0; lav_fd->qt_fd = 0; lav_fd->format = format; lav_fd->interlacing = interlaced ? lav_query_polarity(format) : Y4M_ILACE_NONE; lav_fd->has_audio = (asize>0 && achans>0); lav_fd->bps = (asize*achans+7)/8; lav_fd->chroma = Y4M_UNKNOWN; switch(format) { case 'a': case 'A': /* Open AVI output file */ lav_fd->avi_fd = AVI_open_output_file(filename); if(!lav_fd->avi_fd) { free(lav_fd); return 0; } AVI_set_video(lav_fd->avi_fd, width, height, fps, "MJPG"); if (asize) AVI_set_audio(lav_fd->avi_fd, achans, arate, asize, WAVE_FORMAT_PCM, 0); return lav_fd; case 'j': /* Open JPEG output file */ tempfile = (char *)malloc(strlen(filename) + strlen(TMP_EXTENSION) + 1); if (tempfile == NULL) { internal_error=ERROR_MALLOC; return(0); } strcpy(tempfile, filename); strcat(tempfile, TMP_EXTENSION); lav_fd->jpeg_filename = strdup(filename); lav_fd->jpeg_fd = open(tempfile, O_CREAT | O_TRUNC | O_WRONLY, 0644); free(tempfile); return lav_fd; case 'q': #ifdef HAVE_LIBQUICKTIME /* open quicktime output file */ /* since the documentation says that the file should be empty, we try to remove it first */ remove(filename); lav_fd->qt_fd = quicktime_open(filename, 0, 1); if(!lav_fd->qt_fd) { free(lav_fd); return 0; } quicktime_set_video(lav_fd->qt_fd, 1, width, height, fps, (interlaced ? QUICKTIME_MJPA : QUICKTIME_JPEG)); if (interlaced) { if (lav_fd->interlacing == Y4M_ILACE_TOP_FIRST) lqt_set_fiel(lav_fd->qt_fd, 0, 2, 9); else if (lav_fd->interlacing == Y4M_ILACE_BOTTOM_FIRST) lqt_set_fiel(lav_fd->qt_fd, 0, 2, 14); } if (asize) quicktime_set_audio(lav_fd->qt_fd, achans, arate, asize, QUICKTIME_TWOS); return lav_fd; #else internal_error = ERROR_FORMAT; return 0; #endif default: return 0; } } int lav_close(lav_file_t *lav_file) { int res; char *tempfile; video_format = lav_file->format; internal_error = 0; /* for error messages */ switch (lav_file->format) { case 'a': case 'A': res = AVI_close( lav_file->avi_fd ); break; case 'j': tempfile = (char *)malloc(strlen(lav_file->jpeg_filename) + strlen(TMP_EXTENSION) + 1); if (tempfile == NULL) { res = -1; break; } strcpy(tempfile, lav_file->jpeg_filename); strcat(tempfile, TMP_EXTENSION); res = close(lav_file->jpeg_fd); rename(tempfile, lav_file->jpeg_filename); free(tempfile); free(lav_file->jpeg_filename); break; #ifdef HAVE_LIBQUICKTIME case 'q': res = quicktime_close( lav_file->qt_fd ); break; #endif default: res = -1; } free(lav_file); return res; } int lav_write_frame(lav_file_t *lav_file, uint8_t *buff, long size, long count) { int res, n; uint8_t *jpgdata = NULL; long jpglen = 0; video_format = lav_file->format; internal_error = 0; /* for error messages */ /* For interlaced video insert the apropriate APPn markers */ if(lav_file->interlacing != Y4M_ILACE_NONE) { switch(lav_file->format) { case 'a': case 'A': jpgdata = buff; jpglen = size; /* Loop over both fields */ for(n=0;n<2;n++) { /* For first field scan entire field, for second field scan the JPEG header, put in AVI1 + polarity. Be generous on errors */ res = scan_jpeg(jpgdata, size, n); if (res) { internal_error=ERROR_JPEG; return -1; } if(!jpeg_app0_offset) continue; /* APP0 marker should be at least 14+2 bytes */ if(get_int2(jpgdata+jpeg_app0_offset+2) < 16 ) continue; jpgdata[jpeg_app0_offset+4] = 'A'; jpgdata[jpeg_app0_offset+5] = 'V'; jpgdata[jpeg_app0_offset+6] = 'I'; jpgdata[jpeg_app0_offset+7] = '1'; jpgdata[jpeg_app0_offset+8] = lav_file->format=='a' ? n+1 : 2-n; /* Update pointer and len for second field */ jpgdata += jpeg_padded_len; jpglen -= jpeg_padded_len; } break; case 'j': jpgdata = buff; jpglen = size; break; #ifdef HAVE_LIBQUICKTIME case 'q': jpgdata = buff; jpglen = size; /* Loop over both fields */ for(n=0;n<2;n++) { /* Scan the entire JPEG field data - APP1 marker MUST be present */ res = scan_jpeg(jpgdata,jpglen,0); if(res || !jpeg_app1_offset) { internal_error=ERROR_JPEG; return -1; } /* Length of APP1 marker must be at least 40 + 2 bytes */ if ( get_int2(jpgdata+jpeg_app1_offset+2) < 42) { internal_error=ERROR_JPEG; return -1; } /* Fill in data */ put_int4(jpgdata+jpeg_app1_offset+ 4,0); put_int4(jpgdata+jpeg_app1_offset+ 8,QUICKTIME_MJPG_TAG); put_int4(jpgdata+jpeg_app1_offset+12,jpeg_field_size); put_int4(jpgdata+jpeg_app1_offset+16,jpeg_padded_len); put_int4(jpgdata+jpeg_app1_offset+20,n==0?jpeg_padded_len:0); put_int4(jpgdata+jpeg_app1_offset+24,jpeg_quant_offset); put_int4(jpgdata+jpeg_app1_offset+28,jpeg_huffman_offset); put_int4(jpgdata+jpeg_app1_offset+32,jpeg_image_offset); put_int4(jpgdata+jpeg_app1_offset+36,jpeg_scan_offset); put_int4(jpgdata+jpeg_app1_offset+40,jpeg_data_offset); /* Update pointer and len for second field */ jpgdata += jpeg_padded_len; jpglen -= jpeg_padded_len; } break; #endif } } res = 0; /* Silence gcc */ for(n=0;nformat) { case 'a': case 'A': if(n==0) res = AVI_write_frame( lav_file->avi_fd, buff, size, 0); else res = AVI_dup_frame( lav_file->avi_fd ); break; case 'j': if (n==0) write(lav_file->jpeg_fd, buff, size); break; #ifdef HAVE_LIBQUICKTIME case 'q': res = quicktime_write_frame( lav_file->qt_fd, buff, size, 0 ); break; #endif default: res = -1; } if (res) break; } return res; } int lav_write_audio(lav_file_t *lav_file, uint8_t *buff, long samps) { int res = -1; #ifdef HAVE_LIBQUICKTIME int i, j; int16_t *buff16 = (int16_t *)buff, **qt_audion; int channels = lav_audio_channels(lav_file); int bits = lav_audio_bits(lav_file); #endif video_format = lav_file->format; internal_error = 0; /* for error messages */ switch(lav_file->format) { case 'a': case 'A': res = AVI_write_audio( lav_file->avi_fd, buff, samps*lav_file->bps); break; #ifdef HAVE_LIBQUICKTIME case 'q': if (bits != 16 || channels > 1) { /* Deinterleave the audio into the two channels and/or convert * bits per sample to the required format. */ qt_audion = malloc(channels * sizeof(*qt_audion)); for (i = 0; i < channels; i++) qt_audion[i] = malloc(samps * sizeof(**qt_audion)); if (bits == 16) for (i = 0; i < samps; i++) for (j = 0; j < channels; j++) qt_audion[j][i] = buff16[channels * i + j]; else if (bits == 8) for (i = 0; i < samps; i++) for (j = 0; j < channels; j++) qt_audion[j][i] = ((int16_t)(buff[channels * i + j]) << 8) ^ 0x8000; if (bits == 8 || bits == 16) res = lqt_encode_audio_track(lav_file->qt_fd, qt_audion, NULL, samps, 0); for (i = 0; i < channels; i++) free(qt_audion[i]); free(qt_audion); } else { qt_audion = &buff16; res = lqt_encode_audio_track(lav_file->qt_fd, qt_audion, NULL, samps, 0); } break; #endif default: break; } return res; } long lav_video_frames(lav_file_t *lav_file) { video_format = lav_file->format; internal_error = 0; /* for error messages */ switch(lav_file->format) { case 'a': case 'A': return AVI_video_frames(lav_file->avi_fd); #ifdef HAVE_LIBQUICKTIME case 'q': return quicktime_video_length(lav_file->qt_fd,0); #endif } return -1; } int lav_video_width(lav_file_t *lav_file) { video_format = lav_file->format; internal_error = 0; /* for error messages */ switch(lav_file->format) { case 'a': case 'A': return AVI_video_width(lav_file->avi_fd); #ifdef HAVE_LIBQUICKTIME case 'q': return quicktime_video_width(lav_file->qt_fd,0); #endif } return -1; } int lav_video_height(lav_file_t *lav_file) { video_format = lav_file->format; internal_error = 0; /* for error messages */ switch(lav_file->format) { case 'a': case 'A': return AVI_video_height(lav_file->avi_fd); #ifdef HAVE_LIBQUICKTIME case 'q': return quicktime_video_height(lav_file->qt_fd,0); #endif } return -1; } double lav_frame_rate(lav_file_t *lav_file) { video_format = lav_file->format; internal_error = 0; /* for error messages */ switch(lav_file->format) { case 'a': case 'A': return AVI_frame_rate(lav_file->avi_fd); #ifdef HAVE_LIBQUICKTIME case 'q': return quicktime_frame_rate(lav_file->qt_fd,0); #endif } return -1; } int lav_video_interlacing(lav_file_t *lav_file) { return lav_file->interlacing; } void lav_video_sampleaspect(lav_file_t *lav_file, int *sar_w, int *sar_h) { *sar_w = lav_file->sar_w; *sar_h = lav_file->sar_h; return; } int lav_video_chroma(lav_file_t *lav_file) { return lav_file->chroma; } const char *lav_video_compressor(lav_file_t *lav_file) { video_format = lav_file->format; internal_error = 0; /* for error messages */ switch(lav_file->format) { case 'a': case 'A': return AVI_video_compressor(lav_file->avi_fd); #ifdef HAVE_LIBQUICKTIME case 'q': return quicktime_video_compressor(lav_file->qt_fd,0); #endif } return "N/A"; } int lav_audio_channels(lav_file_t *lav_file) { if(!lav_file->has_audio) return 0; video_format = lav_file->format; internal_error = 0; /* for error messages */ switch(lav_file->format) { case 'a': case 'A': return AVI_audio_channels(lav_file->avi_fd); #ifdef HAVE_LIBQUICKTIME case 'q': return quicktime_track_channels(lav_file->qt_fd,0); #endif } return -1; } int lav_audio_bits(lav_file_t *lav_file) { if(!lav_file->has_audio) return 0; video_format = lav_file->format; internal_error = 0; /* for error messages */ switch(lav_file->format) { case 'a': case 'A': return AVI_audio_bits(lav_file->avi_fd); #ifdef HAVE_LIBQUICKTIME case 'q': return quicktime_audio_bits(lav_file->qt_fd,0); #endif } return -1; } long lav_audio_rate(lav_file_t *lav_file) { if(!lav_file->has_audio) return 0; video_format = lav_file->format; internal_error = 0; /* for error messages */ switch(lav_file->format) { case 'a': case 'A': return AVI_audio_rate(lav_file->avi_fd); #ifdef HAVE_LIBQUICKTIME case 'q': return quicktime_sample_rate(lav_file->qt_fd,0); #endif } return -1; } long lav_audio_samples(lav_file_t *lav_file) { if(!lav_file->has_audio) return 0; video_format = lav_file->format; internal_error = 0; /* for error messages */ switch(lav_file->format) { case 'a': case 'A': return AVI_audio_bytes(lav_file->avi_fd)/lav_file->bps; #ifdef HAVE_LIBQUICKTIME case 'q': return quicktime_audio_length(lav_file->qt_fd,0); #endif } return -1; } long lav_frame_size(lav_file_t *lav_file, long frame) { video_format = lav_file->format; internal_error = 0; /* for error messages */ switch(lav_file->format) { case 'a': case 'A': return AVI_frame_size(lav_file->avi_fd,frame); #ifdef HAVE_LIBQUICKTIME case 'q': return quicktime_frame_size(lav_file->qt_fd,frame,0); #endif } return -1; } int lav_seek_start(lav_file_t *lav_file) { video_format = lav_file->format; internal_error = 0; /* for error messages */ switch(lav_file->format) { case 'a': case 'A': return AVI_seek_start(lav_file->avi_fd); #ifdef HAVE_LIBQUICKTIME case 'q': return quicktime_seek_start(lav_file->qt_fd); #endif } return -1; } int lav_set_video_position(lav_file_t *lav_file, long frame) { video_format = lav_file->format; internal_error = 0; /* for error messages */ switch(lav_file->format) { case 'a': case 'A': return AVI_set_video_position(lav_file->avi_fd,frame); #ifdef HAVE_LIBQUICKTIME case 'q': return quicktime_set_video_position(lav_file->qt_fd,frame,0); #endif } return -1; } int lav_read_frame(lav_file_t *lav_file, uint8_t *vidbuf) { int keyframe; video_format = lav_file->format; internal_error = 0; /* for error messages */ switch(lav_file->format) { case 'a': case 'A': return AVI_read_frame(lav_file->avi_fd,vidbuf, &keyframe); #ifdef HAVE_LIBQUICKTIME case 'q': return quicktime_read_frame(lav_file->qt_fd,vidbuf,0); #endif } return -1; } int lav_set_audio_position(lav_file_t *lav_file, long sample) { if(!lav_file->has_audio) return 0; video_format = lav_file->format; internal_error = 0; /* for error messages */ switch(lav_file->format) { case 'a': case 'A': return AVI_set_audio_position(lav_file->avi_fd,sample*lav_file->bps); #ifdef HAVE_LIBQUICKTIME case 'q': quicktime_set_audio_position(lav_file->qt_fd,sample,0); #endif } return -1; } long lav_read_audio(lav_file_t *lav_file, uint8_t *audbuf, long samps) { #ifdef HAVE_LIBQUICKTIME int64_t last_pos, start_pos; int res, i, j; int16_t *qt_audio = (int16_t *)audbuf, **qt_audion; int channels = lav_audio_channels(lav_file); uint8_t b0, b1; #endif if(!lav_file->has_audio) { internal_error = ERROR_NOAUDIO; return(-1); } video_format = lav_file->format; internal_error = 0; /* for error messages */ switch(lav_file->format) { case 'a': case 'A': return AVI_read_audio(lav_file->avi_fd,audbuf,samps*lav_file->bps)/lav_file->bps; #ifdef HAVE_LIBQUICKTIME case 'q': qt_audion = malloc(channels * sizeof (int16_t **)); for (i = 0; i < channels; i++) qt_audion[i] = (int16_t *)malloc(samps * lav_file->bps); start_pos = quicktime_audio_position(lav_file->qt_fd, 0); lqt_decode_audio_track(lav_file->qt_fd, qt_audion, NULL, samps, 0); last_pos = lqt_last_audio_position(lav_file->qt_fd, 0); res = last_pos - start_pos; if (res <= 0) goto out; /* Interleave the channels of audio into the one buffer provided */ for (i =0; i < res; i++) { for (j = 0; j < channels; j++) qt_audio[(channels*i) + j] = qt_audion[j][i]; } if (lav_detect_endian()) { i= 0; while (i < (2*res) ) { b0 = 0; b1 = 0; b0 = (qt_audio[i] & 0x00FF); b1 = (qt_audio[i] & 0xFF00) >> 8; qt_audio[i] = (b0 <<8) + b1; i = i +1; } } out: for (j = 0; j < channels; j++) free(qt_audion[j]); free(qt_audion); return(res); #endif } return -1; } lav_file_t *lav_open_input_file(char *filename) { int n; const char *video_comp = NULL; #ifdef HAVE_LIBQUICKTIME char *audio_comp; #endif unsigned char *frame = NULL; /* Make sure un-init segfaults! */ long len; int jpg_height, jpg_width, ncomps, hf[3], vf[3]; int ierr; lav_file_t *lav_fd = (lav_file_t*) malloc(sizeof(lav_file_t)); if(lav_fd==0) { internal_error=ERROR_MALLOC; return 0; } /* Set lav_fd */ lav_fd->avi_fd = 0; lav_fd->qt_fd = 0; lav_fd->format = 0; lav_fd->interlacing = Y4M_UNKNOWN; lav_fd->sar_w = 1; /* unknown - assume square pixels */ lav_fd->sar_h = 1; lav_fd->has_audio = 0; lav_fd->bps = 0; lav_fd->chroma = Y4M_UNKNOWN; /* open video file, try AVI first */ lav_fd->avi_fd = AVI_open_input_file(filename,1); video_format = 'a'; /* for error messages */ if(lav_fd->avi_fd) { /* It is an AVI file */ lav_fd->qt_fd = 0; lav_fd->format = 'a'; lav_fd->has_audio = (AVI_audio_bits(lav_fd->avi_fd)>0 && AVI_audio_format(lav_fd->avi_fd)==WAVE_FORMAT_PCM); video_comp = AVI_video_compressor(lav_fd->avi_fd); } else if( AVI_errno==AVI_ERR_NO_AVI ) { #ifdef HAVE_LIBQUICKTIME if(!quicktime_check_sig(filename)) #endif { /* None of the known formats */ char errmsg[1024]; sprintf(errmsg, "Unable to identify file (not a supported format - avi"); #ifdef HAVE_LIBQUICKTIME strcat(errmsg, ", quicktime"); #endif strcat(errmsg, ").\n"); fprintf(stderr, errmsg); free(lav_fd); internal_error = ERROR_FORMAT; /* Format not recognized */ return 0; } #ifdef HAVE_LIBQUICKTIME else { quicktime_pasp_t pasp; int nfields, detail; /* It is a quicktime file */ lav_fd->qt_fd = quicktime_open(filename,1,0); video_format = 'q'; /* for error messages */ if (!lav_fd->qt_fd) { free(lav_fd); return 0; } lav_fd->avi_fd = NULL; lav_fd->format = 'q'; video_comp = quicktime_video_compressor(lav_fd->qt_fd,0); /* We want at least one video track */ if (quicktime_video_tracks(lav_fd->qt_fd) < 1) { lav_close(lav_fd); internal_error = ERROR_FORMAT; return 0; } /* * If the quicktime file has the sample aspect atom then use it to set * the sar values in the lav_fd structure. Hardwired (like everywhere else) * to only look at track 0. */ if (lqt_get_pasp(lav_fd->qt_fd, 0, &pasp) != 0) { lav_fd->sar_w = pasp.hSpacing; lav_fd->sar_h = pasp.vSpacing; } /* * If a 'fiel' atom is present (not guaranteed) then use it to set the * interlacing type. */ if (lqt_get_fiel(lav_fd->qt_fd, 0, &nfields, &detail) != 0) { if (nfields == 2) { if (detail == 14 || detail == 6) lav_fd->interlacing = Y4M_ILACE_BOTTOM_FIRST; else if (detail == 9 || detail == 1) lav_fd->interlacing = Y4M_ILACE_TOP_FIRST; else mjpeg_warn("unknown 'detail' in 'fiel' atom: %d", detail); } else lav_fd->interlacing = Y4M_ILACE_NONE; } /* Check for audio tracks */ lav_fd->has_audio = 0; if (quicktime_audio_tracks(lav_fd->qt_fd)) { audio_comp = quicktime_audio_compressor(lav_fd->qt_fd,0); if (strncasecmp(audio_comp, QUICKTIME_TWOS,4)==0) lav_fd->has_audio = 1; } } #endif } else { /* There should be an error from avilib, just return */ free(lav_fd); return 0; } /* set audio bytes per sample */ lav_fd->bps = (lav_audio_channels(lav_fd)*lav_audio_bits(lav_fd)+7)/8; if(lav_fd->bps==0) lav_fd->bps=1; /* make it save since we will divide by that value */ /* * Check compressor. The YUV checks are not right (the support code appears * incorrect and/or incomplete). In particular yuv2 is a packed format not * planar and YV12 has the U and V planes reversed from IYUV (which is what * the support code appears to think is YUV420). My hunch is that folks are * only using DV and MJPG so the YUV bugs aren't being triggered. * * But at least now the checks are consolidated in 1 place instead of being * duplicated in two places (editlist.c and this file). */ ierr = 0; if (strncasecmp(video_comp, "yv12", 3) == 0) { lav_fd->dataformat = DATAFORMAT_YUV420; /* * This is probably not correct. But since 'yv12' isn't really supported it * doesn't matter ;) */ lav_fd->chroma = Y4M_CHROMA_420JPEG; } else if (strncasecmp(video_comp, "yuv2", 4) == 0) { lav_fd->dataformat = DATAFORMAT_YUV422; lav_fd->chroma = Y4M_CHROMA_422; } else if (strncasecmp(video_comp, "dv", 2) == 0) { lav_fd->dataformat = DATAFORMAT_DV2; lav_fd->interlacing = Y4M_ILACE_BOTTOM_FIRST; } else if (strncasecmp(video_comp, "mjp", 3) == 0 || strncasecmp(video_comp, "jpeg", 4) == 0) lav_fd->dataformat = DATAFORMAT_MJPG; else { internal_error = ERROR_FORMAT; goto ERREXIT; } #ifdef HAVE_LIBDV if (lav_fd->dataformat == DATAFORMAT_DV2) { ierr = check_DV2_input(lav_fd); if (ierr) goto ERREXIT; } #endif /* HAVE_LIBDV */ if (lav_fd->dataformat != DATAFORMAT_MJPG) return lav_fd; /* * From here on down is MJPG only code - the yuv and dv cases have been handled * above. Make some checks on the video source. Read the first frame for this. */ frame = NULL; if (lav_set_video_position(lav_fd,0)) goto ERREXIT; if ((len = lav_frame_size(lav_fd,0)) <=0) goto ERREXIT; if ((frame = (unsigned char*) malloc(len)) == 0) { ierr=ERROR_MALLOC; goto ERREXIT; } if (lav_read_frame(lav_fd,frame) <= 0) goto ERREXIT; /* reset video position to 0 */ if (lav_set_video_position(lav_fd,0)) goto ERREXIT; if (scan_jpeg(frame, len, 1)) { ierr=ERROR_JPEG; goto ERREXIT; } /* We have to look to the JPEG SOF marker for further information The SOF marker has the following format: FF C0 len_hi len_lo data_precision height_hi height_lo width_hi width_lo num_components And then 3 bytes for each component: Component id H, V sampling factors (as nibbles) Quantization table number */ /* Check if the JPEG has the special 4:2:2 format needed for some HW JPEG decompressors (the Iomega Buz, for example) */ ncomps = frame[jpeg_image_offset + 9]; if(ncomps==3) { for(n=0;n<3;n++) { hf[n] = frame[jpeg_image_offset + 10 + 3*n + 1]>>4; vf[n] = frame[jpeg_image_offset + 10 + 3*n + 1]&0xf; } /* Identify chroma sub-sampling format only 420 and 422 supported at present...*/ if( hf[0] == 2*hf[1] && hf[0] == 2*hf[2] ) { if( vf[0] == vf[1] && vf[0] == vf[2] ) { lav_fd->chroma = Y4M_CHROMA_422; } else if( vf[0] == 2*vf[1] && vf[0] == 2*vf[2] ) lav_fd->chroma = Y4M_CHROMA_420JPEG; else lav_fd->chroma = Y4M_UNKNOWN; } else lav_fd->chroma = Y4M_UNKNOWN; } /* Check if video is interlaced */ /* height and width are encoded in the JPEG SOF marker at offsets 5 and 7 */ jpg_height = get_int2(frame + jpeg_image_offset + 5); jpg_width = get_int2(frame + jpeg_image_offset + 7); /* check height */ if( jpg_height == lav_video_height(lav_fd)) lav_fd->interlacing = Y4M_ILACE_NONE; else if ( jpg_height == lav_video_height(lav_fd)/2 ) { /* Video is interlaced */ switch(lav_fd->format) { case 'a': /* Check the APP0 Marker, if present */ if(jpeg_app0_offset && get_int2(frame + jpeg_app0_offset + 2) >= 5 && strncasecmp((char*)(frame + jpeg_app0_offset + 4),"AVI1",4)==0 ) { if (frame[jpeg_app0_offset+8]==1) lav_fd->interlacing = Y4M_ILACE_TOP_FIRST; else lav_fd->interlacing = Y4M_ILACE_BOTTOM_FIRST; } else { /* There is no default, it really depends on the application which produced the AVI */ lav_fd->interlacing = Y4M_ILACE_TOP_FIRST; } lav_fd->format = lav_fd->interlacing == Y4M_ILACE_BOTTOM_FIRST ? 'A' : 'a'; break; case 'q': lav_fd->interlacing = Y4M_ILACE_TOP_FIRST; break; } } else { ierr=ERROR_JPEG; goto ERREXIT; } free(frame); return lav_fd; ERREXIT: lav_close(lav_fd); if(frame) free(frame); internal_error = ierr; return 0; } /* Get size of first field of for a data array containing (possibly) two jpeg fields */ int lav_get_field_size(uint8_t * jpegdata, long jpeglen) { int res; res = scan_jpeg(jpegdata,jpeglen,0); if(res<0) return jpeglen; /* Better than nothing */ /* we return jpeg_padded len since this routine is used for field exchange where alignment might be important */ return jpeg_padded_len; } static char error_string[4096]; const char *lav_strerror(void) { switch(internal_error) { case ERROR_JPEG: sprintf(error_string,"Internal: broken JPEG format"); internal_error = 0; return error_string; case ERROR_MALLOC: sprintf(error_string,"Internal: Out of memory"); internal_error = 0; return error_string; case ERROR_FORMAT: sprintf(error_string,"Input file format not recognized"); internal_error = 0; return error_string; case ERROR_NOAUDIO: sprintf(error_string,"Trying to read audio from a video only file"); internal_error = 0; return error_string; } switch(video_format) { case 'a': case 'A': return AVI_strerror(); #ifdef HAVE_LIBQUICKTIME case 'q': /* The quicktime documentation doesn't say much about error codes, we hope that strerror may give some info */ sprintf(error_string,"Quicktime error, possible(!) reason: %s",strerror(errno)); return error_string; #endif default: /* No or unknown video format */ if(errno) strerror(errno); else sprintf(error_string,"No or unknown video format"); return error_string; } } #ifdef HAVE_LIBDV static int check_DV2_input(lav_file_t *lav_fd) { int ierr = 0; double len = 0; unsigned char *frame = NULL; dv_decoder_t *decoder = NULL; uint8_t *output[3] = { NULL, NULL, NULL }; uint16_t pitches[3]; /* Make some checks on the video source, we read the first frame for that */ if (lav_set_video_position(lav_fd,0)) goto ERREXIT; if ((len = lav_frame_size(lav_fd,0)) <=0) goto ERREXIT; if ((frame = (unsigned char*) malloc(len)) == 0) { ierr=ERROR_MALLOC; goto ERREXIT; } if (lav_read_frame(lav_fd, frame) <= 0) goto ERREXIT; decoder = dv_decoder_new(0,0,0); dv_parse_header(decoder, frame); switch (decoder->system) { case e_dv_system_525_60: if (dv_format_wide(decoder)) { lav_fd->sar_w = 40; lav_fd->sar_h = 33; } else { lav_fd->sar_w = 10; lav_fd->sar_h = 11; } break; case e_dv_system_625_50: if (dv_format_wide(decoder)) { lav_fd->sar_w = 118; lav_fd->sar_h = 81; } else { lav_fd->sar_w = 59; lav_fd->sar_h = 54; } break; default: ierr = ERROR_FORMAT; /* Neither 525 or 625 system */ goto ERREXIT; /* declare a format error! */ } switch(decoder->sampling) { case e_dv_sample_420: /* libdv decodes PAL DV directly as planar YUV 420 * (YV12 or 4CC 0x32315659) if configured with the flag * --with-pal-yuv=YV12 which is not (!) the default */ if (libdv_pal_yv12 < 0 ) { /* PAL YV12 not already detected. * Setting decoding options for 4:2:2, because libdv pitches * is *int* for YUY2 and *uint16_t* for YV12 (no comment...) * In YV12 mode, even if pitches is 0, the first line is filled. */ pitches[0] = decoder->width * 2; pitches[1] = 0; pitches[2] = 0; /* Hacking libdv: set invalid values for chroma. If libdv * was compiled with PAL YV12, the values are overwritten, * otherwise (4:2:2 output) only dv_frame[0] is filled and * chroma planes remain untouched. */ output[0] = (uint8_t *)malloc(decoder->width * decoder->height * 2); output[1] = (uint8_t *)malloc(decoder->width * decoder->height / 2); if (!output[0] || !output[1]) { ierr=ERROR_MALLOC; goto ERREXIT; } else { output[2] = output[1] + (decoder->width * decoder->height / 4 ); output[1][0] = 0; output[1][1] = 255; output[2][0] = 255; output[2][1] = 0; dv_decode_full_frame(decoder, frame, e_dv_color_yuv, output, (int *)pitches); if (output[1][0]==0 && output[1][1]==255 && output[2][0]==255 && output[2][1]==0) { libdv_pal_yv12 = 0; lav_fd->chroma = Y4M_CHROMA_422; mjpeg_info("Detected libdv PAL output YUY2 (4:2:2)"); } else { libdv_pal_yv12 = 1; lav_fd->chroma = Y4M_CHROMA_420PALDV; mjpeg_info("Detected libdv PAL output YV12 (4:2:0)"); } free(output[0]); free(output[1]); } } else { if(libdv_pal_yv12 == 0) lav_fd->chroma = Y4M_CHROMA_422; else lav_fd->chroma = Y4M_CHROMA_420PALDV; } break; case e_dv_sample_411: /* libdv decodes NTSC DV (native 411) as packed YUV 422 (YUY2 or 4CC 0x32595559) * where the U and V information is repeated. */ lav_fd->chroma = Y4M_CHROMA_411; break; case e_dv_sample_422: /* libdv decodes PAL DV (native 420) as packed YUV 422 (YUY2 or 4CC 0x32595559) * where the U and V information is repeated. This can be * transformed to planar 420 (YV12 or 4CC 0x32315659). */ lav_fd->chroma = Y4M_CHROMA_422; break; case e_dv_sample_none: /* FIXME */ break; } free(frame); dv_decoder_free(decoder); lav_set_video_position(lav_fd,0); return 0; ERREXIT: lav_close(lav_fd); if (frame) free(frame); if (decoder) dv_decoder_free(decoder); if (output[0]) free(output[0]); if (output[1]) free(output[1]); if (ierr) internal_error = ierr; return 1; } #endif int lav_fileno(lav_file_t *lav_file) { int res; video_format = lav_file->format; switch(lav_file->format) { case 'a': case 'A': res = AVI_fileno(lav_file->avi_fd); break; #ifdef HAVE_LIBQUICKTIME case 'q': res = lqt_fileno((quicktime_t *)lav_file->qt_fd); break; #endif default: res = -1; } return res; } /* We need this to reorder the 32 bit values for big endian systems */ uint32_t reorder_32(uint32_t todo, int big_endian) { unsigned char b0, b1, b2, b3; unsigned long reversed; if( big_endian ) { b0 = (todo & 0x000000FF); b1 = (todo & 0x0000FF00) >> 8; b2 = (todo & 0x00FF0000) >> 16; b3 = (todo & 0xFF000000) >> 24; reversed = (b0 << 24) + (b1 << 16) + (b2 << 8) +b3; return reversed; } return todo; } int lav_detect_endian (void) { unsigned int fred; char *pfred; fred = 2 | (1 << (sizeof(int)*8-8)); pfred = (char *)&fred; if (*pfred == 1) return 1; else if(*pfred == 2) return 0; else return -1; } mjpegtools-2.1.0/lavtools/yuvinactive.c0000644000175000017500000005030211255212201020555 0ustar glowwormglowworm/**************************************************************************** * yuvinactive.c * Copyright (C) 2003 Bernhard Praschinger * * Sets a area in the yuv frame to black * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *****************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include "yuv4mpeg.h" #define LUMA 16 #define CHROMA 128 /* some defintions */ struct area_s { int width; /**< width of the area */ int height; /**< height of the area */ int voffset; /**< vertical offset from the top left boarder */ int hoffset; /**< horizontal offest from the top left boarder */ }; struct color_yuv { int luma; /**< the luma to use */ int chroma_b; /**< the chroma Cb to use */ int chroma_r; /**< the chroma Cr to use */ }; int verbose = 1; /* protoypes */ static void print_usage(char *progname); void copy_area(struct area_s , int , int , uint8_t *frame[], int ); void process_commandline(int argc, char *argv[], struct area_s *inarea, int *darker, int *copy_pixel, struct color_yuv *coloryuv, int *average_pixel); void fillarea(char area[20], struct area_s *inarea); void set_darker(struct area_s inarea, int horz, int vert, uint8_t *frame[], int darker); void set_inactive(struct area_s inarea, int horz, int vert, uint8_t *frame[], struct color_yuv *coloryuv); void set_yuvcolor(char area[20], struct color_yuv *coloryuv); void average_area(struct area_s inarea, int horz, int vert, uint8_t *frame[], int average_pixel); void average_block(int go_h, int go_w, int horz, int plane, int *orig_offset, uint8_t *frame[]); /* Here we start the programm */ /** The typical help output */ static void print_usage(char *progname) { fprintf(stderr, "%s usage: -i XxY+XOFF+YOFF\n\n",progname); fprintf(stderr, " -h -H - print out this help\n"); fprintf(stderr, " -i X+Y+XOFF+YOFF - the area which will be set inactive, from top left\n"); fprintf(stderr, " - X=Width, Y=Height, XOFF=VerticalOffset, YOFF=HorizonalOffset\n"); fprintf(stderr, " -s luma,Cb,Cr - set the filling color in yuv format\n"); fprintf(stderr, " -d num [1-100] - set how much darker the area will be, in percent\n"); fprintf(stderr, " -c num - copy num sourrounding lines into the area\n"); fprintf(stderr, " -a num - use num pixles for on square to average the area\n"); fprintf(stderr, "\n"); exit(1); } /** Here we process the command line options */ void process_commandline(int argc, char *argv[], struct area_s *inarea, int *darker, int *copy_pixel, struct color_yuv *coloryuv, int *average_pixel) { int c; char area [20]; while ((c = getopt(argc, argv, "Hhv:i:s:d:c:a:")) != -1) { switch (c) { case 'v': verbose = atoi(optarg); if ( verbose < 0 || verbose > 2) print_usage(argv[0]); if (verbose == 2) mjpeg_info("Set Verbose = %i", verbose); break; case 'i': strncpy(area, optarg, 20); /* This part shows how to process */ fillarea(area, inarea); /* command line options */ break; case 's': strncpy(area, optarg, 20); set_yuvcolor(area, coloryuv); break; case 'd': *darker = atoi(optarg); break; case 'c': *copy_pixel = atoi(optarg); break; case 'a': *average_pixel = atoi(optarg); break; case 'H': case 'h': print_usage(argv[0]); } } /* Checking if we have used the -i option */ if ( ((*inarea).height == 0) && ((*inarea).width == 0) ) mjpeg_error_exit1("You have to use the -i option"); /* Checking the range of the darker -d option */ if ( (*darker < 0) || (*darker > 100) ) mjpeg_error_exit1("You can only make the area 1-100 percent darker"); else mjpeg_info("Setting the area %i percent darker", *darker); /* Checking the copy pixel option */ if (*copy_pixel != 0) { if ( ((*inarea).height/2) < *copy_pixel) { mjpeg_error("You can only copy half of the height into the area"); mjpeg_error_exit1("lower the copy pixel value below: %i ", ((*inarea).height/2)); } if ( (*copy_pixel % 2) != 0) mjpeg_error_exit1("you have to use a even number of lines to copy into the field"); if ( ((*inarea).height % *copy_pixel) != 0) mjpeg_error_exit1("the height has to be a multiply of the copy pixel value"); mjpeg_info("Number of rows using for coping into the area %i", *copy_pixel); } /* Checking the average pixel option */ if (*average_pixel != 0) { if ( (*average_pixel > (*inarea).height) || (*average_pixel > (*inarea).width) ) mjpeg_error_exit1("The pixles used for the average must be less the the inactive area"); if ( (*average_pixel % 2) != 0) mjpeg_error_exit1("you have to use a even number for the average pixels"); mjpeg_info("Number of pixels used for averaging %i", *average_pixel); } } /** Here we set the color to use for filling the area */ void set_yuvcolor(char area[20], struct color_yuv *coloryuv) { int i; unsigned int u1, u2, u3; i = sscanf (area, "%i,%i,%i", &u1, &u2, &u3); if ( 3 == i ) { (*coloryuv).luma = u1; (*coloryuv).chroma_b = u2; (*coloryuv).chroma_r = u3; if ( ((*coloryuv).luma > 235) || ((*coloryuv).luma < 16) ) mjpeg_error_exit1("out of range value for luma given: %i, \n" " allowed values 16-235", (*coloryuv).luma); if ( ((*coloryuv).chroma_b > 240) || ((*coloryuv).chroma_b < 16) ) mjpeg_error_exit1("out of range value for Cb given: %i, \n" " allowed values 16-240", (*coloryuv).chroma_b); if ( ((*coloryuv).chroma_r > 240) || ((*coloryuv).chroma_r < 16) ) mjpeg_error_exit1("out of range value for Cr given: %i, \n" " allowed values 16-240", (*coloryuv).chroma_r); mjpeg_info("got luma %i, Cb %i, Cr %i ", (*coloryuv).luma, (*coloryuv).chroma_b, (*coloryuv).chroma_r ); } else mjpeg_error_exit1("Wrong number of colors given, %s", area); } /** Here we cut out the number of the area string */ void fillarea(char area[20], struct area_s *inarea) { int i; unsigned int u1, u2, u3, u4; /* Cuting out the numbers of the stream */ i = sscanf (area, "%ix%i+%i+%i", &u1, &u2, &u3, &u4); if ( 4 == i) /* Checking if we have got 4 numbers */ { (*inarea).width = u1; (*inarea).height = u2; (*inarea).hoffset = u3; (*inarea).voffset = u4; if ( (((*inarea).width % 2) != 0) || (((*inarea).height % 2) != 0) || (((*inarea).hoffset% 2)!= 0) || (((*inarea).voffset% 2) != 0) ) mjpeg_error_exit1("At least one argument no even number"); if (verbose >= 1) mjpeg_info("got the area : W %i, H %i, Xoff %i, Yoff %i", (*inarea).width,(*inarea).height,(*inarea).hoffset,(*inarea).voffset); } else mjpeg_error_exit1("Wrong inactive sting given: %s", area); } /** Here we copy the surrounding information into the area */ void copy_area(struct area_s inarea, int horz, int vert, uint8_t *frame[], int copy_pixel) { uint8_t *plane_l, *plane_cb, *plane_cr; unsigned char *temp_pix_l, *temp_pix_cb, *temp_pix_cr; int i,j, offset_pix, copy_offset_pix, chroma_lines; temp_pix_l = (unsigned char *)malloc(inarea.width); temp_pix_cb = (unsigned char *)malloc(inarea.width/2); temp_pix_cr = (unsigned char *)malloc(inarea.width/2); plane_l = frame[0]; plane_cb = frame[1]; plane_cr = frame[2]; /* In the first step we copy the luma data*/ offset_pix = (horz * inarea.voffset) + inarea.hoffset; i=0; while (i < (inarea.height/2)) /* copying lines from the top down */ { copy_offset_pix = (horz * (inarea.voffset - copy_pixel) + inarea.hoffset); for (j = 0; j < copy_pixel; j++) { memcpy(temp_pix_l, (plane_l+(copy_offset_pix+(j*horz))), inarea.width); memcpy((plane_l+offset_pix), temp_pix_l, inarea.width); offset_pix += horz; //mjpeg_info("copy_offset %i, offset %i von j %i, von i %i", copy_offset_pix, offset_pix, j ,i); } i += copy_pixel; /* we copy more lines in one step */ } while (i < inarea.height) /* copying lines from the bottom up */ { copy_offset_pix = (horz * (inarea.voffset + inarea.height) + inarea.hoffset); for (j = 0; j < copy_pixel; j++) { memcpy(temp_pix_l, (plane_l+copy_offset_pix+(j*horz)), inarea.width); memcpy((plane_l+offset_pix), temp_pix_l, inarea.width); offset_pix += horz; // mjpeg_info("wert von offset_pix %i, von j %i, von i %i", copy_offset_pix, j ,i); } i += copy_pixel; /* we copy more lines in one step */ } /* In the 2nd step we copy the chroma data */ offset_pix = (horz * inarea.voffset)/4 + (inarea.hoffset/2); if ((inarea.height%4) != 0) chroma_lines = ((inarea.height/2 -1) /2); else chroma_lines = inarea.height /4; i=0; while ( i < chroma_lines) { copy_offset_pix = ((horz/2) * (inarea.voffset/2 + inarea.height/2) + inarea.hoffset/2); for (j = 0; j < (copy_pixel/2); j++) { memcpy(temp_pix_cb,(plane_cb+copy_offset_pix+(j*horz)),(inarea.width/2)); memcpy((plane_cb+offset_pix), temp_pix_cb, (inarea.width/2)); memcpy(temp_pix_cr,(plane_cr+copy_offset_pix+(j*horz)),(inarea.width/2)); memcpy((plane_cr+offset_pix), temp_pix_cr, (inarea.width/2)); offset_pix += (horz/2); } i += (copy_pixel/2); /* we copy more lines in one step */ } while ( i < (inarea.height/2)) { copy_offset_pix = ((horz/2) * (inarea.voffset/2 + inarea.height/2) + inarea.hoffset/2); for (j = 0; j < (copy_pixel/2); j++) { memcpy(temp_pix_cb,(plane_cb+copy_offset_pix+(j*horz)),(inarea.width/2)); memcpy((plane_cb+offset_pix), temp_pix_cb, (inarea.width/2)); memcpy(temp_pix_cr,(plane_cr+copy_offset_pix+(j*horz)),(inarea.width/2)); memcpy((plane_cr+offset_pix), temp_pix_cr, (inarea.width/2)); offset_pix += (horz/2); } i += (copy_pixel/2); /* we copy more lines in one step */ } free(temp_pix_l); temp_pix_l = NULL; free(temp_pix_cb); temp_pix_cb = NULL; free(temp_pix_cr); temp_pix_cr = NULL; } /** Here we set a n x n area to a average color */ void average_block(int go_h, int go_w, int horz, int plane, int *orig_offset, uint8_t *frame[]) { unsigned char *temp_pix; int i, j, summe, offset_pix; temp_pix = (unsigned char*)malloc(1); *temp_pix=0; offset_pix = *orig_offset; summe = 0; for ( i=0; i < go_h; i++) { for (j=0; j < go_w; j++) { memcpy(temp_pix,(frame[plane]+offset_pix),1); summe += (int)*temp_pix; offset_pix++; } offset_pix += horz - j; } *temp_pix = (unsigned char)(summe / (go_h * go_w)); offset_pix = *orig_offset; for (i = 0; i < go_h; i++) { for (j = 0; j < go_w; j++) memcpy((frame[plane]+offset_pix+j), temp_pix, 1); offset_pix += horz; } free(temp_pix); temp_pix=NULL; } /** Here we average the area */ void average_area(struct area_s inarea, int horz, int vert, uint8_t *frame[], int average_pixel) { int orig_offset, sub_offset, plane; int go_w, go_h, togo_w, togo_h; orig_offset = (horz* inarea.voffset) + inarea.hoffset; sub_offset = ((horz/2) * (inarea.voffset/2)) + (inarea.hoffset/2); go_w = average_pixel; go_h = average_pixel; togo_w = inarea.width - go_w ; /* we decrease here one block, else we */ togo_h = inarea.height - go_h; /* that solves a problem in the while */ plane = 0; /* here we set that we wnat to use the first plane of the frame */ while ( go_h != 0 ) { while ( go_w != 0) { average_block(go_h, go_w, horz, plane, &orig_offset, frame); average_block(go_h/2, go_w/2, horz/2, plane+1, &sub_offset, frame); average_block(go_h/2, go_w/2, horz/2, plane+2, &sub_offset, frame); orig_offset += go_w; sub_offset += go_w/2; if ( (togo_w - go_w) >= 0 ) togo_w -= go_w; /* normal decrease of the square horicontal*/ else if (togo_w != 0) { go_w = togo_w; /* the last few pixels */ togo_w = 0; } else go_w = 0; /* this row finished averaging the pixels */ } /* Here we go to the next row we have to average,first line+ (width-1line) */ orig_offset = orig_offset+ (horz -inarea.width) + (horz *(average_pixel -1)); sub_offset = sub_offset+ ((horz/2) - (inarea.width/2) + ((horz/2) *(average_pixel/2) -1)); /* we also have to reset the go_w variable, that cost me hours .... */ go_w = average_pixel; togo_w = inarea.width - average_pixel ; if ( (togo_h - go_h) >= 0 ) togo_h -= go_h; /* normal decrease of the square vertical */ else if (togo_h != 0) { go_h = togo_h; /* the last few pixels */ togo_h = 0; } else go_h = 0; /* this field finished averaging the pixels */ } } /** Here we set the area darker, only touching luma */ void set_darker(struct area_s inarea, int horz, int vert, uint8_t *frame[], int darker) { int i, n, hoffset_pix; uint8_t *plane_l; unsigned char *temp_pix; unsigned char *pix; float dark; dark = 1 - (darker* 0.01); temp_pix = (unsigned char *)malloc(1); pix = (unsigned char *)malloc(1); *temp_pix=0; *pix=0; /* First we do the luma */ plane_l = frame[0]; hoffset_pix = (horz * inarea.voffset) + inarea.hoffset; for (i = 0; i < inarea.height; i++) { for (n = 0; n < inarea.width; n++) { memcpy( temp_pix, (plane_l+hoffset_pix), 1); *pix = 16 + (int)((*temp_pix - 16) * dark); if (*pix < 16 ) /* We take care that we don't produce values */ *pix = 16; /* which should not be used */ memset( (plane_l + hoffset_pix), *pix, 1); hoffset_pix++; } hoffset_pix += (horz - inarea.width) ; } /* And then the Cr and Cb */ plane_l = frame[1]; hoffset_pix = ((horz/2) * (inarea.voffset/2)) + (inarea.hoffset/2); for (i = 0; i < (inarea.height/2); i++) { for (n = 0; n < (inarea.width/2); n++) { memcpy( temp_pix, (plane_l+hoffset_pix), 1); *pix = 128 + (int)((*temp_pix - 128) * dark); memset( (plane_l + hoffset_pix), *pix, 1); hoffset_pix++; } hoffset_pix += ((horz - inarea.width) /2) ; } plane_l = frame[2]; hoffset_pix = ((horz/2) * (inarea.voffset/2)) + (inarea.hoffset/2); for (i = 0; i < (inarea.height/2); i++) { for (n = 0; n < (inarea.width/2); n++) { memcpy( temp_pix, (plane_l+hoffset_pix), 1); *pix = 128 + (int)((*temp_pix - 128) * dark); memset( (plane_l + hoffset_pix), *pix, 1); hoffset_pix++; } hoffset_pix += ((horz - inarea.width) /2) ; } free(temp_pix); temp_pix=NULL; free(pix); pix=NULL; } /** Here is the first stage of setting the stream to black */ void set_inactive(struct area_s inarea, int horz, int vert, uint8_t *frame[], struct color_yuv *coloryuv) { int i, hoffset_pix; uint8_t *plane_l, *plane_cb, *plane_cr; plane_l = frame[0]; plane_cb= frame[1]; plane_cr= frame[2]; /* Number of pixels for the luma */ hoffset_pix = (horz * inarea.voffset) + inarea.hoffset; for (i = 0; i < inarea.height; i++) /* Setting the Luma */ { memset( (plane_l + hoffset_pix), (*coloryuv).luma , (inarea.width) ); hoffset_pix += horz; } /* Number of pixels chroma */ hoffset_pix = ((horz / 2) * (inarea.voffset/2) ) + (inarea.hoffset / 2 ); for (i = 0; i < (inarea.height/2); i++) /*Setting the chroma */ { memset( (plane_cb + hoffset_pix), (*coloryuv).chroma_b, (inarea.width/2) ); memset( (plane_cr + hoffset_pix), (*coloryuv).chroma_r, (inarea.width/2) ); hoffset_pix += (horz/2); } } /** MAIN */ int main( int argc, char **argv) { int i, frame_count; int horz, vert; /* width and height of the frame */ uint8_t *frame[3]; /*pointer to the 3 color planes of the input frame */ struct area_s inarea; struct color_yuv coloryuv; int input_fd = 0; /* std in */ int output_fd = 1; /* std out */ int darker = 0; /* how much darker should the image be */ int copy_pixel = 0; /* how much pixels we should use for filling up the area */ int average_pixel = 0; /* how much pixel to use for average */ y4m_stream_info_t istream, ostream; y4m_frame_info_t iframe; inarea.width=0; inarea.height=0; inarea.voffset=0; inarea.hoffset=0; coloryuv.luma = LUMA; /*Setting the luma to black */ coloryuv.chroma_b = CHROMA; /*Setting the chroma to center, means white */ coloryuv.chroma_r = CHROMA; /*Setting the chroma to center, means white */ (void)mjpeg_default_handler_verbosity(verbose); /* processing commandline */ process_commandline(argc, argv, &inarea, &darker, ©_pixel, &coloryuv, &average_pixel); y4m_init_stream_info(&istream); y4m_init_stream_info(&ostream); y4m_init_frame_info(&iframe); /* First read the header of the y4m stream */ i = y4m_read_stream_header(input_fd, &istream); if ( i != Y4M_OK) /* a basic check if we really have y4m stream */ mjpeg_error_exit1("Input stream error: %s", y4m_strerr(i)); else { /* Here we copy the input stream info to the output stream info header */ y4m_copy_stream_info(&ostream, &istream); /* Here we write the new output header to the output fd */ y4m_write_stream_header(output_fd, &ostream); horz = y4m_si_get_width(&istream); /* get the width of the frame */ vert = y4m_si_get_height(&istream); /* get the height of the frame */ if ( (inarea.width + inarea.hoffset) > horz) mjpeg_error_exit1("Input width and offset larger than framewidth,exit"); if ( (inarea.height + inarea.voffset) > vert) mjpeg_error_exit1("Input height and offset larger than frameheight,exit"); /* Here we allocate the memory for on frame */ frame[0] = malloc( horz * vert ); frame[1] = malloc( (horz/2) * (vert/2) ); frame[2] = malloc( (horz/2) * (vert/2) ); /* Here we set the initial number of of frames */ /* We do not need it. Just for showing that is does something */ frame_count = 0 ; /* This is the main loop here can filters effects, scaling and so on be done with the video frames. Just up to your mind */ /* We read now a single frame with the header and check if it does not have any problems or we have alreaddy processed the last without data */ while(y4m_read_frame(input_fd, &istream, &iframe, frame) == Y4M_OK) { frame_count++; /* You can do something usefull here */ if (darker != 0) set_darker(inarea, horz, vert, frame, darker); else if (copy_pixel != 0) copy_area(inarea, horz, vert, frame, copy_pixel); else if (average_pixel != 0) average_area(inarea, horz, vert, frame, average_pixel); else set_inactive(inarea, horz, vert, frame, &coloryuv); /* Now we put out the read frame */ y4m_write_frame(output_fd, &ostream, &iframe, frame); } /* Cleaning up the data structures */ y4m_fini_stream_info(&istream); y4m_fini_stream_info(&ostream); y4m_fini_frame_info(&iframe); } /* giving back the memory to the system */ free(frame[0]); frame[0] = 0; free(frame[1]); frame[1] = 0; free(frame[2]); frame[2] = 0; exit(0); /* exiting */ } mjpegtools-2.1.0/lavtools/lav2wav.c0000644000175000017500000002423710535406460017615 0ustar glowwormglowworm/* * * lav2wav.c * * Copyright (C) 2000 MSSG, Rainer Johanni, Aaron Holtzman, Andrew Stevens * * This file is part of lav2wav,a component of the "MJPEG tools" * suite of open source tools for MJPEG and MPEG processing. * * lav2wav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * lav2wav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Make; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include "lav_io.h" #include "editlist.h" #include "mjpeg_logging.h" struct wave_header wave; static uint8_t audio_buff[2*256*1024]; /* Enough for 1fps, 48kHz ... */ int verbose = 1; int big_endian; /* The endian detection */ int silence_sr, silence_bs, silence_ch ; EditList el; void set_silence (char *); int wav_header(unsigned int bits, unsigned int rate, unsigned int channels, int fd); void Usage(char *str); /* Raw write does *not* guarantee to write the entire buffer load if it becomes possible to do so. This does... */ static size_t do_write( int fd, void *buf, size_t count ) { char *cbuf = buf; size_t count_left = count; size_t written; while( count_left > 0 ) { written = write( fd, cbuf, count_left ); if( written < 0 ) return count-count_left; count_left -= written; cbuf += written; } return count; } int wav_header( unsigned int bits, unsigned int rate, unsigned int channels, int fd ) { uint16_t temp_16; /* temp variables for swapping the bytes */ uint32_t temp_32; /* temp variables for swapping the bytes */ uint32_t dummy_size = 0x7fffff00+sizeof(wave); /* Write out a ZEROD wave header first */ memset(&wave, 0, sizeof(wave)); strncpy((char*)wave.riff.id, "RIFF", 4); strncpy((char*)wave.riff.wave_id, "WAVE",4); dummy_size -=8; wave.riff.len = reorder_32(dummy_size, big_endian); strncpy((char*)wave.format.id, "fmt ",4); wave.format.len = reorder_32((uint32_t)sizeof(struct common_struct), big_endian); /* Store information */ if (big_endian == 0) { wave.common.wFormatTag = WAVE_FORMAT_PCM; wave.common.wChannels = channels; wave.common.dwSamplesPerSec = rate; wave.common.dwAvgBytesPerSec = channels*rate*bits/8; wave.common.wBlockAlign = channels*bits/8; wave.common.wBitsPerSample = bits; } else /* We have a big endian machine and have to swap the bytes */ { temp_16 = WAVE_FORMAT_PCM; swab(&temp_16, &wave.common.wFormatTag,2); temp_16 = channels; swab(&temp_16, &wave.common.wChannels, 2); temp_32 = rate; wave.common.dwSamplesPerSec = reorder_32 (temp_32, big_endian); temp_32 = channels*rate*bits/8; wave.common.dwAvgBytesPerSec = reorder_32 (temp_32, big_endian); temp_16 = channels*bits/8; swab(&temp_16, &wave.common.wBlockAlign, 2); temp_16 = bits; swab(&temp_16, &wave.common.wBitsPerSample, 2); } strncpy((char*)wave.data.id, "data",4); dummy_size -= 20+sizeof(struct common_struct); wave.data.len = reorder_32 (dummy_size, big_endian); if (do_write(fd, &wave, sizeof(wave)) != sizeof(wave)) return 1; return 0; } static void wav_close(int fd) { unsigned int size; /* Find how long our file is in total, including header */ size = lseek(fd, 0, SEEK_CUR); if (size < 0 ) { if( fd > 2 ) mjpeg_error("lseek failed - wav-header is corrupt"); goto EXIT; } /* Rewind file */ if (lseek(fd, 0, SEEK_SET) < 0) { mjpeg_error("rewind failed - wav-header is corrupt"); goto EXIT; } mjpeg_debug("Writing WAV header"); /* Fill out our wav-header with some information. */ size -= 8; wave.riff.len = reorder_32 ((uint32_t)size, big_endian); size -= 20+sizeof(struct common_struct); wave.data.len = reorder_32 ((uint32_t)size, big_endian); if (do_write(fd, &wave, sizeof(wave)) < sizeof(wave)) { mjpeg_error("wav-header write failed -- file is corrupt"); goto EXIT; } mjpeg_info("WAV done"); EXIT: close(fd); } /* The typical help output */ void Usage(char *str) { fprintf(stderr, "Usage: %s [options] inputfiles\n",str); fprintf(stderr, "where options are:\n"); fprintf(stderr, "-o num Start extracting at video frame (num)\n"); fprintf(stderr, "-f num Extract (num) frames of audio\n"); fprintf(stderr, "-s/-c Backwards compatibility options for -o/-f\n"); fprintf(stderr, "-v num verbose level [0..2]\n"); fprintf(stderr, "-I Ignore unsupported bitrates/bits per sample\n"); fprintf(stderr, "-r sr,bs,ch If the file does not contain any sound generate silence\n"); fprintf(stderr, " sr samplerate 32000,44100,48000 bs bytesize 8,16, ch channes 1/2\n"); fprintf(stderr, "-R The same as -r but now a silence with 44100, 16, 2 is created\n"); exit(0); } /* Setting the type of silence, samplerate, bitesize, chanels */ void set_silence (char *optarg) { unsigned int u1, u2, u3; int i; i = (sscanf (optarg, "%i,%i,%i", &u1, &u2, &u3)); if (i != 3) mjpeg_error_exit1("Wrong number of arguments given to the -r option"); else /*Setting user chosen values */ { if ( (u1 == 32000) || (u1 == 44100) || (u1 == 48000) ) silence_sr = u1; else mjpeg_error_exit1("Wrong sampelrate use: 32000,44100,48000, exiting"); if ( (u2 == 8) || (u2 == 16) ) silence_bs = u2; else mjpeg_error_exit1("Wrong audio bitsize use 8 or 16, exiting"); if ( (u3 == 1) || (u3 == 2) ) silence_ch = u3; else mjpeg_error_exit1("Wrong number of chanels use 1 or 2, exiting"); } mjpeg_info("Setting silence to %i sampelrate, %i bitsize, %i chanels", silence_sr, silence_bs, silence_ch); } int main(argc, argv) int argc; char **argv; { int n,f,i; int res; int warned = 0; int start_frame = 0; int num_frames = -1; int ignore_bitrate = 0; int fragments; silence_sr=0; /* silence_sr is use for detecting if the -r option is used */ silence_bs=0; silence_ch=0; while( (n=getopt(argc,argv,"v:s:r:Rc:o:f:I")) != EOF) { switch(n) { case 'v': verbose = atoi(optarg); if( verbose < 0 || verbose > 2 ) Usage(argv[0]); break; case 'o': case 's': start_frame = atoi(optarg); break; case 'r': set_silence(optarg); break; case 'R': silence_sr=44100; silence_bs=16; silence_ch=2; break; case 'f': case 'c': num_frames = atoi(optarg); break; case 'I': ignore_bitrate = 1; break; case '?': Usage(argv[0]); } } big_endian = lav_detect_endian(); if (big_endian < 0) exit(1); /* Open editlist */ if( argc-optind < 1) Usage(argv[0]); (void)mjpeg_default_handler_verbosity(verbose); read_video_files(argv + optind, argc - optind, &el,0); if(!el.has_audio) { if (silence_sr == 0) mjpeg_error_exit1("Input file(s) have no audio, use -r to generate silence"); else { mjpeg_info("mjpeg_framerate %f ", el.video_fps); /* Create wav header (skeleton) on stdout ... */ /* audio_bits, audio_rate, audio_chans */ wav_header( silence_bs, silence_sr, silence_ch, 1); /* skip to the start frame if specified */ f = 0; if (start_frame != 0) f = start_frame; /* num_frames = -1, read em all, else read specified # */ if ( num_frames == -1) num_frames = el.video_frames; fragments = silence_sr / el.video_fps; /* Here is a dirty hack for the number of fragments we put out I dont know a other way how to put out a certain number of \x00 So we put always 4bytes of 00h out and reduce the number of fragments. Works perfect for PAL framerate. But in NTSC there is a round problem. At 44k1Hz, 16bs 2ch 0,47 samples/frame That means that we have on second offset per hour of film */ if (silence_bs == 8) fragments = fragments / 2; if (silence_ch == 1) fragments = fragments / 2; /* Stream out audio wav-style... in per-frame chunks */ for( ; f < num_frames; ++f ) { for ( i = 0; i < fragments ; i++) do_write (1, "\x0000000", 4); } wav_close(1); exit(0); } } if (!ignore_bitrate) { if (el.audio_bits!=16) mjpeg_error_exit1("Input file(s) must have 16 bit audio!"); switch (el.audio_rate) { case 48000 : case 44100 : case 32000 : break; default: mjpeg_error_exit1("Audio rate is %ld Hz - must be 32000, 44100 or 48000!", el.audio_rate); } } switch (el.audio_chans) { case 1: case 2: break; default: mjpeg_error_exit1("Audio channels %d not allowed",el.audio_chans); } /* Create wav header (skeleton) on stdout ... */ wav_header( el.audio_bits, el.audio_rate, el.audio_chans, 1); /* skip to the start frame if specified */ f = 0; if (start_frame != 0) f = start_frame; /* num_frames = -1, read em all, else read specified # */ if ( num_frames == -1) num_frames = el.video_frames; /* Stream out audio wav-style... in per-frame chunks */ for( ; f < num_frames; ++f ) { n = el_get_audio_data(audio_buff, f, &el, 0); if (n < 0) mjpeg_error_exit1( "Couldn't get audio for frame %d!", f); if( n != 0 ) { res = do_write( 1, audio_buff, n ); if (res != n) mjpeg_error_exit1("Couldn't write audio for frame %d!",f); } else if( f < num_frames && ! warned ) { mjpeg_warn("audio ends early at frame %d", f); warned = 1; } } wav_close(1); exit(0); } mjpegtools-2.1.0/lavtools/liblavplay.h0000644000175000017500000001717310473473053020403 0ustar glowwormglowworm/* * liblavplay - a librarified Linux Audio Video PLAYback * * Copyright (C) 2000 Rainer Johanni * Extended by: Gernot Ziegler * Ronald Bultje * & many others * * A library for playing back MJPEG video via software MJPEG * decompression (using SDL) or via hardware MJPEG video * devices such as the Pinnacle/Miro DC10(+), Iomega Buz, * the Linux Media Labs LML33, the Matrox Marvel G200, * Matrox Marvel G400 and the Rainbow Runner G-series. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include enum { LAVPLAY_MSG_ERROR = 0, LAVPLAY_MSG_WARNING = 1, LAVPLAY_MSG_INFO = 2, LAVPLAY_MSG_DEBUG = 3 }; enum { LAVPLAY_STATE_STOP = 0, /* uninitialized state */ LAVPLAY_STATE_PAUSED = 1, /* also known as: speed = 0 */ LAVPLAY_STATE_PLAYING = 2 /* speed != 0 */ }; typedef struct { int stats_changed; /* has anything bad happened? */ unsigned int frame; /* current frame which is being played back */ unsigned int num_corrs_a; /* Number of corrections because video ahead audio */ unsigned int num_corrs_b; /* Number of corrections because video behind audio */ unsigned int num_aerr; /* Number of audio buffers in error */ unsigned int num_asamps; unsigned int nsync; /* Number of syncs */ unsigned int nqueue; /* Number of frames queued */ int play_speed; /* current playback speed */ int audio; /* whether audio is currently turned on */ int norm; /* [0-2] playback norm: 0 = PAL, 1 = NTSC, 2 = SECAM */ double tdiff; /* video/audio time difference (sync debug purposes) */ } video_playback_stats; typedef struct { char playback_mode; /* [HSC] H = hardware/on-screen, C = hardware/on-card, S = software (SDL) */ int horizontal_offset; /* Horizontal offset of the video when using hardware playback */ int vertical_offset; /* Vertical offset of the video when using hardware playback */ int exchange_fields; /* [0-1] whether to exchange the fields (for interlaced video) */ int zoom_to_fit; /* [0-1] zooms video to fit the screen as good as possible */ int flicker_reduction; /* [0-1] whether to use flicker reduction */ int sdl_width; /* width of the SDL playback window in case of software playback */ int sdl_height; /* height of the SDL playback window in case of software playback */ int soft_full_screen; /* [0-1] set software-driven full-screen/screen-output, 1 = yes, 0 = no */ int vw_x_offset; /* onscreen hardware playback video window X offset */ int vw_y_offset; /* onscreen hardware playback video window Y offset */ const char *video_dev; /* the video device */ const char *display; /* the X-display (only important for -H) */ int audio; /* When play audio, 0:never, or sum of 1:forward, 2:reverse, 4:fast, 8:pause */ int use_write; /* whether to use "write" (1) or mmap (0) for audio playback */ const char *audio_dev; /* the audio device */ int continuous; /* [0-1] 0 = quit when the video has been played, 1 = continue cycle */ int sync_correction; /* [0-1] Whether to enable sync correction, 0 = no, 1 = yes */ int sync_skip_frames; /* [0-1] If video is behind audio: 1 = skip video, 0 = insert audio */ int sync_ins_frames; /* [0-1] If video is ahead of audio: 1 = insert video, 0 = skip audio */ int MJPG_numbufs; /* Number of MJPEG-buffers */ int preserve_pathnames; /* [0-1] Don't canonicalise pathnames * when creating edit lists */ EditList *editlist; /* the main editlist */ void (*output_statistics)(video_playback_stats *stats); /* speaks for itself */ void (*msg_callback)(int type, char* message); /* callback for error/info/warn messages */ void (*state_changed)(int new_state); /* changed state */ void (*get_video_frame)(uint8_t *buffer, int *len, long num); /* functions for manually submitting video/audio */ void (*get_audio_sample)(uint8_t *buff, int *samps, long num); /* functions for manually submitting video/audio */ void *settings; /* private info - don't touch :-) (type UNKNOWN) */ } lavplay_t; /* malloc the pointer and set default options */ lavplay_t *lavplay_malloc(void); /* the whole video-playback cycle */ int lavplay_main(lavplay_t *info); /* stop playing back (which also deinitializes everything) */ int lavplay_stop(lavplay_t *info); /* free info and quit if necessary */ int lavplay_free(lavplay_t *info); /* Wait until playback is finished */ void lavplay_busy(lavplay_t *info); /*** Methods for searching through the video stream ***/ /* go to a specific frame, if framenum<0, then it's 'total_frames - framenum' */ int lavplay_set_frame(lavplay_t *info, long framenum); /* increase (numframes>0) or decrease (numframes<0) a number of frames */ int lavplay_increase_frame(lavplay_t *info, long numframes); /* set the playback speed, if speed<0, then we're playing backwards */ int lavplay_set_speed(lavplay_t *info, int speed); /*** Methods for simple video editing (cut/paste) ***/ /* cut a number of frames into a buffer */ int lavplay_edit_cut(lavplay_t *info, long start, long end); /* copy a number of frames into a buffer */ int lavplay_edit_copy(lavplay_t *info, long start, long end); /* paste frames from the buffer into a certain position */ int lavplay_edit_paste(lavplay_t *info, long destination); /* add a number of frames from a new movie to a certain position in the current movie */ int lavplay_edit_addmovie(lavplay_t *info, char *movie, long start, long end, long destination); /* move a number of frames to a different position */ int lavplay_edit_move(lavplay_t *info, long start, long end, long destination); /* delete a number of frames from the current movie */ int lavplay_edit_delete(lavplay_t *info, long start, long end); /* set the part of the movie that will actually be played, start<0 means whole movie */ int lavplay_edit_set_playable(lavplay_t *info, long start, long end); /*** Control sound during video playback */ /* mutes or unmutes audio (1 = on, 0 = off) */ int lavplay_toggle_audio(lavplay_t *info, int audio); /*** Methods for saving the currently played movie to editlists or open new movies */ /* save a certain range of frames to an editlist */ int lavplay_save_selection(lavplay_t *info, char *filename, long start, long end); /* save the whole current movie to an editlist */ int lavplay_save_all(lavplay_t *info, char *filename); /* open a new (series of) movie */ int lavplay_open(lavplay_t *info, char **files, int num_files); mjpegtools-2.1.0/lavtools/audiolib.h0000644000175000017500000000235710473473053020032 0ustar glowwormglowworm/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __AUDIOLIB_H__ #define __AUDIOLIB_H__ #include void audio_shutdown(void); int audio_init(int a_read, int use_read_write, int a_stereo, int a_size, int a_rate); long audio_get_buffer_size(void); void audio_get_output_status(struct timeval *tmstmp, unsigned int *nb_out, unsigned int *nb_err); int audio_read( uint8_t *buf, int size, int swap, struct timeval *tmstmp, int *status); int audio_write( uint8_t *buf, int size, int swap); void audio_start(void); char *audio_strerror(void); #endif /* __AUDIOLIB_H__ */ mjpegtools-2.1.0/lavtools/jpegutils.h0000644000175000017500000000476210320011152020225 0ustar glowwormglowworm/* * jpegutils.h: Some Utility programs for dealing with * JPEG encoded images * * Copyright (C) 1999 Rainer Johanni * Copyright (C) 2001 pHilipp Zabel * * based on jdatasrc.c and jdatadst.c from the Independent * JPEG Group's software by Thomas G. Lane * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __JPEGUTILS_H__ #define __JPEGUTILS_H__ /* * jpeg_data: buffer with input / output jpeg * len: Length of jpeg buffer * itype: Y4M_ILACE_NONE: Not interlaced * Y4M_ILACE_TOP_FIRST: Interlaced, top-field-first * Y4M_ILACE_BOTTOM_FIRST: Interlaced, bottom-field-first * ctype Chroma format for decompression. * Currently always 420 and hence ignored. * raw0 buffer with input / output raw Y channel * raw1 buffer with input / output raw U/Cb channel * raw2 buffer with input / output raw V/Cr channel * width width of Y channel (width of U/V is width/2) * height height of Y channel (height of U/V is height/2) */ int decode_jpeg_raw (unsigned char *jpeg_data, int len, int itype, int ctype, int width, int height, unsigned char *raw0, unsigned char *raw1, unsigned char *raw2); int decode_jpeg_gray_raw (unsigned char *jpeg_data, int len, int itype, int ctype, int width, int height, unsigned char *raw0, unsigned char *raw1, unsigned char *raw2); int encode_jpeg_raw (unsigned char *jpeg_data, int len, int quality, int itype, int ctype, int width, int height, unsigned char *raw0, unsigned char *raw1, unsigned char *raw2); /* void jpeg_skip_ff (j_decompress_ptr cinfo); */ #endif mjpegtools-2.1.0/lavtools/colorspace.c0000644000175000017500000002211510161334555020356 0ustar glowwormglowworm/* * colorspace.c: Routines to perform colorspace conversions. * * * Copyright (C) 2001 Matthew J. Marjanovic * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include "colorspace.h" #define FP_BITS 18 /* precomputed tables */ static int Y_R[256]; static int Y_G[256]; static int Y_B[256]; static int Cb_R[256]; static int Cb_G[256]; static int Cb_B[256]; static int Cr_R[256]; static int Cr_G[256]; static int Cr_B[256]; static int conv_RY_inited = 0; static int RGB_Y[256]; static int R_Cr[256]; static int G_Cb[256]; static int G_Cr[256]; static int B_Cb[256]; static int conv_YR_inited = 0; static int myround(double n) { if (n >= 0) return (int)(n + 0.5); else return (int)(n - 0.5); } static void init_RGB_to_YCbCr_tables(void) { int i; /* * Q_Z[i] = (coefficient * i * * (Q-excursion) / (Z-excursion) * fixed-point-factor) * * to one of each, add the following: * + (fixed-point-factor / 2) --- for rounding later * + (Q-offset * fixed-point-factor) --- to add the offset * */ for (i = 0; i < 256; i++) { Y_R[i] = myround(0.299 * (double)i * 219.0 / 255.0 * (double)(1< [Y', Cb, Cr] * */ void convert_RGB_to_YCbCr(uint8_t *planes[], int length) { uint8_t *Y, *Cb, *Cr; int i; if (!conv_RY_inited) init_RGB_to_YCbCr_tables(); for ( i = 0, Y = planes[0], Cb = planes[1], Cr = planes[2]; i < length; i++, Y++, Cb++, Cr++ ) { int r = *Y; int g = *Cb; int b = *Cr; *Y = (Y_R[r] + Y_G[g]+ Y_B[b]) >> FP_BITS; *Cb = (Cb_R[r] + Cb_G[g]+ Cb_B[b]) >> FP_BITS; *Cr = (Cr_R[r] + Cr_G[g]+ Cr_B[b]) >> FP_BITS; } } /* * in-place conversion [Y', Cb, Cr] --> [R', G', B'] * */ void convert_YCbCr_to_RGB(uint8_t *planes[], int length) { uint8_t *R, *G, *B; int i; if (!conv_YR_inited) init_YCbCr_to_RGB_tables(); for ( i = 0, R = planes[0], G = planes[1], B = planes[2]; i < length; i++, R++, G++, B++ ) { int y = *R; int cb = *G; int cr = *B; int r = (RGB_Y[y] + R_Cr[cr]) >> FP_BITS; int g = (RGB_Y[y] + G_Cb[cb]+ G_Cr[cr]) >> FP_BITS; int b = (RGB_Y[y] + B_Cb[cb]) >> FP_BITS; *R = (r < 0) ? 0 : (r > 255) ? 255 : r ; *G = (g < 0) ? 0 : (g > 255) ? 255 : g ; *B = (b < 0) ? 0 : (b > 255) ? 255 : b ; } } static uint8_t Y219_255[256]; static int conv_Y219_Y255_inited = 0; static uint8_t Y255_219[256]; static int conv_Y255_Y219_inited = 0; static void init_Y255_to_Y219_tables(void) { int i; for (i = 0; i < 256; i++) Y255_219[i] = myround((double)i * 219.0 / 255.0) + 16; conv_Y255_Y219_inited = 1; } static void init_Y219_to_Y255_tables(void) { int i = 0; for ( ; i < 16; i++) Y219_255[i] = 0; for ( ; i < 236; i++) Y219_255[i] = myround((double)(i-16) * 255.0 / 219.0); for ( ; i < 256; i++) Y219_255[i] = 255; conv_Y219_Y255_inited = 1; } void convert_Y255_to_Y219(uint8_t *plane, int length) { if (!conv_Y255_Y219_inited) init_Y255_to_Y219_tables(); while (length > 0) { *plane = Y255_219[*plane]; plane++; length--; } } void convert_Y219_to_Y255(uint8_t *plane, int length) { if (!conv_Y219_Y255_inited) init_Y219_to_Y255_tables(); while (length > 0) { *plane = Y219_255[*plane]; plane++; length--; } } #if 0 /* This stuff ain't ready for prime-time yet, mostly because I haven't figured out if JPEG Y' is scaled to 255, or clipped to 255... - Matto */ static uint8_t JPEG_TO_R601_Y[256]; static uint8_t JPEG_TO_R601_C[256]; static uint8_t R601_TO_JPEG_Y[256]; static uint8_t R601_TO_JPEG_C[256]; static int conv_YJR_inited = 0; static int conv_YRJ_inited = 0; #define CONVERT_Y 1 #define CONVERT_CB 2 #define CONVERT_CR 3 static void init_YCbCr_JPEG_to_Rec601_tables() { int i; for (i = 0; i < 255; i++) { JPEG_TO_R601_Y[i] = i * 219.0 / 256.0 + 16; JPEG_TO_R601_C[i] = (i - 128) * 224.0 / 256.0 + 128; } } static void init_YCbCr_Rec601_to_JPEG_tables() { int i; for (i = 0; i < 255; i++) { R601_TO_JPEG_Y[i] = (i - 16) / 219.0 * 256.0; R601_TO_JPEG_C[i] = (i - 128) / 224.0 * 256.0 + 128; } } /* * in-place conversion JPEG [Y', Cb, Cr] --> CCIR-601 [Y', Cb, Cr] * */ void convert_YCbCr_JPEG_to_Rec601(int plane_type, uint8_t data[], int length) { int i; if (!conv_YJR_inited) init_YCbCr_JPEG_to_Rec601_tables(); switch (plane_type) { case CONVERT_Y: for (i = 0; i < length; i++, data++) { *data = JPEG_TO_R601_Y[*data]; } break; case CONVERT_CB: case CONVERT_CR: for (i = 0; i < length; i++, data++) { *data = JPEG_TO_R601_C[*data]; } break; } } /* * in-place conversion JPEG [Y', Cb, Cr] --> CCIR-601 [Y', Cb, Cr] * */ void convert_YCbCr_Rec601_to_JPEG(int plane_type, uint8_t data[], int length) { int i; if (!conv_YRJ_inited) init_YCbCr_Rec601_to_JPEG_tables(); switch (plane_type) { case CONVERT_Y: for (i = 0; i < length; i++, data++) { *data = R601_TO_JPEG_Y[*data]; } break; case CONVERT_CB: case CONVERT_CR: for (i = 0; i < length; i++, data++) { *data = R601_TO_JPEG_C[*data]; } break; } } #endif mjpegtools-2.1.0/lavtools/lavplay.c0000644000175000017500000004666011344710442017704 0ustar glowwormglowworm/* * lavplay - Linux Audio Video PLAYback * * Copyright (C) 2000 Rainer Johanni * Extended by: Gernot Ziegler * Ronald Bultje * & many others * * Plays back MJPEG AVI or Quicktime files using the * hardware of the zoran card or using SDL (software playback) * * Usage: lavplay [options] filename [filename ...] * where options are as follows: * * -H/--H-offset num --- Horizontal offset * * -V/--V-offset num --- Vertical offset * You may use that only for quarter resolution videos * unless you remove the following 4 lines of code in the BUZ driver: * * if(params->img_x <0) err0++; * if(params->img_y <0) err0++; * * and * * if(params->img_x + params->img_width > 720) err0++; * if(params->img_y + params->img_height > tvnorms[params->norm].Ha/2) err0++; * * These parameters are usefull for videos captured from other sources * which do not appear centered when played with the BUZ * * -a/--audio num --- When play audio, 0:never, or sum of * 1:forward * 2:reverse * 4:fast * 8:pause * (default 7:forward,reverse,fast) * * -s/--skip num --- skip num seconds before playing * * -c/--synchronization [01] --- Sync correction off/on (default on) * * -n/--mjpeg-buffers num --- Number of MJPEG buffers * normally no need to change the default * * -q/--no-quit --- Do NOT quit at end of video * * -g/--gui-mode --- GUI-mode, used by xlav and LVS to control video position * * -x/--exchange-fields --- Exchange fields of an interlaced video * * -z/--zoom --- "Zoom to fit flag" * If this flag is not set, the video is always displayed in origininal * resolution for interlaced input and in double height and width * for not interlaced input. The aspect ratio of the input file is maintained. * * If this flag is set, the program tries to zoom the video in order * to fill the screen as much as possible. The aspect ratio is NOT * maintained, ie. the zoom factors for horizontal and vertical directions * may be different. This might not always yield the results you want! * * -p/--playback [SHC] --- playback method * 'S': software playback (using SDL) * 'H': hardware playback directly on the monitor * 'C': hardware playback to the output of the card * For 'C', you need xawtv to see what you're playing * * --s-x-offset and --s-y-offset * Video window offset from top left corner when using onscreen video * playback (--playback=H). Default: centered * * Following the options, you may give a optional +p/+n parameter (for forcing * the use of PAL or NTSC) and the several AVI files, Quicktime files * or Edit Lists arbitrarily mixed (as long as all files have the same * paramters like width, height and so on). * * The format of an edit list file is as follows: * line 1: "LAV Edit List" * line 2: "PAL" or "NTSC" * line 3: Number of AVI/Quicktime files comprising the edit sequence * next lines: Filenames of AVI/Quicktime files * and then for every sequence * a line consisting of 3 numbers: file-number start-frame end-frame * * If you are a real command line hardliner, you may try to entering the following * commands during playing (normally used by xlav/LVS, just type the command and * press enter): * p Set playback speed, num may also be 0 (=pause) and negative (=reverse) * s Skip to frame * s+ frames forward * s- frames backward * + 1 frame forward (makes only sense when paused) * - 1 frame backward (makes only sense when paused) * q quit * em Move scene (arg1->arg2) to position (arg3) * eu/eo Cut (u) or Copy (o) scene (arg1->arg2) into memory * ep Paste selection into current position of video * ed Delete scene (arg1->arg2) from video * ea Add movie (arg1, be sure that it's mov/avi!!) * frame arg2-arg3 (if arg2=-1, whole movie) to position arg4 * es Set a lowest/highest possible frame (max/min = trimming) * om Open movie (arg1) frame arg2-arg3 (arg2=-1 means whole * movie). Watch out, this movie should have the same params * as the current open movie or weird things may happen!!! * wa Save current movie into edit list (arg1) * ws Save current selection into memory into edit list (arg1) * **** Environment variables *** * * Recognized environment variables * LAV_VIDEO_DEV: Name of video device (default: "/dev/video") * LAV_AUDIO_DEV: Name of audio device (default: "/dev/dsp") * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "liblavplay.h" #include "mjpeg_logging.h" #include #include #include #ifdef HAVE_GETOPT_H #include #endif #include #ifdef HAVE_SYS_STAT_H #include #endif #ifdef HAVE_SDL /* Seems that this is needed so MAC OS X is also happy */ #include #endif #define LAVPLAY_VSTR "lavplay" VERSION /* Expected version info */ static lavplay_t *info; static int verbose = 0; static int skip_seconds = 0; static int current_frame = 0; static int gui_mode = 0; static int exit_flag = 0; static void Usage(char *progname) { fprintf(stderr, "Usage: %s [options] [ ...]\n", progname); fprintf(stderr, "where options are:\n"); fprintf(stderr, " -H/--H-offset num Horizontal offset (for hardware playback)\n"); fprintf(stderr, " -V/--V-offset num Vertical offset (for hardware playback)\n"); fprintf(stderr, " -s/--skip num skip num seconds before playing\n"); fprintf(stderr, " -c/--synchronization [01] Sync correction off/on (default on)\n"); fprintf(stderr, " -n/--mjpeg-buffers num Number of MJPEG buffers\n"); fprintf(stderr, " -q/--no-quit Do NOT quit at end of video\n"); fprintf(stderr, " -g/--gui-mode GUI-mode (used by xlav and LVS)\n"); fprintf(stderr, " -x/--exchange-fields Exchange fields of an interlaced video\n"); fprintf(stderr, " -z/--zoom Zoom video to fill screen as much as possible\n"); fprintf(stderr, " -Z/--full-screen Switch to fullscreen\n"); fprintf(stderr, " -P/--preserve-pathnames Do not 'canonicalise' pathnames in editlists\n" ); fprintf(stderr, " -p/--playback [" #ifdef HAVE_SDL "S" #else " " #endif #ifdef HAVE_V4L "HC" #else " " #endif "] playback: " #ifdef HAVE_SDL "(S)oftware, " #endif #ifdef HAVE_V4L "(H)ardware (screen) or (C)ard" #endif "\n"); fprintf(stderr, " -a/--audio num When play audio, 0:never, or sum of\n"); fprintf(stderr, " 1:forward, 2:reverse, 4:fast, 8:pause (default: 7)\n"); fprintf(stderr, " -U/--use-write Use write instead of mmap for audio playback\n"); fprintf(stderr, " -F/--flicker Disable flicker reduction\n"); fprintf(stderr, " -S/--size NxN width X height for SDL (S) or video (H) window\n"); fprintf(stderr, " --s-x-offset num Video Window X offset from topleft corner\n"); fprintf(stderr, " --s-y-offset num Video Window Y offset from topleft corner\n"); fprintf(stderr, " --display :x.x The X-display to use (default: \':0.0\')\n"); fprintf(stderr, " -v/--verbose [012] verbosity\n"); exit(1); } static void SigHandler(int sig_num) { lavplay_stop(info); } static void input(int type, char *message) { switch (type) { case LAVPLAY_MSG_ERROR: mjpeg_error("%s", message); break; case LAVPLAY_MSG_WARNING: mjpeg_warn("%s", message); break; case LAVPLAY_MSG_INFO: mjpeg_info("%s", message); break; case LAVPLAY_MSG_DEBUG: mjpeg_debug("%s", message); break; } } static void stats(video_playback_stats *stats) { if (exit_flag) return; current_frame = stats->frame; if (gui_mode) { printf("@%g/%d/%ld/%d\n",info->editlist->video_fps,stats->frame, info->editlist->video_frames,stats->play_speed); } else { MPEG_timecode_t tc; mpeg_timecode(&tc, stats->frame, mpeg_framerate_code (mpeg_conform_framerate(info->editlist->video_fps)), info->editlist->video_fps); printf("%d:%2.2d:%2.2d.%2.2d (%6.6d/%6.6ld) - Speed: %c%d, Norm: %s, Diff: %f\r", tc.h, tc.m, tc.s, tc.f, stats->frame, info->editlist->video_frames, stats->play_speed>0?'+':(stats->play_speed<0?'-':' '), abs(stats->play_speed), stats->norm==1?"NTSC":"PAL", stats->tdiff); } fflush(stdout); } static void state_changed(int state) { if (state == LAVPLAY_STATE_STOP) exit_flag = 1; } static void process_input(char *buffer) { int arg1, arg2, arg3; char arg[256]; char *movie[1]; switch (buffer[0]) { case 'q': lavplay_stop(info); break; case '+': lavplay_increase_frame(info, 1); break; case '-': lavplay_increase_frame(info, -1); break; case 'a': lavplay_toggle_audio(info, atoi(buffer+1)); break; case 'p': lavplay_set_speed(info, atoi(buffer+1)); break; case 's': switch (buffer[1]) { case '-': lavplay_increase_frame(info, -atoi(buffer+2)); break; case '+': lavplay_increase_frame(info, atoi(buffer+2)); break; default: lavplay_set_frame(info, atoi(buffer+1)); break; } break; case 'e': switch (buffer[1]) { case 'o': sscanf(buffer+2, "%d %d", &arg1, &arg2); lavplay_edit_copy(info, arg1, arg2); break; case 'u': sscanf(buffer+2, "%d %d", &arg1, &arg2); lavplay_edit_cut(info, arg1, arg2); break; case 'p': lavplay_edit_paste(info, current_frame); break; case 'm': sscanf(buffer+2, "%d %d %d", &arg1, &arg2, &arg3); lavplay_edit_move(info, arg1, arg2, arg3); break; case 'a': sscanf(buffer+2, "%s %d %d %d", arg, &arg1, &arg2, &arg3); lavplay_edit_addmovie(info, arg, arg1, arg2, arg3); break; case 'd': sscanf(buffer+2, "%d %d", &arg1, &arg2); lavplay_edit_delete(info, arg1, arg2); break; case 's': sscanf(buffer+2, "%d %d", &arg1, &arg2); lavplay_edit_set_playable(info, arg1, arg2); break; } break; case 'o': movie[0] = buffer+2; lavplay_open(info, movie, 1); break; case 'w': switch (buffer[1]) { case 'a': sscanf(buffer+3, "%s", arg); lavplay_save_all(info, arg); break; case 's': sscanf(buffer+3, "%d %d %s", &arg1, &arg2, arg); lavplay_save_selection(info, arg, arg1, arg2); break; } break; } } static int set_option(const char *name, char *value) { /* return 1 means error, return 0 means okay */ int nerr = 0; if (strcmp(name, "verbose")==0 || strcmp(name, "v")==0) { verbose = atoi(optarg); } else if (strcmp(name, "audio")==0 || strcmp(name, "a")==0) { info->audio = atoi(optarg); } else if (strcmp(name, "use-write")==0 || strcmp(name, "U")==0) { info->use_write = 1; } else if (strcmp(name, "H-offset")==0 || strcmp(name, "H")==0) { info->horizontal_offset = atoi(optarg); } else if (strcmp(name, "V-offset")==0 || strcmp(name, "V")==0) { info->vertical_offset = atoi(optarg); } else if (strcmp(name, "skip")==0 || strcmp(name, "s")==0) { skip_seconds = atoi(optarg); if (skip_seconds<0) skip_seconds = 0; } else if (strcmp(name, "synchronization")==0 || strcmp(name, "c")==0) { info->sync_correction = atoi(optarg); } else if (strcmp(name, "mjpeg-buffers")==0 || strcmp(name, "n")==0) { info->MJPG_numbufs = atoi(optarg); if (info->MJPG_numbufs<4) info->MJPG_numbufs = 4; if (info->MJPG_numbufs>256) info->MJPG_numbufs = 256; } else if (strcmp(name, "no-quit")==0 || strcmp(name, "q")==0) { info->continuous = 1; } else if (strcmp(name, "exchange-fields")==0 || strcmp(name, "x")==0) { info->exchange_fields = 1; } else if (strcmp(name, "zoom")==0 || strcmp(name, "z")==0) { info->zoom_to_fit = 1; } else if (strcmp(name, "gui-mode")==0 || strcmp(name, "g")==0) { gui_mode = 1; } else if (strcmp(name, "full-screen")==0 || strcmp(name, "Z")==0) { info->soft_full_screen = 1; } else if( strcmp( name, "preserve-pathnames") == 0 || strcmp(name, "P")==0) { info->preserve_pathnames = 1; } else if (strcmp(name, "playback")==0 || strcmp(name, "p")==0) { switch (value[0]) { #ifdef HAVE_V4L case 'H': case 'C': #endif #ifdef HAVE_SDL case 'S': #endif info->playback_mode = value[0]; break; default: mjpeg_error("Unknown playback mode: \'%c\'", value[0]); nerr++; break; } } else if (strcmp(name, "size")==0 || strcmp(name, "S")==0) { if (sscanf(value, "%dx%d", &info->sdl_width, &info->sdl_height)!=2) { mjpeg_error( "--size parameter requires NxN argument"); nerr++; } } else if (strcmp(name, "flicker")==0 || strcmp(name, "F")==0) { info->flicker_reduction = 0; } else if (strcmp(name, "display")==0) { info->display = optarg; } else if (strcmp(name, "s-x-offset")==0) { info->vw_x_offset = atoi(optarg); } else if (strcmp(name, "s-y-offset")==0) { info->vw_y_offset = atoi(optarg); } else nerr++; /* unknown option - error */ return nerr; } static void check_command_line_options(int argc, char *argv[]) { int nerr,n,option_index=0; char option[2]; #ifdef HAVE_GETOPT_LONG /* getopt_long options */ static struct option long_options[]={ {"verbose" ,1,0,0}, /* -v/--verbose */ {"h-offset" ,1,0,0}, /* -H/--H-offset */ {"v-offset" ,1,0,0}, /* -V/--V-offset */ {"skip" ,1,0,0}, /* -s/--skip */ {"synchronization" ,1,0,0}, /* -c/--synchronization */ {"mjpeg-buffers" ,1,0,0}, /* -n/--mjpeg-buffers */ {"no-quit" ,0,0,0}, /* -q/--no-quit */ {"exchange-fields" ,0,0,0}, /* -x/--exchange-fields */ {"zoom" ,0,0,0}, /* -z/--zoom */ {"full-screen" ,0,0,0}, /* -Z/--full-screen */ {"preserve-pathnames" ,0,0,0}, /* -P/--preserve-pathnames */ {"playback" ,1,0,0}, /* -p/--playback [SHC] */ {"audio" ,1,0,0}, /* -a/--audio num */ {"use-write" ,0,0,0}, /* -U/--use-write */ {"gui-mode" ,1,0,0}, /* -g/--gui-mode */ {"size" ,1,0,0}, /* -S/--size */ {"flicker" ,0,0,0}, /* -F/--flicker */ {"display" ,1,0,0}, /* --display */ {"s-x-offset" ,1,0,0}, /* --s-x-offset */ {"s-y-offset" ,1,0,0}, /* --s-y-offset */ {0,0,0,0} }; #endif if(argc < 2) Usage(argv[0]); /* Get options */ nerr = 0; #ifdef HAVE_GETOPT_LONG while( (n=getopt_long(argc,argv,"S:a:v:H:V:s:c:n:t:qUZp:xrzgPF", long_options, &option_index)) != EOF) #else while( (n=getopt(argc,argv,"S:a:v:H:V:s:c:n:t:qUZp:xrzgPF")) != EOF) #endif { switch(n) { #ifdef HAVE_GETOPT_LONG /* getopt_long values */ case 0: nerr += set_option(long_options[option_index].name, optarg); break; #endif /* These are the old getopt-values (non-long) */ default: sprintf(option, "%c", n); nerr += set_option(option, optarg); break; } } if(optind>=argc) nerr++; if(nerr) Usage(argv[0]); if (getenv("LAV_VIDEO_DEV")) info->video_dev = getenv("LAV_VIDEO_DEV"); else { struct stat vstat; if(stat("/dev/video", &vstat) == 0 && S_ISCHR(vstat.st_mode)) info->video_dev = "/dev/video"; else if(stat("/dev/video0", &vstat) == 0 && S_ISCHR(vstat.st_mode)) info->video_dev = "/dev/video0"; else if(stat("/dev/v4l/video0", &vstat) == 0 && S_ISCHR(vstat.st_mode)) info->video_dev = "/dev/v4l/video0"; else if(stat("/dev/v4l0", &vstat) == 0 && S_ISCHR(vstat.st_mode)) info->video_dev = "/dev/v4l0"; else if(stat("/dev/v4l", &vstat) == 0 && S_ISCHR(vstat.st_mode)) info->video_dev = "/dev/v4l"; } if (getenv("LAV_AUDIO_DEV")) info->audio_dev = getenv("LAV_AUDIO_DEV"); else { struct stat astat; if(stat("/dev/dsp", &astat) == 0 && S_ISCHR(astat.st_mode)) info->audio_dev = "/dev/dsp"; else if(stat("/dev/sound/dsp", &astat) == 0 && S_ISCHR(astat.st_mode)) info->audio_dev = "/dev/sound/dsp"; else if(stat("/dev/audio", &astat) == 0 && S_ISCHR(astat.st_mode)) info->audio_dev = "/dev/audio"; } mjpeg_default_handler_verbosity(verbose); /* Get and open input files */ lavplay_open(info, argv + optind, argc - optind); } int main(int argc, char **argv) { char buffer[256]; /* Output Version information - Used by xlav to check for * consistency. */ printf( LAVPLAY_VSTR "\n" ); fflush(stdout); printf( "lavtools version " VERSION "\n" ); fcntl(0, F_SETFL, O_NONBLOCK); signal(SIGINT,SigHandler); info = lavplay_malloc(); if (!info) return 1; check_command_line_options(argc, argv); info->output_statistics = stats; info->msg_callback = input; info->state_changed = state_changed; if (!lavplay_main(info)) return 1; if (!lavplay_set_frame(info, skip_seconds * info->editlist->video_norm=='p'?25:30)) return 1; if (!lavplay_set_speed(info, 1)) return 1; /* okay, now wait until we get command-line input and ROCK! */ while (!exit_flag) { if (read(0, buffer, 255) > 0) process_input(buffer); else usleep(10000); } lavplay_busy(info); /* wait for all the nice goodies to shut down */ lavplay_free(info); fprintf(stderr, "\n"); return 0; } mjpegtools-2.1.0/lavtools/lavtrans.c0000644000175000017500000002503510320011152020040 0ustar glowwormglowworm/* lavtrans - takes file arguments like lavplay (AVI/Quicktime files and Edit Lists) and produces a new file or a bunch of JPEG images from that. Mostly intended to flaten the content of Edit Lists Copyright (C) 2000 Rainer Johanni Additions by Gernot Ziegler Usage: lavtrans [options] filename [filename ...] <-i num> where options are as follows: -o name Write output to file "name". Output must fit into 1 file (2 GB limit!!!) unless single images are produced. -f [amqiw] Format of output a: AVI (no selection of bottom/top frame first possible) q: Quicktime (if the input is interlaced, then all input files must be Quicktime, too) i: single images, "name" in the -o option must be a vaild format string for sprintf! w: WAV file (of sound only) Both options are mandatory! -i num Grab a single frame (num) from the input to the outputfile (you need -f i for this!) Filename options like in lavplay (optional +p/+n followed by an arbitrary number of AVI / Quicktime files or edit lists). This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include "lav_io.h" #include "editlist.h" #include "mjpeg_logging.h" static EditList el; static char *outfile=0; static char format=0; static int process_image_frame = -1; /* All, >-1 means not all */ #define FOURCC(a,b,c,d) ((d<<24) | ((c&0xff)<<16) | ((b&0xff)<<8) | (a&0xff)) #define FOURCC_RIFF FOURCC ('R', 'I', 'F', 'F') #define FOURCC_WAVE FOURCC ('W', 'A', 'V', 'E') #define FOURCC_FMT FOURCC ('f', 'm', 't', ' ') #define FOURCC_DATA FOURCC ('d', 'a', 't', 'a') static struct { uint32_t rifftag; uint32_t rifflen; uint32_t wavetag; uint32_t fmt_tag; uint32_t fmt_len; uint16_t wFormatTag; uint16_t nChannels; uint32_t nSamplesPerSec; uint32_t nAvgBytesPerSec; uint16_t nBlockAlign; uint16_t wBitsPerSample; uint32_t datatag; uint32_t datalen; } wave_hdr; static uint8_t abuff[16384]; int big_endian; int verbose = 1; /* Prototype definitions */ void Usage(char *str); void system_error(const char *str1, const char *str2); void initwav_hdr(void); void initwav_hdr() { wave_hdr.rifflen = 0; /* to be filled later */ wave_hdr.datalen = 0; /* to be filled later */ wave_hdr.wFormatTag = 1; /* PCM */ wave_hdr.rifftag = reorder_32(FOURCC_RIFF, big_endian); wave_hdr.wavetag = reorder_32(FOURCC_WAVE, big_endian); wave_hdr.fmt_tag = reorder_32(FOURCC_FMT, big_endian); wave_hdr.fmt_len = reorder_32(16, big_endian); wave_hdr.datatag = reorder_32(FOURCC_DATA, big_endian); swab(&wave_hdr.wFormatTag, &wave_hdr.wFormatTag ,2); } void Usage(char *str) { fprintf(stderr,"Usage: %s -o -f [aqiw] filenames [<-i num>]\n",str); fprintf(stderr," -f a output AVI file\n"); fprintf(stderr," -f q output Quicktime file\n"); fprintf(stderr," -f i output single JPEG images, " "-o option mut be a valid format string\n"); fprintf(stderr," -f w output WAV file (sound only!)\n"); fprintf(stderr," -i num convert single frame to JPEG\n"); exit(1); } void system_error(const char *str1, const char *str2) { mjpeg_error_exit1("%s: %s: %s",str1, str2, strerror(errno)); } int main(int argc, char ** argv) { lav_file_t *outfd = NULL; FILE *wavfd = NULL; FILE *imgfd = NULL; uint8_t *vbuff; char *dotptr; char imgfname[4096]; long audio_bytes_out = 0; int res, n, nv = 0, na = 0, nframe; int forcestereo = 0; while ((n=getopt(argc,argv,"o:f:i:v:")) != EOF) { switch(n) { case 'o': outfile = optarg; break; case 'f': format = optarg[0]; break; case 'i': process_image_frame = atoi(optarg); break; case 'v': verbose = atoi (optarg); if (verbose < 0 || verbose >2) { Usage (argv[0]); exit (1); } break; case '?': Usage(argv[0]); exit(1); } } (void)mjpeg_default_handler_verbosity(verbose); big_endian = lav_detect_endian(); if (big_endian < 0) exit(1); if (outfile==0) Usage(argv[0]); if (optind>=argc) Usage(argv[0]); if (outfile != 0 && format == 0) { if ((dotptr = strrchr(outfile, '.'))) { #ifdef HAVE_LIBQUICKTIME if (!strcasecmp(dotptr+1, "mov")) format = 'q'; #endif if (!strcasecmp(dotptr+1, "avi")) format = 'a'; if (!strcasecmp(dotptr+1, "wav")) format = 'w'; } if (format == '\0') format = 'a'; } if (format!='a' && format!='q' && format!='i' && format!='w' && format!='A' && format!='W') Usage(argv[0]); if (process_image_frame != -1 && format!='i') { mjpeg_error_exit1("If you specify \'-i \', you must use jpg (\'-f i\') as output:" " lavtrans -o image.jpg -f i movie.avi -i "); } /* Get and open input files */ read_video_files(argv + optind, argc - optind, &el,0); if (format == 'a' && el.video_inter == Y4M_ILACE_BOTTOM_FIRST) format = 'A'; if ((format == 'q') && el.video_inter == Y4M_ILACE_BOTTOM_FIRST) { mjpeg_error_exit1("Output is Quicktime - wrong interlacing order"); } if (format == 'q' || format == 'a' || format == 'A') { outfd = lav_open_output_file(outfile,format, el.video_width,el.video_height,el.video_inter, el.video_fps /* was:video_norm=='n' ? 30000.0/1001.0 : 25.0*/ , el.audio_bits,el.audio_chans,el.audio_rate); if (!outfd) { mjpeg_error_exit1("Opening output file %s: %s", outfile,lav_strerror()); } } if (format == 'w' || format == 'W') { if (!el.has_audio) { mjpeg_error_exit1("WAV output requested but no audio present"); } if (format == 'W') { if (el.audio_bits == 16 && el.audio_chans == 1) forcestereo = 1; else { mjpeg_error_exit1("STEREOFIED WAV output request but non mono 16-bit audio present"); } } initwav_hdr(); wave_hdr.nChannels = forcestereo ? 2 : el.audio_chans; wave_hdr.nBlockAlign = el.audio_bps; wave_hdr.wBitsPerSample = el.audio_bits; wave_hdr.nSamplesPerSec = reorder_32(el.audio_rate, big_endian); wave_hdr.nAvgBytesPerSec = reorder_32(el.audio_rate*el.audio_bps, big_endian); if (big_endian) { swab(&wave_hdr.nChannels, &wave_hdr.nChannels, 2); swab(&wave_hdr.nBlockAlign, &wave_hdr.nBlockAlign, 2); swab(&wave_hdr.wBitsPerSample, &wave_hdr.wBitsPerSample, 2); } wavfd = fopen(outfile,"wb"); if (wavfd==0) system_error("opening WAV file","fopen"); res = fwrite(&wave_hdr,sizeof(wave_hdr),1,wavfd); if (res!=1) system_error("writing WAV file","fwrite"); } vbuff = (uint8_t*) malloc(el.max_frame_size); if (vbuff==0) { mjpeg_error_exit1("malloc failed"); } /* Quick hack by Ronald to enable one-frame picture grabbing */ if (process_image_frame != -1) { nv = el_get_video_frame(vbuff, process_image_frame, &el); sprintf(imgfname,outfile); imgfd = fopen(imgfname,"wb"); if (imgfd==0) system_error("opening image file","fopen"); res = fwrite(vbuff,nv,1,imgfd); if (res!=1) system_error("writing image","fwrite"); fclose(imgfd); mjpeg_info("Frame %d grabbed", process_image_frame); exit(1); } for(nframe=0;nframe= 0; --i) { sbuff[i+i+1]=sbuff[i+i]=sbuff[i]; } na = na + na; res = fwrite(abuff,na,1,wavfd); } else { res = fwrite(abuff,na,1,wavfd); } if (res!=1) system_error("writing WAV file","fwrite"); audio_bytes_out += na; break; } } if (format == 'q' || format == 'a' || format == 'A') { res = lav_close(outfd); if (res) { mjpeg_error_exit1("Closing output file: %s",lav_strerror()); } } if (format == 'w' || format == 'W') { wave_hdr.rifflen = reorder_32(sizeof(wave_hdr) -8+ audio_bytes_out, big_endian); wave_hdr.datalen = reorder_32(audio_bytes_out, big_endian); res = fseek(wavfd,0,SEEK_SET); if (res) system_error("writing WAV file","fseek"); res = fwrite(&wave_hdr,sizeof(wave_hdr),1,wavfd); if (res!=1) system_error("writing WAV file","fwrite"); fclose(wavfd); } return 0; } mjpegtools-2.1.0/lavtools/lav_io.h0000644000175000017500000000627510537655445017526 0ustar glowwormglowworm/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef LAV_IO_H #define LAV_IO_H #include #ifdef HAVE_LIBQUICKTIME #include #include #else typedef void quicktime_t; #endif #include #define MAX_MBYTES_PER_FILE_64 (4194304 - 1024) /* 4TB-1GB should be enough */ #define MAX_MBYTES_PER_FILE_32 (2048 - 4) /* 2GB-4MB */ /* raw data format of a single frame */ #define DATAFORMAT_MJPG 0 #define DATAFORMAT_DV2 1 #define DATAFORMAT_YUV420 2 #define DATAFORMAT_YUV422 3 typedef struct { avi_t *avi_fd; int jpeg_fd; char *jpeg_filename; quicktime_t *qt_fd; int format; int interlacing; int sar_w; /* "sample aspect ratio" width */ int sar_h; /* "sample aspect ratio" height */ int has_audio; int bps; int chroma; int dataformat; } lav_file_t; #ifdef HAVE_LIBDV extern int libdv_pal_yv12; #endif int lav_query_APP_marker(char format); int lav_query_APP_length(char format); int lav_query_polarity(char format); lav_file_t *lav_open_output_file(char *filename, char format, int width, int height, int interlaced, double fps, int asize, int achans, long arate); int lav_close(lav_file_t *lav_file); int lav_write_frame(lav_file_t *lav_file, uint8_t *buff, long size, long count); int lav_write_audio(lav_file_t *lav_file, uint8_t *buff, long samps); long lav_video_frames(lav_file_t *lav_file); int lav_video_width(lav_file_t *lav_file); int lav_video_height(lav_file_t *lav_file); double lav_frame_rate(lav_file_t *lav_file); int lav_video_interlacing(lav_file_t *lav_file); void lav_video_sampleaspect(lav_file_t *lav_file, int *sar_w, int *sar_h); int lav_video_chroma(lav_file_t *lav_file); const char *lav_video_compressor(lav_file_t *lav_file); int lav_audio_channels(lav_file_t *lav_file); int lav_audio_bits(lav_file_t *lav_file); long lav_audio_rate(lav_file_t *lav_file); long lav_audio_samples(lav_file_t *lav_file); long lav_frame_size(lav_file_t *lav_file, long frame); int lav_seek_start(lav_file_t *lav_file); int lav_set_video_position(lav_file_t *lav_file, long frame); int lav_read_frame(lav_file_t *lav_file, uint8_t *vidbuf); int lav_set_audio_position(lav_file_t *lav_file, long sample); long lav_read_audio(lav_file_t *lav_file, uint8_t *audbuf, long samps); lav_file_t *lav_open_input_file(char *filename); int lav_get_field_size(uint8_t * jpegdata, long jpeglen); const char *lav_strerror(void); int lav_fileno( lav_file_t *lav_file ); uint32_t reorder_32(uint32_t, int); int lav_detect_endian (void); #endif mjpegtools-2.1.0/lavtools/colorspace.h0000644000175000017500000000212110161334555020356 0ustar glowwormglowworm/* * colorspace.h: Routines to perform colorspace conversions. * * * Copyright (C) 2001 Matthew J. Marjanovic * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ void convert_RGB_to_YCbCr(uint8_t *planes[], int length); void convert_YCbCr_to_RGB(uint8_t *planes[], int length); void convert_Y255_to_Y219(uint8_t *plane, int length); void convert_Y219_to_Y255(uint8_t *plane, int length); mjpegtools-2.1.0/lavtools/editlist.c0000644000175000017500000003473110351367066020060 0ustar glowwormglowworm/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include "mjpeg_logging.h" #include "lav_io.h" #include "editlist.h" #include /* Since we use malloc often, here the error handling */ static void malloc_error(void) { mjpeg_error_exit1("Out of memory - malloc failed"); } int open_video_file(char *filename, EditList *el, int preserve_pathname) { int i, n, nerr; char realname[PATH_MAX]; /* Get full pathname of file if the user hasn't specified preservation of pathnames... */ if( preserve_pathname ) { strcpy(realname, filename); } else if(realpath(filename,realname)==0) { mjpeg_error_exit1( "Cannot deduce real filename: %s", strerror(errno)); } /* Check if this filename is allready present */ for(i=0;inum_video_files;i++) if(strcmp(realname,el->video_file_list[i])==0) { mjpeg_error("File %s already open",realname); return i; } /* Check if MAX_EDIT_LIST_FILES will be exceeded */ if(el->num_video_files>=MAX_EDIT_LIST_FILES) { mjpeg_error_exit1("Maximum number of video files exceeded"); } n = el->num_video_files; el->num_video_files++; mjpeg_debug("Opening video file %s ...",filename); el->lav_fd[n] = lav_open_input_file(filename); if(!el->lav_fd[n]) { mjpeg_error_exit1("Error opening %s",filename); } if(lav_video_chroma(el->lav_fd[n]) != Y4M_CHROMA_422 && lav_video_chroma(el->lav_fd[n]) != Y4M_CHROMA_420JPEG && lav_video_chroma(el->lav_fd[n]) != Y4M_CHROMA_411) { mjpeg_warn("Input file %s is not in JPEG 4:2:2 or 4:2:0 or 4:1:1 format", filename); el->chroma = Y4M_UNKNOWN; } el->num_frames[n] = lav_video_frames(el->lav_fd[n]); el->video_file_list[n] = strdup(realname); if(el->video_file_list[n]==0) malloc_error(); /* Debug Output */ mjpeg_debug("File: %s, absolute name: %s",filename,realname); mjpeg_debug(" frames: %8ld",lav_video_frames(el->lav_fd[n])); mjpeg_debug(" width: %8d",lav_video_width (el->lav_fd[n])); mjpeg_debug(" height: %8d",lav_video_height(el->lav_fd[n])); { const char *int_msg; switch( lav_video_interlacing(el->lav_fd[n])) { case Y4M_ILACE_NONE : int_msg = "not interlaced"; break; case Y4M_ILACE_TOP_FIRST : int_msg = "top field first"; break; case Y4M_ILACE_BOTTOM_FIRST : int_msg = "bottom field first"; break; default: int_msg = "Unknown!"; break; } mjpeg_debug(" interlacing: %s", int_msg ); } mjpeg_debug(" frames/sec: %8.3f",lav_frame_rate(el->lav_fd[n])); mjpeg_debug(" audio samps: %8ld",lav_audio_samples(el->lav_fd[n])); mjpeg_debug(" audio chans: %8d",lav_audio_channels(el->lav_fd[n])); mjpeg_debug(" audio bits: %8d",lav_audio_bits(el->lav_fd[n])); mjpeg_debug(" audio rate: %8ld",lav_audio_rate(el->lav_fd[n])); nerr = 0; if(n==0) { /* First file determines parameters */ el->video_height = lav_video_height(el->lav_fd[n]); el->video_width = lav_video_width (el->lav_fd[n]); el->video_inter = lav_video_interlacing(el->lav_fd[n]); el->video_fps = lav_frame_rate(el->lav_fd[n]); lav_video_sampleaspect(el->lav_fd[n], &el->video_sar_width, &el->video_sar_height); if(!el->video_norm) { /* TODO: This guessing here is a bit dubious but it can be over-ridden */ if(el->video_fps>24.95 && el->video_fps<25.05) el->video_norm = 'p'; else if (el->video_fps>29.92 && el->video_fps<=30.02) el->video_norm = 'n'; else { mjpeg_error_exit1("File %s has %f frames/sec, choose norm with +[np] param", filename,el->video_fps); } } el->audio_chans = lav_audio_channels(el->lav_fd[n]); if(el->audio_chans>2) { mjpeg_error_exit1("File %s has %d audio channels - cant play that!", filename,el->audio_chans); } el->has_audio = (el->audio_chans>0); el->audio_bits = lav_audio_bits(el->lav_fd[n]); el->audio_rate = lav_audio_rate(el->lav_fd[n]); el->audio_bps = (el->audio_bits*el->audio_chans+7)/8; } else { /* All files after first have to match the paramters of the first */ if( el->video_height != lav_video_height(el->lav_fd[n]) || el->video_width != lav_video_width (el->lav_fd[n]) ) { mjpeg_error("File %s: Geometry %dx%d does not match %ldx%ld", filename,lav_video_width (el->lav_fd[n]), lav_video_height(el->lav_fd[n]),el->video_width,el->video_height); nerr++; } if( el->video_inter != lav_video_interlacing(el->lav_fd[n]) ) { mjpeg_error("File %s: Interlacing is %d should be %ld", filename,lav_video_interlacing(el->lav_fd[n]),el->video_inter); nerr++; } if( fabs(el->video_fps - lav_frame_rate(el->lav_fd[n])) > 0.0000001) { mjpeg_error("File %s: fps is %3.2f should be %3.2f", filename, lav_frame_rate(el->lav_fd[n]), el->video_fps); nerr++; } /* If first file has no audio, we don't care about audio */ if(el->has_audio) { if(el->audio_chans != lav_audio_channels(el->lav_fd[n]) || el->audio_bits != lav_audio_bits(el->lav_fd[n]) || el->audio_rate != lav_audio_rate(el->lav_fd[n]) ) { mjpeg_error("File %s: Audio is %d chans %d bit %ld Hz," " should be %d chans %d bit %ld Hz", filename,lav_audio_channels(el->lav_fd[n]), lav_audio_bits(el->lav_fd[n]), lav_audio_rate(el->lav_fd[n]), el->audio_chans, el->audio_bits, el->audio_rate); nerr++; } } if(nerr) exit(1); } return n; } /* read_video_files: Accepts a list of filenames as input and opens these files for subsequent playback. The list of filenames may consist of: - "+p" or "+n" as the first entry (forcing PAL or NTSC) - ordinary AVI or Quicktimefile names - Edit list file names - lines starting with a colon (:) are ignored for third-party editlist extensions */ void read_video_files(char **filename, int num_files, EditList *el, int preserve_pathnames) { FILE *fd; char line[1024]; long index_list[MAX_EDIT_LIST_FILES]; int i, n, nf, n1, n2, nl, num_list_files; nf = 0; memset(el,0,sizeof(EditList)); el->chroma = Y4M_CHROMA_422; /* default, individual file will override */ /* Check if a norm parameter is present */ if(strcmp(filename[0],"+p")==0 || strcmp(filename[0],"+n")==0) { el->video_norm = filename[0][1]; nf = 1; mjpeg_info("Norm set to %s",el->video_norm=='n'?"NTSC":"PAL"); } for(;nfvideo_norm == 'p') { mjpeg_error_exit1("Norm allready set to PAL"); } el->video_norm = 'n'; } else { if( el->video_norm == 'n') { mjpeg_error_exit1("Norm allready set to NTSC"); } el->video_norm = 'p'; } /* read third line: Number of files */ fgets(line,1024,fd); sscanf(line,"%d",&num_list_files); mjpeg_debug("Edit list contains %d files",num_list_files); /* read files */ for(i=0;i=num_list_files) { mjpeg_error_exit1("Wrong file number in edit list entry"); } if(n1<0) n1 = 0; if(n2>=el->num_frames[index_list[nl]]) n2 = el->num_frames[index_list[nl]]; if(n2frame_list = (long*) realloc(el->frame_list, (el->video_frames+n2-n1+1)*sizeof(long)); if(el->frame_list==0) malloc_error(); for(i=n1;i<=n2;i++) el->frame_list[el->video_frames++] = EL_ENTRY(index_list[nl],i); } } fclose(fd); } else { /* Not an edit list - should be a ordinary video file */ fclose(fd); n = open_video_file(filename[nf],el, preserve_pathnames); el->frame_list = (long*) realloc(el->frame_list, (el->video_frames+el->num_frames[n])*sizeof(long)); if(el->frame_list==0) malloc_error(); for(i=0;inum_frames[n];i++) el->frame_list[el->video_frames++] = EL_ENTRY(n,i); } } /* Calculate maximum frame size */ for(i=0;ivideo_frames;i++) { n = el->frame_list[i]; if(lav_frame_size(el->lav_fd[N_EL_FILE(n)],N_EL_FRAME(n)) > el->max_frame_size) el->max_frame_size = lav_frame_size(el->lav_fd[N_EL_FILE(n)],N_EL_FRAME(n)); } /* Help for audio positioning */ el->last_afile = -1; } int write_edit_list(char *name, long n1, long n2, EditList *el) { FILE *fd; int i, n, num_files, oldfile, oldframe; int index[MAX_EDIT_LIST_FILES]; /* check n1 and n2 for correctness */ if(n1<0) n1 = 0; if(n2>=el->video_frames) n2 = el->video_frames-1; mjpeg_info("Write edit list: %ld %ld %s",n1,n2,name); fd = fopen(name,"w"); if(fd==0) { mjpeg_error("Can not open %s - no edit list written!",name); return -1; } fprintf(fd,"LAV Edit List\n"); fprintf(fd,"%s\n",el->video_norm=='n'?"NTSC":"PAL"); /* get which files are actually referenced in the edit list entries */ for(i=0;iframe_list[i])] = 1; num_files = 0; for(i=0;i=0) fprintf(fd,"%s\n",el->video_file_list[i]); oldfile = index[N_EL_FILE(el->frame_list[n1])]; oldframe = N_EL_FRAME(el->frame_list[n1]); fprintf(fd,"%d %d ",oldfile,oldframe); for(i=n1+1;i<=n2;i++) { n = el->frame_list[i]; if(index[N_EL_FILE(n)]!=oldfile || N_EL_FRAME(n)!=oldframe+1) { fprintf(fd,"%d\n",oldframe); fprintf(fd,"%d %d ",index[N_EL_FILE(n)],N_EL_FRAME(n)); } oldfile = index[N_EL_FILE(n)]; oldframe = N_EL_FRAME(n); } n = fprintf(fd,"%d\n",oldframe); /* We did not check if all our prints succeeded, so check at least the last one */ if(n<=0) { mjpeg_error("Error writing edit list: %s", strerror(errno)); return -1; } fclose(fd); return 0; } int el_get_video_frame(uint8_t *vbuff, long nframe, EditList *el) { int res, n; if (nframe<0) nframe = 0; if (nframe>el->video_frames) nframe = el->video_frames; n = el->frame_list[nframe]; res = lav_set_video_position(el->lav_fd[N_EL_FILE(n)],N_EL_FRAME(n)); if (res<0) mjpeg_error_exit1("Error setting video position: %s",lav_strerror()); res = lav_read_frame(el->lav_fd[N_EL_FILE(n)],vbuff); if (res<0) mjpeg_error_exit1("Error reading video frame: %s",lav_strerror()); return res; } int el_get_audio_data(uint8_t *abuff, long nframe, EditList *el, int mute) { int res, n, ns0, ns1, asamps; if (!el->has_audio) return 0; if (nframe<0) nframe = 0; if (nframe>el->video_frames) nframe = el->video_frames; n = el->frame_list[nframe]; ns1 = (double)(N_EL_FRAME(n)+1)*el->audio_rate/el->video_fps; ns0 = (double) N_EL_FRAME(n) *el->audio_rate/el->video_fps; asamps = ns1-ns0; /* if mute flag is set, don't read actually, just return zero data */ if (mute) { /* TODO: A.Stevens 2000 - this looks like a potential overflow bug to me... non muted we only ever return asamps/FPS samples */ memset(abuff,0,asamps*el->audio_bps); return asamps*el->audio_bps; } if(el->last_afile!=N_EL_FILE(n) || el->last_apos!=ns0) lav_set_audio_position(el->lav_fd[N_EL_FILE(n)],ns0); res = lav_read_audio(el->lav_fd[N_EL_FILE(n)],abuff,asamps); if (res<0) mjpeg_error_exit1("Error reading audio: %s",lav_strerror()); if (resaudio_bps,0,(asamps-res)*el->audio_bps); el->last_afile = N_EL_FILE(n); el->last_apos = ns1; return asamps*el->audio_bps; } int el_video_frame_data_format(long nframe, EditList *el) { int n; if(el->video_frames<=0) return DATAFORMAT_MJPG; /* empty editlist, return default */ if(nframe<0) nframe = 0; if(nframe>el->video_frames) nframe = el->video_frames; n = N_EL_FILE(el->frame_list[nframe]); return(el->lav_fd[n]->dataformat); } mjpegtools-2.1.0/lavtools/yuvplay.c0000644000175000017500000002076611344710443017745 0ustar glowwormglowworm/* * yuvplay - play YUV data using SDL * * Copyright (C) 2000, Ronald Bultje * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "yuv4mpeg.h" #include "mjpeg_logging.h" #include #include #include #include /* SDL variables */ SDL_Surface *screen; SDL_Overlay *yuv_overlay; SDL_Rect rect; static int got_sigint = 0; static void usage (void) { fprintf(stderr, "Usage: lavpipe/lav2yuv... | yuvplay [options]\n" " -s : display size, width x height\n" " -t : set window title\n" " -f : frame rate (overrides rate in stream header)\n" " -c : don't sync on frames - plays at stream speed\n" " -v : verbosity {0, 1, 2} [default: 1]\n" ); } static void sigint_handler (int signal) { mjpeg_warn("Caught SIGINT, exiting..."); got_sigint = 1; } static long get_time_diff(struct timeval time_now) { struct timeval time_now2; gettimeofday(&time_now2,0); return time_now2.tv_sec*1.e6 - time_now.tv_sec*1.e6 + time_now2.tv_usec - time_now.tv_usec; } static char *print_status(int frame, double framerate) { MPEG_timecode_t tc; static char temp[256]; mpeg_timecode(&tc, frame, mpeg_framerate_code(mpeg_conform_framerate(framerate)), framerate); sprintf(temp, "%d:%2.2d:%2.2d.%2.2d", tc.h, tc.m, tc.s, tc.f); return temp; } int main(int argc, char *argv[]) { int verbosity = 1; double time_between_frames = 0.0; double frame_rate = 0.0; struct timeval time_now; int n, frame; unsigned char *yuv[3]; int in_fd = 0; int screenwidth=0, screenheight=0; y4m_stream_info_t streaminfo; y4m_frame_info_t frameinfo; int frame_width; int frame_height; int wait_for_sync = 1; char *window_title = NULL; while ((n = getopt(argc, argv, "hs:t:f:cv:")) != EOF) { switch (n) { case 'c': wait_for_sync = 0; break; case 's': if (sscanf(optarg, "%dx%d", &screenwidth, &screenheight) != 2) { mjpeg_error_exit1( "-s option needs two arguments: -s 10x10"); exit(1); } break; case 't': window_title = optarg; break; case 'f': frame_rate = atof(optarg); if( frame_rate <= 0.0 || frame_rate > 200.0 ) mjpeg_error_exit1( "-f option needs argument > 0.0 and < 200.0"); break; case 'v': verbosity = atoi(optarg); if ((verbosity < 0) || (verbosity > 2)) mjpeg_error_exit1("-v needs argument from {0, 1, 2} (not %d)", verbosity); break; case 'h': case '?': usage(); exit(1); break; default: usage(); exit(1); } } mjpeg_default_handler_verbosity(verbosity); y4m_accept_extensions(1); y4m_init_stream_info(&streaminfo); y4m_init_frame_info(&frameinfo); if ((n = y4m_read_stream_header(in_fd, &streaminfo)) != Y4M_OK) { mjpeg_error("Couldn't read YUV4MPEG2 header: %s!", y4m_strerr(n)); exit (1); } switch (y4m_si_get_chroma(&streaminfo)) { case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: break; default: mjpeg_error_exit1("Cannot handle non-4:2:0 streams yet!"); } frame_width = y4m_si_get_width(&streaminfo); frame_height = y4m_si_get_height(&streaminfo); if ((screenwidth <= 0) || (screenheight <= 0)) { /* no user supplied screen size, so let's use the stream info */ y4m_ratio_t aspect = y4m_si_get_sampleaspect(&streaminfo); if (!(Y4M_RATIO_EQL(aspect, y4m_sar_UNKNOWN))) { /* if pixel aspect ratio present, use it */ #if 1 /* scale width, but maintain height (line count) */ screenheight = frame_height; screenwidth = frame_width * aspect.n / aspect.d; #else if ((frame_width * aspect.d) < (frame_height * aspect.n)) { screenwidth = frame_width; screenheight = frame_width * aspect.d / aspect.n; } else { screenheight = frame_height; screenwidth = frame_height * aspect.n / aspect.d; } #endif } else { /* unknown aspect ratio -- assume square pixels */ screenwidth = frame_width; screenheight = frame_height; } } /* Initialize the SDL library */ if( SDL_Init(SDL_INIT_VIDEO) < 0 ) { mjpeg_error("Couldn't initialize SDL: %s", SDL_GetError()); exit(1); } /* set window title */ SDL_WM_SetCaption(window_title, NULL); /* yuv params */ yuv[0] = malloc(frame_width * frame_height * sizeof(unsigned char)); yuv[1] = malloc(frame_width * frame_height / 4 * sizeof(unsigned char)); yuv[2] = malloc(frame_width * frame_height / 4 * sizeof(unsigned char)); screen = SDL_SetVideoMode(screenwidth, screenheight, 0, SDL_SWSURFACE); if ( screen == NULL ) { mjpeg_error("SDL: Couldn't set %dx%d: %s", screenwidth, screenheight, SDL_GetError()); exit(1); } else { mjpeg_debug("SDL: Set %dx%d @ %d bpp", screenwidth, screenheight, screen->format->BitsPerPixel); } /* since IYUV ordering is not supported by Xv accel on maddog's system * (Matrox G400 --- although, the alias I420 is, but this is not * recognized by SDL), we use YV12 instead, which is identical, * except for ordering of Cb and Cr planes... * we swap those when we copy the data to the display buffer... */ yuv_overlay = SDL_CreateYUVOverlay(frame_width, frame_height, SDL_YV12_OVERLAY, screen); if ( yuv_overlay == NULL ) { mjpeg_error("SDL: Couldn't create SDL_yuv_overlay: %s", SDL_GetError()); exit(1); } if ( yuv_overlay->hw_overlay ) mjpeg_debug("SDL: Using hardware overlay."); rect.x = 0; rect.y = 0; rect.w = screenwidth; rect.h = screenheight; SDL_DisplayYUVOverlay(yuv_overlay, &rect); signal (SIGINT, sigint_handler); frame = 0; if ( frame_rate == 0.0 ) { /* frame rate has not been set from command-line... */ if (Y4M_RATIO_EQL(y4m_fps_UNKNOWN, y4m_si_get_framerate(&streaminfo))) { mjpeg_info("Frame-rate undefined in stream... assuming 25Hz!" ); frame_rate = 25.0; } else { frame_rate = Y4M_RATIO_DBL(y4m_si_get_framerate(&streaminfo)); } } time_between_frames = 1.e6 / frame_rate; gettimeofday(&time_now,0); while ((n = y4m_read_frame(in_fd, &streaminfo, &frameinfo, yuv)) == Y4M_OK && (!got_sigint)) { /* Lock SDL_yuv_overlay */ if ( SDL_MUSTLOCK(screen) ) { if ( SDL_LockSurface(screen) < 0 ) break; } if (SDL_LockYUVOverlay(yuv_overlay) < 0) break; /* let's draw the data (*yuv[3]) on a SDL screen (*screen) */ memcpy(yuv_overlay->pixels[0], yuv[0], frame_width * frame_height); memcpy(yuv_overlay->pixels[1], yuv[2], frame_width * frame_height / 4); memcpy(yuv_overlay->pixels[2], yuv[1], frame_width * frame_height / 4); /* Unlock SDL_yuv_overlay */ if ( SDL_MUSTLOCK(screen) ) { SDL_UnlockSurface(screen); } SDL_UnlockYUVOverlay(yuv_overlay); /* Show, baby, show! */ SDL_DisplayYUVOverlay(yuv_overlay, &rect); mjpeg_info("Playing frame %4.4d - %s", frame, print_status(frame, frame_rate)); if (wait_for_sync) while(get_time_diff(time_now) < time_between_frames) { usleep(1000); } frame++; gettimeofday(&time_now,0); } if ((n != Y4M_OK) && (n != Y4M_ERR_EOF)) mjpeg_error("Couldn't read frame: %s", y4m_strerr(n)); for (n=0; n<3; n++) { free(yuv[n]); } mjpeg_info("Played %4.4d frames (%s)", frame, print_status(frame, frame_rate)); SDL_FreeYUVOverlay(yuv_overlay); SDL_Quit(); y4m_fini_frame_info(&frameinfo); y4m_fini_stream_info(&streaminfo); return 0; } mjpegtools-2.1.0/lavtools/jpegutils.c0000644000175000017500000011164611326764000020236 0ustar glowwormglowworm/* * jpegutils.c: Some Utility programs for dealing with * JPEG encoded images * * Copyright (C) 1999 Rainer Johanni * Copyright (C) 2001 pHilipp Zabel * * based on jdatasrc.c and jdatadst.c from the Independent * JPEG Group's software by Thomas G. Lane * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include "mjpeg_logging.h" #include "jpegutils.h" #include "lav_io.h" /* * jpeg_data: buffer with input / output jpeg * len: Length of jpeg buffer * itype: 0: Not interlaced * 1: Interlaced, Top field first * 2: Interlaced, Bottom field first * ctype Chroma format for decompression. * Currently only Y4M_CHROMA_{420JPEG,422} are available * raw0 buffer with input / output raw Y channel * raw1 buffer with input / output raw U/Cb channel * raw2 buffer with input / output raw V/Cr channel * width width of Y channel (width of U/V is width/2) * height height of Y channel (height of U/V is height/2) */ static void jpeg_buffer_src (j_decompress_ptr cinfo, unsigned char *buffer, long num); static void jpeg_buffer_dest (j_compress_ptr cinfo, unsigned char *buffer, long len); static void jpeg_skip_ff (j_decompress_ptr cinfo); /******************************************************************* * * * The following routines define a JPEG Source manager which * * just reads from a given buffer (instead of a file as in * * the jpeg library) * * * *******************************************************************/ /* * Initialize source --- called by jpeg_read_header * before any data is actually read. */ static void init_source (j_decompress_ptr cinfo) { /* no work necessary here */ } /* * Fill the input buffer --- called whenever buffer is emptied. * * Should never be called since all data should be allready provided. * Is nevertheless sometimes called - sets the input buffer to data * which is the JPEG EOI marker; * */ static uint8_t EOI_data[2] = { 0xFF, 0xD9 }; static boolean fill_input_buffer (j_decompress_ptr cinfo) { cinfo->src->next_input_byte = EOI_data; cinfo->src->bytes_in_buffer = 2; return TRUE; } /* * Skip data --- used to skip over a potentially large amount of * uninteresting data (such as an APPn marker). * */ static void skip_input_data (j_decompress_ptr cinfo, long num_bytes) { if (num_bytes > 0) { if (num_bytes > (long) cinfo->src->bytes_in_buffer) num_bytes = (long) cinfo->src->bytes_in_buffer; cinfo->src->next_input_byte += (size_t) num_bytes; cinfo->src->bytes_in_buffer -= (size_t) num_bytes; } } /* * Terminate source --- called by jpeg_finish_decompress * after all data has been read. Often a no-op. */ static void term_source (j_decompress_ptr cinfo) { /* no work necessary here */ } /* * Prepare for input from a data buffer. */ static void jpeg_buffer_src (j_decompress_ptr cinfo, unsigned char *buffer, long num) { /* The source object and input buffer are made permanent so that a series * of JPEG images can be read from the same buffer by calling jpeg_buffer_src * only before the first one. (If we discarded the buffer at the end of * one image, we'd likely lose the start of the next one.) * This makes it unsafe to use this manager and a different source * manager serially with the same JPEG object. Caveat programmer. */ if (cinfo->src == NULL) { /* first time for this JPEG object? */ cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof (struct jpeg_source_mgr)); } cinfo->src->init_source = init_source; cinfo->src->fill_input_buffer = fill_input_buffer; cinfo->src->skip_input_data = skip_input_data; cinfo->src->resync_to_restart = jpeg_resync_to_restart; /* use default method */ cinfo->src->term_source = term_source; cinfo->src->bytes_in_buffer = num; cinfo->src->next_input_byte = (JOCTET *) buffer; } /* * jpeg_skip_ff is not a part of the source manager but it is * particularly useful when reading several images from the same buffer: * It should be called to skip padding 0xff bytes beetween images. */ static void jpeg_skip_ff (j_decompress_ptr cinfo) { while (cinfo->src->bytes_in_buffer > 1 && cinfo->src->next_input_byte[0] == 0xff && cinfo->src->next_input_byte[1] == 0xff) { cinfo->src->bytes_in_buffer--; cinfo->src->next_input_byte++; } } /******************************************************************* * * * The following routines define a JPEG Destination manager * * which just reads from a given buffer (instead of a file * * as in the jpeg library) * * * *******************************************************************/ /* * Initialize destination --- called by jpeg_start_compress * before any data is actually written. */ static void init_destination (j_compress_ptr cinfo) { /* No work necessary here */ } /* * Empty the output buffer --- called whenever buffer fills up. * * Should never be called since all data should be written to the buffer. * If it gets called, the given jpeg buffer was too small. * */ static boolean empty_output_buffer (j_compress_ptr cinfo) { /*FIXME: */ mjpeg_error( "Given jpeg buffer was too small!"); ERREXIT (cinfo, JERR_BUFFER_SIZE); /* shouldn't be FILE_WRITE but BUFFER_OVERRUN! */ return TRUE; } /* * Terminate destination --- called by jpeg_finish_compress * after all data has been written. Usually needs to flush buffer. * * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding * application must deal with any cleanup that should happen even * for error exit. */ static void term_destination (j_compress_ptr cinfo) { /* no work necessary here */ } /* * Prepare for output to a stdio stream. * The caller must have already opened the stream, and is responsible * for closing it after finishing compression. */ static void jpeg_buffer_dest (j_compress_ptr cinfo, unsigned char *buf, long len) { /* The destination object is made permanent so that multiple JPEG images * can be written to the same file without re-executing jpeg_stdio_dest. * This makes it dangerous to use this manager and a different destination * manager serially with the same JPEG object, because their private object * sizes may be different. Caveat programmer. */ if (cinfo->dest == NULL) { /* first time for this JPEG object? */ cinfo->dest = (struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof (struct jpeg_destination_mgr)); } cinfo->dest->init_destination = init_destination; cinfo->dest->empty_output_buffer = empty_output_buffer; cinfo->dest->term_destination = term_destination; cinfo->dest->free_in_buffer = len; cinfo->dest->next_output_byte = (JOCTET *) buf; } /******************************************************************* * * * decode_jpeg_data: Decode a (possibly interlaced) JPEG frame * * * *******************************************************************/ /* * ERROR HANDLING: * * We want in all cases to return to the user. * The following kind of error handling is from the * example.c file in the Independent JPEG Group's JPEG software */ struct my_error_mgr { struct jpeg_error_mgr pub; /* "public" fields */ jmp_buf setjmp_buffer; /* for return to caller */ /* original emit_message method */ JMETHOD(void, original_emit_message, (j_common_ptr cinfo, int msg_level)); int warning_seen; /* was a corrupt-data warning seen */ }; static void my_error_exit (j_common_ptr cinfo) { /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ struct my_error_mgr *myerr = (struct my_error_mgr *) cinfo->err; /* Always display the message. */ /* We could postpone this until after returning, if we chose. */ (*cinfo->err->output_message) (cinfo); /* Return control to the setjmp point */ longjmp (myerr->setjmp_buffer, 1); } static void my_emit_message (j_common_ptr cinfo, int msg_level) { /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ struct my_error_mgr *myerr = (struct my_error_mgr *) cinfo->err; if(msg_level < 0) myerr->warning_seen = 1; /* call original emit_message() */ (myerr->original_emit_message)(cinfo, msg_level); } #define MAX_LUMA_WIDTH 4096 #define MAX_CHROMA_WIDTH 2048 static unsigned char buf0[16][MAX_LUMA_WIDTH]; static unsigned char buf1[8][MAX_CHROMA_WIDTH]; static unsigned char buf2[8][MAX_CHROMA_WIDTH]; static unsigned char chr1[8][MAX_CHROMA_WIDTH]; static unsigned char chr2[8][MAX_CHROMA_WIDTH]; #if 1 /* generation of 'std' Huffman tables... */ static void add_huff_table (j_decompress_ptr dinfo, JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) /* Define a Huffman table */ { int nsymbols, len; if (*htblptr == NULL) *htblptr = jpeg_alloc_huff_table((j_common_ptr) dinfo); /* Copy the number-of-symbols-of-each-code-length counts */ memcpy((*htblptr)->bits, bits, sizeof((*htblptr)->bits)); /* Validate the counts. We do this here mainly so we can copy the right * number of symbols from the val[] array, without risking marching off * the end of memory. jchuff.c will do a more thorough test later. */ nsymbols = 0; for (len = 1; len <= 16; len++) nsymbols += bits[len]; if (nsymbols < 1 || nsymbols > 256) mjpeg_error_exit1("jpegutils.c: add_huff_table failed badly. "); memcpy((*htblptr)->huffval, val, nsymbols * sizeof(UINT8)); } static void std_huff_tables (j_decompress_ptr dinfo) /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ /* IMPORTANT: these are only valid for 8-bit data precision! */ { static const UINT8 bits_dc_luminance[17] = { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; static const UINT8 val_dc_luminance[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; static const UINT8 bits_dc_chrominance[17] = { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; static const UINT8 val_dc_chrominance[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; static const UINT8 bits_ac_luminance[17] = { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; static const UINT8 val_ac_luminance[] = { 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 }; static const UINT8 bits_ac_chrominance[17] = { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; static const UINT8 val_ac_chrominance[] = { 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 }; add_huff_table(dinfo, &dinfo->dc_huff_tbl_ptrs[0], bits_dc_luminance, val_dc_luminance); add_huff_table(dinfo, &dinfo->ac_huff_tbl_ptrs[0], bits_ac_luminance, val_ac_luminance); add_huff_table(dinfo, &dinfo->dc_huff_tbl_ptrs[1], bits_dc_chrominance, val_dc_chrominance); add_huff_table(dinfo, &dinfo->ac_huff_tbl_ptrs[1], bits_ac_chrominance, val_ac_chrominance); } static void guarantee_huff_tables(j_decompress_ptr dinfo) { if ( (dinfo->dc_huff_tbl_ptrs[0] == NULL) && (dinfo->dc_huff_tbl_ptrs[1] == NULL) && (dinfo->ac_huff_tbl_ptrs[0] == NULL) && (dinfo->ac_huff_tbl_ptrs[1] == NULL) ) { mjpeg_debug( "Generating standard Huffman tables for this frame."); std_huff_tables(dinfo); } } #endif /* ...'std' Huffman table generation */ /* * jpeg_data: Buffer with jpeg data to decode * len: Length of buffer * itype: 0: Not interlaced * 1: Interlaced, Top field first * 2: Interlaced, Bottom field first * ctype Chroma format for decompression. * Currently only Y4M_CHROMA_{420JPEG,422} are available * returns: * -1 on fatal error * 0 on success * 1 if jpeg lib threw a "corrupt jpeg data" warning. * in this case, "a damaged output image is likely." * */ int decode_jpeg_raw (unsigned char *jpeg_data, int len, int itype, int ctype, int width, int height, unsigned char *raw0, unsigned char *raw1, unsigned char *raw2) { int numfields, hsf[3], vsf[3], field, yl, yc, x, y = 0, i, xsl, xsc, xs, xd, hdown; JSAMPROW row0[16] = { buf0[0], buf0[1], buf0[2], buf0[3], buf0[4], buf0[5], buf0[6], buf0[7], buf0[8], buf0[9], buf0[10], buf0[11], buf0[12], buf0[13], buf0[14], buf0[15] }; JSAMPROW row1[8] = { buf1[0], buf1[1], buf1[2], buf1[3], buf1[4], buf1[5], buf1[6], buf1[7] }; JSAMPROW row2[16] = { buf2[0], buf2[1], buf2[2], buf2[3], buf2[4], buf2[5], buf2[6], buf2[7] }; JSAMPROW row1_444[16], row2_444[16]; JSAMPARRAY scanarray[3] = { row0, row1, row2 }; struct jpeg_decompress_struct dinfo; struct my_error_mgr jerr; /* We set up the normal JPEG error routines, then override error_exit. */ dinfo.err = jpeg_std_error (&jerr.pub); jerr.pub.error_exit = my_error_exit; /* also hook the emit_message routine to note corrupt-data warnings */ jerr.original_emit_message = jerr.pub.emit_message; jerr.pub.emit_message = my_emit_message; jerr.warning_seen = 0; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp (jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ jpeg_destroy_decompress (&dinfo); return -1; } jpeg_create_decompress (&dinfo); jpeg_buffer_src (&dinfo, jpeg_data, len); /* Read header, make some checks and try to figure out what the user really wants */ jpeg_read_header (&dinfo, TRUE); dinfo.raw_data_out = TRUE; dinfo.do_fancy_upsampling = FALSE; dinfo.out_color_space = JCS_YCbCr; dinfo.dct_method = JDCT_IFAST; guarantee_huff_tables(&dinfo); jpeg_start_decompress (&dinfo); if (dinfo.output_components != 3) { mjpeg_error( "Output components of JPEG image = %d, must be 3", dinfo.output_components); goto ERR_EXIT; } for (i = 0; i < 3; i++) { hsf[i] = dinfo.comp_info[i].h_samp_factor; vsf[i] = dinfo.comp_info[i].v_samp_factor; } //mjpeg_info( "Sampling factors, hsf=(%d, %d, %d) vsf=(%d, %d, %d) !", hsf[0], hsf[1], hsf[2], vsf[0], vsf[1], vsf[2]); if ((hsf[0] != 2 && hsf[0] != 1) || hsf[1] != 1 || hsf[2] != 1 || (vsf[0] != 1 && vsf[0] != 2) || vsf[1] != 1 || vsf[2] != 1) { mjpeg_error( "Unsupported sampling factors, hsf=(%d, %d, %d) vsf=(%d, %d, %d) !", hsf[0], hsf[1], hsf[2], vsf[0], vsf[1], vsf[2]); goto ERR_EXIT; } if (hsf[0] == 1) { if (height % 8 != 0) { mjpeg_error( "YUV 4:4:4 sampling, but image height %d not dividable by 8 !\n", height); goto ERR_EXIT; } mjpeg_info("YUV 4:4:4 sampling encountered ! Allocating special row buffer\n"); for (y = 0; y < 16; y++) // allocate a special buffer for the extra sampling depth { //mjpeg_info("YUV 4:4:4 %d.\n",y); row1_444[y] = (unsigned char *)malloc(dinfo.output_width * sizeof(char)); row2_444[y] = (unsigned char *)malloc(dinfo.output_width * sizeof(char)); } //mjpeg_info("YUV 4:4:4 sampling encountered ! Allocating done.\n"); scanarray[1] = row1_444; scanarray[2] = row2_444; } /* Height match image height or be exact twice the image height */ if (dinfo.output_height == height) { numfields = 1; } else if (2 * dinfo.output_height == height) { numfields = 2; } else { mjpeg_error( "Read JPEG: requested height = %d, height of image = %d", height, dinfo.output_height); goto ERR_EXIT; } /* Width is more flexible */ if (dinfo.output_width > MAX_LUMA_WIDTH) { mjpeg_error( "Image width of %d exceeds max", dinfo.output_width); goto ERR_EXIT; } if (width < 2 * dinfo.output_width / 3) { /* Downsample 2:1 */ hdown = 1; if (2 * width < dinfo.output_width) xsl = (dinfo.output_width - 2 * width) / 2; else xsl = 0; } else if (width == 2 * dinfo.output_width / 3) { /* special case of 3:2 downsampling */ hdown = 2; xsl = 0; } else { /* No downsampling */ hdown = 0; if (width < dinfo.output_width) xsl = (dinfo.output_width - width) / 2; else xsl = 0; } /* Make xsl even, calculate xsc */ xsl = xsl & ~1; xsc = xsl / 2; yl = yc = 0; for (field = 0; field < numfields; field++) { if (field > 0) { jpeg_read_header (&dinfo, TRUE); dinfo.raw_data_out = TRUE; dinfo.do_fancy_upsampling = FALSE; dinfo.out_color_space = JCS_YCbCr; dinfo.dct_method = JDCT_IFAST; jpeg_start_decompress (&dinfo); } if (numfields == 2) { switch (itype) { case Y4M_ILACE_TOP_FIRST: yl = yc = field; break; case Y4M_ILACE_BOTTOM_FIRST: yl = yc = (1 - field); break; default: mjpeg_error( "Input is interlaced but no interlacing set"); goto ERR_EXIT; } } else yl = yc = 0; while (dinfo.output_scanline < dinfo.output_height) { /* read raw data */ jpeg_read_raw_data (&dinfo, scanarray, 8 * vsf[0]); for (y = 0; y < 8 * vsf[0]; yl += numfields, y++) { xd = yl * width; xs = xsl; if (hdown == 0) for (x = 0; x < width; x++) raw0[xd++] = row0[y][xs++]; else if (hdown == 1) for (x = 0; x < width; x++, xs += 2) raw0[xd++] = (row0[y][xs] + row0[y][xs + 1]) >> 1; else for (x = 0; x < width / 2; x++, xd += 2, xs += 3) { raw0[xd] = (2 * row0[y][xs] + row0[y][xs + 1]) / 3; raw0[xd + 1] = (2 * row0[y][xs + 2] + row0[y][xs + 1]) / 3; } } /* Horizontal downsampling of chroma */ for (y = 0; y < 8; y++) { xs = xsc; if (hsf[0] == 1) for (x = 0; x < width / 2; x++, xs++) { row1[y][xs] = (row1_444[y][2*x] + row1_444[y][2*x + 1]) >> 1; row2[y][xs] = (row2_444[y][2*x] + row2_444[y][2*x + 1]) >> 1; } xs = xsc; if (hdown == 0) for (x = 0; x < width / 2; x++, xs++) { chr1[y][x] = row1[y][xs]; chr2[y][x] = row2[y][xs]; } else if (hdown == 1) for (x = 0; x < width / 2; x++, xs += 2) { chr1[y][x] = (row1[y][xs] + row1[y][xs + 1]) >> 1; chr2[y][x] = (row2[y][xs] + row2[y][xs + 1]) >> 1; } else for (x = 0; x < width / 2; x += 2, xs += 3) { chr1[y][x] = (2 * row1[y][xs] + row1[y][xs + 1]) / 3; chr1[y][x + 1] = (2 * row1[y][xs + 2] + row1[y][xs + 1]) / 3; chr2[y][x] = (2 * row2[y][xs] + row2[y][xs + 1]) / 3; chr2[y][x + 1] = (2 * row2[y][xs + 2] + row2[y][xs + 1]) / 3; } } /* Vertical resampling of chroma */ switch (ctype) { case Y4M_CHROMA_422: if (vsf[0] == 1) { /* Just copy */ for (y = 0; y < 8 /*&& yc < height */; y++, yc += numfields) { xd = yc * width / 2; for (x = 0; x < width / 2; x++, xd++) { raw1[xd] = chr1[y][x]; raw2[xd] = chr2[y][x]; } } } else { /* upsample */ for (y = 0; y < 8 /*&& yc < height */; y++) { xd = yc * width / 2; for (x = 0; x < width / 2; x++, xd++) { raw1[xd] = chr1[y][x]; raw2[xd] = chr2[y][x]; } yc += numfields; xd = yc * width / 2; for (x = 0; x < width / 2; x++, xd++) { raw1[xd] = chr1[y][x]; raw2[xd] = chr2[y][x]; } yc += numfields; } } break; default: /* * should be case Y4M_CHROMA_420JPEG: but use default: for compatibility. Some * pass things like '420' in with the expectation that anything other than * Y4M_CHROMA_422 will default to 420JPEG. */ if (vsf[0] == 1) { /* Really downsample */ for (y = 0; y < 8 /*&& yc < height/2*/; y += 2, yc += numfields) { xd = yc * width / 2; for (x = 0; x < width / 2; x++, xd++) { assert(xd < (width * height / 4)); raw1[xd] = (chr1[y][x] + chr1[y + 1][x]) >> 1; raw2[xd] = (chr2[y][x] + chr2[y + 1][x]) >> 1; } } } else { /* Just copy */ for (y = 0; y < 8 /*&& yc < height/2 */; y++, yc += numfields) { xd = yc * width / 2; for (x = 0; x < width / 2; x++, xd++) { raw1[xd] = chr1[y][x]; raw2[xd] = chr2[y][x]; } } } break; } } (void) jpeg_finish_decompress (&dinfo); if (field == 0 && numfields > 1) jpeg_skip_ff (&dinfo); } if (hsf[0] == 1) { //mjpeg_info("YUV 4:4:4 sampling encountered ! Deallocating special row buffer\n"); for (y = 0; y < 16; y++) // allocate a special buffer for the extra sampling depth { free(row1_444[y]); free(row2_444[y]); } } jpeg_destroy_decompress (&dinfo); if(jerr.warning_seen) return 1; else return 0; ERR_EXIT: jpeg_destroy_decompress (&dinfo); return -1; } /* * jpeg_data: Buffer with jpeg data to decode, must be grayscale mode * len: Length of buffer * itype: 0: Not interlaced * 1: Interlaced, Top field first * 2: Interlaced, Bottom field first * ctype Chroma format for decompression. * Currently only Y4M_CHROMA_{420JPEG,422} are available */ int decode_jpeg_gray_raw (unsigned char *jpeg_data, int len, int itype, int ctype, int width, int height, unsigned char *raw0, unsigned char *raw1, unsigned char *raw2) { int numfields, hsf[3], vsf[3], field, yl, yc, x, y, xsl, xsc, xs, xd, hdown; JSAMPROW row0[16] = { buf0[0], buf0[1], buf0[2], buf0[3], buf0[4], buf0[5], buf0[6], buf0[7], buf0[8], buf0[9], buf0[10], buf0[11], buf0[12], buf0[13], buf0[14], buf0[15] }; JSAMPARRAY scanarray[3] = { row0 }; struct jpeg_decompress_struct dinfo; struct my_error_mgr jerr; mjpeg_info("decoding jpeg gray\n"); /* We set up the normal JPEG error routines, then override error_exit. */ dinfo.err = jpeg_std_error (&jerr.pub); jerr.pub.error_exit = my_error_exit; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp (jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ jpeg_destroy_decompress (&dinfo); return -1; } jpeg_create_decompress (&dinfo); jpeg_buffer_src (&dinfo, jpeg_data, len); /* Read header, make some checks and try to figure out what the user really wants */ jpeg_read_header (&dinfo, TRUE); dinfo.raw_data_out = TRUE; dinfo.out_color_space = JCS_GRAYSCALE; dinfo.dct_method = JDCT_IFAST; if (dinfo.jpeg_color_space != JCS_GRAYSCALE) { mjpeg_error( "FATAL: Expected grayscale colorspace for JPEG raw decoding"); goto ERR_EXIT; } guarantee_huff_tables(&dinfo); jpeg_start_decompress (&dinfo); hsf[0] = 1; hsf[1] = 1; hsf[2] = 1; vsf[0]= 1; vsf[1] = 1; vsf[2] = 1; /* Height match image height or be exact twice the image height */ if (dinfo.output_height == height) { numfields = 1; } else if (2 * dinfo.output_height == height) { numfields = 2; } else { mjpeg_error( "Read JPEG: requested height = %d, height of image = %d", height, dinfo.output_height); goto ERR_EXIT; } /* Width is more flexible */ if (dinfo.output_width > MAX_LUMA_WIDTH) { mjpeg_error( "Image width of %d exceeds max", dinfo.output_width); goto ERR_EXIT; } if (width < 2 * dinfo.output_width / 3) { /* Downsample 2:1 */ hdown = 1; if (2 * width < dinfo.output_width) xsl = (dinfo.output_width - 2 * width) / 2; else xsl = 0; } else if (width == 2 * dinfo.output_width / 3) { /* special case of 3:2 downsampling */ hdown = 2; xsl = 0; } else { /* No downsampling */ hdown = 0; if (width < dinfo.output_width) xsl = (dinfo.output_width - width) / 2; else xsl = 0; } /* Make xsl even, calculate xsc */ xsl = xsl & ~1; xsc = xsl / 2; yl = yc = 0; for (field = 0; field < numfields; field++) { if (field > 0) { jpeg_read_header (&dinfo, TRUE); dinfo.raw_data_out = TRUE; dinfo.out_color_space = JCS_GRAYSCALE; dinfo.dct_method = JDCT_IFAST; jpeg_start_decompress (&dinfo); } if (numfields == 2) { switch (itype) { case Y4M_ILACE_TOP_FIRST: yl = yc = field; break; case Y4M_ILACE_BOTTOM_FIRST: yl = yc = (1 - field); break; default: mjpeg_error( "Input is interlaced but no interlacing set"); goto ERR_EXIT; } } else yl = yc = 0; while (dinfo.output_scanline < dinfo.output_height) { jpeg_read_raw_data (&dinfo, scanarray, 16); for (y = 0; y < 8 * vsf[0]; yl += numfields, y++) { xd = yl * width; xs = xsl; if (hdown == 0) // no horiz downsampling for (x = 0; x < width; x++) raw0[xd++] = row0[y][xs++]; else if (hdown == 1) // half the res for (x = 0; x < width; x++, xs += 2) raw0[xd++] = (row0[y][xs] + row0[y][xs + 1]) >> 1; else // 2:3 downsampling for (x = 0; x < width / 2; x++, xd += 2, xs += 3) { raw0[xd] = (2 * row0[y][xs] + row0[y][xs + 1]) / 3; raw0[xd + 1] = (2 * row0[y][xs + 2] + row0[y][xs + 1]) / 3; } } //mjpeg_info("/* Horizontal downsampling of chroma - in Grayscale, all this is ZERO ! */"); for (y = 0; y < 8; y++) { xs = xsc; if (hdown == 0) for (x = 0; x < width / 2; x++, xs++) { chr1[y][x] = 0; //row1[y][xs]; chr2[y][x] = 0; //row2[y][xs]; } else if (hdown == 1) for (x = 0; x < width / 2; x++, xs += 2) { chr1[y][x] = 0; //(row1[y][xs] + row1[y][xs + 1]) >> 1; chr2[y][x] = 0; //(row2[y][xs] + row2[y][xs + 1]) >> 1; } else for (x = 0; x < width / 2; x += 2, xs += 3) { chr1[y][x] = 0; //(2 * row1[y][xs] + row1[y][xs + 1]) / 3; chr1[y][x + 1] = 0; //(2 * row1[y][xs + 2] + row1[y][xs + 1]) / 3; chr2[y][x] = 0; // (2 * row2[y][xs] + row2[y][xs + 1]) / 3; chr2[y][x + 1] = 0; //(2 * row2[y][xs + 2] + row2[y][xs + 1]) / 3; } } //mjpeg_info("/* Vertical downsampling of chroma, line %d, max %d */", dinfo.output_scanline, dinfo.output_height); switch (ctype) { case Y4M_CHROMA_422: if (vsf[0] == 1) { /* Just copy */ for (y = 0; y < 8 /*&& yc < height */; y++, yc += numfields) { xd = yc * width / 2; for (x = 0; x < width / 2; x++, xd++) { raw1[xd] = 127; //chr1[y][x]; raw2[xd] = 127; //chr2[y][x]; } } } else { /* upsample */ for (y = 0; y < 8 /*&& yc < height */; y++) { xd = yc * width / 2; for (x = 0; x < width / 2; x++, xd++) { raw1[xd] = 127; //chr1[y][x]; raw2[xd] = 127; //chr2[y][x]; } yc += numfields; xd = yc * width / 2; for (x = 0; x < width / 2; x++, xd++) { raw1[xd] = 127; //chr1[y][x]; raw2[xd] = 127; //chr2[y][x]; } yc += numfields; } } break; /* * should be case Y4M_CHROMA_420JPEG: but use default: for compatibility. Some * pass things like '420' in with the expectation that anything other than * Y4M_CHROMA_422 will default to 420JPEG. */ default: if (vsf[0] == 1) { /* Really downsample */ for (y = 0; y < 8; y += 2, yc += numfields) { xd = yc * width / 2; for (x = 0; x < width / 2; x++, xd++) { raw1[xd] = 127; //(chr1[y][x] + chr1[y + 1][x]) >> 1; raw2[xd] = 127; //(chr2[y][x] + chr2[y + 1][x]) >> 1; } } } else { /* Just copy */ for (y = 0; y < 8; y++, yc += numfields) { xd = yc * width / 2; for (x = 0; x < width / 2; x++, xd++) { raw1[xd] = 127; //chr1[y][x]; raw2[xd] = 127; //chr2[y][x]; } } } break; } } (void) jpeg_finish_decompress (&dinfo); if (field == 0 && numfields > 1) jpeg_skip_ff (&dinfo); } jpeg_destroy_decompress (&dinfo); return 0; ERR_EXIT: jpeg_destroy_decompress (&dinfo); return -1; } /******************************************************************* * * * encode_jpeg_data: Compress raw YCbCr data (output JPEG * * may be interlaced * * * *******************************************************************/ /* * jpeg_data: Buffer to hold output jpeg * len: Length of buffer * itype: 0: Not interlaced * 1: Interlaced, Top field first * 2: Interlaced, Bottom field first * ctype Chroma format for decompression. * Currently only Y4M_CHROMA_{420JPEG,422} are available */ int encode_jpeg_raw (unsigned char *jpeg_data, int len, int quality, int itype, int ctype, int width, int height, unsigned char *raw0, unsigned char *raw1, unsigned char *raw2) { int numfields, field, yl, yc, y, i; JSAMPROW row0[16] = { buf0[0], buf0[1], buf0[2], buf0[3], buf0[4], buf0[5], buf0[6], buf0[7], buf0[8], buf0[9], buf0[10], buf0[11], buf0[12], buf0[13], buf0[14], buf0[15] }; JSAMPROW row1[8] = { buf1[0], buf1[1], buf1[2], buf1[3], buf1[4], buf1[5], buf1[6], buf1[7] }; JSAMPROW row2[8] = { buf2[0], buf2[1], buf2[2], buf2[3], buf2[4], buf2[5], buf2[6], buf2[7] }; JSAMPARRAY scanarray[3] = { row0, row1, row2 }; struct jpeg_compress_struct cinfo; struct my_error_mgr jerr; /* We set up the normal JPEG error routines, then override error_exit. */ cinfo.err = jpeg_std_error (&jerr.pub); jerr.pub.error_exit = my_error_exit; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp (jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ jpeg_destroy_compress (&cinfo); return -1; } jpeg_create_compress (&cinfo); jpeg_buffer_dest(&cinfo, jpeg_data, len); /* Set some jpeg header fields */ cinfo.input_components = 3; jpeg_set_defaults (&cinfo); jpeg_set_quality (&cinfo, quality, FALSE); cinfo.raw_data_in = TRUE; cinfo.in_color_space = JCS_YCbCr; cinfo.dct_method = JDCT_IFAST; cinfo.input_gamma = 1.0; cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 1; /*1||2 */ cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = 1; /*1||2 */ cinfo.comp_info[2].v_samp_factor = 1; if ((width>4096)||(height>4096)) { mjpeg_error( "Image dimensions (%dx%d) exceed lavtools' max (4096x4096)", width, height); goto ERR_EXIT; } if ((width%16)||(height%16)) { mjpeg_error( "Image dimensions (%dx%d) not multiples of 16", width, height); goto ERR_EXIT; } cinfo.image_width = width; switch (itype) { case Y4M_ILACE_TOP_FIRST: case Y4M_ILACE_BOTTOM_FIRST: /* interlaced */ numfields = 2; break; default: numfields = 1; if (height > 2048) { mjpeg_error( "Image height (%d) exceeds lavtools max for non-interlaced frames", height); goto ERR_EXIT; } } cinfo.image_height = height/numfields; yl = yc = 0; /* y luma, chroma */ for (field = 0; field < numfields; field++) { jpeg_start_compress (&cinfo, FALSE); if (numfields == 2) { static const JOCTET marker0[40]; jpeg_write_marker(&cinfo, JPEG_APP0, marker0, 14); jpeg_write_marker(&cinfo, JPEG_APP0+1, marker0, 40); switch (itype) { case Y4M_ILACE_TOP_FIRST: /* top field first */ yl = yc = field; break; case Y4M_ILACE_BOTTOM_FIRST: /* bottom field first */ yl = yc = (1 - field); break; default: mjpeg_error( "Input is interlaced but no interlacing set"); goto ERR_EXIT; } } else yl = yc = 0; while (cinfo.next_scanline < cinfo.image_height) { for (y = 0; y < 8 * cinfo.comp_info[0].v_samp_factor; yl += numfields, y++) { row0[y] = &raw0[yl * width]; } for (y = 0; y < 8; y++) { row1[y] = &raw1[yc * width / 2]; row2[y] = &raw2[yc * width / 2]; if ((ctype == Y4M_CHROMA_422) || (y%2)) yc += numfields; } jpeg_write_raw_data (&cinfo, scanarray, 8 * cinfo.comp_info[0].v_samp_factor); } (void) jpeg_finish_compress (&cinfo); } /* FIXME */ i = len - cinfo.dest->free_in_buffer; jpeg_destroy_compress (&cinfo); return i; /* size of jpeg */ ERR_EXIT: jpeg_destroy_compress (&cinfo); return -1; } mjpegtools-2.1.0/lavtools/frequencies.c0000644000175000017500000005275110213253101020527 0ustar glowwormglowworm#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "frequencies.h" struct STRTAB { long nr; const char *str; }; /* --------------------------------------------------------------------- */ /* US broadcast */ static struct CHANLIST ntsc_bcast[] = { { "2", 55250 }, { "3", 61250 }, { "4", 67250 }, { "5", 77250 }, { "6", 83250 }, { "7", 175250 }, { "8", 181250 }, { "9", 187250 }, { "10", 193250 }, { "11", 199250 }, { "12", 205250 }, { "13", 211250 }, { "14", 471250 }, { "15", 477250 }, { "16", 483250 }, { "17", 489250 }, { "18", 495250 }, { "19", 501250 }, { "20", 507250 }, { "21", 513250 }, { "22", 519250 }, { "23", 525250 }, { "24", 531250 }, { "25", 537250 }, { "26", 543250 }, { "27", 549250 }, { "28", 555250 }, { "29", 561250 }, { "30", 567250 }, { "31", 573250 }, { "32", 579250 }, { "33", 585250 }, { "34", 591250 }, { "35", 597250 }, { "36", 603250 }, { "37", 609250 }, { "38", 615250 }, { "39", 621250 }, { "40", 627250 }, { "41", 633250 }, { "42", 639250 }, { "43", 645250 }, { "44", 651250 }, { "45", 657250 }, { "46", 663250 }, { "47", 669250 }, { "48", 675250 }, { "49", 681250 }, { "50", 687250 }, { "51", 693250 }, { "52", 699250 }, { "53", 705250 }, { "54", 711250 }, { "55", 717250 }, { "56", 723250 }, { "57", 729250 }, { "58", 735250 }, { "59", 741250 }, { "60", 747250 }, { "61", 753250 }, { "62", 759250 }, { "63", 765250 }, { "64", 771250 }, { "65", 777250 }, { "66", 783250 }, { "67", 789250 }, { "68", 795250 }, { "69", 801250 }, { "70", 807250 }, { "71", 813250 }, { "72", 819250 }, { "73", 825250 }, { "74", 831250 }, { "75", 837250 }, { "76", 843250 }, { "77", 849250 }, { "78", 855250 }, { "79", 861250 }, { "80", 867250 }, { "81", 873250 }, { "82", 879250 }, { "83", 885250 }, }; /* US cable */ static struct CHANLIST ntsc_cable[] = { { "1", 73250 }, { "2", 55250 }, { "3", 61250 }, { "4", 67250 }, { "5", 77250 }, { "6", 83250 }, { "7", 175250 }, { "8", 181250 }, { "9", 187250 }, { "10", 193250 }, { "11", 199250 }, { "12", 205250 }, { "13", 211250 }, { "14", 121250 }, { "15", 127250 }, { "16", 133250 }, { "17", 139250 }, { "18", 145250 }, { "19", 151250 }, { "20", 157250 }, { "21", 163250 }, { "22", 169250 }, { "23", 217250 }, { "24", 223250 }, { "25", 229250 }, { "26", 235250 }, { "27", 241250 }, { "28", 247250 }, { "29", 253250 }, { "30", 259250 }, { "31", 265250 }, { "32", 271250 }, { "33", 277250 }, { "34", 283250 }, { "35", 289250 }, { "36", 295250 }, { "37", 301250 }, { "38", 307250 }, { "39", 313250 }, { "40", 319250 }, { "41", 325250 }, { "42", 331250 }, { "43", 337250 }, { "44", 343250 }, { "45", 349250 }, { "46", 355250 }, { "47", 361250 }, { "48", 367250 }, { "49", 373250 }, { "50", 379250 }, { "51", 385250 }, { "52", 391250 }, { "53", 397250 }, { "54", 403250 }, { "55", 409250 }, { "56", 415250 }, { "57", 421250 }, { "58", 427250 }, { "59", 433250 }, { "60", 439250 }, { "61", 445250 }, { "62", 451250 }, { "63", 457250 }, { "64", 463250 }, { "65", 469250 }, { "66", 475250 }, { "67", 481250 }, { "68", 487250 }, { "69", 493250 }, { "70", 499250 }, { "71", 505250 }, { "72", 511250 }, { "73", 517250 }, { "74", 523250 }, { "75", 529250 }, { "76", 535250 }, { "77", 541250 }, { "78", 547250 }, { "79", 553250 }, { "80", 559250 }, { "81", 565250 }, { "82", 571250 }, { "83", 577250 }, { "84", 583250 }, { "85", 589250 }, { "86", 595250 }, { "87", 601250 }, { "88", 607250 }, { "89", 613250 }, { "90", 619250 }, { "91", 625250 }, { "92", 631250 }, { "93", 637250 }, { "94", 643250 }, { "95", 91250 }, { "96", 97250 }, { "97", 103250 }, { "98", 109250 }, { "99", 115250 }, { "100", 649250 }, { "101", 655250 }, { "102", 661250 }, { "103", 667250 }, { "104", 673250 }, { "105", 679250 }, { "106", 685250 }, { "107", 691250 }, { "108", 697250 }, { "109", 703250 }, { "110", 709250 }, { "111", 715250 }, { "112", 721250 }, { "113", 727250 }, { "114", 733250 }, { "115", 739250 }, { "116", 745250 }, { "117", 751250 }, { "118", 757250 }, { "119", 763250 }, { "120", 769250 }, { "121", 775250 }, { "122", 781250 }, { "123", 787250 }, { "124", 793250 }, { "125", 799250 }, { "T7", 8250 }, { "T8", 14250 }, { "T9", 20250 }, { "T10", 26250 }, { "T11", 32250 }, { "T12", 38250 }, { "T13", 44250 }, { "T14", 50250 } }; /* US HRC */ static struct CHANLIST ntsc_hrc[] = { { "1", 72000 }, { "2", 54000 }, { "3", 60000 }, { "4", 66000 }, { "5", 78000 }, { "6", 84000 }, { "7", 174000 }, { "8", 180000 }, { "9", 186000 }, { "10", 192000 }, { "11", 198000 }, { "12", 204000 }, { "13", 210000 }, { "14", 120000 }, { "15", 126000 }, { "16", 132000 }, { "17", 138000 }, { "18", 144000 }, { "19", 150000 }, { "20", 156000 }, { "21", 162000 }, { "22", 168000 }, { "23", 216000 }, { "24", 222000 }, { "25", 228000 }, { "26", 234000 }, { "27", 240000 }, { "28", 246000 }, { "29", 252000 }, { "30", 258000 }, { "31", 264000 }, { "32", 270000 }, { "33", 276000 }, { "34", 282000 }, { "35", 288000 }, { "36", 294000 }, { "37", 300000 }, { "38", 306000 }, { "39", 312000 }, { "40", 318000 }, { "41", 324000 }, { "42", 330000 }, { "43", 336000 }, { "44", 342000 }, { "45", 348000 }, { "46", 354000 }, { "47", 360000 }, { "48", 366000 }, { "49", 372000 }, { "50", 378000 }, { "51", 384000 }, { "52", 390000 }, { "53", 396000 }, { "54", 402000 }, { "55", 408000 }, { "56", 414000 }, { "57", 420000 }, { "58", 426000 }, { "59", 432000 }, { "60", 438000 }, { "61", 444000 }, { "62", 450000 }, { "63", 456000 }, { "64", 462000 }, { "65", 468000 }, { "66", 474000 }, { "67", 480000 }, { "68", 486000 }, { "69", 492000 }, { "70", 498000 }, { "71", 504000 }, { "72", 510000 }, { "73", 516000 }, { "74", 522000 }, { "75", 528000 }, { "76", 534000 }, { "77", 540000 }, { "78", 546000 }, { "79", 552000 }, { "80", 558000 }, { "81", 564000 }, { "82", 570000 }, { "83", 576000 }, { "84", 582000 }, { "85", 588000 }, { "86", 594000 }, { "87", 600000 }, { "88", 606000 }, { "89", 612000 }, { "90", 618000 }, { "91", 624000 }, { "92", 630000 }, { "93", 636000 }, { "94", 642000 }, { "95", 900000 }, { "96", 960000 }, { "97", 102000 }, { "98", 108000 }, { "99", 114000 }, { "100", 648000 }, { "101", 654000 }, { "102", 660000 }, { "103", 666000 }, { "104", 672000 }, { "105", 678000 }, { "106", 684000 }, { "107", 690000 }, { "108", 696000 }, { "109", 702000 }, { "110", 708000 }, { "111", 714000 }, { "112", 720000 }, { "113", 726000 }, { "114", 732000 }, { "115", 738000 }, { "116", 744000 }, { "117", 750000 }, { "118", 756000 }, { "119", 762000 }, { "120", 768000 }, { "121", 774000 }, { "122", 780000 }, { "123", 786000 }, { "124", 792000 }, { "125", 798000 }, { "T7", 7000 }, { "T8", 13000 }, { "T9", 19000 }, { "T10", 25000 }, { "T11", 31000 }, { "T12", 37000 }, { "T13", 43000 }, { "T14", 49000 }, }; /* ---------------------------------------------------------------------*/ /* JP broadcast */ static struct CHANLIST ntsc_bcast_jp[] = { { "1", 91250 }, { "2", 97250 }, { "3", 103250 }, { "4", 171250 }, { "5", 177250 }, { "6", 183250 }, { "7", 189250 }, { "8", 193250 }, { "9", 199250 }, { "10", 205250 }, { "11", 211250 }, { "12", 217250 }, { "13", 471250 }, { "14", 477250 }, { "15", 483250 }, { "16", 489250 }, { "17", 495250 }, { "18", 501250 }, { "19", 507250 }, { "20", 513250 }, { "21", 519250 }, { "22", 525250 }, { "23", 531250 }, { "24", 537250 }, { "25", 543250 }, { "26", 549250 }, { "27", 555250 }, { "28", 561250 }, { "29", 567250 }, { "30", 573250 }, { "31", 579250 }, { "32", 585250 }, { "33", 591250 }, { "34", 597250 }, { "35", 603250 }, { "36", 609250 }, { "37", 615250 }, { "38", 621250 }, { "39", 627250 }, { "40", 633250 }, { "41", 639250 }, { "42", 645250 }, { "43", 651250 }, { "44", 657250 }, { "45", 663250 }, { "46", 669250 }, { "47", 675250 }, { "48", 681250 }, { "49", 687250 }, { "50", 693250 }, { "51", 699250 }, { "52", 705250 }, { "53", 711250 }, { "54", 717250 }, { "55", 723250 }, { "56", 729250 }, { "57", 735250 }, { "58", 741250 }, { "59", 747250 }, { "60", 753250 }, { "61", 759250 }, { "62", 765250 }, }; /* JP cable */ static struct CHANLIST ntsc_cable_jp[] = { { "13", 109250 }, { "14", 115250 }, { "15", 121250 }, { "16", 127250 }, { "17", 133250 }, { "18", 139250 }, { "19", 145250 }, { "20", 151250 }, { "21", 157250 }, { "22", 165250 }, { "23", 223250 }, { "24", 231250 }, { "25", 237250 }, { "26", 243250 }, { "27", 249250 }, { "28", 253250 }, { "29", 259250 }, { "30", 265250 }, { "31", 271250 }, { "32", 277250 }, { "33", 283250 }, { "34", 289250 }, { "35", 295250 }, { "36", 301250 }, { "37", 307250 }, { "38", 313250 }, { "39", 319250 }, { "40", 325250 }, { "41", 331250 }, { "42", 337250 }, { "43", 343250 }, { "44", 349250 }, { "45", 355250 }, { "46", 361250 }, { "47", 367250 }, { "48", 373250 }, { "49", 379250 }, { "50", 385250 }, { "51", 391250 }, { "52", 397250 }, { "53", 403250 }, { "54", 409250 }, { "55", 415250 }, { "56", 421250 }, { "57", 427250 }, { "58", 433250 }, { "59", 439250 }, { "60", 445250 }, { "61", 451250 }, { "62", 457250 }, { "63", 463250 }, }; /* ---------------------------------------------------------------------*/ /* australia */ static struct CHANLIST pal_australia[] = { { "0", 46250 }, { "1", 57250 }, { "2", 64250 }, { "3", 86250 }, { "4", 95250 }, { "5", 102250 }, { "5A", 138250 }, { "6", 175250 }, { "7", 182250 }, { "8", 189250 }, { "9", 196250 }, { "10", 209250 }, { "11", 216250 }, { "28", 527250 }, { "29", 534250 }, { "30", 541250 }, { "31", 548250 }, { "32", 555250 }, { "33", 562250 }, { "34", 569250 }, { "35", 576250 }, { "36", 591250 }, { "39", 604250 }, { "40", 611250 }, { "41", 618250 }, { "42", 625250 }, { "43", 632250 }, { "44", 639250 }, { "45", 646250 }, { "46", 653250 }, { "47", 660250 }, { "48", 667250 }, { "49", 674250 }, { "50", 681250 }, { "51", 688250 }, { "52", 695250 }, { "53", 702250 }, { "54", 709250 }, { "55", 716250 }, { "56", 723250 }, { "57", 730250 }, { "58", 737250 }, { "59", 744250 }, { "60", 751250 }, { "61", 758250 }, { "62", 765250 }, { "63", 772250 }, { "64", 779250 }, { "65", 786250 }, { "66", 793250 }, { "67", 800250 }, { "68", 807250 }, { "69", 814250 }, }; /* --------------------------------------------------------------------- */ /* europe */ /* CCIR frequencies */ #define FREQ_CCIR_I_III \ { "E2", 48250 }, \ { "E3", 55250 }, \ { "E4", 62250 }, \ \ { "S01", 69250 }, \ { "S02", 76250 }, \ { "S03", 83250 }, \ \ { "E5", 175250 }, \ { "E6", 182250 }, \ { "E7", 189250 }, \ { "E8", 196250 }, \ { "E9", 203250 }, \ { "E10", 210250 }, \ { "E11", 217250 }, \ { "E12", 224250 } #define FREQ_CCIR_SL_SH \ { "SE1", 105250 }, \ { "SE2", 112250 }, \ { "SE3", 119250 }, \ { "SE4", 126250 }, \ { "SE5", 133250 }, \ { "SE6", 140250 }, \ { "SE7", 147250 }, \ { "SE8", 154250 }, \ { "SE9", 161250 }, \ { "SE10", 168250 }, \ \ { "SE11", 231250 }, \ { "SE12", 238250 }, \ { "SE13", 245250 }, \ { "SE14", 252250 }, \ { "SE15", 259250 }, \ { "SE16", 266250 }, \ { "SE17", 273250 }, \ { "SE18", 280250 }, \ { "SE19", 287250 }, \ { "SE20", 294250 } #define FREQ_CCIR_H \ { "S21", 303250 }, \ { "S22", 311250 }, \ { "S23", 319250 }, \ { "S24", 327250 }, \ { "S25", 335250 }, \ { "S26", 343250 }, \ { "S27", 351250 }, \ { "S28", 359250 }, \ { "S29", 367250 }, \ { "S30", 375250 }, \ { "S31", 383250 }, \ { "S32", 391250 }, \ { "S33", 399250 }, \ { "S34", 407250 }, \ { "S35", 415250 }, \ { "S36", 423250 }, \ { "S37", 431250 }, \ { "S38", 439250 }, \ { "S39", 447250 }, \ { "S40", 455250 }, \ { "S41", 463250 } /* OIRT frequencies */ #define FREQ_OIRT_I_III \ { "R1", 49750 }, \ { "R2", 59250 }, \ \ { "R3", 77250 }, \ { "R4", 85250 }, \ { "R5", 93250 }, \ \ { "R6", 175250 }, \ { "R7", 183250 }, \ { "R8", 191250 }, \ { "R9", 199250 }, \ { "R10", 207250 }, \ { "R11", 215250 }, \ { "R12", 223250 } #define FREQ_OIRT_SL_SH \ { "SR1", 111250 }, \ { "SR2", 119250 }, \ { "SR3", 127250 }, \ { "SR4", 135250 }, \ { "SR5", 143250 }, \ { "SR6", 151250 }, \ { "SR7", 159250 }, \ { "SR8", 167250 }, \ \ { "SR11", 231250 }, \ { "SR12", 239250 }, \ { "SR13", 247250 }, \ { "SR14", 255250 }, \ { "SR15", 263250 }, \ { "SR16", 271250 }, \ { "SR17", 279250 }, \ { "SR18", 287250 }, \ { "SR19", 295250 } #define FREQ_UHF \ { "21", 471250 }, \ { "22", 479250 }, \ { "23", 487250 }, \ { "24", 495250 }, \ { "25", 503250 }, \ { "26", 511250 }, \ { "27", 519250 }, \ { "28", 527250 }, \ { "29", 535250 }, \ { "30", 543250 }, \ { "31", 551250 }, \ { "32", 559250 }, \ { "33", 567250 }, \ { "34", 575250 }, \ { "35", 583250 }, \ { "36", 591250 }, \ { "37", 599250 }, \ { "38", 607250 }, \ { "39", 615250 }, \ { "40", 623250 }, \ { "41", 631250 }, \ { "42", 639250 }, \ { "43", 647250 }, \ { "44", 655250 }, \ { "45", 663250 }, \ { "46", 671250 }, \ { "47", 679250 }, \ { "48", 687250 }, \ { "49", 695250 }, \ { "50", 703250 }, \ { "51", 711250 }, \ { "52", 719250 }, \ { "53", 727250 }, \ { "54", 735250 }, \ { "55", 743250 }, \ { "56", 751250 }, \ { "57", 759250 }, \ { "58", 767250 }, \ { "59", 775250 }, \ { "60", 783250 }, \ { "61", 791250 }, \ { "62", 799250 }, \ { "63", 807250 }, \ { "64", 815250 }, \ { "65", 823250 }, \ { "66", 831250 }, \ { "67", 839250 }, \ { "68", 847250 }, \ { "69", 855250 } static struct CHANLIST europe_west[] = { FREQ_CCIR_I_III, FREQ_CCIR_SL_SH, FREQ_CCIR_H, FREQ_UHF }; static struct CHANLIST europe_east[] = { FREQ_OIRT_I_III, FREQ_OIRT_SL_SH, FREQ_CCIR_I_III, FREQ_CCIR_SL_SH, FREQ_CCIR_H, FREQ_UHF }; static struct CHANLIST pal_italy[] = { { "2", 53750 }, { "3", 62250 }, { "4", 82250 }, { "5", 175250 }, { "6", 183750 }, { "7", 192250 }, { "8", 201250 }, { "9", 210250 }, { "10", 210250 }, { "11", 217250 }, { "12", 224250 }, FREQ_UHF }; static struct CHANLIST pal_ireland[] = { { "0", 45750 }, { "1", 53750 }, { "2", 61750 }, { "3", 175250 }, { "4", 183250 }, { "5", 191250 }, { "6", 199250 }, { "7", 207250 }, { "8", 215250 }, FREQ_UHF, }; static struct CHANLIST secam_france[] = { { "K01", 47750 }, { "K02", 55750 }, { "K03", 60500 }, { "K04", 63750 }, { "K05", 176000 }, { "K06", 184000 }, { "K07", 192000 }, { "K08", 200000 }, { "K09", 208000 }, { "K10", 216000 }, { "KB", 116750 }, { "KC", 128750 }, { "KD", 140750 }, { "KE", 159750 }, { "KF", 164750 }, { "KG", 176750 }, { "KH", 188750 }, { "KI", 200750 }, { "KJ", 212750 }, { "KK", 224750 }, { "KL", 236750 }, { "KM", 248750 }, { "KN", 260750 }, { "KO", 272750 }, { "KP", 284750 }, { "KQ", 296750 }, { "H01", 303250 }, { "H02", 311250 }, { "H03", 319250 }, { "H04", 327250 }, { "H05", 335250 }, { "H06", 343250 }, { "H07", 351250 }, { "H08", 359250 }, { "H09", 367250 }, { "H10", 375250 }, { "H11", 383250 }, { "H12", 391250 }, { "H13", 399250 }, { "H14", 407250 }, { "H15", 415250 }, { "H16", 423250 }, { "H17", 431250 }, { "H18", 439250 }, { "H19", 447250 }, FREQ_UHF, }; /* --------------------------------------------------------------------- */ static struct CHANLIST pal_newzealand[] = { { "1", 45250 }, { "2", 55250 }, { "3", 62250 }, { "4", 175250 }, { "5", 182250 }, { "6", 189250 }, { "7", 196250 }, { "8", 203250 }, { "9", 210250 }, { "10", 217250 }, { "11", 224250 }, FREQ_UHF, }; /* --------------------------------------------------------------------- */ /* China broadcast */ static struct CHANLIST pal_bcast_cn[] = { { "1", 49750 }, { "2", 57750 }, { "3", 65750 }, { "4", 77250 }, { "5", 85250 }, { "6", 112250 }, { "7", 120250 }, { "8", 128250 }, { "9", 136250 }, { "10", 144250 }, { "11", 152250 }, { "12", 160250 }, { "13", 168250 }, { "14", 176250 }, { "15", 184250 }, { "16", 192250 }, { "17", 200250 }, { "18", 208250 }, { "19", 216250 }, { "20", 224250 }, { "21", 232250 }, { "22", 240250 }, { "23", 248250 }, { "24", 256250 }, { "25", 264250 }, { "26", 272250 }, { "27", 280250 }, { "28", 288250 }, { "29", 296250 }, { "30", 304250 }, { "31", 312250 }, { "32", 320250 }, { "33", 328250 }, { "34", 336250 }, { "35", 344250 }, { "36", 352250 }, { "37", 360250 }, { "38", 368250 }, { "39", 376250 }, { "40", 384250 }, { "41", 392250 }, { "42", 400250 }, { "43", 408250 }, { "44", 416250 }, { "45", 424250 }, { "46", 432250 }, { "47", 440250 }, { "48", 448250 }, { "49", 456250 }, { "50", 463250 }, { "51", 471250 }, { "52", 479250 }, { "53", 487250 }, { "54", 495250 }, { "55", 503250 }, { "56", 511250 }, { "57", 519250 }, { "58", 527250 }, { "59", 535250 }, { "60", 543250 }, { "61", 551250 }, { "62", 559250 }, { "63", 607250 }, { "64", 615250 }, { "65", 623250 }, { "66", 631250 }, { "67", 639250 }, { "68", 647250 }, { "69", 655250 }, { "70", 663250 }, { "71", 671250 }, { "72", 679250 }, { "73", 687250 }, { "74", 695250 }, { "75", 703250 }, { "76", 711250 }, { "77", 719250 }, { "78", 727250 }, { "79", 735250 }, { "80", 743250 }, { "81", 751250 }, { "82", 759250 }, { "83", 767250 }, { "84", 775250 }, { "85", 783250 }, { "86", 791250 }, { "87", 799250 }, { "88", 807250 }, { "89", 815250 }, { "90", 823250 }, { "91", 831250 }, { "92", 839250 }, { "93", 847250 }, { "94", 855250 }, }; /* --------------------------------------------------------------------- */ struct CHANLISTS chanlists[] = { { "us-bcast", ntsc_bcast, CHAN_COUNT(ntsc_bcast) }, { "us-cable", ntsc_cable, CHAN_COUNT(ntsc_cable) }, { "us-cable-hrc", ntsc_hrc, CHAN_COUNT(ntsc_hrc) }, { "japan-bcast", ntsc_bcast_jp, CHAN_COUNT(ntsc_bcast_jp) }, { "japan-cable", ntsc_cable_jp, CHAN_COUNT(ntsc_cable_jp) }, { "europe-west", europe_west, CHAN_COUNT(europe_west) }, { "europe-east", europe_east, CHAN_COUNT(europe_east) }, { "italy", pal_italy, CHAN_COUNT(pal_italy) }, { "newzealand", pal_newzealand, CHAN_COUNT(pal_newzealand) }, { "australia", pal_australia, CHAN_COUNT(pal_australia) }, { "ireland", pal_ireland, CHAN_COUNT(pal_ireland) }, { "france", secam_france, CHAN_COUNT(secam_france) }, { "china-bcast", pal_bcast_cn, CHAN_COUNT(pal_bcast_cn) }, { NULL, NULL, 0 } /* EOF */ }; int chantab = 5; struct CHANLIST *chanlist = europe_west; int chancount = CHAN_COUNT(europe_west); mjpegtools-2.1.0/lavtools/audiolib.c0000644000175000017500000007440311576436712020034 0ustar glowwormglowworm/* Small library for reading and writing audio. This library forks an audio task and communicates with it via a shared memory segment. All what this library does can be done in principal with ordinary read/write calls on the sound device. The Linux audio driver uses so small buffers, however, that overruns/underruns are unavoidable in many cases. Copyright (C) 2000 Rainer Johanni This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include #include #include #include #include #include #include #ifdef HAVE_SYS_SOUNDCARD_H #include #endif #include #include #include #include #include #include /* The shared memory things */ #include #include #ifndef FORK_NOT_THREAD #include #endif #include "mjpeg_logging.h" #include "audiolib.h" #ifdef FORK_NOT_THREAD static int pid; /* pid of child */ static int shm_seg; #else static pthread_t capture_thread; #endif #define TIME_STAMP_TOL 100000 /* tolerance for timestamps in us */ #define N_SHM_BUFFS 256 /* Number of buffers, must be a power of 2 */ #define SHM_BUFF_MASK (N_SHM_BUFFS-1) /* #define BUFFSIZE (8192) */ /* A.Stevens Jul 2000: Several drivers for modern PCI cards can't deliver frags larger than 4096 so lets not even try for 8192 byte buffer chunks */ #define BUFFSIZE (4096) #define NBUF(x) ((x)&SHM_BUFF_MASK) struct shm_buff_s { volatile uint8_t audio_data[N_SHM_BUFFS][BUFFSIZE]; volatile int used_flag[N_SHM_BUFFS]; volatile struct timeval tmstmp[N_SHM_BUFFS]; volatile int status[N_SHM_BUFFS]; volatile int exit_flag; /* set by parent */ volatile int audio_status; /* set by audio task */ volatile int audio_start; /* trigger start in playing */ volatile char error_string[4096]; } *shmemptr; static int audio_buffer_size = BUFFSIZE; /* The buffer size actually used */ /* The parameters for audio capture/playback */ static int initialized=0; static int audio_capt; /* Flag for capture/playback */ static int mmap_io; /* Flag for using either mmap or read,write */ static int stereo; /* 0: capture mono, 1: capture stereo */ static int audio_size; /* size of an audio sample: 8 or 16 bits */ static int audio_rate; /* sampling rate for audio */ static int audio_byte_rate; /* sampling rate for audio Bps*/ /* Buffer counter */ static int n_audio; /* Bookkeeping of the write buffers */ static char audio_left_buf[BUFFSIZE]; static int audio_bytes_left; /* Number of bytes in audio_left_buf */ static unsigned int n_buffs_output, n_buffs_error; static struct timeval buffer_timestamp; static int usecs_per_buff; /* Forward declarations: */ void do_audio(void); char *audio_strerror(void); void set_timestamp(struct timeval tmstmp); void swpcpy(char *dst, char *src, int num); typedef void *(*start_routine_p)(void *); /* some (internally used only) error numbers */ static int audio_errno = 0; #define AUDIO_ERR_INIT 1 /* Not initialized */ #define AUDIO_ERR_INIT2 2 /* allready initialized */ #define AUDIO_ERR_ASIZE 3 /* audio size not 8 or 16 */ #define AUDIO_ERR_SHMEM 4 /* Error getting shared memory segment */ #define AUDIO_ERR_FORK 5 /* Can not fork audio task */ #define AUDIO_ERR_MODE 6 /* Wrong read/write mode */ #define AUDIO_ERR_BSIZE 7 /* Buffer size for read too small */ #define AUDIO_ERR_TMOUT 8 /* Timeout waiting for audio */ #define AUDIO_ERR_BOVFL 9 /* Buffer overflow when writing */ #define AUDIO_ERR_ATASK 99 /* Audio task died - more in shmemptr->error_string */ static char errstr[4096]; char *audio_strerror(void) { switch(audio_errno) { case 0: strcpy(errstr,"No Error"); break; case AUDIO_ERR_INIT: strcpy(errstr,"Audio not initialized"); break; case AUDIO_ERR_INIT2: strcpy(errstr,"audio_init called but audio allready initialized"); break; case AUDIO_ERR_ASIZE: strcpy(errstr,"audio sample size not 8 or 16"); break; case AUDIO_ERR_SHMEM: strcpy(errstr,"Audio: Error getting shared memory segment"); break; case AUDIO_ERR_FORK: strcpy(errstr,"Can not fork audio task"); break; case AUDIO_ERR_MODE: strcpy(errstr,"Audio: Wrong read/write mode"); break; case AUDIO_ERR_BSIZE: strcpy(errstr,"Audio: Buffer size for read too small"); break; case AUDIO_ERR_TMOUT: strcpy(errstr,"Timeout waiting for audio initialization"); break; case AUDIO_ERR_BOVFL: strcpy(errstr,"Buffer overflow writing audio"); break; case AUDIO_ERR_ATASK: sprintf(errstr,"Audio task died. Reason: %s",shmemptr->error_string); break; default: strcpy(errstr,"Audio: Unknown error"); } return errstr; } /* * audio_init: Initialize audio system. * * a_read 0: User is going to write (output) audio * 1: User is going to read (input) audio * use_read_write 0: use mmap io as opposed to * 1: read/write system calls * a_stereo 0: mono, 1: stereo * a_size size of an audio sample: 8 or 16 bits * a_rate sampling rate for audio * * returns 0 for success, -1 for failure * */ int audio_init(int a_read, int use_read_write, int a_stereo, int a_size, int a_rate) { int i; /* Check if the audio task is allready initialized */ if(initialized) { audio_errno = AUDIO_ERR_INIT2; return -1; } /* Checks of parameters */ if (a_size != 8 && a_size != 16) { audio_errno = AUDIO_ERR_ASIZE; return -1; } if( use_read_write ) mjpeg_info( "Using read(2)/write(2) system call for capture/playpack"); else mjpeg_info( "Using mmap(2) system call for capture/playback"); /* Copy our parameters into static space */ audio_capt = a_read; mmap_io = !use_read_write; stereo = a_stereo; audio_size = a_size; audio_rate = a_rate; /* Reset counters */ n_audio = 0; audio_bytes_left = 0; n_buffs_output = 0; n_buffs_error = 0; buffer_timestamp.tv_sec = 0; buffer_timestamp.tv_usec = 0; /* * Calculate bytes/second of the audio stream */ audio_byte_rate = audio_rate; if (stereo) audio_byte_rate *= 2; if (audio_size==16) audio_byte_rate *= 2; /* Set audio buffer size */ audio_buffer_size = BUFFSIZE; /* A.Stevens Jul 2000 modified to allow cards with max frag size of 4096.... if(tmp<88200) audio_buffer_size = 4096; */ if(audio_byte_rate<44100) audio_buffer_size = BUFFSIZE/2; if(audio_byte_rate<22050) audio_buffer_size = BUFFSIZE/4; /* Do not change the following calculations, they are this way to avoid overflows ! */ usecs_per_buff = audio_buffer_size*100000/audio_byte_rate; usecs_per_buff *= 10; #ifdef FORK_NOT_THREAD /* Allocate shared memory segment */ shm_seg = shmget(IPC_PRIVATE, sizeof(struct shm_buff_s), IPC_CREAT | 0777); if(shm_seg < 0) { audio_errno = AUDIO_ERR_SHMEM; return -1; } /* attach the segment and get its address */ shmemptr = (struct shm_buff_s *) shmat(shm_seg,0,0); if(shmemptr < 0) { audio_errno = AUDIO_ERR_SHMEM; return -1; } /* mark the segment as destroyed, it will be removed after the last process which had attached it is gone */ if( shmctl( shm_seg, IPC_RMID, (struct shmid_ds *)0 ) == -1 ) { audio_errno = AUDIO_ERR_SHMEM; return -1; } #else shmemptr = (struct shm_buff_s *) malloc(sizeof(struct shm_buff_s)); if( shmemptr == NULL ) { audio_errno = AUDIO_ERR_SHMEM; return -1; } #endif /* set the flags in the shared memory */ for(i=0;iused_flag[i] = 0; for(i=0;istatus[i] = 0; shmemptr->exit_flag = 0; shmemptr->audio_status = 0; shmemptr->audio_start = 0; /* do the fork */ #ifdef FORK_NOT_THREAD pid = fork(); if(pid<0) { audio_errno = AUDIO_ERR_FORK; return -1; } /* the child goes into the audio task */ if (pid==0) { /* The audio buffers in Linux are ridiculosly small, therefore the audio task must have a high priority, This call will fail if we are not superuser, we don't care. */ setpriority(PRIO_PROCESS, getpid(), -20); /* Ignore SIGINT while capturing, the parent wants to catch it */ if(audio_capt) signal(SIGINT,SIG_IGN); do_audio(); exit(0); } #else if( pthread_create( &capture_thread, NULL, (start_routine_p)do_audio, NULL) ) { audio_errno = AUDIO_ERR_FORK; return -1; } #endif /* Since most probably errors happen during initialization, we wait until the audio task signals either success or failure */ for(i=0;;i++) { /* Check for timeout, 10 Seconds should be plenty */ if(i>1000) { #ifdef FORK_NOT_THREAD kill(pid,SIGKILL); shmemptr->exit_flag = 1; waitpid(pid,0,0); #else shmemptr->exit_flag = 1; pthread_cancel( capture_thread ); pthread_join( capture_thread, NULL ); #endif audio_errno = AUDIO_ERR_TMOUT; return -1; } if(shmemptr->audio_status<0) { audio_errno = AUDIO_ERR_ATASK; return -1; } if(shmemptr->audio_status>0) break; usleep(10000); } initialized = 1; return 0; } /* * audio_shutdown: Shutdown audio system * * It is important that this routine is called whenever the host * program finished, or else there will be the audio task * left over, having the sound device still opened and preventing * other programs from using sound. * */ void audio_shutdown(void) { if(!initialized) return; /* show the child we want to exit */ shmemptr->exit_flag = 1; #ifdef FORK_NOT_THREAD waitpid(pid,0,0); #else pthread_join( capture_thread, NULL ); #endif initialized = 0; } long audio_get_buffer_size(void) { return audio_buffer_size; } /* * audio_start: Actually trigger the start of audio after all * initializations have been done. * Only for playing! * * returns 0 for success, -1 for failure */ void audio_start(void) { /* signal the audio task that we want to start */ shmemptr->audio_start = 1; } /* * set_timestamp: * Set buffer timestamp either to the value of the tmstmp parameter * or calculate it from previous value */ void set_timestamp(struct timeval tmstmp) { if( tmstmp.tv_sec != 0 ) { /* Time stamp is realiable */ buffer_timestamp = tmstmp; } else { /* Time stamp not reliable - calculate from previous */ if(buffer_timestamp.tv_sec != 0) { buffer_timestamp.tv_usec += usecs_per_buff; while(buffer_timestamp.tv_usec>=1000000) { buffer_timestamp.tv_usec -= 1000000; buffer_timestamp.tv_sec += 1; } } } } /* * swpcpy: like memcpy, but bytes are swapped during copy */ void swpcpy(char *dst, char *src, int num) { int i; num &= ~1; /* Safety first */ for(i=0;iaudio_status < 0) { audio_errno = AUDIO_ERR_ATASK; return -1; } if(!audio_capt) { audio_errno = AUDIO_ERR_MODE; return -1; } if(sizeused_flag[NBUF(n_audio)]) { /* Got an audio sample, copy it to the output buffer */ if(swap && audio_size==16) swpcpy((void*)buf,(void*)shmemptr->audio_data[NBUF(n_audio)],audio_buffer_size); else memcpy((void*)buf,(void*)shmemptr->audio_data[NBUF(n_audio)],audio_buffer_size); /* set the other return values */ set_timestamp(shmemptr->tmstmp[NBUF(n_audio)]); if(tmstmp) *tmstmp = buffer_timestamp; if(status) *status = shmemptr->status[NBUF(n_audio)] > 0; /* reset used_flag, increment n-audio */ shmemptr->status[NBUF(n_audio)] = 0; shmemptr->used_flag[NBUF(n_audio)] = 0; n_audio++; return audio_buffer_size; } return 0; } static void update_output_status(void) { while(shmemptr->status[NBUF(n_buffs_output)]) { if(shmemptr->status[NBUF(n_buffs_output)] < 0) n_buffs_error++; set_timestamp(shmemptr->tmstmp[NBUF(n_buffs_output)]); shmemptr->status[NBUF(n_buffs_output)] = 0; n_buffs_output++; } } void audio_get_output_status(struct timeval *tmstmp, unsigned int *nb_out, unsigned int *nb_err) { if(tmstmp) *tmstmp = buffer_timestamp; if(nb_out) *nb_out = n_buffs_output; if(nb_err) *nb_err = n_buffs_error; } /* * audio_write: Buffer audio data for output * Behaves like a nonblocking write * * buf Buffer with audio data * size Size of the buffer * swap Flag if to swap the endian-ness of 16 bit data * * returns the number of bytes actually written * -1 if an error occured * * If the number of bytes actually written is smaller * than size, the audio ringbuffer is completely filled * */ int audio_write(uint8_t *buf, int size, int swap) { int nb; if(!initialized) { audio_errno = AUDIO_ERR_INIT; return -1; } /* Is audio task still ok ? */ if(shmemptr->audio_status < 0) { audio_errno = AUDIO_ERR_ATASK; return -1; } if(audio_capt) { audio_errno = AUDIO_ERR_MODE; return -1; } update_output_status(); /* If the number of bytes we got isn't big enough to fill the next buffer, copy buf into audio_left_buf */ if (audio_bytes_left+size < audio_buffer_size) { memcpy(audio_left_buf+audio_bytes_left,buf,size); audio_bytes_left += size; return size; } nb = 0; /* if audio_left_buf contains something, output that first */ if (audio_bytes_left) { memcpy(audio_left_buf+audio_bytes_left,buf,audio_buffer_size-audio_bytes_left); if(shmemptr->used_flag[NBUF(n_audio)]) { audio_errno = AUDIO_ERR_BOVFL; return -1; } if(swap && audio_size==16) swpcpy((void*)shmemptr->audio_data[NBUF(n_audio)],audio_left_buf,audio_buffer_size); else memcpy((void*)shmemptr->audio_data[NBUF(n_audio)],audio_left_buf,audio_buffer_size); shmemptr->used_flag[NBUF(n_audio)] = 1; nb = audio_buffer_size-audio_bytes_left; audio_bytes_left = 0; n_audio++; } /* copy directly to the shmem buffers */ while(size-nb >= audio_buffer_size) { if(shmemptr->used_flag[NBUF(n_audio)]) { audio_errno = AUDIO_ERR_BOVFL; return -1; } if(swap && audio_size==16) swpcpy((void*)shmemptr->audio_data[NBUF(n_audio)],(void*)(buf+nb),audio_buffer_size); else memcpy((void*)shmemptr->audio_data[NBUF(n_audio)],(void*)(buf+nb),audio_buffer_size); shmemptr->used_flag[NBUF(n_audio)] = 1; nb += audio_buffer_size; n_audio++; } /* copy the remainder into audio_left_buf */ if(nberror_string, "Error %s - %s",str,strerror(errno)); else sprintf((char*)shmemptr->error_string, "Error %s",str); shmemptr->audio_status = -1; if( fd >= 0 ) close(fd); #ifdef FORK_NOT_THREAD exit(1); #else pthread_exit(NULL); #endif } #endif /* HAVE_SYS_SOUNDCARD_H */ #ifdef HAVE_SYS_SOUNDCARD_H void do_audio(void) { int fd = -1; int tmp, ret, caps, afmt, frag; int nbdone, nbque, ndiff, nbpend, nbset, maxdiff; uint8_t *buf = NULL; fd_set selectset; struct count_info count; struct audio_buf_info info; struct timeval tv; const char *audio_dev_name; #ifndef FORK_NOT_THREAD struct sched_param schedparam; sigset_t blocked_signals; /* Set the capture thread in a reasonable state - cancellation enabled and asynchronous, SIGINT's ignored... */ /* PTHREAD_CANCEL_ASYNCHRONOUS is evil. */ /* if( pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL) ) { system_error( "Bad pthread_setcancelstate", fd, 0 ); } if( pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL) ) { system_error( "Bad pthread_setcanceltype", fd, 0 ); }*/ sigaddset( &blocked_signals, SIGINT ); if( pthread_sigmask( SIG_BLOCK, &blocked_signals, NULL )) { system_error( "Bad pthread_sigmask", fd, 0 ); } #endif /* * Fragment size and max possible number of frags */ switch (audio_buffer_size) { case 8192: frag = 0x7fff000d; break; case 4096: frag = 0x7fff000c; break; case 2048: frag = 0x7fff000b; break; case 1024: frag = 0x7fff000a; break; default: system_error("Audio internal error - audio_buffer_size",fd,0); } /* if somebody plays with BUFFSIZE without knowing what he does ... */ if (audio_buffer_size>BUFFSIZE) system_error("Audio internal error audio_buffer_size > BUFFSIZE",fd,0); /* * Open Audio device, set number of frags wanted */ audio_dev_name = getenv("LAV_AUDIO_DEV"); if(!audio_dev_name) audio_dev_name = "/dev/dsp"; if(audio_capt) fd=open(audio_dev_name, O_RDONLY, 0); else fd=open(audio_dev_name, O_RDWR, 0); if (fd<0) system_error(audio_dev_name,fd,1); ret = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag); if(ret<0) system_error("in ioctl SNDCTL_DSP_SETFRAGMENT", fd, 1); /* * Setup sampling parameters. */ afmt = (audio_size==16) ? AFMT_S16_LE : AFMT_U8; tmp = afmt; ret = ioctl(fd, SNDCTL_DSP_SETFMT, &tmp); if(ret<0 || tmp!=afmt) system_error("setting sound format",fd,0); tmp = stereo; /* 0=mono, 1=stereo */ ret = ioctl(fd, SNDCTL_DSP_STEREO, &tmp); if(ret<0 || tmp!=stereo) system_error("setting mono/stereo",fd,0); tmp = audio_rate; ret = ioctl(fd, SNDCTL_DSP_SPEED, &tmp); if(ret<0) { system_error("setting sound rate",fd,0); } else if(tmp != audio_rate) { mjpeg_warn("Sound card told us it's using rate %dHz instead of %dHz", tmp, audio_rate); } /* Calculate number of bytes corresponding to TIME_STAMP_TOL */ maxdiff = audio_byte_rate / (1000000/TIME_STAMP_TOL); /* * Check that the device has capability to do mmap and trigger */ if(mmap_io) { ret = ioctl(fd, SNDCTL_DSP_GETCAPS, &caps); if(ret<0) system_error("getting audio device capabilities",fd,1); if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP)) system_error("Soundcard cant do mmap or trigger",fd,0); } /* * Get the size of the input/output buffer and do the mmap */ if (audio_capt) ret = ioctl(fd, SNDCTL_DSP_GETISPACE, &info); else ret = ioctl(fd, SNDCTL_DSP_GETOSPACE, &info); if(ret<0) system_error("in ioctl SNDCTL_DSP_GET[IO]SPACE",fd,1); if (info.fragsize != audio_buffer_size) system_error("Soundcard fragment size unexpected",fd,0); /* * Original comment: * Normally we should get at least 8 fragments (if we use 8KB buffers) * or even more if we use 4KB od 2 KB buffers * We consider 4 fragments as the absolut minimum here! * * A.Stevens Jul 2000: I'm a bit puzzled by the above. A 4096 byte * buffer takes 1/20th second to fill at 44100 stereo. So provide we * empty one frag in less than this we should be o.k. hardly onerous. * Presumably the problem was that this code wasn't running real-time * and so could get starved on a load system. * Anyway, insisting on 8 frags of 8192 bytes puts us sure out of luck * drivers for quite a few modern PCI soundcards ... so lets try for 2 * and see what real-time scheduling can do! */ if (info.fragstotal < 2) { system_error("Could not get enough audio buffer fragments",fd,0); } tmp = info.fragstotal*info.fragsize; if( mmap_io ) { if (audio_capt) buf=mmap(NULL, tmp, PROT_READ , MAP_SHARED, fd, 0); else buf=mmap(NULL, tmp, PROT_WRITE, MAP_SHARED, fd, 0); if (buf==MAP_FAILED) system_error("mapping audio buffer " "(consider using read/write instead of mmap)",fd, 1); /* * Put device into hold */ tmp = 0; ret = ioctl(fd, SNDCTL_DSP_SETTRIGGER, &tmp); if(ret<0) system_error("in ioctl SNDCTL_DSP_SETTRIGGER",fd,1); } /* * Signal the parent that initialization is done */ shmemptr->audio_status = 1; /* * nbdone is the number of buffers processed by the audio driver * so far (ie. the number of buffers read or written) * nbque is the number of buffers which have been queued so far * for playing (not used in audio capture) * nbset Number of buffers set (with real data or 0s) * * If we do playback: Wait until the first buffer arrives */ nbdone = 0; nbque = 0; nbset = 0; if(!audio_capt) { while(!shmemptr->audio_start) { usleep(10000); if(shmemptr->exit_flag) { #ifndef FORK_NOT_THREAD exit(0); #else pthread_exit(NULL); #endif } } /* Copy as many buffers as are allready here */ for(nbque=0;nbqueused_flag[NBUF(nbque)]) break; if (mmap_io) { memcpy(buf+nbque*info.fragsize, (void*) shmemptr->audio_data[NBUF(nbque)], info.fragsize); } else { write(fd,(void *)shmemptr->audio_data[NBUF(nbque)], info.fragsize); } /* Mark the buffer as free */ shmemptr->used_flag[NBUF(nbque)] = 0; } for(nbset=nbque;nbsetaudio_data[NBUF(nbdone)], info.fragsize ) != info.fragsize ) { system_error( "Sound driver returned partial fragment!\n", fd,1 ); } } } /* Get time - this time is after at least one buffer has been recorded/played (because select did return), and before the the audio status obtained by the following ioctl */ gettimeofday(&tv,NULL); /* Get the status of the sound buffer */ usleep(1000); if(audio_capt) ret = ioctl(fd, SNDCTL_DSP_GETIPTR, &count); else ret = ioctl(fd, SNDCTL_DSP_GETOPTR, &count); if (ret<0) system_error("in ioctl SNDCTL_DSP_GET[IO]PTR",fd,1); /* Get the difference of minimum number of bytes after the select call and bytes actually present - this gives us a measure of accuracy of the time in tv. TODO Note: count.bytes can overflow in extreme situations (more than 3 hrs recording with 44.1 KHz, 16bit stereo), ndiff should be calculated correctly. */ ndiff = count.bytes - audio_buffer_size*(nbdone+1); /* Uncomment this and run testrec if you're getting audio capture problems... */ /* mjpeg_info( "CB=%08d ND=%06d BL=%03d NB=%d", count.bytes, ndiff, count.blocks, NBUF(nbdone) ); */ if(ndiff>maxdiff) { tv.tv_sec = tv.tv_usec = 0; } else { /* Adjust timestamp to take into account delay between sync and now indicated by ndiff */ tv.tv_usec -= ndiff * 1000000 / audio_byte_rate; if( tv.tv_usec < 0 ) { tv.tv_usec += 1000000; tv.tv_sec -= 1; } } if(audio_capt) { /* if exit_flag is set, exit immediatly */ if(shmemptr->exit_flag) { shmemptr->audio_status = -1; close(fd); #ifdef FORK_NOT_THREAD exit(0); #else pthread_exit( NULL ); #endif } /* copy the ready buffers to our audio ring buffer */ if( mmap_io ) nbpend = count.blocks; else nbpend = 1; while(nbpend) { /* Check if buffer nbdone in the ring buffer is free */ if(shmemptr->used_flag[NBUF(nbdone)]) system_error("Audio ring buffer overflow",fd,0); if( mmap_io ) memcpy((void*) shmemptr->audio_data[NBUF(nbdone)], buf+(nbdone%info.fragstotal)*info.fragsize, info.fragsize); /* Get the status of the sound buffer after copy, this permits us to see if an overrun occured */ ret = ioctl(fd, SNDCTL_DSP_GETIPTR, &count); if(ret<0) system_error("in ioctl SNDCTL_DSP_GETIPTR",fd,1); if( mmap_io ) nbpend += count.blocks; /* if nbpend >= total frags, a overrun most probably occured */ shmemptr->status[NBUF(nbdone)] = (nbpend >= info.fragstotal) ? -1 : 1; shmemptr->tmstmp[NBUF(nbdone)] = tv; shmemptr->used_flag[NBUF(nbdone)] = 1; nbdone++; nbpend--; /* timestamps of all following buffers are unreliable */ tv.tv_sec = tv.tv_usec = 0; } } else { /* Update the number and status of frags(=buffers) already output */ nbpend = count.blocks; while(nbpend) { /* check for overflow of the status flags in the ringbuffer */ if(shmemptr->status[NBUF(nbdone)]) system_error("Audio ring buffer overflow",fd,0); /* We have a buffer underrun during write if nbdone>=nbque */ shmemptr->tmstmp[NBUF(nbdone)] = tv; shmemptr->status[NBUF(nbdone)] = (nbdoneexit_flag && nbdone >= nbque) { shmemptr->audio_status = -1; close(fd); #ifdef FORK_NOT_THREAD exit(0); #else pthread_exit( NULL ); #endif } /* Fill into the soundcard memory as many buffers as fit and are available */ while(nbque-nbdone < info.fragstotal) { if(!shmemptr->used_flag[NBUF(nbque)]) break; if(nbque>nbdone) if (mmap_io) { memcpy(buf+(nbque%info.fragstotal)*info.fragsize, (void*) shmemptr->audio_data[NBUF(nbque)], info.fragsize); } else { write(fd,(void *)shmemptr->audio_data[NBUF(nbque)], info.fragsize); } /* Mark the buffer as free */ shmemptr->used_flag[NBUF(nbque)] = 0; nbque++; } if(nbset * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "yuv4mpeg.h" static void usage (void) { fprintf (stderr, "usage: matteblend.flt\n" "no params at the moment - color saturation falloff or such has to be implemented\n"); } static void blend (unsigned char *src0[3], unsigned char *src1[3], unsigned char *matte[3], unsigned int width, unsigned int height, unsigned char *dst[3]) { register unsigned int i,j; register unsigned int len = width * height; for (i=0; i>=2; /* len = len / 4 */ /* do we really have to "downscale" matte here? */ for (i=0,j=0; i> 2; if ((j % width) == (width - 2)) j += width; dst[1][i] = ((235-m) * src0[1][i] + (m-16) * src1[1][i]) / 219; dst[2][i] = ((235-m) * src0[2][i] + (m-16) * src1[2][i]) / 219; } } int main (int argc, char *argv[]) { int in_fd = 0; /* stdin */ int out_fd = 1; /* stdout */ unsigned char *yuv0[3]; /* input 0 */ unsigned char *yuv1[3]; /* input 1 */ unsigned char *yuv2[3]; /* input 2 */ unsigned char *yuv[3]; /* output */ y4m_stream_info_t streaminfo; y4m_frame_info_t frameinfo; int i; int w, h; if (argc > 1) { usage (); exit (1); } y4m_init_stream_info (&streaminfo); y4m_init_frame_info (&frameinfo); i = y4m_read_stream_header (in_fd, &streaminfo); if (i != Y4M_OK) { fprintf (stderr, "%s: input stream error - %s\n", argv[0], y4m_strerr(i)); exit (1); } w = y4m_si_get_width(&streaminfo); h = y4m_si_get_height(&streaminfo); yuv[0] = malloc (w * h); yuv0[0] = malloc (w * h); yuv1[0] = malloc (w * h); yuv2[0] = malloc (w * h); yuv[1] = malloc (w * h / 4); yuv0[1] = malloc (w * h / 4); yuv1[1] = malloc (w * h / 4); yuv2[1] = malloc (w * h / 4); yuv[2] = malloc (w * h / 4); yuv0[2] = malloc (w * h / 4); yuv1[2] = malloc (w * h / 4); yuv2[2] = malloc (w * h / 4); y4m_write_stream_header (out_fd, &streaminfo); while (1) { i = y4m_read_frame(in_fd, &streaminfo, &frameinfo, yuv0); if (i == Y4M_ERR_EOF) exit (0); else if (i != Y4M_OK) exit (1); i = y4m_read_frame(in_fd, &streaminfo, &frameinfo, yuv1); if (i != Y4M_OK) exit (1); i = y4m_read_frame(in_fd, &streaminfo, &frameinfo, yuv2); if (i != Y4M_OK) exit (1); /* constrain matte luma */ for (i = 0; i < w*h; i++) { if (yuv2[0][i] < 16) yuv2[0][i] = 16; else if (yuv2[0][i] > 235) yuv2[0][i] = 235; } blend (yuv0, yuv1, yuv2, w, h, yuv); y4m_write_frame (out_fd, &streaminfo, &frameinfo, yuv); } } mjpegtools-2.1.0/lavtools/y4mtoppm.c0000644000175000017500000002046110603772216020020 0ustar glowwormglowworm/* * y4mtoppm.c: Generate one or more PPM images from a YUV4MPEG2 stream * * Performs 4:2:0->4:4:4 chroma supersampling and then * converts ITU-Rec.601 Y'CbCr to R'G'B' colorspace. * * * Copyright (C) 2004 Matthew J. Marjanovic * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include "subsample.h" #include "colorspace.h" /* command-line parameters */ typedef struct _cl_info { int interleave; int verbosity; FILE *outfp; } cl_info_t; static void usage(const char *progname) { fprintf(stderr, "\n"); fprintf(stderr, "usage: %s [options]\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "Reads YUV4MPEG2 stream from stdin and produces RAW PPM image(s) on stdout.\n"); fprintf(stderr, "Converts digital video Y'CbCr colorspace to computer graphics R'G'B',\n"); fprintf(stderr, " and performs chroma supersampling.\n"); fprintf(stderr, "\n"); fprintf(stderr, " options: (defaults specified in [])\n"); fprintf(stderr, "\n"); fprintf(stderr, " -L interleave fields into single PPM image\n"); fprintf(stderr, " -v n verbosity (0,1,2) [1]\n"); } static void parse_args(cl_info_t *cl, int argc, char **argv) { int c; cl->interleave = 0; cl->verbosity = 1; cl->outfp = stdout; /* default to stdout */ while ((c = getopt(argc, argv, "Lv:h")) != -1) { switch (c) { case 'L': cl->interleave = 1; break; case 'v': cl->verbosity = atoi(optarg); if ((cl->verbosity < 0) || (cl->verbosity > 2)) mjpeg_error("Verbosity must be 0, 1, or 2: '%s'", optarg); break; case 'h': usage(argv[0]); exit(0); break; case '?': default: goto ERROR_EXIT; break; } } if (optind != argc) goto ERROR_EXIT; mjpeg_default_handler_verbosity(cl->verbosity); /* DONE! */ return; ERROR_EXIT: mjpeg_error("For usage hints, use option '-h'. Please take a hint."); exit(1); } static void write_ppm_from_two_buffers(FILE *fp, uint8_t *buffers[], uint8_t *buffers2[], uint8_t *rowbuffer, int width, int height) { int x, y; uint8_t *pixels; uint8_t *R = buffers[0]; uint8_t *G = buffers[1]; uint8_t *B = buffers[2]; uint8_t *R2 = buffers2[0]; uint8_t *G2 = buffers2[1]; uint8_t *B2 = buffers2[2]; mjpeg_debug("write PPM image from two buffers, %dx%d", width, height); fprintf(fp, "P6\n%d %d 255\n", width, height); for (y = 0; y < height; y += 2) { pixels = rowbuffer; for (x = 0; x < width; x++) { *(pixels++) = *(R++); *(pixels++) = *(G++); *(pixels++) = *(B++); } fwrite(rowbuffer, sizeof(rowbuffer[0]), width * 3, fp); pixels = rowbuffer; for (x = 0; x < width; x++) { *(pixels++) = *(R2++); *(pixels++) = *(G2++); *(pixels++) = *(B2++); } fwrite(rowbuffer, sizeof(rowbuffer[0]), width * 3, fp); } } static void write_ppm_from_one_buffer(FILE *fp, uint8_t *buffers[], uint8_t *rowbuffer, int width, int height) { int x, y; uint8_t *pixels; uint8_t *R = buffers[0]; uint8_t *G = buffers[1]; uint8_t *B = buffers[2]; mjpeg_debug("write PPM image from one buffer, %dx%d", width, height); fprintf(fp, "P6\n%d %d 255\n", width, height); for (y = 0; y < height; y++) { pixels = rowbuffer; for (x = 0; x < width; x++) { *(pixels++) = *(R++); *(pixels++) = *(G++); *(pixels++) = *(B++); } fwrite(rowbuffer, sizeof(rowbuffer[0]), width * 3, fp); } } int main(int argc, char **argv) { int in_fd = 0; cl_info_t cl; y4m_stream_info_t streaminfo; y4m_frame_info_t frameinfo; uint8_t *buffers[Y4M_MAX_NUM_PLANES]; /* R'G'B' or Y'CbCr */ uint8_t *buffers2[Y4M_MAX_NUM_PLANES]; /* R'G'B' or Y'CbCr */ int err, i; int width, height; int interlace, chroma, planes; uint8_t *rowbuffer; y4m_accept_extensions(1); /* allow non-4:2:0 chroma */ y4m_init_stream_info(&streaminfo); y4m_init_frame_info(&frameinfo); parse_args(&cl, argc, argv); if ((err = y4m_read_stream_header(in_fd, &streaminfo)) != Y4M_OK) { mjpeg_error("Couldn't read YUV4MPEG2 header: %s!", y4m_strerr(err)); exit(1); } mjpeg_info("input stream parameters:"); y4m_log_stream_info(mjpeg_loglev_t("info"), "<<<", &streaminfo); width = y4m_si_get_width(&streaminfo); height = y4m_si_get_height(&streaminfo); interlace = y4m_si_get_interlace(&streaminfo); chroma = y4m_si_get_chroma(&streaminfo); planes = y4m_si_get_plane_count(&streaminfo); if (interlace == Y4M_ILACE_MIXED) { mjpeg_error("Cannot (yet) handle 'mixed' interlacing mode!"); exit(1); } if (!chroma_super_implemented(chroma)) mjpeg_error_exit1("Cannot handle stream's chroma mode!"); /*** Allocate buffers ***/ mjpeg_debug("allocating buffers..."); rowbuffer = malloc(width * planes * sizeof(rowbuffer[0])); mjpeg_debug(" rowbuffer %p", rowbuffer); /* allocate buffers big enough for 4:4:4 supersampled components */ for (i = 0; i < planes; i++) { if (interlace == Y4M_ILACE_NONE) { buffers[i] = malloc(width * height * sizeof(buffers[i][0])); buffers2[i] = NULL; } else { buffers[i] = malloc(width * height / 2 * sizeof(buffers[i][0])); buffers2[i] = malloc(width * height / 2 * sizeof(buffers[i][0])); } mjpeg_debug(" buffers[%d] %p buffers2[%d] %p", i, buffers[i], i, buffers2[i]); } /*** Process frames ***/ while (1) { if (interlace == Y4M_ILACE_NONE) { mjpeg_debug("reading noninterlaced frame..."); err = y4m_read_frame(in_fd, &streaminfo, &frameinfo, buffers); if (err != Y4M_OK) break; if (chroma != Y4M_CHROMA_444) { mjpeg_debug("supersampling noninterlaced frame..."); chroma_supersample(chroma, buffers, width, height); } mjpeg_debug("color converting noninterlaced frame..."); convert_YCbCr_to_RGB(buffers, width * height); write_ppm_from_one_buffer(cl.outfp, buffers, rowbuffer, width, height); } else { err = y4m_read_fields(in_fd, &streaminfo, &frameinfo, buffers, buffers2); if (err != Y4M_OK) break; if (chroma != Y4M_CHROMA_444) { mjpeg_debug("supersampling top field..."); chroma_supersample(chroma, buffers, width, height / 2); mjpeg_debug("supersampling bottom field..."); chroma_supersample(chroma, buffers2, width, height / 2); } mjpeg_debug("color converting top field..."); convert_YCbCr_to_RGB(buffers, width * height / 2); mjpeg_debug("color converting bottom field..."); convert_YCbCr_to_RGB(buffers2, width * height / 2); if (cl.interleave) { write_ppm_from_two_buffers(cl.outfp, buffers, buffers2, rowbuffer, width, height); } else if (interlace == Y4M_ILACE_TOP_FIRST) { write_ppm_from_one_buffer(cl.outfp, buffers, rowbuffer, width, height / 2); write_ppm_from_one_buffer(cl.outfp, buffers2, rowbuffer, width, height / 2); } else { /* ilace == Y4M_ILACE_BOTTOM_FIRST */ write_ppm_from_one_buffer(cl.outfp, buffers2, rowbuffer, width, height / 2); write_ppm_from_one_buffer(cl.outfp, buffers, rowbuffer, width, height / 2); } } } if ((err != Y4M_OK) && (err != Y4M_ERR_EOF)) mjpeg_error("Couldn't read frame: %s", y4m_strerr(err)); /*** Clean-up after ourselves ***/ mjpeg_debug("freeing buffers; cleaning up"); free(rowbuffer); for (i = 0; i < 3; i++) { free(buffers[i]); free(buffers2[i]); } y4m_fini_stream_info(&streaminfo); y4m_fini_frame_info(&frameinfo); mjpeg_debug("Done."); return 0; } mjpegtools-2.1.0/lavtools/ypipe.c0000644000175000017500000001153010603772216017352 0ustar glowwormglowworm/* * ypipe - simple test program that interlaces the output of two * YUV4MPEG-emitting programs together into one output stream * frame-wise - better description urgently needed :) * * Copyright (C) 2001, pHilipp Zabel * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include "mjpeg_logging.h" #include "yuv4mpeg.h" static void usage( char *name ) { fprintf( stderr, "Usage: %s [-v num] \n", name); fprintf( stderr, "-v - verbosity num in [0..2]\n"); fprintf( stderr, "example: ypipe \"lav2yuv test1.el\" \"lav2yuv -n1 test2.avi\"\n"); exit (1); } int main (int argc, char *argv[]) { FILE *sfp0, *sfp1; int stream0; /* read from input 1 */ int stream1; /* read from input 2 */ int outstream = 1; /* output to stdout */ int fstarg; unsigned char *yuv0[3]; unsigned char *yuv1[3]; y4m_stream_info_t sinfo0; y4m_stream_info_t sinfo1; y4m_stream_info_t osinfo; y4m_frame_info_t finfo0; y4m_frame_info_t finfo1; int err; char *command0, *command1; y4m_init_stream_info(&sinfo0); y4m_init_stream_info(&sinfo1); y4m_init_stream_info(&osinfo); y4m_init_frame_info(&finfo0); y4m_init_frame_info(&finfo1); y4m_accept_extensions(1); if ((argc != 3) && (argc != 5)) usage(argv[0]); if (argc == 5) { int verbose; if (strcmp(argv[1],"-v") != 0) usage(argv[0]); verbose = atoi(argv[2]); if (verbose < 0 || verbose > 2) usage(argv[0]); (void)mjpeg_default_handler_verbosity(verbose); fstarg = 3; } else fstarg = 1; command0 = strdup(argv[fstarg]); command1 = strdup(argv[fstarg + 1]); sfp0 = popen(command0, "r"); if (!sfp0) mjpeg_error_exit1("popen(%s) failed", command0); sfp1 = popen(command1, "r"); if (!sfp1) mjpeg_error_exit1("popen(%s) failed", command1); stream0 = fileno(sfp0); stream1 = fileno(sfp1); if ((err = y4m_read_stream_header(stream0, &sinfo0)) != Y4M_OK) mjpeg_error_exit1("Failed to read first stream header: %s errno=%d", y4m_strerr(err), errno); if ((err = y4m_read_stream_header(stream1, &sinfo1)) != Y4M_OK) mjpeg_error_exit1("Failed to read second stream header: %s", y4m_strerr(err)); mjpeg_info("First stream parameters:"); y4m_log_stream_info(mjpeg_loglev_t("info"), "1> ", &sinfo0); mjpeg_info("Second stream parameters:"); y4m_log_stream_info(mjpeg_loglev_t("info"), "2> ", &sinfo1); if (y4m_si_get_width(&sinfo0) != y4m_si_get_width(&sinfo1)) mjpeg_error_exit1("Width mismatch"); if (y4m_si_get_height(&sinfo0) != y4m_si_get_height(&sinfo1)) mjpeg_error_exit1("Height mismatch"); if (!(Y4M_RATIO_EQL(y4m_si_get_framerate(&sinfo0), y4m_si_get_framerate(&sinfo1)))) mjpeg_error_exit1("Framerate mismatch"); if (y4m_si_get_interlace(&sinfo0) != y4m_si_get_interlace(&sinfo1)) mjpeg_error_exit1("Interlace mismatch"); y4m_copy_stream_info(&osinfo, &sinfo0); yuv0[0] = malloc(y4m_si_get_plane_length(&sinfo0, 0)); yuv1[0] = malloc(y4m_si_get_plane_length(&sinfo0, 0)); yuv0[1] = malloc(y4m_si_get_plane_length(&sinfo0, 1)); yuv1[1] = malloc(y4m_si_get_plane_length(&sinfo0, 1)); yuv0[2] = malloc(y4m_si_get_plane_length(&sinfo0, 2)); yuv1[2] = malloc(y4m_si_get_plane_length(&sinfo0, 2)); if ((err = y4m_write_stream_header(outstream, &sinfo0)) != Y4M_OK) mjpeg_error_exit1("Failed to write output header: %s", y4m_strerr(err)); while ( ((err = y4m_read_frame(stream0, &sinfo0, &finfo0, yuv0)) == Y4M_OK) && ((err = y4m_write_frame(outstream, &osinfo, &finfo0, yuv0)) == Y4M_OK) && ((err = y4m_read_frame(stream1, &sinfo1, &finfo1, yuv1)) == Y4M_OK) && ((err = y4m_write_frame(outstream, &osinfo, &finfo1, yuv1)) == Y4M_OK) ) {} if (err != Y4M_ERR_EOF) mjpeg_error_exit1("Some error somewhere: %s", y4m_strerr(err)); y4m_fini_stream_info(&sinfo0); y4m_fini_stream_info(&sinfo1); y4m_fini_stream_info(&osinfo); y4m_fini_frame_info(&finfo0); y4m_fini_frame_info(&finfo1); return 0; } mjpegtools-2.1.0/lavtools/glav_main.c0000644000175000017500000005117410330577101020162 0ustar glowwormglowworm/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include "glav.h" #include #include #include #include #include #define PLAY_PROG "lavplay" #define LAVPLAY_VSTR "lavplay" VERSION /* Expected version info */ static struct timeval time_when_pressed; static int number_of_skipped_frames; int verbose = 1; static GTK_xlav *gtk_xlav; static int inp_pipe; static int out_pipe; static int pid; static double fps; static int cur_pos, total_frames, cur_speed=1, old_speed=999999; static int slider_pause; static int slider_pos; static int ff_stat=0, fr_stat=0; static int ff_speed[4] = { 1, 3, 10, 30 }; static int selection_start = -1; static int selection_end = -1; #define MAXINP 4096 #define SAVE_ALL 1 #define SAVE_SEL 2 static int savetype = 0; static char inpbuff[MAXINP]; static int inplen = 0; static int frame_skip_button_up = 1; static char frame_skip_char; static char timecode[64]; char *selected_filename; GtkWidget *file_selector; static void skip_num_frames(int num) { char out[32]; sprintf(out,"s%d\n",cur_pos + num); write(out_pipe,out,strlen(out)); } static void calc_timecode(int pos, int do_frames) { MPEG_timecode_t tc; mpeg_timecode(&tc, pos, mpeg_framerate_code(mpeg_conform_framerate(fps)), fps); if (!do_frames) tc.f=0; sprintf(timecode,"%2d:%2.2d:%2.2d:%2.2d",tc.h,tc.m,tc.s,tc.f); } static void store_filename(GtkFileSelection *selector, gpointer user_data) { char str[256]; const char *name; /* First easy fix, Bernhard */ selected_filename = (char*)gtk_file_selection_get_filename (GTK_FILE_SELECTION(file_selector)); name = selected_filename; if(name==0) return; switch(savetype) { case SAVE_ALL: sprintf(str,"wa %s\n",name); break; case SAVE_SEL: sprintf(str,"ws %d %d %s\n",selection_start,selection_end,name); break; } write(out_pipe,str,strlen(str)); printf("Wrote to %s\n",name); } static void create_file_selection(void) { /* Create the selector */ char label[32]; switch (savetype) { case SAVE_ALL: sprintf(label,"save all to file..."); break; case SAVE_SEL: sprintf(label,"save selected to file..."); break; default: printf("Error in create_file_selection\n"); return; break; } file_selector = gtk_file_selection_new(label); /* Next problem, Bernhard */ g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION (file_selector)->ok_button), "clicked", (GtkSignalFunc)store_filename, NULL); /* Ensure that the dialog box is destroyed when the user clicks a button. */ g_signal_connect_swapped(G_OBJECT (GTK_FILE_SELECTION(file_selector)->ok_button), "clicked", G_CALLBACK (gtk_widget_destroy), (gpointer) file_selector); g_signal_connect_swapped(G_OBJECT (GTK_FILE_SELECTION(file_selector)->cancel_button), "clicked", G_CALLBACK (gtk_widget_destroy), (gpointer) file_selector); /* Display that dialog */ gtk_widget_show (file_selector); } gint key_press_cb(GtkWidget * widget, GdkEventKey* event, gpointer data ) { int need_pause=FALSE; int n=1; switch (event->keyval) { case GDK_0:/* go to beginning of file */ write(out_pipe,"s0\n",3); /* go to beginning */ break; case GDK_9: /* go to end of file */ need_pause=TRUE; write(out_pipe,"s10000000\n",10); /* go to end */ break; case GDK_parenleft: /* mark start of selection */ case GDK_Home: g_signal_emit_by_name(G_OBJECT(gtk_xlav->BSSelStart),"clicked",(gpointer)1); break; case GDK_parenright: /* mark end of selection */ case GDK_End: g_signal_emit_by_name(G_OBJECT(gtk_xlav->BSSelEnd),"clicked",(gpointer)1); break; case GDK_bracketleft: /* skip to selected start */ g_signal_emit_by_name(G_OBJECT(gtk_xlav->BGotoSelStart),"clicked",(gpointer)1); break; case GDK_bracketright: /* skip to selected end */ g_signal_emit_by_name(G_OBJECT(gtk_xlav->BGotoSelEnd),"clicked",(gpointer)1); break; case GDK_a: /* Save all */ g_signal_emit_by_name(G_OBJECT(gtk_xlav->BSaveAll),"clicked",(gpointer)1); break; case GDK_v: /* Save */ g_signal_emit_by_name(G_OBJECT(gtk_xlav->BSaveSel),"clicked",(gpointer)1); break; case GDK_q: /* Exit */ g_signal_emit_by_name(G_OBJECT(gtk_xlav->Exit),"clicked",(gpointer)1); break; case GDK_l: /* some number of frames right */ case GDK_L: case GDK_Right: need_pause=TRUE; g_signal_stop_emission_by_name(G_OBJECT(gtk_xlav->xlav), "key_press_event"); n=1; if(event->state & GDK_CONTROL_MASK) { write(out_pipe,"s10000000\n",10); /* go to end */ break; } else if(event->state & GDK_MOD1_MASK) { n=50; } else if (event->state & GDK_SHIFT_MASK) { n=10; } skip_num_frames(n); break; case GDK_h: /* some number of frames left */ case GDK_H: case GDK_Left: g_signal_stop_emission_by_name(GTK_OBJECT(gtk_xlav->xlav), "key_press_event"); n=-1; if(event->state & GDK_CONTROL_MASK) { /* go to beginning */ write(out_pipe,"s0\n",3); /* go to beginning */ break; } else if(event->state & GDK_MOD1_MASK) { n=-50; } else if (event->state & GDK_SHIFT_MASK) { n=-10; } need_pause=TRUE; skip_num_frames(n); break; case GDK_w: /* (word) 15 frames right */ need_pause=TRUE; skip_num_frames(15); break; case GDK_b: /* (back) 15 frames left */ need_pause=TRUE; skip_num_frames(-15); break; case GDK_W: /* 30 frames right */ need_pause=TRUE; skip_num_frames(30); break; case GDK_B: /* 30 frames left */ need_pause=TRUE; skip_num_frames(-30); break; case GDK_c: /* clear selection */ g_signal_emit_by_name(G_OBJECT(gtk_xlav->BClearSel),"clicked",(gpointer)1); break; case GDK_x: /* cut selection */ case GDK_Delete: g_signal_emit_by_name(G_OBJECT(gtk_xlav->BECut),"clicked",(gpointer)1); break; case GDK_y: /* copy (yank) selection */ g_signal_emit_by_name(G_OBJECT(gtk_xlav->BECopy),"clicked",(gpointer)1); break; case GDK_p: /* paste selection */ case GDK_Insert: g_signal_emit_by_name(G_OBJECT(gtk_xlav->BEPaste),"clicked",(gpointer)1); break; case GDK_f: /* play (forward) */ g_signal_emit_by_name(G_OBJECT(gtk_xlav->play),"clicked",(gpointer)4); break; case GDK_F: /* fast forward */ g_signal_emit_by_name(G_OBJECT(gtk_xlav->ff),"clicked",(gpointer)5); break; case GDK_r: /* play reverse */ g_signal_emit_by_name(G_OBJECT(gtk_xlav->rew),"clicked",(gpointer)2); break; case GDK_R: /* fast reverse */ g_signal_emit_by_name(G_OBJECT(gtk_xlav->fr),"clicked",(gpointer)1); break; case GDK_s: /* stop */ case GDK_S: g_signal_emit_by_name(G_OBJECT(gtk_xlav->stop),"clicked",(gpointer)3); break; case GDK_1: /* go 5 seconds forward */ skip_num_frames(150); break; case GDK_2: /* go 10 seconds forward */ skip_num_frames(300); break; case GDK_3: /* go 15 seconds forward */ skip_num_frames(450); break; case GDK_4: /* go 20 seconds forward */ skip_num_frames(600); break; case GDK_5: /* go 25 seconds forward */ skip_num_frames(750); break; case GDK_6: /* go 30 seconds forward */ skip_num_frames(900); break; case GDK_exclam: /* go 5 seconds back */ skip_num_frames(-150); break; case GDK_at: /* go 10 seconds back */ skip_num_frames(-300); break; case GDK_numbersign: /* go 15 seconds back */ skip_num_frames(-450); break; case GDK_dollar: /* go 20 seconds back */ skip_num_frames(-600); break; case GDK_percent: /* go 25 seconds back */ skip_num_frames(-750); break; case GDK_asciicircum: /* a.k.a "carat" (shift-6 on us keyboards) */ skip_num_frames(-900); break; case GDK_Shift_L: /* just shift keys, eat them */ case GDK_Shift_R: break; default: break; } if (cur_speed!=0) { if (need_pause) { write(out_pipe,"p0\n",3); /* pause on all keys */ } } return 0; } static void quick_message(const char *message) { GtkWidget *dialog, *label, *okay_button; /* Create the widgets */ dialog = gtk_dialog_new(); label = gtk_label_new (message); okay_button = gtk_button_new_with_label("Okay"); /* Ensure that the dialog box is destroyed when the user clicks ok. */ g_signal_connect_swapped(G_OBJECT (okay_button), "clicked", G_CALLBACK (gtk_widget_destroy), G_OBJECT(dialog)); gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area), okay_button); /* Add the label, and show everything we've added to the dialog. */ gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label); gtk_widget_show_all (dialog); } void dispatch_input(void) { char * token ; char * tokens[ 4] ; int i ; /* A line starting with '-' should be ignored */ if(inpbuff[0]=='-') return; /* A line starting with '@' contains psoition information */ if(inpbuff[0]=='@') { int slider_new_pos; // sscanf(inpbuff+1,"%lg/%d/%d/%d",&fps,&cur_pos,&total_frames,&cur_speed); memset( tokens, 0, sizeof( tokens)) ; tokens[ 0] = token = inpbuff + 1 ; for( i = 1 ; (i < 4) && ( token != NULL) ; i++) { token = strchr( token, '/') ; if( token != NULL) { *token = '\0' ; token++ ; tokens[ i] = token ; } } token = tokens[ 0] ; if( token != NULL) { fps = atof( token) ; } token = tokens[ 1] ; if( token != NULL) { cur_pos = atoi( token) ; } token = tokens[ 2] ; if( token != NULL) { total_frames = atoi( token) ; } token = tokens[ 3] ; if( token != NULL) { cur_speed = atoi( token) ; } calc_timecode(cur_pos,cur_speed==0); gtk_label_set_text(GTK_LABEL(gtk_xlav->Timer),timecode); /* fl_set_object_label(gtk_xlav->Timer,timecode); */ if(total_frames<1) total_frames=1; slider_new_pos = 10000 * cur_pos / total_frames; if (slider_pos != slider_new_pos) { slider_pos = slider_new_pos; slider_pause++; gtk_adjustment_set_value(GTK_ADJUSTMENT(gtk_xlav->timeslider), (double)slider_new_pos / 100.0); } if(cur_speed != old_speed) { char label[32]; if(cur_speed == 1) { gtk_label_set_text(GTK_LABEL(gtk_xlav->StatDisp),"Play >"); } else if(cur_speed == 0) { gtk_label_set_text(GTK_LABEL(gtk_xlav->StatDisp),"Pause"); } else if(cur_speed == -1) { gtk_label_set_text(GTK_LABEL(gtk_xlav->StatDisp),"Play <"); } else if(cur_speed < -1) { sprintf(label,"<<%2dx",-cur_speed); gtk_label_set_text(GTK_LABEL(gtk_xlav->StatDisp),label); } else if(cur_speed > 1) { sprintf(label,">>%2dx",cur_speed); gtk_label_set_text(GTK_LABEL(gtk_xlav->StatDisp),label); } old_speed = cur_speed; } return; } else { fprintf(stderr, "++: %s\n", inpbuff); } } static void get_input(gpointer data, gint fd, GdkInputCondition condition) { char input[4096]; int i, n; n = read(fd,input,4096); if(n==0) exit(0); for(i=0;itimeslider)->value)); sprintf(out,"s%d\n",(int)((val*total_frames)/100)); write(out_pipe,out,strlen(out)); } } void button_cb(GtkWidget *ob, long data) { switch(data) { case 1: write(out_pipe,"s0\n",3); break; /* go to beginning */ case 2: write(out_pipe,"s10000000\n",10); break; /* go to end */ /* moved this to frame_skip_pressed case 3: write(out_pipe,"-\n",2); break; case 4: write(out_pipe,"+\n",2); break; */ } } static guint skip_frame(char *mychar) { struct timeval current_time; gettimeofday(¤t_time,0); if (frame_skip_button_up == 0 ) { if (((current_time.tv_sec-time_when_pressed.tv_sec)*1000+(current_time.tv_usec-time_when_pressed.tv_usec)/1000)>500) { char out[10]; sprintf(out,"%c\n",frame_skip_char); write(out_pipe,out,2); number_of_skipped_frames++; } } return (! frame_skip_button_up); } void frame_skip_pressed(GtkWidget *ob, long data) { frame_skip_button_up=0; gettimeofday(&time_when_pressed,0); number_of_skipped_frames=0; switch(data) { case 3: frame_skip_char='-'; /* frame reverse */ gtk_timeout_add(10,(GtkFunction)skip_frame,(gpointer)0); break; case 4: frame_skip_char='+'; /* frame advance */ gtk_timeout_add(10,(GtkFunction)skip_frame,(gpointer)0); break; default: break; } } void frame_skip_released(GtkWidget *ob, long data){ frame_skip_button_up=1; if(number_of_skipped_frames==0){ char out[10]; sprintf(out,"%c\n",frame_skip_char); write(out_pipe,out,2); } } void rb_cb(GtkWidget *ob, long data) { char out[32]; if (data!=1) fr_stat = 0; if (data!=5) ff_stat = 0; switch(data) { case 1: fr_stat++; if(fr_stat>3) fr_stat=1; sprintf(out,"p-%d\n",ff_speed[fr_stat]); write(out_pipe,out,strlen(out)); break; case 2: write(out_pipe,"p-1\n",4); break; case 3: write(out_pipe,"p0\n",3); break; case 4: write(out_pipe,"p1\n",3); break; case 5: ff_stat++; if(ff_stat>3) ff_stat=1; sprintf(out,"p%d\n",ff_speed[ff_stat]); write(out_pipe,out,strlen(out)); break; case 0: /* this is here for a callback that does nothing */ break; default: break; } } #if 0 /* No Audio mute at the moment */ void Audio_cb(GtkWidget *ob, long data) { if(fl_get_button(gtk_xlav->Audio)) write(out_pipe,"a1\n",3); else write(out_pipe,"a0\n",3); } #endif void do_real_exit(int ID, void *data) { int status; /* Kill all our children and exit */ printf("real exit here\n"); kill(pid,9); waitpid(pid,&status,0); exit(0); } void Exit_cb(GtkWidget *ob, long data) { /* Try to exit gracefully, wait 1 second, do real exit */ write(out_pipe,"q\n\n\n",4); gtk_timeout_add(1000,(GtkFunction)do_real_exit,0); } void signal_cb(int signum, void *data) { Exit_cb(0,0); } static int check_selection(void) { if(selection_start>=0 && selection_end>=selection_start) return 0; quick_message("Selection invalid!!!"); return -1; } void selection_cb(GtkWidget *ob, long data) { char str[256]; switch(data) { case 1: selection_start = cur_pos; calc_timecode(cur_pos,1); gtk_label_set_text(GTK_LABEL(gtk_xlav->FSelStart),timecode); break; case 2: selection_end = cur_pos; calc_timecode(cur_pos,1); gtk_label_set_text(GTK_LABEL(gtk_xlav->FSelEnd),timecode); break; case 3: /* Clear */ selection_start = -1; selection_end = -1; gtk_label_set_text(GTK_LABEL(gtk_xlav->FSelStart),"-:--:--:--"); gtk_label_set_text(GTK_LABEL(gtk_xlav->FSelEnd),"-:--:--:--"); break; case 4: /* Cut */ case 5: /* Copy */ if(check_selection()) return; sprintf(str,"e%c %d %d\n",(data==4)?'u':'o',selection_start,selection_end); write(out_pipe,str,strlen(str)); if(data==4) { selection_start = -1; selection_end = -1; gtk_label_set_text(GTK_LABEL(gtk_xlav->FSelStart),"-:--:--:--"); gtk_label_set_text(GTK_LABEL(gtk_xlav->FSelEnd),"-:--:--:--"); } break; case 6: /* Paste */ if(check_selection()) return; selection_start = -1; selection_end = -1; gtk_label_set_text(GTK_LABEL(gtk_xlav->FSelStart),"-:--:--:--"); gtk_label_set_text(GTK_LABEL(gtk_xlav->FSelEnd),"-:--:--:--"); write(out_pipe,"ep\n",3); break; case 7: /* Save All */ savetype=SAVE_ALL; create_file_selection(); break; case 8: /* Save */ if(check_selection()) return; savetype=SAVE_SEL; create_file_selection(); break; case 11: if(selection_start >= 0) { sprintf(str,"s%d\n",selection_start); write(out_pipe,str,strlen(str)); } else printf("Selection Start is not set!\n"); break; case 12: if(selection_end >= 0) { sprintf(str,"s%d\n",selection_end); write(out_pipe,str,strlen(str)); } else printf("Selection End is not set!\n"); break; default: printf("selection %ld\n",data); } } static void create_child(const char **args) { int ipipe[2], opipe[2]; int n, vlen; char version[32]; if(pipe(ipipe)!=0 || pipe(opipe)!=0) { perror("Starting "PLAY_PROG); exit(1); } pid = fork(); if(pid<0) { perror("Starting "PLAY_PROG); exit(1); } if (pid) { /* We are the parent */ inp_pipe = ipipe[0]; close(ipipe[1]); out_pipe = opipe[1]; close(opipe[0]); } else { /* We are the child */ close(ipipe[0]); close(opipe[1]); close(0); n = dup(opipe[0]); if(n!=0) exit(1); close(opipe[0]); close(1); n = dup(ipipe[1]); if(n!=1) exit(1); close(ipipe[1]); close(2); n = dup(1); if(n!=2) exit(1); execvp(PLAY_PROG,(char *const*)args); /* if exec returns, an error occured */ exit(1); } /* Check if child sends right version number */ vlen = strlen(LAVPLAY_VSTR); n = read(inp_pipe,version,vlen+1); /* vlen+1: for trailing \n */ version[vlen] = 0; if(n!=vlen+1 || strncmp(version,LAVPLAY_VSTR,vlen)!=0) { fprintf(stderr,"%s did not send correct version info\n",PLAY_PROG); fprintf(stderr,"Got: \"%s\" Expected: \"%s\"\n",version, VERSION); do_real_exit(0,0); } } int main(int argc, char *argv[]) { int i; /* copy our argument list */ const char **argvn = (const char **) malloc(sizeof(char*)*(argc+3)); if(argvn==0) { fprintf(stderr,"malloc failed\n"); exit(1); } argvn[0] = PLAY_PROG; argvn[1] = "-q"; argvn[2] = "-g"; for(i=1;ixlav), "destroy", // old: GTK_SIGNAL_FUNC(gtk_main_quit), NULL); g_signal_connect_swapped(G_OBJECT (gtk_xlav->xlav), "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_widget_show(gtk_xlav->xlav); /* show the main window */ gdk_input_add(inp_pipe,GDK_INPUT_READ,(GdkInputFunction)get_input,(gpointer)0); gtk_main(); return 0; } mjpegtools-2.1.0/lavtools/liblavplay.c0000644000175000017500000024747011344710443020376 0ustar glowwormglowworm/* * liblavplay - a librarified Linux Audio Video PLAYback * * Copyright (C) 2000 Rainer Johanni * Extended by: Gernot Ziegler * Ronald Bultje * & many others * * A library for playing back MJPEG video via software MJPEG * decompression (using SDL) or via hardware MJPEG video * devices such as the Pinnacle/Miro DC10(+), Iomega Buz, * the Linux Media Labs LML33, the Matrox Marvel G200, * Matrox Marvel G400 and the Rainbow Runner G-series. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_V4L #include #endif #ifndef X_DISPLAY_MISSING #include #include #endif #ifdef HAVE_SYS_SOUNDCARD_H #include #endif #ifdef HAVE_V4L /* Because of some really cool feature in video4linux1, also known as * 'not including sys/types.h and sys/time.h', we had to include it * ourselves. In all their intelligence, these people decided to fix * this in the next version (video4linux2) in such a cool way that it * breaks all compilations of old stuff... * The real problem is actually that linux/time.h doesn't use proper * macro checks before defining types like struct timeval. The proper * fix here is to either fuck the kernel header (which is what we do * by defining _LINUX_TIME_H, an innocent little hack) or by fixing it * upstream, which I'll consider doing later on. If you get compiler * errors here, check your linux/time.h && sys/time.h header setup. */ #define _LINUX_TIME_H #include #else #define VIDEO_MODE_PAL 0 #define VIDEO_MODE_NTSC 1 #define VIDEO_MODE_SECAM 2 #define VIDEO_MODE_AUTO 3 #endif #include #include #ifdef HAVE_SDL #include #endif #include "mjpeg_logging.h" #include "liblavplay.h" #include "audiolib.h" #include "jpegutils.h" #ifdef HAVE_LIBDV #include #endif /* Prototypes to avoid compile time warning errors */ void frame_YUV422_to_YUV420P(uint8_t **, uint8_t *, int , int ); #ifdef HAVE_SDL int frame_planar_to_packed(uint8_t *, uint8_t **, int, int, int, int, int); #endif /* * As far as I (maddog) can tell, this is what is going on with libdv-0.9 * and the unpacking routine... * o Ft/Fb refer to top/bottom scanlines (interleaved) --- each sample * is implicitly tagged by 't' or 'b' (samples are not mixed between * fields) * o Indices on Cb and Cr samples indicate the Y sample with which * they are co-sited. * o '^' indicates which samples are preserved by the unpacking * * libdv packs both NTSC 4:1:1 and PAL 4:2:0 into a common frame format of * packed 4:2:2 pixels as follows: * * ***** NTSC 4:1:1 ***** * * libdv's 4:2:2-packed representation (chroma repeated horizontally) * *Ft Y00.Cb00.Y01.Cr00.Y02.Cb00.Y03.Cr00 Y04.Cb04.Y05.Cr04.Y06.Cb04.Y07.Cr04 * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ *Fb Y00.Cb00.Y01.Cr00.Y02.Cb00.Y03.Cr00 Y04.Cb04.Y05.Cr04.Y06.Cb04.Y07.Cr04 * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ *Ft Y10.Cb10.Y11.Cr10.Y12.Cb10.Y13.Cr10 Y14.Cb14.Y15.Cr14.Y16.Cb14.Y17.Cr14 * ^ ^ ^ ^ ^ ^ ^ ^ *Fb Y10.Cb10.Y11.Cr10.Y12.Cb10.Y13.Cr10 Y14.Cb14.Y15.Cr14.Y16.Cb14.Y17.Cr14 * ^ ^ ^ ^ ^ ^ ^ ^ * * lavtools unpacking into 4:2:0-planar (note lossiness) * *Ft Y00.Y01.Y02.Y03.Y04.Y05.Y06.Y07... *Fb Y00.Y01.Y02.Y03.Y04.Y05.Y06.Y07... *Ft Y10.Y11.Y12.Y13.Y14.Y15.Y16.Y17... *Fb Y10.Y11.Y12.Y13.Y14.Y15.Y16.Y17... * *Ft Cb00.Cb00.Cb04.Cb04... Cb00,Cb04... are doubled *Fb Cb00.Cb00.Cb04.Cb04... Cb10,Cb14... are ignored * *Ft Cr00.Cr00.Cr04.Cr04... *Fb Cr00.Cr00.Cr04.Cr04... * * ***** PAL 4:2:0 ***** * * libdv's 4:2:2-packed representation (chroma repeated vertically) * *Ft Y00.Cb00.Y01.Cr10.Y02.Cb02.Y03.Cr12 Y04.Cb04.Y05.Cr14.Y06.Cb06.Y07.Cr16 * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ *Fb Y00.Cb00.Y01.Cr10.Y02.Cb02.Y03.Cr12 Y04.Cb04.Y05.Cr14.Y06.Cb06.Y07.Cr16 * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ *Ft Y10.Cb00.Y11.Cr10.Y12.Cb02.Y13.Cr12 Y14.Cb04.Y15.Cr14.Y16.Cb06.Y17.Cr16 * ^ ^ ^ ^ ^ ^ ^ ^ *Fb Y10.Cb00.Y11.Cr10.Y12.Cb02.Y13.Cr12 Y14.Cb04.Y15.Cr14.Y16.Cb06.Y17.Cr16 * ^ ^ ^ ^ ^ ^ ^ ^ * * lavtools unpacking into 4:2:0-planar * *Ft Y00.Y01.Y02.Y03.Y04.Y05.Y06.Y07... *Fb Y00.Y01.Y02.Y03.Y04.Y05.Y06.Y07... *Ft Y10.Y11.Y12.Y13.Y14.Y15.Y16.Y17... *Fb Y10.Y11.Y12.Y13.Y14.Y15.Y16.Y17... * *Ft Cb00.Cb02.Cb04.Cb06... *Fb Cb00.Cb02.Cb04.Cb06... * *Ft Cr10.Cr12.Cr14.Cr16... *Fb Cr10.Cr12.Cr14.Cr16... * */ /* * Unpack libdv's 4:2:2-packed into our 4:2:0-planar, * treating each interlaced field independently * */ void frame_YUV422_to_YUV420P(uint8_t **output, uint8_t *input, int width, int height) { int i, j, w2; uint8_t *y, *cb, *cr; w2 = width/2; y = output[0]; cb = output[1]; cr = output[2]; for (i=0; imsg_callback) info->msg_callback(type, buf); else if (type == LAVPLAY_MSG_ERROR) mjpeg_error("**ERROR: %s", buf); } /****************************************************** * lavplay_change_state() * change the state ******************************************************/ static void lavplay_change_state(lavplay_t *info, int new_state) { video_playback_setup *settings = (video_playback_setup *)info->settings; /*EditList *editlist = info->editlist; */ settings->state = new_state; if (info->state_changed) info->state_changed(new_state); } /****************************************************** * lavplay_set_speed() * set the playback speed (<0 is play backwards) * * return value: 1 on success, 0 on error ******************************************************/ int lavplay_set_speed(lavplay_t *info, int speed) { video_playback_setup *settings = (video_playback_setup *)info->settings; /*EditList *editlist = info->editlist; */ int changed = 0; if ((settings->current_frame_num == settings->max_frame_num && speed > 0) || (settings->current_frame_num == settings->min_frame_num && speed < 0)) { lavplay_msg(LAVPLAY_MSG_WARNING, info, "We are already at the %s", speed<0?"beginning":"end"); return 0; } if ((speed==0 && settings->current_playback_speed!=0) || (speed!=0 && settings->current_playback_speed==0)) changed = 1; settings->current_playback_speed = speed; if (changed) { if (speed==0) lavplay_change_state(info, LAVPLAY_STATE_PAUSED); else lavplay_change_state(info, LAVPLAY_STATE_PLAYING); } return 1; } /****************************************************** * lavplay_increase_frame() * increase (or decrease) a num of frames * * return value: 1 on succes, 0 if we had to change state ******************************************************/ int lavplay_increase_frame(lavplay_t *info, long num) { video_playback_setup *settings = (video_playback_setup *)info->settings; /*EditList *editlist = info->editlist; */ settings->current_frame_num += num; if (settings->current_frame_num < settings->min_frame_num) { settings->current_frame_num = settings->min_frame_num; if (settings->current_playback_speed < 0) lavplay_set_speed(info, 0); return 0; } if (settings->current_frame_num > settings->max_frame_num) { settings->current_frame_num = settings->max_frame_num; if (settings->current_playback_speed > 0) lavplay_set_speed(info, 0); return 0; } return 1; } /****************************************************** * lavplay_set_frame() * set the current framenum * * return value: 1 on success, 0 if we had to change state ******************************************************/ int lavplay_set_frame(lavplay_t *info, long framenum) { video_playback_setup *settings = (video_playback_setup *)info->settings; /*EditList *editlist = info->editlist; */ return lavplay_increase_frame(info, framenum - settings->current_frame_num); } /****************************************************** * lavplay_get_video() * get video data * * return value: length of frame on success, -1 on error ******************************************************/ static int lavplay_get_video(lavplay_t *info, uint8_t *buff, long frame_num) { if (info->get_video_frame) { int length; info->get_video_frame(buff, &length, frame_num); return length; } else { return el_get_video_frame(buff, frame_num, info->editlist); } } /****************************************************** * lavplay_get_audio() * get audio data * * return value: number of samples on success, -1 on error ******************************************************/ static int lavplay_get_audio(lavplay_t *info, uint8_t *buff, long frame_num, int mute) { int num_samps; if (info->get_audio_sample) info->get_audio_sample(buff, &num_samps, frame_num); else num_samps = el_get_audio_data(buff, frame_num, info->editlist, mute); /* fprintf(stderr, "get_audio_sample %x num_samps %x frame_num %x\n", info->get_audio_sample, num_samps, frame_num); */ return(num_samps); } /****************************************************** * lavplay_queue_next_frame() * queues a frame (video + audio) * * return value: 1 on succes, 0 on error ******************************************************/ static int lavplay_queue_next_frame(lavplay_t *info, uint8_t *vbuff, int data_format, int skip_video, int skip_audio, int skip_incr) { int res, mute, i, jpeg_len1, jpeg_len2, new_buff_no; char hlp[16]; video_playback_setup *settings = (video_playback_setup *)info->settings; EditList *editlist = info->editlist; /* Read next frame */ if (!skip_video) { if (info->flicker_reduction && editlist->video_inter && data_format == DATAFORMAT_MJPG && settings->current_playback_speed <= 0) { if (settings->current_playback_speed == 0) { if ((res = lavplay_get_video(info, vbuff, settings->current_frame_num)) < 0) return 0; jpeg_len1 = lav_get_field_size(vbuff, res); /* Found seperate fields? */ if (jpeg_len1 < res) { memcpy(vbuff+jpeg_len1, vbuff, jpeg_len1); settings->old_field_len = 0; } } else /* play_speed < 0, play old first field + actual second field */ { new_buff_no = 1 - settings->old_buff_no; if ((res = lavplay_get_video(info, settings->tmpbuff[new_buff_no], settings->current_frame_num)) < 0) return 0; jpeg_len1 = lav_get_field_size(settings->tmpbuff[new_buff_no], res); if (jpeg_len1 < res) { jpeg_len2 = res - jpeg_len1; if (settings->old_field_len==0) { /* no old first field, duplicate second field */ memcpy(vbuff,settings->tmpbuff[new_buff_no]+jpeg_len1,jpeg_len2); settings->old_field_len = jpeg_len2; } else { /* copy old first field into vbuff */ memcpy(vbuff,settings->tmpbuff[settings->old_buff_no],settings->old_field_len); } /* copy second field */ memcpy(vbuff+settings->old_field_len,settings->tmpbuff[new_buff_no]+jpeg_len1,jpeg_len2); /* save first field */ settings->old_field_len = jpeg_len1; settings->old_buff_no = new_buff_no; } } } else { if (lavplay_get_video(info, vbuff, settings->current_frame_num) < 0) return 0; settings->old_field_len = 0; } } /* Read audio, if present */ if (editlist->has_audio && !skip_audio && info->audio) { mute = (settings->audio_mute || !((settings->current_playback_speed == 1 && (info->audio & 1)) || (settings->current_playback_speed == -1 && (info->audio & 2)) || (settings->current_playback_speed == 0 && (info->audio & 8)) || (1 < settings->current_playback_speed && (info->audio & (1|4)) == (1|4)) || (settings->current_playback_speed < -1 && (info->audio & (2|4)) == (2|4)))); res = lavplay_get_audio(info, settings->abuff, settings->current_frame_num, mute); if (settings->current_playback_speed < 0) { /* reverse audio */ for(i=0;iaudio_bps) { memcpy(hlp,settings->abuff+i, editlist->audio_bps); memcpy(settings->abuff+i,settings->abuff+res-i-editlist->audio_bps, editlist->audio_bps); memcpy(settings->abuff+res-i-editlist->audio_bps,hlp, editlist->audio_bps); } } res = audio_write(settings->abuff,res,0); if (res < 0) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Error playing audio: %s",audio_strerror()); return 0; } } /* Increment frames */ if(!skip_incr) { res = lavplay_increase_frame(info, settings->current_playback_speed); if (!info->continuous) return res; } return 1; } /****************************************************** * lavplay_SDL_lock() * when using software playback - lock the SDL screen * * return value: 1 on success, 0 on error ******************************************************/ #ifdef HAVE_SDL static int lavplay_SDL_lock(lavplay_t *info) { video_playback_setup *settings = (video_playback_setup *)info->settings; /* lock the screen for current decompression */ if (SDL_MUSTLOCK(settings->screen)) { if (SDL_LockSurface(settings->screen) < 0) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Error locking output screen: %s", SDL_GetError()); return 0; } } if (SDL_LockYUVOverlay(settings->yuv_overlay) < 0) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Error locking yuv overlay: %s", SDL_GetError()); return 0; } return 1; } #endif /****************************************************** * lavplay_SDL_unlock() * when using software playback - unlock the SDL screen * * return value: 1 on success, 0 on error ******************************************************/ #ifdef HAVE_SDL static int lavplay_SDL_unlock(lavplay_t *info) { video_playback_setup *settings = (video_playback_setup *)info->settings; if (SDL_MUSTLOCK(settings->screen)) { SDL_UnlockSurface(settings->screen); } SDL_UnlockYUVOverlay(settings->yuv_overlay); return 1; } #endif /****************************************************** * lavplay_SDL_update() * when using software playback - there's a new frame * * return value: 1 on success, 0 on error ******************************************************/ #ifdef HAVE_SDL static int lavplay_SDL_update(lavplay_t *info, uint8_t *jpeg_buffer, int data_format, int buf_len) { video_playback_setup *settings = (video_playback_setup *)info->settings; uint8_t *output[3]; uint8_t *frame_tmp; EditList *editlist = info->editlist; if (!lavplay_SDL_lock(info)) return 0; /* decode frame to yuv */ switch (data_format) { case DATAFORMAT_MJPG: decode_jpeg_raw(jpeg_buffer, buf_len, editlist->video_inter>0&&info->exchange_fields?(editlist->video_inter+1)%2+1:editlist->video_inter, Y4M_CHROMA_422, editlist->video_width, editlist->video_height, settings->yuvbuff[0], settings->yuvbuff[1], settings->yuvbuff[2]); frame_planar_to_packed(settings->yuv_overlay->pixels[0], settings->yuvbuff, editlist->video_width, editlist->video_height, settings->yuvformat, FOURCC_I422, 1); break; case DATAFORMAT_YUV420: output[0] = jpeg_buffer; output[1] = jpeg_buffer + (editlist->video_width * editlist->video_height); output[2] = jpeg_buffer + (editlist->video_width * editlist->video_height * 5 / 4); frame_planar_to_packed(settings->yuv_overlay->pixels[0], output, editlist->video_width, editlist->video_height, settings->yuvformat, FOURCC_I420, 1); break; # ifdef HAVE_LIBDV case DATAFORMAT_DV2: dv_parse_header(settings->decoder, jpeg_buffer); switch(settings->decoder->sampling) { case e_dv_sample_420: /* libdv decodes PAL DV directly as planar YUV 420 * (YV12 or 4CC 0x32315659) if configured with the flag * --with-pal-yuv=YV12 which is not (!) the default */ if (libdv_pal_yv12 == 1) { settings->pitches[0] = settings->decoder->width; settings->pitches[1] = settings->decoder->width / 2; settings->pitches[2] = settings->decoder->width / 2; dv_decode_full_frame(settings->decoder, jpeg_buffer, e_dv_color_yuv, settings->yuvbuff, (int *)settings->pitches); /* swap the U and V components */ frame_tmp = settings->yuvbuff[2]; settings->yuvbuff[2] = settings->yuvbuff[1]; settings->yuvbuff[1] = frame_tmp; frame_planar_to_packed(settings->yuv_overlay->pixels[0], settings->yuvbuff, editlist->video_width, editlist->video_height, settings->yuvformat, FOURCC_I420, 1); break; } case e_dv_sample_411: case e_dv_sample_422: /* libdv decodes NTSC DV (native 411) and by default also PAL * DV (native 420) as packed YUV 422 (YUY2 or 4CC 0x32595559) * where the U and V information is repeated. This can be * transformed to planar 420 (YV12 or 4CC 0x32315659). * For NTSC DV this transformation is lossy. */ settings->pitches[0] = settings->decoder->width * 2; settings->pitches[1] = 0; settings->pitches[2] = 0; dv_decode_full_frame(settings->decoder, jpeg_buffer, e_dv_color_yuv, settings->yuv_overlay->pixels, (int *)settings->pitches); break; case e_dv_sample_none: /* FIXME */ break; } break; # endif default: return 0; } if (!lavplay_SDL_unlock(info)) return 0; SDL_DisplayYUVOverlay(settings->yuv_overlay, &(settings->jpegdims)); return 1; } #endif /* HAVE_SDL */ /****************************************************** * lavplay_SDL_init() * when using software playback - initialize SDL * * return value: 1 on success, 0 on error ******************************************************/ #ifdef HAVE_SDL static int lavplay_SDL_init(lavplay_t *info) { char *sbuffer; int i; video_playback_setup *settings = (video_playback_setup *)info->settings; EditList *editlist = info->editlist; lavplay_msg(LAVPLAY_MSG_INFO, info, "Initialising SDL"); if (SDL_Init (SDL_INIT_VIDEO) < 0) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "SDL Failed to initialise..."); return 0; } /* Now initialize SDL */ if (info->soft_full_screen) settings->screen = SDL_SetVideoMode(info->sdl_width, info->sdl_height, 0, SDL_HWSURFACE | SDL_FULLSCREEN); else settings->screen = SDL_SetVideoMode(info->sdl_width, info->sdl_height, 0, SDL_HWSURFACE); if (!settings->screen) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "SDL: Output screen error: %s", SDL_GetError()); return 0; } SDL_EventState(SDL_KEYDOWN, SDL_ENABLE); SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); /* since IYUV ordering is not supported by Xv accel on maddog's system * (Matrox G400 --- although, the alias I420 is, but this is not * recognized by SDL), we use YV12 instead, which is identical, * except for ordering of Cb and Cr planes... * we swap those when we copy the data to the display buffer... */ /* FIXME: Is YUY2 best 422? */ settings->yuv_overlay = SDL_CreateYUVOverlay(editlist->video_width, editlist->video_height, settings->yuvformat, settings->screen); if (!settings->yuv_overlay) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "SDL: Couldn't create SDL_yuv_overlay: %s", SDL_GetError()); return 0; } lavplay_msg(LAVPLAY_MSG_INFO, info, "SDL YUV overlay: %s", settings->yuv_overlay->hw_overlay ? "hardware" : "software" ); #if 0 if(settings->yuv_overlay->pitches[0] != settings->yuv_overlay->pitches[1] || settings->yuv_overlay->pitches[0] != settings->yuv_overlay->pitches[2] ) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "SDL returned pitches[] = { %d, %d, %d }", settings->yuv_overlay->pitches[0], settings->yuv_overlay->pitches[1], settings->yuv_overlay->pitches[2]); lavplay_msg(LAVPLAY_MSG_ERROR, info, "SDL returned non-YUV422 overlay!"); return 0; } #endif settings->jpegdims.x = 0; /* This is not going to work with interlaced pics !! */ settings->jpegdims.y = 0; settings->jpegdims.w = info->sdl_width; settings->jpegdims.h = info->sdl_height; /* Lock the screen to test, and to be able to access screen->pixels */ if (!lavplay_SDL_lock(info)) return 0; /* Draw bands of color on the raw surface, as run indicator for debugging */ sbuffer = (char *)settings->screen->pixels; for ( i=0; i < settings->screen->h; ++i ) { memset(sbuffer,(i*255)/settings->screen->h, settings->screen->w * settings->screen->format->BytesPerPixel); sbuffer += settings->screen->pitch; } /* Set the windows title */ SDL_WM_SetCaption("Lavplay Video Playback", "0000000"); /* unlock, update and wait for the fun to begin */ if (!lavplay_SDL_unlock(info)) return 0; SDL_UpdateRect(settings->screen, 0, 0, settings->jpegdims.w, settings->jpegdims.h); return 1; } #endif /****************************************************** * lavplay_mjpeg_software_frame_sync() * Try to keep in sync with nominal frame rate, * timestamp frame with actual completion time * (after any deliberate sleeps etc) * * return value: 1 on success, 0 on error ******************************************************/ #ifdef HAVE_SDL static void lavplay_mjpeg_software_frame_sync(lavplay_t *info, int frame_periods) { int usec_since_lastframe; struct timeval now; struct timespec nsecsleep; video_playback_setup *settings = (video_playback_setup *)info->settings; /*EditList *editlist = info->editlist; */ /* I really *wish* the timer was higher res on x86 Linux... 10mSec * is a *pain*. Sooo wasteful here... */ for (;;) { gettimeofday( &now, 0 ); usec_since_lastframe = now.tv_usec - settings->lastframe_completion.tv_usec; if ( usec_since_lastframe< 0) usec_since_lastframe+= 1000000; if( now.tv_sec > settings->lastframe_completion.tv_sec+1 ) usec_since_lastframe= 1000000; if( settings->first_frame || frame_periods*settings->usec_per_frame-usec_since_lastframe < (1000000)/HZ ) break; /* Assume some other process will get a time-slice before * we do... and hence the worst-case delay of 1/HZ after * sleep timer expiry will apply. Reasonable since X will * probably do something... */ nsecsleep.tv_nsec = (frame_periods*settings->usec_per_frame-usec_since_lastframe-1000000/HZ)*1000; nsecsleep.tv_sec = 0; nanosleep( &nsecsleep, NULL ); } settings->first_frame = 0; /* We are done with writing the picture - Now update all surrounding info */ gettimeofday( &(settings->lastframe_completion), 0 ); settings->syncinfo[settings->currently_processed_frame].timestamp = settings->lastframe_completion; } #endif /****************************************************** * lavplay_mjpeg_playback_thread() * the main (software) video playback thread * * return value: 1 on success, 0 on error ******************************************************/ #ifdef HAVE_SDL static void *lavplay_mjpeg_playback_thread(void * arg) { lavplay_t *info = (lavplay_t *)arg; video_playback_setup *settings = (video_playback_setup *)info->settings; /*EditList *editlist = info->editlist; */ lavplay_msg(LAVPLAY_MSG_DEBUG, info, "Starting software playback thread"); /* Allow easy shutting down by other processes... */ pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL ); pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL ); while (settings->state != LAVPLAY_STATE_STOP) { pthread_mutex_lock(&(settings->valid_mutex)); while (settings->valid[settings->currently_processed_frame] == 0) { lavplay_msg(LAVPLAY_MSG_DEBUG, info, "Playback thread: sleeping for new frames (waiting for frame %d)", settings->currently_processed_frame); pthread_cond_wait(&(settings->buffer_filled[settings->currently_processed_frame]), &(settings->valid_mutex)); if (settings->state == LAVPLAY_STATE_STOP) { /* Ok, we shall exit, that's the reason for the wakeup */ lavplay_msg(LAVPLAY_MSG_DEBUG, info, "Playback thread: was told to exit"); pthread_exit(NULL); } } pthread_mutex_unlock(&(settings->valid_mutex)); /* There is one buffer to play - get ready to rock ! */ if (settings->currently_processed_entry != settings->buffer_entry[settings->currently_processed_frame] && !lavplay_SDL_update(info, settings->buff+settings->currently_processed_frame*settings->br.size, settings->data_format[settings->currently_processed_frame], settings->br.size)) { /* something went wrong - give a warning (don't exit yet) */ lavplay_msg(LAVPLAY_MSG_WARNING, info, "Error playing a frame"); } settings->currently_processed_entry = settings->buffer_entry[settings->currently_processed_frame]; /* Synchronise and timestamp current frame after sync */ lavplay_mjpeg_software_frame_sync(info, settings->valid[settings->currently_processed_frame]); settings->syncinfo[settings->currently_processed_frame].frame = settings->currently_processed_frame; pthread_mutex_lock(&(settings->valid_mutex)); settings->valid[settings->currently_processed_frame] = 0; pthread_mutex_unlock(&(settings->valid_mutex)); /* Broadcast & wake up the waiting processes */ pthread_cond_broadcast(&(settings->buffer_done[settings->currently_processed_frame])); /* Now update the internal variables */ settings->currently_processed_frame = (settings->currently_processed_frame + 1) % settings->br.count; settings->show_top = (settings->show_top) ? 0 : 1; } lavplay_msg(LAVPLAY_MSG_DEBUG, info, "Playback thread: was told to exit"); pthread_exit(NULL); return NULL; } #endif /****************************************************** * lavplay_mjpeg_open() * hardware: opens the device and allocates buffers * software: inits threads and allocates buffers * * return value: 1 on success, 0 on error ******************************************************/ static int lavplay_mjpeg_open(lavplay_t *info) { #ifdef HAVE_SDL int i; #endif video_playback_setup *settings = (video_playback_setup *)info->settings; EditList *editlist = info->editlist; int max_frame_size = editlist->max_frame_size; lavplay_msg(LAVPLAY_MSG_DEBUG, info, "Initializing the %s", info->playback_mode=='S'?"threading system":"video device"); switch (info->playback_mode) { #ifdef HAVE_V4L case 'H': case 'C': /* open video device */ if ((settings->video_fd = open(info->video_dev, O_RDWR)) < 0) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Error opening %s: %s", info->video_dev, strerror(errno)); return 0; } /* Request buffers */ settings->br.count = info->MJPG_numbufs; if (max_frame_size < 140*1024) max_frame_size = 140*1024; settings->br.size = (max_frame_size + 4095)&~4095; if (ioctl(settings->video_fd, MJPIOC_REQBUFS, &(settings->br)) < 0) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Error requesting buffers: %s", strerror(errno)); return 0; } /* Map the buffers */ settings->buff = mmap(0, settings->br.count * settings->br.size, PROT_READ | PROT_WRITE, MAP_SHARED, settings->video_fd, 0); if (settings->buff == MAP_FAILED) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Error mapping the video buffer: %s", strerror(errno)); return 0; } break; #endif #ifdef HAVE_SDL case 'S': /* Just allocate MJPG_nbuf buffers */ settings->br.count = info->MJPG_numbufs; settings->br.size = (max_frame_size*2 + 4095)&~4095; settings->buff = (uint8_t *)malloc(settings->br.count * settings->br.size); if (!settings->buff) { lavplay_msg (LAVPLAY_MSG_ERROR, info, "Malloc error, you\'re probably out of memory"); return 0; } pthread_mutex_init(&(settings->valid_mutex), NULL); pthread_mutex_init(&(settings->syncinfo_mutex), NULL); /* Invalidate all buffers, and initialize the conditions */ for (i=0;ivalid[i] = 0; pthread_cond_init(&(settings->buffer_filled[i]), NULL); pthread_cond_init(&(settings->buffer_done[i]), NULL); memset(&(settings->syncinfo[i]), 0, sizeof(struct mjpeg_sync)); } /* Now do the thread magic */ settings->currently_processed_frame = 0; settings->currently_processed_entry = -1; settings->show_top = 1; /* start with top frames as default, change with mjpeg_set_params */ if (pthread_create(&(settings->software_playback_thread), NULL, lavplay_mjpeg_playback_thread, (void *)info)) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Could not create software playback thread"); return 0; } break; #endif default: lavplay_msg(LAVPLAY_MSG_ERROR, info, "lavplay_mjpeg_open(): Unknown playback mode (\'%c\')", info->playback_mode); return 0; } settings->usec_per_frame = 0; return 1; } /****************************************************** * lavplay_mjpeg_get_params() * get default parameters * * return value: 1 on success, 0 on error ******************************************************/ static int lavplay_mjpeg_get_params(lavplay_t *info, struct mjpeg_params *bp) { #ifdef HAVE_SDL int i; #endif #ifdef HAVE_V4L video_playback_setup *settings = (video_playback_setup *)info->settings; #endif /*EditList *editlist = info->editlist; */ switch (info->playback_mode) { #ifdef HAVE_V4L case 'H': case 'C': /* do a MJPIOC_G_PARAMS ioctl to get proper default values */ if (ioctl(settings->video_fd, MJPIOC_G_PARAMS, bp) < 0) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Error getting video parameters: %s", strerror(errno)); return 0; } break; #endif #ifdef HAVE_SDL case 'S': /* Set some necessary params */ bp->decimation = 1; bp->quality = 50; /* default compression factor 8 */ bp->odd_even = 1; bp->APPn = 0; bp->APP_len = 0; /* No APPn marker */ for(i=0;i<60;i++) bp->APP_data[i] = 0; bp->COM_len = 0; /* No COM marker */ for(i=0;i<60;i++) bp->COM_data[i] = 0; bp->VFIFO_FB = 1; memset(bp->reserved,0,sizeof(bp->reserved)); break; #endif default: lavplay_msg(LAVPLAY_MSG_ERROR, info, "lavplay_mjpeg_get_params(): Unknown playback mode (\'%c\')", info->playback_mode); return 0; } return 1; } /****************************************************** * lavplay_mjpeg_set_params() * set the parameters * * return value: 1 on success, 0 on error ******************************************************/ static int lavplay_mjpeg_set_params(lavplay_t *info, struct mjpeg_params *bp) { video_playback_setup *settings = (video_playback_setup *)info->settings; /*EditList *editlist = info->editlist; */ #ifdef HAVE_V4L if (info->playback_mode == 'H') /* only when doing on-screen (hardware-decoded) output */ { struct video_window vw; struct video_capability vc; int n, screenwidth, screenheight; #ifndef X_DISPLAY_MISSING XWindowAttributes wts; Display *dpy; if (NULL == (dpy = XOpenDisplay(strchr(info->display, ':')))) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Can't open X11 display %s\n", info->display); return 0; } #endif if (ioctl(settings->video_fd, VIDIOCGCAP, &vc) < 0) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Error getting device capabilities: %s", strerror(errno)); return 0; } /* hack for wrong return value of marvel cards..... */ if (vc.maxwidth!=640 && vc.maxwidth!=768) vc.maxwidth=720; #ifndef X_DISPLAY_MISSING XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &wts); screenwidth = wts.width; screenheight = wts.height; #else screenwidth = 1024; screenheight = 768; #endif vw.y = info->soft_full_screen ? 0: (screenheight-((bp->norm == 0) ? 576 : 480))/2; if (info->vw_y_offset != VALUE_NOT_FILLED && !info->soft_full_screen) vw.y = info->vw_y_offset; vw.x = info->soft_full_screen ? 0: (screenwidth-vc.maxwidth)/2; if (info->vw_x_offset != VALUE_NOT_FILLED && !info->soft_full_screen) vw.x = info->vw_x_offset; vw.width = info->soft_full_screen ? screenwidth : vc.maxwidth; if (info->sdl_width > 0 && !info->soft_full_screen) vw.width = info->sdl_width; vw.height = info->soft_full_screen ? screenheight : ((bp->norm == 0) ? 576 : 480); if (info->sdl_height > 0 && !info->soft_full_screen) vw.height = info->sdl_height; vw.clips = NULL; vw.clipcount = 0; vw.chromakey = -1; if (info->soft_full_screen ? 0: (screenwidth-vc.maxwidth)/2 < 0) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "X offset (%d) would be < 0", vw.x); return 0; } if (info->soft_full_screen ? 0: (screenheight-((bp->norm == 0) ? 576 : 480))/2 < 0) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Y offset (%d) would be < 0", vw.y); return 0; } #ifndef X_DISPLAY_MISSING if (vw.x + vw.width > wts.width) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "X offset + width (%d+%d) would be > screensize (%d)", vw.x, vw.width, wts.width); return 0; } if (vw.y + vw.height > wts.height) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Y offset + height (%d+%d) would be > screensize (%d)", vw.y, vw.height, wts.height); return 0; } #endif if (ioctl(settings->video_fd, VIDIOCSWIN, &vw) < 0) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Could not set on-screen window parameters (check framebuffer-params with v4l-conf): %s", strerror(errno)); return 0; } n = 1; if (ioctl(settings->video_fd, VIDIOCCAPTURE, &n) < 0) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Could not activate on-screen window: %s", strerror(errno)); return 0; } bp->VFIFO_FB = 1; } #endif switch (info->playback_mode) { #ifdef HAVE_V4L case 'C': case 'H': /* All should be set up now, set the parameters */ lavplay_msg(LAVPLAY_MSG_DEBUG, info, "Hardware video settings: input=%d, norm=%d, fields_per_buf=%d, " "x=%d, y=%d, width=%d, height=%d, quality=%d", bp->input, bp->norm, bp->field_per_buff, bp->img_x, bp->img_y, bp->img_width, bp->img_height, bp->quality); if (ioctl(settings->video_fd, MJPIOC_S_PARAMS, bp) < 0) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Error setting video parameters: %s", strerror(errno)); return 0; } break; #endif #ifdef HAVE_SDL case 'S': settings->show_top = (bp->odd_even) ? 1 : 0; /* odd_even = 1: show top field first */ break; #endif default: lavplay_msg(LAVPLAY_MSG_ERROR, info, "lavplay_mjpeg_set_params(): Unknown playback mode (\'%c\')", info->playback_mode); return 0; } return 1; } /****************************************************** * lavplay_mjpeg_set_frame_rate() * set the frame rate * * return value: 1 on success, 0 on error ******************************************************/ static int lavplay_mjpeg_set_playback_rate(lavplay_t *info, double video_fps, int norm) { int norm_usec_per_frame = 0; int target_usec_per_frame; video_playback_setup *settings = (video_playback_setup *)info->settings; /*EditList *editlist = info->editlist; */ switch (norm) { case VIDEO_MODE_PAL: case VIDEO_MODE_SECAM: norm_usec_per_frame = 1000000/25; /* 25Hz */ break; case VIDEO_MODE_NTSC: norm_usec_per_frame = 1001000/30; /* 30ish Hz */ break; default: if (info->playback_mode != 'S') { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Hardware playback impossible: unknown video norm!"); return 0; } } if( video_fps != 0.0 ) target_usec_per_frame = (int)(1000000.0 / video_fps); else target_usec_per_frame = norm_usec_per_frame; if (info->playback_mode != 'S' && abs(target_usec_per_frame - norm_usec_per_frame) > 50) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Specified frame-rate doesn't match in mode in hardware playback (target: %d, norm: %d)", target_usec_per_frame, norm_usec_per_frame); return 0; } settings->usec_per_frame = target_usec_per_frame; return 1; } /****************************************************** * lavplay_mjpeg_queue_buf() * queue a buffer * * return value: 1 on success, 0 on error ******************************************************/ static int lavplay_mjpeg_queue_buf(lavplay_t *info, int frame, int frame_periods) { video_playback_setup *settings = (video_playback_setup *)info->settings; /*EditList *editlist = info->editlist; */ switch (info->playback_mode) { #ifdef HAVE_V4L case 'H': case 'C': if (ioctl(settings->video_fd, MJPIOC_QBUF_PLAY, &frame) < 0) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Error queueing buffer: %s", strerror(errno)); return 0; } break; #endif #ifdef HAVE_SDL case 'S': /* mark this buffer as playable and tell the software playback thread to wake up if it sleeps */ pthread_mutex_lock(&(settings->valid_mutex)); settings->valid[frame] = frame_periods; pthread_cond_broadcast(&(settings->buffer_filled[frame])); pthread_mutex_unlock(&(settings->valid_mutex)); break; #endif default: lavplay_msg(LAVPLAY_MSG_ERROR, info, "lavplay_mjpeg_queue_buf(): Unknown playback mode (\'%c\')", info->playback_mode); return 0; } return 1; } /****************************************************** * lavplay_mjpeg_sync_buf() * sync on a buffer * * return value: 1 on success, 0 on error ******************************************************/ static int lavplay_mjpeg_sync_buf(lavplay_t *info, struct mjpeg_sync *bs) { video_playback_setup *settings = (video_playback_setup *)info->settings; /*EditList *editlist = info->editlist; */ switch (info->playback_mode) { #ifdef HAVE_V4L case 'H': case 'C': if (ioctl(settings->video_fd, MJPIOC_SYNC, bs) < 0) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Error syncing on a buffer: %s", strerror(errno)); return 0; } lavplay_msg(LAVPLAY_MSG_DEBUG, info, "frame=%ld, length=%ld, seq=%ld", bs->frame, bs->length, bs->seq); break; #endif #ifdef HAVE_SDL case 'S': /* Wait until this buffer has been played */ pthread_mutex_lock(&(settings->valid_mutex)); while (settings->valid[settings->currently_synced_frame] != 0) { pthread_cond_wait(&(settings->buffer_done[settings->currently_synced_frame]), &(settings->valid_mutex)); } pthread_mutex_unlock(&(settings->valid_mutex)); /* copy the relevant sync information */ memcpy(bs, &(settings->syncinfo[settings->currently_synced_frame]), sizeof(struct mjpeg_sync)); settings->currently_synced_frame = (settings->currently_synced_frame + 1) % settings->br.count; break; #endif default: lavplay_msg(LAVPLAY_MSG_ERROR, info, "lavplay_mjpeg_sync_buf(): Unknown playback mode (\'%c\')", info->playback_mode); return 0; } return 1; } /****************************************************** * lavplay_mjpeg_close() * close down * * return value: 1 on success, 0 on error ******************************************************/ static int lavplay_mjpeg_close(lavplay_t *info) { #ifdef HAVE_V4L int n; #endif video_playback_setup *settings = (video_playback_setup *)info->settings; /*EditList *editlist = info->editlist; */ lavplay_msg(LAVPLAY_MSG_DEBUG, info, "Closing down the %s", info->playback_mode=='S'?"threading system":"video device"); switch (info->playback_mode) { #ifdef HAVE_V4L case 'C': case 'H': n = -1; if (ioctl(settings->video_fd, MJPIOC_QBUF_PLAY, &n) < 0) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Error de-queueing the buffers: %s", strerror(errno)); return 0; } if (info->playback_mode == 'H') { n = 0; if (ioctl(settings->video_fd, VIDIOCCAPTURE, &n) < 0) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Could not deactivate on-screen window: %s", strerror(errno)); return 0; } } break; #endif #ifdef HAVE_SDL case 'S': pthread_cancel(settings->software_playback_thread); if (pthread_join(settings->software_playback_thread, NULL)) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Failure deleting software playback thread"); return 0; } break; #endif default: lavplay_msg(LAVPLAY_MSG_ERROR, info, "lavplay_mjpeg_close(): Unknown playback mode (\'%c\')", info->playback_mode); return 0; } return 1; } /****************************************************** * lavplay_init() * check the given settings and initialize everything * * return value: 1 on success, 0 on error ******************************************************/ static int lavplay_init(lavplay_t *info) { long nqueue; struct mjpeg_params bp; #ifdef HAVE_V4L struct video_capability vc; #endif video_playback_setup *settings = (video_playback_setup *)info->settings; EditList *editlist = info->editlist; int hn; if (editlist->video_frames == 0 && !info->get_video_frame) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "No video source!"); return 0; } if (editlist->video_frames == 0 && info->editlist->has_audio && info->audio && !info->get_audio_sample) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Audio turned on but no audio source!"); return 0; } if (editlist->video_frames > 0 && (info->get_video_frame || info->get_audio_sample)) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Manual input as well as file input!"); return 0; } /* Set min/max options so that it runs like it should */ settings->min_frame_num = 0; settings->max_frame_num = editlist->video_frames - 1; settings->current_frame_num = settings->min_frame_num; /* start with frame 0 */ /* Seconds per video frame: */ settings->spvf = 1.0 / editlist->video_fps; lavplay_msg(LAVPLAY_MSG_DEBUG, info, "1.0/SPVF = %4.4f", 1.0 / settings->spvf ); /* Seconds per audio sample: */ if(editlist->has_audio && info->audio) settings->spas = 1.0 / editlist->audio_rate; else settings->spas = 0.; if (info->flicker_reduction) { /* allocate auxiliary video buffer for flicker reduction */ settings->tmpbuff[0] = (uint8_t *)malloc(editlist->max_frame_size); settings->tmpbuff[1] = (uint8_t *)malloc(editlist->max_frame_size); if (!settings->tmpbuff[0] || !settings->tmpbuff[1]) { lavplay_msg (LAVPLAY_MSG_ERROR, info, "Malloc error, you\'re probably out of memory"); return 0; } } /* initialize the playback threading system (used to be libmjpeg) */ lavplay_mjpeg_open(info); #ifdef HAVE_SDL /* init SDL if we want SDL */ if (info->playback_mode == 'S') { char *env = getenv("LAVPLAY_VIDEO_FORMAT"); settings->yuvformat = (env? ((env[0])|(env[1]<<8)|(env[2]<<16)|(env[3]<<24)): SDL_YUY2_OVERLAY); if (!info->sdl_width) info->sdl_width = editlist->video_width; if (!info->sdl_height) info->sdl_height = editlist->video_height; if (!lavplay_SDL_init(info)) return 0; settings->yuvbuff[0] = (uint8_t *)malloc(editlist->video_width * editlist->video_height * 2); if (!settings->yuvbuff[0]) { lavplay_msg (LAVPLAY_MSG_ERROR, info, "Malloc error, you\'re probably out of memory"); return 0; } settings->yuvbuff[1] = settings->yuvbuff[0] + (editlist->video_width * editlist->video_height); settings->yuvbuff[2] = settings->yuvbuff[0] + (editlist->video_width * editlist->video_height * 3 / 2); # ifdef HAVE_LIBDV settings->decoder = dv_decoder_new(0,0,0); settings->decoder->quality = DV_QUALITY_BEST; # endif } #endif if (editlist->has_audio && info->audio) { if (audio_init(0, info->use_write, (editlist->audio_chans>1), editlist->audio_bits, editlist->audio_rate)) /* increase this last argument to test sync */ { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Error initializing Audio: %s",audio_strerror()); return 0; } settings->audio_buffer_size = audio_get_buffer_size(); } /* After we have fired up the audio and video threads system (which * are assisted if we're installed setuid root, we want to set the * effective user id to the real user id */ if(seteuid(getuid()) < 0) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Can't set effective user-id: %s", strerror(errno)); return 0; } /* Fill all buffers first */ for(nqueue=0;nqueuebr.count;nqueue++) { if (!lavplay_queue_next_frame(info, settings->buff+nqueue* settings->br.size, (settings->data_format[nqueue] = el_video_frame_data_format(settings->current_frame_num, editlist)), 0,0,0)) break; } /* Choose the correct parameters for playback */ if (!lavplay_mjpeg_get_params(info, &bp)) return 0; /* set options */ bp.input = 0; bp.norm = (editlist->video_norm == 'n') ? VIDEO_MODE_NTSC : VIDEO_MODE_PAL; lavplay_msg(LAVPLAY_MSG_INFO, info, "Output norm: %s", bp.norm==VIDEO_MODE_NTSC?"NTSC":"PAL"); hn = bp.norm==VIDEO_MODE_NTSC?480:576; /* Height of norm */ if (info->playback_mode != 'S') { #ifdef HAVE_V4L /* set correct width of device for hardware * DC10(+): 768 (PAL/SECAM) or 640 (NTSC), Buz/LML33: 720 */ if (ioctl(settings->video_fd, VIDIOCGCAP, &vc) < 0) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Error getting device capabilities: %s", strerror(errno)); return 0; } /* vc.maxwidth is often reported wrong - let's just keep it broken (sigh) */ if (vc.maxwidth != 768 && vc.maxwidth != 640) vc.maxwidth = 720; bp.decimation = 0; /* we will set proper params ourselves later on */ if (editlist->video_width > vc.maxwidth || editlist->video_height > hn ) { /* the video is too big */ lavplay_msg(LAVPLAY_MSG_ERROR, info, "Video dimensions too large: %ld x %ld, device max = %dx%d", editlist->video_width, editlist->video_height, vc.maxwidth, hn); return 0; } /* if zoom_to_fit is set, HorDcm is independent of interlacing */ if (info->zoom_to_fit) { if (editlist->video_width <= vc.maxwidth/4 ) bp.HorDcm = 4; else if (editlist->video_width <= vc.maxwidth/2) bp.HorDcm = 2; else bp.HorDcm = 1; } if (editlist->video_inter) { /* Interlaced video, 2 fields per buffer */ bp.field_per_buff = 2; bp.TmpDcm = 1; if (info->zoom_to_fit) { if (editlist->video_height <= hn/2) bp.VerDcm = 2; else bp.VerDcm = 1; } else { /* if zoom_to_fit is not set, we always use decimation 1 */ bp.HorDcm = 1; bp.VerDcm = 1; } } else { /* Not interlaced, 1 field per buffer */ bp.field_per_buff = 1; bp.TmpDcm = 2; if (editlist->video_height > hn/2 || (!info->zoom_to_fit && editlist->video_width > vc.maxwidth/2)) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Video dimensions (not interlaced) too large: %ld x %ld", editlist->video_width, editlist->video_height); if (editlist->video_width > vc.maxwidth/2) lavplay_msg(LAVPLAY_MSG_ERROR, info, "Try using the \'zoom-to-fit\'-option"); return 0; } if(info->zoom_to_fit) { if (editlist->video_height <= hn/4 ) bp.VerDcm = 2; else bp.VerDcm = 1; } else { /* the following is equivalent to decimation 2 in lavrec: */ bp.HorDcm = 2; bp.VerDcm = 1; } } /* calculate height, width and offsets from the above settings */ bp.quality = 100; bp.img_width = bp.HorDcm * editlist->video_width; bp.img_height = bp.VerDcm * editlist->video_height/bp.field_per_buff; if (info->horizontal_offset == VALUE_NOT_FILLED) bp.img_x = (vc.maxwidth - bp.img_width)/2; else bp.img_x = info->horizontal_offset; if (info->vertical_offset == VALUE_NOT_FILLED) bp.img_y = (hn/2 - bp.img_height)/2; else bp.img_y = info->vertical_offset/2; lavplay_msg(LAVPLAY_MSG_INFO, info, "Output dimensions: %dx%d+%d+%d", bp.img_width, bp.img_height*2, bp.img_x, bp.img_y*2); lavplay_msg(LAVPLAY_MSG_INFO, info, "Output zoom factors: %d (hor) %d (ver)", bp.HorDcm,bp.VerDcm*bp.TmpDcm); #else fprintf(stderr, "No video4linux support!\n"); return 0; #endif } #ifdef HAVE_SDL else { /* software playback */ lavplay_msg(LAVPLAY_MSG_INFO, info, "Output dimensions: %ldx%ld", editlist->video_width, editlist->video_height); } #endif /* Set field polarity for interlaced video */ bp.odd_even = (editlist->video_inter == Y4M_ILACE_TOP_FIRST); /*if (info->exchange_fields) bp.odd_even = !bp.odd_even; */ /*this is already done by the open_files() function */ /* Set these settings */ if (!lavplay_mjpeg_set_params(info, &bp)) return 0; if (!lavplay_mjpeg_set_playback_rate(info, editlist->video_fps, editlist->video_norm=='p'?0:1)) return 0; return 1; } /****************************************************** * lavplay_playback_cycle() * the playback cycle ******************************************************/ static void lavplay_playback_cycle(lavplay_t *info) { video_playback_stats stats; video_playback_setup *settings = (video_playback_setup *)info->settings; EditList *editlist = info->editlist; struct mjpeg_sync bs; struct timeval audio_tmstmp; struct timeval time_now; double tdiff1, tdiff2; int n; int first_free, frame, skipv, skipa, skipi, nvcorr; long frame_number[256]; /* Must be at least as big as the number of buffers used */ stats.stats_changed = 0; stats.num_corrs_a = 0; stats.num_corrs_b = 0; stats.nqueue = 0; stats.nsync = 0; stats.audio = 0; stats.norm = editlist->video_norm=='n'?1:0; tdiff1 = 0.; tdiff2 = 0.; nvcorr = 0; /* Queue the buffers read, this triggers video playback */ if (editlist->has_audio && info->audio) { audio_start(); stats.audio = 1; } for(n=0;nbr.count;n++) /* TODO: maybe br.count-1? */ { frame_number[n] = settings->current_frame_num; lavplay_mjpeg_queue_buf(info, n, 1); } stats.nqueue = settings->br.count; while (settings->state != LAVPLAY_STATE_STOP) { /* Sync to get a free buffer. We want to have all free buffers, * which have been played so far. Normally there should be a function * in the kernel API to get the number of all free buffers. * I don't want to change this API at the moment, therefore * we look on the clock to see if there are more buffers ready */ first_free = stats.nsync; do { if (settings->state == LAVPLAY_STATE_STOP) goto FINISH; if (!lavplay_mjpeg_sync_buf(info, &bs)) { lavplay_change_state(info, LAVPLAY_STATE_STOP); goto FINISH; } frame = bs.frame; /* Since we queue the frames in order, we have to get them back in order */ if (frame != stats.nsync % settings->br.count) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "**INTERNAL ERROR: Bad frame order on sync: frame = %d, nsync = %d, br.count = %ld", frame, stats.nsync, settings->br.count); lavplay_change_state(info, LAVPLAY_STATE_STOP); goto FINISH; } stats.nsync++; /* Look on clock */ gettimeofday(&time_now, 0); stats.tdiff = time_now.tv_sec - bs.timestamp.tv_sec + (time_now.tv_usec - bs.timestamp.tv_usec)*1.e-6; } while (stats.tdiff > settings->spvf && (stats.nsync - first_free) < settings->br.count - 1); if ((stats.nsync - first_free) > settings->br.count - 3) lavplay_msg(LAVPLAY_MSG_WARNING, info, "Disk too slow, can not keep pace!"); if (editlist->has_audio && info->audio) { audio_get_output_status(&audio_tmstmp, &(stats.num_asamps), &(stats.num_aerr)); if (audio_tmstmp.tv_sec) { tdiff1 = settings->spvf * (stats.nsync - nvcorr) - settings->spas * settings->audio_buffer_size / editlist->audio_bps * stats.num_asamps; tdiff2 = (bs.timestamp.tv_sec - audio_tmstmp.tv_sec) + (bs.timestamp.tv_usec - audio_tmstmp.tv_usec) * 1.e-6; } } stats.tdiff = tdiff1 - tdiff2; /* Fill and queue free buffers again */ for (n=first_free;nsync_correction) { if (stats.tdiff > settings->spvf) { /* Video is ahead audio */ skipa = 1; if (info->sync_ins_frames) skipi = 1; nvcorr++; stats.num_corrs_a++; stats.tdiff -= settings->spvf; stats.stats_changed = 1; } if (stats.tdiff < -settings->spvf) { /* Video is behind audio */ skipv = 1; if (!info->sync_skip_frames) skipi = 1; nvcorr--; stats.num_corrs_b++; stats.tdiff += settings->spvf; stats.stats_changed = 1; } } /* Read one frame, break if EOF is reached */ frame = n % settings->br.count; frame_number[frame] = settings->current_frame_num; #ifdef HAVE_SDL settings->buffer_entry[frame] = editlist->frame_list[settings->current_frame_num]; #endif if (!lavplay_queue_next_frame(info, settings->buff+frame*settings->br.size, (settings->data_format[frame] = el_video_frame_data_format(settings->current_frame_num, editlist)), skipv,skipa,skipi)) { lavplay_change_state(info, LAVPLAY_STATE_STOP); goto FINISH; } if (skipv) continue; /* no frame has been read */ /* Queue the frame */ if (!lavplay_mjpeg_queue_buf(info, frame, 1)) { lavplay_change_state(info, LAVPLAY_STATE_STOP); goto FINISH; } stats.nqueue++; n++; } /* output statistics */ if (editlist->has_audio && info->audio) stats.audio = settings->audio_mute?0:1; stats.play_speed = settings->current_playback_speed; stats.frame = settings->current_frame_num; if (info->output_statistics) info->output_statistics(&stats); stats.stats_changed = 0; } FINISH: /* All buffers are queued, sync on the outstanding buffers * Never try to sync on the last buffer, it is a hostage of * the codec since it is played over and over again */ /* NOTE: this causes lockup for some reason - so just leave it */ /*while (stats.nqueue > stats.nsync + 1) */ /*{ */ /* lavplay_mjpeg_sync_buf(info, &bs); */ /* stats.nsync++; */ /*} */ /* and we also don't need audio anymore */ if (editlist->has_audio && info->audio) audio_shutdown(); } /****************************************************** * lavplay_playback_thread() * The main playback thread ******************************************************/ static void *lavplay_playback_thread(void *data) { lavplay_t *info = (lavplay_t *)data; video_playback_setup *settings = (video_playback_setup *)info->settings; /*EditList *editlist = info->editlist; */ lavplay_playback_cycle(info); if (info->flicker_reduction) { free(settings->tmpbuff[0]); free(settings->tmpbuff[1]); } lavplay_mjpeg_close(info); #ifdef HAVE_SDL if (info->playback_mode == 'S') { SDL_FreeYUVOverlay(settings->yuv_overlay); SDL_Quit(); free(settings->yuvbuff[0]); } #endif pthread_exit(NULL); return NULL; } /****************************************************** * lavplay_malloc() * malloc the pointer and set default options * * return value: a pointer to an allocated lavplay_t ******************************************************/ lavplay_t *lavplay_malloc(void) { lavplay_t *info; video_playback_setup *settings; info = (lavplay_t *)malloc(sizeof(lavplay_t)); if (!info) { lavplay_msg (LAVPLAY_MSG_ERROR, NULL, "Malloc error, you\'re probably out of memory"); return NULL; } info->playback_mode = 'S'; info->horizontal_offset = VALUE_NOT_FILLED; info->vertical_offset = VALUE_NOT_FILLED; info->exchange_fields = 0; info->zoom_to_fit = 0; info->flicker_reduction = 1; info->preserve_pathnames = 0; info->sdl_width = 0; /* use video size */ info->sdl_height = 0; /* use video size */ info->vw_x_offset = 0; info->vw_y_offset = 0; info->soft_full_screen = 0; info->video_dev = "/dev/video"; info->display = ":0.0"; info->audio = 7; /* 1(forward)|2(reverse)|4(fast) */ info->audio_dev = "/dev/dsp"; info->continuous = 0; info->sync_correction = 1; info->sync_ins_frames = 1; info->sync_skip_frames = 1; info->MJPG_numbufs = 8; info->output_statistics = NULL; info->msg_callback = NULL; info->state_changed = NULL; info->get_video_frame = NULL; info->get_audio_sample = NULL; settings = (video_playback_setup *)malloc(sizeof(video_playback_setup)); info->settings = (void *)settings; if (!(info->settings)) { lavplay_msg (LAVPLAY_MSG_ERROR, NULL, "Malloc error, you\'re probably out of memory"); return NULL; } info->editlist = (EditList *)malloc(sizeof(EditList)); if (!(info->editlist)) { lavplay_msg (LAVPLAY_MSG_ERROR, NULL, "Malloc error, you\'re probably out of memory"); return NULL; } info->editlist->video_frames = 0; settings->current_playback_speed = 0; settings->currently_synced_frame = 0; settings->current_frame_num = 0; settings->old_field_len = 0; settings->old_buff_no = 0; settings->first_frame = 1; settings->buff = NULL; settings->save_list = NULL; settings->save_list_len = 0; return info; } /****************************************************** * lavplay_main() * the whole video-playback cycle * * Basic setup: * * this function initializes the devices, * sets up the whole thing and then forks * the main task and returns control to the * main app. It can then start playing by * setting playback speed and such. Stop * by calling lavplay_stop() * * return value: 1 on succes, 0 on error ******************************************************/ int lavplay_main(lavplay_t *info) { video_playback_setup *settings = (video_playback_setup *)info->settings; /* Flush the Linux File buffers to disk */ sync(); lavplay_change_state(info, LAVPLAY_STATE_PAUSED); /* start with initing */ if (!lavplay_init(info)) return 0; /* fork ourselves to return control to the main app */ if( pthread_create( &(settings->playback_thread), NULL, lavplay_playback_thread, (void*)info) ) { lavplay_msg(LAVPLAY_MSG_ERROR, info, "Failed to create thread"); return 0; } return 1; } /****************************************************** * lavplay_stop() * stop playing * * return value: 1 on succes, 0 on error ******************************************************/ int lavplay_stop(lavplay_t *info) { video_playback_setup *settings = (video_playback_setup *)info->settings; /*EditList *editlist = info->editlist; */ if (settings->state == LAVPLAY_STATE_STOP) { lavplay_msg(LAVPLAY_MSG_DEBUG, info, "We weren't even initialized!"); return 0; } lavplay_change_state(info, LAVPLAY_STATE_STOP); /*pthread_cancel( settings->playback_thread ); */ pthread_join( settings->playback_thread, NULL ); return 1; } /****************************************************** * lavplay_free() * free() the struct * * return value: 1 on succes, 0 on error ******************************************************/ int lavplay_free(lavplay_t *info) { video_playback_setup *settings = (video_playback_setup *)info->settings; if (settings->state != LAVPLAY_STATE_STOP) { lavplay_msg(LAVPLAY_MSG_WARNING, info, "We're not stopped yet, use lavplay_stop() first!"); return 0; } free(info->editlist); free(settings); free(info); return 1; } /*** Methods for simple video editing (cut/paste) ***/ /****************************************************** * lavplay_edit_copy() * copy a number of frames into a buffer * * return value: 1 on succes, 0 on error ******************************************************/ int lavplay_edit_copy(lavplay_t *info, long start, long end) { video_playback_setup *settings = (video_playback_setup *)info->settings; EditList *editlist = info->editlist; int k, i; if (settings->save_list) free(settings->save_list); settings->save_list = (unsigned long *)malloc((end - start + 1) * sizeof(unsigned long)); if (!settings->save_list) { lavplay_msg (LAVPLAY_MSG_ERROR, info, "Malloc error, you\'re probably out of memory"); lavplay_change_state(info, LAVPLAY_STATE_STOP); return 0; } k = 0; for (i=start;i<=end;i++) settings->save_list[k++] = editlist->frame_list[i]; settings->save_list_len = k; lavplay_msg(LAVPLAY_MSG_DEBUG, info, "Copied frames %ld-%ld into buffer", start, end); return 1; } /****************************************************** * lavplay_edit_delete() * delete a number of frames from the current movie * * return value: 1 on succes, 0 on error ******************************************************/ int lavplay_edit_delete(lavplay_t *info, long start, long end) { video_playback_setup *settings = (video_playback_setup *)info->settings; EditList *editlist = info->editlist; int i; if (end < start || start > editlist->video_frames || end >= editlist->video_frames || end < 0 || start < 0) { lavplay_msg(LAVPLAY_MSG_WARNING, info, "Incorrect parameters for deleting frames"); return 0; } for(i=end+1;ivideo_frames;i++) editlist->frame_list[i-(end-start+1)] = editlist->frame_list[i]; /* Update min and max frame_num's to reflect the removed section */ if (start - 1 < settings->min_frame_num) { if (end < settings->min_frame_num) settings->min_frame_num -= (end - start + 1); else settings->min_frame_num = start; } if (start - 1 < settings->max_frame_num) { if (end <= settings->max_frame_num) settings->max_frame_num -= (end - start + 1); else settings->max_frame_num = start - 1; } if (start <= settings->current_frame_num) { if (settings->current_frame_num <= end) { settings->current_frame_num = start; } else { settings->current_frame_num -= (end - start + 1); } } editlist->video_frames -= (end - start + 1); lavplay_msg(LAVPLAY_MSG_DEBUG, info, "Deleted frames %ld-%ld", start, end); return 1; } /****************************************************** * lavplay_edit_cut() * cut a number of frames into a buffer * * return value: 1 on succes, 0 on error ******************************************************/ int lavplay_edit_cut(lavplay_t *info, long start, long end) { if (!lavplay_edit_copy(info, start, end)) return 0; if (!lavplay_edit_delete(info, start, end)) return 0; return 1; } /****************************************************** * lavplay_edit_paste() * paste frames from the buffer into a certain position * * return value: 1 on succes, 0 on error ******************************************************/ int lavplay_edit_paste(lavplay_t *info, long destination) { video_playback_setup *settings = (video_playback_setup *)info->settings; EditList *editlist = info->editlist; int i, k; /* there should be something in the buffer */ if (!settings->save_list_len || !settings->save_list) { lavplay_msg(LAVPLAY_MSG_WARNING, info, "No frames in the buffer to paste"); return 0; } if (destination < 0 || destination >= editlist->video_frames) { lavplay_msg(LAVPLAY_MSG_WARNING, info, "Incorrect parameters for pasting frames"); return 0; } editlist->frame_list = realloc(editlist->frame_list, (editlist->video_frames+settings->save_list_len)*sizeof(long)); if (!editlist->frame_list) { lavplay_msg (LAVPLAY_MSG_ERROR, info, "Malloc error, you\'re probably out of memory"); lavplay_change_state(info, LAVPLAY_STATE_STOP); return 0; } k = settings->save_list_len; for (i=editlist->video_frames-1;i>=destination;i--) editlist->frame_list[i+k] = editlist->frame_list[i]; k = destination; for (i=0;isave_list_len;i++) { if (k<=settings->min_frame_num) settings->min_frame_num++; if (kmax_frame_num) settings->max_frame_num++; editlist->frame_list[k++] = settings->save_list[i]; } editlist->video_frames += settings->save_list_len; i = lavplay_increase_frame(info, 0); if (!info->continuous) return i; lavplay_msg(LAVPLAY_MSG_DEBUG, info, "Pasted %ld frames from buffer into position %ld in movie", settings->save_list_len, destination); return 1; } /****************************************************** * lavplay_edit_move() * move a number of frames to a different position * * return value: 1 on succes, 0 on error ******************************************************/ int lavplay_edit_move(lavplay_t *info, long start, long end, long destination) { /*video_playback_setup *settings = (video_playback_setup *)info->settings; */ EditList *editlist = info->editlist; long dest_real; if (destination >= editlist->video_frames || destination < 0 || start < 0 || end < 0 || start >= editlist->video_frames || end >= editlist->video_frames || end < start) { lavplay_msg(LAVPLAY_MSG_WARNING, info, "Incorrect parameters for moving frames"); return 0; } if (destination < start) dest_real = destination; else if (destination > end) dest_real = destination - (end - start + 1); else dest_real = start; if (!lavplay_edit_cut(info, start, end)) return 0; if (!lavplay_edit_paste(info, dest_real)) return 0; return 1; } /****************************************************** * lavplay_edit_addmovie() * add a number of frames from a new movie to a * certain position in the current movie * * return value: 1 on succes, 0 on error ******************************************************/ int lavplay_edit_addmovie(lavplay_t *info, char *movie, long start, long end, long destination) { video_playback_setup *settings = (video_playback_setup *)info->settings; EditList *editlist = info->editlist; int n, i; n = open_video_file(movie, editlist, info->preserve_pathnames); if (start < 0) { start = 0; end = editlist->num_frames[n] - 1; } if (end < 0 || start < 0 || start > end || start > editlist->num_frames[n] || end >= editlist->num_frames[n] || destination < 0 || destination >= editlist->video_frames) { lavplay_msg(LAVPLAY_MSG_WARNING, info, "Wrong parameters for adding a new movie"); return 0; } editlist->frame_list = (long *)realloc(editlist->frame_list, (editlist->video_frames + (end - start + 1)) * sizeof(long)); if (!editlist->frame_list) { lavplay_msg (LAVPLAY_MSG_ERROR, info, "Malloc error, you\'re probably out of memory"); lavplay_change_state(info, LAVPLAY_STATE_STOP); return 0; } if (destination <= settings->max_frame_num) settings->max_frame_num += (end - start + 1); if (destination < settings->min_frame_num) settings->min_frame_num += (end - start + 1); for (i=start;i<=end;i++) { editlist->frame_list[editlist->video_frames++] = editlist->frame_list[destination+i-start]; editlist->frame_list[destination+i-start] = EL_ENTRY(n, i); } lavplay_msg(LAVPLAY_MSG_DEBUG, info, "Added frames %ld-%ld from %s into position %ld in movie", start, end, movie, destination); return 1; } /****************************************************** * lavplay_edit_set_playable() * set the part of the movie that will actually * be played, start<0 means whole movie * * return value: 1 on succes, 0 on error ******************************************************/ int lavplay_edit_set_playable(lavplay_t *info, long start, long end) { video_playback_setup *settings = (video_playback_setup *)info->settings; EditList *editlist = info->editlist; int need_change_frame = 0; if (start < 0) { start = 0; end = editlist->video_frames - 1; } if (end < start || end >= editlist->video_frames || start >= editlist->video_frames) { lavplay_msg(LAVPLAY_MSG_WARNING, info, "Incorrect frame play range!"); return 0; } if (settings->current_frame_num < start || settings->current_frame_num > end) need_change_frame = 1; settings->min_frame_num = start; settings->max_frame_num = end; if (need_change_frame) { int res; res = lavplay_increase_frame(info, 0); if (!info->continuous) return res; } return 1; } /*** Control sound during video playback */ /****************************************************** * lavplay_toggle_audio() * mutes or unmutes audio (1 = on, 0 = off) * * return value: 1 on succes, 0 on error ******************************************************/ int lavplay_toggle_audio(lavplay_t *info, int audio) { video_playback_setup *settings = (video_playback_setup *)info->settings; EditList *editlist = info->editlist; if (!(info->audio && editlist->has_audio)) { lavplay_msg(LAVPLAY_MSG_WARNING, info, "Audio playback has not been enabled"); return 0; } settings->audio_mute = audio==0?1:0; lavplay_msg(LAVPLAY_MSG_DEBUG, info, "Audio playback was %s", audio==0?"muted":"unmuted"); return 1; } /*** Methods for saving the currently played movie to editlists or open new movies */ /****************************************************** * lavplay_save_selection() * save a certain range of frames to an editlist * * return value: 1 on succes, 0 on error ******************************************************/ int lavplay_save_selection(lavplay_t *info, char *filename, long start, long end) { /*video_playback_setup *settings = (video_playback_setup *)info->settings; */ EditList *editlist = info->editlist; if (write_edit_list(filename, start, end, editlist)) return 0; lavplay_msg(LAVPLAY_MSG_DEBUG, info, "Saved frames %ld-%ld to editlist %s", start, end, filename); return 1; } /****************************************************** * lavplay_save_all() * save the whole current movie to an editlist * * return value: 1 on succes, 0 on error ******************************************************/ int lavplay_save_all(lavplay_t *info, char *filename) { /*video_playback_setup *settings = (video_playback_setup *)info->settings; */ EditList *editlist = info->editlist; if (write_edit_list(filename, 0, editlist->video_frames - 1, editlist)) return 0; lavplay_msg(LAVPLAY_MSG_DEBUG, info, "Saved all frames to editlist %s", filename); return 1; } /****************************************************** * lavplay_open() * open a new (series of) movie * * return value: 1 on succes, 0 on error ******************************************************/ int lavplay_open(lavplay_t *info, char **files, int num_files) { video_playback_setup *settings = (video_playback_setup *)info->settings; EditList *editlist = info->editlist; EditList *new_eli = NULL; /* the new to-be-opened-editlist */ int i; if (num_files <= 0) { lavplay_msg(LAVPLAY_MSG_WARNING, info, "That's not a valid number of files"); return 0; } new_eli = (EditList *)malloc(sizeof(EditList)); if (!new_eli) { lavplay_msg (LAVPLAY_MSG_ERROR, NULL, "Malloc error, you\'re probably out of memory"); lavplay_change_state(info, LAVPLAY_STATE_STOP); return 0; } /* open the new movie(s) */ read_video_files(files, num_files, new_eli, info->preserve_pathnames); if (settings->state == LAVPLAY_STATE_STOP) { /* we're not running yet, yay! */ info->editlist = new_eli; free (editlist); } else if (editlist->video_width == new_eli->video_width && editlist->video_height == new_eli->video_height && editlist->video_inter == new_eli->video_inter && abs(editlist->video_fps - new_eli->video_fps) < 0.0000001 && editlist->has_audio == new_eli->has_audio && editlist->audio_rate == new_eli->audio_rate && editlist->audio_chans == new_eli->audio_chans && editlist->audio_bits == new_eli->audio_bits) { /* the movie-properties are the same - just open it */ info->editlist = new_eli; free(editlist); editlist = new_eli; settings->min_frame_num = 0; settings->max_frame_num = editlist->video_frames - 1; } else { /* okay, the properties are different, we could re-init but for now, let's just bail out */ /* TODO: a better thing */ lavplay_msg(LAVPLAY_MSG_WARNING, info, "Editlists are different"); free(new_eli); return 0; } /* if requested, invert field order */ if (info->exchange_fields) { switch (info->editlist->video_inter) { case Y4M_ILACE_BOTTOM_FIRST: info->editlist->video_inter = Y4M_ILACE_TOP_FIRST; break; case Y4M_ILACE_TOP_FIRST: info->editlist->video_inter = Y4M_ILACE_BOTTOM_FIRST; break; default: lavplay_msg(LAVPLAY_MSG_WARNING, info, "Input video is not interlaced - cannot invert field order"); break; } } /* if everything went well et all */ i = lavplay_increase_frame(info, 0); if (!info->continuous) return i; return 1; } /****************************************************** * lavplay_busy() * Wait until playback is finished ******************************************************/ void lavplay_busy(lavplay_t *info) { pthread_join( ((video_playback_setup*)(info->settings))->playback_thread, NULL ); } mjpegtools-2.1.0/configure0000755000175000017500000244751112217306404016135 0ustar glowwormglowworm#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for mjpegtools 2.1.0. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and $0: mjpeg-developer@lists.sourceforge.net about your $0: system, including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='mjpegtools' PACKAGE_TARNAME='mjpegtools' PACKAGE_VERSION='2.1.0' PACKAGE_STRING='mjpegtools 2.1.0' PACKAGE_BUGREPORT='mjpeg-developer@lists.sourceforge.net' PACKAGE_URL='' ac_unique_file="lavtools/lav_io.c" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS HAVE_V4L_OR_SDL_FALSE HAVE_V4L_OR_SDL_TRUE ALTIVEC_EXTRA_LIBS HAVE_ALTIVEC_FALSE HAVE_ALTIVEC_TRUE HAVE_PPCCPU_FALSE HAVE_PPCCPU_TRUE HAVE_X86CPU_FALSE HAVE_X86CPU_TRUE HAVE_ASM_MMX_FALSE HAVE_ASM_MMX_TRUE PROGRAM_NOPIC HAVE_SDLgfx_FALSE HAVE_SDLgfx_TRUE SDLgfx_LIBS HAVE_SDL_FALSE HAVE_SDL_TRUE SDL_LIBS SDL_CFLAGS HAVE_GTK_FALSE HAVE_GTK_TRUE GTK_LIBS GTK_CFLAGS HAVE_LIBXXF86DGA_FALSE HAVE_LIBXXF86DGA_TRUE V4LCONF_LIBS X_EXTRA_LIBS X_LIBS X_PRE_LIBS X_CFLAGS XMKMF LIBDV_LIBS LIBDV_CFLAGS HAVE_LIBPNG_FALSE HAVE_LIBPNG_TRUE LIBPNG_LIBS LIBPNG_CFLAGS HAVE_LIBQUICKTIME_FALSE HAVE_LIBQUICKTIME_TRUE LIBQUICKTIME_LIBS LIBQUICKTIME_CFLAGS PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG JPEG_CFLAGS JPEG_LIBS PTHREAD_CFLAGS PTHREAD_LIBS PTHREAD_CC acx_pthread_config HAVE_V4L_FALSE HAVE_V4L_TRUE EXTRA_LDFLAGS LIBM_LIBS LIBGETOPT_LIB am__fastdepCCAS_FALSE am__fastdepCCAS_TRUE CCASDEPMODE CCASFLAGS CCAS CXXCPP am__fastdepCXX_FALSE am__fastdepCXX_TRUE CXXDEPMODE ac_ct_CXX CXXFLAGS CXX OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB ac_ct_AR AR DLLTOOL OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP SED LIBTOOL EGREP GREP CPP am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC LT_STATIC LT_AGE LT_REVISION LT_CURRENT LT_RELEASE MAINT MAINTAINER_MODE_FALSE MAINTAINER_MODE_TRUE am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM host_os host_vendor host_cpu host build_os build_vendor build_cpu build target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_maintainer_mode enable_compile_warnings enable_warnings_as_errors enable_static_build enable_simd_accel with_extra_cflags with_libquicktime with_libdv with_libpng with_dga with_gtk with_libsdl with_sdlgfx enable_dependency_tracking enable_shared enable_static with_pic enable_fast_install with_gnu_ld with_sysroot enable_libtool_lock enable_largefile with_v4l with_x enable_assert ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP CXX CXXFLAGS CCC CXXCPP CCAS CCASFLAGS PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR LIBQUICKTIME_CFLAGS LIBQUICKTIME_LIBS LIBPNG_CFLAGS LIBPNG_LIBS LIBDV_CFLAGS LIBDV_LIBS XMKMF GTK_CFLAGS GTK_LIBS SDL_CFLAGS SDL_LIBS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures mjpegtools 2.1.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/mjpegtools] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names X features: --x-includes=DIR X include files are in DIR --x-libraries=DIR X library files are in DIR System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of mjpegtools 2.1.0:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer --enable-compile-warnings Turn on compiler warnings. --enable-warnings_as_errors Compiler warnings are errors. --enable-static-build Force static linkage instead of shared libraries (useful for profiling etc). --enable-simd-accel use SIMD multimedia instructions (MMX, AltiVec, etc.) if possible --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --disable-largefile omit support for large files --disable-assert Disable assertions (compile with NDEBUG). Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-extra-cflags=flags Options to be added to CFLAGS (optional) --without-libquicktime Do not use libquicktime. --without-libdv Do not use libdv. --without-libpng Do not use libpng. --without-dga Do not use dga. --without-gtk Do not use gtk. --without-libsdl Do not use libsdl. --without-sdlgfx Do not use sdlgfx. --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot=DIR Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --without-v4l Disable v4l1 API --with-x use the X Window System Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor CXX C++ compiler command CXXFLAGS C++ compiler flags CXXCPP C++ preprocessor CCAS assembler compiler command (defaults to CC) CCASFLAGS assembler compiler flags (defaults to CFLAGS) PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path LIBQUICKTIME_CFLAGS C compiler flags for LIBQUICKTIME, overriding pkg-config LIBQUICKTIME_LIBS linker flags for LIBQUICKTIME, overriding pkg-config LIBPNG_CFLAGS C compiler flags for LIBPNG, overriding pkg-config LIBPNG_LIBS linker flags for LIBPNG, overriding pkg-config LIBDV_CFLAGS C compiler flags for LIBDV, overriding pkg-config LIBDV_LIBS linker flags for LIBDV, overriding pkg-config XMKMF Path to xmkmf, Makefile generator for X Window System GTK_CFLAGS C compiler flags for GTK, overriding pkg-config GTK_LIBS linker flags for GTK, overriding pkg-config SDL_CFLAGS C compiler flags for SDL, overriding pkg-config SDL_LIBS linker flags for SDL, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF mjpegtools configure 2.1.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ---------------------------------------------------- ## ## Report this to mjpeg-developer@lists.sourceforge.net ## ## ---------------------------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_cxx_try_cpp LINENO # ------------------------ # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_cpp # ac_fn_cxx_try_link LINENO # ------------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_link cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by mjpegtools $as_me 2.1.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu MJPEG_MAJOR_VERSION=2 MJPEG_MINOR_VERSION=1 MJPEG_MICRO_VERSION=0 MJPEG_VERSION=$MJPEG_MAJOR_VERSION.$MJPEG_MINOR_VERSION.$MJPEG_MICRO_VERSION ac_config_headers="$ac_config_headers config.h" ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac am__api_version='1.12' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='mjpegtools' VERSION='2.1.0' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} mkdir_p="$MKDIR_P" # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then : enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval else USE_MAINTAINER_MODE=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 $as_echo "$USE_MAINTAINER_MODE" >&6; } if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else MAINTAINER_MODE_TRUE='#' MAINTAINER_MODE_FALSE= fi MAINT=$MAINTAINER_MODE_TRUE # libtool versioning LT_RELEASE=$MJPEG_MAJOR_VERSION.$MJPEG_MINOR_VERSION LT_CURRENT=$MJPEG_MICRO_VERSION LT_REVISION=$MJPEG_MICRO_VERSION LT_AGE=$MJPEG_MICRO_VERSION # Check whether --enable-compile-warnings was given. if test "${enable_compile_warnings+set}" = set; then : enableval=$enable_compile_warnings; fi # Check whether --enable-warnings_as_errors was given. if test "${enable_warnings_as_errors+set}" = set; then : enableval=$enable_warnings_as_errors; fi # Check whether --enable-static-build was given. if test "${enable_static_build+set}" = set; then : enableval=$enable_static_build; fi # Check whether --enable-simd-accel was given. if test "${enable_simd_accel+set}" = set; then : enableval=$enable_simd_accel; fi # Check whether --with-extra-cflags was given. if test "${with_extra_cflags+set}" = set; then : withval=$with_extra_cflags; fi # Check whether --with-libquicktime was given. if test "${with_libquicktime+set}" = set; then : withval=$with_libquicktime; else with_libquicktime=yes fi # Check whether --with-libdv was given. if test "${with_libdv+set}" = set; then : withval=$with_libdv; else with_libdv=yes fi # Check whether --with-libpng was given. if test "${with_libpng+set}" = set; then : withval=$with_libpng; else with_libpng=yes fi # Check whether --with-dga was given. if test "${with_dga+set}" = set; then : withval=$with_dga; else with_dga=yes fi # Check whether --with-gtk was given. if test "${with_gtk+set}" = set; then : withval=$with_gtk; else with_gtk=yes fi # Check whether --with-libsdl was given. if test "${with_libsdl+set}" = set; then : withval=$with_libsdl; else with_libsdl=yes fi # Check whether --with-sdlgfx was given. if test "${with_sdlgfx+set}" = set; then : withval=$with_sdlgfx; else with_sdlgfx=yes fi DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" if test "x$ac_cv_header_minix_config_h" = xyes; then : MINIX=yes else MINIX= fi if test "$MINIX" = yes; then $as_echo "#define _POSIX_SOURCE 1" >>confdefs.h $as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h $as_echo "#define _MINIX 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 $as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } if ${ac_cv_safe_to_define___extensions__+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # define __EXTENSIONS__ 1 $ac_includes_default int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_safe_to_define___extensions__=yes else ac_cv_safe_to_define___extensions__=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 $as_echo "$ac_cv_safe_to_define___extensions__" >&6; } test $ac_cv_safe_to_define___extensions__ = yes && $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h $as_echo "#define _ALL_SOURCE 1" >>confdefs.h $as_echo "#define _GNU_SOURCE 1" >>confdefs.h $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.2' macro_revision='1.3337' ltmain="$ac_aux_dir/ltmain.sh" # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case "$ECHO" in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 $as_echo "$xsi_shell" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 $as_echo_n "checking whether the shell understands \"+=\"... " >&6; } lt_shell_append=no ( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 $as_echo "$lt_shell_append" >&6; } if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test "$GCC" != yes; then reload_cmds=false fi ;; darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} : ${AR_FLAGS=cru} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 $as_echo "${with_sysroot}" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD="${LD-ld}_sol2" fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cru libconftest.a conftest.o" >&5 $AR cru libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[012]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done # Set options enable_dlopen=no enable_win32_dll=no # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=yes fi # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS="$lt_save_ifs" ;; esac else pic_mode=default fi test -z "$pic_mode" && pic_mode=default # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='${wl}--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' link_all_deplibs=yes ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi export_dynamic_flag_spec='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test "$lt_cv_ld_force_load" = "yes"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test x"$lt_cv_prog_compiler__b" = xyes; then archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test "$lt_cv_irix_exported_symbol" = yes; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='${wl}-z,text' allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='${wl}-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test "$ld_shlibs" = no && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([A-Za-z]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test "$hardcode_action" = relink || test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen="shl_load" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen="dlopen" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report which library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" ac_config_commands="$ac_config_commands libtool" # Only expand once: for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi # automake 1.9 could use AM_PROG_STDC but 1.10 became picky and needs CC_C_0 if test "x$CC" != xcc; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 $as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 $as_echo_n "checking whether cc understands -c and -o together... " >&6; } fi set dummy $CC; ac_cc=`$as_echo "$2" | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # We do the test twice because some compilers refuse to overwrite an # existing .o file with -o, though they will create one. ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -f conftest2.$ac_objext && { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then eval ac_cv_prog_cc_${ac_cc}_c_o=yes if test "x$CC" != xcc; then # Test first that cc exists at all. if { ac_try='cc -c conftest.$ac_ext >&5' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -f conftest2.$ac_objext && { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # cc works too. : else # cc exists but doesn't like -o. eval ac_cv_prog_cc_${ac_cc}_c_o=no fi fi fi else eval ac_cv_prog_cc_${ac_cc}_c_o=no fi rm -f core conftest* fi if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h fi # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o if test "$am_t" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi # AM_PROG_CC_STDC ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CXX" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CXX_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 $as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi func_stripname_cnf () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname_cnf if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 $as_echo_n "checking how to run the C++ preprocessor... " >&6; } if test -z "$CXXCPP"; then if ${ac_cv_prog_CXXCPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CXXCPP needs to be expanded for CXXCPP in "$CXX -E" "/lib/cpp" do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CXXCPP=$CXXCPP fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 $as_echo "$CXXCPP" >&6; } ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu else _lt_caught_CXX_error=yes fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu archive_cmds_need_lc_CXX=no allow_undefined_flag_CXX= always_export_symbols_CXX=no archive_expsym_cmds_CXX= compiler_needs_object_CXX=no export_dynamic_flag_spec_CXX= hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no hardcode_libdir_flag_spec_CXX= hardcode_libdir_separator_CXX= hardcode_minus_L_CXX=no hardcode_shlibpath_var_CXX=unsupported hardcode_automatic_CXX=no inherit_rpath_CXX=no module_cmds_CXX= module_expsym_cmds_CXX= link_all_deplibs_CXX=unknown old_archive_cmds_CXX=$old_archive_cmds reload_flag_CXX=$reload_flag reload_cmds_CXX=$reload_cmds no_undefined_flag_CXX= whole_archive_flag_spec_CXX= enable_shared_with_static_runtimes_CXX=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o objext_CXX=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC compiler_CXX=$CC for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' else lt_prog_compiler_no_builtin_flag_CXX= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_CXX= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } ld_shlibs_CXX=yes case $host_os in aix3*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_CXX='' hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes file_list_spec_CXX='${wl}-f,' if test "$GXX" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct_CXX=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_CXX=yes hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_libdir_separator_CXX= fi esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi export_dynamic_flag_spec_CXX='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. always_export_symbols_CXX=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag_CXX='-berok' # Determine the default libpath from the value encoded in an empty # executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath__CXX+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_CXX="-z nodefs" archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath__CXX+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_CXX=' ${wl}-bernotok' allow_undefined_flag_CXX=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_CXX='$convenience' fi archive_cmds_need_lc_CXX=yes # This is similar to how AIX traditionally builds its shared # libraries. archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_CXX=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs_CXX=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_CXX=' ' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=yes file_list_spec_CXX='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' enable_shared_with_static_runtimes_CXX=yes # Don't use ranlib old_postinstall_cmds_CXX='chmod 644 $oldlib' postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ func_to_tool_file "$lt_outputfile"~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_CXX='-L$libdir' export_dynamic_flag_spec_CXX='${wl}--export-all-symbols' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=no enable_shared_with_static_runtimes_CXX=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_CXX=no fi ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc_CXX=no hardcode_direct_CXX=no hardcode_automatic_CXX=yes hardcode_shlibpath_var_CXX=unsupported if test "$lt_cv_ld_force_load" = "yes"; then whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec_CXX='' fi link_all_deplibs_CXX=yes allow_undefined_flag_CXX="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds_CXX="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" if test "$lt_cv_apple_cc_single_mod" != "yes"; then archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi else ld_shlibs_CXX=no fi ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF ld_shlibs_CXX=no ;; freebsd-elf*) archive_cmds_need_lc_CXX=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes ;; gnu*) ;; haiku*) archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' link_all_deplibs_CXX=yes ;; hpux9*) hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_separator_CXX=: export_dynamic_flag_spec_CXX='${wl}-E' hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_separator_CXX=: case $host_cpu in hppa*64*|ia64*) ;; *) export_dynamic_flag_spec_CXX='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no ;; *) hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; interix[3-9]*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi link_all_deplibs_CXX=yes ;; esac hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: inherit_rpath_CXX=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac archive_cmds_need_lc_CXX=no hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [1-5].* | *pgcpp\ [1-5].*) prelink_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' old_archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' archive_expsym_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' hardcode_libdir_flag_spec_CXX='-R$libdir' whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object_CXX=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; m88k*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) ld_shlibs_CXX=yes ;; openbsd2*) # C++ shared libraries are fairly broken ld_shlibs_CXX=no ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no hardcode_direct_absolute_CXX=yes archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' export_dynamic_flag_spec_CXX='${wl}-E' whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else ld_shlibs_CXX=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx*) case $host in osf3*) allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' ;; *) allow_undefined_flag_CXX=' -expect_unresolved \*' archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' hardcode_libdir_flag_spec_CXX='-rpath $libdir' ;; esac hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) archive_cmds_CXX='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ archive_cmds_need_lc_CXX=yes no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_shlibpath_var_CXX=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs_CXX=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then no_undefined_flag_CXX=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag_CXX='${wl}-z,text' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag_CXX='${wl}-z,text' allow_undefined_flag_CXX='${wl}-z,nodefs' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='${wl}-R,$libdir' hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes export_dynamic_flag_spec_CXX='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ '"$old_archive_cmds_CXX" reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ '"$reload_cmds_CXX" ;; *) archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test "$ld_shlibs_CXX" = no && can_build_shared=no GCC_CXX="$GXX" LD_CXX="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... # Dependencies to place before and after the object being linked: predep_objects_CXX= postdep_objects_CXX= predeps_CXX= postdeps_CXX= compiler_lib_search_path_CXX= cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case ${prev}${p} in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" || test $p = "-R"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test "$pre_test_object_deps_done" = no; then case ${prev} in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$compiler_lib_search_path_CXX"; then compiler_lib_search_path_CXX="${prev}${p}" else compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$postdeps_CXX"; then postdeps_CXX="${prev}${p}" else postdeps_CXX="${postdeps_CXX} ${prev}${p}" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$predep_objects_CXX"; then predep_objects_CXX="$p" else predep_objects_CXX="$predep_objects_CXX $p" fi else if test -z "$postdep_objects_CXX"; then postdep_objects_CXX="$p" else postdep_objects_CXX="$postdep_objects_CXX $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling CXX test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken case $host_os in interix[3-9]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. predep_objects_CXX= postdep_objects_CXX= postdeps_CXX= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then postdeps_CXX='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then postdeps_CXX='-library=Cstd -library=Crun' fi ;; esac ;; esac case " $postdeps_CXX " in *" -lc "*) archive_cmds_need_lc_CXX=no ;; esac compiler_lib_search_dirs_CXX= if test -n "${compiler_lib_search_path_CXX}"; then compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi lt_prog_compiler_wl_CXX= lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX= # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic_CXX='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_CXX='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all lt_prog_compiler_pic_CXX= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static_CXX= ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_CXX=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac else case $host_os in aix[4-9]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' else lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; dgux*) case $cc_basename in ec++*) lt_prog_compiler_pic_CXX='-KPIC' ;; ghcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then lt_prog_compiler_pic_CXX='+Z' fi ;; aCC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_CXX='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # KAI C++ Compiler lt_prog_compiler_wl_CXX='--backend -Wl,' lt_prog_compiler_pic_CXX='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64 which still supported -KPIC. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fPIC' lt_prog_compiler_static_CXX='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fpic' lt_prog_compiler_static_CXX='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) # IBM XL 8.0, 9.0 on PPC and BlueGene lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-qpic' lt_prog_compiler_static_CXX='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) lt_prog_compiler_pic_CXX='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) lt_prog_compiler_wl_CXX='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 lt_prog_compiler_pic_CXX='-pic' ;; cxx*) # Digital/Compaq C++ lt_prog_compiler_wl_CXX='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x lt_prog_compiler_pic_CXX='-pic' lt_prog_compiler_static_CXX='-Bstatic' ;; lcc*) # Lucid lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 lt_prog_compiler_pic_CXX='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) lt_prog_compiler_can_build_shared_CXX=no ;; esac fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_CXX= ;; *) lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 $as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; } lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works_CXX=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works_CXX=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } if test x"$lt_cv_prog_compiler_pic_works_CXX" = xyes; then case $lt_prog_compiler_pic_CXX in "" | " "*) ;; *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; esac else lt_prog_compiler_pic_CXX= lt_prog_compiler_can_build_shared_CXX=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works_CXX=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works_CXX=yes fi else lt_cv_prog_compiler_static_works_CXX=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } if test x"$lt_cv_prog_compiler_static_works_CXX" = xyes; then : else lt_prog_compiler_static_CXX= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' case $host_os in aix[4-9]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global defined # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) export_symbols_cmds_CXX="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' ;; esac ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test "$ld_shlibs_CXX" = no && can_build_shared=no with_gnu_ld_CXX=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_CXX" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_CXX=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_CXX in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_CXX pic_flag=$lt_prog_compiler_pic_CXX compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_CXX allow_undefined_flag_CXX= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc_CXX=no else lt_cv_archive_cmds_need_lc_CXX=yes fi allow_undefined_flag_CXX=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 $as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; } archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action_CXX= if test -n "$hardcode_libdir_flag_spec_CXX" || test -n "$runpath_var_CXX" || test "X$hardcode_automatic_CXX" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct_CXX" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" != no && test "$hardcode_minus_L_CXX" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_CXX=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_CXX=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_CXX=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 $as_echo "$hardcode_action_CXX" >&6; } if test "$hardcode_action_CXX" = relink || test "$inherit_rpath_CXX" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test "$_lt_caught_CXX_error" != yes ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 $as_echo_n "checking whether byte ordering is bigendian... " >&6; } if ${ac_cv_c_bigendian+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes; then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; int main () { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Are we little or big endian? From Harbison&Steele. */ union { long int l; char c[sizeof (long int)]; } u; u.l = 1; return u.c[sizeof (long int) - 1] == 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_bigendian=no else ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 $as_echo "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __cplusplus /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this sort of thing. */ char tx; char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; } bx; struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 $as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac # Check whether --enable-largefile was given. if test "${enable_largefile+set}" = set; then : enableval=$enable_largefile; fi if test "$enable_largefile" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 $as_echo_n "checking for special C compiler options needed for large files... " >&6; } if ${ac_cv_sys_largefile_CC+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_sys_largefile_CC=no if test "$GCC" != yes; then ac_save_CC=$CC while :; do # IRIX 6.2 and later do not support large files by default, # so use the C compiler's -n32 option if that helps. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : break fi rm -f core conftest.err conftest.$ac_objext CC="$CC -n32" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_largefile_CC=' -n32'; break fi rm -f core conftest.err conftest.$ac_objext break done CC=$ac_save_CC rm -f conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 $as_echo "$ac_cv_sys_largefile_CC" >&6; } if test "$ac_cv_sys_largefile_CC" != no; then CC=$CC$ac_cv_sys_largefile_CC fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 $as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } if ${ac_cv_sys_file_offset_bits+:} false; then : $as_echo_n "(cached) " >&6 else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_file_offset_bits=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _FILE_OFFSET_BITS 64 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_file_offset_bits=64; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_file_offset_bits=unknown break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 $as_echo "$ac_cv_sys_file_offset_bits" >&6; } case $ac_cv_sys_file_offset_bits in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits _ACEOF ;; esac rm -rf conftest* if test $ac_cv_sys_file_offset_bits = unknown; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 $as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } if ${ac_cv_sys_large_files+:} false; then : $as_echo_n "(cached) " >&6 else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_large_files=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _LARGE_FILES 1 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_large_files=1; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_large_files=unknown break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 $as_echo "$ac_cv_sys_large_files" >&6; } case $ac_cv_sys_large_files in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _LARGE_FILES $ac_cv_sys_large_files _ACEOF ;; esac rm -rf conftest* fi fi # By default we simply use the C compiler to build assembly code. test "${CCAS+set}" = set || CCAS=$CC test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS depcc="$CCAS" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CCAS_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CCAS_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CCAS_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CCAS_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CCAS_dependencies_compiler_type" >&5 $as_echo "$am_cv_CCAS_dependencies_compiler_type" >&6; } CCASDEPMODE=depmode=$am_cv_CCAS_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CCAS_dependencies_compiler_type" = gcc3; then am__fastdepCCAS_TRUE= am__fastdepCCAS_FALSE='#' else am__fastdepCCAS_TRUE='#' am__fastdepCCAS_FALSE= fi if test x"$with_extra_cflags" != "x"; then CFLAGS="$CFLAGS $with_extra_cflags" CXXFLAGS="$CXXFLAGS $with_extra_cflags" CCASFLAGS="$CCASFLAGS $with_extra_cflags" fi for ac_header in stdint.h inttypes.h sys/types.h getopt.h malloc.h sys/soundcard.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done #maddog: check for math lib, and add it to LIBS (needed for fmax, lround...) #maddog: (How does this interact with cpml stuff below???????) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sin in -lm" >&5 $as_echo_n "checking for sin in -lm... " >&6; } if ${ac_cv_lib_m_sin+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char sin (); int main () { return sin (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_m_sin=yes else ac_cv_lib_m_sin=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_sin" >&5 $as_echo "$ac_cv_lib_m_sin" >&6; } if test "x$ac_cv_lib_m_sin" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBM 1 _ACEOF LIBS="-lm $LIBS" fi for ac_func in posix_memalign memalign fmax fmin lround do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_func "$LINENO" "getopt_long" "ac_cv_func_getopt_long" if test "x$ac_cv_func_getopt_long" = xyes; then : $as_echo "#define HAVE_GETOPT_LONG 1" >>confdefs.h else # FreeBSD and BSD/OS have a gnugetopt library for this: { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getopt_long in -lgnugetopt" >&5 $as_echo_n "checking for getopt_long in -lgnugetopt... " >&6; } if ${ac_cv_lib_gnugetopt_getopt_long+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgnugetopt $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char getopt_long (); int main () { return getopt_long (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gnugetopt_getopt_long=yes else ac_cv_lib_gnugetopt_getopt_long=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gnugetopt_getopt_long" >&5 $as_echo "$ac_cv_lib_gnugetopt_getopt_long" >&6; } if test "x$ac_cv_lib_gnugetopt_getopt_long" = xyes; then : $as_echo "#define HAVE_GETOPT_LONG 1" >>confdefs.h LIBGETOPT_LIB="-lgnugetopt" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5 $as_echo_n "checking return type of signal handlers... " >&6; } if ${ac_cv_type_signal+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { return *(signal (0, 0)) (0) == 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_type_signal=int else ac_cv_type_signal=void fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5 $as_echo "$ac_cv_type_signal" >&6; } cat >>confdefs.h <<_ACEOF #define RETSIGTYPE $ac_cv_type_signal _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: The host is $host $host_cpu $host_vendor $host_os ." >&5 $as_echo "$as_me: The host is $host $host_cpu $host_vendor $host_os ." >&6;} LIBM_LIBS="-lm " { $as_echo "$as_me:${as_lineno-$LINENO}: checking for alpha architecture" >&5 $as_echo_n "checking for alpha architecture... " >&6; } case $host in alpha*-*-linux-*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for asin in -lcpml" >&5 $as_echo_n "checking for asin in -lcpml... " >&6; } if ${ac_cv_lib_cpml_asin+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcpml $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char asin (); int main () { return asin (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_cpml_asin=yes else ac_cv_lib_cpml_asin=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cpml_asin" >&5 $as_echo "$ac_cv_lib_cpml_asin" >&6; } if test "x$ac_cv_lib_cpml_asin" = xyes; then : LIBM_LIBS="-lcpml" have_cpml=true fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac case $host in *-apple-darwin*) CFLAGS="$CFLAGS -no-cpp-precomp" ;; *-unknown-netbsdelf2.*) LIBS="-lossaudio" ;; *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) EXTRA_LDFLAGS="-no-undefined" ;; esac have_video4linux=false # Check whether --with-v4l was given. if test "${with_v4l+set}" = set; then : withval=$with_v4l; fi if test "x$with_v4l" != "xno"; then : case $host in *-*-linux*) ac_fn_c_check_header_mongrel "$LINENO" "linux/videodev.h" "ac_cv_header_linux_videodev_h" "$ac_includes_default" if test "x$ac_cv_header_linux_videodev_h" = xyes; then : have_video4linux=true $as_echo "#define HAVE_V4L 1" >>confdefs.h fi ;; esac fi if test "x$have_video4linux" != "xtrue" && test "x$with_v4l" != "xno"; then : have_video4linux=false { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: videodev.h not found - please install the linux kernel headers programms needing v4l disabled" >&5 $as_echo "$as_me: WARNING: videodev.h not found - please install the linux kernel headers programms needing v4l disabled" >&2;} fi if test x$have_video4linux = xtrue; then HAVE_V4L_TRUE= HAVE_V4L_FALSE='#' else HAVE_V4L_TRUE='#' HAVE_V4L_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu acx_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5 $as_echo_n "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_join (); int main () { return pthread_join (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : acx_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5 $as_echo "$acx_pthread_ok" >&6; } if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthread or # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 $as_echo_n "checking whether pthreads work without any flags... " >&6; } ;; -*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $flag" >&5 $as_echo_n "checking whether pthreads work with $flag... " >&6; } PTHREAD_CFLAGS="$flag" ;; pthread-config) # Extract the first word of "pthread-config", so it can be a program name with args. set dummy pthread-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_acx_pthread_config+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$acx_pthread_config"; then ac_cv_prog_acx_pthread_config="$acx_pthread_config" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_acx_pthread_config="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_acx_pthread_config" && ac_cv_prog_acx_pthread_config="no" fi fi acx_pthread_config=$ac_cv_prog_acx_pthread_config if test -n "$acx_pthread_config"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_config" >&5 $as_echo "$acx_pthread_config" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"$acx_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$flag" >&5 $as_echo_n "checking for the pthreads library -l$flag... " >&6; } PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : acx_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5 $as_echo "$acx_pthread_ok" >&6; } if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: threads are created detached by default # and the JOINABLE attribute has a nonstandard name (UNDETACHED). { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 $as_echo_n "checking for joinable pthread attribute... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int attr=PTHREAD_CREATE_JOINABLE; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ok=PTHREAD_CREATE_JOINABLE else ok=unknown fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test x"$ok" = xunknown; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int attr=PTHREAD_CREATE_UNDETACHED; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ok=PTHREAD_CREATE_UNDETACHED else ok=unknown fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then $as_echo "#define PTHREAD_CREATE_JOINABLE \$ok" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ok}" >&5 $as_echo "${ok}" >&6; } if test x"$ok" = xunknown; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: we do not know how to create joinable pthreads" >&5 $as_echo "$as_me: WARNING: we do not know how to create joinable pthreads" >&2;} fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if more special flags are required for pthreads" >&5 $as_echo_n "checking if more special flags are required for pthreads... " >&6; } flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${flag}" >&5 $as_echo "${flag}" >&6; } if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with cc_r # Extract the first word of "cc_r", so it can be a program name with args. set dummy cc_r; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_PTHREAD_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$PTHREAD_CC"; then ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_PTHREAD_CC="cc_r" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_PTHREAD_CC" && ac_cv_prog_PTHREAD_CC="${CC}" fi fi PTHREAD_CC=$ac_cv_prog_PTHREAD_CC if test -n "$PTHREAD_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 $as_echo "$PTHREAD_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else PTHREAD_CC="$CC" fi # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then $as_echo "#define HAVE_PTHREAD 1" >>confdefs.h : else acx_pthread_ok=no fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CFLAGS="$CFLAGS $PTHREAD_CFLAGS" CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS" CC="$PTHREAD_CC" oldLIBS="$LIBS" LIBS="$LIBS $PTHREAD_LIBS" ac_fn_c_check_func "$LINENO" "pthread_attr_getstacksize" "ac_cv_func_pthread_attr_getstacksize" if test "x$ac_cv_func_pthread_attr_getstacksize" = xyes; then : $as_echo "#define HAVE_PTHREADSTACKSIZE 1" >>confdefs.h fi LIBS="$oldLIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jpeg_start_compress in -ljpeg" >&5 $as_echo_n "checking for jpeg_start_compress in -ljpeg... " >&6; } if ${ac_cv_lib_jpeg_jpeg_start_compress+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ljpeg $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char jpeg_start_compress (); int main () { return jpeg_start_compress (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_jpeg_jpeg_start_compress=yes else ac_cv_lib_jpeg_jpeg_start_compress=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jpeg_jpeg_start_compress" >&5 $as_echo "$ac_cv_lib_jpeg_jpeg_start_compress" >&6; } if test "x$ac_cv_lib_jpeg_jpeg_start_compress" = xyes; then : JPEG_LIBS="-ljpeg" JPEG_CFLAGS="" have_libjpeg=true fi if test x$have_libjpeg != "xtrue"; then as_fn_error $? "JPEG 6b library missing - Go to http://www.ijg.org/" "$LINENO" 5 fi if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 $as_echo "$ac_pt_PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 $as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } PKG_CONFIG="" fi fi have_libquicktime=false if test x$with_libquicktime != xno ; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBQUICKTIME" >&5 $as_echo_n "checking for LIBQUICKTIME... " >&6; } if test -n "$LIBQUICKTIME_CFLAGS"; then pkg_cv_LIBQUICKTIME_CFLAGS="$LIBQUICKTIME_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libquicktime > 0.9.7\""; } >&5 ($PKG_CONFIG --exists --print-errors "libquicktime > 0.9.7") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBQUICKTIME_CFLAGS=`$PKG_CONFIG --cflags "libquicktime > 0.9.7" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBQUICKTIME_LIBS"; then pkg_cv_LIBQUICKTIME_LIBS="$LIBQUICKTIME_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libquicktime > 0.9.7\""; } >&5 ($PKG_CONFIG --exists --print-errors "libquicktime > 0.9.7") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBQUICKTIME_LIBS=`$PKG_CONFIG --libs "libquicktime > 0.9.7" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBQUICKTIME_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libquicktime > 0.9.7" 2>&1` else LIBQUICKTIME_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libquicktime > 0.9.7" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBQUICKTIME_PKG_ERRORS" >&5 have_libquicktime=false elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_libquicktime=false else LIBQUICKTIME_CFLAGS=$pkg_cv_LIBQUICKTIME_CFLAGS LIBQUICKTIME_LIBS=$pkg_cv_LIBQUICKTIME_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } have_libquicktime=true $as_echo "#define HAVE_LIBQUICKTIME 1" >>confdefs.h fi fi if test x$have_libquicktime = xtrue; then HAVE_LIBQUICKTIME_TRUE= HAVE_LIBQUICKTIME_FALSE='#' else HAVE_LIBQUICKTIME_TRUE='#' HAVE_LIBQUICKTIME_FALSE= fi have_libpng=false if test x$with_libpng != xno ; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBPNG" >&5 $as_echo_n "checking for LIBPNG... " >&6; } if test -n "$LIBPNG_CFLAGS"; then pkg_cv_LIBPNG_CFLAGS="$LIBPNG_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpng\""; } >&5 ($PKG_CONFIG --exists --print-errors "libpng") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBPNG_CFLAGS=`$PKG_CONFIG --cflags "libpng" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBPNG_LIBS"; then pkg_cv_LIBPNG_LIBS="$LIBPNG_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpng\""; } >&5 ($PKG_CONFIG --exists --print-errors "libpng") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBPNG_LIBS=`$PKG_CONFIG --libs "libpng" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBPNG_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libpng" 2>&1` else LIBPNG_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libpng" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBPNG_PKG_ERRORS" >&5 have_libpng=false elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_libpng=false else LIBPNG_CFLAGS=$pkg_cv_LIBPNG_CFLAGS LIBPNG_LIBS=$pkg_cv_LIBPNG_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } have_libpng=true fi if test x$have_libpng = xfalse ; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBPNG" >&5 $as_echo_n "checking for LIBPNG... " >&6; } if test -n "$LIBPNG_CFLAGS"; then pkg_cv_LIBPNG_CFLAGS="$LIBPNG_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpng12\""; } >&5 ($PKG_CONFIG --exists --print-errors "libpng12") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBPNG_CFLAGS=`$PKG_CONFIG --cflags "libpng12" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBPNG_LIBS"; then pkg_cv_LIBPNG_LIBS="$LIBPNG_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpng12\""; } >&5 ($PKG_CONFIG --exists --print-errors "libpng12") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBPNG_LIBS=`$PKG_CONFIG --libs "libpng12" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBPNG_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libpng12" 2>&1` else LIBPNG_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libpng12" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBPNG_PKG_ERRORS" >&5 have_libpng=false elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_libpng=false else LIBPNG_CFLAGS=$pkg_cv_LIBPNG_CFLAGS LIBPNG_LIBS=$pkg_cv_LIBPNG_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } have_libpng=true fi fi fi if test x$have_libpng = xtrue; then HAVE_LIBPNG_TRUE= HAVE_LIBPNG_FALSE='#' else HAVE_LIBPNG_TRUE='#' HAVE_LIBPNG_FALSE= fi have_libdv=false if test x$with_libdv != xno ; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBDV" >&5 $as_echo_n "checking for LIBDV... " >&6; } if test -n "$LIBDV_CFLAGS"; then pkg_cv_LIBDV_CFLAGS="$LIBDV_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libdv >= 0.9\""; } >&5 ($PKG_CONFIG --exists --print-errors "libdv >= 0.9") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBDV_CFLAGS=`$PKG_CONFIG --cflags "libdv >= 0.9" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBDV_LIBS"; then pkg_cv_LIBDV_LIBS="$LIBDV_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libdv >= 0.9\""; } >&5 ($PKG_CONFIG --exists --print-errors "libdv >= 0.9") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBDV_LIBS=`$PKG_CONFIG --libs "libdv >= 0.9" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBDV_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libdv >= 0.9" 2>&1` else LIBDV_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libdv >= 0.9" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBDV_PKG_ERRORS" >&5 have_libdv=false elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_libdv=false else LIBDV_CFLAGS=$pkg_cv_LIBDV_CFLAGS LIBDV_LIBS=$pkg_cv_LIBDV_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } have_libdv=true $as_echo "#define HAVE_LIBDV 1" >>confdefs.h fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X" >&5 $as_echo_n "checking for X... " >&6; } # Check whether --with-x was given. if test "${with_x+set}" = set; then : withval=$with_x; fi # $have_x is `yes', `no', `disabled', or empty when we do not yet know. if test "x$with_x" = xno; then # The user explicitly disabled X. have_x=disabled else case $x_includes,$x_libraries in #( *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #( *,NONE | NONE,*) if ${ac_cv_have_x+:} false; then : $as_echo_n "(cached) " >&6 else # One or both of the vars are not set, and there is no cached value. ac_x_includes=no ac_x_libraries=no rm -f -r conftest.dir if mkdir conftest.dir; then cd conftest.dir cat >Imakefile <<'_ACEOF' incroot: @echo incroot='${INCROOT}' usrlibdir: @echo usrlibdir='${USRLIBDIR}' libdir: @echo libdir='${LIBDIR}' _ACEOF if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. for ac_var in incroot usrlibdir libdir; do eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" done # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. for ac_extension in a so sl dylib la dll; do if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && test -f "$ac_im_libdir/libX11.$ac_extension"; then ac_im_usrlibdir=$ac_im_libdir; break fi done # Screen out bogus values from the imake configuration. They are # bogus both because they are the default anyway, and because # using them would break gcc on systems where it needs fixed includes. case $ac_im_incroot in /usr/include) ac_x_includes= ;; *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; esac case $ac_im_usrlibdir in /usr/lib | /usr/lib64 | /lib | /lib64) ;; *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; esac fi cd .. rm -f -r conftest.dir fi # Standard set of common directories for X headers. # Check X11 before X11Rn because it is often a symlink to the current release. ac_x_header_dirs=' /usr/X11/include /usr/X11R7/include /usr/X11R6/include /usr/X11R5/include /usr/X11R4/include /usr/include/X11 /usr/include/X11R7 /usr/include/X11R6 /usr/include/X11R5 /usr/include/X11R4 /usr/local/X11/include /usr/local/X11R7/include /usr/local/X11R6/include /usr/local/X11R5/include /usr/local/X11R4/include /usr/local/include/X11 /usr/local/include/X11R7 /usr/local/include/X11R6 /usr/local/include/X11R5 /usr/local/include/X11R4 /usr/X386/include /usr/x386/include /usr/XFree86/include/X11 /usr/include /usr/local/include /usr/unsupported/include /usr/athena/include /usr/local/x11r5/include /usr/lpp/Xamples/include /usr/openwin/include /usr/openwin/share/include' if test "$ac_x_includes" = no; then # Guess where to find include files, by looking for Xlib.h. # First, try using that file with no special directory specified. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # We can compile using X headers with no special include directory. ac_x_includes= else for ac_dir in $ac_x_header_dirs; do if test -r "$ac_dir/X11/Xlib.h"; then ac_x_includes=$ac_dir break fi done fi rm -f conftest.err conftest.i conftest.$ac_ext fi # $ac_x_includes = no if test "$ac_x_libraries" = no; then # Check for the libraries. # See if we find them without any special options. # Don't add to $LIBS permanently. ac_save_LIBS=$LIBS LIBS="-lX11 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { XrmInitialize () ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : LIBS=$ac_save_LIBS # We can link X programs with no special library path. ac_x_libraries= else LIBS=$ac_save_LIBS for ac_dir in `$as_echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` do # Don't even attempt the hair of trying to link an X program! for ac_extension in a so sl dylib la dll; do if test -r "$ac_dir/libX11.$ac_extension"; then ac_x_libraries=$ac_dir break 2 fi done done fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi # $ac_x_libraries = no case $ac_x_includes,$ac_x_libraries in #( no,* | *,no | *\'*) # Didn't find X, or a directory has "'" in its name. ac_cv_have_x="have_x=no";; #( *) # Record where we found X for the cache. ac_cv_have_x="have_x=yes\ ac_x_includes='$ac_x_includes'\ ac_x_libraries='$ac_x_libraries'" esac fi ;; #( *) have_x=yes;; esac eval "$ac_cv_have_x" fi # $with_x != no if test "$have_x" != yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_x" >&5 $as_echo "$have_x" >&6; } no_x=yes else # If each of the values was on the command line, it overrides each guess. test "x$x_includes" = xNONE && x_includes=$ac_x_includes test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries # Update the cache value to reflect the command line values. ac_cv_have_x="have_x=yes\ ac_x_includes='$x_includes'\ ac_x_libraries='$x_libraries'" { $as_echo "$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes" >&5 $as_echo "libraries $x_libraries, headers $x_includes" >&6; } fi if test "$no_x" = yes; then # Not all programs may use this symbol, but it does not hurt to define it. $as_echo "#define X_DISPLAY_MISSING 1" >>confdefs.h X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= else if test -n "$x_includes"; then X_CFLAGS="$X_CFLAGS -I$x_includes" fi # It would also be nice to do this for all -L options, not just this one. if test -n "$x_libraries"; then X_LIBS="$X_LIBS -L$x_libraries" # For Solaris; some versions of Sun CC require a space after -R and # others require no space. Words are not sufficient . . . . { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -R must be followed by a space" >&5 $as_echo_n "checking whether -R must be followed by a space... " >&6; } ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries" ac_xsave_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } X_LIBS="$X_LIBS -R$x_libraries" else LIBS="$ac_xsave_LIBS -R $x_libraries" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } X_LIBS="$X_LIBS -R $x_libraries" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: neither works" >&5 $as_echo "neither works" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_c_werror_flag=$ac_xsave_c_werror_flag LIBS=$ac_xsave_LIBS fi # Check for system-dependent libraries X programs must link with. # Do this before checking for the system-independent R6 libraries # (-lICE), since we may need -lsocket or whatever for X linking. if test "$ISC" = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" else # Martyn Johnson says this is needed for Ultrix, if the X # libraries were built with DECnet support. And Karl Berry says # the Alpha needs dnet_stub (dnet does not exist). ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char XOpenDisplay (); int main () { return XOpenDisplay (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet" >&5 $as_echo_n "checking for dnet_ntoa in -ldnet... " >&6; } if ${ac_cv_lib_dnet_dnet_ntoa+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldnet $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dnet_ntoa (); int main () { return dnet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dnet_dnet_ntoa=yes else ac_cv_lib_dnet_dnet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 $as_echo "$ac_cv_lib_dnet_dnet_ntoa" >&6; } if test "x$ac_cv_lib_dnet_dnet_ntoa" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" fi if test $ac_cv_lib_dnet_dnet_ntoa = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet_stub" >&5 $as_echo_n "checking for dnet_ntoa in -ldnet_stub... " >&6; } if ${ac_cv_lib_dnet_stub_dnet_ntoa+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldnet_stub $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dnet_ntoa (); int main () { return dnet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dnet_stub_dnet_ntoa=yes else ac_cv_lib_dnet_stub_dnet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 $as_echo "$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; } if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" fi fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$ac_xsave_LIBS" # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, # to get the SysV transport functions. # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4) # needs -lnsl. # The nsl library prevents programs from opening the X display # on Irix 5.2, according to T.E. Dickey. # The functions gethostbyname, getservbyname, and inet_addr are # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" if test "x$ac_cv_func_gethostbyname" = xyes; then : fi if test $ac_cv_func_gethostbyname = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 $as_echo_n "checking for gethostbyname in -lnsl... " >&6; } if ${ac_cv_lib_nsl_gethostbyname+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_nsl_gethostbyname=yes else ac_cv_lib_nsl_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5 $as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; } if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" fi if test $ac_cv_lib_nsl_gethostbyname = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lbsd" >&5 $as_echo_n "checking for gethostbyname in -lbsd... " >&6; } if ${ac_cv_lib_bsd_gethostbyname+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbsd $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_bsd_gethostbyname=yes else ac_cv_lib_bsd_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_gethostbyname" >&5 $as_echo "$ac_cv_lib_bsd_gethostbyname" >&6; } if test "x$ac_cv_lib_bsd_gethostbyname" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" fi fi fi # lieder@skyler.mavd.honeywell.com says without -lsocket, # socket/setsockopt and other routines are undefined under SCO ODT # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary # on later versions), says Simon Leinen: it contains gethostby* # variants that don't use the name server (or something). -lsocket # must be given before -lnsl if both are needed. We assume that # if connect needs -lnsl, so does gethostbyname. ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect" if test "x$ac_cv_func_connect" = xyes; then : fi if test $ac_cv_func_connect = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for connect in -lsocket" >&5 $as_echo_n "checking for connect in -lsocket... " >&6; } if ${ac_cv_lib_socket_connect+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char connect (); int main () { return connect (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_connect=yes else ac_cv_lib_socket_connect=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_connect" >&5 $as_echo "$ac_cv_lib_socket_connect" >&6; } if test "x$ac_cv_lib_socket_connect" = xyes; then : X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" fi fi # Guillermo Gomez says -lposix is necessary on A/UX. ac_fn_c_check_func "$LINENO" "remove" "ac_cv_func_remove" if test "x$ac_cv_func_remove" = xyes; then : fi if test $ac_cv_func_remove = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for remove in -lposix" >&5 $as_echo_n "checking for remove in -lposix... " >&6; } if ${ac_cv_lib_posix_remove+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lposix $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char remove (); int main () { return remove (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_posix_remove=yes else ac_cv_lib_posix_remove=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_posix_remove" >&5 $as_echo "$ac_cv_lib_posix_remove" >&6; } if test "x$ac_cv_lib_posix_remove" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" fi fi # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. ac_fn_c_check_func "$LINENO" "shmat" "ac_cv_func_shmat" if test "x$ac_cv_func_shmat" = xyes; then : fi if test $ac_cv_func_shmat = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shmat in -lipc" >&5 $as_echo_n "checking for shmat in -lipc... " >&6; } if ${ac_cv_lib_ipc_shmat+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lipc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shmat (); int main () { return shmat (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ipc_shmat=yes else ac_cv_lib_ipc_shmat=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ipc_shmat" >&5 $as_echo "$ac_cv_lib_ipc_shmat" >&6; } if test "x$ac_cv_lib_ipc_shmat" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" fi fi fi # Check for libraries that X11R6 Xt/Xaw programs need. ac_save_LDFLAGS=$LDFLAGS test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to # check for ICE first), but we must link in the order -lSM -lICE or # we get undefined symbols. So assume we have SM if we have ICE. # These have to be linked with before -lX11, unlike the other # libraries we check for below, so use a different variable. # John Interrante, Karl Berry { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IceConnectionNumber in -lICE" >&5 $as_echo_n "checking for IceConnectionNumber in -lICE... " >&6; } if ${ac_cv_lib_ICE_IceConnectionNumber+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lICE $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char IceConnectionNumber (); int main () { return IceConnectionNumber (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ICE_IceConnectionNumber=yes else ac_cv_lib_ICE_IceConnectionNumber=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 $as_echo "$ac_cv_lib_ICE_IceConnectionNumber" >&6; } if test "x$ac_cv_lib_ICE_IceConnectionNumber" = xyes; then : X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" fi LDFLAGS=$ac_save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __progname" >&5 $as_echo_n "checking for __progname... " >&6; } if ${mjt_cv_extern___progname+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { extern char *__progname; puts(__progname); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : mjt_cv_extern___progname=yes else mjt_cv_extern___progname=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $mjt_cv_extern___progname" >&5 $as_echo "$mjt_cv_extern___progname" >&6; } if test x$mjt_cv_extern___progname = xyes ; then $as_echo "#define HAVE___PROGNAME 1" >>confdefs.h fi have_dga=false if test x$with_dga != xno ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XF86DGAQueryExtension in -lXxf86dga" >&5 $as_echo_n "checking for XF86DGAQueryExtension in -lXxf86dga... " >&6; } if ${ac_cv_lib_Xxf86dga_XF86DGAQueryExtension+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lXxf86dga $X_LIBS $X_PRE_LIBS -lXext $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char XF86DGAQueryExtension (); int main () { return XF86DGAQueryExtension (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_Xxf86dga_XF86DGAQueryExtension=yes else ac_cv_lib_Xxf86dga_XF86DGAQueryExtension=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xxf86dga_XF86DGAQueryExtension" >&5 $as_echo "$ac_cv_lib_Xxf86dga_XF86DGAQueryExtension" >&6; } if test "x$ac_cv_lib_Xxf86dga_XF86DGAQueryExtension" = xyes; then : V4LCONF_LIBS="$X_LIBS -lXxf86dga" have_dga="true" $as_echo "#define HAVE_LIBXXF86DGA 1" >>confdefs.h else have_dga="false" fi fi if test x$have_dga = xtrue; then HAVE_LIBXXF86DGA_TRUE= HAVE_LIBXXF86DGA_FALSE='#' else HAVE_LIBXXF86DGA_TRUE='#' HAVE_LIBXXF86DGA_FALSE= fi have_gtk=false if test x$with_gtk != xno ; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTK" >&5 $as_echo_n "checking for GTK... " >&6; } if test -n "$GTK_CFLAGS"; then pkg_cv_GTK_CFLAGS="$GTK_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-2.0 >= 2.4.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "gtk+-2.0 >= 2.4.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GTK_CFLAGS=`$PKG_CONFIG --cflags "gtk+-2.0 >= 2.4.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$GTK_LIBS"; then pkg_cv_GTK_LIBS="$GTK_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-2.0 >= 2.4.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "gtk+-2.0 >= 2.4.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GTK_LIBS=`$PKG_CONFIG --libs "gtk+-2.0 >= 2.4.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then GTK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gtk+-2.0 >= 2.4.0" 2>&1` else GTK_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gtk+-2.0 >= 2.4.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$GTK_PKG_ERRORS" >&5 have_gtk="false" elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_gtk="false" else GTK_CFLAGS=$pkg_cv_GTK_CFLAGS GTK_LIBS=$pkg_cv_GTK_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } have_gtk="true" fi fi if test x$have_gtk = xtrue; then HAVE_GTK_TRUE= HAVE_GTK_FALSE='#' else HAVE_GTK_TRUE='#' HAVE_GTK_FALSE= fi have_sdl=false if test x$with_libsdl != xno ; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SDL" >&5 $as_echo_n "checking for SDL... " >&6; } if test -n "$SDL_CFLAGS"; then pkg_cv_SDL_CFLAGS="$SDL_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl > 1.1.3\""; } >&5 ($PKG_CONFIG --exists --print-errors "sdl > 1.1.3") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SDL_CFLAGS=`$PKG_CONFIG --cflags "sdl > 1.1.3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$SDL_LIBS"; then pkg_cv_SDL_LIBS="$SDL_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl > 1.1.3\""; } >&5 ($PKG_CONFIG --exists --print-errors "sdl > 1.1.3") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SDL_LIBS=`$PKG_CONFIG --libs "sdl > 1.1.3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then SDL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sdl > 1.1.3" 2>&1` else SDL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sdl > 1.1.3" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$SDL_PKG_ERRORS" >&5 have_sdl=false elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_sdl=false else SDL_CFLAGS=$pkg_cv_SDL_CFLAGS SDL_LIBS=$pkg_cv_SDL_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } have_sdl=true $as_echo "#define HAVE_SDL 1" >>confdefs.h fi fi if test x$have_sdl = xtrue; then HAVE_SDL_TRUE= HAVE_SDL_FALSE='#' else HAVE_SDL_TRUE='#' HAVE_SDL_FALSE= fi have_sdlgfx=false if test x$with_sdlgfx != xno ; then if test x$have_sdl = xtrue; then OLD_LIBS="$LIBS" LIBS="$LIBS -lSDL -lSDL_gfx" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for vlineColor in -lSDL_gfx" >&5 $as_echo_n "checking for vlineColor in -lSDL_gfx... " >&6; } if ${ac_cv_lib_SDL_gfx_vlineColor+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lSDL_gfx $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char vlineColor (); int main () { return vlineColor (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_SDL_gfx_vlineColor=yes else ac_cv_lib_SDL_gfx_vlineColor=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_SDL_gfx_vlineColor" >&5 $as_echo "$ac_cv_lib_SDL_gfx_vlineColor" >&6; } if test "x$ac_cv_lib_SDL_gfx_vlineColor" = xyes; then : SDLgfx_LIBS="-lSDL_gfx" $as_echo "#define HAVE_SDLgfx 1" >>confdefs.h have_sdlgfx=true else have_sdlgfx=false fi LIBS="$OLD_LIBS" fi fi if test x$have_sdlgfx = xtrue; then HAVE_SDLgfx_TRUE= HAVE_SDLgfx_FALSE='#' else HAVE_SDLgfx_TRUE='#' HAVE_SDLgfx_FALSE= fi have_asm_mmx=false have_x86cpu=false have_altivec=false { $as_echo "$as_me:${as_lineno-$LINENO}: checking Architecture" >&5 $as_echo_n "checking Architecture... " >&6; } case $host_cpu in i[3-7]86) { $as_echo "$as_me:${as_lineno-$LINENO}: result: IA32" >&5 $as_echo "IA32" >&6; } $as_echo "#define HAVE_X86CPU 1" >>confdefs.h have_x86cpu=true PROGRAM_NOPIC="-fno-PIC" ;; x86_64*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: x86_64" >&5 $as_echo "x86_64" >&6; } $as_echo "#define HAVE_X86CPU 1" >>confdefs.h have_x86cpu=true have_x86_64cpu=true PROGRAM_NOPIC="-fno-PIC" ;; powerpc | powerpc64) { $as_echo "$as_me:${as_lineno-$LINENO}: result: PowerPC" >&5 $as_echo "PowerPC" >&6; } $as_echo "#define HAVE_PPCCPU 1" >>confdefs.h have_ppccpu=true PROGRAM_NOPIC="" ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unknown" >&5 $as_echo "unknown" >&6; } PROGRAM_NOPIC="" ;; esac case $host in *-apple-darwin*) PROGRAM_NOPIC="-mdynamic-no-pic" # dynamic-no-pic is an Apple gcc option ;; esac if test "$enable_simd_accel" != "false" -a "$enable_simd_accel" != "no" then if test x$have_x86cpu = xtrue then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if C compiler accepts inline MMX assembly" >&5 $as_echo_n "checking if C compiler accepts inline MMX assembly... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { __asm__ __volatile__("emms":::"memory"); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : have_asm_mmx=true else have_asm_mmx=false fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $have_asm_mmx = true; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test $have_asm_mmx = true; then $as_echo "#define HAVE_ASM_MMX 1" >>confdefs.h fi fi if test x$have_ppccpu = xtrue then { $as_echo "$as_me:${as_lineno-$LINENO}: checking compiler support for AltiVec" >&5 $as_echo_n "checking compiler support for AltiVec... " >&6; } cat > conftest.c < #endif int main() { union { vector signed int v; signed int i; } vi; vi.v = vec_splat_s32(1); return vi.i; } EOF ALTIVEC_CFLAGS="" if $CC -o conftest conftest.c >/dev/null 2>&1; then have_altivec=true elif $CC $CFLAGS -faltivec -maltivec -o conftest conftest.c >/dev/null 2>&1; then # Mac OS X style with -maltivec have_altivec=true ALTIVEC_CFLAGS="-faltivec -maltivec" elif $CC $CFLAGS -faltivec -o conftest conftest.c >/dev/null 2>&1; then # Mac OS X style without -maltivec have_altivec=true ALTIVEC_CFLAGS="-faltivec" elif $CC $CFLAGS -fvec -o conftest conftest.c >/dev/null 2>&1; then # Motorola style have_altivec=true ALTIVEC_CFLAGS="-fvec" elif $CC $CFLAGS -DHAVE_ALTIVEC_H=1 -maltivec -mabi=altivec -o conftest conftest.c >/dev/null 2>&1; then # gcc 3.1 style have_altivec=true ALTIVEC_CFLAGS="-DHAVE_ALTIVEC_H=1 -maltivec -mabi=altivec" fi rm -f conftest*; if test x$have_altivec = xtrue then CFLAGS="$CFLAGS ${ALTIVEC_CFLAGS}" CXXFLAGS="$CXXFLAGS ${ALTIVEC_CFLAGS}" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_ALTIVEC 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test x$have_x86cpu = xtrue -o x$have_ppccpu = xtrue; then if test x$host_alias != x; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking sub-architecture settings" >&5 $as_echo_n "checking sub-architecture settings... " >&6; } if test x$have_x86cpu = xtrue; then host_mod_cpu=`echo $host_cpu | tr _ -` ARCHFLAGS="-march=$host_mod_cpu -mcpu=$host_mod_cpu" fi else if test ! -r $srcdir/cpuinfo.sh; then as_fn_error $? "cpuinfo.sh script not found - do a cvs update" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking sub-architecture settings" >&5 $as_echo_n "checking sub-architecture settings... " >&6; } chmod +x $srcdir/cpuinfo.sh if test x$have_x86cpu = xtrue; then ARCHFLAGS=`$srcdir/cpuinfo.sh x86` elif test x$have_ppccpu = xtrue; then ARCHFLAGS=`$srcdir/cpuinfo.sh ppc` fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ARCHFLAGS" >&5 $as_echo "$ARCHFLAGS" >&6; } fi if test "x$enable_static_build" = "xyes" ; then echo "Forcing static linkage..." LT_STATIC=-all-static else echo enable_static_build="\'${enable_static_build}\'" fi if test x$have_asm_mmx = xtrue; then HAVE_ASM_MMX_TRUE= HAVE_ASM_MMX_FALSE='#' else HAVE_ASM_MMX_TRUE='#' HAVE_ASM_MMX_FALSE= fi if test x$have_x86cpu = xtrue; then HAVE_X86CPU_TRUE= HAVE_X86CPU_FALSE='#' else HAVE_X86CPU_TRUE='#' HAVE_X86CPU_FALSE= fi if test x$have_ppccpu = xtrue; then HAVE_PPCCPU_TRUE= HAVE_PPCCPU_FALSE='#' else HAVE_PPCCPU_TRUE='#' HAVE_PPCCPU_FALSE= fi if test x$have_altivec = xtrue; then HAVE_ALTIVEC_TRUE= HAVE_ALTIVEC_FALSE='#' else HAVE_ALTIVEC_TRUE='#' HAVE_ALTIVEC_FALSE= fi # This is a redhat ppc hack - OSX (which also uses gcc4) does NOT have any # of the problems with undefined symbols, etc caused by a misplaced reference # to an encoder routine (next_larger_quant) in the utils/altivec routines. ALTIVEC_EXTRA_LIBS= if test x$have_altivec = xtrue; then ALTIVEC_EXTRA_LIBS=-lmpeg2encpp fi have_v4l_or_sdl=false if test x$have_video4linux = xtrue; then have_v4l_or_sdl=true else if test x$have_sdl = xtrue; then have_v4l_or_sdl=true fi fi if test x$have_v4l_or_sdl = xtrue; then HAVE_V4L_OR_SDL_TRUE= HAVE_V4L_OR_SDL_FALSE='#' else HAVE_V4L_OR_SDL_TRUE='#' HAVE_V4L_OR_SDL_FALSE= fi CFLAGS="$ARCHFLAGS $CFLAGS" CXXFLAGS="$ARCHFLAGS $CXXFLAGS" if test "x${GCC}" != "xyes" ; then enable_compile_warnings=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking what warning flags to pass to the C compiler" >&5 $as_echo_n "checking what warning flags to pass to the C compiler... " >&6; } warnCFLAGS= warnCXXFLAGS= if test "x$enable_compile_warnings" != "xno" ; then if test "x$GCC" = "xyes" ; then case "$CFLAGS" in *-Wall*) ;; *) warnCFLAGS="-Wall -Wunused" ;; esac if test "x$enable_compile_warnings" = "xyes" ; then warnCFLAGS="$warnCFLAGS -Wmissing-prototypes -Wmissing-declarations -Wpointer-arith -Wcast-align -Wwrite-strings -Wcast-qual" warnCXXFLAGS="$warnCXXFLAGS -Wmissing-prototypes -Wpointer-arith -Wcast-align -Wwrite-strings -Wcast-qual" fi if test "x$enable_warnings_as_errors" = "xyes" ; then warnCFLAGS="$warnCFLAGS -Werror" warnCXXFLAGS="$warnCXXFLAGS -Werror" fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $warnCFLAGS" >&5 $as_echo "$warnCFLAGS" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $warnCXXFLAGS" >&5 $as_echo "$warnCXXFLAGS" >&6; } if test "x$cflags_set" != "xyes" ; then CFLAGS="$CFLAGS $warnCFLAGS" CXXFLAGS="$CXXFLAGS $warnCXXFLAGS" cflags_set=yes fi # Check whether --enable-assert was given. if test "${enable_assert+set}" = set; then : enableval=$enable_assert; case "$enableval" in yes|no) : ;; *) as_fn_error $? "bad value for --enable-assert" "$LINENO" 5 ;; esac else enable_assert=yes fi if test x"$enable_assert" = x"no"; then NDEBUG=1; fi $as_echo "#define MJPEGTOOLS 1" >>confdefs.h case x"$NDEBUG" in x"1") $as_echo "#define NDEBUG 1" >>confdefs.h ;; esac ac_config_files="$ac_config_files Makefile debian/Makefile debian/control docs/Makefile lavtools/Makefile yuvcorrect/Makefile yuvdenoise/Makefile yuvdeinterlace/Makefile yuvscaler/Makefile y4munsharp/Makefile y4mutils/Makefile yuvfilters/Makefile mpeg2enc/Makefile aenc/Makefile mplex/Makefile scripts/Makefile utils/Makefile utils/altivec/Makefile utils/mmxsse/Makefile y4mdenoise/Makefile y4mscaler/Makefile mjpegtools.pc mjpegtools.spec" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCCAS_TRUE}" && test -z "${am__fastdepCCAS_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCCAS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_V4L_TRUE}" && test -z "${HAVE_V4L_FALSE}"; then as_fn_error $? "conditional \"HAVE_V4L\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_LIBQUICKTIME_TRUE}" && test -z "${HAVE_LIBQUICKTIME_FALSE}"; then as_fn_error $? "conditional \"HAVE_LIBQUICKTIME\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_LIBPNG_TRUE}" && test -z "${HAVE_LIBPNG_FALSE}"; then as_fn_error $? "conditional \"HAVE_LIBPNG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_LIBXXF86DGA_TRUE}" && test -z "${HAVE_LIBXXF86DGA_FALSE}"; then as_fn_error $? "conditional \"HAVE_LIBXXF86DGA\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_GTK_TRUE}" && test -z "${HAVE_GTK_FALSE}"; then as_fn_error $? "conditional \"HAVE_GTK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_SDL_TRUE}" && test -z "${HAVE_SDL_FALSE}"; then as_fn_error $? "conditional \"HAVE_SDL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_SDLgfx_TRUE}" && test -z "${HAVE_SDLgfx_FALSE}"; then as_fn_error $? "conditional \"HAVE_SDLgfx\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_ASM_MMX_TRUE}" && test -z "${HAVE_ASM_MMX_FALSE}"; then as_fn_error $? "conditional \"HAVE_ASM_MMX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_X86CPU_TRUE}" && test -z "${HAVE_X86CPU_FALSE}"; then as_fn_error $? "conditional \"HAVE_X86CPU\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_PPCCPU_TRUE}" && test -z "${HAVE_PPCCPU_FALSE}"; then as_fn_error $? "conditional \"HAVE_PPCCPU\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_ALTIVEC_TRUE}" && test -z "${HAVE_ALTIVEC_FALSE}"; then as_fn_error $? "conditional \"HAVE_ALTIVEC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_V4L_OR_SDL_TRUE}" && test -z "${HAVE_V4L_OR_SDL_FALSE}"; then as_fn_error $? "conditional \"HAVE_V4L_OR_SDL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by mjpegtools $as_me 2.1.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ mjpegtools config.status 2.1.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ nm_file_list_spec \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib \ compiler_lib_search_dirs \ predep_objects \ postdep_objects \ predeps \ postdeps \ compiler_lib_search_path \ LD_CXX \ reload_flag_CXX \ compiler_CXX \ lt_prog_compiler_no_builtin_flag_CXX \ lt_prog_compiler_pic_CXX \ lt_prog_compiler_wl_CXX \ lt_prog_compiler_static_CXX \ lt_cv_prog_compiler_c_o_CXX \ export_dynamic_flag_spec_CXX \ whole_archive_flag_spec_CXX \ compiler_needs_object_CXX \ with_gnu_ld_CXX \ allow_undefined_flag_CXX \ no_undefined_flag_CXX \ hardcode_libdir_flag_spec_CXX \ hardcode_libdir_separator_CXX \ exclude_expsyms_CXX \ include_expsyms_CXX \ file_list_spec_CXX \ compiler_lib_search_dirs_CXX \ predep_objects_CXX \ postdep_objects_CXX \ predeps_CXX \ postdeps_CXX \ compiler_lib_search_path_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ sys_lib_dlsearch_path_spec \ reload_cmds_CXX \ old_archive_cmds_CXX \ old_archive_from_new_cmds_CXX \ old_archive_from_expsyms_cmds_CXX \ archive_cmds_CXX \ archive_expsym_cmds_CXX \ module_cmds_CXX \ module_expsym_cmds_CXX \ export_symbols_cmds_CXX \ prelink_cmds_CXX \ postlink_cmds_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "debian/Makefile") CONFIG_FILES="$CONFIG_FILES debian/Makefile" ;; "debian/control") CONFIG_FILES="$CONFIG_FILES debian/control" ;; "docs/Makefile") CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;; "lavtools/Makefile") CONFIG_FILES="$CONFIG_FILES lavtools/Makefile" ;; "yuvcorrect/Makefile") CONFIG_FILES="$CONFIG_FILES yuvcorrect/Makefile" ;; "yuvdenoise/Makefile") CONFIG_FILES="$CONFIG_FILES yuvdenoise/Makefile" ;; "yuvdeinterlace/Makefile") CONFIG_FILES="$CONFIG_FILES yuvdeinterlace/Makefile" ;; "yuvscaler/Makefile") CONFIG_FILES="$CONFIG_FILES yuvscaler/Makefile" ;; "y4munsharp/Makefile") CONFIG_FILES="$CONFIG_FILES y4munsharp/Makefile" ;; "y4mutils/Makefile") CONFIG_FILES="$CONFIG_FILES y4mutils/Makefile" ;; "yuvfilters/Makefile") CONFIG_FILES="$CONFIG_FILES yuvfilters/Makefile" ;; "mpeg2enc/Makefile") CONFIG_FILES="$CONFIG_FILES mpeg2enc/Makefile" ;; "aenc/Makefile") CONFIG_FILES="$CONFIG_FILES aenc/Makefile" ;; "mplex/Makefile") CONFIG_FILES="$CONFIG_FILES mplex/Makefile" ;; "scripts/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;; "utils/Makefile") CONFIG_FILES="$CONFIG_FILES utils/Makefile" ;; "utils/altivec/Makefile") CONFIG_FILES="$CONFIG_FILES utils/altivec/Makefile" ;; "utils/mmxsse/Makefile") CONFIG_FILES="$CONFIG_FILES utils/mmxsse/Makefile" ;; "y4mdenoise/Makefile") CONFIG_FILES="$CONFIG_FILES y4mdenoise/Makefile" ;; "y4mscaler/Makefile") CONFIG_FILES="$CONFIG_FILES y4mscaler/Makefile" ;; "mjpegtools.pc") CONFIG_FILES="$CONFIG_FILES mjpegtools.pc" ;; "mjpegtools.spec") CONFIG_FILES="$CONFIG_FILES mjpegtools.spec" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "libtool":C) # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. available_tags="CXX " # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # DLL creation program. DLLTOOL=$lt_DLLTOOL # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and in which our libraries should be installed. lt_sysroot=$lt_sysroot # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects postdep_objects=$lt_postdep_objects predeps=$lt_predeps postdeps=$lt_postdeps # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain="$ac_aux_dir/ltmain.sh" # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) if test x"$xsi_shell" = xyes; then sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ func_dirname ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ } # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_basename ()$/,/^} # func_basename /c\ func_basename ()\ {\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ func_dirname_and_basename ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ func_stripname ()\ {\ \ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ \ # positional parameters, so assign one to ordinary parameter first.\ \ func_stripname_result=${3}\ \ func_stripname_result=${func_stripname_result#"${1}"}\ \ func_stripname_result=${func_stripname_result%"${2}"}\ } # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ func_split_long_opt ()\ {\ \ func_split_long_opt_name=${1%%=*}\ \ func_split_long_opt_arg=${1#*=}\ } # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ func_split_short_opt ()\ {\ \ func_split_short_opt_arg=${1#??}\ \ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ } # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ func_lo2o ()\ {\ \ case ${1} in\ \ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ \ *) func_lo2o_result=${1} ;;\ \ esac\ } # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_xform ()$/,/^} # func_xform /c\ func_xform ()\ {\ func_xform_result=${1%.*}.lo\ } # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_arith ()$/,/^} # func_arith /c\ func_arith ()\ {\ func_arith_result=$(( $* ))\ } # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_len ()$/,/^} # func_len /c\ func_len ()\ {\ func_len_result=${#1}\ } # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$lt_shell_append" = xyes; then sed -e '/^func_append ()$/,/^} # func_append /c\ func_append ()\ {\ eval "${1}+=\\${2}"\ } # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ func_append_quoted ()\ {\ \ func_quote_for_eval "${2}"\ \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ } # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 $as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} fi mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" cat <<_LT_EOF >> "$ofile" # ### BEGIN LIBTOOL TAG CONFIG: CXX # The linker used to build libraries. LD=$lt_LD_CXX # How to create reloadable object files. reload_flag=$lt_reload_flag_CXX reload_cmds=$lt_reload_cmds_CXX # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds_CXX # A language specific compiler. CC=$lt_compiler_CXX # Is the compiler the GNU compiler? with_gcc=$GCC_CXX # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_CXX # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_CXX # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_CXX # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_CXX # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object_CXX # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds_CXX archive_expsym_cmds=$lt_archive_expsym_cmds_CXX # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds_CXX module_expsym_cmds=$lt_module_expsym_cmds_CXX # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld_CXX # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_CXX # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_CXX # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct_CXX # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute_CXX # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L_CXX # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic_CXX # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath_CXX # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_CXX # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols_CXX # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_CXX # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_CXX # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_CXX # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds_CXX # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds_CXX # Specify filename containing input files. file_list_spec=$lt_file_list_spec_CXX # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_CXX # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects_CXX postdep_objects=$lt_postdep_objects_CXX predeps=$lt_predeps_CXX postdeps=$lt_postdeps_CXX # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_CXX # ### END LIBTOOL TAG CONFIG: CXX _LT_EOF ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi { $as_echo "$as_me:${as_lineno-$LINENO}: " >&5 $as_echo "$as_me: " >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: MJPEG tools ${VERSION} build configuration :" >&5 $as_echo "$as_me: MJPEG tools ${VERSION} build configuration :" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: " >&5 $as_echo "$as_me: " >&6;} if test "$have_x86cpu" = "true" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: - X86 Optimizations:" >&5 $as_echo "$as_me: - X86 Optimizations:" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: - MMX/3DNow!/SSE enabled : ${have_asm_mmx}" >&5 $as_echo "$as_me: - MMX/3DNow!/SSE enabled : ${have_asm_mmx}" >&6;} fi if test "$have_ppccpu" = "true" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: - PowerPC Optimizations:" >&5 $as_echo "$as_me: - PowerPC Optimizations:" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: - AltiVec enabled : ${have_altivec}" >&5 $as_echo "$as_me: - AltiVec enabled : ${have_altivec}" >&6;} fi if test x"$ARCHFLAGS" != x; then { $as_echo "$as_me:${as_lineno-$LINENO}: - arch/cpu compiler flags : ${ARCHFLAGS}" >&5 $as_echo "$as_me: - arch/cpu compiler flags : ${ARCHFLAGS}" >&6;} fi if test x"$with_extra_cflags" != "x"; then { $as_echo "$as_me:${as_lineno-$LINENO}: - extra_cflags added to CFLAGS: ${with_extra_cflags}" >&5 $as_echo "$as_me: - extra_cflags added to CFLAGS: ${with_extra_cflags}" >&6;} fi { $as_echo "$as_me:${as_lineno-$LINENO}: - video4linux recording/playback: ${have_video4linux}" >&5 $as_echo "$as_me: - video4linux recording/playback: ${have_video4linux}" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: - software MJPEG playback : ${have_sdl}" >&5 $as_echo "$as_me: - software MJPEG playback : ${have_sdl}" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: - Quicktime playback/recording : ${have_libquicktime}" >&5 $as_echo "$as_me: - Quicktime playback/recording : ${have_libquicktime}" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: - PNG input support : ${have_libpng}" >&5 $as_echo "$as_me: - PNG input support : ${have_libpng}" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: - AVI MJPEG playback/recording : true (always)" >&5 $as_echo "$as_me: - AVI MJPEG playback/recording : true (always)" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: - libDV (digital video) support : ${have_libdv} " >&5 $as_echo "$as_me: - libDV (digital video) support : ${have_libdv} " >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: - Gtk+ support for glav : ${have_gtk}" >&5 $as_echo "$as_me: - Gtk+ support for glav : ${have_gtk}" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: " >&5 $as_echo "$as_me: " >&6;} mjpegtools-2.1.0/mjpegtools.pc0000644000175000017500000000047412217306441016725 0ustar glowwormglowwormprefix=/usr/local exec_prefix=${prefix} libdir=${exec_prefix}/lib64 includedir=${prefix}/include/mjpegtools Name: MJPEG-tools Description: Video-recording, -editing, -filtering and -encoding tools Version: 2.1.0 Libs: -L${libdir} -lmjpegutils Cflags: -I${includedir} -I${includedir}/mpeg2enc -I${includedir}/mplex mjpegtools-2.1.0/install-sh0000755000175000017500000003325512217306406016226 0ustar glowwormglowworm#!/bin/sh # install - install a program, script, or datafile scriptversion=2011-11-20.07; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: mjpegtools-2.1.0/README.avilib0000644000175000017500000001527710163451225016351 0ustar glowwormglowwormavilib: Reading and writing avi files ===================================== Copyright (C) 1999 Rainer Johanni avilib is a open source library for dealing with AVI files under Linux or other UNIX operating systems. It provides a framework for extracting or adding raw audio and single raw (=compressed) frames from/to AVI Files. It does not deal with any compression issues which have to be handled on a higher level by the user of avilib. AVI files may have several video and audiotracks. avilib writes only one video track and (optionally) one audio track and also extracts only the first video and audio track (but input files may contain more than one track, the others just being ingored). The interface to avilib is kept similar to the quicktime4linux interface (by Adam Williams) with the following important differences: - since only the first track of video and audio is considered, there is no track argument in any of the routines. - audio is generally considered as a byte stream and therefore all size arguments used in reading/writing audio are in bytes and not in samples. - as mentioned above, there are no routines dealing with compression issues. Compiling: ========== Since the library consists only of one c source file, I have not provided a Makefile or similar, just compile with cc -c avilib.c Portability: ============ AVI-Files use little endian numbers throughout the file, I have tried to read/write these numbers in a way which doesn't depent on endianness. This library should therefore also be useable on big endian machines. This feature is not so heavily tested, however. Usage: ====== Basics, opening, closing ------------------------ Include "avilib.h" in your source and declare a pointer: avi_t *avifile; Open the AVI file with: avifile = AVI_open_input_file("xxx.avi",1); or avifile = AVI_open_output_file("xxx.avi"); You may either only read from the input file (leaving it unchanged) or create a completly new AVI file. There is no editing or append mode available. Both routines will either return a pointer to avi_t or a zero pointer in the case of an error. For closing the file, use: int AVI_close(avi_t *AVI); Files you have written MUST be closed (the header is written at close time), else they will not be readable by any other software. Files opened for reading should be closed to free the file descriptor and some data (unless your program is finishing anyway). Error handling: --------------- Most routines (besides open/close) will return 0 or a useful number if successfull and a -1 in the case of an error. If an error occured, the external variable AVI_errno is set. See avilib.h for the meaning of the error codes in AVI_errno. There is also a routine (which acts like strerror) to retrieve a string description of the last error (which can then be logged or printed): AVI_strerror(char *str) Reading from an AVI file: ------------------------- After opening the file, you can obtain the parameters of the AVI with the following routines: long AVI_video_frames(avi_t *AVI); number of video frames in the file int AVI_video_width(avi_t *AVI); int AVI_video_height(avi_t *AVI); width and height of the video in pixels double AVI_frame_rate(avi_t *AVI); frame rate in frames per second, notice that this is a double value! char* AVI_video_compressor(avi_t *AVI); string describing the compressor int AVI_audio_channels(avi_t *AVI); number of audio channels, 1 for mono, 2 for stereo, 0 if no audio present int AVI_audio_bits(avi_t *AVI); audio bits, usually 8 or 16 int AVI_audio_format(avi_t *AVI); audio format, most common is 1 for raw PCM, look into avilib.h for others long AVI_audio_rate(avi_t *AVI); audio rate in samples/second long AVI_audio_bytes(avi_t *AVI); total number of audio bytes in the file In order to read the video frame by frame, use (frame numbers are starting from 0 !!!!!) long AVI_frame_size(avi_t *AVI, long frame); to get the size of frame with number "frame" long AVI_read_frame(avi_t *AVI, char *vidbuf); to read the next frame (frame posittion is advanced by 1 after the read) int AVI_seek_start(avi_t *AVI); int AVI_set_video_position(avi_t *AVI, long frame); to position in the AVI file (for reading the frames out of order) Read audio with int AVI_set_audio_position(avi_t *AVI, long byte); to position to an arbitrary byte position within the audio stream long AVI_read_audio(avi_t *AVI, char *audbuf, long bytes); to actually read "bytes" number of audio bytes. the audio position is advanced by "bytes", so there is no need to reposition before every call when reading in order. Avoiding lengthy index searches: -------------------------------- When opening the AVI file, avilib looks if the file has an index attached and if this is not the case, it creates one by reading through the whole file. If you want to read through the file only once, creation of an index is not necessary in that case. You may use AVI_open_input_file with the second argument set to 0 and then use AVI_read_data for readin through the file. Look to the source for the arguments of AVI_read_data. Writing to an AVI file: ----------------------- After you have opened the file, use the following routines to set the properties of the AVI file: void AVI_set_video(avi_t *AVI, int width, int height, double fps, char *compressor); void AVI_set_audio(avi_t *AVI, int channels, long rate, int bits, int format); with: width, height width and height of the video in pixels fps frame rate in frames per second, notice that this is a double value! compressor string describing the compressor channels number of audio channels, 1 for mono, 2 for stereo, 0 if no audio present rate audio rate in samples/second bits audio bits, usually 8 or 16, 0 if no audio present format audio format, most common is 1 for raw PCM, look into avilib.h for others to write video frames or audio, use: int AVI_write_frame(avi_t *AVI, char *data, long bytes); int AVI_write_audio(avi_t *AVI, char *data, long bytes); there is also a feature to duplicate the index entry of the last frame without writing the data again to the file, this should used with care since I don't know if all AVI players can handle the resulting file (xanim can do it!): int AVI_dup_frame(avi_t *AVI); AVI files have a 2 GB limit (as has the Linux ext2 file system), avilib will return an error if you try to add more data to the file (and it cares that the file still can be correctly closed). If you want to check yourself how far you are away from that limit (for example to synchronize the amount of audio and video data) use: long AVI_bytes_remain(avi_t *AVI); mjpegtools-2.1.0/yuvcorrect/0000755000175000017500000000000012217306501016413 5ustar glowwormglowwormmjpegtools-2.1.0/yuvcorrect/yuvcorrect_functions.c0000644000175000017500000014365010324007173023065 0ustar glowwormglowworm/* * yuvcorrect_functions.c * Common functions between yuvcorrect and yuvcorrect_tune * Copyright (C) 2002 Xavier Biquard * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ // ************************************************************************************* #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include "yuv4mpeg.h" #include "yuvcorrect.h" // For pointer adress alignement const uint16_t ALIGNEMENT = 16 ; // 16 bytes alignement for mmx registers in SIMD instructions for Pentium const float PI = 3.141592654; const char *legal_opt_flags = "I:F:M:T:Y:R:v:h"; const char LUMINANCE[] = "LUMINANCE_"; const char CHROMINANCE[] = "CHROMINANCE_"; const char Y[] = "Y_"; const char UV[] = "UV_"; const char CONFORM[] = "CONFORM"; const char R[] = "R_"; const char G[] = "G_"; const char B[] = "B_"; // Possible capacity over or under flow for the RGB to YUV conversion and vice-versa const uint16_t OFFSET = 256; // ************************************************************************************* void handle_args_yuv_rgb (int argc, char *argv[], yuv_correction_t * yuv_correct, rgb_correction_t * rgb_correct) { // This function handles argument passing on the command line int c; unsigned int ui1, ui2, ui3, ui4; int k_yuv, k_rgb; float f1, f2, f3; // Ne pas oublier de mettre la putain de ligne qui suit, sinon, plus d'argument à la ligne de commande, ils auront été bouffés par l'appel précédent à getopt!! optind = 1; while ((c = getopt (argc, argv, legal_opt_flags)) != -1) { switch (c) { // ************** // yuv KEYOWRD // ************** case 'Y': k_yuv = 0; if (strncmp (optarg, LUMINANCE, 10) == 0) { k_yuv = 1; if (sscanf (optarg, "LUMINANCE_%f_%u_%u_%u_%u", &f1, &ui1, &ui2, &ui3, &ui4) == 5) { // Coherence check: if ((f1 <= 0.0) || (ui1 < 0) || (ui1 > 255) || (ui2 < 0) || (ui2 > 255) || (ui3 < 0) || (ui3 > 255) || (ui4 < 0) || (ui4 > 255) || (ui1 > ui2) || (ui3 > ui4)) mjpeg_error_exit1 ("Uncoherent luminance correction (0<>255, small, large): Gamma=%f, InputYmin=%u, InputYmax=%u, OutputYmin=%u, OutputYmax=%u\n", f1, ui1, ui2, ui3, ui4); yuv_correct->luma = 1; yuv_correct->Gamma = f1; yuv_correct->InputYmin = (uint8_t) ui1; yuv_correct->InputYmax = (uint8_t) ui2; yuv_correct->OutputYmin = (uint8_t) ui3; yuv_correct->OutputYmax = (uint8_t) ui4; } else mjpeg_error_exit1 ("Wrong number of argument to LUMINANCE keyword: %s\n", optarg); } if (strncmp (optarg, Y, 2) == 0) { k_yuv = 1; if (sscanf (optarg, "Y_%f_%u_%u_%u_%u", &f1, &ui1, &ui2, &ui3, &ui4) == 5) { // Coherence check: if ((f1 <= 0.0) || (ui1 < 0) || (ui1 > 255) || (ui2 < 0) || (ui2 > 255) || (ui3 < 0) || (ui3 > 255) || (ui4 < 0) || (ui4 > 255) || (ui1 > ui2) || (ui3 > ui4)) mjpeg_error_exit1 ("Uncoherent luminance correction (0<>255, small, large): Gamma=%f, InputYmin=%u, InputYmax=%u, OutputYmin=%u, OutputYmax=%u\n", f1, ui1, ui2, ui3, ui4); yuv_correct->luma = 1; yuv_correct->Gamma = f1; yuv_correct->InputYmin = (uint8_t) ui1; yuv_correct->InputYmax = (uint8_t) ui2; yuv_correct->OutputYmin = (uint8_t) ui3; yuv_correct->OutputYmax = (uint8_t) ui4; } else mjpeg_error_exit1 ("Wrong number of argument to Y keyword: %s\n", optarg); } if (strncmp (optarg, CHROMINANCE, 12) == 0) { k_yuv = 1; if (sscanf (optarg, "CHROMINANCE_%f_%f_%u_%f_%u_%u_%u", &f1, &f2, &ui1, &f3, &ui2, &ui3, &ui4) == 7) { // Coherence check: if ((f2 <= 0.0) || (f3 <= 0.0) || (ui1 < 0) || (ui1 > 255) || (ui2 < 0) || (ui2 > 255) || (ui3 < 0) || (ui3 > 255) || (ui4 < 0) || (ui4 > 255) || (ui3 > ui4) || (ui1 > ui4) || (ui2 > ui4)) mjpeg_error_exit1 ("Uncoherent chrominance correction (0<>255, small, large): UVrotation=%f, Ufactor=%f, Ucenter=%u, Vfactor=%f, Vcenter=%u, UVmin=%u, UVmax=%u, \n", f1, f2, ui1, f3, ui2, ui3, ui4); yuv_correct->chroma = 1; yuv_correct->UVrotation = f1; yuv_correct->Urotcenter = (uint8_t) ui1; yuv_correct->Vrotcenter = (uint8_t) ui2; yuv_correct->Ufactor = f2; yuv_correct->Vfactor = f3; yuv_correct->UVmin = (uint8_t) ui3; yuv_correct->UVmax = (uint8_t) ui4; } else mjpeg_error_exit1 ("Wrong number of argument to CHROMINANCE keyword: %s\n", optarg); } if (strncmp (optarg, UV, 3) == 0) { k_yuv = 1; if (sscanf (optarg, "UV_%f_%f_%u_%f_%u_%u_%u", &f1, &f2, &ui1, &f3, &ui2, &ui3, &ui4) == 7) { // Coherence check: if ((f2 <= 0.0) || (f3 <= 0.0) || (ui1 < 0) || (ui1 > 255) || (ui2 < 0) || (ui2 > 255) || (ui3 < 0) || (ui3 > 255) || (ui4 < 0) || (ui4 > 255) || (ui3 > ui4) || (ui1 > ui4) || (ui2 > ui4)) mjpeg_error_exit1 ("Uncoherent chrominance correction (0<>255, small, large): UVrotation=%f, Ufactor=%f, Ucenter=%u, Vfactor=%f, Vcenter=%u, UVmin=%u, UVmax=%u, \n", f1, f2, ui1, f3, ui2, ui3, ui4); yuv_correct->chroma = 1; yuv_correct->UVrotation = f1; yuv_correct->Urotcenter = (uint8_t) ui1; yuv_correct->Vrotcenter = (uint8_t) ui2; yuv_correct->Ufactor = f2; yuv_correct->Vfactor = f3; yuv_correct->UVmin = (uint8_t) ui3; yuv_correct->UVmax = (uint8_t) ui4; } else mjpeg_error_exit1 ("Wrong number of argument to UV keyword: %s\n", optarg); } if (strncmp (optarg, CONFORM, 7) == 0) { k_yuv = 1; yuv_correct->luma = 1; yuv_correct->Gamma = 1.0; yuv_correct->InputYmin = 16; yuv_correct->InputYmax = 235; yuv_correct->OutputYmin = 16; yuv_correct->OutputYmax = 235; yuv_correct->chroma = 1; yuv_correct->UVrotation = 0.0; yuv_correct->Urotcenter = 128; yuv_correct->Vrotcenter = 128; yuv_correct->Ufactor = 1.0; yuv_correct->Vfactor = 1.0; yuv_correct->UVmin = 16; yuv_correct->UVmax = 240; } if (k_yuv == 0) mjpeg_error_exit1 ("Unrecognized yuv keyword: %s", optarg); break; // ************* // ************** // RGB KEYOWRD // ************** case 'R': k_rgb = 0; if (strncmp (optarg, R, 2) == 0) { k_rgb = 1; if (sscanf (optarg, "R_%f_%u_%u_%u_%u", &f1, &ui1, &ui2, &ui3, &ui4) == 5) { // Coherence check: if ((f1 <= 0.0) || (ui1 < 0) || (ui1 > 255) || (ui2 < 0) || (ui2 > 255) || (ui3 < 0) || (ui3 > 255) || (ui4 < 0) || (ui4 > 255) || (ui1 > ui2) || (ui3 > ui4)) mjpeg_error_exit1 ("Uncoherent RED correction (0<>255, small, large): Gamma=%f, InputYmin=%u, InputYmax=%u, OutputYmin=%u, OutputYmax=%u\n", f1, ui1, ui2, ui3, ui4); rgb_correct->rgb = 1; rgb_correct->RGamma = f1; rgb_correct->InputRmin = (uint8_t) ui1; rgb_correct->InputRmax = (uint8_t) ui2; rgb_correct->OutputRmin = (uint8_t) ui3; rgb_correct->OutputRmax = (uint8_t) ui4; } else mjpeg_error_exit1 ("Wrong number of argument to R keyword: %s\n", optarg); } if (strncmp (optarg, G, 2) == 0) { k_rgb = 1; if (sscanf (optarg, "G_%f_%u_%u_%u_%u", &f1, &ui1, &ui2, &ui3, &ui4) == 5) { // Coherence check: if ((f1 <= 0.0) || (ui1 < 0) || (ui1 > 255) || (ui2 < 0) || (ui2 > 255) || (ui3 < 0) || (ui3 > 255) || (ui4 < 0) || (ui4 > 255) || (ui1 > ui2) || (ui3 > ui4)) mjpeg_error_exit1 ("Uncoherent GREEN correction (0<>255, small, large): Gamma=%f, InputYmin=%u, InputYmax=%u, OutputYmin=%u, OutputYmax=%u\n", f1, ui1, ui2, ui3, ui4); rgb_correct->rgb = 1; rgb_correct->GGamma = f1; rgb_correct->InputGmin = (uint8_t) ui1; rgb_correct->InputGmax = (uint8_t) ui2; rgb_correct->OutputGmin = (uint8_t) ui3; rgb_correct->OutputGmax = (uint8_t) ui4; } else mjpeg_error_exit1 ("Wrong number of argument to G keyword: %s\n", optarg); } if (strncmp (optarg, B, 2) == 0) { k_rgb = 1; if (sscanf (optarg, "B_%f_%u_%u_%u_%u", &f1, &ui1, &ui2, &ui3, &ui4) == 5) { // Coherence check: if ((f1 <= 0.0) || (ui1 < 0) || (ui1 > 255) || (ui2 < 0) || (ui2 > 255) || (ui3 < 0) || (ui3 > 255) || (ui4 < 0) || (ui4 > 255) || (ui1 > ui2) || (ui3 > ui4)) mjpeg_error_exit1 ("Uncoherent BLUE correction (0<>255, small, large): Gamma=%f, InputYmin=%u, InputYmax=%u, OutputYmin=%u, OutputYmax=%u\n", f1, ui1, ui2, ui3, ui4); rgb_correct->rgb = 1; rgb_correct->BGamma = f1; rgb_correct->InputBmin = (uint8_t) ui1; rgb_correct->InputBmax = (uint8_t) ui2; rgb_correct->OutputBmin = (uint8_t) ui3; rgb_correct->OutputBmax = (uint8_t) ui4; } else mjpeg_error_exit1 ("Wrong number of argument to B keyword: %s\n", optarg); } if (k_rgb == 0) mjpeg_error_exit1 ("Unrecognized rgb keyword: %s", optarg); break; // ************* default: break; } } } // ************************************************************************************* // ************************************************************************************* void ref_frame_init(int fd,ref_frame_t *ref_frame) { unsigned long int length; uint8_t *u_c_p; y4m_init_stream_info (&ref_frame->streaminfo); if (y4m_read_stream_header (fd,&ref_frame->streaminfo) != Y4M_OK) mjpeg_error_exit1 ("Could not read RefFrame yuv4mpeg header!"); ref_frame->width = y4m_si_get_width(&ref_frame->streaminfo); ref_frame->height=y4m_si_get_height(&ref_frame->streaminfo); length=(ref_frame->width>>1)*ref_frame->height*3; if (!(u_c_p = malloc (length + ALIGNEMENT))) mjpeg_error_exit1 ("Could not allocate memory for ref frame. STOP!"); mjpeg_debug ("before alignement: %p", u_c_p); if (((unsigned long) u_c_p % ALIGNEMENT) != 0) u_c_p = (uint8_t *) ((((unsigned long) u_c_p / ALIGNEMENT) + 1) * ALIGNEMENT); mjpeg_debug ("after alignement: %p", u_c_p); ref_frame->ref = u_c_p; y4m_init_frame_info (&ref_frame->info); return; } // ************************************************************************************* // ************************************************************************************* void initialisation1(int fd,frame_t * frame, general_correction_t * gen_correct, yuv_correction_t * yuv_correct, rgb_correction_t * rgb_correct) { uint8_t *u_c_p; //u_c_p = uint8_t pointer // gen_correct gen_correct->no_header = gen_correct->line_switch = gen_correct->field_move = 0; y4m_init_stream_info (&gen_correct->streaminfo); if (y4m_read_stream_header (fd, &gen_correct->streaminfo) != Y4M_OK) mjpeg_error_exit1("Couldn't read yuv4mpeg header!"); if (y4m_si_get_plane_count(&gen_correct->streaminfo) != 3) mjpeg_error_exit1("Only 3 plane formats supported"); // frame frame->y_width = y4m_si_get_width (&gen_correct->streaminfo); frame->y_height = y4m_si_get_height (&gen_correct->streaminfo); frame->nb_y = frame->y_width * frame->y_height; frame->ss_h = y4m_chroma_ss_x_ratio(y4m_si_get_chroma(&gen_correct->streaminfo)).d; frame->ss_v = y4m_chroma_ss_y_ratio(y4m_si_get_chroma(&gen_correct->streaminfo)).d; frame->uv_width = y4m_si_get_plane_width(&gen_correct->streaminfo, 1); /* planes 1&2 = U+V */ frame->uv_height = y4m_si_get_plane_height(&gen_correct->streaminfo, 1); frame->nb_uv = frame->uv_width * frame->uv_height; frame->length = frame->nb_y + 2 * frame->nb_uv; if (!(u_c_p = malloc (frame->length + ALIGNEMENT))) mjpeg_error_exit1 ("Could not allocate memory for frame table. STOP!"); mjpeg_debug ("before alignement: %p", u_c_p); if (((unsigned long) u_c_p % ALIGNEMENT) != 0) u_c_p = (uint8_t *) ((((unsigned long) u_c_p / ALIGNEMENT) + 1) * ALIGNEMENT); mjpeg_debug ("after alignement: %p", u_c_p); frame->y = u_c_p; frame->u = frame->y + frame->nb_y; frame->v = frame->u + frame->nb_uv; frame->field1 = frame->field2 = NULL; y4m_init_frame_info (&frame->info); // yuv_correct yuv_correct->luma = yuv_correct->chroma = 0; yuv_correct->luminance = yuv_correct->chrominance = NULL; yuv_correct->InputYmin = yuv_correct->OutputYmin = yuv_correct->UVmin = 0; yuv_correct->InputYmax = yuv_correct->OutputYmax = yuv_correct->UVmax = 255; yuv_correct->Gamma = yuv_correct->Ufactor = yuv_correct->Vfactor = 1.0; yuv_correct->UVrotation = 0.0; yuv_correct->Urotcenter = yuv_correct->Vrotcenter = 128; // rgb_correct rgb_correct->rgb = 0; rgb_correct->new_red = rgb_correct->new_green = rgb_correct->new_blue = NULL; rgb_correct->RGamma = rgb_correct->GGamma = rgb_correct->BGamma = 1.0; rgb_correct->InputRmin = rgb_correct->InputGmin = rgb_correct->InputBmin = 0; rgb_correct->InputRmax = rgb_correct->InputGmax = rgb_correct->InputBmax = 255; rgb_correct->OutputRmin = rgb_correct->OutputGmin = rgb_correct->OutputBmin = 0; rgb_correct->OutputRmax = rgb_correct->OutputGmax = rgb_correct->OutputBmax = 255; rgb_correct->luma_r = rgb_correct->luma_g = rgb_correct->luma_b = NULL; rgb_correct->u_r = rgb_correct->u_g = rgb_correct->u_b = NULL; rgb_correct->v_r = rgb_correct->v_g = rgb_correct->v_b = NULL; rgb_correct->RUV_v = rgb_correct->GUV_v = rgb_correct->GUV_u = rgb_correct->BUV_u = NULL; return ; } // ************************************************************************************* // ************************************************************************************* void initialisation2(yuv_correction_t * yuv_correct, rgb_correction_t * rgb_correct) { uint8_t *u_c_p; //u_c_p = uint8_t pointer int8_t *si; // si = int8_t pointer int16_t *sii; // sii = int16_t pointer // Luminance correction initialisation if (yuv_correct->luma == 1) { // Memory allocation for the luminance vector if (!(u_c_p = (uint8_t *) malloc (256 * sizeof (uint8_t) + ALIGNEMENT))) mjpeg_error_exit1 ("Could not allocate memory for luminance table. STOP!"); if (((unsigned long) u_c_p % ALIGNEMENT) != 0) u_c_p = (uint8_t *) ((((unsigned long) u_c_p / ALIGNEMENT) + 1) * ALIGNEMENT); yuv_correct->luminance = u_c_p; // Filling in the luminance vectors yuvcorrect_luminance_init (yuv_correct); } // Chrominance correction initialisation if (yuv_correct->chroma == 1) { // Memory allocation for the UVchroma vector if (!(u_c_p = (uint8_t *) malloc (2 * 256 * 256 * sizeof (uint8_t) + ALIGNEMENT))) mjpeg_error_exit1 ("Could not allocate memory for UVchroma vector. STOP!"); // memory alignement of the 2 chroma vectors if (((unsigned long) u_c_p % ALIGNEMENT) != 0) u_c_p = (uint8_t *) ((((unsigned long) u_c_p / ALIGNEMENT) + 1) * ALIGNEMENT); yuv_correct->chrominance = u_c_p; // Filling in the UVchroma vector yuvcorrect_chrominance_init (yuv_correct); } // RGB correction initialisation if (rgb_correct->rgb == 1) { // Memory allocation for the rgb vectors if (! (u_c_p = (uint8_t *) malloc (3 * (256 + (OFFSET << 1))* sizeof (uint8_t) + ALIGNEMENT))) mjpeg_error_exit1 ("Could not allocate memory for rgb table. STOP!"); if (((unsigned long) u_c_p % ALIGNEMENT) != 0) u_c_p = (uint8_t *) ((((unsigned long) u_c_p / ALIGNEMENT) + 1) * ALIGNEMENT); rgb_correct->new_red = u_c_p; u_c_p += (256 + (OFFSET<<1)); rgb_correct->new_green = u_c_p; u_c_p += (256 + (OFFSET<<1)); rgb_correct->new_blue = u_c_p; // Accélération if (! (u_c_p = (uint8_t *) malloc (3 * 256 * sizeof (uint8_t) + ALIGNEMENT))) mjpeg_error_exit1 ("Could not allocate memory for rgb table. STOP!"); if (((unsigned long) u_c_p % ALIGNEMENT) != 0) u_c_p = (uint8_t *) ((((unsigned long) u_c_p / ALIGNEMENT) + 1) * ALIGNEMENT); rgb_correct->luma_r = u_c_p; u_c_p += 256; rgb_correct->luma_g = u_c_p; u_c_p += 256; rgb_correct->luma_b = u_c_p; if (!(si = (int8_t *) malloc (3 * 256 * sizeof (int8_t) + ALIGNEMENT))) mjpeg_error_exit1 ("Could not allocate memory for rgb table. STOP!"); if (((unsigned long) si % ALIGNEMENT) != 0) si = (int8_t *) ((((unsigned long) si / ALIGNEMENT) + 1) * ALIGNEMENT); rgb_correct->u_r = si; si += 256; rgb_correct->u_g = si; si += 256; rgb_correct->u_b = si; if (!(si = (int8_t *) malloc (3 * 256 * sizeof (int8_t) + ALIGNEMENT))) mjpeg_error_exit1 ("Could not allocate memory for rgb table. STOP!"); if (((unsigned long) si % ALIGNEMENT) != 0) si = (int8_t *) ((((unsigned long) si / ALIGNEMENT) + 1) * ALIGNEMENT); rgb_correct->v_r = si; si += 256; rgb_correct->v_g = si; si += 256; rgb_correct->v_b = si; if (! (sii = (int16_t *) malloc (4 * 256 * sizeof (int16_t) + ALIGNEMENT))) mjpeg_error_exit1 ("Could not allocate memory for rgb table. STOP!"); if (((unsigned long) sii % ALIGNEMENT) != 0) sii = (int16_t *) ((((unsigned long) sii / ALIGNEMENT) + 1) * ALIGNEMENT); rgb_correct->RUV_v = sii; sii += 256; rgb_correct->GUV_v = sii; sii += 256; rgb_correct->GUV_u = sii; sii += 256; rgb_correct->BUV_u = sii; // Filling in the RGB vectors yuvcorrect_RGB_init (rgb_correct); } } // ************************************************************************************* // ************************************************************************************* int yuvcorrect_y4m_read_frame (int fd, y4m_stream_info_t *si, frame_t * frame, uint8_t line_switch) { // This function reads a frame from input stream. // It is the same as the y4m_read_frame function (from y4mpeg.c) except that line switching // is done during frame read static int err = Y4M_OK; unsigned int line; uint8_t *buf; buf = frame->y; if ((err = y4m_read_frame_header (fd, si, &frame->info)) == Y4M_OK) { if (!line_switch) { if ((err = y4m_read (fd, buf, frame->length)) != Y4M_OK) { mjpeg_info ("Couldn't read FRAME content: %s!", y4m_strerr (err)); return (err); } } else { // line switching during frame read // Y COMPONENT for (line = 0; line < frame->y_height; line += 2) { buf += frame->y_width; // buf points to next line on output, store input line there if ((err = y4m_read (fd, buf, frame->y_width)) != Y4M_OK) { mjpeg_info ("Couldn't read FRAME content line %d : %s!", line, y4m_strerr (err)); return (err); } buf -= frame->y_width; // buf points to former line on output, store input line there if ((err = y4m_read (fd, buf, frame->y_width)) != Y4M_OK) { mjpeg_info ("Couldn't read FRAME content line %d : %s!", line + 1, y4m_strerr (err)); return (err); } buf += (frame->y_width << 1); // 2 lines were read and stored } // U and V component for (line = 0; line < (frame->uv_height << 1); line += 2) { buf += frame->uv_width; // buf points to next line on output, store input line there if ((err = y4m_read (fd, buf, frame->uv_width)) != Y4M_OK) { mjpeg_info ("Couldn't read FRAME content line %d : %s!", line, y4m_strerr (err)); return (err); } buf -= frame->uv_width; // buf points to former line on output, store input line there if ((err = y4m_read (fd, buf, frame->uv_width)) != Y4M_OK) { mjpeg_info ("Couldn't read FRAME content line %d : %s!", line + 1, y4m_strerr (err)); return (err); } buf += (frame->uv_width << 1); // two line were read and stored } } } else { if (err != Y4M_ERR_EOF) mjpeg_info ("Couldn't read FRAME header: %s!", y4m_strerr (err)); else mjpeg_info ("End of stream!"); return (err); } return Y4M_OK; } // ************************************************************************************* // ************************************************************************************* int yuvcorrect_luminance_init (yuv_correction_t * yuv_correct) { // This function initialises the luminance vector uint8_t *u_c_p; //u_c_p = uint8_t pointer uint16_t i; // Filling in the luminance vector u_c_p = yuv_correct->luminance; for (i = 0; i < 256; i++) { if (i <= yuv_correct->InputYmin) *(u_c_p++) = yuv_correct->OutputYmin; else { if (i >= yuv_correct->InputYmax) *(u_c_p++) = yuv_correct->OutputYmax; else *(u_c_p++) = yuv_correct->OutputYmin + floor (0.5 + pow ((float) (i - yuv_correct->InputYmin) / (float) (yuv_correct->InputYmax - yuv_correct->InputYmin), (float) 1 / yuv_correct->Gamma) * (yuv_correct->OutputYmax - yuv_correct->OutputYmin)); } // mjpeg_debug ("Luminance[%u]=%u", i, yuv_correct->luminance[i]); } return (0); } // ************************************************************************************* // ************************************************************************************* int yuvcorrect_chrominance_init (yuv_correction_t * yuv_correct) { // This function initialises the UVchroma vector uint8_t *u_c_p; //u_c_p = uint8_t pointer uint16_t u, v; // do not use uint8_t, else you get infinite loop for u and v because 255+1=0 in unit8_t float newU, newV, cosinus, sinus; mjpeg_debug ("chroma init"); cosinus = cos (yuv_correct->UVrotation / 180.0 * PI); sinus = sin (yuv_correct->UVrotation / 180.0 * PI); // Filling in the chrominance vector u_c_p = yuv_correct->chrominance; for (u = 0; u <= 255; u++) { for (v = 0; v <= 255; v++) { newU = (((float) (u - yuv_correct->Urotcenter) * yuv_correct->Ufactor) * cosinus - ((float) (v - yuv_correct->Vrotcenter) * yuv_correct->Vfactor) * sinus) + 128.0; // mjpeg_debug("u=%u, v=%u, newU=%f",u,v,newU); newU = (float) floor (0.5 + newU); // nearest integer in double format if (newU < yuv_correct->UVmin) newU = yuv_correct->UVmin; if (newU > yuv_correct->UVmax) newU = yuv_correct->UVmax; newV = (((float) (v - yuv_correct->Vrotcenter) * yuv_correct->Vfactor) * cosinus + ((float) (u - yuv_correct->Urotcenter) * yuv_correct->Ufactor) * sinus) + 128.0; // mjpeg_debug("u=%u, v=%u, newV=%f",u,v,newV); newV = (float) floor (0.5 + newV); // nearest integer in double format if (newV < yuv_correct->UVmin) newV = yuv_correct->UVmin; if (newV > yuv_correct->UVmax) newV = yuv_correct->UVmax; *(u_c_p++) = (uint8_t) newU; *(u_c_p++) = (uint8_t) newV; } } mjpeg_debug ("end of chroma init"); return (0); } // ************************************************************************************* // ************************************************************************************* int yuvcorrect_luminance_treatment (frame_t * frame, yuv_correction_t * yuv_correct) { // This function corrects the luminance of input uint8_t *u_c_p; uint32_t i; u_c_p = frame->y; // Luminance (Y component) for (i = 0; i < frame->nb_y; i++) *(u_c_p+i) = yuv_correct->luminance[*(u_c_p+i)]; return (0); } // ************************************************************************************* // ************************************************************************************* int yuvcorrect_chrominance_treatment (frame_t * frame, yuv_correction_t * yuv_correct) { // This function corrects the chrominance of input uint8_t *Uu_c_p, *Vu_c_p; uint32_t i, base; // mjpeg_debug("Start of yuvcorrect_chrominance_treatment(%p, %lu, %p)",input,size,UVchroma); Uu_c_p = frame->u; Vu_c_p = frame->v; // Chroma for (i = 0; i < frame->nb_uv; i++) { base = ((((uint32_t) * Uu_c_p) << 8) + (*Vu_c_p)) << 1; // base = ((((uint32_t)*Uu_c_p) * 256) + (*Vu_c_p)) * 2 *(Uu_c_p++) = yuv_correct->chrominance[base++]; *(Vu_c_p++) = yuv_correct->chrominance[base]; } // mjpeg_debug("End of yuvcorrect_chrominance_treatment"); return (0); } // ************************************************************************************* // ************************************************************************************* int bottom_field_storage (frame_t * frame, uint8_t oddeven, uint8_t * field1, uint8_t * field2) { int ligne; uint8_t *u_c_p; // This function stores the current bottom field into tabular field[1 or 2] u_c_p = frame->y; u_c_p += frame->y_width; // first pixel of the bottom field if (oddeven) { // field1 // Y Component for (ligne = 0; ligne < frame->y_height; ligne += 2) { memcpy (field1, u_c_p, frame->y_width); u_c_p += (frame->y_width << 1); field1 += frame->y_width; } u_c_p -= frame->y_width; u_c_p += frame->uv_width; // U and V COMPONENTS for (ligne = 0; ligne < (frame->uv_height << 1); ligne += 2) { memcpy (field1, u_c_p, frame->uv_width); u_c_p += (frame->uv_width << 1); field1 += frame->uv_width; } } else { // field2 // Y Component for (ligne = 0; ligne < frame->y_height; ligne += 2) { memcpy (field2, u_c_p, frame->y_width); u_c_p += (frame->y_width << 1); field2 += frame->y_width; } u_c_p -= frame->y_width; u_c_p += frame->uv_width; // U and V COMPONENTS for (ligne = 0; ligne < (frame->uv_height << 1); ligne += 2) { memcpy (field2, u_c_p, frame->uv_width); u_c_p += (frame->uv_width << 1); field2 += frame->uv_width; } } return (0); } // ************************************************************************************* // ************************************************************************************* int top_field_storage (frame_t * frame, uint8_t oddeven, uint8_t * field1, uint8_t * field2) { int ligne; uint8_t *u_c_p; // This function stores the current bottom field into tabular field[1 or 2] u_c_p = frame->y; if (oddeven) { // field1 // Y Component for (ligne = 0; ligne < frame->y_height; ligne += 2) { memcpy (field1, u_c_p, frame->y_width); u_c_p += (frame->y_width << 1); field1 += frame->y_width; } // U and V COMPONENTS for (ligne = 0; ligne < (frame->uv_height << 1); ligne += 2) { memcpy (field1, u_c_p, frame->uv_width); u_c_p += (frame->uv_width << 1); field1 += frame->uv_width; } } else { // field2 // Y Component for (ligne = 0; ligne < frame->y_height; ligne += 2) { memcpy (field2, u_c_p, frame->y_width); u_c_p += (frame->y_width << 1); field2 += frame->y_width; } // U and V COMPONENTS for (ligne = 0; ligne < (frame->uv_height << 1); ligne += 2) { memcpy (field2, u_c_p, frame->uv_width); u_c_p += (frame->uv_width << 1); field2 += frame->uv_width; } } return (0); } // ************************************************************************************* // ************************************************************************************* int bottom_field_replace (frame_t * frame, uint8_t oddeven, uint8_t * field1, uint8_t * field2) { int ligne; uint8_t *u_c_p; // This function replaces the current bottom field with tabular field[1 or 2] u_c_p = frame->y; u_c_p += frame->y_width; if (oddeven) { // field2 // Y Component for (ligne = 0; ligne < frame->y_height; ligne += 2) { memcpy (u_c_p, field2, frame->y_width); u_c_p += (frame->y_width << 1); field2 += frame->y_width; } u_c_p -= frame->y_width; u_c_p += frame->uv_width; // U and V COMPONENTS for (ligne = 0; ligne < (frame->uv_height << 1); ligne += 2) { memcpy (u_c_p, field2, frame->uv_width); u_c_p += (frame->uv_width << 1); field2 += frame->uv_width; } } else { // field1 // Y Component for (ligne = 0; ligne < frame->y_height; ligne += 2) { memcpy (u_c_p, field1, frame->y_width); u_c_p += (frame->y_width << 1); field1 += frame->y_width; } u_c_p -= frame->y_width; u_c_p += frame->uv_width; // U and V COMPONENTS for (ligne = 0; ligne < (frame->uv_height << 1); ligne += 2) { memcpy (u_c_p, field1, frame->uv_width); u_c_p += (frame->uv_width << 1); field1 += frame->uv_width; } } return (0); } // ************************************************************************************* // ************************************************************************************* int top_field_replace (frame_t * frame, uint8_t oddeven, uint8_t * field1, uint8_t * field2) { int ligne; uint8_t *u_c_p; // This function replaces the current bottom field with tabular field[1 or 2] u_c_p = frame->y; if (oddeven) { // field2 // Y Component for (ligne = 0; ligne < frame->y_height; ligne += 2) { memcpy (u_c_p, field2, frame->y_width); u_c_p += (frame->y_width << 1); field2 += frame->y_width; } // U and V COMPONENTS for (ligne = 0; ligne < (frame->uv_height << 1); ligne += 2) { memcpy (u_c_p, field2, frame->uv_width); u_c_p += (frame->uv_width << 1); field2 += frame->uv_width; } } else { // field1 // Y Component for (ligne = 0; ligne < frame->y_height; ligne += 2) { memcpy (u_c_p, field1, frame->y_width); u_c_p += (frame->y_width << 1); field1 += frame->y_width; } // U and V COMPONENTS for (ligne = 0; ligne < (frame->uv_height << 1); ligne += 2) { memcpy (u_c_p, field1, frame->uv_width); u_c_p += (frame->uv_width << 1); field1 += frame->uv_width; } } return (0); } // ************************************************************************************* // ************************************************************************************* void yuvstat (frame_t * frame) { uint8_t y, u, v; uint8_t *input; int16_t r, g, b; unsigned long int somme_y = 0, somme_u = 0, somme_v = 0, moy_y = 0, moy_u = 0, moy_v = 0; unsigned long int somme_r = 0, somme_g = 0, somme_b = 0, moy_r = 0, moy_g = 0, moy_b = 0; uint16_t histo_y[256], histo_u[256], histo_v[256]; uint16_t histo_r[256], histo_g[256], histo_b[256]; unsigned long int i; unsigned long int decalage = frame->nb_uv; unsigned long int decalage_y_u = decalage << 2; unsigned long int decalage_y_v = decalage * 5; input = frame->y; for (i = 0; i < 256; i++) { histo_y[i] = histo_u[i] = histo_v[i] = 0; histo_r[i] = histo_g[i] = histo_b[i] = 0; } for (i = 0; i < decalage; i++) { y = input[i * 4]; u = input[i + decalage_y_u]; v = input[i + decalage_y_v]; histo_y[y]++; histo_u[u]++; histo_v[v]++; r = (int) y + (int) floor (1.375 * (float) (v - 128)); g = (int) y + (int) floor (-0.698 * (v - 128) - 0.336 * (u - 128)); b = (int) y + (int) floor (1.732 * (float) (u - 128)); histo_r[clip_0_255 (r)]++; histo_g[clip_0_255 (g)]++; histo_b[clip_0_255 (b)]++; } mjpeg_info ("Histogramme\ni Y U V"); for (i = 0; i < 256; i++) { mjpeg_info ("%03lu %05u %05u %05u", i, histo_y[i], histo_u[i], histo_v[i]); somme_y += histo_y[i]; somme_u += histo_u[i]; somme_v += histo_v[i]; } i = 0; while (moy_y < somme_y / 2) moy_y += histo_y[i++]; moy_y = i; i = 0; while (moy_u < somme_u / 2) moy_u += histo_u[i++]; moy_u = i; i = 0; while (moy_v < somme_v / 2) moy_v += histo_v[i++]; moy_v = i; mjpeg_info ("moyY=%03lu moyU=%03lu moyV=%03lu", moy_y, moy_u, moy_v); mjpeg_info ("sommes = %06lu %06lu %06lu", somme_y, somme_u, somme_v); mjpeg_info ("Histogramme\ni R G B"); for (i = 0; i < 256; i++) { mjpeg_info ("%03lu %05u %05u %05u", i, histo_r[i], histo_g[i], histo_b[i]); somme_r += histo_r[i]; somme_g += histo_g[i]; somme_b += histo_b[i]; } mjpeg_info ("sommes = %06lu %06lu %06lu", somme_r, somme_g, somme_b); i = 0; while (moy_r < somme_r / 2) moy_r += histo_r[i++]; moy_r = i; i = 0; while (moy_g < somme_g / 2) moy_g += histo_g[i++]; moy_g = i; i = 0; while (moy_b < somme_b / 2) moy_b += histo_b[i++]; moy_b = i; mjpeg_info ("moyR=%03lu moyG=%03lu moyB=%03lu", moy_r, moy_g, moy_b); } // ************************************************************************************* // ************************************************************************************* uint8_t clip_0_255 (int16_t number) { if (number <= 0) return (0); else { if (number >= 255) return (255); else return ((uint8_t) number); } mjpeg_error_exit1 ("function clip_0_255 failed!!!"); } // ************************************************************************************* // ************************************************************************************* int8_t clip_127_127 (int16_t number) { if (number <= -127) return (-127); else { if (number >= 127) return (127); else return ((int8_t) number); } mjpeg_error_exit1 ("function clip_127_127 failed!!!"); } // ************************************************************************************* // ************************************************************************************* int yuvcorrect_RGB_init (rgb_correction_t * rgb_correct) { int i; unsigned char *u_c_p; int8_t *si; int16_t *sii; // Filling in R vector u_c_p = rgb_correct->new_red; for (i = 0; i < 256+(OFFSET<<1); i++) { if ((i-OFFSET) <= rgb_correct->InputRmin) *(u_c_p++) = rgb_correct->OutputRmin; else { if ((i-OFFSET) >= rgb_correct->InputRmax) *(u_c_p++) = rgb_correct->OutputRmax; else *(u_c_p++) = rgb_correct->OutputRmin + floor (0.5 + pow ((float) ((i-OFFSET) - rgb_correct->InputRmin) / (float) (rgb_correct->InputRmax - rgb_correct->InputRmin), (float) 1 / rgb_correct->RGamma) * (rgb_correct->OutputRmax - rgb_correct->OutputRmin)); } mjpeg_debug ("R[%u]=%u", i, rgb_correct->new_red[i]); } // Filling in G vector u_c_p = rgb_correct->new_green; for (i = 0; i < 256+(OFFSET<<1); i++) { if ((i-OFFSET) <= rgb_correct->InputGmin) *(u_c_p++) = rgb_correct->OutputGmin; else { if ((i-OFFSET) >= rgb_correct->InputGmax) *(u_c_p++) = rgb_correct->OutputGmax; else *(u_c_p++) = rgb_correct->OutputGmin + floor (0.5 + pow ((float) ((i-OFFSET) - rgb_correct->InputGmin) / (float) (rgb_correct->InputGmax - rgb_correct->InputGmin), (float) 1 / rgb_correct->GGamma) * (rgb_correct->OutputGmax - rgb_correct->OutputGmin)); } mjpeg_debug ("G[%u]=%u", i, rgb_correct->new_green[i]); } // Filling in B vector u_c_p = rgb_correct->new_blue; for (i = 0; i < 256+(OFFSET<<1); i++) { if ((i-OFFSET) <= rgb_correct->InputBmin) *(u_c_p++) = rgb_correct->OutputBmin; else { if ((i-OFFSET) >= rgb_correct->InputBmax) *(u_c_p++) = rgb_correct->OutputBmax; else *(u_c_p++) = rgb_correct->OutputBmin + floor (0.5 + pow ((float) ((i-OFFSET) - rgb_correct->InputBmin) / (float) (rgb_correct->InputBmax - rgb_correct->InputBmin), (float) 1 / rgb_correct->BGamma) * (rgb_correct->OutputBmax - rgb_correct->OutputBmin)); } mjpeg_debug ("B[%u]=%u", i, rgb_correct->new_blue[i]); } // Filling the luma_(r,g,b) vectors u_c_p = rgb_correct->luma_r; for (i = 0; i < 256; i++) *(u_c_p++) = clip_0_255 ((int) floor (0.5 + 0.3000 * i)); u_c_p = rgb_correct->luma_g; for (i = 0; i < 256; i++) *(u_c_p++) = clip_0_255 ((int) floor (0.5 + 0.5859 * i)); u_c_p = rgb_correct->luma_b; for (i = 0; i < 256; i++) *(u_c_p++) = clip_0_255 ((int) floor (0.5 + 0.1120 * i)); // Filling the u_(r,g,b) vectors si = rgb_correct->u_r; for (i = 0; i < 256; i++) *(si++) = clip_127_127 ((int) floor (0.5 - 0.1719 * i)); si = rgb_correct->u_g; for (i = 0; i < 256; i++) *(si++) = clip_127_127 ((int) floor (0.5 - 0.3398 * i)); si = rgb_correct->u_b; for (i = 0; i < 256; i++) *(si++) = clip_127_127 ((int) floor (0.5 + 0.5117 * i)); // Filling the v_(r,g,b) vectors si = rgb_correct->v_r; for (i = 0; i < 256; i++) *(si++) = clip_127_127 ((int) floor (0.5 + 0.5117 * i)); si = rgb_correct->v_g; for (i = 0; i < 256; i++) *(si++) = clip_127_127 ((int) floor (0.5 - 0.4297 * i)); si = rgb_correct->v_b; for (i = 0; i < 256; i++) *(si++) = clip_127_127 ((int) floor (0.5 - 0.0820 * i)); // Filling the RUV_v,GUV_u,GUV_v,BUV_u sii = rgb_correct->RUV_v; for (i = 0; i < 256; i++) *(sii++) = clip_127_127 ((int) floor (0.5 + 1.375 * (i - 128))); sii = rgb_correct->GUV_v; for (i = 0; i < 256; i++) *(sii++) = clip_127_127 ((int) floor (0.5 - 0.698 * (i - 128))); sii = rgb_correct->GUV_u; for (i = 0; i < 256; i++) *(sii++) = clip_127_127 ((int) floor (0.5 - 0.336 * (i - 128))); sii = rgb_correct->BUV_u; for (i = 0; i < 256; i++) *(sii++) = clip_127_127 ((int) floor (0.5 + 1.732 * (i - 128))); /* for (i = 0; i < 256; i++) { mjpeg_info("acceleration : %u %u %u %d %d %d %d %d %d", rgb_correct->luma_r[i],rgb_correct->luma_g[i],rgb_correct->luma_b[i], rgb_correct->u_r[i],rgb_correct->u_g[i],rgb_correct->u_b[i], rgb_correct->v_r[i],rgb_correct->v_g[i],rgb_correct->v_b[i]); } */ return (0); } // ************************************************************************************* // ************************************************************************************* int yuvcorrect_RGB_treatment (frame_t * frame, rgb_correction_t * rgb_correct) { // This function corrects the current frame based on RGB corrections // Optimisations : all possible multiplicative operation results are already stored in tables like luma_r,u_r,GUV_u, etc... // TODO Optimisatiion : suppress the necessity of the clip_0_255 function by enlarging concerned tables new_(red,green,blue): from [0:256] to [-256:512] uint8_t *u_p, *v_p, *line1, *line2; uint32_t i, j; int16_t R_UV, G_UV, B_UV; uint8_t moy_r, moy_g, moy_b; uint8_t R1, R2, R3, R4, G1, G2, G3, G4, B1, B2, B3, B4; line1 = frame->y; line2 = line1 + frame->y_width; u_p = frame->u; v_p = frame->v; if (frame->ss_h==2 && frame->ss_v==2) // 4:2:0 { for (i = 0; i < frame->uv_height; i++) { for (j = 0; j < frame->uv_width; j++) { R_UV = rgb_correct->RUV_v[*v_p]; G_UV = rgb_correct->GUV_v[*v_p] + rgb_correct->GUV_u[*u_p]; B_UV = rgb_correct->BUV_u[*u_p]; // mjpeg_info("YUV = %u + %d %d %d = %d %d %d",*line1,R_UV,G_UV,B_UV,(int16_t)*line1+R_UV,(int16_t)*line1+G_UV,(int16_t)*line1+B_UV); // Calculate the value of the four pixels concerned by the single (u,v) values // Upper Left R1 = rgb_correct->new_red [OFFSET + *line1 + R_UV]; G1 = rgb_correct->new_green[OFFSET + *line1 + G_UV]; B1 = rgb_correct->new_blue [OFFSET + *line1 + B_UV]; // Compute new y value // mjpeg_info("line1 = %u %u %u %d",rgb_correct->luma_r[R1],rgb_correct->luma_g[G1],rgb_correct->luma_b[B1],clip_0_255((uint16_t)rgb_correct->luma_r[R1] // +rgb_correct->luma_g[G1]+rgb_correct->luma_b[B1])); *line1++ = clip_0_255 ((uint16_t) rgb_correct->luma_r[R1] + rgb_correct->luma_g[G1] + rgb_correct->luma_b[B1]); R2 = rgb_correct->new_red [OFFSET + *line1 + R_UV]; G2 = rgb_correct->new_green[OFFSET + *line1 + G_UV]; B2 = rgb_correct->new_blue [OFFSET + *line1 + B_UV]; // Compute new y value *line1++ = clip_0_255 ((int16_t) rgb_correct->luma_r[R2] + (int16_t) rgb_correct->luma_g[G2] + (int16_t) rgb_correct->luma_b[B2]); R3 = rgb_correct->new_red [OFFSET + *line2 + R_UV]; G3 = rgb_correct->new_green[OFFSET + *line2 + G_UV]; B3 = rgb_correct->new_blue [OFFSET + *line2 + B_UV]; // Compute new y value *line2++ = clip_0_255 ((int16_t) rgb_correct->luma_r[R3] + (int16_t) rgb_correct->luma_g[G3] + (int16_t) rgb_correct->luma_b[B3]); R4 = rgb_correct->new_red [OFFSET + *line2 + R_UV]; G4 = rgb_correct->new_green[OFFSET + *line2 + G_UV]; B4 = rgb_correct->new_blue [OFFSET + *line2 + B_UV]; // Compute new y value *line2++ = clip_0_255 ((int16_t) rgb_correct->luma_r[R4] + (int16_t) rgb_correct->luma_g[G4] + (int16_t) rgb_correct->luma_b[B4]); moy_r = clip_0_255 (((int16_t) 2 + R1 + R2 + R3 + R4) >> 2); moy_g = clip_0_255 (((int16_t) 2 + G1 + G2 + G3 + G4) >> 2); moy_b = clip_0_255 (((int16_t) 2 + B1 + B2 + B3 + B4) >> 2); // mjpeg_info("B : %u %u %u %u moyennes %u %u %u",B1,B2,B3,B4,moy_r,moy_g,moy_b); *u_p++ = clip_0_255 ((int16_t) 128 + rgb_correct->u_r[moy_r] + rgb_correct->u_g[moy_g] + rgb_correct->u_b[moy_b]); *v_p++ = clip_0_255 ((int16_t) 128 + rgb_correct->v_r[moy_r] + rgb_correct->v_g[moy_g] + rgb_correct->v_b[moy_b]); } line1 += frame->y_width; line2 += frame->y_width; } } else if (frame->ss_h==4 && frame->ss_v==1) // 4:1:1 { for (i = 0; i < frame->uv_height; i++) { for (j = 0; j < frame->uv_width; j++) { R_UV = rgb_correct->RUV_v[*v_p]; G_UV = rgb_correct->GUV_v[*v_p] + rgb_correct->GUV_u[*u_p]; B_UV = rgb_correct->BUV_u[*u_p]; // mjpeg_info("YUV = %u + %d %d %d = %d %d %d",*line1,R_UV,G_UV,B_UV,(int16_t)*line1+R_UV,(int16_t)*line1+G_UV,(int16_t)*line1+B_UV); // Calculate the value of the four pixels concerned by the single (u,v) values // Upper Left R1 = rgb_correct->new_red [OFFSET + *line1 + R_UV]; G1 = rgb_correct->new_green[OFFSET + *line1 + G_UV]; B1 = rgb_correct->new_blue [OFFSET + *line1 + B_UV]; // Compute new y value // mjpeg_info("line1 = %u %u %u %d",rgb_correct->luma_r[R1],rgb_correct->luma_g[G1],rgb_correct->luma_b[B1],clip_0_255((uint16_t)rgb_correct->luma_r[R1] // +rgb_correct->luma_g[G1]+rgb_correct->luma_b[B1])); *line1++ = clip_0_255 ((uint16_t) rgb_correct->luma_r[R1] + rgb_correct->luma_g[G1] + rgb_correct->luma_b[B1]); R2 = rgb_correct->new_red [OFFSET + *line1 + R_UV]; G2 = rgb_correct->new_green[OFFSET + *line1 + G_UV]; B2 = rgb_correct->new_blue [OFFSET + *line1 + B_UV]; // Compute new y value *line1++ = clip_0_255 ((int16_t) rgb_correct->luma_r[R2] + (int16_t) rgb_correct->luma_g[G2] + (int16_t) rgb_correct->luma_b[B2]); R3 = rgb_correct->new_red [OFFSET + *line1 + R_UV]; G3 = rgb_correct->new_green[OFFSET + *line1 + G_UV]; B3 = rgb_correct->new_blue [OFFSET + *line1 + B_UV]; // Compute new y value *line1++ = clip_0_255 ((int16_t) rgb_correct->luma_r[R3] + (int16_t) rgb_correct->luma_g[G3] + (int16_t) rgb_correct->luma_b[B3]); R4 = rgb_correct->new_red [OFFSET + *line1 + R_UV]; G4 = rgb_correct->new_green[OFFSET + *line1 + G_UV]; B4 = rgb_correct->new_blue [OFFSET + *line1 + B_UV]; // Compute new y value *line1++ = clip_0_255 ((int16_t) rgb_correct->luma_r[R4] + (int16_t) rgb_correct->luma_g[G4] + (int16_t) rgb_correct->luma_b[B4]); moy_r = clip_0_255 (((int16_t) 2 + R1 + R2 + R3 + R4) >> 2); moy_g = clip_0_255 (((int16_t) 2 + G1 + G2 + G3 + G4) >> 2); moy_b = clip_0_255 (((int16_t) 2 + B1 + B2 + B3 + B4) >> 2); // mjpeg_info("B : %u %u %u %u moyennes %u %u %u",B1,B2,B3,B4,moy_r,moy_g,moy_b); *u_p++ = clip_0_255 ((int16_t) 128 + rgb_correct->u_r[moy_r] + rgb_correct->u_g[moy_g] + rgb_correct->u_b[moy_b]); *v_p++ = clip_0_255 ((int16_t) 128 + rgb_correct->v_r[moy_r] + rgb_correct->v_g[moy_g] + rgb_correct->v_b[moy_b]); } } } else if (frame->ss_h==2 && frame->ss_v==1) // 4:2:2 { for (i = 0; i < frame->uv_height; i++) { for (j = 0; j < frame->uv_width; j++) { R_UV = rgb_correct->RUV_v[*v_p]; G_UV = rgb_correct->GUV_v[*v_p] + rgb_correct->GUV_u[*u_p]; B_UV = rgb_correct->BUV_u[*u_p]; // mjpeg_info("YUV = %u + %d %d %d = %d %d %d",*line1,R_UV,G_UV,B_UV,(int16_t)*line1+R_UV,(int16_t)*line1+G_UV,(int16_t)*line1+B_UV); // Calculate the value of the two pixels concerned by the single (u,v) values // Upper Left R1 = rgb_correct->new_red [OFFSET + *line1 + R_UV]; G1 = rgb_correct->new_green[OFFSET + *line1 + G_UV]; B1 = rgb_correct->new_blue [OFFSET + *line1 + B_UV]; // Compute new y value // mjpeg_info("line1 = %u %u %u %d",rgb_correct->luma_r[R1],rgb_correct->luma_g[G1],rgb_correct->luma_b[B1],clip_0_255((uint16_t)rgb_correct->luma_r[R1] // +rgb_correct->luma_g[G1]+rgb_correct->luma_b[B1])); *line1++ = clip_0_255 ((uint16_t) rgb_correct->luma_r[R1] + rgb_correct->luma_g[G1] + rgb_correct->luma_b[B1]); R2 = rgb_correct->new_red [OFFSET + *line1 + R_UV]; G2 = rgb_correct->new_green[OFFSET + *line1 + G_UV]; B2 = rgb_correct->new_blue [OFFSET + *line1 + B_UV]; // Compute new y value *line1++ = clip_0_255 ((int16_t) rgb_correct->luma_r[R2] + (int16_t) rgb_correct->luma_g[G2] + (int16_t) rgb_correct->luma_b[B2]); moy_r = clip_0_255 (((int16_t) 1 + R1 + R2) >> 1); moy_g = clip_0_255 (((int16_t) 1 + G1 + G2) >> 1); moy_b = clip_0_255 (((int16_t) 1 + B1 + B2) >> 1); // mjpeg_info("B : %u %u %u %u moyennes %u %u %u",B1,B2,B3,B4,moy_r,moy_g,moy_b); *u_p++ = clip_0_255 ((int16_t) 128 + rgb_correct->u_r[moy_r] + rgb_correct->u_g[moy_g] + rgb_correct->u_b[moy_b]); *v_p++ = clip_0_255 ((int16_t) 128 + rgb_correct->v_r[moy_r] + rgb_correct->v_g[moy_g] + rgb_correct->v_b[moy_b]); } } } else if (frame->ss_h==1 && frame->ss_v==1) // 4:4:4 { for (i = 0; i < frame->uv_height; i++) { for (j = 0; j < frame->uv_width; j++) { R_UV = rgb_correct->RUV_v[*v_p]; G_UV = rgb_correct->GUV_v[*v_p] + rgb_correct->GUV_u[*u_p]; B_UV = rgb_correct->BUV_u[*u_p]; // mjpeg_info("YUV = %u + %d %d %d = %d %d %d",*line1,R_UV,G_UV,B_UV,(int16_t)*line1+R_UV,(int16_t)*line1+G_UV,(int16_t)*line1+B_UV); // here we have 1-1 correspondence between RGB and YUV R1 = rgb_correct->new_red [OFFSET + *line1 + R_UV]; G1 = rgb_correct->new_green[OFFSET + *line1 + G_UV]; B1 = rgb_correct->new_blue [OFFSET + *line1 + B_UV]; // Compute new y value // mjpeg_info("line1 = %u %u %u %d",rgb_correct->luma_r[R1],rgb_correct->luma_g[G1],rgb_correct->luma_b[B1],clip_0_255((uint16_t)rgb_correct->luma_r[R1] // +rgb_correct->luma_g[G1]+rgb_correct->luma_b[B1])); *line1++ = clip_0_255 ((uint16_t) rgb_correct->luma_r[R1] + rgb_correct->luma_g[G1] + rgb_correct->luma_b[B1]); *u_p++ = clip_0_255 ((int16_t) 128 + rgb_correct->u_r[R1] + rgb_correct->u_g[G1] + rgb_correct->u_b[B1]); *v_p++ = clip_0_255 ((int16_t) 128 + rgb_correct->v_r[R1] + rgb_correct->v_g[G1] + rgb_correct->v_b[B1]); } } } else mjpeg_error_exit1 ("Sorry, RGB corrections not supported with that chroma subsampling"); return (0); } // ************************************************************************************* /* * Local variables: * tab-width: 8 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/yuvcorrect/Makefile.am0000644000175000017500000000105311736012535020454 0ustar glowwormglowworm# Makefile for yuvcorrect MAINTAINERCLEANFILES = Makefile.in AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/utils LIBMJPEGUTILS = $(top_builddir)/utils/libmjpegutils.la if HAVE_ALTIVEC LIBMJPEGUTILS += $(top_builddir)/mpeg2enc/libmpeg2encpp.la endif bin_PROGRAMS = yuvcorrect yuvcorrect_tune noinst_HEADERS = yuvcorrect.h yuvcorrect_SOURCES = yuvcorrect.c yuvcorrect_functions.c yuvcorrect_LDADD = $(LIBMJPEGUTILS) $(LIBM_LIBS) yuvcorrect_tune_SOURCES = yuvcorrect_tune.c yuvcorrect_functions.c yuvcorrect_tune_LDADD = $(LIBMJPEGUTILS) $(LIBM_LIBS) mjpegtools-2.1.0/yuvcorrect/yuvcorrect.c0000644000175000017500000004007512216627211020775 0ustar glowwormglowworm/* * yuvcorrect.c * Copyright (C) 2002 Xavier Biquard * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ // September/October 2002: First version #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include "yuv4mpeg.h" #include "yuvcorrect.h" extern const uint16_t OFFSET; extern const uint16_t ALIGNENEMENT; extern const char *legal_opt_flags; const char PIPE[] = "PIPE"; const char STAT[] = "STAT"; const char FULL[] = "FULL"; const char HALF[] = "HALF"; const char TOP_FIRST[] = "INTERLACED_TOP_FIRST"; const char BOT_FIRST[] = "INTERLACED_BOTTOM_FIRST"; const char NOT_INTER[] = "NOT_INTERLACED"; const char PROGRESSIVE[] = "PROGRESSIVE"; const char LINESWITCH[] = "LINE_SWITCH"; const char NO_HEADER[] = "NO_HEADER"; const char TOP_FORWARD[] = "TOP_FORWARD"; const char BOTT_FORWARD[] = "BOTT_FORWARD"; const char RGBFIRST[] = "RGBFIRST"; // Prototypes specific to yuvcorrect void yuvcorrect_print_usage (void); void yuvcorrect_print_information (general_correction_t * gen_correct, yuv_correction_t * yuv_correct, rgb_correction_t * rgb_correct); void yuvcorrect_handle_args (int argc, char *argv[], overall_t * overall, general_correction_t * gen_correct); void yuvcorrect_print_usage (void) { fprintf (stderr, "usage: yuvcorrect -M [mode_keyword] -T [general_keyword] -Y [yuv_keyword] -R [RGB_keyword] [-v 0-2] [-h]\n" "yuvcorrect applies different corrections related to interlacing and color\n" "to yuv frames coming from stdin (in yuv4MPEG 4:2:0 format) to stdout.\n" "In contrast to yuvscaler, frame size is kept constant.\n" "\n" "yuvcorrect is keyword driven :\n" "\t -M for keyword concerning the correction MODE of yuvcorrect\n" "\t -T for keyword concerning spatial, temporal or header corrections to be applied\n" "\t -Y for keyword concerning color corrections in the yuv space\n" "\t -R for keyword concerning color corrections in the RGB space\n" "By default, yuvcorrect will not modify frames and simply act as a pass-through. Also, it will apply\n" "YUV corrections first and then RGB corrections\n" "\n" "Possible mode keyword are:\n" "\t STAT to have yuvcorrect print statistical information on your frames _before_ corrections\n" "\t RGBFIRST to have yuvcorrect apply RGB corrections first, then YUV corrections\n" "\n" "Possible general keyword are:\n" "\t If you suspect that your video capture was given a wrong interlacing type,\n" "\t and/or was spatially or temporarly missed up, please use and combine:\n" "\t INTERLACED_TOP_FIRST to correct file header by specifying top_field_first as interlacing type\n" "\t INTERLACED_BOTTOM_FIRST to correct file header by specifying bottom_field_first as interlacing\n" "\t NOT_INTERLACED to correct file header by specifying not-interlaced/progressive as interlacing type\n" "\t PROGRESSIVE to correct file header by specifying not-interlaced/progressive as interlacing type\n" "\t NO_HEADER to suppress stream header generation (apply different corrections to different part of an input file)\n" "\t LINE_SWITCH to switch lines two by two\n" "\t BOTT_FORWARD to move the bottom field one frame forward\n" "\t TOP_FORWARD to move the top field one frame forward\n" "\n" "Possible yuv keywords are:\n" "\t LUMINANCE_Gamma_InputYmin_InputYmax_OutputYmin_OutputYmax or\n" "\t Y_Gamma_InputYmin_InputYmax_OutputYmin_OutputYmax\n" "\t to correct the input frame luminance by clipping it inside range [InputYmin;InputYmax],\n" "\t scale with power (1/Gamma), and expand/shrink/shift it to [OutputYmin;OutputYmax]\n" "\t CHROMINANCE_UVrotation_Ufactor_Urotcenter_Vfactor_Vrotcenter_UVmin_UVmax or\n" "\t UV_UVrotation_Ufactor_Urotcenter_Vfactor_Vrotcenter_UVmin_UVmax\n" "\t to rotate rescaled UV chroma components Ufactor*(U-Urotcenter) and Vfactor*(V-Vrotcenter)\n" "\t by (float) UVrotation degrees, recenter to the normalize (128,128) center,\n" "\t and _clip_ the result to range [UVmin;UVmax]\n" "\t CONFORM to have yuvcorrect generate frames conform to the Rec.601 specification for Y'CbCr frames\n" "\t that is LUMINANCE_1.0_16_235_16_235 and CHROMINANCE_0.0_1.0_128_1.0_128_16_240\n" "\n" "\t Possible RGB keywords are:\n" "\t R_Gamma_InputRmin_InputRmax_OutputRmin_OutputRmax\n" "\t G_Gamma_InputGmin_InputGmax_OutputGmin_OutputGmax\n" "\t B_Gamma_InputBmin_InputBmax_OutputBmin_OutputBmax\n" "\t to correct the input frame RGB color by clipping it inside range [InputRGBmin;InputRGBmax],\n" "\t scale with power (1/Gamma), and expand/shrink/shift it to [OutputRGBmin;OutputRGBmax]\n" "\n" "-v Specifies the degree of verbosity: 0=quiet, 1=normal, 2=verbose/debug\n" "-h : print this lot!\n"); exit (1); } void handle_args_overall (int argc, char *argv[], overall_t * overall) { int c, verb; while ((c = getopt (argc, argv, legal_opt_flags)) != -1) { switch (c) { case 'v': verb = atoi (optarg); if (verb < 0 || verb > 2) { mjpeg_info ("Verbose level must be 0, 1 or 2 ! => resuming to default 1"); } else { overall->verbose = verb; } break; case 'h': yuvcorrect_print_usage (); break; default: break; } } if (optind != argc) yuvcorrect_print_usage (); } void yuvcorrect_handle_args (int argc, char *argv[], overall_t * overall, general_correction_t * gen_correct) { // This function handles argument passing on the command line int c; int k_mode, k_general; // Ne pas oublier de mettre la putain de ligne qui suit, sinon, plus d'argument à la lign de commande, ils auront été bouffés par l'appel précédnt à getopt!! optind = 1; while ((c = getopt (argc, argv, legal_opt_flags)) != -1) { switch (c) { // ************** // MODE KEYOWRD // ************* case 'M': k_mode = 0; if (strcmp (optarg, STAT) == 0) { k_mode = 1; overall->stat = 1; } if (strcmp (optarg, RGBFIRST) == 0) { k_mode = 1; overall->rgbfirst = 1; } if (k_mode == 0) mjpeg_error_exit1 ("Unrecognized MODE keyword: %s", optarg); break; // ************* // ************** // GENERAL KEYOWRD // ************* case 'T': k_general = 0; if (strcmp (optarg, TOP_FIRST) == 0) { k_general = 1; y4m_si_set_interlace (&gen_correct->streaminfo, Y4M_ILACE_TOP_FIRST); } if (strcmp (optarg, BOT_FIRST) == 0) { k_general = 1; y4m_si_set_interlace (&gen_correct->streaminfo, Y4M_ILACE_BOTTOM_FIRST); } if ((strcmp (optarg, NOT_INTER) == 0) || (strcmp (optarg, PROGRESSIVE) == 0)) { k_general = 1; y4m_si_set_interlace (&gen_correct->streaminfo, Y4M_ILACE_NONE); } if (strcmp (optarg, NO_HEADER) == 0) { k_general = 1; gen_correct->no_header = 1; } if (strcmp (optarg, LINESWITCH) == 0) { k_general = 1; gen_correct->line_switch = 1; } if (strcmp (optarg, BOTT_FORWARD) == 0) { k_general = 1; gen_correct->field_move = 1; } if (strcmp (optarg, TOP_FORWARD) == 0) { k_general = 1; gen_correct->field_move = -1; } if (k_general == 0) mjpeg_error_exit1 ("Unrecognized GENERAL keyword: %s", optarg); break; // ************* default: break; } } } void yuvcorrect_print_information (general_correction_t * gen_correct, yuv_correction_t * yuv_correct, rgb_correction_t * rgb_correct) { // This function print USER'S INFORMATION y4m_log_stream_info (mjpeg_loglev_t("info"), "input: ", &gen_correct->streaminfo); switch (gen_correct->line_switch) { case 0: mjpeg_info ("no line switching"); break; case 1: mjpeg_info ("with line switching"); break; default: mjpeg_error_exit1 ("Unknown line switching status: %d", gen_correct->line_switch); } switch (gen_correct->field_move) { case 0: mjpeg_info ("no time forwarding"); break; case 1: mjpeg_info ("with bottom field one frame forward"); break; case -1: mjpeg_info ("with top field one frame forward"); break; default: mjpeg_error_exit1 ("Unknown time reordering status: %d", gen_correct->field_move); } switch (yuv_correct->luma) { case 0: mjpeg_info ("Without luminance correction"); break; case 1: mjpeg_info ("With luminance correction"); break; default: mjpeg_error_exit1 ("Unknown luminance correction status %u", yuv_correct->luma); } switch (yuv_correct->chroma) { case 0: mjpeg_info ("Without chrominance correction"); break; case 1: mjpeg_info ("With chrominance correction"); break; default: mjpeg_error_exit1 ("Unknown chrominance correction status %u", yuv_correct->chroma); } switch (rgb_correct->rgb) { case 0: mjpeg_info ("Without rgb correction"); break; case 1: mjpeg_info ("With rgb correction"); break; default: mjpeg_error_exit1 ("Unknown rgb correction status %u", rgb_correct->rgb); } } int main (int argc, char *argv[]) { // Defining yuvcorrect dedicated structures (see yuvcorrect.h) overall_t *overall=NULL; frame_t *frame=NULL; general_correction_t *gen_correct=NULL; yuv_correction_t *yuv_correct=NULL; rgb_correction_t *rgb_correct=NULL; int err = Y4M_OK; uint8_t oddeven; unsigned long int frame_num = 0; y4m_accept_extensions(1); // START OF INITIALISATION // yuvcorrect overall structure initialisation if (!(overall = (overall_t *) malloc (sizeof (overall_t)))) mjpeg_error_exit1 ("Could not allocate memory for overall structure pointer"); overall->verbose = 1; overall->mode = overall->stat = overall->rgbfirst = 0; handle_args_overall (argc, argv, overall); mjpeg_default_handler_verbosity (overall->verbose); mjpeg_debug ("Start of initialisation"); // yuvcorrect general_correction_t structure initialisations if (!(gen_correct = (general_correction_t *) malloc (sizeof (general_correction_t)))) mjpeg_error_exit1 ("Could not allocate memory for gen_correct structure pointer"); // yuvcorrect frame_t structure initialisations if (!(frame = (frame_t *) malloc (sizeof (frame_t)))) mjpeg_error_exit1 ("Could not allocate memory for frame structure pointer"); // yuvcorrect yuv_correction_t structure initialisation if (!(yuv_correct = (yuv_correction_t *) malloc (sizeof (yuv_correction_t)))) mjpeg_error_exit1 ("Could not allocate memory for yuv_correct structure pointer"); // rgbcorrect rgb_correction_t structure initialisation if (!(rgb_correct = (rgb_correction_t *) malloc (sizeof (rgb_correction_t)))) mjpeg_error_exit1 ("Could not allocate memory for rgb_correct structure pointer"); initialisation1(0,frame,gen_correct,yuv_correct,rgb_correct); // Deal with args handle_args_yuv_rgb (argc, argv, yuv_correct, rgb_correct); yuvcorrect_handle_args (argc, argv, overall, gen_correct); // Further initialisations depending on the stream itself // General correction initialisations if (gen_correct->field_move != 0) { if (!(frame->field1 = (uint8_t *) malloc ((frame->length >> 1)*sizeof(uint8_t))) || !(frame->field2 = (uint8_t *) malloc ((frame->length >> 1)*sizeof(uint8_t)))) mjpeg_error_exit1 ("Could not allocate memory for field1 or field2 tables. STOP!"); } initialisation2(yuv_correct,rgb_correct); // USER'S INFORMATION OUTPUT yuvcorrect_print_information (gen_correct, yuv_correct, rgb_correct); mjpeg_debug ("End of Initialisation"); // END OF INITIALISATION // Eventually output file header if (gen_correct->no_header == 0) y4m_write_stream_header (1, &gen_correct->streaminfo); mjpeg_debug ("overall: verbose=%u, mode=%d, stat=%u", overall->verbose, overall->mode, overall->stat); mjpeg_debug ("frame: Y:%ux%u=>%lu UV:%ux%u=>%lu Size=%lu", frame->y_width, frame->y_height, frame->nb_y, frame->uv_width, frame->uv_height, frame->nb_uv, frame->length); mjpeg_debug ("yuv: Gamma=%f, InputYmin=%u, InputYmax=%u, OutputYmin=%u, OutputYmax=%u", yuv_correct->Gamma, yuv_correct->InputYmin, yuv_correct->InputYmax, yuv_correct->OutputYmin, yuv_correct->OutputYmax); // Master loop : continue until there is no next frame in stdin while ((err = yuvcorrect_y4m_read_frame (0, &gen_correct->streaminfo, frame, gen_correct->line_switch)) == Y4M_OK) { if (overall->stat == 1) yuvstat (frame); mjpeg_info ("Frame number %ld", frame_num); // Time reordering if (gen_correct->field_move != 0) { oddeven = frame_num & (unsigned long int) 1; // oddeven = frame_num % 2, fast implementation if (gen_correct->field_move == 1) { // Bottom field one frame forward if (frame_num == 0) { bottom_field_storage (frame, oddeven, frame->field1, frame->field2); if (yuvcorrect_y4m_read_frame (0, &gen_correct->streaminfo, frame, gen_correct->line_switch) != Y4M_OK) mjpeg_error_exit1 ("Can't read frame %ld", frame_num); frame_num++; oddeven = frame_num & (unsigned long int) 1; mjpeg_info ("Frame number %ld", frame_num); } bottom_field_storage (frame, oddeven, frame->field1, frame->field2); bottom_field_replace (frame, oddeven, frame->field1, frame->field2); } else { // Top field one frame forward if (frame_num == 0) { top_field_storage (frame, oddeven, frame->field1, frame->field2); if (yuvcorrect_y4m_read_frame (0, &gen_correct->streaminfo, frame, gen_correct->line_switch) != Y4M_OK) mjpeg_error_exit1 ("Can't read frame %ld", frame_num); frame_num++; oddeven = frame_num & (unsigned long int) 1; mjpeg_info ("Frame number %ld", frame_num); } top_field_storage (frame, oddeven, frame->field1, frame->field2); top_field_replace (frame, oddeven, frame->field1, frame->field2); } } if (overall->rgbfirst == 1) { // RGB correction if (rgb_correct->rgb == 1) yuvcorrect_RGB_treatment (frame, rgb_correct); } // luminance correction if (yuv_correct->luma == 1) yuvcorrect_luminance_treatment (frame, yuv_correct); // chrominance correction if (yuv_correct->chroma == 1) yuvcorrect_chrominance_treatment (frame, yuv_correct); if (overall->rgbfirst != 1) { // RGB correction if (rgb_correct->rgb == 1) yuvcorrect_RGB_treatment (frame, rgb_correct); } // Output Frame Header if (y4m_write_frame_header (1, &gen_correct->streaminfo, &frame->info) != Y4M_OK) goto out_error; // Output Frame content if (y4m_write (1, frame->y, frame->length) != Y4M_OK) goto out_error; frame_num++; } // End of master loop => no more frame in stdin if (err != Y4M_ERR_EOF) mjpeg_error_exit1 ("Couldn't read frame number %ld!", frame_num); else mjpeg_info ("Normal exit: end of stream with frame number %ld!", frame_num); y4m_fini_stream_info (&gen_correct->streaminfo); y4m_fini_frame_info (&frame->info); return 0; out_error: mjpeg_error_exit1 ("Unable to write to output - aborting!"); return 1; } /* * Local variables: * tab-width: 8 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/yuvcorrect/yuvcorrect_tune.c0000644000175000017500000011526710324007173022033 0ustar glowwormglowworm/* * yuvcorrect_tune.c * Copyright (C) 2002 Xavier Biquard * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ // September/October 2002: First version // November: RGB corrections available as well as image splitting // TODO: // S, D and Q keystrokes #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include "yuv4mpeg.h" #include "yuvcorrect.h" #define yuvcorrect_tune_VERSION "26-11-2002" // For pointer adress alignement extern const uint16_t ALIGNEMENT; // 16 bytes alignement for mmx registers in SIMD instructions for Pentium extern const char *legal_opt_flags; const float gamma_increment=0.01; const char FULL[] = "FULL"; const char HALF_LEFT[] = "HALF_LEFT"; const char HALF_RIGHT[] = "HALF_RIGHT"; const char QUARTER_LEFT[] = "QUARTER_LEFT"; const char QUARTER_RIGHT[] = "QUARTER_RIGHT"; const char TQUARTER_LEFT[] = "3QUARTER_LEFT"; const char TQUARTER_RIGHT[] = "3QUARTER_RIGHT"; const char TOP[] = "TOP"; const char BOTTOM[] = "BOTTOM"; const char RGBFIRST[] = "RGBFIRST"; void yuvcorrect_tune_print_usage (void); void add_reference_part(frame_t *frame,uint8_t *final_ref,uint8_t type); void yuvcorrect_tune_handle_args (int argc, char *argv[], overall_t *overall, general_correction_t *gen_correct); // ************************************************************************************* void yuvcorrect_tune_print_usage (void) { fprintf (stderr, "usage: yuvcorrect_tune -I -F -M [mode_keyword] -Y [yuv_keyword] -R [RGB_keyword] [-v 0-2] [-h]\n" "yuvcorrect_tune is an interactive tool enabling you to interactively tune different\n" "corrections related to interlacing, luminance and color. defines the uncorrected\n" "reference yuv frames (in yuv4MPEG 4:2:0 format)\n" "Typical use is 'lav2yuv -f 1 > frame ; cat fifo | yuvplay ; yuvcorrect_tune -I frame > fifo' \n" "\n" "yuvcorrect_tune is keyword driven :\n" "\t -I \n" "\t -F (optional)\n" "\t -M for keyword concerning the correction MODE of yuvcorrect_tune\n" "\t -Y for keyword concerning color corrections in the YUV space\n" "\t -R for keyword concerning color corrections in the RGB space\n" "\n" "\t Yuvcorrect_tune uses _only_ the first frame it reads from and all corrections defined on command\n" "\t line will then be applied to this frame to generate the image frame.\n" "\t It is to this image frame that color corrections will be applied, as defined by succesive keystrokes\n" "\t on the keyboard. By default, the resulting corrected frame is then outputted to stdout.\n" "\t But - using mode keywords - part of this corrected frame may be replaced by the corresponding part of a\n" "\t Ref frame (-F keyword) like colorbars, thus enabling to visually adjust correction to match the reference frame.\n" "\n" "Possible mode keyword are:\n" "\t FULL (default)\n" "\t HALF_LEFT The generated frame is now constituted of two different parts:\n" "\t the left half shows the final reference uncorrected while the right half shows it corrected\n" "\t HALF_RIGHT Same as HALF_LEFT except right and left are inversed\n" "\t QUARTER_LEFT Same as HALF_LEFT except the uncorrected part is only a quarter of the image\n" "\t QUARTER_RIGHT Same as HALF_RIGHT except the uncorrected part is only a quarter of the image\n" "\t 3QUARTER_LEFT The left three quarters of the image is uncorrected, the right quarter corrected\n" "\t 3QUARTER_RIGHT The right three quarters of the image is uncorrected, the left quarter corrected\n" "\t TOP the top half is uncorrected, the bottom half is corrected\n" "\t BOTTOM the bottom half is uncorrected, the top half is corrected\n" "\t RGBFIRST to have yuvcorrect_tune apply RGB corrections first, then YUV corrections\n" "\n" "Possible yuv keywords are:\n" "\t LUMINANCE_Gamma_InputYmin_InputYmax_OutputYmin_OutputYmax\n" "\t Y_Gamma_InputYmin_InputYmax_OutputYmin_OutputYmax\n" "\t to correct the input frame luminance by clipping it inside range [InputYmin;InputYmax],\n" "\t scale with power (1/Gamma), and expand/shrink/shift it to [OutputYmin;OutputYmax]\n" "\t CHROMINANCE_UVrotation_Ufactor_Urotcenter_Vfactor_Vrotcenter_UVmin_UVmax\n" "\t UV_UVrotation_Ufactor_Urotcenter_Vfactor_Vrotcenter_UVmin_UVmax\n" "\t to rotate rescaled UV chroma components Ufactor*(U-Urotcenter) and Vfactor*(V-Vrotcenter)\n" "\t by (float) UVrotation degrees, recenter to the normalize (128,128) center,\n" "\t and _clip_ the result to range [UVmin;UVmax]\n" "\t CONFORM to have yuvcorrect_tune generate frames conform to the Rec.601 specification for Y'CbCr frames\n" "\t that is LUMINANCE_1.0_16_235_16_235 and CHROMINANCE_0.0_1.0_128_1.0_128_16_240\n" "\n" "Possible RGB keywords are:\n" "\t R_Gamma_InputRmin_InputRmax_OutputRmin_OutputRmax\n" "\t G_Gamma_InputGmin_InputGmax_OutputGmin_OutputGmax\n" "\t B_Gamma_InputBmin_InputBmax_OutputBmin_OutputBmax\n" "\t to correct the input frame RGB color by clipping it inside range [InputRGBmin;InputRGBmax],\n" "\t scale with power (1/Gamma), and expand/shrink/shift it to [OutputRGBmin;OutputRGBmax]\n" "\n" "How to use the keyboard:\n" "Pressing Y, U, V, R, G, B or M will tell yuvcorrect_tune that all following keystrokes refer to corrections applied to\n" "Y values, UV values, UV values, R values, G values, B values, Mode of yuvcorrect_tune ; until ESCAPE is pressed\n" "To define corrections, use Capital letter to increase and minor letter to decrease\n" "Gamma values are changed by amount of 0.01, Ufactor and Vfactor by 0.05; UVrotation by amount of 1 degree; Integer values by 1\n" "To modify the 1st, 2nd, 3rd, 4th, 5th, 6th or 7th parameter, use respectively e/E, r/R, t/T, y/Y, u/U, i/I, o/O\n" "To modify yuvcorrect_tune mode, use keypad values 0, 1, 2, 3, 4, 5, 6, 7, 8, 9\n" "For status, press S. To go back to default, press D. To quit, press Q.\n" "-v Specifies the degree of verbosity: 0=quiet, 1=normal, 2=verbose/debug\n" "-h : print this lot!\n"); exit (1); } // ************************************************************************************* // ************************************************************************************* void handle_args_overall (int argc, char *argv[], overall_t *overall) { int c,verb; optind = 1; while ((c = getopt (argc, argv, legal_opt_flags)) != -1) { switch (c) { case 'I': if ((overall->ImgFrame=open(optarg,O_RDONLY))==-1) mjpeg_error_exit1("Unable to open %s!!",optarg); break; case 'F': if ((overall->RefFrame=open(optarg,O_RDONLY))==-1) mjpeg_error_exit1("Unable to open %s!!",optarg); break; case 'v': verb = atoi (optarg); if (verb < 0 || verb > 2) { mjpeg_info ("Verbose level must be 0, 1 or 2 ! => resuming to default 1"); } else { overall->verbose = verb; } break; case 'h': yuvcorrect_tune_print_usage (); break; default: break; } } if ((optind != argc)||(overall->ImgFrame==-1)) yuvcorrect_tune_print_usage (); if (overall->RefFrame==-1) overall->RefFrame=overall->ImgFrame; } // ************************************************************************************* // ************************************************************************************* void yuvcorrect_tune_handle_args (int argc, char *argv[], overall_t *overall, general_correction_t *gen_correct) { // This function handles argument passing on the command line int c; int k_mode; // Ne pas oublier de mettre la putain de ligne qui suit, sinon, plus d'argument à la lign de commande, ils auront été bouffés par l'appel précédnt à getopt!! optind=1; while ((c = getopt (argc, argv, legal_opt_flags)) != -1) { switch (c) { // ************** // MODE KEYOWRD // ************* case 'M': k_mode = 0; if (strcmp (optarg, RGBFIRST) == 0) { k_mode = 1; overall->rgbfirst = 1; } if (strcmp (optarg, FULL) == 0) { k_mode = 1; overall->mode = 0; } if (strcmp (optarg, HALF_LEFT) == 0) { k_mode = 1; overall->mode = 1; } if (strcmp (optarg, HALF_RIGHT) == 0) { k_mode = 1; overall->mode = 2; } if (strcmp (optarg, QUARTER_LEFT) == 0) { k_mode = 1; overall->mode = 3; } if (strcmp (optarg, QUARTER_RIGHT) == 0) { k_mode = 1; overall->mode = 4; } if (strcmp (optarg, TQUARTER_LEFT) == 0) { k_mode = 1; overall->mode = 5; } if (strcmp (optarg, TQUARTER_RIGHT) == 0) { k_mode = 1; overall->mode = 6; } if (strcmp (optarg, TOP) == 0) { k_mode = 1; overall->mode = 7; } if (strcmp (optarg, BOTTOM) == 0) { k_mode = 1; overall->mode = 8; } if (k_mode == 0) mjpeg_error_exit1 ("Unrecognized MODE keyword: %s", optarg); break; // ************* default: break; } } } // ************************************************************************************* // ************************************************************************************* void add_reference_part(frame_t *frame,uint8_t *final_ref,uint8_t type) { uint8_t *u_c_p_frame,*u_c_p_ref; unsigned long int length_y,length_uv,offset3,offset4; uint16_t i; u_c_p_frame=frame->y; u_c_p_ref =final_ref; switch(type+'0') { case '1': // "HALF_LEFT"; length_y=frame->y_width>>1; length_uv=length_y>>1; for (i=0;iy_height;i++,u_c_p_frame+=frame->y_width,u_c_p_ref+=frame->y_width) memcpy(u_c_p_frame,u_c_p_ref,length_y); for (i=0;iuv_height;i++,u_c_p_frame+=frame->uv_width,u_c_p_ref+=frame->uv_width) memcpy(u_c_p_frame,u_c_p_ref,length_uv); for (i=0;iuv_height;i++,u_c_p_frame+=frame->uv_width,u_c_p_ref+=frame->uv_width) memcpy(u_c_p_frame,u_c_p_ref,length_uv); break; case '2': // "HALF_RIGHT"; length_y=frame->y_width>>1; length_uv=length_y>>1; offset3=length_y>>1; u_c_p_frame+=length_y; u_c_p_ref +=length_y; for (i=0;iy_height;i++,u_c_p_frame+=frame->y_width,u_c_p_ref+=frame->y_width) memcpy(u_c_p_frame,u_c_p_ref,length_y); u_c_p_frame-=offset3; u_c_p_ref -=offset3; for (i=0;iuv_height;i++,u_c_p_frame+=frame->uv_width,u_c_p_ref+=frame->uv_width) memcpy(u_c_p_frame,u_c_p_ref,length_uv); for (i=0;iuv_height;i++,u_c_p_frame+=frame->uv_width,u_c_p_ref+=frame->uv_width) memcpy(u_c_p_frame,u_c_p_ref,length_uv); break; case '3': // "QUARTER_LEFT"; length_y=frame->y_width>>2; length_uv=length_y>>1; for (i=0;iy_height;i++,u_c_p_frame+=frame->y_width,u_c_p_ref+=frame->y_width) memcpy(u_c_p_frame,u_c_p_ref,length_y); for (i=0;iuv_height;i++,u_c_p_frame+=frame->uv_width,u_c_p_ref+=frame->uv_width) memcpy(u_c_p_frame,u_c_p_ref,length_uv); for (i=0;iuv_height;i++,u_c_p_frame+=frame->uv_width,u_c_p_ref+=frame->uv_width) memcpy(u_c_p_frame,u_c_p_ref,length_uv); break; case '4': // "QUARTER_RIGHT"; length_y=frame->y_width>>2; length_uv=length_y>>1; offset3=3*length_y; offset4=offset3>>1; u_c_p_frame+=offset3; u_c_p_ref +=offset3; for (i=0;iy_height;i++,u_c_p_frame+=frame->y_width,u_c_p_ref+=frame->y_width) memcpy(u_c_p_frame,u_c_p_ref,length_y); u_c_p_frame-=offset4; u_c_p_ref -=offset4; for (i=0;iuv_height;i++,u_c_p_frame+=frame->uv_width,u_c_p_ref+=frame->uv_width) memcpy(u_c_p_frame,u_c_p_ref,length_uv); for (i=0;iuv_height;i++,u_c_p_frame+=frame->uv_width,u_c_p_ref+=frame->uv_width) memcpy(u_c_p_frame,u_c_p_ref,length_uv); break; case '5': // "3QUARTER_LEFT"; length_y=(3*frame->y_width)>>2; length_uv=length_y>>1; for (i=0;iy_height;i++,u_c_p_frame+=frame->y_width,u_c_p_ref+=frame->y_width) memcpy(u_c_p_frame,u_c_p_ref,length_y); for (i=0;iuv_height;i++,u_c_p_frame+=frame->uv_width,u_c_p_ref+=frame->uv_width) memcpy(u_c_p_frame,u_c_p_ref,length_uv); for (i=0;iuv_height;i++,u_c_p_frame+=frame->uv_width,u_c_p_ref+=frame->uv_width) memcpy(u_c_p_frame,u_c_p_ref,length_uv); break; case '6': // "3QUARTER_RIGHT"; length_y=(3*frame->y_width)>>2; length_uv=length_y>>1; offset3=(frame->y_width>>2); offset4=offset3>>1; u_c_p_frame+=offset3; u_c_p_ref +=offset3; for (i=0;iy_height;i++,u_c_p_frame+=frame->y_width,u_c_p_ref+=frame->y_width) memcpy(u_c_p_frame,u_c_p_ref,length_y); u_c_p_frame-=offset4; u_c_p_ref -=offset4; for (i=0;iuv_height;i++,u_c_p_frame+=frame->uv_width,u_c_p_ref+=frame->uv_width) memcpy(u_c_p_frame,u_c_p_ref,length_uv); for (i=0;iuv_height;i++,u_c_p_frame+=frame->uv_width,u_c_p_ref+=frame->uv_width) memcpy(u_c_p_frame,u_c_p_ref,length_uv); break; case '7': // "TOP"; length_y =frame->nb_y>>1; length_uv=length_y>>2; memcpy(u_c_p_frame,u_c_p_ref,length_y); u_c_p_frame=frame->u; u_c_p_ref+=frame->nb_y; memcpy(u_c_p_frame,u_c_p_ref,length_uv); u_c_p_frame=frame->v; u_c_p_ref+=frame->nb_uv; memcpy(u_c_p_frame,u_c_p_ref,length_uv); break; case '8': // "BOTTOM"; length_y =frame->nb_y>>1; length_uv=length_y>>2; offset3 =frame->nb_y>>1; offset4 =length_y+length_uv; u_c_p_frame+=offset3; u_c_p_ref +=offset3; memcpy(u_c_p_frame,u_c_p_ref,length_y); u_c_p_frame+=offset4; u_c_p_ref +=offset4; memcpy(u_c_p_frame,u_c_p_ref,length_uv); u_c_p_frame+=(length_uv<<1); u_c_p_ref +=(length_uv<<1); memcpy(u_c_p_frame,u_c_p_ref,length_uv); break; default: break; } } // ************************************************************************************* // ************************************************************************************* // MAIN // ************************************************************************************* int main (int argc, char *argv[]) { // Defining yuvcorrect dedicated structures (see yuvcorrect.h) overall_t *overall=NULL; frame_t *frame=NULL; general_correction_t *gen_correct=NULL; yuv_correction_t *yuv_correct=NULL; rgb_correction_t *rgb_correct=NULL; ref_frame_t *ref_frame=NULL; int c,err; uint8_t quit=0,current_correction=0; uint8_t *u_c_p, *image_frame; //u_c_p = uint8_t pointer // Information output mjpeg_info("yuvcorrect_tune "VERSION" ("yuvcorrect_tune_VERSION") is an interactive image correction utility for yuv frames"); mjpeg_info ("(C) 2002 Xavier Biquard , yuvcorrect_tune -h for usage, or man yuvcorrect_tune"); // START OF INITIALISATION // START OF INITIALISATION // START OF INITIALISATION // yuvcorrect overall structure initialisation if (!(overall = malloc(sizeof(overall_t)))) mjpeg_error_exit1("Could not allocate memory for overall structure pointer"); overall->verbose=1; overall->mode=overall->stat=0; overall->RefFrame=overall->ImgFrame=-1; handle_args_overall(argc, argv, overall); mjpeg_default_handler_verbosity (overall->verbose); mjpeg_debug("Start of initialisation"); // yuvcorrect general_correction_t structure initialisations if (!(gen_correct = (general_correction_t *) malloc (sizeof (general_correction_t)))) mjpeg_error_exit1 ("Could not allocate memory for gen_correct structure pointer"); // yuvcorrect frame_t structure initialisations if (!(frame = (frame_t *) malloc (sizeof (frame_t)))) mjpeg_error_exit1 ("Could not allocate memory for frame structure pointer"); // yuvcorrect yuv_correction_t structure initialisation if (!(yuv_correct = (yuv_correction_t *) malloc (sizeof (yuv_correction_t)))) mjpeg_error_exit1 ("Could not allocate memory for yuv_correct structure pointer"); // rgbcorrect rgb_correction_t structure initialisation if (!(rgb_correct = (rgb_correction_t *) malloc (sizeof (rgb_correction_t)))) mjpeg_error_exit1 ("Could not allocate memory for rgb_correct structure pointer"); // ref_frame if (!(ref_frame = (ref_frame_t *) malloc (sizeof (ref_frame_t)))) mjpeg_error_exit1 ("Could not allocate memory for ref_frame structure pointer"); initialisation1(overall->ImgFrame,frame,gen_correct,yuv_correct,rgb_correct); // Deal with args handle_args_yuv_rgb (argc, argv, yuv_correct, rgb_correct); yuvcorrect_tune_handle_args (argc, argv, overall, gen_correct); // Specific to yuvcorrect_tune: automatically activate yuv and rgb corrections yuv_correct->luma = yuv_correct->chroma = rgb_correct->rgb = 1; initialisation2(yuv_correct,rgb_correct); mjpeg_debug ("End of Initialisation"); // END OF INITIALISATION // END OF INITIALISATION // END OF INITIALISATION mjpeg_debug("overall: verbose=%u, mode=%d, stat=%u",overall->verbose,overall->mode,overall->stat); mjpeg_debug("frame: Y:%ux%u=>%lu UV:%ux%u=>%lu Size=%lu",frame->y_width,frame->y_height,frame->nb_y,frame->uv_width,frame->uv_height,frame->nb_uv,frame->length); mjpeg_debug("yuv: Gamma=%f, InputYmin=%u, InputYmax=%u, OutputYmin=%u, OutputYmax=%u",yuv_correct->Gamma,yuv_correct->InputYmin,yuv_correct->InputYmax,yuv_correct->OutputYmin,yuv_correct->OutputYmax); mjpeg_debug("yuv: Gamma=%f, InputYmin=%u, InputYmax=%u, OutputYmin=%u, OutputYmax=%u",yuv_correct->Gamma,yuv_correct->InputYmin,yuv_correct->InputYmax,yuv_correct->OutputYmin,yuv_correct->OutputYmax); if (!(u_c_p = malloc (frame->length + ALIGNEMENT))) mjpeg_error_exit1 ("Could not allocate memory for frame table. STOP!"); mjpeg_debug ("before alignement: %p", u_c_p); if (((unsigned long) u_c_p % ALIGNEMENT) != 0) u_c_p =(uint8_t *) ((((unsigned long) u_c_p / ALIGNEMENT) + 1) * ALIGNEMENT); mjpeg_debug ("after alignement: %p", u_c_p); image_frame=u_c_p; // Read image frame and apply corrections eventually defined on command line if(yuvcorrect_y4m_read_frame (overall->ImgFrame, &gen_correct->streaminfo, frame, gen_correct->line_switch) != Y4M_OK) mjpeg_error_exit1("Unable to read image frame. Aborting now !!"); close(overall->ImgFrame); if (overall->RefFrame!=overall->ImgFrame) { // Specific to yuvcorrect_tune: ref frame // ref_frame ref_frame_init(overall->RefFrame,ref_frame); // Coherence check if ((ref_frame->width!=frame->y_width)||(ref_frame->height!=frame->y_height)) mjpeg_error_exit1("Width and Height of Image and Ref Frame differ. aborting now!!"); // Read ref frame if (y4m_read_frame_header (overall->RefFrame, &gen_correct->streaminfo, &ref_frame->info) == Y4M_OK) { if ((err = y4m_read (overall->RefFrame, ref_frame->ref, frame->length)) != Y4M_OK) mjpeg_error_exit1 ("Couldn't read FRAME content: %s!",y4m_strerr (err)); } else mjpeg_error_exit1("Unable to read ref frame. Aborting now !!"); close(overall->RefFrame); } mjpeg_info("Y_%f_%u_%u_%u_%u",yuv_correct->Gamma,yuv_correct->InputYmin,yuv_correct->InputYmax,yuv_correct->OutputYmin,yuv_correct->OutputYmax); mjpeg_info("UV_%f_%f_%u_%f_%u_%u_%u",yuv_correct->UVrotation,yuv_correct->Ufactor,yuv_correct->Urotcenter, yuv_correct->Vfactor,yuv_correct->Vrotcenter,yuv_correct->UVmin,yuv_correct->UVmax); mjpeg_info("R_%f_%u_%u_%u_%u",rgb_correct->RGamma,rgb_correct->InputRmin,rgb_correct->InputRmax,rgb_correct->OutputRmin,rgb_correct->OutputRmax); mjpeg_info("G_%f_%u_%u_%u_%u",rgb_correct->GGamma,rgb_correct->InputGmin,rgb_correct->InputGmax,rgb_correct->OutputGmin,rgb_correct->OutputGmax); mjpeg_info("B_%f_%u_%u_%u_%u",rgb_correct->BGamma,rgb_correct->InputBmin,rgb_correct->InputBmax,rgb_correct->OutputBmin,rgb_correct->OutputBmax); if (overall->rgbfirst == 1) yuvcorrect_RGB_treatment (frame, rgb_correct); // luminance correction yuvcorrect_luminance_treatment (frame, yuv_correct); // chrominance correction yuvcorrect_chrominance_treatment (frame, yuv_correct); if (overall->rgbfirst != 1) yuvcorrect_RGB_treatment (frame, rgb_correct); y4m_write_stream_header (1, &gen_correct->streaminfo); // Now, frame->y points on the corrected frame. Store it inside image_frame memcpy(image_frame,frame->y,frame->length); // Output Frame Header if (y4m_write_frame_header (1, &gen_correct->streaminfo, &frame->info) != Y4M_OK) goto out_error; // Output Frame content if (y4m_write (1, frame->y, frame->length) != Y4M_OK) goto out_error; // Master loop : continue until there is no more keystrokes while (((c=getc(stdin))!=EOF)&&(quit!=1)) { if (c!='\n') { if (current_correction==0) { // this keystroke may defined the current_correction switch(c) { case 'y' : case 'Y' : // Activate Luminance corrections current_correction=1; mjpeg_info("Luminance corrections activated"); break; case 'u' : case 'U' : case 'v' : case 'V' : // Activate Chrominance corrections current_correction=2; mjpeg_info("Chrominance corrections activated"); break; case 'r' : case 'R' : // Activate RED corrections current_correction=3; mjpeg_info("RED corrections activated"); break; case 'g' : case 'G' : // Activate GREEN corrections current_correction=4; mjpeg_info("GREEN corrections activated"); break; case 'b' : case 'B' : // Activate BLUE corrections current_correction=5; mjpeg_info("BLUE corrections activated"); break; case 'm' : case 'M' : // Activate MODE corrections current_correction=6; mjpeg_info("MODE corrections activated"); break; } c = '\n'; } if (c=='\e') { current_correction=0; mjpeg_info("ESCAPE!!! => next (valid) keystroke defined which correction type will be activated"); } if ((c=='Q')||(c=='q')) quit=1; if ((c=='D')||(c=='d')) { // Go back to default values mjpeg_info("Not implemented yet. Sorry ... please relanch yuvcorrect_tune.\n"); } if ((c=='S')||(c=='s')) { mjpeg_info("Y_%f_%u_%u_%u_%u",yuv_correct->Gamma,yuv_correct->InputYmin,yuv_correct->InputYmax,yuv_correct->OutputYmin,yuv_correct->OutputYmax); mjpeg_info("UV_%f_%f_%u_%f_%u_%u_%u",yuv_correct->UVrotation,yuv_correct->Ufactor,yuv_correct->Urotcenter, yuv_correct->Vfactor,yuv_correct->Vrotcenter,yuv_correct->UVmin,yuv_correct->UVmax); mjpeg_info("R_%f_%u_%u_%u_%u",rgb_correct->RGamma,rgb_correct->InputRmin,rgb_correct->InputRmax,rgb_correct->OutputRmin,rgb_correct->OutputRmax); mjpeg_info("G_%f_%u_%u_%u_%u",rgb_correct->GGamma,rgb_correct->InputGmin,rgb_correct->InputGmax,rgb_correct->OutputGmin,rgb_correct->OutputGmax); mjpeg_info("B_%f_%u_%u_%u_%u",rgb_correct->BGamma,rgb_correct->InputBmin,rgb_correct->InputBmax,rgb_correct->OutputBmin,rgb_correct->OutputBmax); } if (current_correction!=0) { if (current_correction==6) { // MODE output corrections switch(c) { case '0' : overall->mode=0; break; case '1' : overall->mode=1; break; case '2' : overall->mode=2; break; case '3' : overall->mode=3; break; case '4' : overall->mode=4; break; case '5' : overall->mode=5; break; case '6' : overall->mode=6; break; case '7' : overall->mode=7; break; case '8' : overall->mode=8; break; case '9' : if (overall->rgbfirst==1) overall->rgbfirst=0; else overall->rgbfirst=1; break; break; default: break; } } if (current_correction==1) { switch(c) { case 'E': // Increase first parameter yuv_correct->Gamma+=gamma_increment; break; case 'e': // Decrease first parameter if (yuv_correct->Gamma<=gamma_increment) mjpeg_info("Gamma value would become negative!! Ignoring"); else yuv_correct->Gamma-=gamma_increment; break; case 'R': // Increase Second parameter if ((yuv_correct->InputYmin==255)||(yuv_correct->InputYmin==yuv_correct->InputYmax)) mjpeg_info("InputYmin would be greater than 255 or InputYmax!! Ignoring"); else yuv_correct->InputYmin+=1; break; case 'r': // Decrease second parameter if (yuv_correct->InputYmin==0) mjpeg_info("InputYmin would be smaller than 0!! Ignoring"); else yuv_correct->InputYmin-=1; break; case 'T': // Increase third parameter if (yuv_correct->InputYmax==255) mjpeg_info("InputYmax would be greater than 255!! Ignoring"); else yuv_correct->InputYmax+=1; break; case 't': // Decrease third parameter if ((yuv_correct->InputYmax==0)||(yuv_correct->InputYmax==yuv_correct->InputYmin)) mjpeg_info("InputYmax would be smaller than 0 or InputYmin!! Ignoring"); else yuv_correct->InputYmax-=1; break; case 'Y': // Increase fourth parameter if ((yuv_correct->OutputYmin==255)||(yuv_correct->OutputYmin==yuv_correct->OutputYmax)) mjpeg_info("OutputYmin would be greater than 255 or OutputYmax!! Ignoring"); else yuv_correct->OutputYmin+=1; break; case 'y': // Decrease fourth parameter if (yuv_correct->OutputYmin==0) mjpeg_info("OutputYmin would be smaller than 0!! Ignoring"); else yuv_correct->OutputYmin-=1; break; case 'U': // Increase fifth parameter if (yuv_correct->OutputYmax==255) mjpeg_info("OutputYmax would be greater than 255!! Ignoring"); else yuv_correct->OutputYmax+=1; break; case 'u': // Decrease fifth parameter if ((yuv_correct->OutputYmax==0)||(yuv_correct->OutputYmax==yuv_correct->OutputYmin)) mjpeg_info("OutputYmax would be smaller than 0 or OutputYmin!! Ignoring"); else yuv_correct->OutputYmax-=1; break; default : break; } } if (current_correction==3) { switch(c) { case 'E': // Increase first parameter rgb_correct->RGamma+=gamma_increment; break; case 'e': // Decrease first parameter if (rgb_correct->RGamma<=gamma_increment) mjpeg_info("RGamma value would become negative!! Ignoring"); else rgb_correct->RGamma-=gamma_increment; break; case 'R': // Increase Second parameter if ((rgb_correct->InputRmin==255)||(rgb_correct->InputRmin==rgb_correct->InputRmax)) mjpeg_info("InputRmin would be greater than 255 or InputRmax!! Ignoring"); else rgb_correct->InputRmin+=1; break; case 'r': // Decrease second parameter if (rgb_correct->InputRmin==0) mjpeg_info("InputRmin would be smaller than 0!! Ignoring"); else rgb_correct->InputRmin-=1; break; case 'T': // Increase third parameter if (rgb_correct->InputRmax==255) mjpeg_info("InputRmax would be greater than 255!! Ignoring"); else rgb_correct->InputRmax+=1; break; case 't': // Decrease third parameter if ((rgb_correct->InputRmax==0)||(rgb_correct->InputRmax==rgb_correct->InputRmin)) mjpeg_info("InputRmax would be smaller than 0 or InputRmin!! Ignoring"); else rgb_correct->InputRmax-=1; break; case 'Y': // Increase fourth parameter if ((rgb_correct->OutputRmin==255)||(rgb_correct->OutputRmin==rgb_correct->OutputRmax)) mjpeg_info("OutputRmin would be greater than 255 or OutputRmax!! Ignoring"); else rgb_correct->OutputRmin+=1; break; case 'y': // Decrease fourth parameter if (rgb_correct->OutputRmin==0) mjpeg_info("OutputRmin would be smaller than 0!! Ignoring"); else rgb_correct->OutputRmin-=1; break; case 'U': // Increase fifth parameter if (rgb_correct->OutputRmax==255) mjpeg_info("OutputRmax would be greater than 255!! Ignoring"); else rgb_correct->OutputRmax+=1; break; case 'u': // Decrease fifth parameter if ((rgb_correct->OutputRmax==0)||(rgb_correct->OutputRmax==rgb_correct->OutputRmin)) mjpeg_info("OutputRmax would be smaller than 0 or OutputRmin!! Ignoring"); else rgb_correct->OutputRmax-=1; break; default : break; } } if (current_correction==4) { switch(c) { case 'E': // Increase first parameter rgb_correct->GGamma+=gamma_increment; break; case 'e': // Decrease first parameter if (rgb_correct->GGamma<=gamma_increment) mjpeg_info("GGamma value would become negative!! Ignoring"); else rgb_correct->GGamma-=gamma_increment; break; case 'R': // Increase Second parameter if ((rgb_correct->InputGmin==255)||(rgb_correct->InputGmin==rgb_correct->InputGmax)) mjpeg_info("InputGmin would be greater than 255 or InputGmax!! Ignoring"); else rgb_correct->InputGmin+=1; break; case 'r': // Decrease second parameter if (rgb_correct->InputGmin==0) mjpeg_info("InputGmin would be smaller than 0!! Ignoring"); else rgb_correct->InputGmin-=1; break; case 'T': // Increase third parameter if (rgb_correct->InputGmax==255) mjpeg_info("InputGmax would be greater than 255!! Ignoring"); else rgb_correct->InputGmax+=1; break; case 't': // Decrease third parameter if ((rgb_correct->InputGmax==0)||(rgb_correct->InputGmax==rgb_correct->InputGmin)) mjpeg_info("InputGmax would be smaller than 0 or InputGmin!! Ignoring"); else rgb_correct->InputGmax-=1; break; case 'Y': // Increase fourth parameter if ((rgb_correct->OutputGmin==255)||(rgb_correct->OutputGmin==rgb_correct->OutputGmax)) mjpeg_info("OutputGmin would be greater than 255 or OutputGmax!! Ignoring"); else rgb_correct->OutputGmin+=1; break; case 'y': // Decrease fourth parameter if (rgb_correct->OutputGmin==0) mjpeg_info("OutputGmin would be smaller than 0!! Ignoring"); else rgb_correct->OutputGmin-=1; break; case 'U': // Increase fifth parameter if (rgb_correct->OutputGmax==255) mjpeg_info("OutputGmax would be greater than 255!! Ignoring"); else rgb_correct->OutputGmax+=1; break; case 'u': // Decrease fifth parameter if ((rgb_correct->OutputGmax==0)||(rgb_correct->OutputGmax==rgb_correct->OutputGmin)) mjpeg_info("OutputGmax would be smaller than 0 or OutputGmin!! Ignoring"); else rgb_correct->OutputGmax-=1; break; default : break; } } if (current_correction==5) { switch(c) { case 'E': // Increase first parameter rgb_correct->BGamma+=gamma_increment; break; case 'e': // Decrease first parameter if (rgb_correct->BGamma<=gamma_increment) mjpeg_info("BGamma value would become negative!! Ignoring"); else rgb_correct->BGamma-=gamma_increment; break; case 'R': // Increase Second parameter if ((rgb_correct->InputBmin==255)||(rgb_correct->InputBmin==rgb_correct->InputBmax)) mjpeg_info("InputBmin would be greater than 255 or InputBmax!! Ignoring"); else rgb_correct->InputBmin+=1; break; case 'r': // Decrease second parameter if (rgb_correct->InputBmin==0) mjpeg_info("InputBmin would be smaller than 0!! Ignoring"); else rgb_correct->InputBmin-=1; break; case 'T': // Increase third parameter if (rgb_correct->InputBmax==255) mjpeg_info("InputBmax would be greater than 255!! Ignoring"); else rgb_correct->InputBmax+=1; break; case 't': // Decrease third parameter if ((rgb_correct->InputBmax==0)||(rgb_correct->InputBmax==rgb_correct->InputBmin)) mjpeg_info("InputBmax would be smaller than 0 or InputBmin!! Ignoring"); else rgb_correct->InputBmax-=1; break; case 'Y': // Increase fourth parameter if ((rgb_correct->OutputBmin==255)||(rgb_correct->OutputBmin==rgb_correct->OutputBmax)) mjpeg_info("OutputBmin would be greater than 255 or OutputBmax!! Ignoring"); else rgb_correct->OutputBmin+=1; break; case 'y': // Decrease fourth parameter if (rgb_correct->OutputBmin==0) mjpeg_info("OutputBmin would be smaller than 0!! Ignoring"); else rgb_correct->OutputBmin-=1; break; case 'U': // Increase fifth parameter if (rgb_correct->OutputBmax==255) mjpeg_info("OutputBmax would be greater than 255!! Ignoring"); else rgb_correct->OutputBmax+=1; break; case 'u': // Decrease fifth parameter if ((rgb_correct->OutputBmax==0)||(rgb_correct->OutputBmax==rgb_correct->OutputBmin)) mjpeg_info("OutputBmax would be smaller than 0 or OutputBmin!! Ignoring"); else rgb_correct->OutputBmax-=1; break; default : break; } } if (current_correction==2) { switch(c) { case 'E': // Increase UBrotation by 1 yuv_correct->UVrotation+=1.0; break; case 'e': // Decrease UBrotation by 1 yuv_correct->UVrotation-=1.0; break; case 'R': // Increase Ufactor yuv_correct->Ufactor+=0.05; break; case 'r': // Decrease Ufactor value if (yuv_correct->Ufactor<=0.05) mjpeg_info("Ufactor value would become negative!! Ignoring"); else yuv_correct->Ufactor-=0.05; break; case 'T': // Increase Urotcenter by 1 if (yuv_correct->Urotcenter==255) mjpeg_info("Urotcenter would be greater than 255!! Ignoring"); else yuv_correct->Urotcenter+=1; break; case 't': // Decrease Urotcenter by 1 if (yuv_correct->Urotcenter==0) mjpeg_info("Urotcenter would be smaller than 0!! Ignoring"); else yuv_correct->Urotcenter-=1; break; case 'Y': // Increase Vfactor yuv_correct->Vfactor+=0.05; break; case 'y': // Decrease Vfactor value if (yuv_correct->Vfactor<=0.05) mjpeg_info("Vfactor value would become negative!! Ignoring"); else yuv_correct->Vfactor-=0.05; break; case 'U': // Increase Vrotcenter by 1 if (yuv_correct->Vrotcenter==255) mjpeg_info("Vrotcenter would be greater than 255!! Ignoring"); else yuv_correct->Vrotcenter+=1; break; case 'u': // Decrease Vrotcenter by 1 if (yuv_correct->Vrotcenter==0) mjpeg_info("Vrotcenter would be smaller than 0!! Ignoring"); else yuv_correct->Vrotcenter-=1; break; case 'I': // Increase UVmin by 1 if (yuv_correct->UVmin==255) mjpeg_info("UVmin would be greater than 255!! Ignoring"); else yuv_correct->UVmin+=1; break; case 'i': // Decrease UVmin by 1 if (yuv_correct->UVmin==0) mjpeg_info("UVmin would be smaller than 0!! Ignoring"); else yuv_correct->UVmin-=1; break; case 'O': // Increase UVmax by 1 if (yuv_correct->UVmax==255) mjpeg_info("UVmax would be greater than 255!! Ignoring"); else yuv_correct->UVmax+=1; break; case 'o': // Decrease UVmax by 1 if (yuv_correct->UVmax==0) mjpeg_info("UVmax would be smaller than 0!! Ignoring"); else yuv_correct->UVmax-=1; break; } } } memcpy(frame->y,image_frame,frame->length); // Apply correction if (overall->rgbfirst == 1) { // RGB correction yuvcorrect_RGB_init(rgb_correct); yuvcorrect_RGB_treatment (frame, rgb_correct); } // luminance correction yuvcorrect_luminance_init(yuv_correct); yuvcorrect_luminance_treatment (frame, yuv_correct); // chrominance correction yuvcorrect_chrominance_init(yuv_correct); yuvcorrect_chrominance_treatment (frame, yuv_correct); if (overall->rgbfirst != 1) { yuvcorrect_RGB_init(rgb_correct); yuvcorrect_RGB_treatment (frame, rgb_correct); } // Output Frame Header if (y4m_write_frame_header (1, &gen_correct->streaminfo, &frame->info) != Y4M_OK) goto out_error; // Output Frame content // Output may be in fact constituted of two parts => cover part of frame with final_ref if (overall->mode!=0) { if (overall->RefFrame!=overall->ImgFrame) add_reference_part(frame,ref_frame->ref,overall->mode); else add_reference_part(frame,frame->y,overall->mode); } // Output full frame size if (y4m_write (1, frame->y, frame->length) != Y4M_OK) goto out_error; } } y4m_fini_stream_info (&gen_correct->streaminfo); y4m_fini_frame_info (&frame->info); return 0; out_error: mjpeg_error_exit1 ("Unable to write to output - aborting!"); return 1; } // ************************************************************************************* // ************************************************************************************* // ************************************************************************************* // ************************************************************************************* /* * Local variables: * tab-width: 8 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/yuvcorrect/Makefile.in0000644000175000017500000004620412217306410020465 0ustar glowwormglowworm# Makefile.in generated by automake 1.12.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Makefile for yuvcorrect VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @HAVE_ALTIVEC_TRUE@am__append_1 = $(top_builddir)/mpeg2enc/libmpeg2encpp.la bin_PROGRAMS = yuvcorrect$(EXEEXT) yuvcorrect_tune$(EXEEXT) subdir = yuvcorrect DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_yuvcorrect_OBJECTS = yuvcorrect.$(OBJEXT) \ yuvcorrect_functions.$(OBJEXT) yuvcorrect_OBJECTS = $(am_yuvcorrect_OBJECTS) am__DEPENDENCIES_1 = yuvcorrect_DEPENDENCIES = $(LIBMJPEGUTILS) $(am__DEPENDENCIES_1) am_yuvcorrect_tune_OBJECTS = yuvcorrect_tune.$(OBJEXT) \ yuvcorrect_functions.$(OBJEXT) yuvcorrect_tune_OBJECTS = $(am_yuvcorrect_tune_OBJECTS) yuvcorrect_tune_DEPENDENCIES = $(LIBMJPEGUTILS) $(am__DEPENDENCIES_1) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(yuvcorrect_SOURCES) $(yuvcorrect_tune_SOURCES) DIST_SOURCES = $(yuvcorrect_SOURCES) $(yuvcorrect_tune_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALTIVEC_EXTRA_LIBS = @ALTIVEC_EXTRA_LIBS@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDV_CFLAGS = @LIBDV_CFLAGS@ LIBDV_LIBS = @LIBDV_LIBS@ LIBGETOPT_LIB = @LIBGETOPT_LIB@ LIBM_LIBS = @LIBM_LIBS@ LIBOBJS = @LIBOBJS@ LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ LIBPNG_LIBS = @LIBPNG_LIBS@ LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@ LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ LT_STATIC = @LT_STATIC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROGRAM_NOPIC = @PROGRAM_NOPIC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ SDLgfx_LIBS = @SDLgfx_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ V4LCONF_LIBS = @V4LCONF_LIBS@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAINTAINERCLEANFILES = Makefile.in AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/utils LIBMJPEGUTILS = $(top_builddir)/utils/libmjpegutils.la $(am__append_1) noinst_HEADERS = yuvcorrect.h yuvcorrect_SOURCES = yuvcorrect.c yuvcorrect_functions.c yuvcorrect_LDADD = $(LIBMJPEGUTILS) $(LIBM_LIBS) yuvcorrect_tune_SOURCES = yuvcorrect_tune.c yuvcorrect_functions.c yuvcorrect_tune_LDADD = $(LIBMJPEGUTILS) $(LIBM_LIBS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu yuvcorrect/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu yuvcorrect/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list yuvcorrect$(EXEEXT): $(yuvcorrect_OBJECTS) $(yuvcorrect_DEPENDENCIES) $(EXTRA_yuvcorrect_DEPENDENCIES) @rm -f yuvcorrect$(EXEEXT) $(LINK) $(yuvcorrect_OBJECTS) $(yuvcorrect_LDADD) $(LIBS) yuvcorrect_tune$(EXEEXT): $(yuvcorrect_tune_OBJECTS) $(yuvcorrect_tune_DEPENDENCIES) $(EXTRA_yuvcorrect_tune_DEPENDENCIES) @rm -f yuvcorrect_tune$(EXEEXT) $(LINK) $(yuvcorrect_tune_OBJECTS) $(yuvcorrect_tune_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuvcorrect.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuvcorrect_functions.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuvcorrect_tune.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool cscopelist ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mjpegtools-2.1.0/yuvcorrect/yuvcorrect.h0000644000175000017500000001137310324007173020776 0ustar glowwormglowworm// Data type for yuvcorrect overall functionnality typedef struct { uint8_t verbose; uint8_t mode; // =0 for non-interactive mode, =1 for interactive corrections in full mode, =2 in half mode uint8_t stat; // =1 if statistics informations are to be displayed int ImgFrame; // Only useful for yuvcorrect_tune int RefFrame; // Only useful for yuvcorrect_tune uint8_t rgbfirst; // =1 if rgb corrections are to be applied before yuv ones } overall_t; // Data type for yuvcorrect_tune reference frame typedef struct { unsigned int width; unsigned int height; uint8_t *ref; y4m_frame_info_t info; y4m_stream_info_t streaminfo; } ref_frame_t; // Data type for yuvcorrect frame characteristics typedef struct { // General frame characteristics // y4m_ratio_t sample_aspect_ratio = Y4M_SAR_UNKNOWN; // see yuv4mpeg.h and yuv4mpeg_intern.h for possible values // int interlaced = -1; // =Y4M_ILACE_NONE for progressive/not-interlaced, Y4M_ILACE_TOP_FIRST for top interlaced, Y4M_ILACE_BOTTOM_FIRST for bottom interlaced unsigned long int length; y4m_frame_info_t info; // Y characteristics uint8_t *y; unsigned int y_width; unsigned int y_height; unsigned long int nb_y; // UV characteristics uint8_t *u, *v; unsigned int ss_h; unsigned int ss_v; unsigned int uv_width; unsigned int uv_height; unsigned long int nb_uv; // Two fields uint8_t *field1, *field2; } frame_t; // Data type for general frame correction typedef struct { // HEADER management uint8_t no_header; // =0 by default, =1 to suppress header output y4m_stream_info_t streaminfo; // Frame corrections uint8_t line_switch; // =0 by default, =1 if line switching is activated int8_t field_move; // =0 by default, =1 if bottom field is moved one frame forward, =-1 if it is the top field } general_correction_t; // Data type for correction in the YUV space typedef struct { // LUMINANCE correction uint8_t luma; // =1 if luminance correction is activated uint8_t *luminance; float Gamma; uint8_t InputYmin; uint8_t InputYmax; uint8_t OutputYmin; uint8_t OutputYmax; // CHROMINANCE correction uint8_t chroma; // =1 if chrominance correction is activated uint8_t *chrominance; float UVrotation; float Ufactor; uint8_t Urotcenter; float Vfactor; uint8_t Vrotcenter; uint8_t UVmin; uint8_t UVmax; } yuv_correction_t; /* * Data type for correction in the RGB space */ typedef struct { // RGB correction uint8_t rgb; // =1 if RGB correction is activated uint8_t *new_red; uint8_t *new_green; uint8_t *new_blue; float RGamma; float GGamma; float BGamma; uint8_t InputRmin; uint8_t InputRmax; uint8_t OutputRmin; uint8_t OutputRmax; uint8_t InputGmin; uint8_t InputGmax; uint8_t OutputGmin; uint8_t OutputGmax; uint8_t InputBmin; uint8_t InputBmax; uint8_t OutputBmin; uint8_t OutputBmax; // Acceleration through tabulation of all multiplicative operations uint8_t *luma_r, *luma_g, *luma_b; int8_t *u_r, *u_g, *u_b; int8_t *v_r, *v_g, *v_b; int16_t *RUV_v, *GUV_v, *GUV_u, *BUV_u; } rgb_correction_t; // Functions Prototypes void handle_args_overall (int argc, char *argv[], overall_t * overall); int yuvcorrect_y4m_read_frame (int fd, y4m_stream_info_t *si, frame_t * frame, uint8_t line_switch); int yuvcorrect_luminance_init (yuv_correction_t * yuv_correct); int yuvcorrect_chrominance_init (yuv_correction_t * yuv_correct); int yuvcorrect_luminance_treatment (frame_t * frame, yuv_correction_t * yuv_correct); int yuvcorrect_chrominance_treatment (frame_t * frame, yuv_correction_t * yuv_correct); int bottom_field_storage (frame_t * frame, uint8_t oddeven, uint8_t * field1, uint8_t * field2); int top_field_storage (frame_t * frame, uint8_t oddeven, uint8_t * field1, uint8_t * field2); int bottom_field_replace (frame_t * frame, uint8_t oddeven, uint8_t * field1, uint8_t * field2); int top_field_replace (frame_t * frame, uint8_t oddeven, uint8_t * field1, uint8_t * field2); int main (int argc, char *argv[]); uint8_t clip_0_255 (int16_t number); int8_t clip_127_127 (int16_t number); void yuvstat (frame_t * frame); uint8_t yuvcorrect_nearest_integer_division (unsigned long int p, unsigned long int q); int yuvcorrect_RGB_treatment (frame_t * frame, rgb_correction_t * rgb_correct); int yuvcorrect_RGB_init (rgb_correction_t * rgb_correct); void handle_args_yuv_rgb (int argc, char *argv[], yuv_correction_t * yuv_correct, rgb_correction_t * rgb_correct); void initialisation1(int, frame_t * frame, general_correction_t * gen_correct, yuv_correction_t * yuv_correct, rgb_correction_t * rgb_correct); void initialisation2(yuv_correction_t * yuv_correct, rgb_correction_t * rgb_correct); void ref_frame_init(int fd,ref_frame_t *ref_frame); mjpegtools-2.1.0/y4mscaler/0000755000175000017500000000000012217306501016111 5ustar glowwormglowwormmjpegtools-2.1.0/y4mscaler/ChangeLog0000644000175000017500000002072012051575455017700 0ustar glowwormglowworm2005-12-11 Matto Marjanovic * Makefile, TODO: Update TODO. Set owner/group to root/root within distribution tarballs. 2005-11-28 Matto Marjanovic * Makefile: o Add arch-specific targets. o Set chmod-bits appropriately when creating dist tarballs. o Bump version to 9.0. 2005-11-27 Matto Marjanovic * TODO, y4mscaler.1, ysTarget.C, ysTarget.H: Add presets for ATSC's 720p, 1080i, 1080p. * graphics.H, ysTarget.C: Use floats for ratio simplification; doubles are overkill. * ysTarget.C: Use double FP for scoring when simplifying ratios. 2005-06-04 Matto Marjanovic * graphics.C, graphics.H: Reimplement ysRatio * and / operations using 64-bit intermediate values, to try to avoid overflow. 2005-01-24 Matto Marjanovic * Makefile, TODO, scaler-matto.H, y4mscaler.1: o add sms's PPC CPU opt flags to Makefile. o bump rev to 8.1 o make 'cubicK4' the default kernel. 2005-01-17 Matto Marjanovic * kernels.C: change name of cubicK to cubicK4... * TODO: update todo * kernels.C, scaler-matto.H: o Actually change default kernel to DEFAULT_KERNEL. o Add "Keys 4th-order Cubic" kernel, as requested by Nicholas Boos. o Add that 'cubicK' kernel to tests; compare against sinc:4 (same support). 2005-01-10 Matto Marjanovic * Makefile: Change name of binary tarball to include "x86". 2005-01-09 Matto Marjanovic * TODO, y4mscaler.1, ysSource.C, ysTarget.C: o update manpage with new YUV4MPEG2 functionality. o prettify bg color keyword help output * Makefile, TODO, kernels.C, notes.txt, scaler-matto.C, scaler-matto.H, y4mscaler.1, y4mscaler.C: o Changed to MAJOR.MINOR version numbers, instead of MAJOR.MINOR.PATCH. o Made 'sinc:6' the default kernel. * y4mscaler.1: Add notes on anomalous interlacing modes. * ysTarget.C: better printing of chromass keyword help * ysStreamInfo.C: clean up comment - danger has passed. * ysScaling.C, ysScaling.H: o error out if fatal anomalous frames are detected. o only process alpha planes if both src and tgt have them. * ysSource.C, ysSource.H: o Disallow fake-ilace on mixed-mode streams. o Better chromass help output. o Comment out read_frame_or_fields(). * graphics.C, graphics.H: Added alpha-channel to ysYCbCr class. * y4mscaler.1: Updated manpage; include preset table. 2004-12-19 Matto Marjanovic * TODO, graphics.C, graphics.H, notes.txt, ysScaling.C, ysScaling.H, ysSource.C, ysSource.H, ysStreamInfo.C, ysStreamInfo.H, ysTarget.C: All kinds of work done a while back to incorporate new YUV4MPEG2 stream functionality (e.g. alpha channels and mono streams and liby4m support for chroma/sampling tags). 2004-08-02 Matto Marjanovic * Makefile, graphics.H, kernels.C, scaler-matto.C, ysScaling.C, ysStreamInfo.H: o Version bumped to 0.7.1 (last commit actually) o Fix some syntax buglets, to allow compiling with gcc-3.4. * Makefile, TODO, y4mscaler.1, y4mscaler.C: o Explicitly process '-I' options before '-O' options. o Improve documentation. o Update Makefile to use "pkg-config" instead of "mjpegtools-config". 2004-04-09 Matto Marjanovic * y4mscaler.C, ysScaling.C, ysStreamInfo.C: Quick hack/update to work with updated YUV4MPEG2 API. Static build, for ez-distribution sake. Comment out the experimental stuff (which doesn't ship anyway). * Makefile: Upped version to 0.7.0. 2004-03-31 Matto Marjanovic * scaler-exp.C, scaler-exp.H, scaler-jit.C, scaler-jit.H: Added the failed "just-in-time" engine and the "experimental" engine (which will be useful for experimenting in the future). * scaler-matto.C: a non-change --- the commented out "more clever" C code actually is treated much less cleverly by gcc-3.3 --- it's slower! * ysSource.C, ysTarget.C: Some fixes so that it compiles with the new YUV4MPEG2 library in MJPEGtools CVS. (Still no use of extended library functionality yet.) 2004-02-16 Matto Marjanovic * TODO: Rearrange, so that one can see in which version items were completed... 2004-02-15 Matto Marjanovic * y4mscaler.C: tiny fix to version number printout. 2003-12-05 Matto Marjanovic * ysTarget.C (set_prefab_target): Ugh... used wrong SAR in CVD preset. * Makefile: Upped version to 0.6.1. 2003-12-04 Matto Marjanovic * Makefile: Added "dbg" target to Makefile. Upped version to 0.6.0. 2003-11-07 Matto Marjanovic * Tests/create-graphs2.sh, Tests/create-steps2.sh: Replaced sinc4hann, sinc4lan, sinc8lan with sinc:4 and sinc:8 and updated text appropriately. * Makefile: Another intra-source dependency in Makefile. * kernels.C, kernels.H, scaler-matto.C, scaler-matto.H, scaler.H, ysScaling.C, ysScaling.H: Kernels can now be parameterized (e.g. "sinc:8"). Independent x and y kernels can be specified. Tells user what scaling-engine (kernel) parameters are being used. * y4mscaler.1: Update to reflect changes. 2003-10-19 Matto Marjanovic * ysSource.H: Norm detection now recognizes NTSC field and film (60000/1001, 24000/1001) and PAL field (50/1) framerates. * ysTarget.C: Added "CVD" (Chaoji Video Disk) preset. 2003-05-29 Matto Marjanovic * y4mscaler.1: Document this new behavior (see next entry). Document the subsampling X-tags. * ysTarget.C, ysSource.C, graphics.H, graphics.C: Allow geometry strings for active and matte regions to specify offset only; the dimensions are then inherited from the framesize. * scaler-matto.C (CLIP_PIXEL): Clip values to [1,254] when converting back to uint8_t from signed, fixed-point calculations. Fixes a bug of noise-induced defects in the output. 2003-02-22 Matto Marjanovic * ysScaling.C: Error message for "cannot make progressive from interleaved" should suggest using 'ilace=XXX_only' modes. * ysSource.H: Warn about chroma-mangling when casting interlaced input to progressive, and vice-versa, when chroma is vertically subsampled. * ysSource.C: Inform when fake progressive mode is used. * scaler-matto.C: Small fixes to fix-point related code (proper rounding of negative kernel coeffs when fixing; correct rounding offset for double-fixed ops). Also changed fprintf's to DBG's. 2003-02-21 Matto Marjanovic * kernels.C: Cleaned up calcs; removed some cruft. 2003-02-21 Matto Marjanovic * scaler-matto.C: Small fixes to fix-point related code (proper rounding of negative kernel coeffs when fixing; correct rounding offset for double-fixed ops). Also changed fprintf's to DBG's. 2003-02-18 Matto Marjanovic * ysTarget.C: Add DVD_WIDE, DV, DV_WIDE presets. Add methods for writing frame and fields. Actually parse the STILL_IMAGE presets. * ysTarget.H: Add DVD_WIDE, DV, DV_WIDE presets. Add methods for writing frame and fields. Choose matte bg color depending on DEV branch flag or not. * ysSource.C: Add functions to read frames/fields with non-standard non-4:2:0 chroma subsampling modes. 2003-02-17 Matto Marjanovic * ysScaling.C: Ooops -- take chroma subsampling ratios into account when computing scaling ratios for chroma planes. Use target methods to write frames/fields instead of straight yuv4mpeg -- handles non- standard chroma SS modes. 2003-01-26 Matto Marjanovic * ysStreamInfo.H (read_stream_header): Preliminary code to handle a "YSCSS" X-tag in header (for chroma subsampling mode). * scaler-matto.C (new_scaler): Default scaler is now "linear", matching the manpage. * kernels.C: Added Lanczos-windowed sinc kernels. 2003-01-08 Matto Marjanovic * general: Now compiling with g++-3.2; this uncovered a couple of little buglets/discrepencies. * Makefile (CXXFLAGS): Added "-W" to get even more warnings. 2002-12-24 Matto Marjanovic * ysTarget.C (score_ratios): Changed from int to int64_t to try to avoid overflows from big numerators/denominators. * general: Added VCD/SVCD still image presets. * graphics.C (parse_string): proper rounding in R'G'B'->Y'CbCr conv. * kernels.C: add math.h/string.h includes. * ysScaling.C (parse_keyword): add (int) casts, because strlen() returns size_t, not necessarily int... * y4mscaler.C (parse_args): optind should initialize to 1, not 0. 2002-12-02 Matto Marjanovic * ChangeLog: created this file. mjpegtools-2.1.0/y4mscaler/COPYING0000644000175000017500000004313112051575455017162 0ustar glowwormglowworm GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. mjpegtools-2.1.0/y4mscaler/Makefile.am0000644000175000017500000000141012051575455020155 0ustar glowwormglowworm# Makefile for y4mscaler MAINTAINERCLEANFILES = Makefile.in EXTRA_DIST = ChangeLog README TODO AM_CFLAGS = -DNDEBUG -finline-functions -DYS_VERSION_MAJOR=9 -DYS_VERSION_MINOR=0 AM_CXXFLAGS = -DNDEBUG -finline-functions -DYS_VERSION_MAJOR=9 -DYS_VERSION_MINOR=0 INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/utils LIBMJPEGUTILS = $(top_builddir)/utils/libmjpegutils.la if HAVE_ALTIVEC LIBMJPEGUTILS += $(top_builddir)/mpeg2enc/libmpeg2encpp.la endif bin_PROGRAMS = y4mscaler noinst_HEADERS = \ debug.h y4m-config.h \ graphics.H kernels.H scaler-matto.H scaler.H ysScaling.H \ ysSource.H ysStreamInfo.H ysTarget.H y4mscaler_SOURCES = graphics.C kernels.C scaler-matto.C y4mscaler.C \ ysScaling.C ysSource.C ysStreamInfo.C ysTarget.C y4mscaler_LDADD = $(LIBMJPEGUTILS) mjpegtools-2.1.0/y4mscaler/ysSource.C0000644000175000017500000004562012051575455020054 0ustar glowwormglowworm/* Copyright 2003 Matthew Marjanovic This file is part of y4mscaler. y4mscaler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. y4mscaler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with y4mscaler; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "y4m-config.h" #include "debug.h" #include "ysSource.H" #include void ysSource::describe_keywords(FILE *fp, const char *prefix) const { fprintf(fp, "%sactive=WxH+X+Y\n", prefix); fprintf(fp, "%smatte=WxH+X+Y\n", prefix); { ysYCbCr defbg(default_bgcolor()); fprintf(fp, "%sbg=[ RGB:r,g,b | YCBCR:y,cb,cr |\n", prefix); fprintf(fp, "%s RGBA:r,g,b,a | YCBCR:y,cb,cr,a ] (YCBCRA:%d,%d,%d,%d)\n", prefix, defbg(0), defbg(1), defbg(2), defbg(3)); } fprintf(fp, "%snorm=[ NTSC | PAL | SECAM ]\n", prefix); fprintf(fp, "%silace=[ NONE | TOP_FIRST | BOTTOM_FIRST | TOP_ONLY | BOTTOM_ONLY ]\n", prefix); { fprintf(fp, "%schromass=[ ", prefix); int i = 0; const char *keyword; while ((keyword = y4m_chroma_keyword(i++)) != NULL) fprintf(fp, "%s%s ", (i < 2) ? "" : "| ", keyword); fprintf(fp, "]\n"); } fprintf(fp, "%ssar=[ N:D | NTSC | PAL | NTSC_WIDE | PAL_WIDE ]\n", prefix); } void ysSource::fake_progressive(FakeProg_t f) { if (f) { if ( (_stream.interlace() == Y4M_UNKNOWN) || (_stream.interlace() == Y4M_ILACE_NONE) ) { mjpeg_error_exit1("Must be interlaced to fake non-interlaced!"); } if (_stream.interlace() == Y4M_ILACE_MIXED) mjpeg_error_exit1("Cannot fake non-interlaced from mixed-mode source!"); if (f == FAKE_TOP_ONLY) mjpeg_info("Faking non-interlaced source; using top field only."); else mjpeg_info("Faking non-interlaced source; using bottom field only."); _fake_progressive = f; _real_stream = _stream; _stream.interlace(Y4M_ILACE_NONE); _stream.y_size(_stream.y_size() / 2); _stream.sar(_stream.sar() / 2); // ???????? if (_fake_field[0] != NULL) delete[] _fake_field[0]; _fake_field[0] = new uint8_t[_real_stream.fielddim().area()]; _fake_field[1] = _fake_field[2] = _fake_field[0]; } } void ysSource::parse_keyword(char *optarg) { if (!strncasecmp(optarg, "ACTIVE=", 7)) { if (_active_region.parse_geometry(optarg+7)) { mjpeg_error_exit1("Bad ACTIVE keyword: '%s'", optarg); } } else if (!strncasecmp(optarg, "MATTE=", 6)) { if (_matte_region.parse_geometry(optarg+6)) { mjpeg_error_exit1("Bad MATTE keyword: '%s'", optarg); } } else if (!strncasecmp(optarg, "BG=", 3)) { bgcolor(ysYCbCr::parse_string(optarg+3)); } else if (!strcasecmp(optarg, "NORM=NTSC")) { norm(NORM_NTSC); } else if (!strcasecmp(optarg, "NORM=PAL")) { norm(NORM_PAL); } else if (!strcasecmp(optarg, "NORM=SECAM")) { norm(NORM_PAL); } else if (!strncasecmp(optarg, "CHROMASS=", 9)) { // if (_stream.subsampling().parse_mode(optarg+9)) { if (_stream.subsampling().is_known()) { mjpeg_warn("Overriding source's chroma subsampling mode!"); // Was %s", // _stream.subsampling().mode_to_string()); } if (_stream.parse_subsampling(optarg+9)) { mjpeg_error_exit1("Bad chroma subsampling spec: '%s'", optarg); } } else if (!strncasecmp(optarg, "ILACE=", 6)) { if (!strcasecmp(optarg+6, "TOP_FIRST")) { interlace(Y4M_ILACE_TOP_FIRST); } else if (!strcasecmp(optarg+6, "BOTTOM_FIRST")) { interlace(Y4M_ILACE_BOTTOM_FIRST); } else if (!strcasecmp(optarg+6, "NONE")) { interlace(Y4M_ILACE_NONE); } else if (!strcasecmp(optarg+6, "TOP_ONLY")) { fake_progressive(FAKE_TOP_ONLY); } else if (!strcasecmp(optarg+6, "BOTTOM_ONLY")) { fake_progressive(FAKE_BOT_ONLY); } else { mjpeg_error_exit1("Bad interlace spec: '%s'", optarg); } } else if (!strncasecmp(optarg, "SAR=", 4)) { ysRatio sar; if (!strcasecmp(optarg+4, "NTSC")) { sar = y4m_sar_NTSC_CCIR601; } else if (!strcasecmp(optarg+4, "PAL")) { sar = y4m_sar_PAL_CCIR601; } else if (!strcasecmp(optarg+4, "NTSC_WIDE")) { sar = y4m_sar_NTSC_16_9; } else if (!strcasecmp(optarg+4, "PAL_WIDE")) { sar = y4m_sar_PAL_16_9; } else if (sar.parse_ratio(optarg+4)) { mjpeg_error_exit1("Bad ratio spec: '%s'", optarg); } _stream.sar(sar); } else mjpeg_error_exit1 ("Unrecognized input parameter: '%s'", optarg); } void ysSource::check_parameters() { int cause_to_exit = 0; /* init interlacing */ if (_stream.interlace() == Y4M_UNKNOWN) { mjpeg_error("Source interlacing is unknown!"); cause_to_exit = 1; } /* init/constrain SAR */ if (!_stream.sar().is_known()) { mjpeg_error("Source sample aspect ratio unknown!"); cause_to_exit = 1; } /* init/constrain chroma subsampling */ if (!_stream.subsampling().is_known()) { mjpeg_error("Source chroma subsampling is unknown!"); cause_to_exit = 1; } /* init/clip matte region */ /* default is entire source frame --- so convolution can extend beyond the active region */ if (!_matte_region.is_known()) { if (_matte_region.offset().is_known()) { mjpeg_info("Source matte region defaulting to source frame size."); _matte_region.dim(_stream.dim()); } else { mjpeg_info("Source matte region defaulting to full source frame."); _matte_region = ysRegion(_stream.dim()); _matte_region.origin_mode(ANC_TL); } } _matte_region.fixate(_stream.dim()); /* check alignment */ /* frame size and matte region must conform to alignment */ { int xal = _stream.x_alignment(); int yal = _stream.y_alignment(); if (_stream.x_size() % xal) { mjpeg_error("Source x size (%d) is not multiple of %d!", _stream.x_size(), xal); cause_to_exit = 1; } if (_stream.y_size() % yal) { mjpeg_error("Source y size (%d) is not multiple of %d!", _stream.y_size(), yal); cause_to_exit = 1; } if (_matte_region.dim().x() % xal) { mjpeg_error("Source matte region x size (%d) is not multiple of %d!", _matte_region.dim().x(), xal); cause_to_exit = 1; } if (_matte_region.offset().x() % xal) { mjpeg_error("Source matte region x offset (%d) is not multiple of %d!", _matte_region.offset().x(), xal); cause_to_exit = 1; } if (_matte_region.dim().y() % yal) { mjpeg_error("Source matte region y size (%d) is not multiple of %d!", _matte_region.dim().y(), yal); cause_to_exit = 1; } if (_matte_region.offset().y() % yal) { mjpeg_error("Source matte region y offset (%d) is not multiple of %d!", _matte_region.offset().y(), yal); cause_to_exit = 1; } } if (cause_to_exit) exit(1); /* init/clip active region */ if (!_active_region.is_known()) { if (_active_region.offset().is_known()) { mjpeg_info("Source active region defaulting to source frame size."); _active_region.dim(_stream.dim()); } else { mjpeg_info("Source active region defaulting to full source frame."); _active_region = ysRegion(_stream.dim()); _active_region.origin_mode(ANC_TL); } } _active_region.fixate(_stream.dim()); #if 0 /* do clipping later, after ratios are established */ if (_active_region.clip(ysRatioPoint(_stream.dim()))) { mjpeg_warn("Source active region clipped by frame size."); } #endif } void ysSource::describe_parameters() const { mjpeg_info("=== SOURCE parameters: ================="); if (_fake_progressive) { mjpeg_info("< effective stream:"); } else { mjpeg_info("< stream:"); } mjpeg_info("< %dx%d, SAR %d:%d, %s", _stream.x_size(), _stream.y_size(), _stream.sar().ratio().n, _stream.sar().ratio().d, ilace_to_string(_stream.interlace())); mjpeg_info("< chroma subsampling: %s", _stream.subsampling().mode_to_string()); mjpeg_info("< chroma ss ratios: x %d:%d y %d:%d", _stream.subsampling().ratio().x().numerator(), _stream.subsampling().ratio().x().denominator(), _stream.subsampling().ratio().y().numerator(), _stream.subsampling().ratio().y().denominator()); mjpeg_info("< active region:"); mjpeg_info("< %fx%f at %f,%f", _active_region.dim().x().to_double(), _active_region.dim().y().to_double(), _active_region.offset().x().to_double(), _active_region.offset().y().to_double()); mjpeg_info("< matte region:"); mjpeg_info("< %dx%d at %d,%d (bg Y'CbCr: %d,%d,%d)", _matte_region.dim().x(), _matte_region.dim().y(), _matte_region.offset().x(), _matte_region.offset().y(), _bgcolor(0), _bgcolor(1), _bgcolor(2)); } int ysSource::read_stream_header(int fdin) { return _stream.read_stream_header(fdin); } #if 0 static int internal_read_444_frame(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const yuv[3]) { int err; int w = y4m_si_get_width(si); int h = y4m_si_get_height(si); /* Read frame header */ if ((err = y4m_read_frame_header(fd, si, fi)) != Y4M_OK) return err; /* Read luminance scanlines */ if (y4m_read(fd, yuv[0], w*h)) return Y4M_ERR_SYSTEM; /* Read chrominance scanlines */ if (y4m_read(fd, yuv[1], w*h)) return Y4M_ERR_SYSTEM; if (y4m_read(fd, yuv[2], w*h)) return Y4M_ERR_SYSTEM; return Y4M_OK; } static int internal_read_422_frame(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const yuv[3]) { int err; int w = y4m_si_get_width(si); int h = y4m_si_get_height(si); /* Read frame header */ if ((err = y4m_read_frame_header(fd, si, fi)) != Y4M_OK) return err; /* Read luminance scanlines */ if (y4m_read(fd, yuv[0], w*h)) return Y4M_ERR_SYSTEM; /* Read chrominance scanlines */ if (y4m_read(fd, yuv[1], w*h/2)) return Y4M_ERR_SYSTEM; if (y4m_read(fd, yuv[2], w*h/2)) return Y4M_ERR_SYSTEM; return Y4M_OK; } static int internal_read_411_fields(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const upper_field[3], uint8_t * const lower_field[3]) { int i, y, err; int width = y4m_si_get_width(si); int height = y4m_si_get_height(si); /* Read frame header */ if ((err = y4m_read_frame_header(fd, si, fi)) != Y4M_OK) return err; /* Read Y', Cb, and Cr planes */ for (i = 0; i < 3; i++) { uint8_t *srctop = upper_field[i]; uint8_t *srcbot = lower_field[i]; /* alternately write one line from each */ for (y = 0; y < height; y += 2) { if (y4m_read(fd, srctop, width)) return Y4M_ERR_SYSTEM; srctop += width; if (y4m_read(fd, srcbot, width)) return Y4M_ERR_SYSTEM; srcbot += width; } /* for chroma, width/height are half as big */ if (i == 0) { width /= 4; // height /= 2; } } return Y4M_OK; } static int internal_read_422_fields(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const upper_field[3], uint8_t * const lower_field[3]) { int i, y, err; int width = y4m_si_get_width(si); int height = y4m_si_get_height(si); /* Read frame header */ if ((err = y4m_read_frame_header(fd, si, fi)) != Y4M_OK) return err; /* Read Y', Cb, and Cr planes */ for (i = 0; i < 3; i++) { uint8_t *srctop = upper_field[i]; uint8_t *srcbot = lower_field[i]; /* alternately write one line from each */ for (y = 0; y < height; y += 2) { if (y4m_read(fd, srctop, width)) return Y4M_ERR_SYSTEM; srctop += width; if (y4m_read(fd, srcbot, width)) return Y4M_ERR_SYSTEM; srcbot += width; } /* for chroma, width/height are half as big */ if (i == 0) { width /= 2; // height /= 2; } } return Y4M_OK; } static int internal_read_444_fields(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const upper_field[3], uint8_t * const lower_field[3]) { int i, y, err; int width = y4m_si_get_width(si); int height = y4m_si_get_height(si); /* Read frame header */ if ((err = y4m_read_frame_header(fd, si, fi)) != Y4M_OK) return err; /* Read Y', Cb, and Cr planes */ for (i = 0; i < 3; i++) { uint8_t *srctop = upper_field[i]; uint8_t *srcbot = lower_field[i]; /* alternately write one line from each */ for (y = 0; y < height; y += 2) { if (y4m_read(fd, srctop, width)) return Y4M_ERR_SYSTEM; srctop += width; if (y4m_read(fd, srcbot, width)) return Y4M_ERR_SYSTEM; srcbot += width; } } return Y4M_OK; } #endif #if 0 int ysSource::read_frame(int fdin, y4m_frame_info_t *frameinfo, uint8_t **frame) { #if 1 switch (_fake_progressive) { case FAKE_NO_FAKE: switch (_stream.subsampling().mode()) { case ysSubsampling::SS_444: return internal_read_444_frame(fdin, _stream.streaminfo(), frameinfo, frame); case ysSubsampling::SS_422: return internal_read_422_frame(fdin, _stream.streaminfo(), frameinfo, frame); case ysSubsampling::SS_411: case ysSubsampling::SS_420_JPEG: case ysSubsampling::SS_420_MPEG2: case ysSubsampling::SS_420_PALDV: default: return y4m_read_frame(fdin, _stream.streaminfo(), frameinfo, frame); } case FAKE_TOP_ONLY: switch (_stream.subsampling().mode()) { case ysSubsampling::SS_411: return internal_read_411_fields(fdin, _real_stream.streaminfo(), frameinfo, frame, _fake_field); case ysSubsampling::SS_444: return internal_read_444_fields(fdin, _real_stream.streaminfo(), frameinfo, frame, _fake_field); case ysSubsampling::SS_422: return internal_read_422_fields(fdin, _real_stream.streaminfo(), frameinfo, frame, _fake_field); case ysSubsampling::SS_420_JPEG: case ysSubsampling::SS_420_MPEG2: case ysSubsampling::SS_420_PALDV: default: return y4m_read_fields(fdin, _real_stream.streaminfo(), frameinfo, frame, _fake_field); } case FAKE_BOT_ONLY: switch (_stream.subsampling().mode()) { case ysSubsampling::SS_411: return internal_read_411_fields(fdin, _real_stream.streaminfo(), frameinfo, _fake_field, frame); case ysSubsampling::SS_444: return internal_read_444_fields(fdin, _real_stream.streaminfo(), frameinfo, _fake_field, frame); case ysSubsampling::SS_422: return internal_read_422_fields(fdin, _real_stream.streaminfo(), frameinfo, _fake_field, frame); case ysSubsampling::SS_420_JPEG: case ysSubsampling::SS_420_MPEG2: case ysSubsampling::SS_420_PALDV: default: return y4m_read_fields(fdin, _real_stream.streaminfo(), frameinfo, _fake_field, frame); } } return -1; /*????? */ #else switch (_fake_progressive) { case FAKE_NO_FAKE: return y4m_read_frame(fdin, _stream.streaminfo(), frameinfo, frame); case FAKE_TOP_ONLY: return y4m_read_fields(fdin, _real_stream.streaminfo(), frameinfo, frame, _fake_field); case FAKE_BOT_ONLY: return y4m_read_fields(fdin, _real_stream.streaminfo(), frameinfo, _fake_field, frame); } return -1; /*????? */ #endif } #endif #if 0 int ysSource::read_fields(int fdin, y4m_frame_info_t *frameinfo, uint8_t **topfield, uint8_t **bottomfield) { switch (_stream.subsampling().mode()) { case ysSubsampling::SS_411: return internal_read_411_fields(fdin, _stream.streaminfo(), frameinfo, topfield, bottomfield); case ysSubsampling::SS_444: return internal_read_444_fields(fdin, _stream.streaminfo(), frameinfo, topfield, bottomfield); case ysSubsampling::SS_422: return internal_read_422_fields(fdin, _stream.streaminfo(), frameinfo, topfield, bottomfield); case ysSubsampling::SS_420_JPEG: case ysSubsampling::SS_420_MPEG2: case ysSubsampling::SS_420_PALDV: default: return y4m_read_fields(fdin, _stream.streaminfo(), frameinfo, topfield, bottomfield); } } #endif int ysSource::read_frame(int fdin, y4m_frame_info_t *frameinfo, uint8_t **frame) { switch (_fake_progressive) { case FAKE_NO_FAKE: return y4m_read_frame(fdin, _stream.streaminfo(), frameinfo, frame); case FAKE_TOP_ONLY: return y4m_read_fields(fdin, _real_stream.streaminfo(), frameinfo, frame, _fake_field); case FAKE_BOT_ONLY: return y4m_read_fields(fdin, _real_stream.streaminfo(), frameinfo, _fake_field, frame); } return -1; /*????? */ } int ysSource::read_frame_data(int fdin, y4m_frame_info_t *frameinfo, uint8_t **frame) { switch (_fake_progressive) { case FAKE_NO_FAKE: return y4m_read_frame_data(fdin, _stream.streaminfo(), frameinfo, frame); case FAKE_TOP_ONLY: return y4m_read_fields_data(fdin, _real_stream.streaminfo(), frameinfo, frame, _fake_field); case FAKE_BOT_ONLY: return y4m_read_fields_data(fdin, _real_stream.streaminfo(), frameinfo, _fake_field, frame); } return -1; /*????? */ } int ysSource::read_fields(int fdin, y4m_frame_info_t *frameinfo, uint8_t **topfield, uint8_t **bottomfield) { return y4m_read_fields(fdin, _stream.streaminfo(), frameinfo, topfield, bottomfield); } int ysSource::read_fields_data(int fdin, y4m_frame_info_t *frameinfo, uint8_t **topfield, uint8_t **bottomfield) { return y4m_read_fields_data(fdin, _stream.streaminfo(), frameinfo, topfield, bottomfield); } #if 0 // Should probably just remove this... int ysSource::read_frame_or_fields(int fdin, y4m_frame_info_t *frameinfo, uint8_t **frame, uint8_t **upper, uint8_t **lower) { int err; err = y4m_read_frame_header(fdin, _stream.streaminfo(), frameinfo); if (err != Y4M_OK) return err; mjpeg_info("F-or-F: %d %d", y4m_fi_get_temporal(frameinfo), y4m_fi_get_spatial(frameinfo)); /* XXXXXX what about ip/pi/420 issues? XXXXXXX */ int sampling = y4m_fi_get_temporal(frameinfo); if (sampling == Y4M_SAMPLING_PROGRESSIVE) return y4m_read_frame_data(fdin, _stream.streaminfo(), frameinfo, frame); else /* == Y4M_SAMPLING_INTERLACED */ return y4m_read_fields_data(fdin, _stream.streaminfo(), frameinfo, upper, lower); } #endif int ysSource::read_frame_header(int fdin, y4m_frame_info_t *frameinfo) { return y4m_read_frame_header(fdin, _stream.streaminfo(), frameinfo); } mjpegtools-2.1.0/y4mscaler/scaler.H0000644000175000017500000000602412051575455017511 0ustar glowwormglowworm/* Copyright 2003 Matthew Marjanovic This file is part of y4mscaler. y4mscaler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. y4mscaler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with y4mscaler; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _YS_SCALER_H_ #define _YS_SCALER_H_ #include "graphics.H" /* * ysScaler is a generic interface to a scaling engine. * ysScalerFactory is a generic interface to a factory class which creates * instances of the scaling engine. * * ysScaler has two public methods, setup() and scale() (as well as a virtual * destructor). * * setup() initializes/sets-up the engine to perform a specific scaling * operation. * * source_size: XxY size of the whole source frame * source_offset: (x,y) position of the upper-left corner of * the source region * dest_size: XxY size of the target frame * dest_region: XxY size and (x,y) position of the target region * (within the target frame) * x_scale: X scale factor (target/source) * y_scale: Y scale factor (target/source) * matte_pixel: background value used for pixels outside of the source * region * * setup() returns 0 on success, non-zero on failure. * Failure may occur is the engine cannot provide the requested scaling. * * * scale() actually performs the scaling, given source and target buffers. * Pixels in the target frame which lie outside of the target region * are left alone. * * source: raster buffer of source pixels (row-major ordering) * target: raster buffer of target pixels (row-major ordering) * */ class ysScaler { public: virtual ~ysScaler() {} virtual int setup(const ysPoint &source_size, const ysRatioPoint &source_offset, const ysRegion &source_matte, const ysPoint &dest_size, const ysRegion &dest_region, const ysRatio &x_scale, const ysRatio &y_scale, uint8_t matte_pixel) = 0; virtual int scale(uint8_t *source, uint8_t *dest) = 0; }; class ysScalerFactory { public: virtual ~ysScalerFactory() {} virtual const char *description() const = 0; virtual void describe_options(FILE *fp, const char *prefix) const = 0; virtual int parse_option(const char *s) = 0; typedef void (logging_function)(const char format[], ...); virtual void describe_parameters(logging_function *logger, const char *prefix) const = 0; virtual ysScaler *new_scaler() const = 0; }; #endif /* _YS_SCALER_H_ */ mjpegtools-2.1.0/y4mscaler/graphics.C0000644000175000017500000005676212051575455020051 0ustar glowwormglowworm/* Copyright 2003 Matthew Marjanovic This file is part of y4mscaler. y4mscaler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. y4mscaler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with y4mscaler; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "y4m-config.h" #include "debug.h" #include #include #include "graphics.H" // const uint8_t ysYCbCr::Y_black = 16; // const uint8_t ysYCbCr::Y_white = 219; ysYCbCr ysYCbCr::parse_string(char *s) { if (!strncasecmp(s, "RGB:", 4)) { int r, g, b; if (sscanf(s+4, "%u,%u,%u", &r, &g, &b) == 3) { return ysYCbCr((int)(16.5 + 219.0 * (0.299 * (double)r / 255.0 + 0.587 * (double)g / 255.0 + 0.114 * (double)b / 255.0)), (int)(128.5 + 224.0 * (-0.168736 * (double)r / 255.0 + -0.331264 * (double)g / 255.0 + 0.500 * (double)b / 255.0)), (int)(128.5 + 224.0 * (0.500 * (double)r / 255.0 + -0.418688 * (double)g / 255.0 + -0.081312 * (double)b / 255.0)) ); } } else if (!strncasecmp(s, "YCBCR:", 6)) { int y, cb, cr; if (sscanf(s+6, "%u,%u,%u", &y, &cb, &cr) == 3) { return ysYCbCr(y, cb, cr); } } if (!strncasecmp(s, "RGBA:", 5)) { int r, g, b, a; if (sscanf(s+5, "%u,%u,%u,%u", &r, &g, &b, &a) == 4) { return ysYCbCr((int)(16.5 + 219.0 * (0.299 * (double)r / 255.0 + 0.587 * (double)g / 255.0 + 0.114 * (double)b / 255.0)), (int)(128.5 + 224.0 * (-0.168736 * (double)r / 255.0 + -0.331264 * (double)g / 255.0 + 0.500 * (double)b / 255.0)), (int)(128.5 + 224.0 * (0.500 * (double)r / 255.0 + -0.418688 * (double)g / 255.0 + -0.081312 * (double)b / 255.0)), (int)(16.5 + 219.0 * (double)a / 255.0) ); } } else if (!strncasecmp(s, "YCBCRA:", 7)) { int y, cb, cr, a; if (sscanf(s+7, "%u,%u,%u,%u", &y, &cb, &cr, &a) == 4) { return ysYCbCr(y, cb, cr, a); } } return ysYCbCr(); } /* * Euler's algorithm for greatest common divisor */ int64_t ysRatio::_gcd64(int64_t a, int64_t b) { a = (a >= 0) ? a : -a; b = (b >= 0) ? b : -b; while (b > 0) { int64_t x = b; b = a % b; a = x; } return a; } void ysRatio::_reduce64(int64_t &nn, int64_t &dd) { int64_t c; if ((nn == 0) && (dd == 0)) return; /* "unknown" */ c = _gcd64(nn, dd); nn = (int64_t)nn / c; dd = (int64_t)dd / c; } /* a ratio can be expressed as either "N:D" or "N/D" (same meaning either way) sometimes one way is easier to think of than the other... D must be strictly positive. */ int ysRatio::parse_ratio(const char *s) { int n, d; if ( !( (sscanf(s, "%d/%d", &n, &d) == 2) || (sscanf(s, "%d:%d", &n, &d) == 2) ) || (d <= 0) ) // ((n == 0) && (d == 0)) ) return 1; r.n = n; r.d = d; y4m_ratio_reduce(&r); return 0; } int ysRegion::parse_geometry(const char *s) { /* XXXXxYYYY+NNN+NNNcc */ int sx, sy, ox, oy; char origin[5], signX, signY; int args; if (strchr(s, 'x')) { args = sscanf(s, "%ux%u%c%d%c%d%2s", &sx, &sy, &signX, &ox, &signY, &oy, origin); if ((args != 6) && (args != 7)) return 1; _dim = ysPoint(sx, sy); } else { args = sscanf(s, "%c%d%c%d%2s", &signX, &ox, &signY, &oy, origin); if ((args != 4) && (args != 5)) return 1; _dim = ysPoint(); } DBG("signX %c signY %c\n", signX, signY); switch (signX) { case '+': break; case '-': ox = -ox; break; default: return 1; } switch (signY) { case '+': break; case '-': oy = -oy; break; default: return 1; } if (args == 7) { _origin_mode = parse_anchor_mode(origin); if (_origin_mode == ANC_UNKNOWN) return 1; } else { _origin_mode = ANC_TL; } _offset = ysPoint(ox, oy); return 0; } #if 0 int ysRatioRegion::parse_geometry(const char *s) { /* XXXXxYYYY+NNN+NNNcc */ int sx, sy, ox, oy; char origin[5], signX, signY; int args; args = sscanf(s, "%ux%u%c%d%c%d%2s", &sx, &sy, &signX, &ox, &signY, &oy, origin); if ((args != 6) && (args != 7)) return 1; DBG("signX %c signY %c\n", signX, signY); switch (signX) { case '+': break; case '-': ox = -ox; break; default: return 1; } switch (signY) { case '+': break; case '-': oy = -oy; break; default: return 1; } if (args == 7) { _origin_mode = parse_anchor_mode(origin); if (_origin_mode == ANC_UNKNOWN) return 1; } else { _origin_mode = ANC_TL; } _dim = ysRatioPoint(sx, sy); _offset = ysRatioPoint(ox, oy); return 0; } #else int ysRatioRegion::parse_geometry(const char *s) { /* XXXXxYYYY+NNN+NNNcc */ int sx, sy, ox, oy; char origin[5], signX, signY; int args; if (strchr(s, 'x')) { args = sscanf(s, "%ux%u%c%d%c%d%2s", &sx, &sy, &signX, &ox, &signY, &oy, origin); if ((args != 6) && (args != 7)) return 1; _dim = ysRatioPoint(sx, sy); } else { args = sscanf(s, "%c%d%c%d%2s", &signX, &ox, &signY, &oy, origin); if ((args != 4) && (args != 5)) return 1; _dim = ysRatioPoint(); /* unknown */ } DBG("signX %c signY %c\n", signX, signY); switch (signX) { case '+': break; case '-': ox = -ox; break; default: return 1; } switch (signY) { case '+': break; case '-': oy = -oy; break; default: return 1; } if (args == 7) { _origin_mode = parse_anchor_mode(origin); if (_origin_mode == ANC_UNKNOWN) return 1; } else { _origin_mode = ANC_TL; } _offset = ysRatioPoint(ox, oy); return 0; } #endif enum AnchorMode_t parse_anchor_mode(const char *s) { if (!strcasecmp("TL", s)) return ANC_TL; else if (!strcasecmp("TC", s)) return ANC_TC; else if (!strcasecmp("TR", s)) return ANC_TR; else if (!strcasecmp("CL", s)) return ANC_CL; else if (!strcasecmp("CC", s)) return ANC_CC; else if (!strcasecmp("CR", s)) return ANC_CR; else if (!strcasecmp("BL", s)) return ANC_BL; else if (!strcasecmp("BC", s)) return ANC_BC; else if (!strcasecmp("BR", s)) return ANC_BR; else return ANC_UNKNOWN; } int ysRegion::clip(const ysRegion &bounds) { int clipped = 0; int ox = _offset.x(); int oy = _offset.y(); int px = ox + _dim.x(); int py = oy + _dim.y(); if (ox < bounds.offset().x()) { ox = bounds.offset().x(); clipped = 1; } if (oy < bounds.offset().y()) { oy = bounds.offset().y(); clipped = 1; } if (px > (bounds.offset().x() + bounds.dim().x())) { px = bounds.offset().x() + bounds.dim().x(); clipped = 1; } if (py > (bounds.offset().y() + bounds.dim().y())) { py = bounds.offset().y() + bounds.dim().y(); clipped = 1; } if (clipped) { _offset = ysPoint(ox,oy); _dim = ysPoint(px - ox, py - oy); } return clipped; } int ysRegion::clip(const ysRatioRegion &bounds) { int clipped = 0; ysRatio ox = _offset.x(); ysRatio oy = _offset.y(); ysRatio px = ox + _dim.x(); ysRatio py = oy + _dim.y(); DBG("ox,oy: %f, %f\n", ox.to_double(), oy.to_double()); DBG("px,py: %f, %f\n", px.to_double(), py.to_double()); DBG("b ox,y: %f, %f\n", bounds.offset().x().to_double(), bounds.offset().y().to_double()); DBG("b dx,y: %f, %f\n", bounds.dim().x().to_double(), bounds.dim().y().to_double()); if (ox < bounds.offset().x()) { ox = bounds.offset().x(); clipped = 1; } if (oy < bounds.offset().y()) { oy = bounds.offset().y(); clipped = 1; } if (px > (bounds.offset().x() + bounds.dim().x())) { px = bounds.offset().x() + bounds.dim().x(); clipped = 1; } if (py > (bounds.offset().y() + bounds.dim().y())) { py = bounds.offset().y() + bounds.dim().y(); clipped = 1; } if (clipped) { /* round TL corner upwards (inwards)... */ _offset = ysPoint((int)(ox.to_double() + 0.5), (int)(oy.to_double() + 0.5)); /* round BR corner downwards (inwards)... */ _dim = ysPoint((px - ox).to_int(), (py - oy).to_int()); DBG("o x,y: %d, %d\n", _offset.x(), _offset.y()); DBG("d x,y: %d, %d\n", _dim.x(), _dim.y()); } return clipped; } #if 0 void ysRegion::center_to(const ysRegion &bounds) { int ox = _offset.x(); int oy = _offset.y(); int cx = ox + (_dim.x() / 2); int cy = oy + (_dim.y() / 2); ox += (bounds.offset().x() + (bounds.dim().x() / 2)) - cx; oy += (bounds.offset().y() + (bounds.dim().y() / 2)) - cy; _offset = ysPoint(ox, oy); } #endif #if 0 int ysRatioRegion::clip(const ysRatioRegion &bounds) { int clipped = 0; ysRatio ox = _offset.x(); ysRatio oy = _offset.y(); ysRatio px = ox + _dim.x(); ysRatio py = oy + _dim.y(); if (ox < bounds.offset().x()) { ox = bounds.offset().x(); clipped = 1; } if (oy < bounds.offset().y()) { oy = bounds.offset().y(); clipped = 1; } if (px > (bounds.offset().x() + bounds.dim().x())) { px = bounds.offset().x() + bounds.dim().x(); clipped = 1; } if (py > (bounds.offset().y() + bounds.dim().y())) { py = bounds.offset().y() + bounds.dim().y(); clipped = 1; } if (clipped) { _offset = ysRatioPoint(ox,oy); _dim = ysRatioPoint(px - ox, py - oy); } return clipped; } #else ysRatioRegion ysRatioRegion::clip(const ysRatioRegion &bounds) { int clipped = 0; ysRatio ox = _offset.x(); ysRatio oy = _offset.y(); ysRatio px = ox + _dim.x(); ysRatio py = oy + _dim.y(); ysRatio dox = 0; ysRatio doy = 0; ysRatio dpx = 0; ysRatio dpy = 0; if (ox < bounds.ul().x()) { dox = bounds.ul().x() - ox; ox = bounds.ul().x(); clipped = 1; } if (oy < bounds.ul().y()) { doy = bounds.ul().y() - oy; oy = bounds.ul().y(); clipped = 1; } if (px > bounds.lr().x()) { dpx = bounds.lr().x() - px; px = bounds.lr().x(); clipped = 1; } if (py > bounds.lr().y()) { dpy = bounds.lr().y() - py; py = bounds.lr().y(); clipped = 1; } if (clipped) { _offset = ysRatioPoint(ox,oy); _dim = ysRatioPoint(px - ox, py - oy); } return ysRatioRegion((dpx - dox), (dpy - doy), dox, doy); } #endif void ysRatioRegion::center_to(const ysRatioRegion &bounds) { ysRatio ox = _offset.x(); ysRatio oy = _offset.y(); ysRatio cx = ox + (_dim.x() / 2); ysRatio cy = oy + (_dim.y() / 2); ox += (bounds.offset().x() + (bounds.dim().x() / 2)) - cx; oy += (bounds.offset().y() + (bounds.dim().y() / 2)) - cy; _offset = ysRatioPoint(ox, oy); } #if 1 void ysRegion::fixate(const ysPoint &framesize) { //align_to(rel_anchor(_origin_mode), // ysRatioRegion(framesize, ysPoint(0,0)).rel_anchor(_origin_mode)); DBG("ba %d %d ta %d %d\n", ysRegion(framesize).rel_anchor(_origin_mode).x(), ysRegion(framesize).rel_anchor(_origin_mode).y(), rel_anchor(_origin_mode).x(), rel_anchor(_origin_mode).y()); _offset += ysRegion(framesize).rel_anchor(_origin_mode) - rel_anchor(_origin_mode); } /* define anchor point as named corner point */ ysPoint ysRegion::rel_anchor(AnchorMode_t mode) const { switch (mode) { case ANC_TL: return ysPoint(0,0); case ANC_TC: return ysPoint(_dim.x() / 2, 0); case ANC_TR: return ysPoint(_dim.x(), 0); case ANC_CL: return ysPoint(0, _dim.y() / 2); case ANC_CC: return ysPoint(_dim.x() / 2, _dim.y() / 2); case ANC_CR: return ysPoint(_dim.x(), _dim.y() / 2); case ANC_BL: return ysPoint(0, _dim.y()); case ANC_BC: return ysPoint(_dim.x() / 2, _dim.y()); case ANC_BR: return ysPoint(_dim.x(), _dim.y()); case ANC_UNKNOWN: return ysPoint(); } return ysPoint(); } void ysRatioRegion::fixate(const ysRatioPoint &framesize) { //align_to(rel_anchor(_origin_mode), // ysRatioRegion(framesize, ysPoint(0,0)).rel_anchor(_origin_mode)); DBG("ba %f %f ta %f %f\n", ysRatioRegion(framesize).rel_anchor(_origin_mode).x().to_double(), ysRatioRegion(framesize).rel_anchor(_origin_mode).y().to_double(), rel_anchor(_origin_mode).x().to_double(), rel_anchor(_origin_mode).y().to_double()); _offset += ysRatioRegion(framesize).rel_anchor(_origin_mode) - rel_anchor(_origin_mode); } /* move *this so that its relative 'anchor' point coincides with the absolute 'fixed point' */ void ysRatioRegion::align_to(const ysRatioPoint &relative_anchor, const ysRatioPoint &fixed_point) { _offset = fixed_point - relative_anchor; } /* move *this so that its relative 'anchor' point coincides with the absolute 'fixed point' */ void ysRatioRegion::align_to(const ysRatioRegion &bounds, AnchorMode_t mode) { _offset = (bounds.offset() + bounds.rel_anchor(mode)) - rel_anchor(mode); } // something.align_to(something.rel_anchor(ANC_CC), // bounds.offset() + bounds.rel_anchor(ANC_CC)); /* define anchor point by fractional distance from TL */ ysRatioPoint ysRatioRegion::rel_anchor(ysRatioPoint &relative) const { return _dim * relative; } /* define anchor point as named corner point */ ysRatioPoint ysRatioRegion::rel_anchor(AnchorMode_t mode) const { switch (mode) { case ANC_TL: return ysRatioPoint(0,0); case ANC_TC: return ysRatioPoint(_dim.x() / 2, 0); case ANC_TR: return ysRatioPoint(_dim.x(), 0); case ANC_CL: return ysRatioPoint(0, _dim.y() / 2); case ANC_CC: return ysRatioPoint(_dim.x() / 2, _dim.y() / 2); case ANC_CR: return ysRatioPoint(_dim.x(), _dim.y() / 2); case ANC_BL: return ysRatioPoint(0, _dim.y()); case ANC_BC: return ysRatioPoint(_dim.x() / 2, _dim.y()); case ANC_BR: return ysRatioPoint(_dim.x(), _dim.y()); case ANC_UNKNOWN: return ysRatioPoint(); } return ysRatioPoint(); } #if 0 /* move *this so that its anchor point coincides with the * anchor point of bounds */ void ysRatioRegion::align_to(const ysRatioRegion &bounds) { ysRatio ox = _offset.x(); ysRatio oy = _offset.y(); ysRatio cx = ox + (_dim.x() / 2); ysRatio cy = oy + (_dim.y() / 2); ox += (bounds.offset().x() + (bounds.dim().x() / 2)) - cx; oy += (bounds.offset().y() + (bounds.dim().y() / 2)) - cy; _offset = ysRatioPoint(ox, oy); } #endif #endif #if 0 void ysSubsampling::mode(Mode amode) { _mode = amode; _offset[FRAME][PLANE_Y] = ysRatioPoint(0,0); _offset[UPPER_FIELD][PLANE_Y] = ysRatioPoint(0,0); _offset[LOWER_FIELD][PLANE_Y] = ysRatioPoint(0,0); switch (amode) { case SS_UNKNOWN: _ratio = ysRatioPoint(); _offset[FRAME][PLANE_Cb] = ysRatioPoint(); _offset[FRAME][PLANE_Cr] = ysRatioPoint(); _offset[UPPER_FIELD][PLANE_Cb] = ysRatioPoint(); _offset[UPPER_FIELD][PLANE_Cr] = ysRatioPoint(); _offset[LOWER_FIELD][PLANE_Cb] = ysRatioPoint(); _offset[LOWER_FIELD][PLANE_Cr] = ysRatioPoint(); break; // leave everything unknown; case SS_444: _ratio = ysRatioPoint(1,1); _offset[FRAME][PLANE_Cb] = ysRatioPoint(0,0); _offset[FRAME][PLANE_Cr] = ysRatioPoint(0,0); _offset[UPPER_FIELD][PLANE_Cb] = ysRatioPoint(0,0); _offset[UPPER_FIELD][PLANE_Cr] = ysRatioPoint(0,0); _offset[LOWER_FIELD][PLANE_Cb] = ysRatioPoint(0,0); _offset[LOWER_FIELD][PLANE_Cr] = ysRatioPoint(0,0); break; case SS_422: _ratio = ysRatioPoint(ysRatio(1,2), ysRatio(1)); _offset[FRAME][PLANE_Cb] = ysRatioPoint(0,0); _offset[FRAME][PLANE_Cr] = ysRatioPoint(0,0); _offset[UPPER_FIELD][PLANE_Cb] = ysRatioPoint(0,0); _offset[UPPER_FIELD][PLANE_Cr] = ysRatioPoint(0,0); _offset[LOWER_FIELD][PLANE_Cb] = ysRatioPoint(0,0); _offset[LOWER_FIELD][PLANE_Cr] = ysRatioPoint(0,0); break; case SS_420_JPEG: _ratio = ysRatioPoint(ysRatio(1,2), ysRatio(1,2)); _offset[FRAME][PLANE_Cb] = ysRatioPoint(ysRatio(1,2), ysRatio(1,2)); _offset[FRAME][PLANE_Cr] = ysRatioPoint(ysRatio(1,2), ysRatio(1,2)); _offset[UPPER_FIELD][PLANE_Cb] = ysRatioPoint(ysRatio(1,2), ysRatio(1,2)); _offset[UPPER_FIELD][PLANE_Cr] = ysRatioPoint(ysRatio(1,2), ysRatio(1,2)); _offset[LOWER_FIELD][PLANE_Cb] = ysRatioPoint(ysRatio(1,2), ysRatio(1,2)); _offset[LOWER_FIELD][PLANE_Cr] = ysRatioPoint(ysRatio(1,2), ysRatio(1,2)); break; case SS_420_MPEG2: _ratio = ysRatioPoint(ysRatio(1,2), ysRatio(1,2)); _offset[FRAME][PLANE_Cb] = ysRatioPoint(ysRatio(0), ysRatio(1,2)); _offset[FRAME][PLANE_Cr] = ysRatioPoint(ysRatio(0), ysRatio(1,2)); _offset[UPPER_FIELD][PLANE_Cb] = ysRatioPoint(ysRatio(0), ysRatio(1,4)); _offset[UPPER_FIELD][PLANE_Cr] = ysRatioPoint(ysRatio(0), ysRatio(1,4)); _offset[LOWER_FIELD][PLANE_Cb] = ysRatioPoint(ysRatio(0), ysRatio(3,4)); _offset[LOWER_FIELD][PLANE_Cr] = ysRatioPoint(ysRatio(0), ysRatio(3,4)); break; case SS_420_PALDV: _ratio = ysRatioPoint(ysRatio(1,2), ysRatio(1,2)); _offset[FRAME][PLANE_Cb] = ysRatioPoint(); // unknown _offset[FRAME][PLANE_Cr] = ysRatioPoint(); // unknonw _offset[UPPER_FIELD][PLANE_Cb] = ysRatioPoint(0, 1); _offset[UPPER_FIELD][PLANE_Cr] = ysRatioPoint(0, 0); _offset[LOWER_FIELD][PLANE_Cb] = ysRatioPoint(0, 1); _offset[LOWER_FIELD][PLANE_Cr] = ysRatioPoint(0, 0); break; case SS_411: _ratio = ysRatioPoint(ysRatio(1,4), ysRatio(1)); _offset[FRAME][PLANE_Cb] = ysRatioPoint(0,0); _offset[FRAME][PLANE_Cr] = ysRatioPoint(0,0); _offset[UPPER_FIELD][PLANE_Cb] = ysRatioPoint(0,0); _offset[UPPER_FIELD][PLANE_Cr] = ysRatioPoint(0,0); _offset[LOWER_FIELD][PLANE_Cb] = ysRatioPoint(0,0); _offset[LOWER_FIELD][PLANE_Cr] = ysRatioPoint(0,0); break; } } #endif void ysSubsampling::mode(Mode amode) { _mode = amode; _ratio = ysRatioPoint(y4m_chroma_ss_x_ratio(_mode), y4m_chroma_ss_y_ratio(_mode)); _offset[FRAME][PLANE_Y] = ysRatioPoint(0,0); _offset[UPPER_FIELD][PLANE_Y] = ysRatioPoint(0,0); _offset[LOWER_FIELD][PLANE_Y] = ysRatioPoint(0,0); _offset[FRAME][PLANE_ALPHA] = ysRatioPoint(0,0); _offset[UPPER_FIELD][PLANE_ALPHA] = ysRatioPoint(0,0); _offset[LOWER_FIELD][PLANE_ALPHA] = ysRatioPoint(0,0); switch (amode) { case SS_UNKNOWN: _offset[FRAME][PLANE_Cb] = ysRatioPoint(); _offset[FRAME][PLANE_Cr] = ysRatioPoint(); _offset[UPPER_FIELD][PLANE_Cb] = ysRatioPoint(); _offset[UPPER_FIELD][PLANE_Cr] = ysRatioPoint(); _offset[LOWER_FIELD][PLANE_Cb] = ysRatioPoint(); _offset[LOWER_FIELD][PLANE_Cr] = ysRatioPoint(); break; // leave everything unknown; case SS_444: case SS_444ALPHA: case SS_MONO: _offset[FRAME][PLANE_Cb] = ysRatioPoint(0,0); _offset[FRAME][PLANE_Cr] = ysRatioPoint(0,0); _offset[UPPER_FIELD][PLANE_Cb] = ysRatioPoint(0,0); _offset[UPPER_FIELD][PLANE_Cr] = ysRatioPoint(0,0); _offset[LOWER_FIELD][PLANE_Cb] = ysRatioPoint(0,0); _offset[LOWER_FIELD][PLANE_Cr] = ysRatioPoint(0,0); break; case SS_422: _offset[FRAME][PLANE_Cb] = ysRatioPoint(0,0); _offset[FRAME][PLANE_Cr] = ysRatioPoint(0,0); _offset[UPPER_FIELD][PLANE_Cb] = ysRatioPoint(0,0); _offset[UPPER_FIELD][PLANE_Cr] = ysRatioPoint(0,0); _offset[LOWER_FIELD][PLANE_Cb] = ysRatioPoint(0,0); _offset[LOWER_FIELD][PLANE_Cr] = ysRatioPoint(0,0); break; case SS_420_JPEG: _offset[FRAME][PLANE_Cb] = ysRatioPoint(ysRatio(1,2), ysRatio(1,2)); _offset[FRAME][PLANE_Cr] = ysRatioPoint(ysRatio(1,2), ysRatio(1,2)); _offset[UPPER_FIELD][PLANE_Cb] = ysRatioPoint(ysRatio(1,2), ysRatio(1,2)); _offset[UPPER_FIELD][PLANE_Cr] = ysRatioPoint(ysRatio(1,2), ysRatio(1,2)); _offset[LOWER_FIELD][PLANE_Cb] = ysRatioPoint(ysRatio(1,2), ysRatio(1,2)); _offset[LOWER_FIELD][PLANE_Cr] = ysRatioPoint(ysRatio(1,2), ysRatio(1,2)); break; case SS_420_MPEG2: _offset[FRAME][PLANE_Cb] = ysRatioPoint(ysRatio(0), ysRatio(1,2)); _offset[FRAME][PLANE_Cr] = ysRatioPoint(ysRatio(0), ysRatio(1,2)); _offset[UPPER_FIELD][PLANE_Cb] = ysRatioPoint(ysRatio(0), ysRatio(1,4)); _offset[UPPER_FIELD][PLANE_Cr] = ysRatioPoint(ysRatio(0), ysRatio(1,4)); _offset[LOWER_FIELD][PLANE_Cb] = ysRatioPoint(ysRatio(0), ysRatio(3,4)); _offset[LOWER_FIELD][PLANE_Cr] = ysRatioPoint(ysRatio(0), ysRatio(3,4)); break; case SS_420_PALDV: _offset[FRAME][PLANE_Cb] = ysRatioPoint(); // unknown _offset[FRAME][PLANE_Cr] = ysRatioPoint(); // unknonw _offset[UPPER_FIELD][PLANE_Cb] = ysRatioPoint(0, 1); _offset[UPPER_FIELD][PLANE_Cr] = ysRatioPoint(0, 0); _offset[LOWER_FIELD][PLANE_Cb] = ysRatioPoint(0, 1); _offset[LOWER_FIELD][PLANE_Cr] = ysRatioPoint(0, 0); break; case SS_411: _offset[FRAME][PLANE_Cb] = ysRatioPoint(0,0); _offset[FRAME][PLANE_Cr] = ysRatioPoint(0,0); _offset[UPPER_FIELD][PLANE_Cb] = ysRatioPoint(0,0); _offset[UPPER_FIELD][PLANE_Cr] = ysRatioPoint(0,0); _offset[LOWER_FIELD][PLANE_Cb] = ysRatioPoint(0,0); _offset[LOWER_FIELD][PLANE_Cr] = ysRatioPoint(0,0); break; } } /* * continuous position of (chroma) sample: x = (m - q) + 1/2 * * for 1:K subsampling, with pel offset D, * q = 1/2 - (2D + 1)/(2K) */ ysRatioPoint ysSubsampling::effective_sample_offset(Field field, Plane plane) const { ysRatioPoint D = offset(field, plane); ysRatioPoint K = ratio(); // return ysRatioPoint( ysRatio(1,2) - (D.x() * 2 + 1) / (K.x() / 2)), // ysRatio(1,2) - (D.y() * 2 + 1) / (K.y() / 2)) ); return ysRatioPoint( (ysRatio(1) - (D.x() * 2 + 1) * K.x()) / 2, (ysRatio(1) - (D.y() * 2 + 1) * K.y()) / 2 ); } int ysSubsampling::parse_mode(const char *s) { int chroma = y4m_chroma_parse_keyword(s); if (chroma != Y4M_UNKNOWN) { switch (chroma) { case Y4M_CHROMA_420JPEG: mode(ysSubsampling::SS_420_JPEG); break; case Y4M_CHROMA_420MPEG2: mode(ysSubsampling::SS_420_MPEG2); break; case Y4M_CHROMA_420PALDV: mode(ysSubsampling::SS_420_PALDV); break; case Y4M_CHROMA_411: mode(ysSubsampling::SS_411); break; case Y4M_CHROMA_422: mode(ysSubsampling::SS_422); break; case Y4M_CHROMA_444: mode(ysSubsampling::SS_444); break; case Y4M_CHROMA_444ALPHA: mode(ysSubsampling::SS_444ALPHA); break; // mjpeg_error("4:4:4/alpha streams not yet supported."); // return 1; case Y4M_CHROMA_MONO: mode(ysSubsampling::SS_MONO); break; // mjpeg_error("Mono/Luma-only streams not yet supported."); // return 1; default: mjpeg_error("Unknown (and/or unsupported) chroma format."); return 1; } return 0; } /* fall-back to old-style keywords */ if (!strcasecmp("444", s)) { mode(SS_444); return 0; } else if (!strcasecmp("422", s)) { mode(SS_422); return 0; } else if (!strcasecmp("420_jpeg", s)) { mode(SS_420_JPEG); return 0; } else if (!strcasecmp("420_mpeg2", s)) { mode(SS_420_MPEG2); return 0; } else if (!strcasecmp("420_paldv", s)) { mode(SS_420_PALDV); return 0; } else if (!strcasecmp("411", s)) { mode(SS_411); return 0; } else { return 1; } } #if 0 const char *ysSubsampling::mode_to_string() const { switch (_mode) { case SS_444: return "444"; case SS_422: return "422"; case SS_420_JPEG: return "420_JPEG"; case SS_420_MPEG2: return "420_MPEG2"; case SS_420_PALDV: return "420_PALDV"; case SS_411: return "411"; case SS_UNKNOWN: return "*unknown*"; } return "*unknown*"; } #endif const char *ysSubsampling::mode_to_string() const { const char *s = y4m_chroma_description(_mode); if (s == NULL) return "*unknown*"; else return s; } mjpegtools-2.1.0/y4mscaler/kernels.C0000644000175000017500000002614312051575455017702 0ustar glowwormglowworm/* Copyright 2003 Matthew Marjanovic This file is part of y4mscaler. y4mscaler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. y4mscaler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with y4mscaler; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "y4m-config.h" #include "debug.h" #include "kernels.H" #include #include #include /******************************************************************** * Plain-old Polynomial Kernels ********************************************************************/ class BoxKernel : public ysKernel { public: virtual const char *name() const { return "box"; } virtual const char *desc() const { return "Box (zero order)"; } virtual ysKernel *clone() const { return new BoxKernel(*this); } virtual double k(double t) const { #if 0 if (t < -0.5) return 0.0; if (t < 0.5) return 1.0; #elif 0 if (t <= -0.5) return 0.0; if (t < 0.5) return 1.0; #else if (t < -0.5) return 0.0; if (t <= 0.5) return 1.0; #endif return 0.0; } virtual double support() const { return 0.5; } }; class LinearKernel : public ysKernel { public: virtual const char *name() const { return "linear"; } virtual const char *desc() const { return "Linear (1st order)"; } virtual ysKernel *clone() const { return new LinearKernel(*this); } virtual double k(double t) const { if (t <= -1.0) return 0.0; if (t < 0.0) return (t + 1.0); if (t < 1.0) return (1.0 - t); return 0.0; } virtual double support() const { return 1.0; } }; class QuadraticKernel : public ysKernel { public: virtual const char *name() const { return "quadratic"; } virtual const char *desc() const { return "Quadratic (2rd order)"; } virtual ysKernel *clone() const { return new QuadraticKernel(*this); } virtual double k(double t) const { if (t < 0.0) t = -t; if (t < 0.5) return 0.75 - (t * t); if (t < 1.5) { t -= 1.5; return 0.5 * t * t; } return 0.0; } virtual double support() const { return 1.5; } }; /******************************************************************** * Cubic Kernels (BC-splines) * * B-spline: B=1, C=0 * Mitchell-Netravali: B=1/3, C=1/3 * Catmull-Rom: B=0, C=1/2 ********************************************************************/ class CubicBKernel : public ysKernel { public: virtual const char *name() const { return "cubicB"; } virtual const char *desc() const { return "Cubic, B-spline (3rd order)"; } virtual ysKernel *clone() const { return new CubicBKernel(*this); } virtual double k(double t) const { if (t < 0.0) t = -t; if (t < 1.0) { return (4.0 + (t * t * (-6.0 + (t * 3.0)))) / 6.0; } if (t < 2.0) { t = 2.0 - t; return t * t * t / 6.0; } return 0.0; } virtual double support() const { return 2.0; } }; class CubicMitchellKernel : public ysKernel { public: virtual const char *name() const { return "cubic"; } virtual const char *desc() const { return "Cubic, Mitchell-Netravali spline (3rd order)"; } virtual ysKernel *clone() const { return new CubicMitchellKernel(*this); } virtual double k(double t) const { if (t < 0.0) t = -t; if (t < 1.0) { return (16.0/3.0 + (t * (0.0 + (t * (-12.0 + (t * (7.0))))))) / 6.0; /* (3)t^3 - (6)t^2 + 4 */ /* (1)t^3 - (2)t^2 + 1 */ /* 3 6 3 */ /* 2(a+2) = a+3 2a+4=a+3 a=-1 */ } if (t < 2.0) { return (32.0/3.0 + (t * (-20.0 + (t * (12.0 + (t * -7.0/3.0)))))) / 6.0; } return 0.0; } virtual double support() const { return 2.0; } }; class CubicCatmullKernel : public ysKernel { public: virtual const char *name() const { return "cubicCR"; } virtual const char *desc() const { return "Cubic, Catmull-Rom spline (3rd order)"; } virtual ysKernel *clone() const { return new CubicCatmullKernel(*this); } virtual double k(double t) const { if (t < 0.0) t = -t; if (t < 1.0) return (2.0 + (t * t * (-5.0 + (t * 3.0)))) / 2.0; if (t < 2.0) return (4.0 + (t * (-8.0 + (t * (5.0 - t))))) / 2.0; return 0.0; } virtual double support() const { return 2.0; } }; class CubicKeys4Kernel : public ysKernel { public: virtual const char *name() const { return "cubicK4"; } virtual const char *desc() const { return "Keys 4th-order Cubic"; } virtual ysKernel *clone() const { return new CubicKeys4Kernel(*this); } virtual double k(double t) const { if (t < 0.0) t = -t; if (t < 1.0) return (3.0 + (t * t * (-7.0 + (t * 4.0)))) / 3.0; if (t < 2.0) return (30.0 + (t * (-59.0 + (t * (36.0 + (t * -7.0)))))) / 12.0; if (t < 3.0) return (-18.0 + (t * (21.0 + (t * (-8.0 + t))))) / 12.0; return 0.0; } virtual double support() const { return 3.0; } }; /******************************************************************** * Windowed Sinc Kernels ********************************************************************/ #define PI 3.1415926535897932384626433832795029L #if 0 class Sinc4Hann : public ysKernel { private: double _order; public: Sinc4Hann(void) : _order(4.0) {} virtual const char *name() const { return "sinc4hann"; } virtual const char *desc() const { return "Experimental Nth order Sinc"; } virtual ysKernel *clone() const { return new Sinc4Hann(*this); } virtual double k(double t) const { if (t < 0.0) t = -t; if (t == 0.0) { return 1.0; } else if (t < _order) { double w = 0.5 + (0.5)*cos(PI*t / _order); return w * sin(t*PI) / (t*PI); } else { return 0.0; } } virtual double support() const { return 1.0 * _order; } }; #endif #if 0 #include class Sinc4Lanczos : public ysKernel { private: double _order; public: Sinc4Lanczos(void) : _order(4.0) {} virtual const char *name() const { return "sinc4lan"; } virtual const char *desc() const { return "Sinc with Lanczos window, 4 cycles"; } virtual ysKernel *clone() const { return new Sinc4Lanczos(*this); } virtual double k(double t) const { if (t < 0.0) t = -t; if (t == 0.0) { // DBG("ZERO\n"); return 1.0; } else if (t < _order) { double w = sin(PI*t / _order) / (PI*t / _order); return w * sin(t*PI) / (t*PI); } else { return 0.0; } } virtual double support() const { return 1.0 * _order; } }; class Sinc8Lanczos : public ysKernel { private: double _order; public: Sinc8Lanczos(void) : _order(8.0) {} virtual const char *name() const { return "sinc8lan"; } virtual const char *desc() const { return "Sinc with Lanczos window, 8 cycles"; } virtual ysKernel *clone() const { return new Sinc8Lanczos(*this); } virtual double k(double t) const { if (t < 0.0) t = -t; if (t == 0.0) { return 1.0; } else if (t < _order) { double w = sin(PI*t / _order) / (PI*t / _order); return w * sin(t*PI) / (t*PI); } else { return 0.0; } } virtual double support() const { return 1.0 * _order; } }; #endif class SincLanczos : public ysKernel { private: double _order; public: SincLanczos(void) : _order(6.0) {} virtual const char *name() const { return "sinc"; } virtual const char *desc() const { return "Sinc with Lanczos window, N cycles [default: 6]"; } virtual ysKernel *clone() const { return new SincLanczos(*this); } virtual const char *pdesc() const { return ":N"; } virtual int pcount() const { return 1; } virtual int set_params(int count, double *params) { if (count == 1) { _order = params[0]; if (_order <= 0) return 1; } else if (count != 0) { return 1; } return 0; } virtual double param(int index) { /* just ignore index?? */ index = index; return _order; } virtual double k(double t) const { if (t < 0.0) t = -t; if (t == 0.0) { return 1.0; } else if (t < _order) { double w = sin(PI*t / _order) / (PI*t / _order); return w * sin(t*PI) / (t*PI); } else { return 0.0; } } virtual double support() const { return 1.0 * _order; } }; /************************************************************************ ************************************************************************ **** Kernel Factory: singleton which creates instances of kernels **** **** with given parameters **** ************************************************************************ ************************************************************************/ //ysKernelFactory *ysKernelFactory::_instance = NULL; const ysKernelFactory *ysKernelFactory::instance() { static ysKernelFactory *me = new ysKernelFactory; // if (_instance == NULL) // _instance = new ysKernelFactory; // return _instance; return me; } ysKernelFactory::ysKernelFactory() { _kernel_list = new ysKernel *[20]; _count = 0; _kernel_list[_count++] = new BoxKernel; _kernel_list[_count++] = new LinearKernel; _kernel_list[_count++] = new QuadraticKernel; _kernel_list[_count++] = new CubicMitchellKernel; _kernel_list[_count++] = new CubicCatmullKernel; _kernel_list[_count++] = new CubicBKernel; _kernel_list[_count++] = new CubicKeys4Kernel; // _kernel_list[_count++] = new Sinc10Kernel; // _kernel_list[_count++] = new Sinc4Hann; // _kernel_list[_count++] = new Sinc4Lanczos; // _kernel_list[_count++] = new Sinc8Lanczos; _kernel_list[_count++] = new SincLanczos; } static int count_delimiters(const char *s, char d) { if (s == NULL) return 0; int count = 0; for ( ; *s != '\0'; s++) { if (*s == d) count++; } return count; } ysKernel *ysKernelFactory::create_kernel(const char *name) const { /* parse "name:p1:p2...:pN" into name and array of parameters */ int num = count_delimiters(name, ':'); char *root = strdup(name); double *params = new double[num]; for (int n = num - 1; n >= 0; n--) { char *colon = strrchr(root, ':'); *colon = '\0'; params[n] = atof(colon+1); } ysKernel *new_kernel = NULL; /* lookup */ const ysKernel *prototype = lookup(root); if (prototype == NULL) goto bug_out; /* copy */ new_kernel = prototype->clone(); /* set params */ if (new_kernel->set_params(num, params)) { delete new_kernel; new_kernel = NULL; } bug_out: free(root); delete[] params; return new_kernel; } const ysKernel *ysKernelFactory::lookup(const char *name) const { int i; for (i = 0; i < _count; i++) { if (!strcmp(name, _kernel_list[i]->name())) return _kernel_list[i]; } return NULL; } const ysKernel *ysKernelFactory::lookup(int i) const { if ((i < 0) || (i >= _count)) return NULL; else return _kernel_list[i]; } mjpegtools-2.1.0/y4mscaler/INSTALL0000644000175000017500000000143712051575455017163 0ustar glowwormglowworm 0) Make sure you have the MJPEGtools library and header files installed on your system. The Makefile is setup to look for these in /usr/local/lib/libmjpegutils.a and /usr/local/include/mjpegtools/ You may need/want to edit "Makefile" to change MJPEG_PREFIX or other relevant parameters. 1) You may need to edit "y4m-config.h". The foreign build interface of MJPEGtools isn't quite up-to-speed yet. This file contains the necessary #defines from "mjpeg-config.h" for *my* system. Yours may be different. If you have built MJPEGtools, you can just copy it into y4m-config.h and everything should work a-ok. 2) Do a "make". 3) No errors? Great. There is no "make install". Just move "y4mscaler" to wherever you want it. 4) Scale away. -matt m. mjpegtools-2.1.0/y4mscaler/ysStreamInfo.H0000644000175000017500000001245312051575455020666 0ustar glowwormglowworm/* Copyright 2003 Matthew Marjanovic This file is part of y4mscaler. y4mscaler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. y4mscaler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with y4mscaler; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _YS_STREAM_H_ #define _YS_STREAM_H_ #include extern "C" { #include } #include "graphics.H" class ysStreamInfo { private: y4m_stream_info_t _streaminfo; ysSubsampling _subsampling; public: ysStreamInfo() { y4m_init_stream_info(&_streaminfo); } ~ysStreamInfo() { y4m_fini_stream_info(&_streaminfo); } ysStreamInfo(const ysStreamInfo &si); ysStreamInfo &operator=(const ysStreamInfo &si) { if (this != &si) { y4m_copy_stream_info(&_streaminfo, &si._streaminfo); _subsampling = si._subsampling; } return *this; } /* basic setters */ void x_size(int a) { y4m_si_set_width(&_streaminfo, a); } void y_size(int a) { y4m_si_set_height(&_streaminfo, a); } void interlace(int a) { y4m_si_set_interlace(&_streaminfo, a); } void framerate(const ysRatio &a) { y4m_si_set_framerate(&_streaminfo, a.ratio()); } void sar(const ysRatio &a) { y4m_si_set_sampleaspect(&_streaminfo, a.ratio()); } /* basic accessors */ int x_size() const { return y4m_si_get_width(&_streaminfo); } int y_size() const { return y4m_si_get_height(&_streaminfo); } int interlace() const { return y4m_si_get_interlace(&_streaminfo); } ysRatio framerate() const { return y4m_si_get_framerate(&_streaminfo); } ysRatio sar() const { return y4m_si_get_sampleaspect(&_streaminfo); } int planes() const { return y4m_si_get_plane_count(&_streaminfo); } const y4m_stream_info_t *streaminfo() const { return &_streaminfo; } const ysSubsampling &subsampling() const { return _subsampling; } /* chroma mode must be kept in sync... */ void subsampling(ysSubsampling::Mode amode) { y4m_si_set_chroma(&_streaminfo, amode); _subsampling.mode(amode); } /* derivative accessors */ int x_alignment() const; int y_alignment() const; // int planes() const { return 3; } ysPoint dim() const; ysPoint framedim(int plane = 0) const; ysPoint fielddim(int plane = 0) const; /* derivative setters */ void dim(const ysPoint &p); /* basic methods */ int read_stream_header(int fdin); int write_stream_header(int fdout); void log_info(log_level_t level, const char *prefix) const; /* derivative methods */ int parse_dimensions(const char *s); int parse_subsampling(const char *s); }; const char *ilace_to_string(int i); inline void ysStreamInfo::log_info(log_level_t level, const char *prefix) const { y4m_log_stream_info(level, prefix, &_streaminfo); } inline ysPoint ysStreamInfo::dim() const { int x = x_size(); int y = y_size(); if ((x == Y4M_UNKNOWN) || (y == Y4M_UNKNOWN)) return ysPoint(); else return ysPoint(x,y); } inline void ysStreamInfo::dim(const ysPoint &p) { if (p.is_known()) { x_size(p.x()); y_size(p.y()); } else { x_size(Y4M_UNKNOWN); y_size(Y4M_UNKNOWN); } } #if 0 inline ysPoint ysStreamInfo::framedim(int plane) const { switch (plane) { case 0: return dim(); break; case 1: case 2: { #if 0 int x = x_size(); int y = y_size(); x = (_subsampling.ratio().x() * x).to_int(); y = (_subsampling.ratio().y() * y).to_int(); return ysPoint(x,y); #endif return ysPoint((_subsampling.ratio().x() * x_size()).to_int(), (_subsampling.ratio().y() * y_size()).to_int()); } break; default: assert((plane >=0) && (plane <= 2)); break; } return ysPoint(); } inline ysPoint ysStreamInfo::fielddim(int plane) const { switch (plane) { case 0: return ysPoint(x_size(), y_size() / 2); break; case 1: case 2: { #if 0 int x = x_size(); int y = y_size(); x = (_subsampling.ratio().x() * x).to_int(); y = (_subsampling.ratio().y() * (y / 2)).to_int(); return ysPoint(x,y); #endif return ysPoint((_subsampling.ratio().x() * x_size()).to_int(), (_subsampling.ratio().y() * (y_size() / 2)).to_int()); } break; default: assert((plane >=0) && (plane <= 2)); break; } return ysPoint(); } #endif inline ysPoint ysStreamInfo::framedim(int plane) const { int x = y4m_si_get_plane_width(&_streaminfo, plane); int y = y4m_si_get_plane_height(&_streaminfo, plane); if ((x == Y4M_UNKNOWN) || (y == Y4M_UNKNOWN)) return ysPoint(); else return ysPoint(x, y); } inline ysPoint ysStreamInfo::fielddim(int plane) const { int x = y4m_si_get_plane_width(&_streaminfo, plane); int y = y4m_si_get_plane_height(&_streaminfo, plane); if ((x == Y4M_UNKNOWN) || (y == Y4M_UNKNOWN)) return ysPoint(); else return ysPoint(x, y/2); } #endif /* _YS_STREAM_H_ */ mjpegtools-2.1.0/y4mscaler/y4mscaler.C0000644000175000017500000001371712051575455020145 0ustar glowwormglowworm/* Copyright 2003 Matthew Marjanovic This file is part of y4mscaler. y4mscaler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. y4mscaler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with y4mscaler; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "y4m-config.h" #include "debug.h" #include #include "ysScaling.H" #include "ysSource.H" #include "ysTarget.H" void print_version(char *argv[]) { printf("%s is y4mscaler %d.%d\n", argv[0], YS_VERSION_MAJOR, YS_VERSION_MINOR); printf("Copyright 2004 Matthew J. Marjanovic\n"); } void print_usage(char *argv[], const ysSource &source, const ysTarget &target, const ysScaling &scaling) { print_version(argv); fprintf(stdout, "\n"); fprintf(stdout, "[This is just a summary --- read the manpage!]\n"); fprintf(stdout, "\n"); fprintf(stdout, "usage: %s [options...]\n", argv[0]); fprintf(stdout, "\n"); fprintf(stdout, " -I input_parameter:\n"); source.describe_keywords(stdout, " "); fprintf(stdout, "\n"); fprintf(stdout, " -O output_parameter:\n"); target.describe_keywords(stdout, " "); fprintf(stdout, "\n"); fprintf(stdout, " -S scaling_parameter:\n"); scaling.describe_keywords(stdout, " "); fprintf(stdout, "\n"); fprintf(stdout, " -v N verbosity: 0=quiet, 1=normal, 2=debug\n"); fprintf(stdout, " -V show version info and exit\n"); fprintf(stdout, " -h show this help message\n"); } enum parsing_mode_t { GLOBAL = 0, /* stream-independent arguments */ SOURCE, /* '-I' input arguments */ DEST /* '-O' output arguments */ }; static void parse_args(int argc, char *argv[], ysSource &source, ysTarget &target, ysScaling &scaling, parsing_mode_t mode) { int verbosity = 1; int c; optind = 1; while ((c = getopt(argc, argv, "I:O:S:v:hV")) != -1) { switch (mode) { case GLOBAL: /* process 'global' options only */ switch (c) { case 'v': verbosity = atoi (optarg); if (verbosity < 0 || verbosity > 2) { mjpeg_error_exit1("Verbosity level must be [0..2]"); } break; case 'h': print_usage(argv, source, target, scaling); exit(0); break; case 'V': print_version(argv); exit(0); break; case 'S': scaling.parse_keyword(optarg); break; case '?': mjpeg_error("Unknown option character: '%c'", c); mjpeg_error("Use '-h' to get usage hints."); exit(1); break; case 'I': case 'O': default: break; } break; case SOURCE: /* process stream-dependent options only */ switch (c) { case 'I': source.parse_keyword(optarg); break; case '?': mjpeg_error("Unknown option character: '%c'", c); mjpeg_error("Use '-h' to get usage hints."); exit(1); break; case 'O': case 'S': case 'v': case 'h': default: break; } break; case DEST: /* process stream-dependent options only */ switch (c) { case 'O': target.parse_keyword(source, optarg); break; case '?': mjpeg_error("Unknown option character: '%c'", c); mjpeg_error("Use '-h' to get usage hints."); exit(1); break; case 'I': case 'S': case 'v': case 'h': default: break; } break; } /* switch */ } /* while getopt */ if (mode == GLOBAL) mjpeg_default_handler_verbosity(verbosity); if (optind != argc) { mjpeg_error_exit1("STREAMS ONLY MY FRIEND!"); } return; } // *************************************************************************** // *************************************************************************** // *************************************************************************** // *************************************************************************** // MAIN // *************************************************************************** // *************************************************************************** // *************************************************************************** // *************************************************************************** int main(int argc, char *argv[]) { int fd_in = 0; /* stdin */ int fd_out = 1; /* stdout */ ysSource source; ysTarget target; ysScaling scaling; y4m_accept_extensions(1); /* parse stream-independent arguments */ parse_args(argc, argv, source, target, scaling, GLOBAL); /* read source stream header */ if (source.read_stream_header(fd_in) != Y4M_OK) mjpeg_error_exit1("Failed to read YUV4MPEG2 header!"); mjpeg_info("Input Stream Header:"); source.stream().log_info(mjpeg_loglev_t("info"), "<<< "); /* set target stream defaults from source stream */ target.init_stream(source); /* parse stream-dependent arguments (source, target parameters) */ parse_args(argc, argv, source, target, scaling, SOURCE); parse_args(argc, argv, source, target, scaling, DEST); /* apply heuristics and finalize parameters */ source.check_parameters(); target.check_parameters(source); scaling.check_parameters(source, target); /* log results to user */ source.describe_parameters(); scaling.describe_parameters(); target.describe_parameters(); /* set up target stream */ target.stream().write_stream_header(fd_out); mjpeg_info("Output Stream Header:"); target.stream().log_info(mjpeg_loglev_t("info"), ">>> "); /* do some scaling */ scaling.create_scalers(source, target); scaling.process_stream(fd_in, fd_out, source, target); return 0; } mjpegtools-2.1.0/y4mscaler/ysScaling.H0000644000175000017500000000541312051575455020175 0ustar glowwormglowworm/* Copyright 2003 Matthew Marjanovic This file is part of y4mscaler. y4mscaler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. y4mscaler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with y4mscaler; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _YS_SCALING_H_ #define _YS_SCALING_H_ #include #include "scaler.H" #include "ysSource.H" #include "ysTarget.H" class ysScaling { private: struct factory_info { const char *id; ysScalerFactory *factory; }; int _factory_count; factory_info *_factory_list; ysScalerFactory *_factory; int _mono; int _line_switching; int _swap_ilace; enum { PLANE_Y = 0, PLANE_CB, PLANE_CR, PLANE_A, MAX_PLANES }; enum { SC_PROG_Y = 0, SC_PROG_CB, SC_PROG_CR, SC_PROG_A, SC_INTER_Y, SC_UPPER_CB, SC_UPPER_CR, SC_LOWER_CB, SC_LOWER_CR, SC_INTER_A, SC_MAX_SCALERS }; // ysScaler **_scalers; ysScaler *_scalers[SC_MAX_SCALERS]; // int _scaler_count; bool _vertically_mixed_source; bool _anomalous_mixtures_are_fatal; void set_factory(ysScalerFactory *f) { // delete _factory; _factory = f; } void require_factory(void); void _create_factory_list(void); void _destroy_factory_list(void); void _create_frame_scalers(const ysSource &source, const ysTarget &target); void _create_field_scalers(const ysSource &source, const ysTarget &target); void _process_frames(int fd_in, int fd_out, ysSource &source, ysTarget &target); void _process_fields(int fd_in, int fd_out, ysSource &source, ysTarget &target); void _process_mixed(int fd_in, int fd_out, ysSource &source, ysTarget &target); public: ysScaling(void); ~ysScaling(); ysScalerFactory *factory() const { return _factory; } void describe_keywords(FILE *fp, const char *prefix) const; void parse_keyword(char *optarg); void describe_parameters() const; void check_parameters(const ysSource &source, const ysTarget &target); void create_scalers(const ysSource &source, const ysTarget &target); void process_stream(int fd_in, int fd_out, ysSource &source, ysTarget &target); void destroy_scalers(); }; #endif /* _YS_SCALING_H_ */ mjpegtools-2.1.0/y4mscaler/graphics.H0000644000175000017500000004252212051575455020043 0ustar glowwormglowworm/* Copyright 2003 Matthew Marjanovic This file is part of y4mscaler. y4mscaler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. y4mscaler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with y4mscaler; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _YS_GRAPHICS_H_ #define _YS_GRAPHICS_H_ #include extern "C" { #include } #define Y_WHITE 235 #define Y_BLACK 16 class ysYCbCr { public: // const uint8_t Y_black; // const uint8_t Y_white; uint8_t Y; uint8_t Cb; uint8_t Cr; uint8_t A; public: ysYCbCr(void) : Y(0), Cb(0), Cr(0), A(0) {} ysYCbCr(int y, int cb, int cr, int a = Y_WHITE) : Y(y), Cb(cb), Cr(cr), A(a) {} uint8_t operator()(int plane) const { switch (plane) { #if 1 case 0: return Y; break; case 1: return Cb; break; case 2: return Cr; break; case 3: return A; break; #else case PLANE_Y: return Y; break; case PLANE_CB: return Cb; break; case PLANE_CR: return Cr; break; case PLANE_A: return A; break; #endif default: assert(0); break; } return 0; } static ysYCbCr parse_string(char *); }; void ys_ratio_reduce(y4m_ratio_t *r); class ysRatio { private: y4m_ratio_t r; static int64_t _gcd64(int64_t a, int64_t b); static void _reduce64(int64_t &nn, int64_t &dd); public: ysRatio() { r.n = 0; r.d = 0; } ysRatio(int n, int d) { r.n = n; r.d = d; y4m_ratio_reduce(&r); } ysRatio(const y4m_ratio_t &ar) : r(ar) { y4m_ratio_reduce(&r); } ysRatio(const int &i) { r.n = i; r.d = 1; } bool is_known() const { return ((r.n != 0) || (r.d != 0)); } bool is_integral() const { return (r.d == 1); } const y4m_ratio_t &ratio() const { return r; } float to_float() const { return (float)r.n / (float)r.d; } double to_double() const { return (double)r.n / (double)r.d; } int to_int() const { return r.n / r.d; } int numerator() const { return r.n; } int denominator() const { return r.d; } /* comparison operations */ bool operator==(const ysRatio &rb) const; bool operator!=(const ysRatio &rb) const; bool operator<(const ysRatio &b) const; bool operator>(const ysRatio &b) const; /* arithmetic operations */ ysRatio operator*(const ysRatio &b) const; ysRatio operator/(const ysRatio &b) const; ysRatio operator+(const ysRatio &b) const; ysRatio operator-(const ysRatio &b) const; ysRatio &operator*=(const ysRatio &b); ysRatio &operator/=(const ysRatio &b); ysRatio &operator+=(const ysRatio &b); ysRatio &operator-=(const ysRatio &b); int parse_ratio(const char *s); }; class ysRatioPoint; class ysPoint { private: int _x, _y; int _unknown; public: ysPoint() : _x(0), _y(0), _unknown(1) {} ysPoint(int x, int y) : _x(x), _y(y), _unknown(0) {} int x() const { return _x; } int y() const { return _y; } int area() const { return _x * _y; } bool is_known() const { return !_unknown; } ysPoint &operator*=(int z); ysPoint &operator/=(int z); ysPoint operator*(int z) const; ysPoint operator/(int z) const; ysPoint &operator+=(const ysPoint &b); ysPoint &operator-=(const ysPoint &b); ysPoint &operator*=(const ysPoint &b); ysPoint &operator/=(const ysPoint &b); ysPoint operator+(const ysPoint &b) const; ysPoint operator-(const ysPoint &b) const; ysPoint operator*(const ysPoint &b) const; ysPoint operator/(const ysPoint &b) const; ysPoint &operator*=(const ysRatioPoint &b); ysPoint operator*(const ysRatioPoint &b) const; }; class ysRatioPoint { private: ysRatio _x, _y; int _unknown; public: ysRatioPoint() : _x(0,1), _y(0,1), _unknown(1) {} ysRatioPoint(ysRatio x, ysRatio y) : _x(x), _y(y), _unknown(0) {} ysRatioPoint(int x, int y) : _x(x), _y(y), _unknown(0) {} ysRatioPoint(const ysPoint &p) : _x(p.x()), _y(p.y()), _unknown(0) {} ysRatio x() const { return _x; } ysRatio y() const { return _y; } ysRatio area() const { return _x * _y; } bool is_known() const { return !_unknown; } ysRatioPoint &operator+=(const ysRatioPoint &b); ysRatioPoint &operator-=(const ysRatioPoint &b); ysRatioPoint &operator*=(const ysRatioPoint &b); ysRatioPoint &operator/=(const ysRatioPoint &b); ysRatioPoint operator+(const ysRatioPoint &b) const; ysRatioPoint operator-(const ysRatioPoint &b) const; ysRatioPoint operator*(const ysRatioPoint &b) const; ysRatioPoint operator/(const ysRatioPoint &b) const; ysRatioPoint &operator*=(const ysRatio &r); ysRatioPoint &operator/=(const ysRatio &r); ysRatioPoint operator*(const ysRatio &r) const; ysRatioPoint operator/(const ysRatio &r) const; }; enum AnchorMode_t { ANC_UNKNOWN, ANC_TL, ANC_TC, ANC_TR, ANC_CL, ANC_CC, ANC_CR, ANC_BL, ANC_BC, ANC_BR }; enum AnchorMode_t parse_anchor_mode(const char *s); class ysRatioRegion; class ysRegion { private: ysPoint _dim; ysPoint _offset; AnchorMode_t _origin_mode; public: ysRegion() : _origin_mode(ANC_UNKNOWN) {} ysRegion(ysPoint dim, ysPoint offset) : _dim(dim), _offset(offset), _origin_mode(ANC_UNKNOWN) {} ysRegion(ysPoint dim) : _dim(dim), _offset(0,0), _origin_mode(ANC_UNKNOWN) {} ysRegion(int sx, int sy, int ox, int oy) : _dim(sx, sy), _offset(ox, oy), _origin_mode(ANC_UNKNOWN) {} const ysPoint &dim() const { return _dim; } const ysPoint &offset() const { return _offset; } bool is_known() const { return (_dim.is_known() && _offset.is_known()); } int area() const { return _dim.area(); } const ysPoint &ul() const { return _offset; } ysPoint lr() const { return _offset + _dim; } void dim(const ysPoint &p) { _dim = p; } void offset(const ysPoint &p) { _offset = p; } void origin_mode(AnchorMode_t mode) { _origin_mode = mode; } void fixate(const ysPoint &framesize); int clip(const ysRegion &bounds); /* return 1 if clipping occurs */ int clip(const ysRatioRegion &bounds); /* return 1 if clipping occurs */ // void center_to(const ysRegion &bounds); ysPoint rel_anchor(ysRatioPoint &relative) const; ysPoint rel_anchor(AnchorMode_t mode) const; int parse_geometry(const char *s); }; class ysRatioRegion { private: ysRatioPoint _dim; ysRatioPoint _offset; AnchorMode_t _origin_mode; public: ysRatioRegion() : _origin_mode(ANC_UNKNOWN) {} ysRatioRegion(ysRatioPoint dim, ysRatioPoint offset) : _dim(dim), _offset(offset), _origin_mode(ANC_UNKNOWN) {} ysRatioRegion(ysRatioPoint dim) : _dim(dim), _offset(0,0), _origin_mode(ANC_UNKNOWN) {} ysRatioRegion(ysRatio sx, ysRatio sy, ysRatio ox, ysRatio oy) : _dim(sx, sy), _offset(ox, oy), _origin_mode(ANC_UNKNOWN) {} ysRatioRegion(const ysRegion ®ion) : _dim(region.dim()), _offset(region.offset()), _origin_mode(ANC_UNKNOWN) {} const ysRatioPoint &dim() const { return _dim; } const ysRatioPoint &offset() const { return _offset; } ysRatio area() const { return _dim.area(); } bool is_known() const { return (_dim.is_known() && _offset.is_known()); } const ysRatioPoint &ul() const { return _offset; } ysRatioPoint lr() const { return _offset + _dim; } void dim(const ysRatioPoint &p) { _dim = p; } void offset(const ysRatioPoint &p) { _offset = p; } void origin_mode(AnchorMode_t mode) { _origin_mode = mode; } void fixate(const ysRatioPoint &framesize); //int clip(const ysRatioRegion &bounds); /* return 1 if clipping occurs */ ysRatioRegion clip(const ysRatioRegion &bounds); /* return delta */ void center_to(const ysRatioRegion &bounds); void align_to(const ysRatioPoint &relative_anchor, const ysRatioPoint &fixed_point); void align_to(const ysRatioRegion &bounds, AnchorMode_t mode); ysRatioPoint rel_anchor(ysRatioPoint &relative) const; ysRatioPoint rel_anchor(AnchorMode_t mode) const; int parse_geometry(const char *s); bool operator==(const ysRatioRegion &b) const { return ((_dim.x() == b._dim.x()) && (_dim.y() == b._dim.y()) && (_offset.x() == b._offset.x()) && (_offset.y() == b._offset.y())); } bool operator!=(const ysRatioRegion &b) const { return !((_dim.x() == b._dim.x()) && (_dim.y() == b._dim.y()) && (_offset.x() == b._offset.x()) && (_offset.y() == b._offset.y())); } }; class ysSubsampling { public: enum Mode { SS_UNKNOWN = Y4M_UNKNOWN, SS_444 = Y4M_CHROMA_444, SS_422 = Y4M_CHROMA_422, SS_420_JPEG = Y4M_CHROMA_420JPEG, SS_420_MPEG2 = Y4M_CHROMA_420MPEG2, SS_420_PALDV = Y4M_CHROMA_420PALDV, SS_411 = Y4M_CHROMA_411, SS_MONO = Y4M_CHROMA_MONO, SS_444ALPHA = Y4M_CHROMA_444ALPHA }; enum Field { FRAME = 0, UPPER_FIELD, LOWER_FIELD, FT_COUNT }; enum Plane { PLANE_Y = 0, PLANE_Cb, PLANE_Cr, PLANE_ALPHA, PLANES }; private: Mode _mode; ysRatioPoint _ratio; ysRatioPoint _offset[FT_COUNT][PLANES]; // pels, relative to luma plane public: ysSubsampling(Mode amode = SS_UNKNOWN) { mode(amode); } Mode mode(void) const { return _mode; } void mode(Mode amode); bool is_known(void) const { return _mode != SS_UNKNOWN; } ysRatioPoint ratio(void) const { return _ratio; } ysRatioPoint offset(Field field, Plane plane) const { return _offset[field][plane]; } ysRatioPoint effective_sample_offset(Field field, Plane plane) const; const char *mode_to_string() const; int parse_mode(const char *s); }; /*************************************************************************/ /*************************************************************************/ /* operators for ysRatio */ /*************************************************************************/ /*************************************************************************/ inline bool ysRatio::operator==(const ysRatio &rb) const { return (is_known() && rb.is_known() && (r.n == rb.r.n) && (r.d == rb.r.d)); } inline bool ysRatio::operator!=(const ysRatio &rb) const { return (!is_known() || !rb.is_known() || (r.n != rb.r.n) || (r.d != rb.r.d)); } inline bool ysRatio::operator<(const ysRatio &b) const { return ((r.n * b.r.d) - (r.d * b.r.n)) < 0; } inline bool ysRatio::operator>(const ysRatio &b) const { return ((r.n * b.r.d) - (r.d * b.r.n)) > 0; } /* arithmetic operations */ inline ysRatio &ysRatio::operator*=(const ysRatio &b) { #if _YS_DEBUG if ( ((r.n * b.r.n) != ((int64_t)r.n * (int64_t)b.r.n)) || ((r.d * b.r.d) != ((int64_t)r.d * (int64_t)b.r.d)) ) mjpeg_error("*= OVERFLOW %d %d %d %d", r.n, r.d, b.r.n, b.r.d); #endif int64_t nn = (int64_t)r.n * (int64_t)b.r.n; int64_t dd = (int64_t)r.d * (int64_t)b.r.d; _reduce64(nn, dd); r.n = nn; r.d = dd; return *this; } inline ysRatio &ysRatio::operator/=(const ysRatio &b) { #if _YS_DEBUG if ( ((r.n * b.r.d) != ((int64_t)r.n * (int64_t)b.r.d)) || ((r.d * b.r.n) != ((int64_t)r.d * (int64_t)b.r.n)) ) mjpeg_error("/= OVERFLOW %d %d %d %d", r.n, r.d, b.r.n, b.r.d); #endif int64_t nn = (int64_t)r.n * (int64_t)b.r.d; int64_t dd = (int64_t)r.d * (int64_t)b.r.n; _reduce64(nn, dd); r.n = nn; r.d = dd; return *this; } inline ysRatio ysRatio::operator*(const ysRatio &b) const { // if ( ((r.n * b.r.n) != ((int64_t)r.n * (int64_t)b.r.n)) || // ((r.d * b.r.d) != ((int64_t)r.d * (int64_t)b.r.d)) ) // mjpeg_error("* OVERFLOW %d %d %d %d", r.n, r.d, b.r.n, b.r.d); // int64_t nn = (int64_t)r.n * (int64_t)b.r.n; // int64_t dd = (int64_t)r.d * (int64_t)b.r.d; // _reduce64(nn, dd); // return ysRatio(nn, dd); ysRatio a = *this; a *= b; return a; } inline ysRatio ysRatio::operator/(const ysRatio &b) const { // if ( ((r.n * b.r.d) != ((int64_t)r.n * (int64_t)b.r.d)) || // ((r.d * b.r.n) != ((int64_t)r.d * (int64_t)b.r.n)) ) // mjpeg_error("/ OVERFLOW %d %d %d %d", r.n, r.d, b.r.n, b.r.d); // int64_t nn = (int64_t)r.n * (int64_t)b.r.d; // int64_t dd = (int64_t)r.d * (int64_t)b.r.n; // _reduce64(nn, dd); // return ysRatio(nn, dd); ysRatio a = *this; a /= b; return a; } inline ysRatio &ysRatio::operator+=(const ysRatio &b) { int64_t nn = ( ((int64_t)r.n * (int64_t)b.r.d) + ((int64_t)r.d * (int64_t)b.r.n) ); int64_t dd = (int64_t)r.d * (int64_t)b.r.d; _reduce64(nn, dd); r.n = nn; r.d = dd; return *this; } inline ysRatio &ysRatio::operator-=(const ysRatio &b) { int64_t nn = ( ((int64_t)r.n * (int64_t)b.r.d) - ((int64_t)r.d * (int64_t)b.r.n) ); int64_t dd = (int64_t)r.d * (int64_t)b.r.d; _reduce64(nn, dd); r.n = nn; r.d = dd; return *this; } inline ysRatio ysRatio::operator+(const ysRatio &b) const { ysRatio a = *this; a += b; return a; // return ysRatio( (r.n * b.r.d) + (r.d * b.r.n), // r.d * b.r.d ); } inline ysRatio ysRatio::operator-(const ysRatio &b) const { ysRatio a = *this; a -= b; return a; // return ysRatio( (r.n * b.r.d) - (r.d * b.r.n), // r.d * b.r.d ); } /*************************************************************************/ /*************************************************************************/ /* operators for ysPoint */ /*************************************************************************/ /*************************************************************************/ inline ysPoint &ysPoint::operator+=(const ysPoint &b) { _unknown = _unknown || b._unknown; _x += b._x; _y += b._y; return *this; } inline ysPoint &ysPoint::operator-=(const ysPoint &b) { _unknown = _unknown || b._unknown; _x -= b._x; _y -= b._y; return *this; } inline ysPoint ysPoint::operator+(const ysPoint &b) const { ysPoint a = *this; return (a += b); } inline ysPoint ysPoint::operator-(const ysPoint &b) const { ysPoint a = *this; return (a -= b); } inline ysPoint &ysPoint::operator*=(const ysPoint &b) { _unknown = _unknown || b._unknown; _x *= b._x; _y *= b._y; return *this; } inline ysPoint &ysPoint::operator/=(const ysPoint &b) { _unknown = _unknown || b._unknown; if (!_unknown) { _x /= b._x; _y /= b._y; } return *this; } inline ysPoint ysPoint::operator*(const ysPoint &b) const { ysPoint a = *this; return (a *= b); } inline ysPoint ysPoint::operator/(const ysPoint &b) const { ysPoint a = *this; return (a /= b); } inline ysPoint &ysPoint::operator*=(int z) { _x *= z; _y *= z; return *this; } inline ysPoint &ysPoint::operator/=(int z) { _x /= z; _y /= z; return *this; } inline ysPoint ysPoint::operator*(int z) const { ysPoint a = *this; return (a *= z); } inline ysPoint ysPoint::operator/(int z) const { ysPoint a = *this; return (a /= z); } inline ysPoint &ysPoint::operator*=(const ysRatioPoint &b) { _unknown = _unknown || !(b.is_known()); if (!_unknown) { ysRatio rx = b.x() * _x; ysRatio ry = b.y() * _y; assert(rx.is_integral()); assert(ry.is_integral()); _x = rx.to_int(); _y = ry.to_int(); } return *this; } inline ysPoint ysPoint::operator*(const ysRatioPoint &b) const { ysPoint a = *this; return (a *= b); } /*************************************************************************/ /*************************************************************************/ /* operators for ysRatioPoint */ /*************************************************************************/ /*************************************************************************/ inline ysRatioPoint &ysRatioPoint::operator+=(const ysRatioPoint &b) { _unknown = _unknown || b._unknown; _x += b._x; _y += b._y; return *this; } inline ysRatioPoint &ysRatioPoint::operator-=(const ysRatioPoint &b) { _unknown = _unknown || b._unknown; _x -= b._x; _y -= b._y; return *this; } inline ysRatioPoint ysRatioPoint::operator+(const ysRatioPoint &b) const { ysRatioPoint a = *this; return (a += b); } inline ysRatioPoint ysRatioPoint::operator-(const ysRatioPoint &b) const { ysRatioPoint a = *this; return (a -= b); } inline ysRatioPoint &ysRatioPoint::operator*=(const ysRatioPoint &b) { _unknown = _unknown || b._unknown; _x *= b._x; _y *= b._y; return *this; } inline ysRatioPoint &ysRatioPoint::operator/=(const ysRatioPoint &b) { _unknown = _unknown || b._unknown; if (!_unknown) { _x /= b._x; _y /= b._y; } return *this; } inline ysRatioPoint ysRatioPoint::operator*(const ysRatioPoint &b) const { ysRatioPoint a = *this; return (a *= b); } inline ysRatioPoint ysRatioPoint::operator/(const ysRatioPoint &b) const { ysRatioPoint a = *this; return (a /= b); } inline ysRatioPoint &ysRatioPoint::operator*=(const ysRatio &r) { _unknown = _unknown || !(r.is_known()); _x *= r; _y *= r; return *this; } inline ysRatioPoint &ysRatioPoint::operator/=(const ysRatio &r) { _unknown = _unknown || !(r.is_known()); if (!_unknown) { _x /= r; _y /= r; } return *this; } inline ysRatioPoint ysRatioPoint::operator*(const ysRatio &r) const { ysRatioPoint a = *this; return (a *= r); } inline ysRatioPoint ysRatioPoint::operator/(const ysRatio &r) const { ysRatioPoint a = *this; return (a /= r); } #endif /* _YS_GRAPHICS_H_ */ mjpegtools-2.1.0/y4mscaler/ysScaling.C0000644000175000017500000007535512051575455020204 0ustar glowwormglowworm/* Copyright 2003 Matthew Marjanovic This file is part of y4mscaler. y4mscaler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. y4mscaler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with y4mscaler; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "y4m-config.h" #include "debug.h" #include "ysScaling.H" #include "scaler-matto.H" #ifdef _EXPERIMENTAL #include "scaler-jit.H" #include "scaler-exp.H" #endif /* _EXPERIMENTAL */ #include void ysScaling::_create_factory_list(void) { #ifdef _EXPERIMENTAL _factory_count = 4; #else _factory_count = 2; #endif _factory_list = new factory_info[_factory_count]; _factory_list[0].id = "default"; _factory_list[0].factory = new mattoScalerFactory(); _factory_list[1].id = "matto"; _factory_list[1].factory = new mattoScalerFactory(); #ifdef _EXPERIMENTAL _factory_list[2].id = "jit"; _factory_list[2].factory = new jitScalerFactory(); _factory_list[3].id = "exp"; _factory_list[3].factory = new expScalerFactory(); #endif } void ysScaling::_destroy_factory_list(void) { if (_factory_list != NULL) { for (int i = 0; i < _factory_count; i++) { delete _factory_list[i].factory; } delete[] _factory_list; _factory_list = NULL; } } ysScaling::ysScaling(void) : _factory(NULL), _mono(0), _line_switching(0), _swap_ilace(0) { _create_factory_list(); for (int i = 0; i < SC_MAX_SCALERS; i++) _scalers[i] = NULL; } ysScaling::~ysScaling() { _destroy_factory_list(); _factory = NULL; destroy_scalers(); } void ysScaling::require_factory(void) { if (_factory == NULL) set_factory(_factory_list[0].factory); } void ysScaling::describe_keywords(FILE *fp, const char *prefix) const { fprintf(fp, "%smode=mono\n", prefix); fprintf(fp, "%smode=lineswitch\n", prefix); fprintf(fp, "%sscaler=scaler-name\n", prefix); fprintf(fp, "%s Available scalers:\n", prefix); int maxlen = 0; for (int i = 0; i < _factory_count; i++) { int x = strlen(_factory_list[i].id); if (x > maxlen) maxlen = x; } for (int i = 0; i < _factory_count; i++) { fprintf(fp, "%s '%s'%*s - %s %s\n", prefix, _factory_list[i].id, maxlen - (int)strlen(_factory_list[i].id), "", _factory_list[i].factory->description(), (i==0 ? "(default)" : "")); } fprintf(fp, "%soption=scaler-option\n", prefix); fprintf(fp, "%s Use 'option=help' to see options for chosen scaler.\n", prefix); } void ysScaling::parse_keyword(char *optarg) { if (!strcasecmp(optarg, "MODE=MONO")) { _mono = 1; } else if (!strcasecmp(optarg, "MODE=LINESWITCH")) { _line_switching = 1; } else if (!strncasecmp(optarg, "SCALER=", 7)) { if (_factory != NULL) { mjpeg_error_exit1("A scaler has already been chosen: '%s'", optarg); } for (int i = 0; i < _factory_count; i++) { if (!strcasecmp(optarg+7, _factory_list[i].id)) { set_factory(_factory_list[i].factory); break; } } if (_factory == NULL) { mjpeg_error_exit1("Unrecognized scaler selected: '%s'", optarg); } } else if (!strncasecmp(optarg, "OPTION=", 7)) { char *option = optarg+7; require_factory(); if (!strcasecmp(option, "HELP")) { fprintf(stdout, "Options for scaler '%s':\n", _factory->description()); _factory->describe_options(stdout, " "); exit(1); } else { if (_factory->parse_option(option)) { mjpeg_error_exit1("Unrecognized scaler option: '%s'", option); } } } else { mjpeg_error_exit1("Unrecognized scaling parameter: '%s'", optarg); } } void ysScaling::describe_parameters() const { mjpeg_info("=== SCALING parameters: ================"); if (_factory != NULL) { mjpeg_info("| Scaler: %s", _factory->description()); _factory->describe_parameters(mjpeg_info, "| "); } else mjpeg_info("| Scaler: *NONE*"); if (_mono) mjpeg_info("| MONO: process luma only"); if (_line_switching) mjpeg_info("| LINESWITCH: swap scanline pairs"); if (_swap_ilace) mjpeg_info("| SWAP-ILACE: drop first field, reframe stream"); } #if 0 void ysScaling::check_parameters(const ysSource &source, const ysTarget &target) { require_factory(); _swap_ilace = 0; if (source.stream().interlace() == Y4M_ILACE_NONE) { if (target.stream().interlace() != Y4M_ILACE_NONE) { mjpeg_error_exit1("Cannot make interlaced stream from progressive."); } } else { /* source is interlaced/mixed */ if (target.stream().interlace() == Y4M_ILACE_NONE) { if (source.stream().interlace() != Y4M_ILACE_MIXED) { mjpeg_error("Cannot make progressive stream from interlaced."); mjpeg_error_(" (Try '-I ilace=TOP_ONLY/BOTTOM_ONLY'; see manpage.)"); } else { mjpeg_error("Cannot make progressive stream from mixed-mode."); } exit(1); } if (target.stream().interlace() != source.stream().interlace()) { mjpeg_warn("Will swap interlacing modes (by dropping first field)."); _swap_ilace = 1; } } if (_line_switching && (trg_lace == Y4M_ILACE_NONE)) { mjpeg_warn("LINESWITCH has no effect on non-interlaced output!"); } } #endif void ysScaling::check_parameters(const ysSource &source, const ysTarget &target) { require_factory(); _swap_ilace = 0; _vertically_mixed_source = (source.stream().subsampling().ratio().y().denominator() != 1); _anomalous_mixtures_are_fatal = 0; int src_lace = source.stream().interlace(); int trg_lace = target.stream().interlace(); switch (src_lace) { case Y4M_ILACE_NONE: if (trg_lace != Y4M_ILACE_NONE) mjpeg_error_exit1("Cannot make interlaced stream from progressive!"); break; case Y4M_ILACE_TOP_FIRST: case Y4M_ILACE_BOTTOM_FIRST: if (trg_lace == Y4M_ILACE_NONE) { mjpeg_error("Cannot make progressive stream from interlaced."); mjpeg_error(" (Try '-I ilace=TOP_ONLY/BOTTOM_ONLY'; see manpage.)"); exit(1); } if (trg_lace != src_lace) { mjpeg_warn("Will swap interlacing modes (by dropping first field)."); _swap_ilace = 1; } break; case Y4M_ILACE_MIXED: if (trg_lace != Y4M_ILACE_MIXED) { mjpeg_error_exit1("Cannot make non-mixed interlacing from mixed!"); } // IF source is vertically subsampled and mixed-mode, // and IF any vertical processing is performed --- meaning: // o vertical scale factor is not 1/1 // o y-offset of active region is not an integer // OR target is still vertically subsampled // THEN processing will fail on anomalous interlacing mode (i.e. ip, pi). // (y4mscaler output is always non-anomalous pp or ii!) if (_vertically_mixed_source && ( (target.y_ratio() != ysRatio(1,1)) || !(source.active_region().offset().y().is_integral()) || (target.stream().subsampling().ratio().y().denominator() != 1) )) { _anomalous_mixtures_are_fatal = 1; mjpeg_warn("(Beware: Processing will fail midstream if an anomalous"); mjpeg_warn(" interlace mixture (ip/pi) is encountered.)"); } break; default: mjpeg_error_exit1("Unknown source interlacing mode!"); break; } if (_line_switching) { if (target.stream().interlace() == Y4M_ILACE_NONE) mjpeg_warn("LINESWITCH has no effect on non-interlaced output!"); if (target.stream().interlace() == Y4M_ILACE_NONE) mjpeg_warn("LINESWITCH has no effect on mixed-interlaced output!"); } } /* * Handling of chroma offset: * * Proper siting of chroma subsamples requires an additional active_region * offset for the chroma plane scalers. Since this offset may be different * for each plane and for each *field* (in interlaced streams), up to five * different scaler setups may be required. * * The additional offset is: qS - (qT / s), * where qS is the source "effective_sample_offset()", * qT is the target "effective_sample_offset()", * s is the scale ratio for the axis. * * Note that if interlacing is being swapped, then qS and qT must still * correspond to the actual fields, which will be different. Hence * the arguments for 'src_field' and 'tgt_field'. * */ ysRatioPoint chroma_active_offset(ysSubsampling::Plane plane, ysSubsampling::Field src_field, ysSubsampling::Field tgt_field, const ysSource &source, const ysTarget &target) { DBG("ss eso (%f, %f) ts eso (%f, %f)\n", source.stream().subsampling().effective_sample_offset(src_field, plane).x().to_double(), source.stream().subsampling().effective_sample_offset(src_field, plane).y().to_double(), target.stream().subsampling().effective_sample_offset(src_field, plane).x().to_double(), target.stream().subsampling().effective_sample_offset(src_field, plane).y().to_double()); return (source.active_region().offset() * source.stream().subsampling().ratio() / ( (src_field == ysSubsampling::FRAME) ? ysPoint(1,1) : ysPoint(1,2) )) + source.stream().subsampling().effective_sample_offset(src_field, plane) - ( target.stream().subsampling().effective_sample_offset(tgt_field, plane) / ysRatioPoint(target.x_ratio(), target.y_ratio()) ); } void ysScaling::_create_frame_scalers(const ysSource &source, const ysTarget &target) { int planes = target.stream().planes(); _scalers[SC_PROG_Y] = _factory->new_scaler(); _scalers[SC_PROG_Y]->setup(source.stream().framedim(0), source.active_region().offset(), source.matte_region(), target.stream().framedim(0), target.active_region(), target.x_ratio(), target.y_ratio(), source.bgcolor()(0)); if ((planes > 1) && (!_mono)) { ysRatioPoint offsetCb = chroma_active_offset(ysSubsampling::PLANE_Cb, ysSubsampling::FRAME, ysSubsampling::FRAME, source, target); ysRatioPoint offsetCr = chroma_active_offset(ysSubsampling::PLANE_Cr, ysSubsampling::FRAME, ysSubsampling::FRAME, source, target); ysRatioPoint src_ssRatio = source.stream().subsampling().ratio(); ysRatioPoint tgt_ssRatio = target.stream().subsampling().ratio(); ysRatioPoint c_scale = ysRatioPoint(target.x_ratio(), target.y_ratio()) * tgt_ssRatio / src_ssRatio; _scalers[SC_PROG_CB] = _factory->new_scaler(); _scalers[SC_PROG_CB]->setup(source.stream().framedim(1), offsetCb, ysRegion(source.matte_region().dim() * src_ssRatio, source.matte_region().offset() * src_ssRatio), target.stream().framedim(1), ysRegion(target.active_region().dim() * tgt_ssRatio, target.active_region().offset() * tgt_ssRatio), c_scale.x(), c_scale.y(), //target.x_ratio(), target.y_ratio(), source.bgcolor()(1) ); _scalers[SC_PROG_CR] = _factory->new_scaler(); _scalers[SC_PROG_CR]->setup(source.stream().framedim(2), offsetCr, ysRegion(source.matte_region().dim() * src_ssRatio, source.matte_region().offset() * src_ssRatio), target.stream().framedim(2), ysRegion(target.active_region().dim() * tgt_ssRatio, target.active_region().offset() * tgt_ssRatio), c_scale.x(), c_scale.y(), //target.x_ratio(), target.y_ratio(), source.bgcolor()(2) ); } if (planes > 3) { _scalers[SC_PROG_A] = _factory->new_scaler(); _scalers[SC_PROG_A]->setup(source.stream().framedim(0), source.active_region().offset(), source.matte_region(), target.stream().framedim(0), target.active_region(), target.x_ratio(), target.y_ratio(), source.bgcolor()(3)); } } void ysScaling::_create_field_scalers(const ysSource &source, const ysTarget &target) { int planes = target.stream().planes(); _scalers[SC_INTER_Y] = _factory->new_scaler(); _scalers[SC_INTER_Y]->setup(source.stream().fielddim(0), source.active_region().offset() / ysPoint(1,2), ysRegion(source.matte_region().dim() / ysPoint(1,2), source.matte_region().offset() / ysPoint(1,2)), target.stream().fielddim(0), ysRegion(target.active_region().dim() / ysPoint(1,2), target.active_region().offset() / ysPoint(1,2)), target.x_ratio(), target.y_ratio(), source.bgcolor()(0) ); if ((planes > 1) && (!_mono)) { ysRatioPoint offsetCbUpper; ysRatioPoint offsetCrUpper; ysRatioPoint offsetCbLower; ysRatioPoint offsetCrLower; if (_swap_ilace) { /* if swapping ilace, then Source LOWER field --> Target UPPER field, and vice-versa. */ offsetCbUpper = chroma_active_offset(ysSubsampling::PLANE_Cb, ysSubsampling::LOWER_FIELD, ysSubsampling::UPPER_FIELD, source, target); offsetCrUpper = chroma_active_offset(ysSubsampling::PLANE_Cr, ysSubsampling::LOWER_FIELD, ysSubsampling::UPPER_FIELD, source, target); offsetCbLower = chroma_active_offset(ysSubsampling::PLANE_Cb, ysSubsampling::UPPER_FIELD, ysSubsampling::LOWER_FIELD, source, target); offsetCrLower = chroma_active_offset(ysSubsampling::PLANE_Cr, ysSubsampling::UPPER_FIELD, ysSubsampling::LOWER_FIELD, source, target); } else { /* if not swapping, then Source LOWER field --> Target LOWER field, etc. */ offsetCbUpper = chroma_active_offset(ysSubsampling::PLANE_Cb, ysSubsampling::UPPER_FIELD, ysSubsampling::UPPER_FIELD, source, target); offsetCrUpper = chroma_active_offset(ysSubsampling::PLANE_Cr, ysSubsampling::UPPER_FIELD, ysSubsampling::UPPER_FIELD, source, target); offsetCbLower = chroma_active_offset(ysSubsampling::PLANE_Cb, ysSubsampling::LOWER_FIELD, ysSubsampling::LOWER_FIELD, source, target); offsetCrLower = chroma_active_offset(ysSubsampling::PLANE_Cr, ysSubsampling::LOWER_FIELD, ysSubsampling::LOWER_FIELD, source, target); } ysRatioPoint src_ssRatio = source.stream().subsampling().ratio(); ysRatioPoint tgt_ssRatio = target.stream().subsampling().ratio(); ysRatioPoint c_scale = ysRatioPoint(target.x_ratio(), target.y_ratio()) * tgt_ssRatio / src_ssRatio; _scalers[SC_UPPER_CB] = _factory->new_scaler(); _scalers[SC_UPPER_CB]->setup(source.stream().fielddim(1), offsetCbUpper, ysRegion(source.matte_region().dim() * src_ssRatio / ysPoint(1,2), source.matte_region().offset() * src_ssRatio / ysPoint(1,2)), target.stream().fielddim(1), ysRegion(target.active_region().dim() * tgt_ssRatio / ysPoint(1,2), target.active_region().offset() * tgt_ssRatio / ysPoint(1,2)), c_scale.x(), c_scale.y(), source.bgcolor()(1) ); _scalers[SC_UPPER_CR] = _factory->new_scaler(); _scalers[SC_UPPER_CR]->setup(source.stream().fielddim(2), offsetCrUpper, ysRegion(source.matte_region().dim() * src_ssRatio / ysPoint(1,2), source.matte_region().offset() * src_ssRatio / ysPoint(1,2)), target.stream().fielddim(2), ysRegion(target.active_region().dim() * tgt_ssRatio / ysPoint(1,2), target.active_region().offset() * tgt_ssRatio / ysPoint(1,2)), c_scale.x(), c_scale.y(), source.bgcolor()(2) ); _scalers[SC_LOWER_CB] = _factory->new_scaler(); _scalers[SC_LOWER_CB]->setup(source.stream().fielddim(1), offsetCbLower, ysRegion(source.matte_region().dim() * src_ssRatio / ysPoint(1,2), source.matte_region().offset() * src_ssRatio / ysPoint(1,2)), target.stream().fielddim(1), ysRegion(target.active_region().dim() * tgt_ssRatio / ysPoint(1,2), target.active_region().offset() * tgt_ssRatio / ysPoint(1,2)), c_scale.x(), c_scale.y(), source.bgcolor()(1) ); _scalers[SC_LOWER_CR] = _factory->new_scaler(); _scalers[SC_LOWER_CR]->setup(source.stream().fielddim(2), offsetCrLower, ysRegion(source.matte_region().dim() * src_ssRatio / ysPoint(1,2), source.matte_region().offset() * src_ssRatio / ysPoint(1,2)), target.stream().fielddim(2), ysRegion(target.active_region().dim() * tgt_ssRatio / ysPoint(1,2), target.active_region().offset() * tgt_ssRatio / ysPoint(1,2)), c_scale.x(), c_scale.y(), source.bgcolor()(2) ); } if (planes > 3) { _scalers[SC_INTER_A] = _factory->new_scaler(); _scalers[SC_INTER_A]->setup(source.stream().fielddim(0), source.active_region().offset() / ysPoint(1,2), ysRegion(source.matte_region().dim() / ysPoint(1,2), source.matte_region().offset() / ysPoint(1,2)), target.stream().fielddim(0), ysRegion(target.active_region().dim() / ysPoint(1,2), target.active_region().offset() / ysPoint(1,2)), target.x_ratio(), target.y_ratio(), source.bgcolor()(3) ); } } /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ void ysScaling::_process_frames(int fd_in, int fd_out, ysSource &source, ysTarget &target) { int err; y4m_frame_info_t frameinfo; uint8_t *in_frame[MAX_PLANES]; uint8_t *out_frame[MAX_PLANES]; int planes_in = source.stream().planes(); int planes_out = target.stream().planes(); y4m_init_frame_info(&frameinfo); for (int i = 0; i < MAX_PLANES; i++) { out_frame[i] = NULL; in_frame[i] = NULL; } for (int i = 0; i < planes_in; i++) { in_frame[i] = new uint8_t[source.stream().framedim(i).area()]; } for (int i = 0; i < planes_out; i++) { out_frame[i] = new uint8_t[target.stream().framedim(i).area()]; if ( ((i == PLANE_CB) || (i == PLANE_CR)) && (_mono) ) { memset(out_frame[i], 128, target.stream().framedim(i).area()); } else { memset(out_frame[i], target.bgcolor()(i), target.stream().framedim(i).area()); } } int frame_num = 0; while (1) { mjpeg_info ("Frame number %d", frame_num); err = source.read_frame(fd_in, &frameinfo, in_frame); if (err != Y4M_OK) goto done; /* Scale luma always. */ _scalers[SC_PROG_Y]->scale(in_frame[PLANE_Y], out_frame[PLANE_Y]); /* Scale chroma maybe. */ if ((planes_in > 1) && (planes_out > 1) && (!_mono)) { _scalers[SC_PROG_CB]->scale(in_frame[PLANE_CB], out_frame[PLANE_CB]); _scalers[SC_PROG_CR]->scale(in_frame[PLANE_CR], out_frame[PLANE_CR]); } /* Scale alpha maybe. */ if ((planes_in > 3) && (planes_out > 3)) { _scalers[SC_PROG_A]->scale(in_frame[PLANE_A], out_frame[PLANE_A]); } err = target.write_frame(fd_out, &frameinfo, out_frame); if (err != Y4M_OK) goto done; frame_num++; } done: if (err == Y4M_ERR_EOF) mjpeg_info("End of stream at frame %d.", frame_num); else mjpeg_error_exit1("Failure at frame %d: %s", frame_num, y4m_strerr(err)); for (int i = 0; i < MAX_PLANES; i++) { delete[] in_frame[i]; delete[] out_frame[i]; } y4m_fini_frame_info(&frameinfo); } /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ void ysScaling::_process_fields(int fd_in, int fd_out, ysSource &source, ysTarget &target) { int err; y4m_frame_info_t frameinfo; uint8_t **in_upper = new uint8_t *[MAX_PLANES]; uint8_t **in_lower = new uint8_t *[MAX_PLANES]; uint8_t **in_other = new uint8_t *[MAX_PLANES]; uint8_t *out_upper[MAX_PLANES]; uint8_t *out_lower[MAX_PLANES]; int planes_in = source.stream().planes(); int planes_out = target.stream().planes(); y4m_init_frame_info(&frameinfo); for (int i = 0; i < MAX_PLANES; i++) { in_upper[i] = NULL; in_lower[i] = NULL; in_other[i] = NULL; out_upper[i] = NULL; out_lower[i] = NULL; } for (int i = 0; i < planes_in; i++) { in_upper[i] = new uint8_t[source.stream().fielddim(i).area()]; in_lower[i] = new uint8_t[source.stream().fielddim(i).area()]; in_other[i] = new uint8_t[source.stream().fielddim(i).area()]; } for (int i = 0; i < planes_out; i++) { out_upper[i] = new uint8_t[target.stream().fielddim(i).area()]; out_lower[i] = new uint8_t[target.stream().fielddim(i).area()]; if ( ((i == PLANE_CB) || (i == PLANE_CR)) && (_mono) ) { memset(out_upper[i], 128, target.stream().fielddim(i).area()); memset(out_lower[i], 128, target.stream().fielddim(i).area()); } else { memset(out_upper[i], target.bgcolor()(i), target.stream().fielddim(i).area()); memset(out_lower[i], target.bgcolor()(i), target.stream().fielddim(i).area()); } } int frame_num = 0; while (1) { mjpeg_info("Frame number %d", frame_num); err = source.read_fields(fd_in, &frameinfo, in_upper, in_lower); if (err != Y4M_OK) goto done; if (_line_switching) { uint8_t **extra = in_upper; in_upper = in_lower; in_lower = extra; } if (_swap_ilace) { if (target.stream().interlace() == Y4M_ILACE_TOP_FIRST) { /* target is top-field-first */ if (frame_num == 0) { err = source.read_fields(fd_in, &frameinfo, in_other, in_lower); if (err != Y4M_OK) goto done; } uint8_t **extra = in_upper; in_upper = in_other; in_other = extra; } else { /* target is bottom-field-first */ if (frame_num == 0) { err = source.read_fields(fd_in, &frameinfo, in_upper, in_other); if (err != Y4M_OK) goto done; } uint8_t **extra = in_lower; in_lower = in_other; in_other = extra; } } /* Scale luma always. */ _scalers[SC_INTER_Y]->scale(in_upper[PLANE_Y], out_upper[PLANE_Y]); _scalers[SC_INTER_Y]->scale(in_lower[PLANE_Y], out_lower[PLANE_Y]); /* Scale chroma maybe. */ if ((planes_in > 1) && (planes_out > 1) && (!_mono)) { _scalers[SC_UPPER_CB]->scale(in_upper[PLANE_CB], out_upper[PLANE_CB]); _scalers[SC_UPPER_CR]->scale(in_upper[PLANE_CR], out_upper[PLANE_CR]); _scalers[SC_LOWER_CB]->scale(in_lower[PLANE_CB], out_lower[PLANE_CB]); _scalers[SC_LOWER_CR]->scale(in_lower[PLANE_CR], out_lower[PLANE_CR]); } /* Scale alpha maybe. */ if ((planes_in > 3) && (planes_out > 3)) { _scalers[SC_INTER_A]->scale(in_upper[PLANE_A], out_upper[PLANE_A]); _scalers[SC_INTER_A]->scale(in_lower[PLANE_A], out_lower[PLANE_A]); } /* Write fields. */ err = target.write_fields(fd_out, &frameinfo, out_upper, out_lower); if (err != Y4M_OK) goto done; frame_num++; } done: if (err == Y4M_ERR_EOF) mjpeg_info("End of stream at frame %d.", frame_num); else { mjpeg_error("Failure at frame %d: %s", frame_num, y4m_strerr(err)); perror("sys:"); exit(1); } for (int i = 0; i < MAX_PLANES; i++) { delete[] in_upper[i]; delete[] in_lower[i]; delete[] in_other[i]; delete[] out_upper[i]; delete[] out_lower[i]; } delete[] in_upper; delete[] in_lower; delete[] in_other; y4m_fini_frame_info(&frameinfo); } /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ void ysScaling::_process_mixed(int fd_in, int fd_out, ysSource &source, ysTarget &target) { int err; y4m_frame_info_t frameinfo; uint8_t *in_frame[MAX_PLANES]; uint8_t *in_upper[MAX_PLANES]; uint8_t *in_lower[MAX_PLANES]; uint8_t *out_frame[MAX_PLANES]; uint8_t *out_upper[MAX_PLANES]; uint8_t *out_lower[MAX_PLANES]; int planes_in = source.stream().planes(); int planes_out = target.stream().planes(); y4m_init_frame_info(&frameinfo); for (int i = 0; i < MAX_PLANES; i++) { out_frame[i] = NULL; out_upper[i] = NULL; out_lower[i] = NULL; in_frame[i] = NULL; in_upper[i] = NULL; in_lower[i] = NULL; } for (int i = 0; i < planes_in; i++) { in_frame[i] = new uint8_t[source.stream().framedim(i).area()]; in_upper[i] = new uint8_t[source.stream().fielddim(i).area()]; in_lower[i] = new uint8_t[source.stream().fielddim(i).area()]; } for (int i = 0; i < planes_out; i++) { out_frame[i] = new uint8_t[target.stream().framedim(i).area()]; out_upper[i] = new uint8_t[target.stream().fielddim(i).area()]; out_lower[i] = new uint8_t[target.stream().fielddim(i).area()]; if ( ((i == PLANE_CB) || (i == PLANE_CR)) && (_mono) ) { memset(out_frame[i], 128, target.stream().framedim(i).area()); memset(out_upper[i], 128, target.stream().fielddim(i).area()); memset(out_lower[i], 128, target.stream().fielddim(i).area()); } else { memset(out_frame[i], target.bgcolor()(i), target.stream().framedim(i).area()); memset(out_upper[i], target.bgcolor()(i), target.stream().fielddim(i).area()); memset(out_lower[i], target.bgcolor()(i), target.stream().fielddim(i).area()); } } int frame_num = 0; while (1) { mjpeg_info("Frame number %d", frame_num); err = source.read_frame_header(fd_in, &frameinfo); if (err != Y4M_OK) goto done; int t_sampling = y4m_fi_get_temporal(&frameinfo); int s_sampling = y4m_fi_get_spatial(&frameinfo); int sampling; if (_vertically_mixed_source && (t_sampling != s_sampling)) { sampling = s_sampling; mjpeg_info("Anomalous mixed-mode frame! T=%c S=%c", (t_sampling == Y4M_SAMPLING_PROGRESSIVE) ? 'p' : (t_sampling == Y4M_SAMPLING_INTERLACED) ? 'i' : '?', (s_sampling == Y4M_SAMPLING_PROGRESSIVE) ? 'p' : (s_sampling == Y4M_SAMPLING_INTERLACED) ? 'i' : '?'); if (_anomalous_mixtures_are_fatal) { mjpeg_error("Only chroma upsampling (vertical) of anomalous frames"); mjpeg_error(" is allowed. (See manpage.)"); exit(1); } } else { sampling = t_sampling; } /* Always produce pp or ii output! */ /* And, always preserve t_sampling mode in output... Any processing here using s_sampling mode will only be one-time deal for chroma-upsampling. */ y4m_fi_set_spatial(&frameinfo, t_sampling); y4m_fi_set_temporal(&frameinfo, t_sampling); if (sampling == Y4M_SAMPLING_PROGRESSIVE) { /* Read frame. */ err = source.read_frame_data(fd_in, &frameinfo, in_frame); if (err != Y4M_OK) goto done; /* Scale luma always. */ _scalers[SC_PROG_Y]->scale(in_frame[PLANE_Y], out_frame[PLANE_Y]); /* Scale chroma maybe. */ if ((planes_in > 1) && (planes_out > 1) && (!_mono)) { _scalers[SC_PROG_CB]->scale(in_frame[PLANE_CB], out_frame[PLANE_CB]); _scalers[SC_PROG_CR]->scale(in_frame[PLANE_CR], out_frame[PLANE_CR]); } /* Scale alpha maybe. */ if ((planes_in > 3) && (planes_out > 3)) { _scalers[SC_PROG_A]->scale(in_frame[PLANE_A], out_frame[PLANE_A]); } /* Write frame. */ err = target.write_frame(fd_out, &frameinfo, out_frame); } else { /* == Y4M_SAMPLING_INTERLACED */ /* Read fields. */ err = source.read_fields_data(fd_in, &frameinfo, in_upper, in_lower); if (err != Y4M_OK) goto done; /* Scale luma always. */ _scalers[SC_INTER_Y]->scale(in_upper[PLANE_Y], out_upper[PLANE_Y]); _scalers[SC_INTER_Y]->scale(in_lower[PLANE_Y], out_lower[PLANE_Y]); /* Scale chroma maybe. */ if ((planes_in > 1) && (planes_out > 1) && (!_mono)) { _scalers[SC_UPPER_CB]->scale(in_upper[PLANE_CB], out_upper[PLANE_CB]); _scalers[SC_UPPER_CR]->scale(in_upper[PLANE_CR], out_upper[PLANE_CR]); _scalers[SC_LOWER_CB]->scale(in_lower[PLANE_CB], out_lower[PLANE_CB]); _scalers[SC_LOWER_CR]->scale(in_lower[PLANE_CR], out_lower[PLANE_CR]); } /* Scale alpha maybe. */ if ((planes_in > 3) && (planes_out > 3)) { _scalers[SC_INTER_A]->scale(in_upper[PLANE_A], out_upper[PLANE_A]); _scalers[SC_INTER_A]->scale(in_lower[PLANE_A], out_lower[PLANE_A]); } /* Write fields. */ err = target.write_fields(fd_out, &frameinfo, out_upper, out_lower); } if (err != Y4M_OK) goto done; frame_num++; } done: if (err == Y4M_ERR_EOF) mjpeg_info("End of stream at frame %d.", frame_num); else { mjpeg_error("Failure at frame %d: %s", frame_num, y4m_strerr(err)); exit(1); } for (int i = 0; i < MAX_PLANES; i++) { delete[] in_frame[i]; delete[] in_upper[i]; delete[] in_lower[i]; delete[] out_frame[i]; delete[] out_upper[i]; delete[] out_lower[i]; } y4m_fini_frame_info(&frameinfo); } /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ void ysScaling::create_scalers(const ysSource &source, const ysTarget &target) { destroy_scalers(); require_factory(); switch (target.stream().interlace()) { case Y4M_ILACE_NONE: _create_frame_scalers(source, target); break; case Y4M_ILACE_TOP_FIRST: case Y4M_ILACE_BOTTOM_FIRST: _create_field_scalers(source, target); break; case Y4M_ILACE_MIXED: _create_frame_scalers(source, target); _create_field_scalers(source, target); break; } } void ysScaling::destroy_scalers() { for (int i = 0; i < SC_MAX_SCALERS; i++) { delete _scalers[i]; _scalers[i] = NULL; } } void ysScaling::process_stream(int fd_in, int fd_out, ysSource &source, ysTarget &target) { switch (target.stream().interlace()) { case Y4M_ILACE_NONE: _process_frames(fd_in, fd_out, source, target); break; case Y4M_ILACE_TOP_FIRST: case Y4M_ILACE_BOTTOM_FIRST: _process_fields(fd_in, fd_out, source, target); break; case Y4M_ILACE_MIXED: _process_mixed(fd_in, fd_out, source, target); break; } } mjpegtools-2.1.0/y4mscaler/scaler-matto.H0000644000175000017500000001022612051575455020632 0ustar glowwormglowworm/* Copyright 2003 Matthew Marjanovic This file is part of y4mscaler. y4mscaler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. y4mscaler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with y4mscaler; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _SCALER_MATTO_H_ #define _SCALER_MATTO_H_ #include "scaler.H" #include "kernels.H" #define DEFAULT_KERNEL "cubicK4" class mattoScaler; class mattoScalerFactory : public ysScalerFactory { private: ysKernel *_the_x_kernel; ysKernel *_the_y_kernel; mattoScalerFactory(const mattoScalerFactory &orig); /* copy */ mattoScalerFactory &operator=(const mattoScalerFactory &orig); /* assign */ public: mattoScalerFactory() : _the_x_kernel(ysKernelFactory::instance()->create_kernel(DEFAULT_KERNEL)), _the_y_kernel(ysKernelFactory::instance()->create_kernel(DEFAULT_KERNEL)) {} virtual ~mattoScalerFactory() { delete _the_x_kernel; delete _the_y_kernel; } virtual const char *description() const; virtual void describe_options(FILE *fp, const char *prefix) const; virtual int parse_option(const char *s); virtual void describe_parameters(logging_function *logger, const char *prefix) const; virtual ysScaler *new_scaler() const; }; class mattoScaler : public ysScaler { private: class kernelSet; int SframeX, SframeY; // source frame size int DframeX, DframeY; // dest frame size int Sxmin, Sxmax, Symin, Symax; // source matte/sample boundary int Dx, Dy; // dest window size int xq0, yq0; // dest window offset ysRatio xp0, yp0; // source window offset ysRatio sigmaX, sigmaY; // scaling ratios int zero_pixel; // background/matte pixel value /* setup variables for scale_* */ //XXXXX const ysKernel *_the_kernel; // kernel function ysKernel *_the_x_kernel; // x kernel function ysKernel *_the_y_kernel; // y kernel function kernelSet *_KX; kernelSet *_KY; int _Yminspot, _Ymaxspot; int _Xminspot, _Xmaxspot; int TframeX, TframeY; // temporary frame size int *tempo; // temporary frame data void (mattoScaler::*scaling_function)(uint8_t *src, uint8_t *dst); int Dx_pre, Dx_fill, Dx_post; int Sx0, Sy0, Sy1; static void setup_kernel_cache(double scale, double p0, const ysKernel *kernel, int Dsize, int Smin, int Smax, int Spitch, int zero_pixel, int offset_premult, int offset_offset, kernelSet *&KS, int &minspot, int &maxspot); void setup_x_then_y(); void scale_x_then_y(uint8_t *src, uint8_t *dst); void setup_y_then_x(); void scale_y_then_x(uint8_t *src, uint8_t *dst); void setup_y_only(); void scale_y_only(uint8_t *src, uint8_t *dst); void setup_x_only(); void scale_x_only(uint8_t *src, uint8_t *dst); void setup_copy(); void scale_copy(uint8_t *src, uint8_t *dst); void scale_copy_direct(uint8_t *src, uint8_t *dst); void scale_fill(uint8_t *src, uint8_t *dst); int internal_setup(); protected: friend class mattoScalerFactory; mattoScaler(ysKernel *x_kernel, ysKernel *y_kernel) : _the_x_kernel(x_kernel), _the_y_kernel(y_kernel), _KX(NULL), _KY(NULL), tempo(NULL) {} mattoScaler(const mattoScaler &k); /* copy */ mattoScaler &operator=(const mattoScaler &v); /* assign */ public: virtual ~mattoScaler(); virtual int setup(const ysPoint &source_size, const ysRatioPoint &source_offset, const ysRegion &source_matte, const ysPoint &dest_size, const ysRegion &dest_region, const ysRatio &x_scale, const ysRatio &y_scale, uint8_t matte_pixel); virtual int scale(uint8_t *source, uint8_t *dest); }; #endif /* _SCALER_MATTO_H_ */ mjpegtools-2.1.0/y4mscaler/kernels.H0000644000175000017500000000374212051575455017707 0ustar glowwormglowworm/* Copyright 2003 Matthew Marjanovic This file is part of y4mscaler. y4mscaler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. y4mscaler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with y4mscaler; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _YS_KERNELS_H_ #define _YS_KERNELS_H_ class ysKernel { public: virtual ~ysKernel() {} virtual double k(double t) const = 0; virtual double support() const = 0; virtual const char *name() const = 0; virtual const char *desc() const = 0; virtual ysKernel *clone() const = 0; /* default behavior: accept no parameters */ virtual const char *pdesc() const { return ""; } virtual int pcount() const { return 0; } virtual int set_params(int count, double *params) { params = params; return (count != 0); } virtual double param(int index) { index = index; return 0.0; } }; class ysKernelFactory { private: ysKernel **_kernel_list; int _count; // static ysKernelFactory *_instance; protected: ysKernelFactory(); /* "There can be only one!" */ ~ysKernelFactory(); public: static const ysKernelFactory *instance(); const ysKernel *lookup(const char *name) const; const ysKernel *lookup(int i) const; int count() const { return _count; } /* take name of form "name:p1:p2...:pN" and create instance of kernel "name" with the given parameters */ ysKernel *create_kernel(const char *name) const; }; #endif /* _YS_KERNELS_H_ */ mjpegtools-2.1.0/y4mscaler/README0000644000175000017500000000103312051575455017002 0ustar glowwormglowworm This is "y4mscaler", a program which scales, crops, and shifts Y'CbCr video. It consumes and produces YUV4MPEG2 streams, as used by the MJPEGtools suite. Read the manual page, "y4mscaler.1", for more information. This program is released under the Gnu Public License (GPL), of which a copy is included in the file "COPYING". Please send any bug reports, feature request, or other commentary to: < dmg @ mir.com >. For more information and/or updates, consult: http://www.mir.com/DMG/y4mscaler.html Have fun, -matt marjanovic mjpegtools-2.1.0/y4mscaler/debug.h0000644000175000017500000000034512051575455017366 0ustar glowwormglowworm#ifndef _YS_debug_h_ #define _YS_debug_h_ #ifdef _YS_DEV_BRANCH_ # define DBG(format, args...) fprintf(stderr, format , ## args) # define _YS_DEBUG 1 #else # define DBG(format, args...) #endif #endif /* _YS_debug_h_ */ mjpegtools-2.1.0/y4mscaler/Makefile.in0000644000175000017500000004656212217306410020172 0ustar glowwormglowworm# Makefile.in generated by automake 1.12.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Makefile for y4mscaler VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @HAVE_ALTIVEC_TRUE@am__append_1 = $(top_builddir)/mpeg2enc/libmpeg2encpp.la bin_PROGRAMS = y4mscaler$(EXEEXT) subdir = y4mscaler DIST_COMMON = README $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(top_srcdir)/depcomp COPYING ChangeLog \ INSTALL TODO ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_y4mscaler_OBJECTS = graphics.$(OBJEXT) kernels.$(OBJEXT) \ scaler-matto.$(OBJEXT) y4mscaler.$(OBJEXT) ysScaling.$(OBJEXT) \ ysSource.$(OBJEXT) ysStreamInfo.$(OBJEXT) ysTarget.$(OBJEXT) y4mscaler_OBJECTS = $(am_y4mscaler_OBJECTS) y4mscaler_DEPENDENCIES = $(LIBMJPEGUTILS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(y4mscaler_SOURCES) DIST_SOURCES = $(y4mscaler_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALTIVEC_EXTRA_LIBS = @ALTIVEC_EXTRA_LIBS@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDV_CFLAGS = @LIBDV_CFLAGS@ LIBDV_LIBS = @LIBDV_LIBS@ LIBGETOPT_LIB = @LIBGETOPT_LIB@ LIBM_LIBS = @LIBM_LIBS@ LIBOBJS = @LIBOBJS@ LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ LIBPNG_LIBS = @LIBPNG_LIBS@ LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@ LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ LT_STATIC = @LT_STATIC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROGRAM_NOPIC = @PROGRAM_NOPIC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ SDLgfx_LIBS = @SDLgfx_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ V4LCONF_LIBS = @V4LCONF_LIBS@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAINTAINERCLEANFILES = Makefile.in EXTRA_DIST = ChangeLog README TODO AM_CFLAGS = -DNDEBUG -finline-functions -DYS_VERSION_MAJOR=9 -DYS_VERSION_MINOR=0 AM_CXXFLAGS = -DNDEBUG -finline-functions -DYS_VERSION_MAJOR=9 -DYS_VERSION_MINOR=0 INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/utils LIBMJPEGUTILS = $(top_builddir)/utils/libmjpegutils.la $(am__append_1) noinst_HEADERS = \ debug.h y4m-config.h \ graphics.H kernels.H scaler-matto.H scaler.H ysScaling.H \ ysSource.H ysStreamInfo.H ysTarget.H y4mscaler_SOURCES = graphics.C kernels.C scaler-matto.C y4mscaler.C \ ysScaling.C ysSource.C ysStreamInfo.C ysTarget.C y4mscaler_LDADD = $(LIBMJPEGUTILS) all: all-am .SUFFIXES: .SUFFIXES: .C .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu y4mscaler/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu y4mscaler/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list y4mscaler$(EXEEXT): $(y4mscaler_OBJECTS) $(y4mscaler_DEPENDENCIES) $(EXTRA_y4mscaler_DEPENDENCIES) @rm -f y4mscaler$(EXEEXT) $(CXXLINK) $(y4mscaler_OBJECTS) $(y4mscaler_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/graphics.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernels.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scaler-matto.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/y4mscaler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ysScaling.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ysSource.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ysStreamInfo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ysTarget.Po@am__quote@ .C.o: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .C.obj: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .C.lo: @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool cscopelist ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mjpegtools-2.1.0/y4mscaler/ysTarget.C0000644000175000017500000012320012051575455020031 0ustar glowwormglowworm/* Copyright 2003 Matthew Marjanovic This file is part of y4mscaler. y4mscaler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. y4mscaler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with y4mscaler; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "y4m-config.h" #include "debug.h" #include "ysTarget.H" #include /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ void ysTarget::set_prefab_target(PrefabType_t target, const ysSource &source) { switch (target) { case PREFAB_VCD: { switch (source.norm()) { case ysSource::NORM_NTSC: { mjpeg_info ("VCD output format requested in NTSC norm."); _stream.x_size(352); _stream.y_size(240); _stream.sar(y4m_sar_NTSC_CCIR601); _stream.interlace(Y4M_ILACE_NONE); //_stream.subsampling().mode(ysSubsampling::SS_420_JPEG); _stream.subsampling(ysSubsampling::SS_420_JPEG); } break; case ysSource::NORM_PAL: { mjpeg_info("VCD output format requested in PAL/SECAM norm."); _stream.x_size(352); _stream.y_size(288); _stream.sar(y4m_sar_PAL_CCIR601); _stream.interlace(Y4M_ILACE_NONE); //_stream.subsampling().mode(ysSubsampling::SS_420_JPEG); _stream.subsampling(ysSubsampling::SS_420_JPEG); } break; default: mjpeg_error_exit1("Unknown norm; cannot determine VCD format."); break; } } break; case PREFAB_CVD: { switch (source.norm()) { case ysSource::NORM_NTSC: { mjpeg_info ("CVD output format requested in NTSC norm."); _stream.x_size(352); _stream.y_size(480); _stream.sar(ysRatio(y4m_sar_NTSC_CCIR601) * 2); //_stream.interlace(Y4M_ILACE_NONE); // interlace ok --- but is it required???? //_stream.subsampling().mode(ysSubsampling::SS_420_MPEG2); _stream.subsampling(ysSubsampling::SS_420_MPEG2); } break; case ysSource::NORM_PAL: { mjpeg_info("CVD output format requested in PAL/SECAM norm."); _stream.x_size(352); _stream.y_size(576); _stream.sar(ysRatio(y4m_sar_PAL_CCIR601) * 2); //_stream.interlace(Y4M_ILACE_NONE); // interlace ok --- but is it required???? //_stream.subsampling().mode(ysSubsampling::SS_420_MPEG2); _stream.subsampling(ysSubsampling::SS_420_MPEG2); } break; default: mjpeg_error_exit1("Unknown norm; cannot determine CVD format."); break; } } break; case PREFAB_SVCD: { switch (source.norm()) { case ysSource::NORM_NTSC: { mjpeg_info ("SVCD output format requested in NTSC norm."); _stream.x_size(480); _stream.y_size(480); _stream.sar(y4m_sar_NTSC_SVCD_4_3); //_stream.interlace(Y4M_ILACE_NONE); // interlace ok --- but is it required???? //_stream.subsampling().mode(ysSubsampling::SS_420_MPEG2); _stream.subsampling(ysSubsampling::SS_420_MPEG2); } break; case ysSource::NORM_PAL: { mjpeg_info("SVCD output format requested in PAL/SECAM norm."); _stream.x_size(480); _stream.y_size(576); _stream.sar(y4m_sar_PAL_SVCD_4_3); //_stream.interlace(Y4M_ILACE_NONE); // interlace ok --- but is it required???? // _stream.subsampling().mode(ysSubsampling::SS_420_MPEG2); _stream.subsampling(ysSubsampling::SS_420_MPEG2); } break; default: mjpeg_error_exit1("Unknown norm; cannot determine SVCD format."); break; } } break; case PREFAB_DVD: { switch (source.norm()) { case ysSource::NORM_NTSC: { mjpeg_info ("DVD output format requested in NTSC norm."); _stream.x_size(720); _stream.y_size(480); _stream.sar(y4m_sar_NTSC_CCIR601); //_stream.interlace(Y4M_ILACE_NONE); // interlace ok --- but is it required???? //_stream.subsampling().mode(ysSubsampling::SS_420_MPEG2); _stream.subsampling(ysSubsampling::SS_420_MPEG2); } break; case ysSource::NORM_PAL: { mjpeg_info("DVD output format requested in PAL/SECAM norm."); _stream.x_size(720); _stream.y_size(576); _stream.sar(y4m_sar_PAL_CCIR601); //_stream.interlace(Y4M_ILACE_NONE); // interlace ok --- but is it required???? // _stream.subsampling().mode(ysSubsampling::SS_420_MPEG2); _stream.subsampling(ysSubsampling::SS_420_MPEG2); } break; default: mjpeg_error_exit1("Unknown norm; cannot determine DVD format."); break; } } break; case PREFAB_DVD_WIDE: { switch (source.norm()) { case ysSource::NORM_NTSC: { mjpeg_info ("DVD(widescreen) output format requested in NTSC norm."); _stream.x_size(720); _stream.y_size(480); _stream.sar(y4m_sar_NTSC_16_9); //_stream.interlace(Y4M_ILACE_NONE); // interlace ok --- but is it required???? //_stream.subsampling().mode(ysSubsampling::SS_420_MPEG2); _stream.subsampling(ysSubsampling::SS_420_MPEG2); } break; case ysSource::NORM_PAL: { mjpeg_info("DVD(widescreen) output format requested in PAL/SECAM norm."); _stream.x_size(720); _stream.y_size(576); _stream.sar(y4m_sar_PAL_16_9); //_stream.interlace(Y4M_ILACE_NONE); // interlace ok --- but is it required???? // _stream.subsampling().mode(ysSubsampling::SS_420_MPEG2); _stream.subsampling(ysSubsampling::SS_420_MPEG2); } break; default: mjpeg_error_exit1("Unknown norm; cannot determine DVD(widescreen) format."); break; } } break; case PREFAB_DV: { switch (source.norm()) { case ysSource::NORM_NTSC: { mjpeg_info ("DV output format requested in NTSC norm."); _stream.x_size(720); _stream.y_size(480); _stream.sar(y4m_sar_NTSC_CCIR601); _stream.interlace(Y4M_ILACE_BOTTOM_FIRST); //_stream.subsampling().mode(ysSubsampling::SS_411); _stream.subsampling(ysSubsampling::SS_411); } break; case ysSource::NORM_PAL: { mjpeg_info("DV output format requested in PAL/SECAM norm."); _stream.x_size(720); _stream.y_size(576); _stream.sar(y4m_sar_PAL_CCIR601); _stream.interlace(Y4M_ILACE_BOTTOM_FIRST); // _stream.subsampling().mode(ysSubsampling::SS_420_PALDV); _stream.subsampling(ysSubsampling::SS_420_PALDV); } break; default: mjpeg_error_exit1("Unknown norm; cannot determine DV format."); break; } } break; case PREFAB_DV_WIDE: { switch (source.norm()) { case ysSource::NORM_NTSC: { mjpeg_info ("DV(widescreen) output format requested in NTSC norm."); _stream.x_size(720); _stream.y_size(480); _stream.sar(y4m_sar_NTSC_16_9); _stream.interlace(Y4M_ILACE_BOTTOM_FIRST); _stream.subsampling(ysSubsampling::SS_411); } break; case ysSource::NORM_PAL: { mjpeg_info("DV(widescreen) output format requested in PAL/SECAM norm."); _stream.x_size(720); _stream.y_size(576); _stream.sar(y4m_sar_PAL_16_9); _stream.interlace(Y4M_ILACE_BOTTOM_FIRST); _stream.subsampling(ysSubsampling::SS_420_PALDV); } break; default: mjpeg_error_exit1("Unknown norm; cannot determine DV(widescreen) format."); break; } } break; case PREFAB_SVCD_STILL_HI: case PREFAB_VCD_STILL_HI: { switch (source.norm()) { case ysSource::NORM_NTSC: mjpeg_info ("SVCD/VCD hi-res still image format requested, NTSC."); _stream.y_size(480); _stream.sar(y4m_sar_NTSC_CCIR601); break; case ysSource::NORM_PAL: mjpeg_info ("SVCD/VCD hi-res still image format requested, PAL."); _stream.y_size(576); _stream.sar(y4m_sar_PAL_CCIR601); break; default: mjpeg_error_exit1("Unknown norm; cannot determine image format."); break; } _stream.x_size(704); _stream.interlace(Y4M_ILACE_NONE); if (target == PREFAB_SVCD_STILL_HI) _stream.subsampling(ysSubsampling::SS_420_MPEG2); else _stream.subsampling(ysSubsampling::SS_420_JPEG); } break; case PREFAB_SVCD_STILL_LO: { switch (source.norm()) { case ysSource::NORM_NTSC: mjpeg_info ("SVCD lo-res still image format requested, NTSC."); _stream.y_size(480); _stream.sar(y4m_sar_NTSC_SVCD_4_3); break; case ysSource::NORM_PAL: mjpeg_info ("SVCD lo-res still image format requested, PAL."); _stream.y_size(576); _stream.sar(y4m_sar_PAL_SVCD_4_3); break; default: mjpeg_error_exit1("Unknown norm; cannot determine image format."); break; } _stream.x_size(480); _stream.interlace(Y4M_ILACE_NONE); _stream.subsampling(ysSubsampling::SS_420_MPEG2); } break; case PREFAB_VCD_STILL_LO: { switch (source.norm()) { case ysSource::NORM_NTSC: mjpeg_info ("VCD lo-res still image format requested, NTSC."); _stream.y_size(240); _stream.sar(y4m_sar_NTSC_CCIR601); break; case ysSource::NORM_PAL: mjpeg_info ("VCD lo-res still image format requested, PAL."); _stream.y_size(288); _stream.sar(y4m_sar_PAL_CCIR601); break; default: mjpeg_error_exit1("Unknown norm; cannot determine image format."); break; } _stream.x_size(352); _stream.interlace(Y4M_ILACE_NONE); _stream.subsampling(ysSubsampling::SS_420_JPEG); } break; case PREFAB_ATSC_720P: { if (source.norm() == ysSource::NORM_PAL) mjpeg_warn("ATSC preset requested for PAL norm --- ignoring norm."); mjpeg_info ("ATSC 720p output format requested."); _stream.x_size(1280); _stream.y_size(720); _stream.sar(y4m_sar_SQUARE); _stream.interlace(Y4M_ILACE_NONE); _stream.subsampling(ysSubsampling::SS_420_MPEG2); } break; case PREFAB_ATSC_1080I: { if (source.norm() == ysSource::NORM_PAL) mjpeg_warn("ATSC preset requested for PAL norm --- ignoring norm."); mjpeg_info ("ATSC 1080i output format requested."); _stream.x_size(1920); _stream.y_size(1080); _stream.sar(y4m_sar_SQUARE); _stream.subsampling(ysSubsampling::SS_420_MPEG2); { int ilace = source.stream().interlace(); if (ilace == Y4M_ILACE_NONE) { mjpeg_warn("1080i requires interlacing; defaulting to bottom-first."); ilace = Y4M_ILACE_BOTTOM_FIRST; } _stream.interlace(ilace); } } break; case PREFAB_ATSC_1080P: { if (source.norm() == ysSource::NORM_PAL) mjpeg_warn("ATSC preset requested for PAL norm --- ignoring norm."); mjpeg_info ("ATSC 1080p output format requested."); _stream.x_size(1920); _stream.y_size(1080); _stream.sar(y4m_sar_SQUARE); _stream.interlace(Y4M_ILACE_NONE); _stream.subsampling(ysSubsampling::SS_420_MPEG2); } break; default: mjpeg_error_exit1("Spurious prefab format requested!"); break; } } /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ void ysTarget::init_stream(const ysSource &source) { _stream = source.stream(); _stream.x_size(Y4M_UNKNOWN); _stream.y_size(Y4M_UNKNOWN); _stream.interlace(Y4M_UNKNOWN); _stream.sar(ysRatio()); _stream.subsampling(ysSubsampling::SS_UNKNOWN); } void ysTarget::describe_keywords(FILE *fp, const char *prefix) const { fprintf(fp, "%ssize=[ WxH | src ]\n", prefix); fprintf(fp, "%sactive=WxH+X+Y\n", prefix); { ysYCbCr defbg(default_bgcolor()); fprintf(fp, "%sbg=[ RGB:r,g,b | YCBCR:y,cb,cr |\n", prefix); fprintf(fp, "%s RGBA:r,g,b,a | YCBCR:y,cb,cr,a ] (YCBCRA:%d,%d,%d,%d)\n", prefix, defbg(0), defbg(1), defbg(2), defbg(3)); } fprintf(fp, "%silace=[ NONE | TOP_FIRST | BOTTOM_FIRST ]\n", prefix); //fprintf(fp, "%schromass=[ 420_JPEG | 420_MPEG2 | 420_PALDV ]\n", prefix); { fprintf(fp, "%schromass=[ ", prefix); int i = 0; const char *keyword; while ((keyword = y4m_chroma_keyword(i++)) != NULL) fprintf(fp, "%s%s ", (i < 2) ? "" : "| ", keyword); fprintf(fp, "]\n"); } fprintf(fp, "%ssar=[ N:D | src | NTSC | PAL | NTSC_WIDE | PAL_WIDE ]\n", prefix); fprintf(fp, "%sscale=N/D\n", prefix); fprintf(fp, "%sXscale=N/D\n", prefix); fprintf(fp, "%sYscale=N/D\n", prefix); fprintf(fp, "%sinfer=[ PAD | CLIP | PRESERVE_X | PRESERVE_Y ] (CLIP)\n", prefix); fprintf(fp, "%sinfer=[ SIMPLIFY | EXACT ] (SIMPLIFY)\n", prefix); fprintf(fp, "%salign=[ TL | TC | TR | CL | CC | CR | BL | BC | BR ] (CC)\n", prefix); fprintf(fp, "%spreset=[ VCD | CVD | SVCD | DVD | DVD_WIDE | DV | DV_WIDE |\n", prefix); fprintf(fp, "%s VCD_STILL_LO | VCD_STILL_HI | SVCD_STILL_LO | SVCD_STILL_HI |\n", prefix); fprintf(fp, "%s ATSC_720P | ATSC_1080I | ATSC_1080P ]\n", prefix); } void ysTarget::parse_keyword(ysSource &source, char *optarg) { if (!(strncasecmp(optarg, "SIZE=", 5))) { if (!strcasecmp(optarg+5, "src")) { _stream.dim(source.stream().dim()); } else if (_stream.parse_dimensions(optarg+5)) { mjpeg_error_exit1("Bad dimensions spec: '%s'", optarg+5); } } else if (!strncasecmp(optarg, "ACTIVE=", 7)) { if (_active_region.parse_geometry(optarg+7)) { mjpeg_error_exit1("Bad geometery spec: '%s'", optarg); } } else if (!strncasecmp(optarg, "BG=", 3)) { bgcolor(ysYCbCr::parse_string(optarg+3)); } else if (!strncasecmp(optarg, "PRESET=", 7)) { if (!(strcasecmp(optarg+7, "VCD"))) { set_prefab_target(PREFAB_VCD, source); } else if (!(strcasecmp(optarg+7, "CVD"))) { set_prefab_target(PREFAB_CVD, source); } else if (!(strcasecmp(optarg+7, "SVCD"))) { set_prefab_target(PREFAB_SVCD, source); } else if (!(strcasecmp(optarg+7, "DVD"))) { set_prefab_target(PREFAB_DVD, source); } else if (!(strcasecmp(optarg+7, "DVD_WIDE"))) { set_prefab_target(PREFAB_DVD_WIDE, source); } else if (!(strcasecmp(optarg+7, "DV"))) { set_prefab_target(PREFAB_DV, source); } else if (!(strcasecmp(optarg+7, "DV_WIDE"))) { set_prefab_target(PREFAB_DV_WIDE, source); } else if (!(strcasecmp(optarg+7, "VCD_STILL_LO"))) { set_prefab_target(PREFAB_VCD_STILL_LO, source); } else if (!(strcasecmp(optarg+7, "VCD_STILL_HI"))) { set_prefab_target(PREFAB_VCD_STILL_HI, source); } else if (!(strcasecmp(optarg+7, "SVCD_STILL_LO"))) { set_prefab_target(PREFAB_SVCD_STILL_LO, source); } else if (!(strcasecmp(optarg+7, "SVCD_STILL_HI"))) { set_prefab_target(PREFAB_SVCD_STILL_HI, source); } else if (!(strcasecmp(optarg+7, "ATSC_720P"))) { set_prefab_target(PREFAB_ATSC_720P, source); } else if (!(strcasecmp(optarg+7, "ATSC_1080I"))) { set_prefab_target(PREFAB_ATSC_1080I, source); } else if (!(strcasecmp(optarg+7, "ATSC_1080P"))) { set_prefab_target(PREFAB_ATSC_1080P, source); } else { mjpeg_error_exit1("Unknown preset keyword: '%s'", optarg); } } else if (!strncasecmp(optarg, "SCALE=", 6)) { ysRatio s; if (s.parse_ratio(optarg+6)) { mjpeg_error_exit1("Bad ratio spec: '%s'", optarg); } _x_ratio = s; _y_ratio = s; } else if (!strncasecmp(optarg, "XSCALE=", 7)) { ysRatio s; if (s.parse_ratio(optarg+7)) { mjpeg_error_exit1("Bad ratio spec: '%s'", optarg); } _x_ratio = s; } else if (!strncasecmp(optarg, "YSCALE=", 7)) { ysRatio s; if (s.parse_ratio(optarg+7)) { mjpeg_error_exit1("Bad ratio spec: '%s'", optarg); } _y_ratio = s; } else if (!strncasecmp(optarg, "SAR=", 4)) { ysRatio sar; if (!strcasecmp(optarg+4, "src")) { sar = source.stream().sar(); } else if (!strcasecmp(optarg+4, "NTSC")) { sar = y4m_sar_NTSC_CCIR601; } else if (!strcasecmp(optarg+4, "PAL")) { sar = y4m_sar_PAL_CCIR601; } else if (!strcasecmp(optarg+4, "NTSC_WIDE")) { sar = y4m_sar_NTSC_16_9; } else if (!strcasecmp(optarg+4, "PAL_WIDE")) { sar = y4m_sar_PAL_16_9; } else if (sar.parse_ratio(optarg+4)) { mjpeg_error_exit1("Bad ratio spec: '%s'", optarg); } _stream.sar(sar); } else if (!strncasecmp(optarg, "CHROMASS=", 9)) { if (_stream.parse_subsampling(optarg+9)) { mjpeg_error_exit1("Bad chroma subsampling spec: '%s'", optarg); } } else if (!strncasecmp(optarg, "ILACE=", 6)) { if (!strcasecmp(optarg+6, "TOP_FIRST")) { _stream.interlace(Y4M_ILACE_TOP_FIRST); } else if (!strcasecmp(optarg+6, "BOTTOM_FIRST")) { _stream.interlace(Y4M_ILACE_BOTTOM_FIRST); } else if (!strcasecmp(optarg+6, "NONE")) { _stream.interlace(Y4M_ILACE_NONE); } else { mjpeg_error_exit1("Bad interlace spec: '%s'", optarg); } } else if (!strcasecmp(optarg, "INFER=CLIP")) { _reconcile_mode = RCMD_CLIP; } else if (!strcasecmp(optarg, "INFER=PAD")) { _reconcile_mode = RCMD_PAD; } else if (!strcasecmp(optarg, "INFER=PRESERVE_X")) { _reconcile_mode = RCMD_PRESERVE_X; } else if (!strcasecmp(optarg, "INFER=PRESERVE_Y")) { _reconcile_mode = RCMD_PRESERVE_Y; } else if (!strcasecmp(optarg, "INFER=SIMPLIFY")) { _reconcile_mode2 = RCMD2_SIMPLIFY; } else if (!strcasecmp(optarg, "INFER=EXACT")) { _reconcile_mode2 = RCMD2_EXACT; } else if (!strncasecmp(optarg, "ALIGN=", 6)) { _anchor_mode = parse_anchor_mode(optarg+6); if (_anchor_mode == ANC_UNKNOWN) mjpeg_error_exit1("Bad anchor mode specifier: '%s'", optarg); } else mjpeg_error_exit1("Unrecognized output parameter: %s", optarg); } /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ void ysTarget::require_interlace(const ysSource &source) { if (_stream.interlace() == Y4M_UNKNOWN) { mjpeg_info("Target interlacing defaulting to match source."); _stream.interlace(source.stream().interlace()); } } void ysTarget::require_chromass(const ysSource &source) { if (!_stream.subsampling().is_known()) { mjpeg_info("Target chroma subsampling defaulting to match source."); _stream.subsampling(source.stream().subsampling().mode()); } } void ysTarget::require_sar(const ysSource &source) { if (!_stream.sar().is_known()) { mjpeg_info("Target SAR defaulting to match source."); _stream.sar(source.stream().sar()); } } void ysTarget::require_framesize(const ysSource &source) { int cause_to_exit = 0; if (_stream.dim().is_known()) { /* size set by user; verify correct alignment */ int xal = _stream.x_alignment(); int yal = _stream.y_alignment(); if (_stream.x_size() % xal) { mjpeg_error("Target x size (%d) is not multiple of %d!", _stream.x_size(), xal); cause_to_exit = 1; } if (_stream.y_size() % yal) { mjpeg_error("Target y size (%d) is not multiple of %d!", _stream.y_size(), yal); cause_to_exit = 1; } } else { /* if both ratios set: use ratios to calc from source size else if one ratio and sar: use ratio and sar to calc from source size else: use source size */ ysRatio xsize = source.stream().x_size(); ysRatio ysize = source.stream().y_size(); if (_x_ratio.is_known() && _y_ratio.is_known()) { mjpeg_info("Target frame size defaulting to scaled source size."); xsize *= _x_ratio; ysize *= _y_ratio; } else if (_x_ratio.is_known() || _y_ratio.is_known()) { require_sar(source); if (_x_ratio.is_known()) { mjpeg_info("Target frame size defaulting to scaled source size."); xsize *= _x_ratio; ysize *= _x_ratio * _stream.sar() / source.stream().sar(); } else if (_y_ratio.is_known()) { mjpeg_info("Target frame size defaulting to scaled source size."); xsize *= _y_ratio / _stream.sar() * source.stream().sar(); ysize *= _y_ratio; } } else { mjpeg_info("Target frame size defaulting to match source."); } /* perhaps we should adjust instead of flagging error... */ int xal = _stream.x_alignment(); int yal = _stream.y_alignment(); if (!xsize.is_integral()) { mjpeg_error("Scaled source x size (%f) is not integral!", xsize.to_double()); cause_to_exit = 1; } else if (xsize.to_int() % xal) { mjpeg_error("Scaled source x size (%d) is not multiple of %d!", xsize.to_int(), xal); cause_to_exit = 1; } if (!ysize.is_integral()) { mjpeg_error("Scaled source y size (%f) is not integral!", ysize.to_double()); cause_to_exit = 1; } else if (ysize.to_int() % yal) { mjpeg_error("Scaled source y size (%d) is not multiple of %d!", ysize.to_int(), yal); cause_to_exit = 1; } _stream.x_size(xsize.to_int()); _stream.y_size(ysize.to_int()); } if (cause_to_exit) exit(1); } void ysTarget::require_active_region(void) { #if 0 if (!_active_region.is_known()) { mjpeg_info("Target active region defaulting to target frame size."); _active_region = ysRegion(_stream.dim(), ysPoint(0,0)); } else { _active_region.fixate(_stream.dim()); } #else if (!_active_region.is_known()) { if (_active_region.offset().is_known()) { mjpeg_info("Target active region defaulting to target frame size."); _active_region.dim(_stream.dim()); } else { mjpeg_info("Target active region defaulting to full target frame."); _active_region = ysRegion(_stream.dim()); _active_region.origin_mode(ANC_TL); } } _active_region.fixate(_stream.dim()); #endif } void ysTarget::calculate_y_ratio_from_x_ratio_and_sars(const ysSource &source) { mjpeg_info("Deriving Y ratio from X ratio and SARs..."); _y_ratio = _x_ratio * _stream.sar() / source.stream().sar(); } void ysTarget::calculate_x_ratio_from_y_ratio_and_sars(const ysSource &source) { mjpeg_info("Deriving X ratio from Y ratio and SARs..."); _x_ratio = _y_ratio / _stream.sar() * source.stream().sar(); } void ysTarget::calculate_ratios_from_active_regions(const ysSource &source) { mjpeg_info("Deriving ratios from active regions..."); /* calculate scaling ratios */ _x_ratio = ysRatio(_active_region.dim().x()) / source.active_region().dim().x(); _y_ratio = ysRatio(_active_region.dim().y()) / source.active_region().dim().y(); /* calculate target SAR */ // _stream.sar(source.stream().sar() / _x_ratio * _y_ratio); // ^... subsumed by reconcile_sar_with_ratios() } static inline float score_ratios(ysRatio xr, ysRatio yr) { // return ((double)xr.numerator() * (double)xr.denominator() * // (double)yr.numerator() * (double)yr.denominator()); // One only needs to score the denominators --- since the X and Y ratios // are within P% of some optimum, then the numerators are always going // to scale with the denominators. I.e. since xr is roughly 'F', then // xr.num = F * xr.den --- if the denominator is huge, so is the // numerator. return ((float)xr.denominator() * (float)yr.denominator()); } /* ry = rx * scale_ratio */ static inline bool within_percent(float A, float A0, float pcent) { float Amin = A0 * (1.0 - pcent); float Amax = A0 * (1.0 + pcent); return (Amin < A) && (A < Amax); } #define SLIP_LIMIT 0.10 #include static void find_simpler_scales_x_y(ysRatio &sx, ysRatio &sy, ysRatio sx_base, ysRatio scale_ratio) { int xn = sx_base.numerator(); int xd = sx_base.denominator(); float xf = sx_base.to_float(); int n; int d; int n0 = xn * 900 / 1000; int n1 = xn * 1100 / 1000; int d0 = xd * 900 / 1000; int d1 = xd * 1100 / 1000; if (n0 <= 0) n0 = 1; if (d0 <= 0) d0 = 1; // DBG("n %d-%d d %d-%d\n", n0, n1, d0, d1); sx = sx_base; sy = sx * scale_ratio; float best_score = score_ratios(sx, sy); float yf = sy.to_float(); for (n = n0; n <= n1; n++) { for (d = d0; d <= d1; d++) { ysRatio newx(n, d); ysRatio newy = newx * scale_ratio; float newscore = score_ratios(newx, newy); // DBG("n/d %d/%d %d/%d %d\n", // n, d, newy.numerator(), newy.denominator(), newscore); if (newscore < best_score) { if (within_percent(newx.to_float(), xf, SLIP_LIMIT) && within_percent(newy.to_float(), yf, SLIP_LIMIT)) { best_score = newscore; sx = newx; sy = newy; //DBG("better: %" PRID64_STRING_FORMAT " %d/%d %d/%d\n", //best_score, newx.numerator(), newx.denominator(), //newy.numerator(), newy.denominator()); } } } } } void ysTarget::calculate_ratios_from_active_regions_and_sar(const ysSource &source) { mjpeg_info("Deriving ratios from active regions and SARs..."); ysRatio xratioA = ysRatio(_active_region.dim().x()) / source.active_region().dim().x(); ysRatio yratioA = xratioA * _stream.sar() / source.stream().sar(); ysRatio yratioB = ysRatio(_active_region.dim().y()) / source.active_region().dim().y(); ysRatio xratioB = yratioB / _stream.sar() * source.stream().sar(); mjpeg_debug("xrA %d : %d", xratioA.numerator(), xratioA.denominator()); mjpeg_debug("yrA %d : %d", yratioA.numerator(), yratioA.denominator()); mjpeg_debug("xrB %d : %d", xratioB.numerator(), xratioB.denominator()); mjpeg_debug("yrB %d : %d", yratioB.numerator(), yratioB.denominator()); int syA = (source.active_region().dim().y() * yratioA).to_int(); // int sxB = (source.active_region().dim().x() * xratioB).to_int(); switch (_reconcile_mode) { case RCMD_PRESERVE_X: mjpeg_info("...using scaling ratios which preserve X size."); _x_ratio = xratioA; _y_ratio = yratioA; break; case RCMD_PRESERVE_Y: mjpeg_info("...using scaling ratios which preserve Y size."); _x_ratio = xratioB; _y_ratio = yratioB; break; case RCMD_CLIP: mjpeg_info("...using scaling ratios which clip target."); if (syA > _active_region.dim().y()) { /* 'A' will clip in Y direction */ _x_ratio = xratioA; _y_ratio = yratioA; } else { /* 'B' will clip in X direction */ _x_ratio = xratioB; _y_ratio = yratioB; } break; // default: case RCMD_PAD: mjpeg_info("...using scaling ratios which pad target."); if (syA < _active_region.dim().y()) { /* 'A' will pad in Y direction */ _x_ratio = xratioA; _y_ratio = yratioA; } else { /* 'B' will pad in X direction */ _x_ratio = xratioB; _y_ratio = yratioB; } break; } mjpeg_debug("pre x %d : %d", _x_ratio.numerator(), _x_ratio.denominator()); mjpeg_debug("pre y %d : %d", _y_ratio.numerator(), _y_ratio.denominator()); switch (_reconcile_mode2) { case RCMD2_SIMPLIFY: mjpeg_info("...using scaling ratios which are simple."); find_simpler_scales_x_y(_x_ratio, _y_ratio, _x_ratio, _stream.sar() / source.stream().sar()); break; case RCMD2_EXACT: // default: mjpeg_info("...using scaling ratios which are exact."); break; } mjpeg_debug("post x %d : %d", _x_ratio.numerator(), _x_ratio.denominator()); mjpeg_debug("post y %d : %d", _y_ratio.numerator(), _y_ratio.denominator()); } void ysTarget::reconcile_active_regions_with_ratios(ysSource &source) { /* * new target region = intersection of (old region) and (proj. of src region) * new source region = intersection of (old region) and (proj. of tgt region) * */ ysRatioRegion real_tgt(_active_region); /* project src region -> tgt space */ ysRatioRegion proj_src(source.active_region().dim() * ysRatioPoint(_x_ratio, _y_ratio), ysPoint(0,0)); /* align */ // proj_src.align_to(real_tgt, _align_mode); ///// proj_src.center_to(real_tgt); proj_src.align_to(real_tgt, _anchor_mode); /* clip target to projected source */ if (real_tgt.clip(proj_src) != ysRatioRegion(0,0,0,0)) { mjpeg_warn("Target active region clipped by projection of source."); } /* project new tgt region -> src space */ ysRatioRegion proj_tgt(real_tgt.dim() / ysRatioPoint(_x_ratio, _y_ratio), ysPoint(0,0)); /* align */ // proj_tgt.align_to(source.active_region(), _align_mode); //// proj_tgt.center_to(source.active_region()); proj_tgt.align_to(source.active_region(), _anchor_mode); /* clip source to projected target */ if (source.active_region().clip(proj_tgt) != ysRatioRegion(0,0,0,0)) { mjpeg_warn("Source active region clipped by projection of target."); } /* at this point, * source.active_region() and real_tgt are properly aligned with respect * to each other and to the frames, and mutually clipped. */ #if 0 /* source doesn't really need to be clipped to frame, since it is matted to at most frame-size anyway. */ { /* clip source to frame */ ysRatioRegion delta = source.active_region().clip(ysRatioPoint(source.stream().dim())); if (delta != ysRatioRegion(0,0,0,0)) { mjpeg_warn("Source active region clipped by source frame size."); } ysRatioPoint src_ul_delta = delta.ul(); ysRatioPoint src_lr_delta = delta.lr(); /* project delta back to target */ src_ul_delta *= _x_ratio; src_lr_delta *= _y_ratio; /* if delta is 'inward', clip target */ if (src_ul_delta.x() < 0) src_ul_delta = ysRatioPoint(0, src_ul_delta.y()); if (src_ul_delta.y() < 0) src_ul_delta = ysRatioPoint(src_ul_delta.x(), 0); if (src_lr_delta.x() > 0) src_ul_delta = ysRatioPoint(0, src_ul_delta.y()); if (src_lr_delta.y() > 0) src_ul_delta = ysRatioPoint(src_ul_delta.x(), 0); ysRatioPoint tgt_ul_new = real_tgt.ul() + src_ul_delta; ysRatioPoint tgt_lr_new = real_tgt.lr() + src_lr_delta; real_tgt = ysRatioRegion(tgt_lr_new - tgt_ul_new, tgt_ul_new); } #endif { ysRatioRegion delta; /* clip target to frame */ delta = real_tgt.clip(ysRatioPoint(_stream.dim())); if (delta != ysRatioRegion(0,0,0,0)) { mjpeg_warn("Target active region clipped by target frame size."); } ysRatioPoint tgt_ul_delta = delta.ul(); ysRatioPoint tgt_lr_delta = delta.lr(); /* make target integral and check alignment */ delta = check_active_alignment(real_tgt); tgt_ul_delta += delta.ul(); tgt_lr_delta += delta.lr(); DBG("tgt d (%f,%f) (%f,%f)\n", tgt_ul_delta.x().to_double(), tgt_ul_delta.y().to_double(), tgt_lr_delta.x().to_double(), tgt_lr_delta.y().to_double()); /* project delta back to source */ tgt_ul_delta /= _x_ratio; tgt_lr_delta /= _y_ratio; /* if delta is 'inward', clip target */ if (tgt_ul_delta.x() < 0) tgt_ul_delta = ysRatioPoint(0, tgt_ul_delta.y()); if (tgt_ul_delta.y() < 0) tgt_ul_delta = ysRatioPoint(tgt_ul_delta.x(), 0); if (tgt_lr_delta.x() > 0) tgt_ul_delta = ysRatioPoint(0, tgt_ul_delta.y()); if (tgt_lr_delta.y() > 0) tgt_ul_delta = ysRatioPoint(tgt_ul_delta.x(), 0); ysRatioPoint src_ul_new = source.active_region().ul() + tgt_ul_delta; ysRatioPoint src_lr_new = source.active_region().lr() + tgt_lr_delta; source.active_region() = ysRatioRegion(src_lr_new - src_ul_new, src_ul_new); } /* set target active region for real */ _active_region = ysRegion(real_tgt.dim().x().to_int(), real_tgt.dim().y().to_int(), real_tgt.offset().x().to_int(), real_tgt.offset().y().to_int()); } ysRatioRegion ysTarget::check_active_alignment(ysRatioRegion &r) { int xal = _stream.x_alignment(); int yal = _stream.y_alignment(); int rem; /* are sizes/offsets compatible with subsampling/interlacing? */ ysRatio dox, doy, dpx, dpy; int ox, oy, px, py; /* round 'inwards' */ if (!r.ul().x().is_integral()) { ox = r.ul().x().to_int() + 1; dox = ysRatio(ox) - r.ul().x(); } else { ox = r.ul().x().to_int(); dox = 0; } if (!r.ul().y().is_integral()) { oy = r.ul().y().to_int() + 1; doy = ysRatio(oy) - r.ul().y(); } else { oy = r.ul().y().to_int(); doy = 0; } if (!r.lr().x().is_integral()) { px = r.lr().x().to_int(); dpx = ysRatio(px) - r.lr().x(); } else { px = r.lr().x().to_int(); dpx = 0; } if (!r.lr().y().is_integral()) { py = r.lr().y().to_int(); dpy = ysRatio(py) - r.lr().y(); } else { py = r.lr().y().to_int(); dpy = 0; } if ((rem = (ox % xal)) != 0) { mjpeg_warn("Target active region x1 (%d) is not multiple of %d...", ox, xal); mjpeg_warn(" ...shifted right by %d.", rem); ox += xal - rem; dox += xal - rem; } if ((rem = (px % xal)) != 0) { mjpeg_warn("Target active region x2 (%d) is not multiple of %d...", px, xal); mjpeg_warn(" ...shifted left by %d.", rem); px -= rem; dpx -= rem; } if ((rem = (oy % yal)) != 0) { mjpeg_warn("Target active region y1 (%d) is not multiple of %d...", oy, yal); mjpeg_warn(" ...shifted down by %d.", rem); oy += yal - rem; doy += yal - rem; } if ((rem = (py % yal)) != 0) { mjpeg_warn("Target active region y2 (%d) is not multiple of %d...", py, yal); mjpeg_warn(" ...shifted up by %d.", rem); py -= rem; dpy -= rem; } r = ysRatioRegion((px - ox), (py - oy), ox, oy); return ysRatioRegion((dpx - dox), (dpy - doy), dox, doy); } void ysTarget::reconcile_sar_with_ratios(const ysSource &source) { ysRatio out_sar = source.stream().sar() * _y_ratio / _x_ratio; if (!_stream.sar().is_known()) { _stream.sar(out_sar); } else if (_stream.sar() != out_sar) { mjpeg_warn("Target SAR mismatch... image will look squished!"); } } /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /* known: ilace, framesize maybe: sar, x_ratio, y_ratio, active region */ /* elements: x ratio, y ratio, sar, active region, src active region */ /* ---> active regions are malleable, * ratios/sar will not be changed once established */ /* priority list for setting scale: o x & y ratios - must be consistent with active region o x or y ratio, and sar - calculate other ratio - must be consistent with active region o sar and active region - */ void ysTarget::check_parameters(ysSource &source) { require_interlace(source); require_chromass(source); require_framesize(source); require_active_region(); /* decide Xscale, Yscale, and SAR, if it hasn't happened already */ if (_x_ratio.is_known() && _y_ratio.is_known()) { reconcile_sar_with_ratios(source); } else if (_stream.sar().is_known()) { if (_x_ratio.is_known()) { calculate_y_ratio_from_x_ratio_and_sars(source); } else if (_y_ratio.is_known()) { calculate_x_ratio_from_y_ratio_and_sars(source); } else { calculate_ratios_from_active_regions_and_sar(source); } } else { calculate_ratios_from_active_regions(source); reconcile_sar_with_ratios(source); } reconcile_active_regions_with_ratios(source); } void ysTarget::describe_parameters() const { mjpeg_info("=== TARGET parameters: ================="); mjpeg_info("> stream:"); mjpeg_info("> %dx%d, SAR %d:%d, %s", _stream.x_size(), _stream.y_size(), _stream.sar().ratio().n, _stream.sar().ratio().d, ilace_to_string(_stream.interlace())); mjpeg_info("< chroma subsampling: %s", _stream.subsampling().mode_to_string()); mjpeg_info("< chroma ss ratios: x %d:%d y %d:%d", _stream.subsampling().ratio().x().numerator(), _stream.subsampling().ratio().x().denominator(), _stream.subsampling().ratio().y().numerator(), _stream.subsampling().ratio().y().denominator()); mjpeg_info("> active region:"); mjpeg_info("> %dx%d at %d,%d (bg Y'CbCr: %d,%d,%d)", _active_region.dim().x(), _active_region.dim().y(), _active_region.offset().x(), _active_region.offset().y(), _bgcolor(0), _bgcolor(1), _bgcolor(2)); mjpeg_info("> X ratio: %d/%d", _x_ratio.ratio().n, _x_ratio.ratio().d); mjpeg_info("> Y ratio: %d/%d", _y_ratio.ratio().n, _y_ratio.ratio().d); } #if 0 static int internal_write_444_frame(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const yuv[3]) { int err; int w = y4m_si_get_width(si); int h = y4m_si_get_height(si); /* Write frame header */ if ((err = y4m_write_frame_header(fd, si, fi)) != Y4M_OK) return err; /* Write luminance scanlines */ if (y4m_write(fd, yuv[0], w*h)) return Y4M_ERR_SYSTEM; /* Write chrominance scanlines */ if (y4m_write(fd, yuv[1], w*h)) return Y4M_ERR_SYSTEM; if (y4m_write(fd, yuv[2], w*h)) return Y4M_ERR_SYSTEM; return Y4M_OK; } static int internal_write_422_frame(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const yuv[3]) { int err; int w = y4m_si_get_width(si); int h = y4m_si_get_height(si); /* Write frame header */ if ((err = y4m_write_frame_header(fd, si, fi)) != Y4M_OK) return err; /* Write luminance scanlines */ if (y4m_write(fd, yuv[0], w*h)) return Y4M_ERR_SYSTEM; /* Write chrominance scanlines */ if (y4m_write(fd, yuv[1], w*h/2)) return Y4M_ERR_SYSTEM; if (y4m_write(fd, yuv[2], w*h/2)) return Y4M_ERR_SYSTEM; return Y4M_OK; } static int internal_write_411_fields(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const upper_field[3], uint8_t * const lower_field[3]) { int i, y, err; int width = y4m_si_get_width(si); int height = y4m_si_get_height(si); /* Write frame header */ if ((err = y4m_write_frame_header(fd, si, fi)) != Y4M_OK) return err; /* Write Y', Cb, and Cr planes */ for (i = 0; i < 3; i++) { uint8_t *srctop = upper_field[i]; uint8_t *srcbot = lower_field[i]; /* alternately write one line from each */ for (y = 0; y < height; y += 2) { if (y4m_write(fd, srctop, width)) return Y4M_ERR_SYSTEM; srctop += width; if (y4m_write(fd, srcbot, width)) return Y4M_ERR_SYSTEM; srcbot += width; } /* for chroma, width/height are half as big */ if (i == 0) { width /= 4; // height /= 2; } } return Y4M_OK; } static int internal_write_422_fields(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const upper_field[3], uint8_t * const lower_field[3]) { int i, y, err; int width = y4m_si_get_width(si); int height = y4m_si_get_height(si); /* Write frame header */ if ((err = y4m_write_frame_header(fd, si, fi)) != Y4M_OK) return err; /* Write Y', Cb, and Cr planes */ for (i = 0; i < 3; i++) { uint8_t *srctop = upper_field[i]; uint8_t *srcbot = lower_field[i]; /* alternately write one line from each */ for (y = 0; y < height; y += 2) { if (y4m_write(fd, srctop, width)) return Y4M_ERR_SYSTEM; srctop += width; if (y4m_write(fd, srcbot, width)) return Y4M_ERR_SYSTEM; srcbot += width; } /* for chroma, width/height are half as big */ if (i == 0) { width /= 2; // height /= 2; } } return Y4M_OK; } static int internal_write_444_fields(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const upper_field[3], uint8_t * const lower_field[3]) { int i, y, err; int width = y4m_si_get_width(si); int height = y4m_si_get_height(si); /* Write frame header */ if ((err = y4m_write_frame_header(fd, si, fi)) != Y4M_OK) return err; /* Write Y', Cb, and Cr planes */ for (i = 0; i < 3; i++) { uint8_t *srctop = upper_field[i]; uint8_t *srcbot = lower_field[i]; /* alternately write one line from each */ for (y = 0; y < height; y += 2) { if (y4m_write(fd, srctop, width)) return Y4M_ERR_SYSTEM; srctop += width; if (y4m_write(fd, srcbot, width)) return Y4M_ERR_SYSTEM; srcbot += width; } } return Y4M_OK; } #endif #if 0 int ysTarget::write_frame(int fdin, y4m_frame_info_t *frameinfo, uint8_t **frame) { switch (_stream.subsampling().mode()) { case ysSubsampling::SS_444: return internal_write_444_frame(fdin, _stream.streaminfo(), frameinfo, frame); case ysSubsampling::SS_422: return internal_write_422_frame(fdin, _stream.streaminfo(), frameinfo, frame); case ysSubsampling::SS_411: case ysSubsampling::SS_420_JPEG: case ysSubsampling::SS_420_MPEG2: case ysSubsampling::SS_420_PALDV: default: return y4m_write_frame(fdin, _stream.streaminfo(), frameinfo, frame); } } int ysTarget::write_fields(int fdin, y4m_frame_info_t *frameinfo, uint8_t **topfield, uint8_t **bottomfield) { switch (_stream.subsampling().mode()) { case ysSubsampling::SS_411: return internal_write_411_fields(fdin, _stream.streaminfo(), frameinfo, topfield, bottomfield); case ysSubsampling::SS_444: return internal_write_444_fields(fdin, _stream.streaminfo(), frameinfo, topfield, bottomfield); case ysSubsampling::SS_422: return internal_write_422_fields(fdin, _stream.streaminfo(), frameinfo, topfield, bottomfield); case ysSubsampling::SS_420_JPEG: case ysSubsampling::SS_420_MPEG2: case ysSubsampling::SS_420_PALDV: default: return y4m_write_fields(fdin, _stream.streaminfo(), frameinfo, topfield, bottomfield); } } #endif int ysTarget::write_frame(int fdout, y4m_frame_info_t *frameinfo, uint8_t **frame) { return y4m_write_frame(fdout, _stream.streaminfo(), frameinfo, frame); } int ysTarget::write_fields(int fdout, y4m_frame_info_t *frameinfo, uint8_t **topfield, uint8_t **bottomfield) { return y4m_write_fields(fdout, _stream.streaminfo(), frameinfo, topfield, bottomfield); } mjpegtools-2.1.0/y4mscaler/y4m-config.h0000644000175000017500000000266712051575455020265 0ustar glowwormglowworm/* Copyright 2003 Matthew Marjanovic This file is part of y4mscaler. y4mscaler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. y4mscaler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with y4mscaler; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* do we have some cool thing for 64bits integers? */ #define PRID64_STRING_FORMAT "lld" /* Define if you have the header file. */ #define HAVE_ALLOCA_H 1 /* Define if you have the header file. */ #define HAVE_FENV_H 1 /* Define if you have the header file. */ #define HAVE_GETOPT_H 1 /* Define if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define if you have the header file. */ #define HAVE_STDBOOL_H 1 /* Define if you have the header file. */ #define HAVE_STDINT_H 1 /* Define if you have the header file. */ #define HAVE_SYS_TYPES_H 1 mjpegtools-2.1.0/y4mscaler/TODO0000644000175000017500000001307212051575455016620 0ustar glowwormglowworm x Xtag for chroma subsampling mode x document Xtag in manpage x Error message for "cannot make progressive from interleaved" should suggest using 'ilace=XXX_only' modes. x 7-9 tap Lanczos-windowed sinc kernel x independent kernels for X and Y scaling - Instead of simple matte-padding of off-frame pixels (for large kernels), do proper tiling --- tile the matte+frame, as bounded by the projection of the target back to the source. (i.e. Source size is the tile size, even though some of the tile may be filled with matte.) [hmm... on second/third thought, this is probably unnecessary and a poorer way to do it anyway.] x Fix subsampling for NTSC DV ---- horizontal shift in chroma. [...unless Poynton's book is *wrong*.] [Yes, Poynton's was wrong. See his errata.] - Fix the rounding errors in scaler-matto fixed-point calculations: x 1) Negative doubles should get "- 0.5" to round properly when being converted to fixed-point. x 2) When unfixing, stuff with ">>(2*FSHIFT)" should have had an offset of "(1<<(2*FSHIFT-1))" pre-applied, *not* "2*(1<<(FSHIFT-1))" (i.e. *not* just "2*FHALF"). - 3) Shouldn't negative fixed-point quantities, like <128 chroma samples, get rounded inward (upward), not downward? (When UNFIXing after the convolution) [not right now --- would make UNFIX op much slower?] (See if these fixes have any affect on the chirp tests....) x Warn about chroma-mangling when casting interlaced input to progressive, when chroma is vertically subsampled. (But TOP_ONLY or BOTTOM_ONLY is ok.) x Warn about chroma-mangling when casting progressive input to interlaced, when chroma is vertically subsampled. x Warn/Inform when fake progressive mode being used. x Both read and write streams in extra chroma ss modes. x Add more presets: DVD_WIDE, DV, DV_WIDE x let active region geometry strings use framesize as a default region size, so that one can specify "active=+4+0" to just do shifting. x recognize other XXX:1001 framerates as NTSC norm (and similar for PAL). x add CVD preset x (add note to aspect webpage about pedantic square pixel issues.) x display more/better info about scaler engine configuration to user. ---------------- v 0.6.1 ------------------- x Update to work with YUV4MPEG2(v1). ---------------- v 0.7.0 ------------------- x Make it clear that cl options are evaluated in order, and that some need to be evaluated before others (-I before -O...). x (Maybe it would be better to evaluate all -I before all -O ??) [Yes, eval -I arguments before -O arguments.] x Create a JIT-assembled scaling engine using GNU Lightning. [Tried it --- instruction stream was too long and blows out instruction cache for larger framesizes.] x Improve description/explanation of "-I ilace=TOP/BOTTOM_ONLY" in manpage. ---------------- v 0.7.1 ------------------- x Document the CVD preset in manpage. x Describe the preset settings in detail (what options do they set?) in the manpage. x Change version numbering from a.b.c to b.c. x change default scaler options to high-quality sinc. --> sinc:6 x Finish *proper* update to work with YUV4MPEG2(v2). ---------------- v 8.0 ------------------- x Nicholas Boos wants a gaussian kernel and "fourth-order cubic" (?) --> well, he gets the 4th-order cubic so far. x 'cubicK4' is the *new* default kernel, and really make it so. ---------------- v 8.1 ------------------- x Use 64-bit intermediate values in ratio operations (to avoid overflow). x Use floats in ratio simplification (to avoid overflow). x Remove eXecute bit from manpage (reported by Don Mullis). x Add presets for ATSC 720p, 1080i, 1080p. ---------------- v 9.0 ------------------- o non-fake ilace options should undo preceding fake ilace options. o fix bug: box kernel coefficients are not correctly normalized. o fix bug: coefficients with two maximum should share any norm correction o add 'blur' option to scaling engine. o Nicholas Boos wants a gaussian kernel and "fourth-order cubic" (?) o check the behavior of kernel support calculation in scaler-matto.C ...currently, 'supp' refers to 1/2 of support (one side or other); perhaps calcs should deal with 2.0*supp instead, to alleviate rounding down too much??? o add presets for (S)VCD stills which accounts for overscan... (perhaps do same for DVD/etc... "full-frame" mode?) -O preset=VCD_STILL,hi,ovscan:10% -O preset=SVCD_STILL,lo o add "-O dar=XXX:YYY" option; calculate SAR from framesize + DAR. o take out the CPU_OPT flag in Makefile, or at least condition it on the actual processor/compile environment. (powerpc -> uname -m = "ppc") o figure out what "3rd order", etc, really means and straighten out comments. o Make the norm-from-framerate calculation/heuristic more lenient. (Try guess_mpeg_framerate, and see if any of those match.) o Double-check the interlacing/chroma-subsampling constraints (has this been done already?). Vertical subsampling must be either frame-based or field-based. o Add a "-X" expert flag; turn certain conditions (chroma-mangling) into fatal errors. o Make the "Target frame size defaulting to scaled source size" more lenient --- i.e. if scaled source size is non-integral, round it. o Don't create (alpha) scalers if they will never be used. o Warn (in messages and manpage) about loss of 1-field duration when swapping-interlacing. o Should bg chroma be used in output when input is MONO or -S mode=mono?? (Currently, it is in first case, but is not in second case!) ...and should it be the src BG chroma, or the tgt BG chroma? mjpegtools-2.1.0/y4mscaler/ysTarget.H0000644000175000017500000000727212051575455020050 0ustar glowwormglowworm/* Copyright 2003 Matthew Marjanovic This file is part of y4mscaler. y4mscaler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. y4mscaler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with y4mscaler; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _YS_TARGET_H_ #define _YS_TARGET_H_ #include #include "graphics.H" #include "ysStreamInfo.H" #include "ysSource.H" class ysTarget { public: enum ReconcileMode_t { RCMD_PAD, RCMD_CLIP, RCMD_PRESERVE_X, RCMD_PRESERVE_Y }; enum ReconcileMode2_t { RCMD2_SIMPLIFY, RCMD2_EXACT }; enum PrefabType_t { PREFAB_VCD, PREFAB_CVD, PREFAB_SVCD, PREFAB_DVD, PREFAB_DVD_WIDE, PREFAB_DV, PREFAB_DV_WIDE, PREFAB_SVCD_STILL_HI, PREFAB_SVCD_STILL_LO, PREFAB_VCD_STILL_HI, PREFAB_VCD_STILL_LO, PREFAB_ATSC_720P, PREFAB_ATSC_1080I, PREFAB_ATSC_1080P }; private: ysStreamInfo _stream; ysRegion _active_region; ysRatio _x_ratio; ysRatio _y_ratio; ReconcileMode_t _reconcile_mode; ReconcileMode2_t _reconcile_mode2; ysYCbCr _bgcolor; AnchorMode_t _anchor_mode; void set_prefab_target(PrefabType_t target, const ysSource &source); void require_interlace(const ysSource &source); void require_chromass(const ysSource &source); void require_sar(const ysSource &source); void require_framesize(const ysSource &source); void require_active_region(void); void reconcile_sar_with_ratios(const ysSource &source); void reconcile_active_regions_with_ratios(ysSource &source); void calculate_y_ratio_from_x_ratio_and_sars(const ysSource &source); void calculate_x_ratio_from_y_ratio_and_sars(const ysSource &source); void calculate_ratios_from_active_regions_and_sar(const ysSource &source); void calculate_ratios_from_active_regions(const ysSource &source); ysRatioRegion check_active_alignment(ysRatioRegion &r); #ifdef _YS_DEV_BRANCH_ static ysYCbCr default_bgcolor(void) { return ysYCbCr(128,240,108); } #else static ysYCbCr default_bgcolor(void) { return ysYCbCr(16,128,128); } #endif public: ysTarget() : _reconcile_mode(RCMD_PAD), _reconcile_mode2(RCMD2_SIMPLIFY), _bgcolor(default_bgcolor()), _anchor_mode(ANC_CC) {} ysYCbCr bgcolor() const { return _bgcolor; } ysRatio x_ratio() const { return _x_ratio; } ysRatio y_ratio() const { return _y_ratio; } void bgcolor(const ysYCbCr &x) { _bgcolor = x; } void x_ratio(const ysRatio &r) { _x_ratio = r; } void y_ratio(const ysRatio &r) { _y_ratio = r; } ysStreamInfo &stream() { return _stream; } ysRegion &active_region() { return _active_region; } const ysStreamInfo &stream() const { return _stream; } ysRegion active_region() const { return _active_region; } int write_frame(int fdin, y4m_frame_info_t *frameinfo, uint8_t **frame); int write_fields(int fdin, y4m_frame_info_t *frameinfo, uint8_t **topfield, uint8_t **bottomfield); void describe_keywords(FILE *fp, const char *prefix) const; void init_stream(const ysSource &source); void parse_keyword(ysSource &source, char *optarg); void check_parameters(ysSource &source); void describe_parameters() const; }; #endif /* _YS_TARGET_H_ */ mjpegtools-2.1.0/y4mscaler/ysStreamInfo.C0000644000175000017500000001113012051575455020650 0ustar glowwormglowworm/* Copyright 2003 Matthew Marjanovic This file is part of y4mscaler. y4mscaler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. y4mscaler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with y4mscaler; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "y4m-config.h" #include "debug.h" #include #include "ysStreamInfo.H" int ysStreamInfo::parse_dimensions(const char *s) { int sx, sy; if (sscanf(s, "%ux%u", &sx, &sy) == 2) { x_size(sx); y_size(sy); return 0; } return 1; } int ysStreamInfo::parse_subsampling(const char *s) { if (_subsampling.parse_mode(s)) return 1; y4m_si_set_chroma(&_streaminfo, _subsampling.mode()); return 0; } int ysStreamInfo::x_alignment() const { return _subsampling.ratio().x().denominator(); } int ysStreamInfo::y_alignment() const { if (interlace() != Y4M_ILACE_NONE) /* worst-case: some kind of interlacing may be involved. */ return _subsampling.ratio().y().denominator() * 2; else return _subsampling.ratio().y().denominator(); } const char *ilace_to_string(int i) { switch (i) { case Y4M_UNKNOWN: return "unknown"; break; case Y4M_ILACE_NONE: return "progressive"; break; case Y4M_ILACE_TOP_FIRST: return "top-field-first"; break; case Y4M_ILACE_BOTTOM_FIRST: return "bottom-field-first"; break; case Y4M_ILACE_MIXED: return "mixed-interlacing"; break; default: return "?????"; break; } } int ysStreamInfo::read_stream_header(int fdin) { int retval = y4m_read_stream_header(fdin, &_streaminfo); if (retval == Y4M_OK) { int chroma = y4m_si_get_chroma(&_streaminfo); switch (chroma) { case Y4M_CHROMA_420JPEG: _subsampling.mode(ysSubsampling::SS_420_JPEG); break; case Y4M_CHROMA_420MPEG2: _subsampling.mode(ysSubsampling::SS_420_MPEG2); break; case Y4M_CHROMA_420PALDV: _subsampling.mode(ysSubsampling::SS_420_PALDV); break; case Y4M_CHROMA_411: _subsampling.mode(ysSubsampling::SS_411); break; case Y4M_CHROMA_422: _subsampling.mode(ysSubsampling::SS_422); break; case Y4M_CHROMA_444: _subsampling.mode(ysSubsampling::SS_444); break; case Y4M_CHROMA_444ALPHA: _subsampling.mode(ysSubsampling::SS_444ALPHA); break; // mjpeg_error("4:4:4/alpha streams not yet supported."); // retval = Y4M_ERR_FEATURE; // break; case Y4M_CHROMA_MONO: _subsampling.mode(ysSubsampling::SS_MONO); break; // mjpeg_error("Mono/Luma-only streams not yet supported."); // retval = Y4M_ERR_FEATURE; // break; default: mjpeg_error("Unknown (and unsupported) chroma format."); retval = Y4M_ERR_HEADER; break; } } return retval; } int ysStreamInfo::write_stream_header(int fdout) { #if 0 /* NB: this is now taken care of by yuv4mpeg lib. */ y4m_xtag_list_t *xtags = y4m_si_xtags(&_streaminfo); /* remove any old chromass tags */ for (int n = 0; n < y4m_xtag_count(xtags); n++) { const char *tag = y4m_xtag_get(xtags, n); if (!strncmp("XYSCSS=", tag, 7)) y4m_xtag_remove(xtags, n); } #endif #if 0 /* set correct chroma mode --- this should be done by a subsampling setter method everytime subsampling is modified... */ switch (_subsampling.mode()) { case ysSubsampling::SS_444: y4m_si_set_chroma(&_streaminfo, Y4M_CHROMA_444); break; case ysSubsampling::SS_422: y4m_si_set_chroma(&_streaminfo, Y4M_CHROMA_422); break; case ysSubsampling::SS_420_MPEG2: y4m_si_set_chroma(&_streaminfo, Y4M_CHROMA_420MPEG2); break; case ysSubsampling::SS_420_PALDV: y4m_si_set_chroma(&_streaminfo, Y4M_CHROMA_420PALDV); break; case ysSubsampling::SS_411: y4m_si_set_chroma(&_streaminfo, Y4M_CHROMA_411); break; case ysSubsampling::SS_420_JPEG: y4m_si_set_chroma(&_streaminfo, Y4M_CHROMA_420JPEG); break; default: mjpeg_error("OOOPS. Encountered unknown chroma ss mode. %d", _subsampling.mode()); exit(1); } #endif /* write that header! */ return y4m_write_stream_header(fdout, &_streaminfo); } mjpegtools-2.1.0/y4mscaler/ysSource.H0000644000175000017500000001036512051575455020057 0ustar glowwormglowworm/* Copyright 2003 Matthew Marjanovic This file is part of y4mscaler. y4mscaler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. y4mscaler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with y4mscaler; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _YS_SOURCE_H_ #define _YS_SOURCE_H_ #include #include "graphics.H" #include "ysStreamInfo.H" class ysSource { public: enum Norm_t { NORM_UNKNOWN = -1, NORM_NTSC, NORM_PAL }; enum FakeProg_t { FAKE_NO_FAKE = 0, FAKE_TOP_ONLY, FAKE_BOT_ONLY }; private: ysStreamInfo _stream; ysStreamInfo _real_stream; ysRatioRegion _active_region; ysRegion _matte_region; ysYCbCr _bgcolor; Norm_t _norm; FakeProg_t _fake_progressive; uint8_t *_fake_field[3]; void norm(Norm_t n) { _norm = n; } void interlace(int ilace) { if ((_stream.interlace() != Y4M_UNKNOWN) && (_stream.interlace() != ilace)) { #if 0 mjpeg_warn("Casting source interlace from %s to %s.", ilace_to_string(_stream.interlace()), ilace_to_string(ilace)); #else mjpeg_warn("Casting source interlacing to %s.", ilace_to_string(ilace)); #endif if (((_stream.interlace() == Y4M_ILACE_NONE) || (ilace == Y4M_ILACE_NONE)) && (_stream.subsampling().ratio().y() != ysRatio(1,1))) { mjpeg_warn("...chroma planes will get commangled!"); } } _stream.interlace(ilace); } void sar(const ysRatio &r) { if (_stream.sar().is_known()) mjpeg_warn("Casting source SAR from %d:%d to %d:%d", _stream.sar().ratio().n, _stream.sar().ratio().d, r.ratio().n, r.ratio().d); _stream.sar(r); } void fake_progressive(FakeProg_t f); static ysYCbCr default_bgcolor(void) { return ysYCbCr(16,128,128); } ysSource &operator=(const ysSource &other); ysSource(const ysSource &other); public: ysSource() : _bgcolor(default_bgcolor()), _norm(NORM_UNKNOWN), _fake_progressive(FAKE_NO_FAKE) { _fake_field[0] = NULL; } ~ysSource() { if (_fake_field[0] != NULL) delete[] _fake_field[0]; } /* const accessors */ ysYCbCr bgcolor() const { return _bgcolor; } const ysRatioRegion &active_region() const { return _active_region; } const ysRegion &matte_region() const { return _matte_region; } const ysStreamInfo &stream() const { return _stream; } /* non-const accessors */ ysRatioRegion &active_region() { return _active_region; } ysRegion &matte_region() { return _matte_region; } /* setters */ void bgcolor(const ysYCbCr &x) { _bgcolor = x; } Norm_t norm() const { if (_norm == NORM_UNKNOWN) { if ((_stream.framerate() == y4m_fps_NTSC) || (_stream.framerate() == y4m_fps_NTSC_FIELD) || (_stream.framerate() == y4m_fps_NTSC_FILM)) return NORM_NTSC; else if ((_stream.framerate() == y4m_fps_PAL) || (_stream.framerate() == y4m_fps_PAL_FIELD)) return NORM_PAL; else return NORM_UNKNOWN; } else return _norm; } int read_stream_header(int fdin); int read_frame_header(int fdin, y4m_frame_info_t *frameinfo); int read_frame(int fdin, y4m_frame_info_t *frameinfo, uint8_t **frame); int read_fields(int fdin, y4m_frame_info_t *frameinfo, uint8_t **topfield, uint8_t **bottomfield); //int read_frame_or_fields(int fdin, y4m_frame_info_t *frameinfo, // uint8_t **frame, uint8_t **upper, uint8_t **lower); int read_frame_data(int fdin, y4m_frame_info_t *frameinfo, uint8_t **frame); int read_fields_data(int fdin, y4m_frame_info_t *frameinfo, uint8_t **upper, uint8_t **lower); void describe_keywords(FILE *fp, const char *prefix) const; void parse_keyword(char *optarg); void check_parameters(); void describe_parameters() const; }; #endif /* _YS_SOURCE_H_ */ mjpegtools-2.1.0/y4mscaler/scaler-matto.C0000644000175000017500000005774212051575455020643 0ustar glowwormglowworm/* Copyright 2003 Matthew Marjanovic This file is part of y4mscaler. y4mscaler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. y4mscaler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with y4mscaler; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "y4m-config.h" #include "debug.h" #include #include #include #include "scaler-matto.H" #define FSHIFT 10 //#define FSHIFT 20 #define FUNIT (1< (max_pixel) ) (dst) = (max_pixel); \ else (dst) = (src); \ } #define MIN_PIXEL 1 #define MAX_PIXEL 254 //=========================================================================== //=========================================================================== //==== scaler factory: parses options and generates an instance of ==== //==== the engine ==== //=========================================================================== //=========================================================================== const char *mattoScalerFactory::description() const { return "Matto's Generic Scaler"; } void mattoScalerFactory::describe_options(FILE *fp, const char *prefix) const { fprintf(fp, "%sOptions specify scaling kernels/modes:\n", prefix); fprintf(fp, "%s KKK - use 'KKK' kernel for x and/or y scaling\n", prefix); fprintf(fp, "%s XXX,YYY - use 'XXX' for x scaling, 'YYY' for y scaling\n", prefix); fprintf(fp, "%sSome kernels take a numeric parameter: 'KKK:N'\n", prefix); fprintf(fp, "%sKernel list:\n", prefix); int maxlen = 0; for (int i = 0; i < ysKernelFactory::instance()->count(); i++) { int x = strlen(ysKernelFactory::instance()->lookup(i)->name()) + strlen(ysKernelFactory::instance()->lookup(i)->pdesc()); if (x > maxlen) maxlen = x; } for (int i = 0; i < ysKernelFactory::instance()->count(); i++) { const char *name = ysKernelFactory::instance()->lookup(i)->name(); const char *pdesc = ysKernelFactory::instance()->lookup(i)->pdesc(); fprintf(fp, "%s %s%s%*s - %s\n", prefix, name, pdesc, maxlen - (int)strlen(name) - (int)strlen(pdesc), "", ysKernelFactory::instance()->lookup(i)->desc()); int x = strlen(ysKernelFactory::instance()->lookup(i)->name()); if (x > maxlen) maxlen = x; } fprintf(fp, "%sThe default kernel is '%s'.\n", prefix, DEFAULT_KERNEL); } void mattoScalerFactory::describe_parameters(logging_function *logger, const char *prefix) const { char sout[256]; char *s = sout; int rem = sizeof(sout); int len; #define CHECK_LENGTH rem -= len; s += len; if (rem <= 0) goto done; len = snprintf(s, rem, "%skernels: ", prefix); CHECK_LENGTH; if (_the_x_kernel == NULL) { len = snprintf(s, rem, "???"); CHECK_LENGTH; } else { len = snprintf(s, rem, "%s", _the_x_kernel->name()); CHECK_LENGTH; for (int i = 0; i < _the_x_kernel->pcount(); i++) { len = snprintf(s, rem, ":%1g", _the_x_kernel->param(i)); CHECK_LENGTH; } } if (_the_y_kernel == NULL) { len = snprintf(s, rem, ", ???"); CHECK_LENGTH; } else { len = snprintf(s, rem, ", %s", _the_y_kernel->name()); CHECK_LENGTH; for (int i = 0; i < _the_y_kernel->pcount(); i++) { len = snprintf(s, rem, ":%1g", _the_y_kernel->param(i)); CHECK_LENGTH; } } done: (*logger)("%s", sout); } int mattoScalerFactory::parse_option(const char *option) { /* look for comma; split string */ char *xname = strdup(option); char *yname = strchr(xname, ','); if (yname != NULL) { *yname = '\0'; yname++; } else { yname = xname; } /* create our own prototypes, with provided parameters, etc. */ ysKernel *new_x_kernel = ysKernelFactory::instance()->create_kernel(xname); ysKernel *new_y_kernel = ysKernelFactory::instance()->create_kernel(yname); free(xname); if ((new_x_kernel == NULL) || (new_y_kernel == NULL)) { delete new_x_kernel; delete new_y_kernel; return 1; } /* clean out previous kernels (if any) */ delete _the_x_kernel; delete _the_y_kernel; _the_x_kernel = new_x_kernel; _the_y_kernel = new_y_kernel; return 0; } ysScaler *mattoScalerFactory::new_scaler() const { /* assume _the_*_kernel's have valid, non-NULL values... */ /* (i.e. defaults assigned to/by factory earlier) */ return new mattoScaler(_the_x_kernel->clone(), _the_y_kernel->clone()); } //========================================================================= //========================================================================= //==== scaler - the actual engine that does scaling on an image plane ==== //========================================================================= //========================================================================= int mattoScaler::setup(const ysPoint &source_size, const ysRatioPoint &source_offset, const ysRegion &source_matte, const ysPoint &dest_size, const ysRegion &dest_region, const ysRatio &x_scale, const ysRatio &y_scale, uint8_t matte_pixel) { SframeX = source_size.x(); SframeY = source_size.y(); DframeX = dest_size.x(); DframeY = dest_size.y(); DBG("S (%d, %d) D (%d, %d)\n", SframeX, SframeY, DframeX, DframeY); DBG("scale: (%f, %f)\n", x_scale.to_double(), y_scale.to_double()); Dx = dest_region.dim().x(); Dy = dest_region.dim().y(); xq0 = dest_region.offset().x(); yq0 = dest_region.offset().y(); Sxmin = source_matte.offset().x(); Symin = source_matte.offset().y(); Sxmax = Sxmin + source_matte.dim().x() - 1; Symax = Symin + source_matte.dim().y() - 1; if (Sxmin < 0) Sxmin = 0; if (Sxmax >= SframeX) Sxmax = SframeX - 1; if (Symin < 0) Symin = 0; if (Symax >= SframeY) Symax = SframeY - 1; // DBG("Sx (%d %d) Sy (%d %d)\n", Sxmin, Sxmax, Symin, Symax); xp0 = source_offset.x(); yp0 = source_offset.y(); sigmaX = x_scale; sigmaY = y_scale; zero_pixel = matte_pixel; return internal_setup(); } int mattoScaler::scale(uint8_t *source, uint8_t *dest) { (this->*(scaling_function))(source, dest); return 0; } //========================================================================= //========================================================================= //========================================================================= int mattoScaler::internal_setup() { /* Pick order of x and y scaling to minimize computation: Dx / sigmaX = sourceX Dy / sigmaY = sourceY x_then_y: SX*SY -> DX*SY -> DX*DY y_then_x: SX*SY -> SX*DY -> DX*DY DX*SY = DX * DY / sigY = DX*DY / sigY SX*DY = DX / sigX * DY = DX*DY / sigX SX*DY < DX*SY --> y_then_x else x_then_y ==> sigX > sigY --> y_then_x else x_then_y */ if ((sigmaX == 1) && (xp0.is_integral())) { if ((sigmaY == 1) && (yp0.is_integral())) { DBG("SCALER MODE: copy\n"); setup_copy(); } else { DBG("SCALER MODE: y only\n"); // setup_x_then_y(); setup_y_only(); } } else if ((sigmaY == 1) && (yp0.is_integral())) { DBG("SCALER MODE: x only\n"); //setup_x_then_y(); setup_x_only(); } else if (sigmaX > sigmaY) { DBG("SCALER MODE: y then x\n"); setup_y_then_x(); } else { DBG("SCALER MODE: x then y\n"); setup_x_then_y(); //setup_y_then_x(); } #if 0 DBG("setup scaler:\n"); DBG("src frame: %dx%d dst frame: %dx%d\n", SframeX, SframeY, DframeX, DframeY); DBG("map xdxxd (+%f+%f) to %dx%d (+%d+%d)\n", /*Sx,Sy,*/xp0.to_double(),yp0.to_double(), Dx,Dy,xq0,yq0); DBG("x-ratio: %d/%d y-ratio: %d/%d\n", sigmaX.ratio().n, sigmaX.ratio().d, sigmaY.ratio().n, sigmaY.ratio().d); #endif return 0; } class mattoScaler::kernelSet { public: int *K; int width; int spot0; int offset; kernelSet() : K(NULL) {} ~kernelSet() { delete[](K); } protected: kernelSet(const kernelSet &k); kernelSet &operator=(const kernelSet &v); }; /* translate a discrete (pixel) destination coordinate back into the corresponding continuous source coordinate q - dest coord (pixel) scale - src->dst scale factor p0 - source offset (pixel) */ static double push_back(int q, double scale, double p0) { return ((double)(q) + 0.5) / scale - 0.5 + p0; } void mattoScaler::setup_kernel_cache(double scale, double p0, const ysKernel *kernel, int Dsize, int Smin, int Smax, int Spitch, int zero_pixel, int offset_premult, int offset_offset, kernelSet *&KS, int &minspot, int &maxspot) { DBG("setup kernel cache\n"); DBG(" scale %f p0 %f\n", scale, p0); KS = new mattoScaler::kernelSet[Dsize]; minspot = Smax + 1; maxspot = Smin - 1; double kscale = scale; if (kscale > 1.0) kscale = 1.0; int supp = (int)ceil(kernel->support() / kscale); DBG(" support: %d\n", supp); for (int q = 0; q < Dsize; q++) { double Pq = push_back(q, scale, p0); int spot0 = (int)floor(Pq) - supp; int spot1 = (int)floor(Pq) + supp + 1; KS[q].K = new int[spot1 - spot0 + 1]; KS[q].offset = 0; KS[q].width = 0; int valsum = 0; int valmax = 0; int maxpos = -1; int m, s; for (m = 0, s = spot0; s <= spot1; s++) { #if 0 int value = (int)( (kernel->k((Pq - s) * kscale) * kscale * (double)FUNIT) + 0.5 ); #else double fvalue = kernel->k((Pq - s) * kscale) * kscale * (double)FUNIT; int value = (fvalue >= 0.0) ? (int)(fvalue + 0.5) : (int)(fvalue - 0.5); #endif #ifdef _YS_DEBUG if (q == 10) { fprintf(stderr, " %2d: %3d %4d %f\n", m, s, value, fvalue / (double)FUNIT); } #endif if ((m == 0) && (value == 0)) { /* remove zero entries from head of list */ spot0++; } else if ((s < Smin) || (s > Smax)) { /* remove out-of-region entries from head and tail of list, and add to offset instead */ KS[q].offset += value; // * zero_pixel; if (m == 0) spot0++; if (value > valmax) { valmax = value; maxpos = -1; } } else { if (value > valmax) { valmax = value; maxpos = m; } KS[q].K[m++] = value; KS[q].width++; } valsum += value; } /* remove zero entries from tail of list */ while (--m >= 0) { if (KS[q].K[m] != 0) break; KS[q].width--; } if (valsum != FUNIT) { DBG("valsum over: %d at %d\n", valsum, q); if (maxpos == -1) KS[q].offset -= (valsum - FUNIT); else KS[q].K[maxpos] -= (valsum - FUNIT); // Q: what about symmetric, even (two peak) lists? } #if 0 if (KS[q].width == 0) { DBG("zero width: [%d] off %d %f\n", q, KS[q].offset, (double)(KS[q].offset)/(double)FUNIT); } #endif KS[q].offset *= zero_pixel; KS[q].offset *= offset_premult; KS[q].offset += offset_offset; KS[q].spot0 = spot0 * Spitch; if (KS[q].width > 0) { /* i.e. if spot0 and spot1 actually mean anything */ if (spot0 < minspot) minspot = spot0; int real_spot1 = spot0 + KS[q].width - 1; if (real_spot1 > maxspot) maxspot = real_spot1; } } // DBG("minspot: %d maxspot: %d\n", minspot, maxspot); } mattoScaler::~mattoScaler() { delete _the_x_kernel; delete _the_y_kernel; delete[](_KX); delete[](_KY); delete[](tempo); } //========================================================================= //========================================================================= //========================================================================= void mattoScaler::setup_x_then_y() { setup_kernel_cache(sigmaX.to_double(), xp0.to_double(), _the_x_kernel, Dx, Sxmin, Sxmax, 1, zero_pixel, 1, 0, _KX, _Xminspot, _Xmaxspot); setup_kernel_cache(sigmaY.to_double(), yp0.to_double(), _the_y_kernel, Dy, Symin, Symax, 1, zero_pixel, FUNIT, (1<<(2*FSHIFT - 1)), //(not) 2*FHALF, _KY, _Yminspot, _Ymaxspot); for (int q = 0; q < Dy; q++) { _KY[q].spot0 -= _Yminspot; _KY[q].spot0 *= Dx; /*TframeX;*/ } // DBG("Y spot limits: %d -- %d\n", _Yminspot, _Ymaxspot); if ((_Xminspot > _Xmaxspot) || (_Yminspot > _Ymaxspot)) { scaling_function = &mattoScaler::scale_fill; } else { TframeX = Dx; TframeY = _Ymaxspot - _Yminspot + 1; tempo = new int[TframeX * TframeY]; scaling_function = &mattoScaler::scale_x_then_y; } // DBG("caches set up\n"); } void mattoScaler::scale_x_then_y(uint8_t *src, uint8_t *dst) { /* scale x direction, src into tempo */ int *Tptr = tempo; uint8_t *srcline = src + (_Yminspot * SframeX); for (int y = _Yminspot; y <= _Ymaxspot; y++) { //uint8_t *srcline = src + y*SframeX; for (int xq = 0; xq < Dx; xq++) { int sum = _KX[xq].offset; /*FHALF;*/ int *KXptr = _KX[xq].K; uint8_t *srcspot = srcline + _KX[xq].spot0; for (int s = 0; s < _KX[xq].width; s++) { sum += (*KXptr) * (*srcspot); srcspot++; KXptr++; } *Tptr = sum; Tptr++; } srcline += SframeX; } /* scale y direction, tempo into dst */ for (int x = 0; x < Dx; x++) { uint8_t *Dptr = (dst + xq0 + (yq0 * DframeX)) + x; int *tempcol = tempo + x; for (int yq = 0; yq < Dy; yq++) { /////// int sum = (_KY[yq].offset * FUNIT) + (2*FHALF); int sum = _KY[yq].offset; /////// int *Tptr = tempcol + (_KY[yq].spot0 * TframeX); int *Tptr = tempcol + _KY[yq].spot0; int *KYptr = _KY[yq].K; for (int s = 0; s < _KY[yq].width; s++) { sum += (*KYptr) * (*Tptr); Tptr += TframeX; KYptr++; } /* *Dptr = sum >> (2*FSHIFT);*/ sum >>= (2*FSHIFT); CLIP_PIXEL(*Dptr, sum, MIN_PIXEL, MAX_PIXEL); Dptr += DframeX; } } } //========================================================================= //========================================================================= //========================================================================= void mattoScaler::setup_y_then_x() { setup_kernel_cache(sigmaY.to_double(), yp0.to_double(), _the_y_kernel, Dy, Symin, Symax, SframeX, zero_pixel, 1, 0, _KY, _Yminspot, _Ymaxspot); setup_kernel_cache(sigmaX.to_double(), xp0.to_double(), _the_x_kernel, Dx, Sxmin, Sxmax, 1, zero_pixel, FUNIT, (1<<(2*FSHIFT - 1)), //(not) 2*FHALF, _KX, _Xminspot, _Xmaxspot); for (int q = 0; q < Dx; q++) { _KX[q].spot0 -= _Xminspot; } // DBG("X spot limits: %d -- %d\n", _Xminspot, _Xmaxspot); //// DBG("X kernel max width: %d\n", xmaxwidth); // DBG("caches set up\n"); if ((_Xminspot > _Xmaxspot) || (_Yminspot > _Ymaxspot)) { scaling_function = &mattoScaler::scale_fill; } else { TframeY = Dy; TframeX = _Xmaxspot - _Xminspot + 1; tempo = new int[TframeY * TframeX]; scaling_function = &mattoScaler::scale_y_then_x; } } void mattoScaler::scale_y_then_x(uint8_t *src, uint8_t *dst) { /* scale y direction, src into tempo */ int *tempcol = tempo; uint8_t *srccol = src + _Xminspot; for (int x = _Xminspot; x <= _Xmaxspot; x++) { int *Tptr = tempcol; for (int yq = 0; yq < Dy; yq++) { int sum = _KY[yq].offset; int *KYptr = _KY[yq].K; uint8_t *srcspot = srccol + _KY[yq].spot0; for (int s = 0; s < _KY[yq].width; s++) { sum += (*KYptr) * (*srcspot); srcspot += SframeX; KYptr++; } *Tptr = sum; Tptr += TframeX; } srccol++; tempcol++; } /* scale x direction, tempo into dst */ for (int y = 0; y < Dy; y++) { uint8_t *Dptr = (dst + xq0 + ((yq0 + y) * DframeX)); int *templine = tempo + (y * TframeX); for (int xq = 0; xq < Dx; xq++) { int sum = _KX[xq].offset; int *Tptr = templine + _KX[xq].spot0; int *KXptr = _KX[xq].K; for (int s = 0; s < _KX[xq].width; s++) { sum += (*KXptr) * (*Tptr); Tptr++; KXptr++; } /* *Dptr = sum >> (2*FSHIFT);*/ sum >>= (2*FSHIFT); CLIP_PIXEL(*Dptr, sum, MIN_PIXEL, MAX_PIXEL); Dptr++; } } } //========================================================================= //========================================================================= //========================================================================= void mattoScaler::setup_copy() { Sx0 = xp0.to_int(); Sy0 = yp0.to_int(); int Sx1 = Sx0 + Dx - 1; Sy1 = Sy0 + Dy - 1; DBG("SC: sx %d-%d sy %d-%d Dx %d Dy %d\n", Sx0, Sx1, Sy0, Sy1, Dx, Dy); if (Sx0 < Sxmin) Dx_pre = Sxmin - Sx0; else Dx_pre = 0; if (Sx1 > Sxmax) Dx_post = Sx1 - Sxmax; else Dx_post = 0; Dx_fill = Dx - Dx_pre - Dx_post; if ((Sx0 > Sxmax) || (Sx1 < Sxmin) || (Sy0 > Symax) || (Sy1 < Symin)) scaling_function = &mattoScaler::scale_fill; else if ((Sx0 >= Sxmin) && (Sx1 <= Sxmax) && (Sy0 >= Symin) && (Sy1 <= Symax)) scaling_function = &mattoScaler::scale_copy_direct; else scaling_function = &mattoScaler::scale_copy; } void mattoScaler::scale_copy(uint8_t *src, uint8_t *dst) { uint8_t *srcspot = src + (Sy0 * SframeX) + Sx0 + Dx_pre; uint8_t *dstspot = dst + (yq0 * DframeX) + xq0; int y; /* above Symin: matte color */ for (y = Sy0; (y < Symin) && (y <= Sy1); y++) { memset(dstspot, zero_pixel, Dx); srcspot += SframeX; dstspot += DframeX; } /* within [Symin,Symax]: copy */ for ( ; (y <= Symax) && (y <= Sy1); y++) { memset(dstspot, zero_pixel, Dx_pre); memcpy(dstspot + Dx_pre, srcspot, Dx_fill); memset(dstspot + Dx_pre + Dx_fill, zero_pixel, Dx_post); srcspot += SframeX; dstspot += DframeX; } /* below Symax: matte color */ for ( ; y <= Sy1; y++) { memset(dstspot, zero_pixel, Dx); srcspot += SframeX; dstspot += DframeX; } } void mattoScaler::scale_copy_direct(uint8_t *src, uint8_t *dst) { uint8_t *srcspot = src + (Sy0 * SframeX) + Sx0; uint8_t *dstspot = dst + (yq0 * DframeX) + xq0; for (int y = 0; y < Dy; y++) { memcpy(dstspot, srcspot, Dx); srcspot += SframeX; dstspot += DframeX; } } void mattoScaler::scale_fill(uint8_t *src, uint8_t *dst) { src = src; /* unused parameter */ uint8_t *dstspot = dst + (yq0 * DframeX) + xq0; DBG("SCALE FILL\n"); for (int y = 0; y < Dy; y++) { memset(dstspot, zero_pixel, Dx); dstspot += DframeX; } } //========================================================================= //========================================================================= //========================================================================= void mattoScaler::setup_x_only() { setup_kernel_cache(sigmaX.to_double(), xp0.to_double(), _the_x_kernel, Dx, Sxmin, Sxmax, 1, zero_pixel, 1, FHALF, _KX, _Xminspot, _Xmaxspot); #ifdef _YS_DEBUG { int x; for (x = 0; x < Dx; x++) { fprintf(stderr, "%3d: %2d %2d %3d\n", x, _KX[x].width, _KX[x].spot0, _KX[x].offset); int s = 0; for (int i = 0; i < _KX[x].width; i++) { fprintf(stderr, "%d ", _KX[x].K[i]); s += _KX[x].K[i]; } fprintf(stderr, " = %d\n", s); } } #endif Sy0 = yp0.to_int(); Sy1 = Sy0 + Dy - 1; // DBG("caches set up\n"); if ((_Xminspot > _Xmaxspot) || (Sy0 > Symax) || (Sy1 < Symin)) { scaling_function = &mattoScaler::scale_fill; } else { scaling_function = &mattoScaler::scale_x_only; } } void mattoScaler::scale_x_only(uint8_t *src, uint8_t *dst) { /* scale x direction, src into tempo */ uint8_t *srcline = src + (Sy0 * SframeX); uint8_t *dstline = dst + (yq0 * DframeX) + xq0; int y; for (y = Sy0; (y < Symin) && (y <= Sy1); y++) { memset(dstline, zero_pixel, Dx); srcline += SframeX; dstline += DframeX; } for ( ; (y <= Symax) && (y <= Sy1); y++) { //uint8_t *srcline = src + y*SframeX; uint8_t *dstspot = dstline; for (int xq = 0; xq < Dx; xq++) { int sum = _KX[xq].offset; /*FHALF;*/ int *KXptr = _KX[xq].K; uint8_t *srcspot = srcline + _KX[xq].spot0; for (int s = 0; s < _KX[xq].width; s++) { //for (int s = _KX[xq].width; s != 0; s--) { sum += (*KXptr) * (*srcspot); srcspot++; KXptr++; } #if 0 { uint8_t *dmax = dst + (DframeX * DframeY); if ((dstspot < dst) || (dstspot >= dmax)) DBG("%p (%p - %p) : xq %d y %d \n", dstspot, dst, dst + (DframeX * DframeY), xq, y); } #endif #if 0 *dstspot = sum >> FSHIFT; #elif 0 /* EXPERIMENT: avoid under/over-flow when casting */ sum >>= FSHIFT; sum = (sum < 0) ? 0 : sum; sum = (sum > 255) ? 255 : sum; *dstspot = sum; #elif 0 /* EXPERIMENT: avoid under/over-flow when casting */ sum >>= FSHIFT; if (sum < 0) sum = 0; if (sum > 255) sum = 255; *dstspot = sum; #elif 0 /* EXPERIMENT: avoid under/over-flow when casting */ sum >>= FSHIFT; if (sum < 0) *dstspot = 0; else if (sum > 255) *dstspot = 255; else *dstspot = sum; #elif 0 /* EXPERIMENT: avoid under/over-flow when casting */ { int val = sum >> FSHIFT; if (val < 0) *dstspot = 0; else if (val > 255) *dstspot = 255; else *dstspot = val; } #else /* EXPERIMENT: avoid under/over-flow when casting */ sum >>= FSHIFT; CLIP_PIXEL(*dstspot, sum, MIN_PIXEL, MAX_PIXEL); #endif dstspot++; } srcline += SframeX; dstline += DframeX; } for ( ; y <= Sy1; y++) { memset(dstline, zero_pixel, Dx); srcline += SframeX; dstline += DframeX; } } //========================================================================= //========================================================================= //========================================================================= void mattoScaler::setup_y_only() { setup_kernel_cache(sigmaY.to_double(), yp0.to_double(), _the_y_kernel, Dy, Symin, Symax, SframeX, zero_pixel, 1, FHALF, _KY, _Yminspot, _Ymaxspot); Sx0 = xp0.to_int(); int Sx1 = Sx0 + Dx - 1; if (Sx0 < Sxmin) Dx_pre = Sxmin - Sx0; else Dx_pre = 0; if (Sx1 > Sxmax) Dx_post = Sx1 - Sxmax; else Dx_post = 0; Dx_fill = Dx - Dx_pre - Dx_post; if ((_Yminspot > _Ymaxspot) || (Sx0 > Sxmax) || (Sx1 < Sxmin)) { scaling_function = &mattoScaler::scale_fill; } else { scaling_function = &mattoScaler::scale_y_only; } } void mattoScaler::scale_y_only(uint8_t *src, uint8_t *dst) { /* scale y direction, src into dst */ // uint8_t *srccol = src + xp0.to_int(); uint8_t *srccol = src + Sx0 + Dx_pre; uint8_t *dstcol; /* right side, outside of src matte */ dstcol = dst + (yq0 * DframeX) + xq0; for (int yq = 0; yq < Dy; yq++) { memset(dstcol, zero_pixel, Dx_pre); dstcol += DframeX; } /* middle, inside src matte */ dstcol = dst + (yq0 * DframeX) + xq0 + Dx_pre; for (int x = 0; x < Dx_fill; x++) { //uint8_t *srcline = src + y*SframeX; uint8_t *dstspot = dstcol; for (int yq = 0; yq < Dy; yq++) { int sum = _KY[yq].offset; /*FHALF;*/ int *KYptr = _KY[yq].K; uint8_t *srcspot = srccol + _KY[yq].spot0; for (int s = 0; s < _KY[yq].width; s++) { sum += (*KYptr) * (*srcspot); srcspot += SframeX; KYptr++; } /* *dstspot = sum >> FSHIFT;*/ sum >>= FSHIFT; CLIP_PIXEL(*dstspot, sum, MIN_PIXEL, MAX_PIXEL); dstspot += DframeX; } srccol++; dstcol++; } /* left side, outside of src matte */ dstcol = dst + (yq0 * DframeX) + xq0 + Dx_pre + Dx_fill; for (int yq = 0; yq < Dy; yq++) { memset(dstcol, zero_pixel, Dx_post); dstcol += DframeX; } } mjpegtools-2.1.0/mplex/0000755000175000017500000000000012217306500015332 5ustar glowwormglowwormmjpegtools-2.1.0/mplex/lpcmstrm_in.cpp0000644000175000017500000002220611215040532020364 0ustar glowwormglowworm/* * lpcmstrm_in.c: LPCM Audio strem class members handling scanning and * buffering raw input stream. * * Takes a *RAW* LPCM stream as input. * This is *signed* linear 16, 20, or 24-bit sample PCM. * Samples are stored msb first. * How 20-bit samples are allocated to bytes? I just don't know, but * believe 4 bits are appended after the lsb (samples are msb-byte aligned). * * Copyright (C) 2001 Andrew Stevens * Copyright (C) 2000,2001 Brent Byeler for original header-structure * parsing code. * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include "audiostrm.hpp" #include "interact.hpp" #include "multiplexor.hpp" const unsigned int LPCMStream::default_buffer_size = 58*1024; const unsigned int LPCMStream::ticks_per_frame_90kHz = 150; LPCMStream::LPCMStream(IBitStream &ibs, LpcmParams *parms, Multiplexor &into) : AudioStream( ibs, into ), parms(parms) { num_frames = 0; } bool LPCMStream::Probe(IBitStream &bs ) { const char *last_dot = strrchr( bs.StreamName(), '.' ); return last_dot != NULL && strcmp( last_dot+1, "lpcm") == 0; } /************************************************************************* * * Reads initial stream parameters and displays feedback banner to users * *************************************************************************/ void LPCMStream::Init ( const int _stream_num) { stream_num = _stream_num; header_skip = 0; MuxStream::Init( PRIVATE_STR_1, 1, // Buffer scale default_buffer_size, false, muxinto.buffers_in_audio, muxinto.always_buffers_in_audio ); // This seems to be necessary not only for some software players but // for some standalone players too. Yuck... shades of the VCD audio // sectors. min_pes_header_len = 10; mjpeg_info ("Scanning for header info: LPCM Audio stream %02x (%s)", stream_num, bs.StreamName() ); AU_start = bs.bitcount(); // This is a dummy debug version that simply assumes 48kHz // two channel 16 bit sample LPCM samples_per_second = parms->SamplesPerSec(); channels = parms->Channels(); bits_per_sample = parms->BitsPerSample(); bytes_per_frame = samples_per_second * channels * bits_per_sample / 8 * ticks_per_frame_90kHz / 90000; whole_unit = (channels * bits_per_sample) / 4; frame_index = 0; dynamic_range_code = 0x80; /* Presentation/decoding time-stamping */ access_unit.start = AU_start; access_unit.length = bytes_per_frame; access_unit.PTS = static_cast(decoding_order) * (CLOCKS_per_90Kth_sec * ticks_per_frame_90kHz); access_unit.DTS = access_unit.PTS; access_unit.dorder = decoding_order; decoding_order++; aunits.Append( access_unit ); OutputHdrInfo(); } unsigned int LPCMStream::NominalBitRate() { return samples_per_second * channels * bits_per_sample; } void LPCMStream::FillAUbuffer(unsigned int frames_to_buffer ) { last_buffered_AU += frames_to_buffer; mjpeg_debug( "Scanning %d MPEG LPCM audio frames to frame %d", frames_to_buffer, last_buffered_AU ); while ( !bs.eos() && decoding_order < last_buffered_AU && !muxinto.AfterMaxPTS(access_unit.PTS) ) { int skip=access_unit.length; bs.SeekFwdBits( skip ); prev_offset = AU_start; AU_start = bs.bitcount(); if( AU_start - prev_offset != access_unit.length*8 ) { mjpeg_warn("Discarding incomplete final frame LPCM stream %d", stream_num); aunits.DropLast(); --decoding_order; break; } // Here we would check for header data but LPCM has no headers... if( bs.eos() ) break; access_unit.start = AU_start; access_unit.length = bytes_per_frame; access_unit.PTS = static_cast(decoding_order) * (CLOCKS_per_90Kth_sec * ticks_per_frame_90kHz); access_unit.DTS = access_unit.PTS; access_unit.dorder = decoding_order; decoding_order++; aunits.Append( access_unit ); num_frames++; num_syncword++; if (num_syncword >= old_frames+10 ) { mjpeg_debug ("Got %d frame headers.", num_syncword); old_frames=num_syncword; } mjpeg_debug( "Got frame %d\n", decoding_order ); } last_buffered_AU = decoding_order; eoscan = bs.eos() || muxinto.AfterMaxPTS(access_unit.PTS); } void LPCMStream::Close() { stream_length = AU_start / 8; mjpeg_info ("AUDIO_STATISTICS: %02x", stream_id); mjpeg_info ("Audio stream length %lld bytes.", stream_length); mjpeg_info ("Frames : %8u ", num_frames); } /************************************************************************* OutputAudioInfo gibt gesammelte Informationen zu den Audio Access Units aus. Prints information on audio access units *************************************************************************/ void LPCMStream::OutputHdrInfo () { mjpeg_info("LPCM AUDIO STREAM:"); mjpeg_info ("Bit rate : %8u bytes/sec (%u) bit/sec)", NominalBitRate()/8, NominalBitRate() ); mjpeg_info ("Channels : %d", channels); mjpeg_info ("Bits per sample: %d", bits_per_sample ); mjpeg_info ("Frequency : %d Hz", samples_per_second ); } unsigned int LPCMStream::ReadPacketPayload(uint8_t *dst, unsigned int to_read) { unsigned int header_size = LPCMStream::StreamHeaderSize(); bitcount_t read_start = bs.GetBytePos(); unsigned int bytes_read = bs.GetBytes( dst + header_size, (( to_read - header_size ) / whole_unit ) * whole_unit ); bs.Flush( read_start ); clockticks decode_time; bool starting_frame_found = false; uint8_t starting_frame_index = 0; int starting_frame_offset = (new_au_next_sec || au_unsent > bytes_read ) ? 0 : au_unsent; unsigned int frames = 0; unsigned int bytes_muxed = bytes_read; if (bytes_muxed == 0 || MuxCompleted() ) { goto completion; } /* Work through what's left of the current frames and the following frames's updating the info until we reach a point where an frame had to be split between packets. The DTS/PTS field for the packet in this case would have been given the that for the first AU to start in the packet. */ decode_time = RequiredDTS(); while (au_unsent < bytes_muxed) { assert( bytes_muxed > 1 ); bufmodel.Queued(au_unsent, decode_time); bytes_muxed -= au_unsent; if( new_au_next_sec ) { ++frames; if( ! starting_frame_found ) { starting_frame_index = static_cast(au->dorder % 20); starting_frame_found = true; } } if( !NextAU() ) { goto completion; } new_au_next_sec = true; decode_time = RequiredDTS(); }; // We've now reached a point where the current AU overran or // fitted exactly. We need to distinguish the latter case so we // can record whether the next packet starts with the tail end of // // an already started frame or a new one. We need this info to // decide what PTS/DTS info to write at the start of the next // packet. if (au_unsent > bytes_muxed) { if( new_au_next_sec ) ++frames; bufmodel.Queued( bytes_muxed, decode_time); au_unsent -= bytes_muxed; new_au_next_sec = false; } else // if (au_unsent == bytes_muxed) { bufmodel.Queued(bytes_muxed, decode_time); if( new_au_next_sec ) ++frames; new_au_next_sec = NextAU(); } completion: // Generate the LPCM header... // Note the index counts from the low byte of the offset so // the smallest value is 1! dst[0] = LPCM_SUB_STR_0 + stream_num; dst[1] = frames; dst[2] = (starting_frame_offset+4)>>8; dst[3] = (starting_frame_offset+4)&0xff; unsigned int bps_code; switch( bits_per_sample ) { case 16 : bps_code = 0; break; case 20 : bps_code = 1; break; case 24 : bps_code = 2; break; default : bps_code = 3; break; } dst[4] = starting_frame_index; unsigned int bsf_code = (samples_per_second == 48000) ? 0 : 1; unsigned int channels_code = channels - 1; dst[5] = (bps_code << 6) | (bsf_code << 4) | channels_code; dst[6] = dynamic_range_code; return bytes_read+header_size; } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/decodebufmodel.cpp0000644000175000017500000000401610025375117021005 0ustar glowwormglowworm#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "decodebufmodel.hpp" #include using std::deque; /****************************************************************** * Remove entries from FIFO buffer list, if their DTS is less than * actual SCR. These packet data have been already decoded and have * been removed from the system target decoder's elementary stream * buffer. *****************************************************************/ void DecodeBufModel::Cleaned(clockticks SCR) { while ( bufstate.size() != 0 && bufstate.front().DTS < SCR) { bufstate.pop_front(); } } /****************************************************************** * Return the SCR when there will next be some change in the * buffer. * If the buffer is empty return a zero timestamp. *****************************************************************/ clockticks DecodeBufModel::NextChange() { if( bufstate.size() == 0 ) return static_cast(0); else return bufstate.front().DTS; } /****************************************************************** * * Remove all entries from FIFO buffer list. * *****************************************************************/ void DecodeBufModel::Flushed () { bufstate.clear(); } /****************************************************************** DecodeBufModel::Space returns free space in the buffer ******************************************************************/ unsigned int DecodeBufModel::Space () { unsigned int used_bytes = 0; for( std::deque::iterator i = bufstate.begin(); i < bufstate.end(); ++i ) { used_bytes += i->size; } return (buffer_size - used_bytes); } /****************************************************************** Queue_Buffer adds entry into the buffer FIFO queue ******************************************************************/ void DecodeBufModel::Queued (unsigned int bytes, clockticks TS) { DecodeBufEntry entry; entry.size = bytes; entry.DTS = TS; bufstate.push_back( entry ); } mjpegtools-2.1.0/mplex/COPYING0000644000175000017500000004307607133030460016377 0ustar glowwormglowworm GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. mjpegtools-2.1.0/mplex/mpeg_systems_paper_0.99.ps.gz0000644000175000017500000035573607133030460022725 0ustar glowwormglowworm‹p5.mpeg_systems_paper.psÄZëoÛÆ²ÿúö¢·8)zÛ T¢¤4El –Ý$‚ Ф$6É’”-BÿûýÍì.ŠsZœ/·uÄ}ÌÎÌÎÎÎcwü¯ÅòÍØ‹Wþ›Þ…Õnýø£úN§×âCyñs&KûþÝâú‚<ô¯ÅMà¦q¯sñ!N=ñFÜ,fo»Ó;›€&ñ>ò‚h3‰×¢ÓK F#qÙëRï4v÷;?Êo}ßó½{?‹÷©ëg×ⵓû‘÷Sf¹O’0øÔÂÙœµLüMàk‘¤±›ù9M¤7˜n.ÀL»%«z÷Ê<][¹òŠD@}'SATŒ0Ý><­<é{…p· Ä“¡W„±ã™jžâω²ŠÐ“› Γ*§`d“úDÍ 7r?ùyLå÷2 "]Nw9þ•]iˆjÙ ©‹wŸ€,Ç_e¤‘ŒüçÄɷܳ“ÆÎÉÓà@uw'1.…œU[»E‰tÃ8óÍ ñ½-Ô¨üp_ ƒÞ"{âéþA‰™?â€!Bé6×I¨i2Õ ÷Á6>ÌIh€žO3盈D±vÂÌo·HÖ™[˜æ"‰¡ÿ K`9üƒèê¯ÿgYì—Mí–yå¸î`@l ÐݤÎñTô Ó¥i†§ÔO ú’nVnÆé)Xû`Ç|V$ð¹]¬îÅê­XMDæ’Öv!Qñ=‰Vú½Ç/uüjÛ{±}+¶tk@±eà-o ðÂ.’{‘¼‰N€7aЄAšÝ@Õ:’œ~ôs`õDY ¸¸;ÌE hw˜5«³44àד™Z …wê?ac‰QWX5(g–Êã±®¯ãt'¼}"°C„ÚºâxžÈþLs…}±¨a_. 4d–¿ Þ!´ƒŠMV ^Þ+èMƒþ´Ö?û­àÍÕneÛ:¿ñ…Ù^Ôýƒ]ì3?õªíýƒ'¦ä{öƒ`æ³Õ~ MÂþùR:8ŸmÂc²}ýVˆŸT½èð¼ šWg(Ô ÷)Í„†UÓVPíV²ÏƒÊÿä„hÓÊIÚ}Š€N1±¼)dpÏ|I÷¸Àbq‹j¸áÏ>´Ëb&f2× }.Y"ò ˜6ÿÏ‚G0#ªzPU‘§â Ò8'ãô¦Þxü‰A˜-˜ýŸÖˆ˜í¡Ïö+Çd_¦ð´h·4âBñÐÜu¼‡I/#¤Øë5¬Ë&Ù²ý;XŠ$s,yC–þ¯´ú¢;`æSòo\+™itµ[¾ ÂPz^èß £¼4ÚRUðd€ä~ù+-;x”ÞÁT>O÷jÏTûa|»|÷»ï~n·:Ã,¸ÚV(v¤ãîs.v¥ÀuìÖ!x@½'ó ô¸«/w||Då\¥>m,”‡Òƒ`]NƒºFÒ |ì² £Ú¥¤}C¥+éú^†UÆr»6Nºß…Î>g4oâÈÿJݶtMiJØC?Ëfo$ÿÜÇ9°G›¹êy0Ž‘-WNÊt»5À•“1ìeO®aÁF|ÙWÞªê`_ùa$†{ÌÍÙl|…r¤+Áõ+™øi¾÷¼ ·Œå’gf.'r³Bæ ô×,œK[ÞÍXEÝt\i~Ó`³U =ðb,¡*ž+@¬Åª2”0\N¶åʈ¦³+«WzxþÎIYÈWcxS#櫳j[ÆJ°Wsù©¾¬cKf‰ã²ÔÆ}3¸G®¡ˆ5"½ã»›Z*ãˆ~Œ¡qr,IŽÇáãÚßBnQœ…þŽô`­”elË0ÞØ‘Q¬ÆMå–ÓçÉŒg2…=Ï NŸf<¯éîÄ’ž? f6éÈ$Üg ·g†&]™?ÇÙKÄ< öÀà¶~µe&¤5»=‡2qR ™°È'#Éc<Ú†™Ée}'L®$´ÞàV,± vNæîC-„IM¥¬&6 ýs魯ÒÐÉ”¶N¸VxfŠq ¡¦7‡Áb9ȳ2…f"ÏÈØò±x*?U\ÍäÃ6N•}œK˜¤,Ð*TšYÒ)éÌ`ÛËq³.´¶AfÖ“N)†”º!ëÙq¾^ÎÙP: j$ÝÚbÎ.¥_Q»’~EmLæçŒÞùQmZ3[Õè© ªÑ3Tc;sÔÏ-éç,ÚyGFå4æ]xƒsÞ“q‰sÞGq“£ù@ÆÕСŒÈ™=ºóRƼ˜ÌÌüJî+*c¹¯¨LäþŒ†-÷ ´Sy¬NÛT¯æ|.%䄱#—cÔN·LLå»ÌÞ:iAžkG9µÓ.CÛ’#ÕLlà8Øøa£“û¿q[Ũj´€í¤Cû íÒ/Â'g‘SÂÎhL6Ä1©B4e Z€å•1§+…ìªáT°ó7“×Ã'êÔ]…]µœ}ÏÇS3“E%¾kæ#gçsÎ¥…Cõv Æ—MƒÞ(N¢Í2byȺHE…X#袊ÊôpÑ€ß9‡Ð6ÐÊò¡Þ_˜ìGÎßMIØ´•¬ñ•é‘Fã¤ÈL¹HÃos5 È¿ØW•)GÖu„ ÌJ“PnYBu`<ômtÁUñ¢Vezèd¥ÝÒ!¦pøÐƒ(›=!$åØR…ZL]—ú$X5šœ˜©A–p†\T“i, N×–“›íñ=ˆÑŠÓ±…ÇôÑô)4¦uæTMlrÄÒËÒ]-ybé·^ ò¬£E ËàQ™ :¤(+yì0ý ”ñGù-ꇟ ÕR]…š×™“gD5Fñ@] £0!«2ÍjÉ…³Ê@x£Ñöæ@½ÚÒ;ÎûÔ\¼ƒ©L3»!y&s°ÄÄWÈŒ¤I;<_Ê¢O…îÇ.¨pŸÞ©ëÇ÷…Áïß~Ò].xe˜&Sä–ÒtøPK¬`ÀÒ0Gz‡Y(>HæçËf¹à4_¬—w ÓniBË;ÂÏ „Äß Ón}—PÔ<úà2@Ò˜šqÆé ™ôA®z$dUKeÓøòÈ¿jïXœ¯#æ#C>jÑ¡+µø™Kp´(èhØ yÐ$-vG]Ójz|áØÀAfˆ«jö:¹¦Í > &Ãh„AjÐ5…E›¡œhɀςý¼ûЉ’” Mè=sfI¤ ãô Áˆ}_— A²ºöô±ù}t·[ª_‰÷{P x| ŠÏ9 Ȩ Ò­!"-ÐÉiE!N>g?¯V‰ek|¿6Òݾã?:€-1ì‹âç Å'«h«ÞŠ‘ØCPà“Ÿæ†?ÓhšÑ'r%@¯S¿"8ÿWŽçvë“‚úhÄÕ™n~íΦÄʆºöô0‚p9 ž>ƒ`Q¡õO%¬¨@ õªDÝn©ùžáf[ù÷ÑS¨µ9£1~,Ô²»O¢?¡[§*RâV²£#®_ïI·«UŒ?ÊO¡ðQ¸Zº@Lð ­Zçg>a½Ñ…ºuÑG¥´¤ÖEç¿éx ö–„,ˆŠâÐ@ iºÔÀ‹À) 5õ¨i¥›¨oÐ3tP’oÈ8qú°Þ‰î€'®‚>Äs[“ES"“Å_é0e1ö†|ù¤FBhyüÊ£íCXÝ~…Z>ì’òÖCð¶ÔTÞs¬á'°64`û E^—‚¯€ Ã…M‹KV¸~—óöC¡Ž·9«| ­W€§±ëå~Ý}I½íÖy÷6ÛàÆø òã/ÉJ•†T‚?«¯1/÷òª~ž~o?4ûÕà®êŽ¿Óßnõªñâ»`J P0›c Í·IÅN¸;¶Û”ðme}«¬³%zC Y›+ÜDìD¶S„ã·…Ì8èË8èÃ/ µoÒ5ô5ëßô«{ˆ²Áƒ‘N—p©bG£&ÅZÐ?¾·O´Ücf&Yq?~«˜ã«ÂƼh7Ôoø'û{ä̉Kùð›*ÑÔÖ¯áú{üï²ß½¿·íBr:UËŽÊ|Š·²„ƒ26J 9’GË‘Û1,%YBº}ò™&_T]”a ¹zÂ2ÖwPX†°3¿…0“0Q +®¾fRŠk¼8KçTt‘¤ ¾·¡éŸJÑÊc—§Í¿ÇL zèêÑoÉC†6d3çíGíc0Œï¢T7ª¦£U‡RñÈÁú,e €MÅü Q:s¶:³j¬G÷/äeˆv«±"/#©/ÉËHH!iaίàåbQðbZî&dŸÙ˜Ž ­¤›ò¨²`Þq¬îÞtv¤s“;Q•vT 4`$Þ(Tl§0b"Ø4oØENŠ„î*pçK9J`ȷ‚¹àt.Ã9g¢lƒ=)&‚]Á§t³4ýf=ôÓÂOÓX]Oó…yy¶ÄkªË›œ=\ –cZŠêÑ´õÃäüìPÔÛÕÁY–;î×=Åýë0~~'~Jž…›EÙN±ø¥:…cÞë|d*-¥olÎh`é#á0=¤GNzä[òßo˜Å×Çx/¶äÙö 1/ŠKó-òÑ”/Åÿ‘‰¿‹Õ(Ë–#$v¿*¶àþij“A Ý*!¾%JëµO9 `¯…žFÄŠt!Þ”ñ>§°“›Dì"ðâç‚Α‚µ8“&½Ïà5áöâ¿ÕXî¢S(Õ*M©:(å»z 4êªm¤ ž7­¸ºréW?„ \§L̤àëq/6ôP¹œ×w˜6?«v¼£+ñ³ø‰HJW×éŽ#VŒT ùìñ5p¬…ŸÜ'z\Á<Ÿüƒï‚»#3A±"YŠŠòŒç©©Á’S•¡¤EûZ4 ¢Àè_‹kÍè9K/ i0u¾4 m.ùÐIoqÐL9í¬_ħšú‹”Î;hdÿ% ,yoü̳1ï”â[uÔ+3J¼°â/§­r·ê‹fï¤uV§~ôØm•ïâøáÌ4vË(R÷/`¾âMù2né甜½s-XÂ}V3ÇNÄ«<Øù1m¢ø T­A˜¥úúûOâP‰:=bÀ†®»Èø¼\ šgaÒÑn絡°«Åù«=q¢AôœåûãhÉØmƒÀSêt:¦¦‚øk~»õÿÏåçBœèÞ¶ ŸÁëãu¾ä§¢êú‚`ý@ËjúÔC=äq¸ç“­ç-Ì*X%’=ËâM¢ª5K«’z„yM7¦òÒ[Íå’ŽJ2_Ò{ÐÑ%ÊÎðŠ),oè #ù_ÖÜR}_ÉÒ˜'ÕÒ×':J~4„Ýhe~©‰Óª hæzB'²,ÑÉ z 䙘Ë`ñUCûÕ+!4X÷¬Öp ÑòŽEÅyœ£VÍз+Üc±{8#¯Z·ùس÷WôYD/Ó'î0ÏN¯_I‚Z£ªŽ v.ëý]1pÛôÖ¿¨¥µDbS©#–‹v ÑØ s%º½¡ 9‘¶'íV·7ô¯Óíqš 0@ôö•f·ý +Æ2P’ÑÆTÏ—¢)õøÕZ&º¡ Ai v)@még°¬Â¯ÌÊJ´²õr#¥˜h럳îìpÖKWKO ™}„ŠÉõ˜ãA3E-èoÆäC $ºÒ×HÚi¸£AZ"| ¸]^ŒK¼e^Éâ"“ýcõL¼{a‰Ùb9§B㽸÷$X÷‹AË]½ó¹ºþ¿W}qïxôŠGÌŽ¾XÂE<;©_{Uî9{Ïï^M‰Vg ήÅTø·}$:HŠ­ënïº?dœ/¼7ﳓÞBWµ¹¢ v1Cuúû»ÅR‡Pï¡!†ï7³& ·pRx5zO°$øëŸÂÕÈDê“rzx©Ÿ‹ÿ£Ð'ñxa /¬Ñug0è”®žÙ… ½¹¸HÒF£Ô›ôAíìÚ4j«w[ÐïÇIõ8ý†M³ßÏÇb)nOAϵ«‡€ ²0ÓÆµ§,ø—;L¯HI7дå¦Ë‹ÐOÜ©1„œèÑÔ•UðXEý,n„²ø +Pѩ쩠¥pMÚ]±ø¢.p( ÉûÊ­–£å÷³&ÚŬ…@Cdj4ê #•A«éÏ* >5˜7#ân+(sˆöpOÕ€ëÈV=\‡—|CûpoÎ×Oè9æS'Ž_ª—¢}e¥Í9:ý¨[Õ?¨úË÷ù´^¿ÐŒ!Ä/ÔÚ±!ç¥ýÚ»wµï{E#2“U‡§Ëz ;å«çÔ:¿qòÚì÷ÐO&Ÿ-½f¨Fâûn¦¾.¡à­ßäNq©TöVD0çZYk÷,·¢~ͲŽòô`Úør$Q×ñ0¿Êé †ÞCÈI€Ø¡EíV…~¸æ§$«òî\ÞrÄDy²\Ç1ŸìñÝW·þÀ‚¢¡[4Y`š¥o¦ö™dã­ ™­±æÀÎ ·[$.Tõ¼PVfäG ÷9[³ð²µvD$ÅÚ˜Y¡Næ"uÄýíu¹Û7| _ à9¹S&¢ÞC°ÁèÖ'Sûl¿„U‡x½.:ÝËÿcïߟã:®¬QðwGø8ñMÜhT ž÷ÃwîL¢dËnÙlQ–{ºq£@Õ(TÁUҢ⛿}r­½wfžhùs÷µC²Èʤ~H>„§„“þ»CôÝü;k˜a$ü¢Žx÷‰Ñ!ç×àoÞ÷ÿ©5n•@CúÓF ú{º?òªúÉýü›[½ÏtÙÅŽã(¹å—¿púX›6µ4.gë$Ã_å„þ|ÙíO´ˆ¸?};{N½zíî9yÚÛ!îÖL§Ð?þ(|ÿ“þí?¬Æ$ßcÁ|ï.áøï·ß'ëÆ §•ß¹¿ò^,öý%ZÛüŸÒÄé™nø<ØÃ^¯ö·ëå‹àH N`uN~ßÿÇw ú$hO”+S™þ§*[ºr`­”ô&§¯p—ã_÷GŸ·“ȇñ;ù Ñò0l?a”¢Íîs¢þç|ƒƒfÌï•%iPûêÆóß¿·\¬|%º‡"úc”£»Ï¦ÐßóœšÄÉçµü(•†÷<5Îa¶üIšäAݯK=¨´PÌóW·\#¡ê7NƱŒ";·Ïø;ÿ&çîOÏËä6þÓóBþÔÿô<—?]@æŸ.Ýúà®~Ò_V?i¥ÿü ¾Kþñú'mìÃOƒÞ¬ºMÜ{>àÏ7øs!ÞàϹüyû“;ïÜëø—¿ü)Å?î~‚då÷?Á/Î?~‚zÊ?þÕ½ëmü¶Ù!õîÝ&K‘ªNm|ûV&¿Òýâ~C,’z¯q òàâR¦yÕ–E“TyÚuYUŠQ3Ó/qòân¿{±wÇrÿâêöj¹^÷µdwç/n¶ËÝ Ü`þú"\ωH=ó,¶ê¬ÿWZ|éM¿úªMÓ쫯¾HÓâ‹ÌýÔ´éWîÿ£ÜE;øÿ_þ"þ[\Wž––¤Uyƒ¼-˲¢yÝYûÿÎÜeôuòåp0f̯ÿÛÿö•»ÙÞíÜMñ_#¹ëÆÁÝ0G÷Ë_ ímgÈf­s÷o—äiáæò½ü½«á™mÝ_‹ÔIçE®ÐÍ(þÚå(M­”•ñhQJÝï“¢jËä«åÉiV/ÜYì*»âÖ*fuòA+ȯ,/óPþË_ø üY*ÔYÜIô¹Èùb×!,7€ü˜ÎýÕõtéßò¼DÍRjêŸò”ßôË_¼×¿—öQ­¯×†zV Õð:'õø§POþjÍ¡çè*zŽÇ¤ëõ`ø‹ªŒ‡¿(R}˜ŸS¹N¿§òßS¤ã1-}y딤™ ­U`?'åîW÷˜T¨³¸kì©{Z½jlÀð·¦Áø5‚za ®¬W/š›2“^êPK­VjŃîc—Y­¯é»Ìê¾ËeÚZ—Û*^'eZ׉Ö,¥æ`Xd1k…v¦‚¼•åÒ›Jþä^—–ñÊ@°2äo¡¯E%}uey´J7vþJMtÊUœë«Thg*ȯ…öЗT+Ôò§¸“u®ZÝ`@«vÔI©YJMýSÕ6ê„'õªq_ÙŽtªÃr-X«P[sQ_+ÙixÓ~i2ܹsN JÛHWÞœteýëÿTÇžC3Ï2=¿~ùO÷ÃÿB÷CÙ ÜðÄî‡2­gÝp0À‹àD_Ö4…w1¸Ã;Éó.ÉZ·Yÿécø§aÎÇ=ÐÇP´÷øÜ¢ÅBÅâ|”!ûÙ| uÚþÓÇðOÃ?} ÿô1üÓÇðOÃ?} ÿô1üÓÇðOÃ?} ÿô1üÓÇðPC6ô1ü= ú°5ç0m¦˜›"å¿0I×~p—NüÐ9u5ÚrT£­:¶Q9ÕK쮮ѢeƒYZˆ±®à/î²!ÆÌ¬JÚ¢m”EÉZµvV™;ƒÀÿD6QçͰ‰ºä®—]-Uº2Véh…mdiUh_þBªdi“z’eÕ¨¯YÖ”ÚŒI–×ã:y;ü ¬¨[«R•íÏdR,r$M‡äžÓTI”÷AH‰,O Þ&‘|©zñ…;ÇÒ–è´î³³ää»þÝÕfµwjZòÇÍê}¿Û¯?eyH¾ù¡hÊ+Ø,¤î[§#·yå¦Nš¬MN¾Þ쫃;'/Pu— ÷çÔÕõ‚ðÀ\3w»_ÝôûçßnÝ…Oz\Lz\U©Ûzžœ|µÝ.{×ÏÝêpè7ýæv·¼voº»IV7‰ÛϰU,¤rôÞªÅ?òÞ*Ð{Ý·º½àæÑõóä¬_á[Ød׸át£2k’·a/N“ßž&oß]­Wï®Ü¹¸`Iôr·Œø¯&çg…½ÿÕv}.¯Ï»ñëË ^G××Îm¶ä8¼xûÿ}ûÝ—ß¼]ð'´ŸE'•êÜMò€…õE'ðÓq#_»]•çµë|êöÀÉ÷ýî†+d“¼wÒ]z~M€«×*á…¬¥E…(ì¼NN^¹Ês¤}%ßm7+[[7uÉfIãîÍBªâáÜ¥"]ê¾èë·p:Ûn̲&wgƒëÂÅòj‡×¡ü¾ ®2À]ëºÙÁ7‘VÉÉnAÁ¼|•|ãdõ‚?·~:×B‘ºY¬œ,:y…<‡»~÷«ä;¼È=öÁ‚¥œËäÿñÅL Ll õETlŠ/›|ûÖÒ"¼t™dIðZî%*ü?å·0H“ùi!ý"Oò#Ò/tÝJÂb’?‘°ŠæÉ=~¯ÄÊáss"-oÒääå™S˜—ï þ5šª²Æ?òTù°…ކ«ºDrºf‰›”’-æ]Åß·Ï{´ºèœ@bÁOÖýáã¥Y!û²Ê*-v¢ã·\°,•%UW©¼Ím·\I-ÐdR;Éì̇þòÉ[IžÉ[;·£Q^ºâ»©¿7%¯ÑÍUï Tøe© v$uù“SÑTvš“oÒFó¼ßá1é ÛŒúyn'»/W‡åZ>¡QÁƒí! 7¶Ãq:èkÝ™ÎÒֽߛ¾³N –xÎÉgN€ì–ú­…µÑéæ™¦ËþšæêÓÿιqsVCüa°~ï¶;ÐÉôÔ©”9ýàÄË Œdª" KÑUÀ§¼Ã§·"Ûk7¶((Ðêï¶7·»ÕpÖ7i¾Ó§Ãçu6ÞNABIîØÉE1ü¶\—•[…½Œ¼¾>+ºRzž»¶á4…cãê„$K¦vòán'k2Óå“Õ­;íCæDõ)xs®Uº´¾§ë]'_îΔädϳã¦~ÁlÀ›ÌM]Ž—÷€[ï7‡«w×n]bxŠZåÊð¨ºe¼ß"ãwÏu¬ë¼• \•P¯¹,epÛ®–BŒÀÕòL>1ït€ÞR÷¥'{wÜâtP1ù(jP亇QÕ"ôD^è¶kÖµm¼X‹LšŒvOm“!_<³Œ´áª“g£-¤¤nô•ØBvŒ¹·ÚD·n-°äË¿úÅ¥Ÿ '3N~í®š·û @8-\n¹ë¼»3â>eϤýÒ5Ä*˜¬ßº“ú[—™¬œ ÂÜéÄ'ßlq£ ¯¥ûmU°F´LdL:ÜÐ.ºýñŽ¢-Ûü¸UÄrwu Ò‚ÂÊÄŠµÚaòØlf#‰x ”a$—w˜<}Ê ÁÙ {BÚ?ååõÇþÖ®¹æu,›N>׋ͺ°9hý;uê;»Rå‚“ïy$]ò´–¹£³Àl^Z7'XO~³ÜÃ5è¾ó¦tºP¹\»ýŠœÀKhôNV4N¼E" îåVÏž×|º“¹éÜ!Ë·@õ¾ÝÿøÎÝnª˜a¶6Ú5ë…9ÌÒ, 6ŠÐá“çËk×Aÿ|^k¥Zß“¹íìVÉy﮳\E]£Ã‡«ÝàØi;“2¥5TE¼:×±K¥W®{ÉÉöluIÕ1 »›•ÛºYK·‚º¡ÜV™ã~DAî¾Lä60¾ùjDŒq@]ÝPèÖ*qZyÖÝçì´[íE­Åó¶eÝB’Þ escb¤–R§"œ,7nVmotŠ•ÔpËÎ PHoާºu—J9î9n:ÖNÙâ+lX[í@ôõúò®–—C,þYdŸ»Ûj•§ …Þ¬¸øÁv+BÅÛÍÒ×ûþ†ƒÝê`wRó-`6gýùrwÁQ‘W7H“C%·É]§‚lóR›Ç"{uçž>åa%B˜ÅNWº—õœ§E4Ä”´NT¼\_nÝ­õêFæ£Ê¥›ÖR):€J•Ó©”à Ùp›NUÈNK¼¸lÂý‰%0ÄœX|‚ûòºÞ;-DD„—Öm)•3šgK,z]”ªèfy­½Ë10ií®ÐØ»«½Ûƒ±®Êû>$«sýÜN^C›‹vhaßåÚBÐpM ·:’¸”»µ¸\c´ü«i¬-Äë8™³ÛôçÓH UN± $êŸ9š6ÍufO»@¾qR{¿¼‘g'R>3ª®sŸ`*Z^tR-’}Yab7·Nºáþîûçÿînvff ‡¯ŒVÆûƒ[6߯Îû-ϵ?89”…w¨h·w@ôÊ;œòÅëø þè‡+§ž[Pîåøš\‡Ì‰ ù"hj×ËÍ&:ëVÛp½9Áå*Œg³Š‚PPìŽ^iªÇÙj½^©Œ³oK‹R{†mm‡èhýšÄ,Ó.jîÒ¶&SMc¶NF‡”îßÚý$E®“j¹ *cSå÷=ØúV„2ŸÀTöîjÕ;i¾§$ï"ùZ8ù@;‘}Éízy8`¬¥£¥®ßºÓÊî,rZ„Pa¶¶\Ê5mk…o©¡hš²ñÜ #Ÿ¿ùâ_ö|“®c'Žky"#vVdˆ9bTužÀx]_T}tÂB;DÑî¾úJvš?É:w(J'Éý§?_ðïal(U\¯û\'l~s>ˆ¿c­Á‡›pì- ÒF&¨nJm*á'_¾»:@Z<ÿa‘„ûc‹5*µxÕ;÷×¼\­w.·¬âtP÷Ûµ;ƒ8\UaÂ1µ ‘ºkÒ•«“¥nŽN¾Z­oúø*Sá+†êpg ¨õQl¼ÍVÖƒ^Ÿ2ž¹…i÷nw¸}û>2?dm«#Q·é±[-ê@éS m¡ieEγÚp¶Jª‚߸ Û=¹žñÌDSoÜÜó¸v¿bJ½Þ'ç°Ô&Nªº?»Sô°Æ9“D‡vB »ÈÝ%ò"ÿê ƒäÕ„Ö Ê”@üœSqÑ^:m’%yEùY³U›¬ê ÁP±€FöÕÙ-½ëq/z@aW…èJWÛÕòDZFë.»ÝI3»x¶RÆûÛ=ì9SºŠÒÆq±êב­¤toy–¢3؃n¦¡Wv gb¿ŽËºÔÁá ‘Êךtk­ih…—°Mn6ÔŠjÓn\›R=û· ÖsS×± Q)#KøÙÛ‹ „ l‰¯®ÍÒ5Ø{v"WµÔǨ …Û¦žŽ¥¬â¶±bÓg?œFŸ®éô½0L¿¼;_mÏUÏͤ¡Á:þìªÛí¥> yD‹<_Ï£»±Mͽ>·m]X fÓg'’`Ät¸ÖÉPçía‡¡¿ÑCÒvj£u°nÝÈ/ð?% Ž&øbùMMHEOÙ¤R«s›êOK.ÈTš®¬(˱`W{•xz5ifÅîÍýÕú wB5ý´ü(w2åÄÉü°];lJ–¸{Yv"¥¹õv­oðÁ—ð¥\»ÝBMÙÏ&W^ß™@Žï`p6JCÌ’NŸÝïmy€Ùö¨õ+ýÛ>opäøïG?o’È×Vö‚†VÉs¸ÈÉßÓ¤Û$jå×ÍnÞì©ìÊ$À­ÅJ¼ »yÞòMº k|i_«t†œ (Ì ”uÉpœTþÃÌ:ÿDw1õ €"h {Õfε×Ñ–óö3} WQŒÊÅR¯c™™ ÇüæOèmf¨l*­Œ¸•˸-˜žäÑû·ýáùwÛÛ篶í÷ þF˜Ò wö^ÝPQ‡(}œ.fê 6Y­ENvðˆ»Ü-oÄ0mÛË­~i3v,¾ÝTÖiè-'·;L÷]UÌ™àŽ¡R›YäÕ2ËížNvµA‘Zr`; KuÜLáêýþ• £$FáÄ<›|¼»I~íÖ玖XgãõÇ—ß?–á{XNÜ‘rHtn1ʧ iÝü{•<(ˆ¤HŠœ X¦pµ\öïi¼gÜ‚b`hþ£á$ÕƒÃIJ˜`pä…8ÛSo¦;4Œÿžœþÿ-XMôÕü1e£y®fŒÊg?ç´„”Ïå| ‡‹üÇw»9Çuð æ§rB·“ét ˜Ùçñ¯€G¯øÜ¡Kyóˆç1÷˜çÑ‹çò²™}nÁ? ¬êf¡x¢Y¨ Ä׺;{‘žið£âgZ0œðžÂàÏüá BÓŸ9Hˆ%~Äc<¥ó\à’RêÞçB¤'†#æ&¦z¢‰iÒŽ“'?Óyõk*\Kñvªñ爉©:6ý¹ã4G<&q=x®uJ.G ëî}nÁR?/¬þDó"}QÅòSl™Æ”ïL ð¦×Nˤ'"K¾Æ5nÃí³\{±ëו Ö§æ1GC•=æ9§ 6|®‘_$E<ÈíÓ-~:d°9ÈùpQÐ!¦s—œë€«98Þ]q¬2AÑÞ>R´·í­Šöú $_3ŒÆÁ)kñÛeÓ;2)-ˆŸ¿K$¹<â¹¶”Ï‚Ûoö¹‹üv*”ŸjH³ÔÄ/Ú6ã§¿ ãL!a´zÔƒ5Dx0Ot“ŠQÖJÍ(œ¥6FnЛ' ’iP ¥K0Ç#qP˜8ßÎP”O!øæÇÈ>ø@ uÝHvOµ|aèø;ˆyÏ#d£„Pàƒ• Rù)Ç5‡œÁÉÈçű·MŠ…ür’bá1R,<âA x°R•ÙçF¸Ke¦Enz2wq©Ò§ pã‰T(GR%ÐL'ÉK*Ì”3 ÍÑYÙæòîÏ^À]+Ò›5®fÖ<GTã8–O0Ž•¹¸Ù†uÒç® ¦,=ÜhZÌ “Z}k÷Ã*ñV•ØÊŠ¡­Œ¿W GÛ×ðU݈+êns¹`ù‘¹Ñ.|¶Dn›Ç=Ø BÝÌ_$â§ Õéeð•ºyúTR·U©[Œ b,a@bwÕÆÊòhµçJûµ±uyP‚•£#å#4s[æ„´*ºŸnB:UŒ‹±ñŒ%¼äæÒ]Þ]œ-ïüñÈMPµÒþgo„Ê=æA$kÉu÷(yñcE«{Jö<{²AomŒm()Š&ô³µ÷ÐQaå§•Œê"­ä°Ë nº=Ç`Ÿìݲìׄ9Þ\Nô‘ì1º.‚=ð "3|±np°2“–ùS âݛ𢦿‚2qÙŸáàjòc…$…ßøaÇ?_Øñ1ŽÙS˜^d̘µXéÉî•«ç¿YÞÝHŠ4°gI¨†(p‰†[ȓǮ±®“n|ö̰VR¹´°®âÑ2!Õ<ÑÑ•Ç#CK xÙ™Ëì†èîc›=òl(ryÁcbNõ Ó*ñ Œ{abð©.[9pÎJɾÙnL×ï¶çýÿÅ¿/Xvä… a¢åcœP{Ôƒp€óAÆSÞSÛòíe`K™O6°äP“ù}¿¼Û¬6¬Esì Òe©¼ä³‡5¯÷`œ-~VÑ~êÁî c[¥O½h¬ ø:Ûåplëc ÛÇØòúqÊØR þ¼±5AüfŽ-rö™cë>\?´ÕÑÚ8êGN„ß?êÁ&ï쫲O>¸`0¶µ Û'Û¦(c»„#ì‰Ç¶yŒ¤ÅØ>æAŽ­|Õçm£ò¶xŠ =Ƕ…`‚¾¢c»ïß¶» ޽´P&´•·y2¡ý|yÛª¼}±…`BííòݵÙòØW u¾â³G6M÷`“ÙGÕå§\°J4¶íS¯Û"­2aÿãþÿºê—ç½_»eý$ñò¦GÄ<êAÄðAø´g\° lW=ñ¢-ÑÒöìîâ ê_îú»~Á’#‚½ä³—m•?îÁÆ)6òY ¹MÉþg¢ö©L'EFQÛGÖ‹Ú£o NÔò%µz¢V>ë³D-™[×`™ëg»GtæE ™æR4(Ý!bneéŽ]—ËÈE¬»ž°U•Ø¿H%yqqC, Q!qßõ›iÙ’ùÑNò‰Á¤³x‚•r­ä¤OTé+U‡ì•Ǧê§÷-ø{¤íU²KžÂY%¥±¨{ÓPÀôÏ7»íÙº¿¹@NÍÖùÑæ´Æm´ÿÙþ4·ìó¬wxŽÆ;¿¸Û\Kø‘Ç‹+ëc ÁYê¤Gõ éÇТàsˆr渚}ªÐ; {—HÜÿj¹?$oÖËÏÜ¥.y‘|ÛXþ lŽŽO ÷ù‹ ;û1Ïag㹇íìÚáS )“žúÌSiR€æx çâ»kÆÖ-øÓ‘G0¡!“ô˜çª²yÔs]]ð9`D²,ZâIÚ§u$Ʊ“E b^n®–›Ëäå³DàÙ™aßï’8=¥y‚ ~ÀRÃ}Ìs݇j¸­‰ç§pq^.Âut¿î `ºéŽÖ¦€Ñ=FV»Óÿ1ϵMÎç­73ºitÍîLR?Y,$ðùœóo@µgÕ ±¾<úB†ÃEÞò™ã’Èø2±â12±> ±"U]>…•NÀ¡Tf%1aû¿.øç#b@eŸ/O™Gôˆç$è12èJ¼'(Sa_þ¯7K•ÿ=ÌR³Ö'·þ€bjÁ§¨ikhtlÓïI°E‹²æï@cЋ¢¨²ä6*c ¬“›€÷lÊ’ÐVП—W k¥7á;¡«j®P…dƒgˆWDÞïâ{wîNP±µKƒ,vn©HÚgÄÿ2tnPz”^k…Èx¾ÇÊó¶Õò¼›ÃLž¡—<$KbÓÕ€o¨f˜VoŒã£©d`xQüR˜lÖFÔc*HšK×]óo¿CÏ=«À$öö÷‹¤ ˜vU&jY–x®À¬WLMTǵp˜¨Ø)³Ž¥14ª"`gÒñL‡À¨Ä9STV9’»%ëzúªSBª9 +›ˆT[è8GëUf¢ûvm‘–Reóg vn«¬œ窶sê´Ð]oÜFÞ­–ë$@} ÖiŒwj«§mô½¼Lƒ}Lm`-†2@¨r.˜ªY[\ª%Q!ÝFÄ@ȯ]¡¿ YuÕƒ}+†ô¬l7è{0ú‚`¨j:ø“M|ÐuñË}Xà– ¤tAÂ"(paײ Ï €ìîAxxèÝ¢@ù¡“•“ž‚0€³xºR戫ÊIFŸB¤.µÙŽ V²€ÉÉîGèP0®ù°í¶J‹‘æôÞà‡u±&ÈÙ7,Œpãma©|·[õ²Ä¬ºà6¥Œó«ˆ’ññNh"fØá 7Z™‹Ù¸“r²/wË;~¶:Ù*ÍR¼«,ÆŠDv çPÞS'GåÉ\;qKN“…²Ìrc’q ÕF‚ã×™Á×á„—hF7WN}¾ãì ûY1P ÝßÜ?ªu¤µT¢ÃNArÛ1ƒ°=ò€qk¢œûÈÊ©•2à5N‰•BŠŠ& êdP\f•¯T2D`ß9ysËÎó×®«M`ä!PÁ®ëßÐG@È%H/y< 5ÈÌV‡¤Æ6#0¢Iˆ&»çbÿ8÷ÌaæÉ£Ré –?ƒß…»Ì\-¥ 9$ ˆ2<^>m'äqËõœÇHℵœܺ,Y°çÖ 4"[g€,Od3º'‚ ÿ=HJ¿\mäX…‚àô_¬V6g‰º gËÚ{¯î/Þþxs¶]ë_Q ›¾Ð/è@EãvÄN Af²ÁËÝüì–á9Å5CR¯Ò &Á$Êhмç©ýŒXïtõdÓXï"Ad/±'?Œyb9àÏ_˜Mа+Ý«7æß–?b»ðqÝû­4ˆæã ó¸aE ÝÓ«…oð žnXÕâûƒ²$è˜ Ð”_ÞòW®]ŒW›ÕG˜SüŽ…Èì‹™!+žlÈ\ÇÓ”9ã1‰ùk³aÊÃ#/ZÊÚÔà´Ùl”¨PMˆ­’:EøÜòÁàʆpÏæãŒ¦r‹ºóà’ºPùb–0ãîo£KvÀ ÇJÒš|Äj³ð u-•¿o–¸2+¡X \šš÷)ÅoC! éqËüëJÄ`6ê¢ÔWº•µ¢™LéˆIǃ†‡v2¥ïÆ{ ŒsÅöwC6c¼]:÷‡Ýår³Ú Ÿg½)íB$ÈC¬Ò™ðrĹ}W7ùo¿û"{ñö‹üÅŸ~Ý.ø“ˆIšØØËø—ã$• 9Õ.`œ÷™¶°þ#VÂåîîö¶ßü*\ÅR?Z€%<½úÑ‚ôĹ¿[QÖ¹VY—ƒc0v%F“?S%žè°Pn*vm­¤Ä¿Ý®ä,TLüšŒ3µ²Ø¾¹Úp¾½rí-ÈÝÉÕ éÏ&àßÖéó•>VpÞiž§Ù‘£”åD¢ÀÕ0p…Ù& ˜`(xÕ‡{VÄØDMÈžîšäD®¨,c2±ý2ЭÂ]YDD­=Nð6v «Æúè~Ѝ(wáûدå„Ä| õ¨UíFáçXÕyJ–[¬êW_ÿ:,±ªI{“ûU]„U-??éªvý¯ê\W5aP 9ójõüßú÷bq4îfpµ°ÂG½2ñ\i1(¹žƒYïˆåœ‚üb:>42þQ4{Y¯Ì-s£ 3›TÂqr “`2ß'yÝåZäË»‹Ëþly'ֵܬk]a3;îÿ8[=_cäþ98 ¿ÞsðµC©ß7X÷å~ìqë>ûY¤y?Í‹_üšÒ|ˆ„û˜uyÍ‚47yÏÙÓJs!‚õßMÐÛ›[Ná¯Efï]ʺdë¡Ù÷1K6«ôÓ`í:I°8ãEˆrX·;'þVN¥Þˆ=¡<~ äD‹yò%RZ’ã¨ó§8Zô!×ûÈtåʲ ~º% ªœÄ¢¤:x¿¢0È”|‚z!‹á |³zp†$_µU­åCÑgG&oµ|p–¿’@'†¡ˆ„œ§¯«¥hö,7»@£Ï ºÎÈëj|:e_NðÜ»ì%Ó÷wi«³Tš˜^ÊÊÂSAF†ò±A€k©ps]b-½"×*ÿç~OPƼK%¨"c JÈgâ*õaµ#=·Rá•áƒð3]õwb"RÑ^çÚ¬§’R'hÝjÁÄѸÅ" Ž/² ¨Ï œyĦÿwîe!u8Ë}¿†ŒçyÔ‹“¼_‹ÅûwõÊSó€1lX:HVá‹Ò§C‡ ~îC'¾#PLÊêæMûG¢*¿×y4Ø)mÏ›½™5¦Ê;©5˜ôB[ÃðÕªÎì{žÅ–”RRÊ&Ì­ÜçÚûxí2¯4Úõ”V¸¥ºíÉÔjá e®•+ ­H=ʪJ{XÈ~ÛI4ç+¥í.ÌEß‚L •ÉfÕج-¢5 ër%T¿1•`?Šƒ%ör•f¼‡ŽL]VR—7æóÕåÊIAé¶Ý© €ˆ)p÷xŽío$Èj…q„a_°:,þZc̰`YîÞ}ZhëÐù¾xýü»þÝÕf»Þ^r– [Û g½Á¢0˜ƫŒ\­v¯á.µ~<whlòW»É èx¨RÓ¨»_$uDVcÂÔîÊÝê†Q©²–Í&ÜH-Hrq‹#[G¿ÑF"~O%l«J)A0Í»%–YmJt*%ÌìYLv-d_-図Õá…Xì쌱΀–ï„Þ‡]v8 D}G¸9si½¦Ÿ³x ?'ŽCùÕïlÍT­ýî¦í7nÐW›Ø2I$%ŽjÄÕ®ee›Ú"*|4b- ˆF…k…8•TZ,7L\êãC³«µç'ðͱ}]Ø ùæÈi<]Žz"Az“o¢Ë«µëàž¯6ËBåÛÈÑïhÈ4²¢µ—@v¸A÷몃ÚÜÐÁꃂDt]Jpo÷$òuXß¿sKn/kΟU…> ëàrN66OöƬi•Îõ`ԼΠ)ÈÞŽ©y«J†×ã?1ª6¸Lú ó‘:D$ÔÞ¦ÒÛû‘B´Ö@Œ€;BA7&¶þ<õì¹Ö âkÆ#Œe/íIîÈîʈ÷~wã麹“ïóöù¿ßù$®DÍðâ#Ä,,7\_Nغ¿üæë¯¾ž«Î•È0åtÖîÃöã\ù©4Sµ'ÿ[°ˆË±~x]jE¨ËƒfR-«³`( çCeñ›âÝný6¹§”V¥Qj OrgïòNüm¼”kqîN‘@¼·½Zh\=´Öƒ¶·¢3MUH‚r œ³BSª&’¢‘„¯ |ŒYZ¤Ö)Ñ.¸È¢+¨?å{Ê e8ü¼|šüwWnXd{ªöZË¡%ýfy%Q^±)ôq9¢SÞȼ·IÛ€$ÐÈRÓuJ}ž‚?õeÆ»R; ˆÌaPgf%%¢:ƒNAþb½@o“iã„ —8£ÊÌ›vÂÿŽ\™®¿iœÏ#×_& ònüñÔiË»‹ÓþÕwož¿eÚlrØö§ïÎOÏ4žé´?¿K~8Éòö´ÈO`;u[E·wg/˜Š|ÓŸ¯–/nnûKþß¿ÂÃîTýs­ñmO1mv*ðØ¡h¹áô÷ßàúhgž‘…,*¹aüÌ"ÓU;'å;:×öÃöj9sàÃGéÀofƒŒXâ¾Ûÿè®Û‡õ:^4Ê £µiDpl·Å´‘’øZlÖ\êï{«\ÍðÚ–ëÑ{‹Ô.f|/ 1UTäÈÊÚJÇ V…˾_]nz5*x­XZÁ±ö%9˜Û OØs0®€ÊÍ+ah£>—TÓV¬1´˜U ¿ÂeêŽéíî\Írz ãNu «dô³ç…‡S϶yB—ÂÍÑ `m|¤ìiå¥e:¹?ôûˆ3=÷aRe†qÜ4hø»}'^Þ]|XRo÷}èÁâÊ#ÚkðFžœ£'ÚyÝ{[5à(j»Ôõzò2š“h=6]®íäÃÛqhè³´’†èo—X¯ìeq¶…4Qrv‚ê,7lSkÊ\Aª.ÿ¢[ø\„¸Jy c¤®¹ÑÔ)ÝVësZ!ó»|É4W¢cR-ÍNiÚnþsfƆ\¹ë뵘&̨[²`f è»asFi×5L­n¤‰ñü·TÖ±8È"µÊvY« —¸¢Mò,Ü(•úk÷ÔwýjÍÜ›Ä×d)€‘t©3(¿ˆ*ó%V,(2õÝ=·²$à×n\PI,k˽-]uÃàF1Ì–¸Æ<©o+ñB}é.egÄ!oJL×ù‡‡d¸RøtËd ¹¯í-bÌV*6+;ÇÈ*ñ>Z˜%N–á& ²ƒÛÛAÞ"0,“7øÖ&ú¬W#ΦY«œ5N ƒÜ®tD4k3œÎˆÏ;Þ¿üý@H¤n³>Š™mugyX­¼M‡°ÝY±®Åø6L˜Ñïë*ysî ö肇²k,þ ¬Ç0ŽÉK†#ÜTý?*?J·üQ1/KQqW86ÌÙ¯vË Àm„4 ¬qƒ‰JAéê†íGxoÝe´M$’ÚÍÔoNÝ>_Œ“ìc¢î ùT³P›fà¶ncЂ· ÎRU Üæ…Xií’ÜJDãù2 Y©]*óñ¸0:IñȰ­§5“ÈX^Ò×°[/©Ô™°n3k6­ß#“'Ú¼ðL²4Ú€¦,3E¼¼½í?®.V×>.²ŽÔá{Z(öÀW³U; ­±eÚ{úU÷¸ï,½­Ë ûú£³?ôb«|аVÀÁÊ„°H!vŠ!’‡ó±ìㆆ«ËBI«îþ¼„ÏÊŠhq·IÒ8b5Ç<=zÑBÏã'ዞ%¢H™ ÌEŽSÂjó"ÈEœaæùå½ñÊÜr”ëZ‡w¾žñynkÓÖF–΃ÅóÙ ðW+õp }¼ƒc?ÌLfÒ7$ë>bì(ˆ×ËþÆUpÖ#\Ãqd±R‘QÙ¼»ÚmÝéãýxæÿíêÚÞ5“lÌË ÆìÈòRË”x‡=¼¸öËø7Ñ1RtÚúT¯-ýg`Û~?‚É‹®A ³+xÂIšˆÜV[;¨ôÝ’ÎçÍR›HŸ× tcl© ©Œ´ø&BšEÑhi´=Õ]Uµöœe“ó9 Òéô9Ø FôC ^.)—¬uf¡~ž.¯´ñÁ;3±TæÚzW {üI;A:(ò[‡KLü}ó눵¯”©Î¥}1P‹Þã(uН¬¹ÔPv«RŸö×2sjµ™õŽUC°¸_6Ö‰Ýp²*z’J%²ô²8#­»áËÕ†Øk´$è]«Â(Û%§’‚ÉÒ¬0vï¯.‘œÚµR-ZhÆ3¡UDÌÏòˆ'ˆYÔσ—“ÕÇIûÌ ÒŸfz_Xq!‘r,´×Kq¹úùBγ§n© 1)‰Ô¿:ï¤ äfð>­ E̬é#ÿ¼“b­!êFÕ¦wW«þ\´êcÏKI¿Á¢GíÒr!*-ÎkMïÚEÇvUÖR ½àä»ýíN)’¼ ´‘–8­.}¯~_„TˆŽãmjŸ‰X¥û9éìý9}´àn¿¼æu„÷2›%ˆžk„ùoìY,›,´ÙüR Õà›à±öv–¼ Q@•çL´–óÜ’ãBˆ–$ýàŽ„Û.SId7: ½wíøý‰| ¡à¨ÄœNsòIbòaÉ¥ Û¸ˆÖ8_(ËÚód€Õ<´_8Þ²šší=qÁ²ã4 I4qÇ5ŽÜ¯¼=Ù<»µF’D R”º’V Šj…fÈ+‹jÐg™ÂüxmÐàh ÿO®þæm5[®S!²Ð¹’û¥RŽ.§&zpi˜í6AVä•pNz µÈSÖZcdÅȽÅG;ʺ=¯nÍþg¢©±‘éZ{ƒ3=›~a¡±ùÔrï‚E3‡lüIf±i´_˜ ñxß³dú NââêáEvç¹áÔÞ£6ºÚÕ8“Y±»~Ý¿‡ÃNR»ôR§ZeV)èÌÎU¥ÖœØíwƒ„Lf²N§ß¹ó0 ¹x®¤T,œLšdV¥·”)2Ê0â,3#Mª_NbŸo‰,2¶ £¬i¾¼Šuš@4šÎå&Íiµ4Xè’(„9Et†#S€°?ÿvw³Ú,7ÌbU¿"Ò@X!x…Ä7Áípò…Sråéç/ÝðÃZ‚cØÌºi¦ípÈ ÎÁIÉó° *X¬¥TrHw =‹Ô ɨ–Xçä´y„iÍô]1=¬ÅXÈ‹F¯õ4öšŒ1‡Ãè¼ÔÍ”î“Û«°CL¡-…üTàJD=R}ÿº§jqåmm¹ K«ÕéY³îa¹Gè‚?G’óQÑs)3kÄe^z—y–“#T¯ž$ª®häcTçÕ0¦ù;Ö;¢š’(t°”Ì‚§¶›ñK¸ÝCÄiF“2ËGÖ‡Æ[5 ©…aÚU͉+›…Љ—ȾÞÀ,B÷⌶žõÁqýùÝÇp××{AÅlÈ>ˆ©N¾Z^DV%½©©€åÿ°8 ",Ô(Â1ù:¾Ãv$y—†?W²Ô^»ƒÍ‹Ukwƒ´óÈÇ(jÄÐ>Ôû´®lò­Ksm6ïÆÞ±`³“tžš©÷ôpøgNÿ,‰P{w×0Æ]D 0Èêrw¢Ü<}ž¥©Ê…¼É¿;—˜ ‰“ª{ýíc¾!5$*N‚ìÜ¢Zô»+ŒŽî÷³õöݵ?Í‹O픈’Å=‡‰´@xÖë/¾{þÝn¹Ùã¤Á´,øû‘›¬+;ùxÜGd ä÷o܇Ú0‘¾,|ª¸ ½^í¯w=¶ˆ­5ŽxÁ4à YJûÕF`³¢«ËqŒžøVðB;[ÿÕ€gÊaÂýaA#¯àÐË FÍÈÝb×´M–ˆe_ñ æÑ¥/@Tˆ”‘]—éëR5H¯‚ºþŸ ñv¬.·Š(k¾}΄ät }hqOÞ¬þÚ¯¹“oë–»6A³8,‹«›Íïó÷ö¬±×À›Í#+Š„@ lÆÐ719äCÜŒÅ,¡»Þ5 8ÜL9ÖzuVI½gn×_I›ÀqŒ ø¡Ën€a¶“ë92Ò²½¯‰ ÞFi3ÿÕ®ÿË]¿ù¸TÝ‚Íø°Ý¬ÖgÕ0z¢] +ío|™-—Qû( ös¼uU#EÁ%Ýy_¤69ëmÉ™ÙÚ5ãm®ëB„i‡Õ¢û³ÅîtR2:Uƒ¯J‹a}ð‡_æoí,%“'ϵë s1*…D¾U¥'ôoûÃGÙ'Þç^èk†ºRe¨õ¹¾h¢õ»ëŠ6L|›¿>MÖ’šuàüË›]±“ Ì¡¿?¤úâö²ªÕÔÛçÔ-«I]¨¡6º‘"ËY…£”5`Ä Ý|-6-¥Î ¤É íÄÕ§³îEʲ&²Zß ì )ŒxfÒtjVsë<çøåÝeß!¥c¯µ¨ŠÂ¾ rèæјv´Ì SúÞ¯Dáö@eªo˜ÅÖºt)—¸ö ·¿ þÕOO]·º2еºÖh÷«§«d>®kÌJÄh̼ ·ºÑj£¿,ͯˆ l:‘¹>RàNŽSúwÛþ‚ª“^‹Ö_G´®­ÅM,Æ ºâº•A²}cö¢µà ­õÁHÚb1ÝïïÖëAŒƒ‚päršNƒÎ˜5]¾N#È-Ñ Õf5!ú´‘ÎÛL¯?fÝiqü]jÚ.©{r‘ßÃì^™+¤tTŒN±d®Cìaª>ª 1…†/-µ_Р‚ê¹?Ä·\ܼ¥Ö``M^qÖ• ìõx‚Íû_•õÂc… XK£ a2kéL(Ôä&#¬…ÆCÐjS‘³Âl‰P_Ø¡éÅ;‡žy.Õ¤EMb"¸Qúîî¶_ãäˆÔƒJÜô…ìüN^ºcQã>5 .¬µ_–—˜!48‚‘(GpSA0Î">‹ŽÈ´ó0¢ÅY2È*i ßáô—bQ[@6f Ü6®+’ãÃ$òRß2Y9§ƒY€šÙŽ.’¶Û˜eÔΜ•Ý&} ‰i‘ i›ÓÒ~FNËëÖ­Öý9sZò®[Ž ¤ÏAÙÙÐåºר¢-¤„&ÖÑ1gb<Ó:˜NÊ¥–›KaÈf©,òG_ 3éäLÆ—6Ý7ö‡’yb¡ZÌ0ÒÌàØ`× ÔušÒ‚,½½ qÍ¢'òoœŠ)^‹}äª[“Ggªµ#° Éuu&è%•w±jgJ†Ó ÎrΚZ;=ü•$üy¡díÂôñòîbm@tI]èèÑoˆèpXûœ7\¦«Š8"û·Þæü‡ÅÿÎ;õWËÝ™hÜ •· ÃÚ–w®˜È#r§¸ë¨© ¯`¥4F&³!÷±¹XS«Õ¹XÄ?Oìå*m=J¨2ÕQS‚B/ú.$LjËÍÈÁž@õ¶²–kE³K¨åp ¶DpB[ãu;ÌÆôÐßþy¢ÖÓòræ+™¿92·†0egÏCÿø3¿½xwe Þ–øØe!÷j¨û7~dâÍÙx­¿¼gܲ.·œ0\޽[Þ1hÇ¢žÓJg -pBöœ¥aåˆ3ÀºU…W bšD×X²Vð1Jm΂œiô_Ãî1¨L2}Ÿí«eªÊê ·ê€t…>Ç ¹œ„§±Êh-V€úDI«ÜÆ‹,ä,ëpa‹œK«Y ,I Ó¬¹Öæðk+Í_ÃQï®ú’@a-ik¥C×k1œò,æ1ü~»‰õ=KßÀ¦dU.5îl9H³`3¸¼}¹9ìÝÍš¢.‰ð—`š•h½«Çtx n°,¤-z>‹Ìúˆ[‚J_¨õ×2jk¹Ë|ügÅHËŸ·hv28ã±–V[Õ¡ÌœdcC§÷GŽ]´xÝÖÓ§± ÝÜVË£ƒAˆ îIWÉv‘ÈÚx7êûÿ.rõó ¹£⚤ùGHˆk:¹ÌO‚†ÔdÃ:vø7.èC8¥.¦‡jÖ²j˘΋`ÅcÌ 8Ñ{a€1‚xC^Å’È…ŠÒ/×þK›q’—€aØD£›oB|§aoU«S}mJƒ×fƒÖäu(ô^xsz•Òv°8 ½ˆs@$È%œï..ÜôEqÇG„vd:òCZKÏ«!‰| 3ñÊœ°ÝmoW}[k`ÝÛLÓÈ5VÉvÁ! ö(òA0•Þ¶‰PÚŒxv#(X6€ˆQ§ “RçØ[J,‡ª–ç#1ô¨iS©4˜IµvZ9Ž< »6ù‹5t;Ô éôÛþÜ®æºØØF‘ŠCæQ‰q³û‰›T Óxå>˜rUH 4ðˆ•àBKuSôõsëKƒÝkž‡ ´ü!—h·ä)d¦`dÕ¡œÀ>î:L¹ney{¡8–? Â¥‚SGãm´3%RíªrÄXj}ØœŠq±”©U àlX\‡Ô0I 1ïU.å¹fŠ£!wrÝP w›Ó”†ƒhžXè*!“úÁ<>;“ÇSqSÆLcüNèÞ’œ¥êœä ”5°,þÝ›ëÝ>”qé‚b5| ñÝYd3Ø\ÍÑd1x’Iwû~}¶?DjºDå$!M ˜×¸ÝÂÅš¼†Àäš•µ•}×ÿ¡ ®¦A[ØÏoâ…kŽ$XÁ/à€ov=Ž{Ë3å ÙUhp|\½±*ä:–>õúÍSö¾ ØsÖ·ü}&¾I5•ìÜÒƒ 2µ–BžÊ¯‚8WÓ "3›t”¥î–‚p:)÷R#t$HÔï>Ú1¸6ÌÇ, L]âÿèô pjà…A`0…KE¡tR Ô­n§Ô¼µÚ'0uf)f=™M)ßKµØ]Å/w«‹ ucYÒAZj÷‡u «¨ZO·¯nîöûøV˜툽F¢R£Œ;$G…sÇÌ6eÊ’€S®Öy†+ÀïŒî‚ØlM;ó6ÌÁše*É4c! ø}¯Q.¥™ka~á;¤€™O•R&,@rѱ½·@Q5òY!Ë¢œèn,‰ÔMòB‚5ŒÏrké)ƒÕ¾~fËSÔܛЫ=°&/øã‘‚@’s‘¯¦r ,–ƒÎ‰W«ó•» @þúÇç· +• •ê;’Ηß#R¦8þ ÇZ†‹;)B4OÁ» ù¹¡ËôãÊ‚¾·Õ²̧{Qi<õSV˳sz·!­µ"a`õüØrÆcŠN”äMfËã;G8W„Iß!]wT§½°Í®Æ Ò¢œQSw*_l×—h" ‰‹½`Ó5¦YkHD$¦¨S³³'q¤õ»ðMI,«×Ú½Š¦‹sw§W‰nŸ¢òH¡ðfœTŸÌ5gŸþš$Êf„1$6Â0ÒK¼(&¨*©¡ò¥† ص¤«åÐ+ú«ÌSí9&l·Üõ0IrK‰Vþõò H¯™—Iµ”ǨyÇÃæ¦|k.†Û׺ c¼¥ÇDIB¡èzŒ“Ð*Óß±úÞÆÛM§_HœWC(ÿ5ʯÔg#às5H¡²n:Á»2wÝ$TU \k¾ßî5a¿¿½“õåÁ2ì ­ "z-1œ¹¬)¬»ãd˜êŒ¯\›û&ÓmŽ\Êàq\Ý,’²‹ÈÜ©¤¦>Æ“3O£^ tí˜&¨‡H0—G;"ÀìðÁ;1æéç’nFÞÞRaµ|æp¿{¼?ö¤LbÛiO:>Š–‰'ìî›R–ɶC–qƒ1?‡ÆtMRò*óh[*Ù–À¤¬·¤´Z›.ÄË! rù[´YÝê{¢ àÝT© òd¸lfU cl¯Tò˜U?+£oxÕ;-+˜44!sæ°($9±”ü­¥e ›yQ$R\6vpÆêP×hñ}°yÕæÂ_ºB_?ÍHg°;‹¢âyv;-k™OÅË™9IõÌ·[»-ü,žÍ"Óg1°‘hJÅ40Yã¾5—*ãKulzhíJËbÜ€,èV:š¥@<èù`©X¤ÁA…IÀ£ÐŒñR3à¤÷Cñ?ØòTs@ò€yaBG2dsWl/†Y œð´(nú>ŒÒ1¦¨K!7߸^˜(™+ë­9nåe•Èú¤%=<=¯r°Æýg€ åŒÁÏ5Eúl‡iV¿Ÿ9ÒLk0=y«Ãc"çÚ›íhÎ9DôéÇ—êmŠÕ¦L­8†Ë)|„¥¾_5Œêâ@ƉÙùü¥TÒ-gaaŠVó-'"’;Bò4ëØï¡¸à”¸†¬™Îp”g<T§Ñ´ÒÙ@KQjȰ¥J£÷‰2K•1/œ]g­Ðˆ—g!®W:J®ùÃ·Š `Rû¨¦ Ö§A }Ýjfi'“•ÍzãºåÎ’€Žß/tž–»¬Â cÀÒÊ\žž?SÁw7KýXº24û_-X¤Éúÿÿ?ÍApû…› ÄÍÅ›Øe0ðÝЛ}Ç©à…w˼¥gÆÎ}®Ù¹s´iÖãLnFPúp`~ð` æ@üÚ¿è‘v¢Äa1íDè9ÀP¥Yf¯|³¶¹à¡ÿFÍ6Ð>>Õ,ù}³o&ÍÎ÷¶&•Ú'šeÛ'z;ß,0a>Ù,<èŸ?„ ûd»²c>{2¸•?Ý0Õ¯Ï`ødä™üü†ëòo qVçŸckH¢' É“ŸXþܨ™ß¨äØBP].4ø+³Ï­ö2îž{gòXç|`X5VÙëàéf›ß¸F2dÄâ?ÏÝéV.’7o&‚n¹£÷9¿7éæ­!^ž;÷œLŽî¿¸äÌ‚54ù '–Ÿ»³#…íðÈÀtɸIÖ‘ÿâŸûjÎ|n!±›>×½Ìí‡çˆ€„ çÞÍhÐyÞBÚߪI¸ g>á9•9þÌlm mÉjwqxÐdÀ’ý ZJž»³ÿ-NòÉþ¹1ÖAq‚­¼¬ï9é^]‡ºÕÃÆ®Å-3l½«¥wõ=½úy†»æ7dŽuý·ÆÚ išˆ Fdì##Äüª¯j]õU«uó‡-{nÄÏ^ö3¯Ì¡Ò=è•Y[~ÞV{ìAK”3Š\vNñ?oÑ·6‘ïkmÖ1nÁÎÖ«¿ÜõÚö$]<()!šôòììÔ …¢hˆU;¨=¸8TªªcE$8+ÁqH8H–£Co³JE\é8T„†Ä( À ”P5û7zÎ$€°°”îJ+ øQÑjÙPœû¬R»ÉÀY#5àW¦ƒR.Öê¬É¬8V›=ªøÈºX5öˆ!äÿqe}Á£Ì·RÒ©á6v[2Ç…L·ŽXì4ùÀ¬ÎH[X¯T…uÿ×ßήЈñ“¡ $9f˳ùOÀŽX>Ç63^$gJKZ^m`Gð0õj»«”Rm VÃ\и,¶ŽMt'`Ä?ˇƎ*ØÁäõ3°°ªÒ§$cHK°g~"6d‹l)Z©‡@š?­bZœ2¯¢^ -A–”Ôè["r‹7¬uŒ¸p¯½Á¼lL|a™òfÈìr{Œ0YµŠ1Ó€\ PYó"Õ¥#Ö[›E•kaÇDýeïC^Í…f#^Z@e S»ò¼V£Õ;}2& 2„RŠÆC§l«ƒù(¼þË”O¢Ó4þë¸þlnÈa†è!ZbvKÜR”Y‰km$ì2»øYóƒ]fV¾<‹šž†4[N\üбù8O}ïá‹V>2_æÇ H‡Ø,¯Ÿ¿yn~¶Ó„‰ô†JÖ÷M"ð[É¿-$çAfù Õ°ƒ%ÍPÒÝÚzC$½`/X5:\Šã´XEˆ §È‚?g|’tGð1!§Xªƒö»cìIãð ˜a›'0h3)FÆÒI‚<‚CB¡ï¦Â†OÊ_Þ]üjÁZñ E2IÎCI&hôîÂêˆÎZ³1—Rî­“í¡Ÿ"qGØ–Wëg™Žš ;„”ð'9ËÑÑÖB"Ú‹5‘ñ~çÙƒ€ :Ä%ÖpäÀø–Ù®ïĽiäű–n¬ì BêZ¿UþøÖ1BLع K[ QÑèø"rã7+µ+ÞŽ/œ†æe“C»3Õ¢++}ŽI<Öü ÿ¥%ð“•Çž\ n…CppÕ±D4bfc:úÝ ®[©1”M¥ÏÂrurIÜ®>¸©=Bj®µ>t˜ÁbÌj;¥'ËÂס4Z`&…¬w~túh~ ×…ïÀ'3÷ºLßb M›jôf¡E‡:º0Ë2Ï"äSÓèNÙýj³y¿]¯ŸE]«ŠRk Auà™üˆÄó<‰ù¡uëVëþ¬Ä|FŒ6 ¾8† )T8¨ÔLj{ïtÖoVý9â“ ^ë‹Çˆ·y±Ü¶›(öY2ŽJäûžb0”mª¸C–›ñši¾ZƒöÉ«~µ¿E.âÔZ–à$w¼Äú¿L^yàÆ· ¿wÞWsoÞ×™T¯(sëÞô¯‰%ôg%Ok“öq®˜(…)õ$bòªå*²­ñâÌ £BÌ’1NÏ«V´ü-T‰ÚÜüBW6AéhIÒ<ÁòVhÓNÐ<®†>‰@ªÕÕ&º˜dÄÂH%|O$®–w·Àg ½VBð¹8[2êÍÓ* Åô!¡§‰)tdâ~KΓTt~±2ÞÄ:§]3j•…i¤:bs÷%" #®CÎû(|y|ÌÝžÞlÈ=Y] L„ú´¬*<Áº]¶Š/=†3õ,Sî¶Yh4‹”i$Ë,Xy}E©]y=l%xT«ÕÜ3–6ú‰¹»É³Ø‹Zd$÷ |±fLŒg›])aà‹qÞ%^áþû÷‡u”Ã9 íajäæìÝíVÝ’Œ*Ö†©ïnÿêµùÜd°Çt(å&›\ m+¹||V£E˜!iˆÌfLƒÀ‰°ÇÝ+‰àd€—]NÑ÷í†c¤l#­Ü3Ó«Úhù(ÄF‹+¢Ä@ä³  Êlæ¶h§üL‰kR05F2¬å]_n.˜‰’@¤œ.äáãŽs·zÁ¤Vð8o?uœ?Ø,V÷É­b°²DËä~¬ÇÙ¦Ê-bcù`¿íEbá{fã- /*ÏXÛÌI÷'y=ì{ÏI«t(t‰W ‹ÉvûU ôü¥»òöƒ¤Jäþ¢8 •5X0Pä5Ä9æõÃ5xˆ×pì?º»¦»ÄÄD!UB&‘©@;aûe¦(ÇÑöÇy`|zŸЋÌ&§ÂʘAúòj}áÔY7ç¾c6TšËµß S „̉´WtJl² Mº )$k”Õ w­íZ“\}fU)ÅL8¼ì¯ûÍæ#TçMXxZÈ‚¾º)aœKÖ,Pí 2_: ïÓ;1Œ®EÌ|ªF«†É)©°pS•wµÞ" W¸C-Oª´.UTŸ¯ÄÏ—8Žx–wd8ì–0„¢ûzVX÷Fúv›¬Ü÷5ƒl[u&_LOà8Ís-~/*ågMdöBcI0BD/p0è`Ì ‹HB¡Ãrwð¸ìê‹Câj«‚1ºÕü}¤9ÉÀ4nnXØä!»UŒ?ÆžZWú8¬w–BcWwÌK šu)XÆ>ØäP<ô|{Ê(é1GüÕêp±^^ Ô­Ï–.XA š^ù\½cBœ+$Y#Ä Ùn{­fdÛiÃR¬¶[mÈ®bV&„h¡ §áW®«€ë£­'Èþà´"D@m…÷ëu:r±SßsÎɨÃüäNJŸ·ÄEÒÎè æÔn¥¸¥¨;\öâ! V"@ü¶sÌ”–ŠU±x'¨e]Á2¬`ï–1(¾BÞŒd§÷N“½sëŒ/ö)£R.×Ð-&x3)U™ôŸËù¦†áRÕ¦M‡ù¦>‘BÆ ½Ï$û±É¼NjL!Ua0GÉ4v‚"Üú2á]UM’É•ôÏN§:°Ð©Å©É_¥Ì§ç‘ÇôVäÖ*KK‚4yjC 6p½di[‡üÁg‘18ƒ-5èàЋŽpÐ áË‹²Õ÷ ójm˜Sí6»;;Ö']zGOÎòd ·Åeò,¦AÂéèªmS²ÿZ¿$pÏÙºÍýg r»ìªSèƒÔßÇ Z’†â"Úœ.àhQíÁxy¢í ¸Ö‡-ø¥¨ðæ9¸CÏœëÜ¥aâãÎ5Ì;¾<<ÎÓ³)Á™_ªR.‘/V¹hlÆ1VêCÔž^Þ]\.wÓbª<— Qx²)6œ=Èära.d˜,ÛAH™Ý'!¬Ê©OÃ.y¹N€?…AhŠÚtœ²Éɬ(ý ‚‹«i "oŠ"€–³ö䶨ºY­åÑÑhÁu.E!j¥¶ƒ¯µF[7ý,¾ÓSEf b–lÔ:Øqò$™ëwбU{—P*ÀÍtòm¿rrSœD âe¡íOà L, †'ºã[ôAc>Až†9m}‚mÆËžИ—»Kž¶Ú÷Š€í½Ç†á$• i¨`Pƒ¸ÝkYLéaä§–^Õ†à«3–^Uó/ÄrHS! ñ3)r¼‘FQšMŠ#Ƽ²üïÜJad¦ôA8Zt/¹tÆ‹„iDô âõlÚo“,øŸ~¹`ÂÛ™3O>& HvR]•Ðàá_ "%ër–æs9øºÏàà{`]rðu?wúŠq™}2Äós¹Ì`µÐi×C¯52/Øaâ°YU  Šah¶¹º´å®˜ àá4>®2 M*É^ª­F$EÞ¬‚§‰¯,©[¯Wý™€ Úu ²I¸Ñ‘q×;Ò® iÓj¯ ¡[VÆ‚ÏvŸ§Eƒ…D˜®¶jí7õÅ…›È³èª‘Á « em ¸j!:~ºýñåÊh¥>⣳¿FËàÁíAªyŠžØÌTU°‹ ·’»ñ+È[¥pã!ßíÚ¸^»ãÈäüI³®¦þ³#²®0Úäð5„ŸÊÒ±²*ÒÆÕÚŒ8 )c‹H ôÓ#S¯†Ìe íR øÞò(.< ÕÒ\tF1†ìÒÍò@œa˜ÛZKS¥ð"SÝ~{±•»´y̰De‚]kLe覕g¬ (ˆ±åµ iÍlÞ Xª6·…¤Z÷ú9ŒÏÚ/iŸ¡­ŸB’x‰i=µ­>Œ}¸—0SsÕ:Èu+KÝoQŸ>oA{aþeÝÀh›|u‹C>C‘»ªŽJkÿ{Pƒ©UïgMüê’î$ñ çôëe8 EÔÎDGƒÛ’)L»sråc¿¶+¥nj5Cj6±÷,Å®}¿Ü­–gë8*‚FúPGà[>$8:40ÂääÎLåc´+ô~>OÇ€q¯Ø­ ÍF_e;ð"¥×1…•É ëTÃÄŠþf¥Â#x7úÒ6U>¿Óâšçˆ‹žNè`ׇëçÁ§}Æánbf—*•â å‚ó™dáí›wW»ífµçmuÿao [[zVÆR³¯Z±;œ÷wÑ)Ì‘f¼b^q– @TøÌª¡I£,+y®ñ̈òÞr—KgqÈf+l²v˜.fÙ^o-ôòw.Ç›÷·ÚS*ñØN¦×y™ôv.ÍNR †Þ<îLK1? ³agXî-zf6Y©‰Wí.0b0± Ž”ç1d\NCM7ËÉ:Æ6·”2u´úhé y\~7¢pÏ}(„¦‹ â¬ÍÒ—5ã‰,TL”+òY¾\gË"¸2V`;™‡h+L©H%s «Wäb~wÝ‹c¿6²ßœU`eãi‰SÐ#þä¶Ša'@5MÝÄ õaAîx®ÒÑ*3¸„¡°ÓX¶$¸i ·;Ù9RPSWÿ!R‘ånµ[ZÉ}®H¸Y) žµÄÇ\–Ò-Ùwô¨®õnߘ„°&h=[J*I¢*£ºCîî¡W«­~\:1en4ë¾Q©I‰ Pß)µ]\À´KòƸÛÅÑ@]Ö1Ÿ®D"±Ïò}y¸zú8ÙÂ/˜«åMhű^/7›¹ FSFSg,Éq¾÷tä²Rsï%Æt5TŸÝA!Xûg`í+ZøÙÀ H™¿À½0# Ëð\öœï«0sþ$¸ÈkKÝÞÆÛÕá.ò¢fZÓ¶+¢†OcÉ‘:IQ,Q¶SÜçÖãP戥c!NùKÄ({OžùÙËFŸ{ò,‹ªLY>ÜnžüX3ã±£~KTÒ4©¹ÚÏ~<ôEnzu+­ÃaæÄðÀaæ3¯âͨL¬%æv!<ûf…naªKeº.Ò0´sÙcv)H+i' ß÷$^R2Ãò˜\…æÓaWé¥Ç<4%PŠthY'„%ä’Õ–CZìý¹nþ@K~Crç0iÏ µ9ÈP$m¯Ú[X­d¦U’UôvµÙ¬·{åè H8­E*z?(Ú'0`¥±;Q×t ú¯¹ÀÌ.µ6+l†”„;V­1‹ Ù)}&÷n»<·Ü" ƒŠ NÀ>y{»^]GûɬÆÈ`;Sh,sc»KÏÚ“ítÁEÅ 4ØJ˜ÈW}ÂjØÆá‘*'@‰Á«¡7MÓ‹À<ÆHÿ:˜„òÂGÐjæWGÞò•O/4 ¬Jl¢ÎŒëèdt'é-CÞ›™%pÂTúá1!$ ÇG¯Ë'D@§°`ÏÍ7 W¢|^*rMI:%ÍËSݧ3ÉkfJµp̃F¹ÜjäèX.K2ùÆ¡¤Þ¨QÖ)y£II!Tš4gøì 8 –g®(¬¸´Ý,/Oq’f…—|š“…‹Š\­_Þ¯èù¶T´´Ôܱ˜VŽVü¶9žÕAóôùRŒ£k2 ;º´|!ØLN¾Á–¿€çjpWZGISÞ¸žVUi¤eJ¶Þ]CX™ð—šmážLÍòÑY6óCOMV·€Xl@S$ÓÜ-/!›.þoØDÂ+ƒ$Wl 3?v¥¶¨b,¢ðÑR3¤hvr:¦p÷†HZ‡aŒPìS¨‚;I1‰oÌÌ%Ü/ÿzp÷Ç 1©YÊ" %«hæ“Ü!¹Y·ßºƒj{ó!´a»¦ÂÀ&§ Å¡Œ–0‚OM ¢hNe¡XAYœc§™O9³Dúݵ²–ɤ]ù"‡ó¥ÓÒ/ÏVj"´r‹Ù¾ÃLy~Å‹ƒY(C®”©'§Áþ}Tøm^}FøíƒBe5ÁIWì[·µúhþ˜'ÃÒ'Å­$›©`÷çR?è+à÷ÍŒfÂi¶ï°7·ï®y»RË®ÿЙOa äkGJë´*¦É;þFaN"X¿Ï¸d…@ì¾Ì ÉW{º/$c%?‘i[gH/{•¿’èL ViƒG¡ œ¡aJp qˆz¼`ÑÕÌã’éBš2Ó1wƒ30áaËSÉ´+˜Î ™÷û¼1D Ým¢‹²Ô„¬±ë¸ì4‹)Kä°ãÙ§–K³ŠhoU:æú\ÁU™ªüIΣÆÅYFN.Z~‚‰üaÂÓÈ£ëZ’âß¾ ü•BŠš3® ­ðs?È‘W!lï(ÍsZ×úôóÝk:Ú„2\^^Ðïe×̬¨û4:2s&.¦µ™˜pÁAÀKŠòsšÏnyjßòÝn”Ý>¤J®Š¨'²êÝ›ˆòMAŒ€KŒX~Zœúùö KÈúpòõÛ?¼øúË/pOlòçEBËl&*“@®A€¶êq¿>ž½ é‹1 ìþ½Íü‚eÇí{IÉŠèR®vT `¶ÛSs4W9Ó 2M3€ª dFLjž?Kùýv÷¡¿4û˜°8˜§o˜S›ÛÎ Çjsg¯G×ÝéÏ5£ðúyi—ä“›Ø=þ‡«XáG¯¤yi>Œ21aÞá§U ¼¼SÜ©˜—• “ p/ÉfmhÊ0rŠ8c;Œ!ÿïò 6ªp¼¼SÈWïÖ"JrVÌäõÙö£Öá„ßÇË;éòu@ ñð0˾í—×´Ä#´èí9\–™Ó˜QÒzÞãVšâõöw¹>ô}dàË f¿´itµ7›XsÔöÃ!°røe¦úk"€ò3 bOüïÞ@ôñ§©B~ñúùë—‹@Ò~ {) ˆb¶P-™ògc‡±hH®kV (°4˜ªŸ 8^ ÚÎclY+ËB+À¡%|šQÏÅ8Ó¿[Þö°âñ£W#^x:ûN[¬žvúyÃãü“Zèåw^a8&Ú¿Õµ‹Ø&‡Zò@gYìb1¥5Óo£s "lZð—°Ý[ÅÑüÝ7¾oÕvïÅ=5&Ô"rŒP¥|µ–š£ÍN·ëºÒBÀ¼<;,÷Æ,fž!)Z¯ŒdÆ$boãYtµö¦ `jB‡îcAfãšåÆ7DøÃx,ͺ’ëß|L¢ÄBbÄÍQœ½_ÈM+5Jˆq§6ßÜmÔ›=“lý *[¤-þx^–§Yœðî´æ×?’BdÎDLtb…û†r × tv•¢(Øê‹0î¤ótxu¡ ‡ï×9lòT_Ù0!ùí/Œ> o¶K!Ø™ØÊ4ƒ:Á¢¯*ê”[! Çf0ÈCû¸Ðö âŠEí UzœW¶¶>˜CÒC ¶ÚÕ‰.‘qmòy¨)Ñ-(‰ÂJ:dŸ¢3(®UîŸæ´©uÜpŒa[ø¾+uáˆAÈ»†BO&g˜U¡O¯mð'°„®‡ýêrCa›+åÊÇ*àbY€¥[äςҴ](©Ë¨¤­³PÒÕQIWh'±ü4’4«¥(^•¶²,z¬Ë£Ç`ˆc¯ú¿;[^ì‡ØÀöʱé$+:-¹Ç©XÙ~¢Öé®qÔQ¤DüwÑX®zz<éb.<9[.5i ¼¡ÏiRd5æ[gÅTIû–%ea®wôî⃤m–f‡%—•3nQ r2 ºÐŽw‚EÖ¬CEj]-‘šé&cl×g¦ß2LŸ5N¢I3ÁycÎ&èyJ¿%PPöÝÚI4husci´ðˆ$/1RIDÀCçƒÆ›„OÒ®S…qm‹˜5qU*}c¬äÁ%¯ Éäž^ûªRë¡)–ôÍÄæ¬ˆï'æ²X Ë ³œ­ŒS/6{±`a8f˜u´“^ö2³œF{œl±¨câŸïÂ÷ULâVŽ÷(X3dHÆÆ1ýß º@ÍÝTw«§Á—®ö¿*•ò( Ð>.Té[P²î×Þ¦¼ßWòWß=2¼ÕúÕ»Ä!ÏߟN|±ôİ}µ¤ºê—Nn”œò+…êXpÆ«“Û²ÿ»ÑºÉ?q ~¨¹¦ÑÙŽÔxÓQë`d•Â6†ø¡ã¬‹!?£¹ÇS)‹ÙÕ‘†µ‹Æ>ÿg|U`ÕCÂÃŽ5p*¼ô¡ÑºCšZ‹#|4õmš¬ªooûëÃîîFÂò¼ÞWJ•­mÈ{H•·úóE€QÊ›üžb싼ïé0ï()ˆÉ¿›%ñ,oo{ é3ú6ÓÎÁ‘ë%Å™ôô»Í‚~èxÑ1Lhpâ[CÜt˜q/g Øk~¯d¿Æõ«ÚyT1+Z)a¬÷Ÿ‘mt©§Pj!rµ>;†§ƒ?@žEÐwî¶Aµo0þ$mv-“Ì Ý(âË•4ú±g›KQ»Ir8?;õq7ÚÃ)ihÃtï‚ø#z•Ó›Öšˆ…Ç:û29QM"ëD´+1)ª©@ef­¶±…»\+óXâÿZ²7ÂŽûΠàñQ…¦«í…81GêQ,ãs«0è#xˆÃ²™Á*|Ã*Ó‡[ß§§×Z’Ö’àÉè'–GöûÅùCelÓ±³H{t}ºÝÿøîj»¼¾s;\QûSÒ*ýÏ7N÷'@åÑ‘ÛEÃvš‚¥çVú3œX·K7±ë^ 5Í[TKlÆw‘Ñ•‹%¼^÷ð~‹¥d]¥¸Q âTÎF%©Êë¹þÀKæ_7´ñ¦\xn(ß.ïÜÈÝö—b=¶kJ^ëóË4Oiya,AÍYY¾?CÝÄÒ˜éÕ"«¸žÙæ\»ºÛZf"þÌ>äîT:À+ÄQÖygrÞ®š#…,’V ’ÕMTÊü–â(–’ tN V˜?²+q^Æð†pÔJYlàö—¥6Z‘/úö™2Kù´ë÷§ÄWƳW¾NÄ—y*{ÃTx6àNªDˆ·ZÔäötM¢²§™ÿ¡k±w°ND kÁ_lZŠÔ·Ü"±‚À V&µ7 ôPžœ¹UY®¥ƒ Í-‡!ÕRhf/ÍsÏQ³´²VÒÑ…Uç4\QWÊß#“ÂLø®ŽÅ3„Îj[NüÅO“ºB &Rí¾óÀ{e¬ÿ#s¡¦:ª.3@né¨uv ñºÜa,n%8€†ºÓ²q°»ÏWá1\ì|Ñÿªdßî¿G²ï½DOŸó›!Nôq֯跺¬Ýò»Pýµºßƒþ°HØŽ¸7ûæ‹o'íñ®D *¡š¶© ·Ox‹¬Jò±K|ý›»µ„Ðë¢W¶yÙÍÈQKB -§`ù‚IBTi½Šßm6ÌÚÞ=LQŽ’@¤ׄ»Í ޼>Þß-I зO¹!„êÇ+\$$+›_â,ddpòõ³Ä (¾ŒÁÔy6Ð~t`·¾&¾,õðä? ê4ÕÏø:IúÆ4lqî ;÷=ËÇfµOƒÅÇ$ï’8d üm¡³FF‹ÖÓ…´ïK2ô+Íò±œÞ2—2îX‹t fBšñóh «ýQâ¤jÁÓ{¶ð0£DìÔÓ`Fò”䣵¦fɦԆ±D÷Ë›ÛõJ³Ì˜ÖÑ×|»T†\sÄÕÚ¯(pÑ\•¾4Šìâ@ë&zo‘¶– šÛ Ì’ "½< í¼6kóÑøàEYÞ÷!]¡"ù,qÎ"”D‘|A¿Aÿ·»m Á’À£ŒØR'¿["¢mƒŽV—’%Ùø Ve3çiíyå:ðMlªÑm¥k­ñ éœJ8H¬¨G‘R¡ ¢Õw³käw\0sO %þ̼ã²ÌÒ4„Å€$Æ?“ùgÜd–á÷Òÿ~O†ãƒ"òS’'d´œŸ!ØÀÒo‹Z ¨s¹ÁçŽ`ê.l©‘ê~À¥ÞѲ´É¤·Â›W«p%|ü #éÑÀ¿†Á̲¹Ÿ‘/’ÃÕ+É“ï"¦¹L'é"§!–)%“ÂÌ3]vU‡È.ÉK³ÍåMáX{2·ó’!ËɉúŸ¿xä×ÜoÝaÚoc K@d%ËkÒêM³Áh›e!bèà*¿3B½¥05"Ì75"]%¹îúuÿÞ'Ý©ÒR*VŠáä̾—VúvøUOvý¹;)|¦9 qG*ÍrGyв'”õÿåÝ>RNjûÈÐó‚§Ö…ÚnÆÏßúÈÙÆKéWŒ8Ädž—âí7‡‹~·Q'žŽ_ÉàWe ¦YÑŠ‹‚q0oÅÀ´ gн`t­!FQÚÑʽ[~VצÓþÀšJS»á¶ÓÍ&ãÀ= ,ñgÖþÿp%Ð8ú2•ß!ß'¢ î\ár’`\%ÛótšÚ}ØõÒGlúÍ”(E~ý 'Á ‘•~Tàd^ñ²eFŒF?nŒŠ”‰Ý_»«±Ã~Yø¯¬»±ƒ¼)t4I*ÎÈ~Ç׀zO¢m !8kõ£Ø™³8F¶lj¬J-ì4¡),’hê¶j+C˜!ÃJÓuÓlå†ãErû ¬¨ ‚ EòéÀ„ðWЋJÌ—îÍN{ ÚÛAªïN—² F w]|Þ{üom~èwËÓxÂZëµ[yŽ¢Æëì6Xªø=¶´tÍø›Bd.ß“åvÚ-¨0¤ÕNüŠÏSû|Üž€ý=Eidô‡Ë$d]V†â“üUÙ£&×UÀå0ûU>‰4lvÛ^)€_jNƒp¥òT âí]Z-i в¯¯—wg"—m›1›‡]ç哚ŒEÄá BÑ$1Oµ+tÚè7‚óšû%Pêë˜uB4"Ou+QT¥æ^»åKÌ«$Ò$봾罌äø 3:Xòd¼ÛJ"°0H^~{j{„èK#ÎOm—ÙäR>< íÇP0vña ­ †ÖýYpw¹ç¾øX¬y±Ë•zÿÅí6ÙvýòfŸ0Sþvhƒ=ÐÑ$þüíÇ~cô@/_ Ûä˵Ó“³¥@~<ýóá@‰6«WgÒ\tG÷ü³CÜžç0KaðÔ¼=±ãþW kˆ‚î u˜ÂÞ0˜îþ †(ªÁ3„R >¹Ð :ñAÇ9 ªüµl%¼©Å›}©dŽêTBÞ4BªkZ¼Ôœå~ Þ¶Hó—û87Ééðë;š3 Ï §àëã .'èµ{N®î6Ñ RdÍP]®ìd¯ïwüŽw|{l çmËÒ“_kC¨ {†î¨Ðò#•× Yˆ}ÊÝÞe¹‡ªŸ €v6ü®›’ÐzÛl@WGp¨?7,¨ Òxj·äÉrÓ_íV_ö›;°ª!Ò×#¤1|H‡0ΞÀx‡¾ 1 ޳&+Ì*Sª¿0wµ‹x}šnîUüµ.£‡Íè^Y‘—<$Ù–Öm$Æ©v'²óÚRÍì¹8SÈ–Ö+K§°[U¾ô_!7¶¢‰ÒÞh¢9¹x`bùüÈŽv|ú;‘íK´fݘÎÝ„àücRHªL¿hà=éšT~&ѳ¤Ü‹ÍæèÂúÐoA¤HÈäë°–ðŽâè!Ütª*ÜSu º‰Ç¯c͆ ”å}B “C1´ÒçoÌh1&¥¶aÑD¶ ÌL|tõ ‹…Ïx¸"³ë¶™tƒ9€Âç]ýp mF™[^uÖïæõùRvžç»Aúâð»Uï­:ùpõþ)¤óËŽ6½¹’þz¢láWȸûO½»\ì¹(-¢ó\+0Üöâ€`”„m¢`ãÕ¡ €hwxï.—ÅÏ6'®´;tÔXh/¤1Ýÿ5S÷w›þêÆŽ=CPÏÀØÆ&ŠB—à³ÈœE_]ć·G&wJV=…p-=ƒ¬´ ) 5~³…íf¥/ÓK½ç”ȤÕ"³“Žë¦ËM‘…h놭õð¶}±CSÀTŽÁ2Ü(®5mF–Uü=æTÒ°´•'‚oÝ@M¤)^#¿é7CØÄE4êS'€ «!ëê<ÆÄxQÈÃqèžùò°ø8îl’¡~nZíìØ¶ù€òÔ6†0"|Æ7°8)Š4¸H¦ŽëãN°,cr1ßÛ]5o7) "žHËÔªå ¿ëdL@åÁ7!/ÿ»P~\Ý&!ð»qç"Ûk% ; ®à¤­.È!Ö²æ$™›´‘6¢´KȪ¤·’&¢æ'Í39{zÈ´xByzhCýUE‚Æœ€ûÐRֹŨúv̆;Én@Ã(ËhÈY;2`àzC¸×kp.å3ÔA) î[(æ“ËYk gEx¶áÎÍ{ô ÿ6E¡j{¨œB~…ÂÆ*g“™A‹b1èŠh(QÒqËìp2] ¨ƒ¶+Zix‚r6>2¹¨]§P2Ÿ¨[é|N¼+q‘„cwÉ”‡yiûÀôǧ×å]ÌlišIÁu}CpÇ$$¿àfÃÒAΩ’ËÆÉJu!¿ÏÞ-š Xµ/Ã{p>æ)Ÿv<ÂÕˆ²ÈT¬æk˜ñ4ë<—©¡r0锥 f’Û•]o|šžv”ý;sv”×¥MLQe¥=±ÜwW½»›ßD C–çè&P&‹ R@a<ùý¹[‘á <!+C¢ Ò Q»mä#<ÛeØ5•¨¨TË„ÌáJ¸%àÃ2¢P2+lñóíímO0s‹J–\åﲯ:ïY/ ih" Ã" M±3z@r6©Ãdq}¸Á"v‚{ÞPs¤ÆaK»ÌõáŽVvÌËþL„¾‡—'?žgÙZwºRß‹mȱk¢±3™üövÕ¯wKªy¹Œ—Ô˜»ã¦ÎBšºžßãèLB,q¢Y‹@Bv¸û¤¸Íõý̱\îÎp˜Åés>æXú…¥gá¶éÉõ­À4@ÈÇ0|Ã0DÈÈÀz‘mÅdë§a<Ý¢:O² A`,œZ ¡ƒeÓ@‹†ÿ“±ÌLY)´3Áhd×±LdÐù›å ½ !ü‡)‘mYÈ OB€zI‚=$´Ñ4•J…Î#ðŠR¡E®VJG&"Ú9at<‹l/òo?ðä²9 î=§MÇÍ*a1Y, ˆX–„Ï~k`ªç“¹p{ ö˜mQJ9cÝwʽă&4ÚrMrÌý ‚„ø$™ä(_ý¸_]ê…£ôk2V@î#æØkô~kH-¶WëÛ~¤IX‚s&|T¸èá¬M”\Ü=à]….»ŠÎ^w•SZ邨æ¼Rf`¼S^½Òà½J-Æ&ù`cUZ(D'¥ÑÆ3¤§ZJ&áBM§%ã°S†‚H5Q÷a¡PRÀI1 6tDÛ³øî”óVR•Z6Ãbkõ­áîj7<@»ÚSšÈnÚv!;„d¥Ë;a‡2ë1ÇlUrD‘âH\`ļˆR‘ #¢ZÄ «',DÉ…Œc°›jÚ¡ÑG±éªr.@!# Òu‡ì ˆQ 5R~½¯L°2?8[ÊÁ}Ú Øa.•ÍEa½Fg)i IËÚ»‹®ÏŸ×¥“j·€·SŸ¿J¼¯´ë´ÝQ¦¸kçZ SŒ¯( Ò¶ uuº…qYtú8ÄÄ[¥¬Ïwwï®Ešãš¤7B¾X‡°Ã$æÊt`xëìw»Þ¬•ÛCU÷t00gLj‡é~HøÁZ‘º¨ùð ¤ýÃøúX•ÌX÷¹šDIÀŠ!ÏMòènë¾WÂXÆ’!¸DçÝ͹¶ŒUÙ¥ç¯NCúãÍãÄ}ËéIyþò ËFº:¼ñÁ²,ß 3ÍâÇ_/ëÙ&Û+‡¹/î«þƘ­ƒd£ B<{Œ‘‰ÅS€„îÈzß1(0"—‘]µº^ã* 2Àsg¥h[hŒ¢ZøøœQ[hQ*•ÈoZÄ>¶¾!ÖKª NðÂ"‡Zkapg´;w«˜Ü2Ié¥ £,¯VâMè¥YÙÙó1ЃõwUhܘžÆ:‘r1]AEb $¸|„ö˳úÀ-•¶œd“éY¥ã­J/Âà3;ÿ|ÄPf|’­”œÖ‘ÂýæQ]"PvX×|kêhJ-€12µ¥3ø’ïÅ]M—÷npqÈqÏ:­LYÜxiWëMæŠHìb*𛫼ñ/Ï•YÜk¬)÷E…L>̹ÊÂ\™Â`àµ|(Âuù,œeÂí.h¦ô:V¼äc°—¨.øšÒ–Fã1ˆ0Îõ˜¶Œa͇€ ùï1iZ¶R2ºë»m¤Ô;,-8\òÍRFù!Ü caôY¡Ý‚1ðÄix=Yà 2Ñ;ÑóNûÁ¡áæì+=¨E4ùr;çZÿð`È4VràRI÷ —æÔŠØVåsçÒj‹TÙÇUކšu.ÙN*¦~S$(ÉseÜ(FžªüäSÅØ|Š^™þ Ày¶1°{Ú9ÖXaÌÄk ¼–ÅXk%,ð6S&²ñáÑ>ð0ee5qæ¦çœø·3Ž ¥H®ÐσuØâ.ú¸˜Y¥ __F0ÓŠp2nÎéžw€v÷îØ'¿t¡£D¨äbÈgä?;ê—gÔô6—ƒn¾@{ÏD6wˆ,(y‡vØ.„Eêr£€­Nž‡¦ó¥äñèõÙãõÕ¥Ö)•¹èÝÕÙr'NïC‡•E¾-éY/ºœÝç™Ñ •«ŽôM|U¢dáÓƒ@úg#ÑRêån˜ïA’ŠrV`ªA+*£ªñíREh J]i›ðç<ó¢-ËüÐröj§—ÇJ+Dq5>“¨Ðî`Õ,ÏÂZp‡F£ý 9%þì·áUV<ªÌÄ›ÛUJq5 @¹_F{E>¨µ,NOm†šLß ‘¨K}°_ª<úä/m…{ %I„J‹„8ëqwè%sc{ZÚYKÅy~šWE:õ%’ä ŠI=-³o¬ŠA؇(úY_þxsÙŸ}”^+‘dBÒØá¬žÈ;¬f¤½ú:dÄWÅœ6e¥Ôºîv¶À̾uæáØÛKn¶—²¶wTÞ]%=:7wÆ:ÃÔ*›1fë~\koÚÁ ·ß‹:“p¿®-l\Z(Ü"ARz'\NıÙC«BJ™5ämR™³& ´¢$œF‹œ‘ÒõÀT©Ä•òÜ=H©‚jÊ3£é£Å­û{§Éà’«é·†Ë$ ´ã¥/«u™7Åeöý3LfPê—DKÚ“®TÖ½{­,‚ÕP«™Ò3žu;\ ª@òZ‘.µ›âJQ·Sµ¥²Ä¯TËñ½ÿiqOz87©•Nöˆ…=ê‹Gz½/Õ·3„ÇPwûÃÃ"ÜJAØÄì/¬Ó.V‚M}¯j}Ç4 v?+ÚÜÅš}ƒ3“‡A™šœê—!ZøÕŠñÖÞ8šêÃCwº§‘Ö·V¢. |'9/ã”h;7B8ûH ‡;wöX”ˆS©hÅK s3Z2Á€ŒÔm´¡:Q\rqÄ`§ –sÉ•?–wÏ{h]ä±îÏ™?–w–?6MYx\þXJqh³'ßnß]ÿËæ_¾Ý®¹xUfø¼Sæ þk-;½•"ÌÙ›-Â1;Ú*)ÁÉ=¤Ð.ë±Ô@Ãîîj¥Æ%³Dà¤gyGÅÿà QÒûøâ‹ðV‘ƒ ¸Ü„éâw¥ä/FT¸»ë‹5I™úÔ]$°uR7¯ÆA'u®CGÑr nZ>ã+r‹ô`Ö:úÍÝ~%Ôö– “[qJÔäõZK —#·¤>ÄÎöh§/Sõ8[5“’Ü#€Ó‚ISÓ€¼(‰=—½»;]Æüáuó$™©­Ì©¯ð‘™)3k¢™'þ,Ó£qF¬A„íÈ3 Þ&͵’Ü ]sþ è2©Ô”v±‰(¶åñT]«ñu!eê›>'‚Ûª•¥>5ölE쎪²æ´i¬ñ.Ò‹zlÊ’ÔX•ÄžŽ °7à®pä8kr •]§þiùgm‘ù )9»L>‹v¯åÙþ–mGœò!Èöèn­·&ìµî|ˆÙJ·Æ ‹XÄåb&$=`j’„xhpM¡ ðmþpµi¨Î#-Š¢t4ôÌ ÖË_‡é ÷¨F:4ê4-Îõ’¬³vaÍ[izf ÌæƒT`6€“J8ý!Yº®¦|h`·Œççm¤NƳ#²†0`f÷2•‚Óé â5+PÊR˜µ¶0¦©u¤Ô§pJ…ûcU™ù ³ž´ï»ÞÞ8!À,•ž±+í¤ÐÅ—w‡]oùVžŒ®“'\tÌγÀ’ßß>šÑñ•Û“g;$HЊ°O\·àÝ>ì–—BÌ}÷Võ¯›þ|M ,'^nä!B:nÓ]SX;á’à‘3ëÇ,÷Ó¬@CqHþ4§S]–:f >¡éZà+ìb?š­Êù‹ªB ¥¨IØJž êïÛwW’d¾ð!|šÆX>!ñ.‚®É\0€öwggníƒ#óñw"ѦHæÙ1Bé#Œo0³³4¾O¨_v6¢pò*mäç(R 7áx½êbn²NK[:e‘¢ôÊzHJš^Z!}º"Â/Q‰%3ÁÙ{ï}ðd•VoKÓïúÌP\—•uìD² ÄB»?áœ#éæýMã ’bœº¶‰Ê'™,uc¦…eŸ~"‹Eæ«M'É(U­zeC–› í ꌪõ•¥žZfjœ®KÝÂOYžê›S$Á{‹›àÜ«ÍÞÖøw§~@ønRÚYZì8šÚ.›>ñ‘"lÞnâeWÛÃàÉÙªý,³ûLfÃ2ä—1²Å­ùa±}`œSaWöÔçкá‘{¦)i˜N'—‡Y’’| ‘~Õ¯äÜ”.œ¿zþ'`'&õ ò«á-‰´0ÆË ”Pn@o.N5s’]”‘ÌIJB5‰Â¢1Zë&ëOÌa9M[Í$›Z¦/¹J}éù¨´³—ÎQÖó¨Ï,<kdpÖK>éx}3f*å‘VdI›š!ú Ï5xÅXÇfÎH8(Ùjkȵ>1»Õó ÀsÉNµh A$©üØA:YiX©–G¤qfìà«qbF £²äÌš\Û'¥™éÛ0ùJLŸŽëÅ8,ÇäT™Úàe›ÚóNü¶£à“|ÚT#7ß+Só¥LªÒÈt(æoJ¦VòºŸ –V—¦R:æWn~i6Ì–´ZB­òOô!>‹Ôð–Ê“±åÐLüia_”qø5ÉMVjŸçcÍU´úŽ9o;+2º¶Öø€€ÚÉÒ¹à€Ò†»Æ½¢t«Ðbϳ{3¶3Sª ý„ÎpÙüî—éœÚMõîg)&ø< ÎÄþbÛ8U£hÃSüÁ¸5_¸¹¢ªS>ãFÞØWÆ <ó ; ^ªÝC ¢sx­ÙÀЩB™E;6rŸJÉ'¸‚ìøkôÕ³dAš˜:ù²Qð÷~¬³žy÷ï®™²â Ì:©¾aªÓ~2i»¼7„túnˆÞTŽœ{Å}ç^©eIcŽ#µ%\Þ÷þæöbµ!¡»|ªæ¼ºÌB'5‰½nË‘ÍY ­=…qzZêBŸ#b„Q;ËÖò[ìÚ»OrOk- 3`ÀœËߣl¿(æ€E%4£AÎLÁb3(cO¬´@÷3òBŠ*êÌ;Ç—dUÜ¿ßøÕön·â=x³÷¨T|…n$G1LpÆZ£Ú}1ƒ:˜Äï·±&I”l)ó‹)б@Ûbð_Ì=jVlhÔÕ$ä¾´L’Fß9ŽôúN©Ç‘ð^pj§+Ãì€uzeöÎÜG—jaÈ«±‹ug#Eœ›°5ìHÆQEÒT_%íAy¼_ÃöF-ýªW@Á¯ŸôN Ê×d.^ŽÛ]O½q¹8/E;LºkŠSy4êC×Xwq¸Þn÷‡Ð_;‚ŽÈDO[í°±øZè´))Éa#tÚ’iLÔ«J¯P—:AŒ>éÕ™\uoB2¾¼Û»…v}·¹TDF“™u­­@72Ñ…Sí÷ÁV'ˆžÏ†þ;M¬ ü¸ÕòyÍúcùYtÕsãˆDµçÚfän ÌÚó|:*¯~faÊìðç‰F»'€ö(8NœÒn‘ÐUæ¯à¹<ÕÂMpdQi$,Ý<§‘Ê6r>®LÃǹ«ZªŸ€@’3±|\@kíŹºæ Ìm¼Ç¸ÿÞ±¡-Ïže oX•ÁÕn“œí BúxkûäÏ`ûxwþ®¥¶œ.ø€oÁÒ( >gIA°¹£%ÆCMHÄ÷ñéœv!ËŒë@Ó #ôJïØµ2@*¸ J¤Þ'Q¦oÚjºh 1ãm&|”㫳÷±w–å µ…qhÿ=„¢$ÂFè–þYYŠ'c–îYÊ>)³—”YD˜”;,iDdÂuÊŽÓ`_Œ,¾Œ›a ™ýäDÑ5Ïs^jÐýqÕ_é64T–<•‘åÌ®–Ž­k\9 ºÉ5» 7K&¯Æ( Þ'Ó铌hOטKi0ZÅ7KkÔcišÙw˜—»ÃÐå[eö=xøývb^.­ ªfl?ÊÁ1³ÄG7M´ôع:Ô ¼çÇàò¶ÐN÷¼ž6ÁψJ6ì6Ÿ8ƒí\%#J'kGu¸Â¥"ß㪷^+I‡ZÈÂȽñ:M¡E@HÖ*8@÷KeÍKo×l­)!†2qÁ3ÈCí å(UÈ¿G3À1#•½Ùð|Þ?ßQ!’ÿæò­}8ä^x^˜BJ¦¦X¦?Ȧ¼™ÜícM¸:ó.Æ?iÕx}u­6¼¾þv»Ú ¯¯9!°0„ÊÑ–Ñ–Z ¯..RaSa8G²_¦z@aq7µüîí¡ñˆôÀ™Ñ/7‘ÀÈ;‹1K_-—ÝÙU³ÒWÝ{¥ó°îX'ò’Ø7å½”Fc†ÒXïÆÐ–~Ïä…ÌÔ îªMt\f€<“r ;Ôñ7Îξ¡5Þ…Nˆ˜5(“ó£’¼8XaÌ€÷PbÒ©ÚDSl°øcÌçËÝòœ¤sE8z™a‰;ÌŸVó¾|vªO´/,=ÀÒ71á±²H§µYØÅ0NB- >¿ÛÜlMq–ª·,Øæµ%ˆâð2Ï©¾…eØ~*é‡A#ӜɃÖ2\?EVÙt6P1Qµ;#5—q:Þ¥š„ •>Vî-NâÔV#$¸Yd¹^.°öŠ!7‚NK©%H…;ùÍòîöà=¤êuÅ–à³cÄ'Rz¡€  ðƒ÷¤—™¿ÃÖRz¦»ã³<§(’lPFÓðŸ'J•¥!{Õb׿YRm~Œåë6¯–ÌR;ƒ4BÇm€³U7úTÄ.|ÿUêÁ(¸L©ÅR*æ80¬C’LJöóßw³]ûŒ\ÄÊS:0`‹ß ‚4iÁþ‘j gG Ë,gïä÷hÌ-›>RÆk˜`¼,F[-ˆØ< ÙÓ„åµx.ð3 ¬hP`|ç‚AÚÖλª$›ZZf}‡¥}@XxB–çÀÌ[mögý~»Q›±§{¬³TjM¡aëV_bÒ“/ÝØ]ƒ«›–Ò6s+µDŽs©’"XÓÊËÃê=û©›§Q­A­ €ñ¹@Bý _/Àëå%ð7cM\öF«i†)¤ÞÔš, !’©’"ï>ôD¥ö*äµ}ú3 Lâ…³ò£†› äÒDŒ²3µW½‰gdâú¨§ï͹b ÅvµmµÜ3®–³­×Àº0²Ú†%Vš”tê} ¥å£(#Ý+XoZØþ,Ÿi÷¡T‹:ÆŽ˜ÝO‘­95HL”ø4ʾ•à%q"­·¦¹j0€IXWÉË^…,Þ·ÃepS +ÒdøÆJp˜¬@–{Óoºˆ"e]°)¼Îõ3Ç1N…®¥èÀ ( emße’§V(A½¸³´1Yâ$—Y ™…ĵτ¹•d œ$kÜnå[½©a»Ò0mJ—Aj³ÎÎÁù¸¹ÞGs× ‹ÔÀYeb-KõA¨QQ óûúhÄZj‚-íB‘ʼ(M¿¤‘EèöºÄû*aêª&Ñÿ¦Û¤úbBÕÀi¹]_ªzâ¡‘­3­Y[Û—ÍÄ0ðéëcÄ9IbÇï°i}MŽ.†l:†&RS7DÁ`_¤Ñ*!1oËnWî’TcCuG!¦r{xèwÕ+mUIé$0™7A>Õç;w’XD£AÉæ­TcvBÙÑt<K*ÅD Çœ®öð^.?>©ÁìÒÊ“È3Þ !ŒûôÁ=Û=ˆÒ…B(9{×LÿI *8•}†·C{ãfªÃÁYêi×è·cUåÅl%oA±&a`¸Œp°èµ1˜„´ÖF g¿ÒPØ:²•ˆQ*J[HB@¡-ºJ=ßn¿JNŽàVõ•YñÁܸ²[ µs@êó‰mËüdPŠXÚjfHd°ÉræßªëO}1æpˆ[EÙ›Ýöl-kÌßZqH˜kß+°^n#o_áxPSG…bs‰ÜC6l㔄ÎßttÜÆn¹#ÙPÓÏ`C}`]²¡¦?7ªÏž†-‘3 )÷J”WUVˆö$|¦ÁÂ\¶šK‹8 c{ͲI‚¯á+jj-dïQªfÃ!-°ªÜ5«±Öº6Ês2 ¼’ËÎäËÝÝí­zŒÌuö%U|žÙÁ‚Í&@¨åNõ2ÓÕ =Ž´aZ*ìó5\i3iäe¨â†L¾8ªP§’˜ÊWkåAí 9´¶±i_MM¬–h`-'·ªCÞíøÞ‚¬›"D.|”}Òóû¡¶–W’Å ‚˜‡cŒ#d¹Õ0‰0à'ê 1„=³K'‹y¬ËÙ´y»¨âû’G«-±8ö†[ìT£_}ráDÙÊ5¼ nŸî‹uö~»£¡‚Õ› ¹å˜Cj{µI^ ™¼e»ºWŽE+²™žëÄì»íMf>Ž„\gx28 Q0¡OÔ¥ØV,Žì~–+ B8‹YÓÓqø ÇTj …1Æ11œ;5Q#²ÉxRWéÕÔ逫+J Ú»ÀE<yðþæ\^ÞR“§9­óáüòV†þbÿ]mpj>‹ŒIŒa'5\”öé_KyœñëÛá¢í:-,_y·“”Ï" 5Èh,ÈUÔЮ±Ã 0a-Ík‡ºÐÇ1‡îq‡íRrÆ-Yû ˜ ØýŽ9³Ð $,ÏÂ!—Q+®Õ/KCïß\÷–´Wy¨®Úø¬)à^ë”Lasõ#—KÿâèÊO„l=ôzN·>Be¡5]Ã!ƒË….*ÒŠf`ñ¥-ïöÀ:Úï–¨W|Â×ñÀ`áohFiQXgøzó{a’UO:˜lP2q44d$mƹ ìXHaé’5ëSh*–2Ì@ƒÚ›1^% åߺö!î1¸¥ùà ¨ŠãiÚt†x>=˜Èϧg.ý¥N•w«8x6È'õ!ä¢[ô{95éÊ‘£|¿M‚Çáð,Q ôbñžÊNéìc o E08—h]*(Ö‹„!­BË$¤ VµÎ@mQžÕAP'—k†ÛR‰u«»ßTÚê ‡‚ÉÑâjAŒ •~‡¯vˆ–Çfb(:\pq}©ž‚Å~í–"Ø3*{X¶&1T¶RêcG&C^‡¦(bEƇÁ¤:pÕçTî AÙäRì6ÄÉ7NõŒÜmàc¡îèâØÁºÒéýöR³õçİ4`d´;ÏT)Æ¥Îß®ª§Õ>0|;Þøv½Å¸t÷Q¨~À>Áïpz:pû¹ï.b¼w]ظ ¡|ô"Ê´–"ú •<# !<Œ•Gùì¡¶F'˜¼¤B ,‘4³[]ªVnêJgï¥ÑP#LÏ•ÙÝó'¥‰‰NdÁ”eÞÙ×eM_žõrRÚº­3Ä e£ì±s}s D²ëO§‡òð~5pX5­öŠþËW?úg‘,k;m‹òd–+Ô"_Sí÷ýö°ŒîÃÉ.9ŒPåÆ}‚¶Ë’¡Á_O;†~²Ô:uuбŸlu¼pHû*­v*/#=£©¬t~퀺Vʇ×D‹¿+ª{>†<òä.¯$áÏ÷h€B;eU@,7ŠÜQN+Z¼]WÛ¢-¼¼‰b´4€ÝùA"ÅöÌ¥ÏãŠP‚HUW™ÈÈLÖ•†¨BÕiÑ4«¯Ñæøµ¯úËÝêâ"º<×ÈK=©ÞƒÔž^^e˜ùÒîPæâ¥}ÍEäG°çu#E>BÏ ,Ë&aí}½ÜI¶m¸ñÞ|<6v•úÂÈOæ#1íCpÓ¼^»£ôÇdéRSÚu0Ð ØÛ¾%µ`” ÜZó8] oÛ±b©·Jl^”ŽóÁaú•Ç:q‚b»…”º¬Ê„€¹æëÈ<1§ææ—¯¤Öd]Krl«-d6K€³¿ÆØ'!±†¹Ÿ;ƒŠ­<%|5ûÙ>ŒÑzˆœ§÷Ûµ&$lÎ¥‹þ.Ù5Ú Óz¹p |‰Óœ+T  ±\x–(‹<–`›H3Ë„+õ ­è”Á‡(Ù–õd½«E€~QO×»…—RDÆ7K£²îÍNân¥t,Š0|ßàkÒ„:oµ!Åó€ú1Ã>ð¨>*Rf†ëD¾ dh©ëoî£3‡®úIh}ƒ4èìí°ªqÑ&ܸ%ñ2+Ä®[Xöª¡³‚ã„UJÄ€RœÞ M#ÁyhfÌdýŽÿÿŸæ¸ýr]zƒWÒ´\'ß$…; àV~ã~~KÇÉœ³z ‰\Ð>+néè[‘&1§µ…)*¾MŒM¥±ùÌRC*âΜrÈË›ºm+ĵðLsPâr¬uFå,Ý{o0/ÂX.†­õø¡*MM7ÿF )ÂÀüëx`cˆb’]§*u’8YF§¼¹œuâÝ^}ª‰oìë(?!!ƒ gÞì“Î}K£ÿ=sÏdóûçÀëósße?×Üwu97÷mûÄsŸ¾“Ϲ‡“{`Òy×sM^½Z¬DõX‰$™ÑIܶ®@"÷-"bΗwNtŠU9™ bëÝØ©h³'Bö¹ÚÓ qzâüny ëDÒ/̘gàö)‰ÐÂã߉šú|ž8µ€|þ*x˜YÆ’<­ŠaIÍ‹_ˤ³áS6ËWîå>!:,éò†"ùâ•Ê"š•Çœ­j¼¸ÜÝÿ`G ¿)@˜„B<3Ćdi§7êcÍWYMy¡cÿv/g¥ùÂÖ• ÒQõ\ûLÍÕÙø©?Ó¥sÏ”R4ÿŒì±ù‚zRmóÑV‹¶ùl‰MÂ\‘Žõ\càç‹t€æŠtæ$òúÇEŸ)Hv~Hl”)¤¹r¤~Þìüí>)b PŠ ì™ìoH{(ƒÛOÁ‡ßž6Þ:3+DücL¸fo ¹E÷Ëÿeˆõ°¨?-CüS”!x 2$¯ÿ– ñÏQ†ØÛòr^† ö¼ •x2þ=È™'dùÎ>æaV†Lži¼ ™{† ~þ=~fEÅü3~fEÅä™Ê‹ŠQ‘üÓï‰$Âh§˜zœMý߃Ú<.‰dËÌ;øûø‰Ôêù¶t:§IÁlkBù2ßœÌôLs,˜4W²¨½·9Y3ͱ`¾w@P¾§9Y3ͱ`¾9xÃîiN–ÎLs,˜4Ç{J—M›‹%òÜÚaÁÜâ™+kðdxØ)ã§Ó‚‰_¶Top%å‘VóF3-A X¤^÷+Aæª f¿ÖzÙ˨üÌfFµY÷†yï`Òdµ HNÁLiÆAÁò‹N?ÉŸº*I.Q€Ì¬Á°Xvv ÉÀîIàÌõÛÈ€èÜõ´Ÿ­~à§Þn#$éÛ9²30AYÇìïªÒxXÍE+äå0®:&ßEÍÀFïƒ-H©-t\± 4WßI¸Ç)^€,<ÂI¾o¶ Šr]‡©Ì#L¥æÈ„x{XÁ¡‚¸=|LÝðdþ¿m¢ò4„úrczú×è„¢‘`/xÉ(tE$1Ž¿é—nÞ÷Èó„+Œ\—É«äã]ˆlIR²ø€cÓ^‹ì>àcÓ^G@ ñ€B[Â\äÕB#ç…6§R_M¿U™Þ^ú, ö$OÍ[#æH“ëÎèwá•,Éý×C&WÝQš³¢X³!ë[CØÜ%•ÈûÂS‘'ïkbyBå;{_«rð4øy“úá׃¸Â¢T’a„´žÜ¸£QoSµ+j8cÆ,lžº¹ kÔXŒåâ$­>g²{]í6ˆ¾4Ô.?M3|Îû Aª=ðD&Û Q„©æEw| F²vkû6 ^8¹TȪCr³Ü‘ó¤ÿaAn@ØÓ;¼àÓG®Ôã2Ÿ‹{3ŸÿÑ“‡Ù‹“tçÙ˜øªÔè(ËVŠ%øÆ0¹+Tk¾1và¯w½Sß¼Òrõ4ÛÛËÝ ‘‹&Ö!–š”IÁ|°K…‹˜d-¯{'ÐWzëÈC<¬¼1 3%¥U6aD†d%Ádñ ¨æacsn/.@ÛáîfJhÚŒåÏó¾¶æ4¥$líˆI+H…S0Ò$äf9W”å€zŒP–%Y7¾L¨¢Ôgdª0I•B8eVÆ\ë§‘±4Ê@Ììª!ïºÆŒç™'76‘f7ˆTy£SS»:tûÃVbùmœ0g(„ sÛ2 ÷f˜m¥¿®èí›wH#çž[ºì$ÛšiÂ7ä„blöÒ’â­ƒ&üOÌ&“ËðmJÜlÚÞ„þïÔ³`8²4è Þ ’:˜ Gûk„JËQiä»­P#wîæNÍz]nš•½ßÞ„‚Ú©e1M´W£MÑxúâò" ߤ+T]wýR‘<ÇR£4Åx!RB=fœálÂÜǦ—ׯ€œZ 1=i¡ÔÄ™ Ï«J߉ÃYT¶$ o”Ø8ðAyx!e<†>àn:‘É<”Raä^o•ŽË&Ù˜”ö?›çNÚ…‚‚£+½­Œ{hÄÑU”ňÜWC)€~ꉕGÆ$CÎ):¡žä_eBºŒ©€Êî/MªDÇ]&0± }å,é­®"âIf´/ákº]WÍF†Âçfš(]u0n…bgÚWcÑ3÷WZÿùΰñí‚_U¯Yó É `éÁÓ °-k-Ës£oÜ)M²~BUÉ—ÃØXa*Æ8Þl÷vèØÝ ŽŽè©ÂW;M©²Óq~ú(mg¶dwÚ¬*-ó`ÕZfH#e„‚ÿëòúYñ2¨è‚Õ:!•4;|ªdÓc±ñðTÆð§^“JÌVZ0Í4_s6@+C+ù)ûwWË e É£iÓ©½öQòMçrÜ ¬£‚]ZD‡]2 ü¯Md‡³Y/EE«ìÊU¥nå¦l=ƒ³&éDµy6¦}6ÙÒ¥¡àWÛ ?õ}–RãN…™»e߯Ï$³Ðn9e®,×XÛ«SV)O5uŠo#s*Ef+ô˜Œóånyw!Ù(eôÐên&ÒZ&’Ü{w ¿V­/Ø PhN%\@ %†ù•§øV†M•*5fI²¡³+†Ÿ¨›F*àÀã!²^ ö¤¦¬´y8£ÿÔoâl.Äò5ãÙrrrí×øl¶œœ. <ÍÑ ÍÌý…1UãÒ½Ú!Ì–|^> о¢"f2óT-ú$.Br'‘y³©•â¹&Ò鹤x0Aù¦îAPt×s"…9 ïuÚŒ¤¬6\Zæþ‹²ûkTp ó(èûÊrmø[;ö(4É£k¥îŒjFZÀ*´ƒ³ÁºeÄÁ@(’òy´ª Ôî"A,åIyí–ÅOøìEJ#»Ü™…Ò†±o•>ÂÃRéÒY<_ìPáö{žÈì>KáŠhÐÆ`UoØ%Ù«Ývyþn¹»­å£i¤Èêìg`6î‘ã··ëÕõŒg¶v›LZ/RÛómÅ cî\§j¿rœì¶’ŽìIZåíspNÄ¢ L ºpˆ? (•{E¢TØÕ\žñÉ€Ï"-:$cÙÒ)j-Œ6·ÑÚUÒdI™ã6ˆðE(2L-Mv¾Ýd@Î])]fëÝ’9â¸EÌQÙHÍ`B÷h - Â61U©“P8›-ª•‡‚µE_¹Y>øâ¸.F*s€uÒ±ˆõþ­¶“–é5WA¤ºäÈX·W_-q·‰ÄºÓ4Ò-]A $É+¾Þ2‡R-ðÌ(·P•RßMÖ×ÌÉËÑ*^5¹ƒ©òëéíM/>U¡ÏMFyéÁ̵_ÔÐÜŽ•d>ÊTãÐèGÝ8S’ÞšÇPƒ(ˆsEì5ÔòZ»5ìz¨Z— ~¸Ò)sZ§ç›Œupå£ÅMNšgPï€Êr.kgéo²uXÚF÷ ÉõUè²Öi+ѳHÑu&UlZ¹Šé´4 Vb4@Õüíc»¸æÖ¼ï"Å—²›íÍdC—AÛYTvS‹ëÛ˜4V¦³Ù@5Í„æžm@rą́lÕœ®UÌûÎ Öð›¥0>((“jë¹ 3Æäj«S¡Zp®]›l ƒ“@ZF6äT5£]“JÑD·Î4Â"P§žüiyµ#hâ&Vl 3Õ6SH& Qhc¡ev£ÚÆ4Š71èU"o´±QÄs䵡˺ ŒI µ‘(Ìù<Ä:Ö&Ê]_áÆ`\ Ãc¢œ—µ*‡zÙdò¼qG(I<5a(̪ö—»å9È%öbÙ4²R §° ×Î!Ö~p`ΚfóRë{†Z¹YºTJ§põÜxùÜñì±+; û 7ôé«ÃTš¶S¦öh)£§ìeX×jy<ÕÿŽ´Úaªô;DW¢„¾Þ:!y­Ö Cè餜C;¦\ƒU™)µÚœiªaŸ‹tB·!ôÕþ“PfÍãäŒõ¸ÕæÚ¡|¨¿ÆšM¦uhiZǪ̀3ìÙÓ°ç òúšº£Yv}5r«Ox¸¹1ü ÊËB­4Õ…|²°P¬AÀ7ÖÖó’)£0ê‹·ï®vÛôiKxfú»I×~÷±¿»4C§j)L»Ogô0\UõÈ( :(G¡æå3tŒ¥/ðWÞGײ¦)¥<Ô­±Ýi #€»ÜG®#Õˆ -íCÁ¸Á Ð-ãb×# ½ILò®°éT+6kl¦#–’¹+«Î¿zÀF`T…ÈÂ+Íâ¶éïÔâfJ¥ wä˜[ªEÖ%’/ùp#n{8 ]—õ\ú’$¡áåäú.íXò\1¯S !g¾W_ …‰‘êÓ‘÷I-­E#%¸ž–n:µ¸ T[4¦0¡Sëóa¶#è7i`-Ô¶Pn=‡ë;âžíÓzGaA\’ƒ,‹»«ËÚF­SËœÐxŒ–BË!뾡OƒN“h'8Ò^ƒÐ<75·pÞ…›”À5ˆ<í"Ñi‚h ŸP ! uÏñ1ë&YØæÞowÛÁìe’Î ‘ÛÜ)ãþ7¥{ù!d•XhÃòÓòÔË@„Ö²$#NÔ×oÿðâë/¿€>Óäϳ„þÍì…l’}òk7»çëå%¿=¯ïO‚ÿ,pÛ c ÷=ñ&ƒÁ›Œ÷÷Øür&Eα«©òV ul34jšíº–²` 0pœJ †þ`ó#ú^~ Œ¨ ­qiÉæð«I#Uoü€AVº6ÎññåúH©ã(NØ/XlK“”çÞϼàÏÇMŒÓm´ã#`žæÞÊšVG‹¦/7™Kl˜‹å^8‹2Ú“Qt&ùÂP6j-žå¢¬òJŠ9stžìô^ÝÄ4ÂM«­xßœ9í+k~xR¨û¸ÓÖÅØ xeõ'xî6HÖF¶ º†{©T4ú… OÏy>÷ñ'»•r†ã1ÄMÁ¬Ãä@FÅxO›^*Þûi0Oú|IÑfvucÇE7RB³£ ÕÛ—w—K¼[ð{]hyt€«þ5ÚxFd7ržXÜàá»ÉÖy´*R?¾ˆû– Óñõ›ªÒ:¸àþÆ•s†½_–Ñ,ÇW~dÿzàuªÀ'…sPæu«…•êð+ÖlUÛ¿Ûnwç+‘9éAšú1ÑýÙˆåKçŒÄyÆœCZ>ì–›ý…„/ÔF˜\K­ yl‚ñXaBõ×4ú(lØLr‚ž+ŠÅ^øZu7ÞÐb*¶]…Ô¢aL®ßŒ‡™íƒS;)DéÉU¿³Ð½ÝÞ)_æRqr…? í:£ýG£’~{ç4ì–ÇfÈHº'Fíî˜×è|Ì™¾óŒÝíš?^Y”“š_êVJ'†¬’ã>„‰¾ÿxyàÀ€½/'!Ìî.ܪs_ëñ³‹¤8zG´ñiH>~(„óËudbé¸1@Py.w[‘{#¬ãÒèôÇ+¡åñ¡š~€g8`Á ,o‹eefÅHo–Ub…P‚˜Dd>]gÝ­ëîÃE Öj2ëí<¶ÉõóI¶çå«HxK‚ çÐeeØ’d6ˆswêt¾ÒT hlÀÚ¯ÅÜÍìV6tÉ¥¼Cœ¼Y¾»Þ‡ûÄã €;¥ËÉYKÆ.sw±#¥•8vÍcÍ:Ô èü…æ6C#‘G\l ­€ÅÖï"èF»–’IUï󟟪`ýÞŸ|.¢äiçømë/ÒöÅ™ d|[®ËJŠ‚(î[//sïcŽ>jår-¾ÁÑ 0´y´Jà…¡Ó$¬£$P‚—ÈÙ.†h~jÎ%熄Øl°8¨6fæ÷–I«IõæN¯ çÈ4Ö´ÐJaÃ{äÃ\;8Id Þ\íE”)hçö•¤Ã tËH}–Á“SïÄÄÜ,ÿºº‘ïLðBqN#È*™ ÒJc”ã‚ÖöŠ \€nØÜµõ'ß”»rvkDjµ”€Y‹Õ¯´MHÀWˆZŽUsXn¥8Õ Ô}¤VÌMJ3ºU­ÏŒ-¡“Ғƺ·x.7ݰh˜–h‘­…u1Èïåj¥$²*Ú²‡æÊÌGûÕUkýÏd[$ÁǨ)Åf÷I5ñÌÁ%Í*±ÙG iYpŸúõ"“Õ¶ñ…!ø0¥ÄŸÞ+ÝIÉL”±Æ–Ô•6;"åQ;tB{¶Pļð?ú°ÙÖbåzÊ RûAB•$DÉyb‡‰Ü1 ™›ÍòJu;ËZ­‘ëÅF ¦^ö®ˆjþUŽw:iw;g7¥6Àà$ÂÑ-NKžÂvä³è:^e©”#:äòò"òIƒÄ%¾"p÷,¯Ö»~¥.Âé ÔA¼K¶¤vvX¼9»“âHˆ™ó¶k¬K´»®û u·{Ÿ6Dxu²³B>4w^àj‡‚$£ÛØdv»Ý‘Ý.mšŒ Íjðn¼^-×ÛK'^„j ×,- |T›Æ »_Û(s’+ÜÜÜm4Dh¿é±½KsY$×ΆÖ3Ð#»Œ…‘?Ätd,íÆàzaØÝôW’o›Kó;²þÅé¸@JŽÆNwÊ7g±-"Øì”±C±’ ÛØÂZN(!×»•x5‘HíÁ‰BOU7Fü–ËãQ"p۬„/ç{ÑMÉ€NÏŒ‹üð•’<ÝŠB¿Ü|¼F¼ÃãÁ:Ž·8ôe3£˜{hŠJê § ’$„·tÝÀÇáÕ(Iç‰ uµñR0»E„]ì<«ëUfÊafþJ­B!Ø oï6|¬›‰Wþ¶ž#Cè -ʱ(äøÎfoANk‘vž·³+îÓȽÌ"ø”|¤OF‡¼lí˜ñ!ûÞ=ÙZiL2c!œ]RÜòÛ70–V—zèšÏ«ÕñC‚ûôÌ[ðw?ÄÇÂ슻ã|µžI›_8½Y +ùã]§ZáÀ‘Çs®Dê¸CÊ_Å“kElÌvtVúþIdnGrhÈO«Ï(…Xä\Ôuhg˜#)‹fGÌsNfÚÇÜ-²L†SnQ™ÖÛ(DÌCÓV¡ËÈAž9y?v«äÄW—d&« ô[M,e%eã‹v™–RÀT( †‘³K¯O ~L3å®yyå),‘ ØBÛymàär˵pX­ð;L U©61 g4S®uäoß]}p[luyMÇ3NË[Š45à²?S-ÀŽª¯ì‡ö= HÒÕ”Y”V—ê p’†+•懷÷1%¨94¯µ–Лî?Þ]¬Öø1ô¢¦‘ZĘwº¾}º…ÛNßXºä›TJ‚8´ ˜ÂÞ,†=1Üà#¨®Û”€0N^°…7»ía{½] }¹ÝƒR}ÇL¤•iek0q‹Eª­/3;¥ôQD¶‘3ЧÛÂǽKf:áçóÀS-ùU¾Ü]$~YÂãà ›jȰùwÏ.ÿ{ð"ÿTáf#Èê%+Ø+/­ï%·À5A¦Y}æ µô_%Qæ;h +’*ÓZŸÉ«f63ñáÕ#\1I¶À¦‰MæŽTòÛ»Msۯݱûq…³2ÅÒF°ë×nݼO`ž3~äÔ$ °phK„öýŠO˜#+·(øÊ‰_Ýìî,«-Ë­tÄ œ*l§ÝecúŠ8_,¾Ÿ$Ñì‡Ñ\ê|rË[ží·ë»@‡„¾z“¸ÖŒ¯)»‘®¤ÿëjPms“Œ|ô§ yDZ»¤UO¾Û›JA£½»»½•0ÈàÅ:b§çèq «ÔæPó×°7:ãòIµzl>Õ ØÖó(ŒC°”§Â°Û}ZÉë‘ÞòÇÝþßµßûÍRT>ºaE¬}$RËÜòÌ›­.>34À**QŒeýÔÒctgÖé¶èä;‡!¼–ºŽs›Å…ßÚ‘5ØMWˈiò©»=ÅUyéÖÝÊ­V9,>v­‘8ôÉ×A“šùx†æX7uC~û@¨änyãW ‡›Sež÷°[±0¬g‚Ó¢b¥Â á -蔕¹ -é¨ …äl©Z_Aà:€­Ršq¥ VhäGè˜LfGÑqY[•X,ZÚ'uäÖ¿AZ}ÀzôÈĦ(^ ïµ-¥øzSFNZéc¼ó%©ƒ¿#tðËMðø{5.®àõ,À´ÔM4) ¹¬„º×µÃ•Y%å!G'MÐ?ð$,e߸WË•_÷LKÓŽ<³f›C® J Ó§Hª– aáØinM´™h¯äÖ» ­îùxexAfpfc¾¿{Véãä+Ë—ÈZF )Œeô¡¥aÑßûª‡†•ÄC`¶I7Hihì~[¹{éwK'ìäné}öšZ$rˆ/”é"`11Ÿ6‡ÕæÎ­H¬©4·†i^J½(ßQ-. &/Ú¨¸‡Y2KcßBéã›9[Û \9žaÉ\ÌG$~'€Ê»å´Y$ŸÞ‹*¸d,ÑZÙƒã•Oe¢0 ©Ë>ÚÆèè{<µ¤ñ‡¢¡œò ®­¶‹Ë£|¹±]§_;wñ‰åZ:+æJD²ßºëìö ‘¤í¹ÜEC_°ºhž¥< ½ëÊ~ždšV¯µ»íóÊ[•ÓÍIVd’€‰V;‰´-²cxÉ-ƒ^5H *óoµýâXláʈ{‰-Ü<Û(Bn…’wRÐ%»Ip×Ë7;$âÜzC£»Yñê°IÜmùW VÇ›Sò(§#e7ºäQþ$u(îj°°áÞz¥N˜·#gMSHÄm[ÓÎÕŽ*Î g-] ÓÉy‘˜ Ì$Ržˆg*ùÍ—/_ùmòÃÉÅr½Þ»ÅÍÄcpŽWª«‡Î¢“9ìHÀð:yóò‹ß¹‡-X"y¿ê×=4„/í|Ž˜^í|þèÎÃŽø.“DÕ KÆV\3lÉÚÄ&{Âyš£‚îå@ŠGF GåËïæÇ¥Jy‘û¬ rîqÉ0}&Xàî¿ÞÍÂÛ¢:f8>î" ãRóŽF„o–¸m!Wª-ž|˜HÛÄk-.²zd†ká¤OÑÜåШïÛF(Ž—9@ˆìÏ3ñ÷"môgY«yów'Ø~~þq‚müg§2ý;!'öqBšÆÏ2Nxûßeœªî‰ÆÉtŠÿ¤¦_üí^´$C«9d'o õx•:‡k?¿ý\5ĉýÂÃëòg„¾¢öï|íŒÚFFm£ÍSѾ¡þäýäÍ›5æð‡²Ð)¬qáX+6 'Qù9’`ŸçBû¼p'êsü§‰§Œ'Â…Ç]BÙä@Ô]höäèxräMõT*ÌèäÈa ¼çä^Ž8[~3Èjî Û/¦„£)K|Øuþ96‘í£œ£È ¯ça¬¹ˆ0nøk35ûöÿè·ÇëìùÎÖ«¿Üõ:Ÿ }ï ´Œ¿;;-’(ÊhÁßå>–R“VqÓÏí6>!ûBñ«Ø4÷D¡Rn•ʸґÌ/Ùg0¿<°.™_²Ÿ›ù%kィ<–ˆQdÀÑë»›[Ã× ¶K™Í~ÌóòÅç%+îÐqÑlÕ}®‹(HíÞ ¶É6ŽÊÄmø¤dpy‚°¸Où7ÃÜçéÌ›Ÿ#† ®ôÁÉi½ápGäá¦LR1˜aÅò×iÖ%eeúØLbRËäŒ6ò¬[®wVIÁ8õ è\9ãïÝÉuÇ:ïØ—ÞŽ–ûÿN_< ‡ó0‡ÆmyüøB…EïOKá›0'%lk|l ›5¥ŒEB:ùËp¿yZÈ"€šŠ¿˜ø¬Š¾¶Nt›_iÚÈ{Y슄è1'Uíbëå~oé§s¦¿¶±{C]8MçŸT6 s4³×¨Ð'ïÖÊ¢ëÅbüé7Þ÷»åî¬_Ôq`ù†e&ÏZ¢æ©¹xü1“I|d!ÇLûö°LõÉ'V:Ì0¾¾¼‰ÖU](ýʈzÃL³­LÁ”t¦µÙG0¶îé$$Â1½’å˜~9¸ÂŠÅÒ1J«È9Qjb™3(ÜMefI BÄ1ÎÓD½ªòox) ­føžÐ‰ø`´Lz5þ$‹adl¡Èa?HhgŒSéåÒ"$5”tF_Q ¡ôòò,vkåVÁ«wx6º\ºLè9"2¥BˆhÜÏ‚FÈÆûˆ;ѱU’Ÿ¦‘š®Ó´ cåé éÝ1@%a6è¸7ìåª&Ð뚯V ­E„MéÓÕ*y 1~:Ï£®KøŸEÜ–JèÑ ®}b aPÔ•QžT1¬ÛïìGÖsñþÙ+šN>1ê°Ø:%ý‹)ãÓÌuø°¤Å)R93Œ²p:ÑjÉBfYõ7·Û«u¿‘ÈJƒœ@ø"ø©·V2§Gcµ)Ú­% ùuÿnË‹vÈëºNÊ å·ºé£ngø±¼LB,ÜÜîƒoêÙ†‹`÷ _eòóßÂxX ¢ï+ yýÝÛ§ˆ Ap§Ò‡ÆÚÒÅîhÚØ+v<„õˆW…ðù7;ä(B²­è¬™™B“înÉýSØé8Œ¦9LO:…‡µbøLa{‹EOŠû¸÷ñ1—Ì”¬åôïžàôÏ!lxO}Äãz+‘]ß“³‘lÖR0P¾Ô÷\)+LÈ'×Ðt7õ–±’hgÊé‚“„qëî2¦`´¯’jè²,гûOÁµõ 5“T.ÁKn8öe1ßU·`ågPs;Œê­óP¶¬XýÞ†V0}-¬\ùk&›×}j{ï'º!›ýD.1Òí0Ãwï#o•ŒÀ–,ú àÓP4ØmC'¬r&E&n¼UÚŒ¾ã4ÚïdœP¦?Q³¸Š´2梥®Ü™©†="—G!½ÙÿŠ­–aø›"沉‰QëH@~@_“ö€&'f ËÉÉ-"gñ€…Æë¤PöúÓêÝán×G1 9bíY>ÃöÍPbà¤ñ­Q¢¶î÷«?»¬û­»–ã£ÞP?ñ2yÏè¯ =Õ Ö8RƦEÆ/1eÞâç‚m:2Ë”ãXÓ{ëRK§pÄNÍidÜZboî"¢¦•&{Nˆºõ=04ëŒØ|Ga”_`âñŤó9®ì¯„óKÂòó°EÚA¤Lt£@.ƒ<Ì[³´1Mnذ¹Ô¶I=!•MAMõË«™fšRz]¦5o- ŽÖ÷[@ "®O£MU¥‘ž’ÕJ‚´ŸE>Y®T6¥Úƒ]íx,ü¶“Á {úW«õM<“U¡oEœ•Þ¨®–w·B¸e1n¥ PVdø8̪5vâˆ"{±,ï.1 ™YZ¨~-!5~‰Rx²È™è  Ê`«QX‹Ø³%¬¦,µ„Á2eé„Ï$’(€ íäÕj}mÇ$àâfyÖ²^ ¶Ðµ¶Ð÷…Ž8,äÍsB'CN ,Z{8¸P„, f9ñðRÒ£ OC[–Ú£†‡Á{E(«îÏ`y08e‡þæ|¬»@¼ tGØ7BµÞ¸ãb{½±´”"„/7{¥±t1!Sų~xÜsí$‘ª¾w'óºW´»BÖ¹~_„•áI¶OÖ²N•Çe¤4ÒŽ®,.1„²»E»Ë0Û ñÂC|´—ÿ¶EÛBËÇê¥ÜÂxg'áõü'h>r HÈÛÐK^Ÿc‡óV¦#ºWã¼ÏMÌ Mè),’óõópgežA9<ŒãÔT` xóü«ÝRp" U†Gƒ°¤à¼>_] }}Zj•ÏÌR UHÙxÌòÀÝ2¸åÆ6C”ÚïÇÓ@+DJ=Jò«„gYûï)£aµNü¶0B¼(¢µÙĪ2W1? ¢Ï3IØjWá–{ÙE³ÙŒcÚ¢›7ÉۃܻO ¬$ûþ/wýæ#“;©céùÖyºWââšq@föåÝÉNÑP~\4d“ÛlÀ c²êOüÿ—{êËŒ°`Ú~M÷sHäÙÀÈóÝ·~ÛÂý<~+Ž€ðÿO½i ®]©§/¢vˆwøì‹`9qw£¿õE€s/jã/êà£ç‹F«/r§syX;jõ¾ß1´U±Ñe—N~G]”Ô³O´e5óDä¼Ì<‘!aí3 ¸òɰå2qé|tkXÀ¦ô%Ã’ñl Ö_;-iœÒâWL{O$”›HPÒÃgõ0‘ˆ* •I ­ïÞ&ÿGòîpÅÿkòw‹¢S¹öÀB\—ñTû¡¾8ŠaAüÅÃ’O}1Ò??µã¾)õr~ ä³"ðò¼U]Ö­ãžà@ØL¹àéJÝÇ¿y²¥üƒ´M´ñ«:À‡û³™Ä•1Â#£uŸ‡~F/—ÁýÙ‡~žà?hÝÐáÁDä:“›ÓѨ‡9+зW÷Lö¨äS“‰‡L6ŒœlžÆ5à`Ûª!/3“mOp²ñĽs6šl{“í,?5Ùxd~²G%~²G¿G“=ó‡{üD˜ìQI˜ìIMöhÔÃdÏèÛ‹{&{Tò©ÉÙèC&ª»L6pL‡“©Wg&Ûžàdw̰us–ÿíɶ9ÙŸ|ÐO6™ŸìQ‰ŸìÑïÑdÏ<Áá?&{T&{R`“=õ0ÙsòöaA4Ù£’ON¶SA4Ù]í';Oü7'[Ÿ YEÊ|g7gÅ&[ÄdúÁ0ÙÝD}ÉC¿g'{ø{<ÙÓ'd¸GOD“ÝÕ÷Lö¸ÀOöpÔM ËÓa@ô}¿õl\-›é+ðûø ·Í6¥_>i ¿O›2…núaiNÛbÁܧÏ0ÄNÁˆ×D»K-!©!#Z¼"7z½Fj É»«]¿:“bö+õñâŸEWA2V¡lcdèc¹6=¹Íç™¶‰²Ôνç8µþ¨cÇR¡s{•óõ΀oó‘¡Ùœh€`i€å5ÛèäUØj»f’ ňÐ\—(ý¹EÒËK3Çk¦]%í#…ç€Ì,ÃH<¦¡Í…E©O,/´ ÙJ{¬ÆP0³0¦EKÍ fÖôJï®í~ïáÊK©_ï ¸'Õü8쪓—ïÞõû˜óYp?ø¬› ?nV‡™!¼(ò63 ÔZ» lbm &¹n\õ;`¿‡'!2”áJ,e‰Ù[õ…¸¯<Í\0‚Ð>X™!®Õ‚ßÀì¥mtv×f.v¹È§+C7^gŵð3,îR}qF[K‰®ÁÛùôÆÒòžÐk– áx]Ä豇©–»Ml§NXh³¬¶w"œíÛþRüV–[¾w`dë¢iBñŒ±ˆ‚|t´š >¢Ñq˜®&¤;é@ ¬I”XÃ/ôˆf¹=!Cª†®.&Óö,løcŠ:v©aDQž>AD—€Ã i²ßJàM¦c@Ôy––ô|\)ÐmiF÷ZÊcîq5­gZ4ájZmt,®Û¦’‚‰´îjëÇä‰Èø9^7lª:Ó¢À–¢ë“9H³=Ëàv’´Ê=O3$ñéh טY•+íÎt¿LƒÄʽ]¹œtÆÃÑhg‚à0ÿ”Avd(l£Ä€o‘˜ò‹m3·xâºïûèsø%"–îO€5±hàÓ/©…ú£2“éü5i­…ö)vÛtÖ$r Än®pÆJÝ©œŽÑ Ÿ7Ë‘Ôrâ)™Ïŵï'¦ÑF2™}$FÝÁØXňᄭ˜ ‡VÄj÷99vVAE‘qèw·Ûµzã‚a¹Æy‹jS™L›4Ãb¬âÂ0z¬tŒ‚A ³B je*TM> ¯ß×ÏÕ·/öz/s­ƒvöÑ2Lƒ½qi~ºÒÝøŽL×úùp­%ÑÀÃ÷àdfÓn7ü`æpOýMbP”{øf ¿hKý(f0\¿úñÐÿ°Àduµ5b˜^ÜbRjºÎG¾$Õ~ ÄÔ3b¼»òàjÛ…­åq>€—V>¥ ôyÐwXiÆË¡% æyAIéY{ _8äb.¬¹^laÅ©ónkÚ+Ž4yYÌ>â‰Ù3ŠØ§ù3HÉw?‘/X_óTB;5¾ñÙ‚¿øIjäJUusƒU÷üay À»+ê˜ÔD©±W‚]D:ÐBšŠOÇÇå·æÝÃó[Zù­¬ûsæ·æå·N—ßêZ¬ÝÆ/$½5Áé1îeAÎ5R”xÓË„;ö”×5;€qlKS¯lKØéòõI °K Œ:ÑF®½ØèÃy G²Ã4ÓîsvfåŒzÎ=yK®×âq‹œ¹]m 3goæ™Ï´UiˆT:údÙ ô)¦¸„—׳½°[¬vØýáÃ’n¾ßôâà®dÌÁ=F7ˆ;V£ƒÂ”’šl1xgÇøg9“@å’µVÃmeG I €.á¬wg,Eƒ±ìU™·š˜±…SÔ  `ý$çËëv|V«.Å=l¸~†î›@ÑàvÎó'ØÔô{ò›õígôµzbE1˜…‡.úçݪڨ+·K¯ó1¹\oÏ–øñ‹õöÝõéB|ŠÏU!0s[8&Éi-ã+[>žA„rûPru‡4­C°O <‹×ìy'Ä<Ñ&ØñãGé÷ô÷ú¿lúûϵ4©ÿZYëŸqùuWÜ:#wmŒw“˜:§BHqÒL[ðóä³*°U¢Ñ‡&´Ã4y» !`R@°_*Ö½Ó>¿ì ±Zž‘µ“Ffƒ³-1#—:~• c»´–søM¼héµäÝ+‚¤Pz#¤%›Ã€˜æÑ4Üî¶üsà(È @“»ý‡Óg S3©ZP=™¼u°Õ ot@ŒÏž…¸^,xЬwe¦7Ð)¾|w}nh^±0Ú™ §køhêJšœRÏ5ʃkÒ¤kùAlCº¦Ëš±0­‹M@<È-$Ìuìj~b-ŠÛŸO_Ë9Hx%yBú%BÖ* ÙÆU‡ÕV#sª^öÝ e«¸õìoq®×ƒÀ0Ks†9ðä#Ÿ5Π —&p‡D0O®Ø…mh+Z»Ñâ…”#nD·N‚^ŽRŠ=\iZ†,qfCÛK€ÿÉF•ü½§aß…Èsu´|%ˆ§úä‹Ài¹Ù¤|’ŠKF•¼@sj¯B+e ã·EåT”kMš6-VšJ¢ð[\ô™ŽŒMº½= G߬\­&,r!qx#I5 MèWåÙL¦· [–êwºr{õã~uí—½cÛÜâöÀwà3¤ûÉ”çZ† ­ÜÀ„V‡°ÆŠ¼Wîåëíe GQy€ÌVã4jZ‘çoÉ/nÙîPËY9÷Þ¦’U–‚¬ç©¼b„¥`‘§<ÇDX…]Úò ŠÒLŒàíÛÐj÷×ö,Yô'2{[;ÚÙ#†ü¯½&Äyæ_éR@I°´°™ÚG*e%Ñe:Ò8Npü<—Ö¬Ãi¹¼lhti—±ìãÃÊÔXJÖ˜ÐV=úD$w  ®|ñ­¥?M°Z£gD:~}2"€¶Cni6¦°Àï”™­™,^ ¸\23{6RŠcé[`1÷›w}°Ó“É^ÈO3Ùë–ññéé–e^aÄ]R˜4f[Í¥¤òtmÞ)šË€Â*÷¡‡ ‡ßïs@k-Ÿ2õúd ™¨H‚› )äYÜx×@Õï½ÏÎ2mQ„KIlj¥MÒ„$Y¥)Y´7뢔"8¬¾ê׺çÕܸñ˜m6Mi1Y¹pß–„Ü̼½þ8¦Äɱ¾@ß6ÉÛö‡£–+øþa×j;2hÒ‹ÖX;r„Ärãt „–r¸n–ê,²Å¿)2Ì”K¸-7y˜Á •˜MγY0iç]mS¹9W'sœ2ØžcÆiØ0W¶ÄÉ›æ.S¡L@ÊxÚ\ö4ÐÒAc ‘ˆÔnÓjBFMˆ66=^Á–Ôi:,´­¡­ÌQP»ó¤Ò>|IÙ¬n¤Á6üÖ>H ô½¥uÐZޚɜ±\Sýx-x€†‰§ê9«*IW½3 ±\ÜA>•ÎA¡)«C¤…ȃóy’~á§’ŒëN•ífÈ[Ð¥ ’QfŽôw¨Z†T-ÅAjYzH®Ù±d—Àù¶^¿` oNk¬ ”fX<öBža^ÿ¶§û$?ýØÈ‚n!E>úBsãu’i ô¯~I?a4¼ÙmÏÖýMÌÖP•Riت‡æµ„ ¶“ÛZ4£0Ên·œ;ͲÂéÀdÍ£êRy6–Ÿ…i«˦£=ŽOÑ! éæTm|OÅò mßÕÚUxÉÀUÑÿu@WÇìÇ»ºù¯'íJŠlJ™ÖXMŸi›4Ý ‹¤ÔΤ"ÄœoxUè#>üE7!’¢ð;–íùCRøSŠчiTɆxUs~î÷n®šH‡C8-ÒqÞuGR>/®¬#åñô{aX[〽ƒƒL”vŸªhƒGù鲞¥ŠÙ&œ%–>µÖ6rll1 CÏÚÆ^ŽÓåWZ\ø,«ÌŠ--s —,Ù¶, °ìú½_4µ,XÌÖȹç1$Ù«þ°[º­’Y¹x»×8w~> —+0K°¨iÅ82íµÀ’q2*óŠsºÖG2ÙξBÊ xdo˜)EDÃ9} Kb—Ø5v¾p¥'>Ã1pFÒÕfUä¹GZ)ÅùÃ%Û£¹®H-ÅOdÔ¹ Á£2Y™«Qy2¼°®}«SyjÀŠ›FÌÀ{ÐÉÆT{bVÂ%›òô<’P {—aˆÄ®9‘]U:9ûzé *äw›½X¿|¦×ÛëÕÇ}âºwæ&€jfëã1èT#²-Ô¡s¥lØN 0=[©û³ç%=†r Æñ|P6•j[À¢éYæMX9J²rþ%GÈ'Á±Âa?ø8`ŒuÎóæPÔÂfW´X+µP_I,%éwH&ÿÿÿöþ´¹­$ËD¿¼O׬ÿÃymvoUãÌCæënÓCE*BTF¼—7ú…"H" ,”"Ôyÿ{ûZ{ow?çÔ*2oUÉrà~|öí{\Ñ=em€¡u4œ´Õ¬‘¾ñ‡Q!'R:Æë}?Ò>ˆµ 8×ðÒÑ|2¤ “²Q'Ax :{oàîÑÀóÐ|¥¯!–óuFéxð¹c7^P‰Ñ/¼-¼ÈhÊVWÈYð3Öy2÷±üß–÷ÖY[¬z³»q-vÂÓîò ¾Vov·6ì\Ž×•N6:á{‡mwát 輿Àfòè-'¿A³Ø1hA•Ø÷wü¥“7 ƒsD•AªÐ€(oÈ|¦ûúŽ Ûvx*,Vmç‡]ú1£“~- °žÔ‰&p¤–7A4PûæŸ>éõ%w<Æqòr€É­k&›:RùøéÓç§§ÉŸ¿ûY ΧkX\Íu‘Ju#øÌ%KIÝÍì:gàsÏCþžx»n3敃Ø?§U;ŒdŸUKrRgNŸ÷)F\Šî”ðv³oÛAÖ€®„¸;öt´Ðìȯtø×¾¥¶Šk~È ”ÌPr‹‘ýçD£*Å(üO‰åûÿ$ä˺ +µ÷  ËeE^ªlO0~7ýï\üºµêVx ?,+FöÂðM6ªt “¹·ÀÊ}ÉLPAó\<¥‘‹éá€gð3«š\²ËN¯·w˃3ì§O¦¦bã}}ç/¸¦b¬]9”?[x)£\ü?CúTi–ÉV8½4±(à % y•3›>“ÃûäÝn-ÕbðVcOa¨X>öÜš¶O?ƒ–¿˜éŸH*"•¹~)Í=ˆN]va–ÿféÍy‡Ÿë™*Þ?³m¦u8†Ì¾Œ­}ùær ‡÷t‡€ëb‰ÿ -é:MÜ´¼Ÿ~XÄ]§»õ.Z>Íß„¿x¾éoZŠäq¤÷Þïø=Jè©Bz­_Œ$9S’¥ZŽ%! ¢*Sd³¬¶*QÎQÓVV:±ˆÈì«•öNáR1—3ï‚çK{€††µdkY г·Ê‹ÇGN#œ4'½DV8à„IéÎ$†ûpxk¡F‘{¨1}=èÀö ½Å #*5z”;É ‹q(® Ï5ðR‹pƒ—?jä‚×D{¦‚Ýx†J«@ÍAw-óbðHXu©ãi¹›Ì&íì‚èŒò0ïì´²VLbŒì×=s3ݳYe¯{6²À´žP°d”–Y°ä›Î Î,è£ã× òøy¬ÖlµwŽM ¤ä’’ë—C-#ÒNkO½è)»r¹Ã|g™E-¬&ƒubÇ83Haü]Á=H©ÚªD(gÓt_J…­æêŒ—ñ-q¿f×Éu©{—ÍÂ' ½×Òˆ¹ÃÑ5‚·›¶ë•éBŠ.º’¨¥šÞãþl›rlÈ+áMÝ6 [z5›d'RV Qüt´±™}ºkš¢ÔÒÞúÕ“?áêéÞî‡2\ƒY8X Jæ®(® 40Id¯+!•ÀÀ2£~¥÷OÒ ¼ìS¾Þ˜TÛˆA( íBaØF? LÞgC?äý¼¼8Ib—Â)Ó'4R ¢Ñ“#ƒ§”O–ß§á;Úìgë>j¼Óݲ‡47—døû½" ^‚àië*ËC&¶‘év~èt†Î£ÎÞ•Jzðxz¨îa!X‡çÌ«>‹St­ö¥¦ˆRšÈ·¥%+E¸…æÐ)½âÙ/l\2ÙÇ|¤ú!öøñÝeüàe`Ÿd¦žî›´´É4 ùJtö¶Ð#0]³ƒä¶‚žkóæG›8ëÛ醚òp è˜æêâÔú8ŽÈ pÉX¯ïŒ¤â|mÀ‡Ë¢×W7SzIéË GV ø²Y½] o~3€Ú”ÖGw@åS8nHÃo_¥RÄÊ)ßsý‹L[íY3,H-/G]šÕ>†œì||lÎ$ÄbÂÐc¡Òemã*=‘g¯ôqÈ–ãè¾\L·ï"!1C’#vÏ×Ï4ÙMjry‘¥jdYÊ^iܤ²ð“*ƒ(æ6ì‹áÃãßIÓŠ8ÐÃV½ÕÎ!ÐnVŽ3š"€„~eŸùø O-™R…€¶Là: ù[ÁòŒþþŽ©ŒnÅA¦” ^#u–¥Úa¬|ð„àí(ìI*ÅSµœ¤H"×t±£›%®£åUø€L‡BuT•âWå÷4ZÜÇñ÷¬â”—TÁ< Ãc^™—‹c6–盕Ftyån…àZ¸¡};_¬Îˆ½?B÷ÊI•ý´Û?Xw€t„pªÛÞÆ["†Ž Öxÿ×ͽjÿMþ<¶ØÈ»íU~Û†ŠdËäë‘ ¢Þ‘š´Ê$óS_áTi~©‘b_©C'±†ƒQ†²Þ9†Nû‚cÒé|y?P©M.¦K;¾á=í¢MÏzÈOImÕ÷äõ8Z2‘"ÏÉÕúÙàA±TG> ÒÉÇ£\?˜«ÕU/I!s¹TêžíŸ„`5±H€¡g¸ò3êeŸ— ý¯Ð4í¥w]“jq­$t­:¿Æ2ˆs{”ÀïC¹ÓYßÊñž7c×F{3Ø©]–'Ýs±ö––é ’:ÝËînúásÐ6–d”A„±®¨±øx…½‚Z™Úª$ü²W¢Ó$a”Ÿ/gúôÒÐ…´2bHhLêdŽ>ï`׃¾Ür†Ô¿žž¸‰ý×GYõ_£F¼#¡:ìW¸œÉÕÜMï'wJUøvus»f âá Wµá”øëÑx4õܦ§¾c˜¯x“È­=MÅ j'0“Áni*™œv¥ú‚Õ—^ä,F1Pc†üSì³#Süv¾ÙÌÖ7S顎}#ƒkôœ-¯%,Â<ÛL\ÒCr"»”]ª ¤Ü¸Ïæ‹ÅüRb|¼¢óó¢"=m©Û:rG>‰ «ëýÄ-<J¢>½–mº ®ægïÞ ÆÚrªLýÂÄÖT°ŽæwÕ«9¬Šij"WY…uò‚ÌϽf–=É4b´±–‘EòžÑÆ28²Gj%¶d¢!f*aàH³¸ðB“Bת'ú¨Ëj]b¾Ø*ÍBn ï¾ÃÓ?H J9óÙÍõL:Ng´†Lï’àóp²ÐAKȈcaUàù³gŒüe6‚÷Í´¯¹ºº4';üMiÃÆr¾¾Z#wå2&ºeUú~܇ù‚ƒës-†ïtO.‰$ç‹ÍìuIªµ ¯“_ôXƒq\Z©3c+%Ãs¤gÕTE 5ÖÉzv~'yši©Âa~¹^½|T»Ó¥"#-ûô0™­¯fp¾¢;n³gcѰ˜éÕ?2C†j$•` »Ÿ,P€`gPÇr„ë¤É`Ã"à¯ÓÁîLôÏÌ8ƒ^Ħ¶Ÿ{Œ”‰|ÂN`(G–É“Š?|X´Àœ¤ æz0iXóLmb2D‡lÓ2r¦˜úð˜Ã@iýPe¹©{³Ãäo¬‚ä0ÄÜÐ l;5,9’’Êö·â⟟#ŠoÄ Òλ\Šk¾ÚŒI•Jq º™.â,à ƒ{{„^%±ÜØ_ZU{X²¦Ö»Ú=!=›>ö½Ìï\wŽ4@M¡ÛõT—ÞÈ3ì¸ÒÐ@¼ôœr©cDùs²ØÞΠÓ"šì(‚[Df-hš4£•@‚8±µ¶ïøœMø»_fæ+Bć\'¬Ö7 y"@ÕJ€¿ð˜ÅÏDk)“H¤ ïÙa1A¾ùÊ ˆ¦!×»æ~BÜ“.T,‹pw“ÜG-ð¯12‘ L¡)G-µŒ c -y·ÿT6!•S¥v&aÚž*y€â[¬æà²ÑÌIÚž,Me‰…ú@Òª^o´ÍHÚšÁÌN‘³–YÈJÍh4öÕ2÷Ðéuì«e®%yªUb$hÓ$1"9‹,¯±qH ÑñßyÓ£.¬gpÞšT´*C'©Ògv|JÑÔF¶‹ÛñY“°•qÜëÕt{’œŠGÜåìÖ ¼î¹tåÇôê L`k±·ÈÅ–HÜÔÚG͉ugZ*æ°K5¶häŒwæV´;´kΑæ…Jmüñ*!â]Fð-œÙ{irNË^Xª™á*?&Šõޝz[˜®ô¨P294’†…«H4 qËLa{÷vöúú„·eÌ®5Y]lîO÷I1ɆäxɵžN¤Íèõt$«2_mÇiE¾ÚáÝvDlŠY?};ùIåVCƒQ"hdï6 rúCïI òäÙzêFK#È’¤kºHÌ3ጉ¾ïÍ‡Ž°ÈˆgâxƒV­¦®ã¯@\ ïþ~ÁEh…l#ˆò†eškaM„Ó‹ùÒ _Œà0’‚YyƒÚr ¦ZFó7@ƒæGšV©D²eˆzðd„¥J­B•Ùÿv7]Ì·|a&üYnP—[â¸Súd¹­€ô-²«ç$gI´¢•AY¼0Rù8r®ðbOaK¶Áq,«Ø7‚Á¹,®øí…W1qÝ;ø~å|ǧ2 ¨Xecu`ûz¾Ü¾u‡pq§iæs•m™Lµð¸% 2 \ËXÉîj€~œ*bŠ¥Ä ¹±H²éʇ*¸ºwwš¤Û ë¹:âAŸZw;5ØîFi…¥Ei[cËA¥Æ¿†Ýå÷æáWTŠ eÌÄÒÚTáåÄTÆ@·Ô]/Ƚ ~ MÁ/³ãZ]ñ×z‚%õE¦–W«¥è¨ OCiŠXón áðmM \2«®hùΦqüs–[óQP·Y¬àŠ"f^ýñëÓGï.Þ¡%÷ÂYº¢²¾Ô[ÍgyÖAD~߯˜ØŠH~ÅåÊɬW7wb`1°÷¦ÊJÎÏÛ@e=å"…©†Ï0 p&Žþr·™â¾_ šQ¡Ú’:Ó¯£Y+ƒÂQ2Dhà?€r]³µã]ùÂŽ«§H`/õÀUQù6ÛlÔBm÷9g(VÛö¦Í`Õj´O—w\¤å”YÇ~L&wTyÔ¨a)yí§–Ñ–ê6r~qÃ,ô^²imíž»ˆˆ’†Ç‡>µ¹f¡§Œ2@4Ö%ö¨¨Ó_ÝI „;˜Õz9ÿu¶8‰¨ZQk1râÎg›íXÕ‰l0)…i«3­ƒƒëJµ("†Ý¦:pWX‘+Ř2ë,3Ad$ç]Ýd×Møì˜4Ëp¨g¢×ôfã’¨©‘MÑRiµÄgjtÞX°znêfzêržnIëPâæI0ÿâ5¶…=p}@9|.gÐL6!`;‡‘¶;Ð&’VÔÊ2òm«‰Wç]"ÖÅ!Ù„Ú\?„ªôÛÕf;ÐefáCeSÍ+½Õ!nFd˜§Ã)°V­Ä6•]xMXè¢Ý!\_™mìÏf2\MQS×# 6`e×pë8¬³j—ÞëÐA ÷óµ`”Y>V˜\èPZ¾^½ç7/2Ì8WçwâÈ‚e丂à‰;‡ËU&gó­¾àÛ¨±’ëá¶÷+pªê¡d*}xXJ…¥9æ‡àŽEl˜úi€gáHÞkáSê‹*Z~Kl6HAèïLÒ©hŸãüÒ‹ º=Ì®%Xï?Úi/ýhŸœ¾Ý3Ä'ÖÖ#,+‹ta4!õ0%Í×¢ó6ac: üGOe-ZU ôiìäSh)(ìÛ»õyÏnWeVÜ'@:Ýùm*¾¶™¨Ÿ¯ñ,.Ïç—šïX%¼¨5Ècz¿X”QŠsÏ@JÌᇠæ1Ýu¨°ÂíUŽ•Å) k`d">óf¯ŒÏµ¯ñÓg¾ _1aUaïÍ^úa‚›®çæ'äØ\×"<ÓvÔ¡ýÓE(ÛÕ|1¿ü©L*T˜5œr”AÜÚ±zÆÜ>½’6 u´B d­Ž%“Ò]JõkÆŠñC°4XUtÏ ‚õh‡ ´dê¹G ˆw «ôKè¿úo¯Â¡Ì ÅQ›çƒ9TµõçûôÑÓ»³Y`Ö3xôíü0šúÛÓ§¿‘"…qf%ˆý®Kk†Á§_½ ÷ ]@ŒÉèÎæ¬FØÔê'C¡ÊçÈi¤B0Åy^ø)„)þŸÚc•Ú>äÔ¡®D£HcJ8 (^NP‘ÅA J’!¤z*²¨Wân±yÄ¿S ­-M‚y£‰óh-4èrÖ‹E*ñ ‰¨ ¯ÒÒ ½¯·V+‰¢3a$-¥-½ÉD…­rRس¬çIè}[ý0DNŒ/k5ºävú™GÕÅX 4%lÞiÏý ñ:óL‹ck‰E¶Ut¦*NÌ„¢ K¡² XîTÈšÇOÕy15еw û‚Új–V‚z©Ù'‰YØ*Ì´½Á©%Ò*­´–\3±†¦ÐÂ<í)!’à,@OhT‰øf¶²VŠFQŽµÈµa|öfµ6s°Hkæ*[WZ+c„¯X$5[˜Î³µÉÆÞ$”J•ˆ>éÑ3œƒ’÷©Âà³ã*ÈÞ9…wö +³p{ÊÜaoqRÑÙ ÎC¼-V1^˜¶S¸•GªªUL!eПÀ÷¦Z “ ëð^ AІyvÚ¼ %êrkp-Ú=ÆŸ»­8Äi47Öh‰A«¯‡™ý€mŽÂ±g‘H½¹˜dì '§oœªtEc7…¦è¢FWU´-AÆÒðÙxš‰ˆü>ëŒÀðÊÔS¤ígêùкÈÔúŸ3SÏI²#ˆá€œ$U§æ*¸µ£„"ßM`j˪µ4&UÏÕÄl㾸—T=zšJ›…9r*á2Zäc©-€¹Ü…™¡D†]Òß)ÒÌ:Eð ³P=«ÝhïÌOe¡X«ÍYßV̯X{M*ªõC\î+‹y¶‹`£¡âsR?•?&Q Xfi"Á2 UVZ¡IˆCµT*P =>{ ­¡èL¨[XÖ˜%];2àØ‡“ ?8ð„æÕî óêYýOó5 Ûú Á]Èø;w [Úyíæ[Ç‹îMs}BPo:‘çË{0Wd›É¢k„3˜xC­É&L@ÒÅ ^ÿŒ~ >:£Ç¢Põ4¡Ú°8“N‚ž‹7+Ž!!%QòÜq[ïfómCˆ;gbÍ(q´Å ²¾‘hgÜÝ!Þð{å<@‡¾¿¸XÉž32ާˆ~úli„Þn/àd#~…äåÛØÿ4³ø±BÎÂØ½“O]+Ï«•j#ؾŽñúæ&QóiÞ“ÙÛÙåöl¾8ô-µÅØ{vw>Û\Mg¢\±°¹®Þˆ¥ÒD1Àì çÅÔ^-w!p,jK9d¯ì‘x®† ƒh$i D18x€¥Ü.…ùEØ ½Âò‘WV&—³©cTç[dMnÌÖQßžÍĸ„òŸ‚Ã9 3aÂÌ]Âñhèx¶€U-®Ú³‰&*IÎ!èáÛéÙBDˆi†_4.fžZœK®i@*D¡/—6b‰ª0É£–$%x7‘Fd!ÓLka_o"${I¬M²ä¤…¤ Ù\2ðH¡çQ0¤»Ø$d#Ól%#ã‡OÎ^Éh("uø4²÷eDÆÒ”tÿr;gaµ¦>.4"g„ÑŒ”«ü”2Ãür¾š§¹I"£R–4v³…õ}¹Z3ÃS¹?(ê© |*qJLŽž>ýæ‡H­É¼|(„έN3/¼@›2 –òYFÔs]ŠÝ'Ãbš›C!–ÕmݧkêöîCäW*; ±Z-b.¾éúõ•À†G[ÍÀí^¬ÎgÑbµ„ì “¦—¹…¹oþÅML¼wTuPIXM|@çB`J‘o‡Drs3Œ.J‚ý¬«¸­ !‡xÙÓt`ý,CœX‹¸.ž@ÏÖâQç j+HAlî"½›@ ZLCG¬u­nòg±™Bc½@=×\TŽ„w"ìy©I+˜*rR2+¼éy›ÒUÇÝ{cö¯!±P¼²Ó!=ÉX cäZ&ã({ ,:P³rfRÉç^2}eÕHÍ.¸ºl ‚o|ÐŽÅõt™~3$à¦Ù¾ýhÂßl}%E*+#œçНIòx¡nVo€Ÿy·Nð@ ;"Öz§;Åýò:'²ìÃ;ÃXßÕšÚ2º·Ÿìuî¶Hl虺òDê™ÙäV§Žoq>б%©Wœ¤›ñW*hÙF£Ê ÝëÒXdÏ¢“[Yñ¤lÈšû¤Ñ k…Ÿ‡ïƒÆ€D^M՗Ч’ç$kÙ]©À:fÃ(5­vd&DâØádÂz‡· ¾Ÿ#È®îñ;4ÅdÉ0ÈrÂiâΪz2Ï¤ŠØ{×ag[¦L¨4V/šìöëC“TÒA+$Öòìe%¿ï>æVK0`T 4Î̽ÀFcQxÔLs$=hqÎ?1ÊórzÆÛgOB¶}Ë*½jËMgŸçT[­‰¹o«i¡2ÕmTßg÷6uqÔR3B¯6>ªàlr ˜Ë™eÙˆg-H¼–âH{®–€kÓˆféÇÕb!›èçÍ߯g ©4ƒ‡{^hËL%v:»FÆ^ñ#1»0ª3ÍëôÌ|_|~¯¨p”¸¹2Mð¦¨,Ò(³xøêfÄ@—Õˆ1?,²E¸ªnQ!÷Åê-„xA­’âQ0÷ap±YN\<¡¾\Ootj¾Ÿ~a`Ì&¼'ØïŽrÜ"hŸ)Ÿn®("h÷„æ=«Z SÛAÏ”6Ä“U=SɈ8ÿL¸[ò¡Ùn|<ñùMxX³\¦: è ]‚ûœ¡FÏℽƜ—­ü>N@”36 ý©¡t¹eŽáŒ{,۬߰7­7£†= ~}ͳ§‘Õ]mÜê×üèÛÕìâbî„õ¥âæ!Ÿ¶Ž“£³ùl+áœY|ïP¾ DHZ5„:’Ð5G¬.É[¼IHJ3¾ÊÙgÓ;úwE>z$ø01<.X/!ô¯| zr£ÚnÀ¢±tœ·z,¢ì`>‡ÞåPÝ4[F„ Xï  V6r–uT²ÒQAu¬òân³Ì*‚_¤BÓiŒùBøöð¤;EÉîsnüãW/b5J#%¼5þÂŒk>$íŽ-h?:Ñ[]:ÝÂL„Ðs/€zß®¶élK ê‡î‡ ºö¤ó$TÈzšÁ´ôZ­Ôñtº›p–cSVÀ°ÛË´ÌX&·±“` 鹞N#ÖÖ«!à3+U &‹…(‘J³a–^ vã±÷ë᯶ÎÀ0G?}süòø‰˜dKwTX+FtoQskd¯iby«MDva¦cltGCNFî0¦+•`Mz$HŽñèÝÝ#þ”a TœÙב{ç ì~"mú^,í䟦t×ë æ*‘)@G\Ãkc-+s‰i¤Ö芚’%ˆð®¯Ö³›¹Š)fÚ¬µ×YX(N»µœW'ÑåÏx­)˜·$}e¹~‹HÐLh×nÖ¹Ö{N¸©”F êö”QQ6[¢Øu¤G-L¯il¹ô‰ÌÝókËqç²_^!˜f؇üàDNiº ^KÄèŠ!{†HÏ }`îxLF‹¶ÌrP)ž ±MšiÐaFáak2%GPZä¶­õçš´ˆç‰Y§))¡J…cg§¨¬Q8ÜÓb@u¡ñ ˆEyü°câÅ/¡ƒ2KDäWvÖk¸ æ4k­hÑõÐ(ç}@*ÝèB쥋NÑV{^öYÛC%4|‚¬–J9›»³¿Î®EÍ4aÈ+ï±}MójÜô4òDïMžZò‰º~±Zo/g AtÄêIYWRIÜÀL¹8@[§@Pmœ—óEÝVÖ*Zdˆ?106Hç}<3C•6Šx‚#Úᯧîœ>2pùÂÂä‹“5Áo¼šÍ%(ÄçµRr ?õ`‰Ì ¶“Dê)]rH²È=‡A^U·¬$%PŸÍ#hcäUËzà)J\‘ã†ë»·äÊÌ£Pj,ƒ(-ƒnÆŒZ]ÕcV‹@„¿Iµ<´=ec„T“¶:²§’5ï8âOE|ë 0`ª¸$rýóa54I…¨"m :·æa˜¦Ã%3B]ÛèÚ™÷yÞI à c5ßÔ¦ÕoèÖªq\Á3(ü¤BΖÍô2¦ éhyH«“¬j!$p ³}àS[®?Ë3ÎéÁÅÍœZܵ›é|™,fÛ‘WÖ§ ˜¢÷gpnøðz~ ¹eà>lÄÍçYbbÉâjlîÖk@&›ùù, T4h¸2ŽAÓjOpwôz6]¼ôƒ]~¦ÃìF_CÊŽFmõ™N2ìÞ%ä8¼=_¿K6·³×sÇX!êk¤i-Ó ä "|io¢×ÊWRHpÍ·Œž[ð$R}Q‰Jê­&P„¦Ô©´º o-ñ‘Eúp4ûÛ³ùvó…Äs˜+n©å•xÃ>µôÌÖPýÌóˆY•†ÞöÎÃ¥¹6@ øªˆæÓÞúVç¼ ¯Öž‡TëDܲ“mèx8³úúëwâ_kN ¥²}žŸ¤•«’„8K‰Ê²ÆÓ$ŽÊª …"/݇„rè=ŸŽ“7®Ÿž©Š“ðüWHðpTžð÷Ãøm‰™€Š—êõº#ò; ó IJÙ8-ƒ¤j±æ_¹çE²«gdÍœ.èÏ¼Ž d2 "!IyPD¦ $,Cͬ–ƒó—I8nKå<>¶&W¦VŒ(Üxõ³ƒQT³ÒVy€:Wæú;2±—S„wXípïÌPÚ&€!"R¢ây/ÝÁ(ü$h' ÛA‚íˆíÈ®¢[Ý(høîn<&A­ sŒà.pÄêG^YpÚ_Μ´»žIÌŒj‚jk$’ÅUäD°]gÑ4³èv·8(Ab^B—/‰-ºÞÎûˆD*é:„ úZ½u1Æ 7ݶKj@w³¾dàø»~†± ä—•†xÙ<×WÄ›xŽZ¸\e°%s¡ :Upˆ~X£úäVd²JKûC»6Á/Ì5\Ê3ñLÜ«x¶ô}é2-¯¸Š+`vEZ“¶²ïÁprJÝ›ª;-å=zººq·ç<>ôð¾e…–®óÔ=›;Sj=C |êF»^-&¯ükZÚbbëVg„‰7L|:ˆ72ê¹ Q`>;}ñèéÓ,r÷j-CEÜôÏ“žŒ”5Rµ[/k5¡/׫íêZ"w2ÓÙu]!U¢pkŸG—m—We-×®Œ zK°f¨C;«O.”°HÁ'D¬_ßÌ—’>È\+‘+ž5¢¸Ë?fC hkÇÓ,ƒšQÖZILVÞ´žYϹ9Rd´ xÇò»ÚœΦËk5™B³Îm€gxúì‘“=úh)õò8d\ºšÐ),*êfu. sóyþîÝF<|dÄqVþ" Ê-øzŠÉIÙI1˜J qÐÐS« ™Z},1Œ¥ á ˜”³&¾‘ k=ä©N“âÄ +æ5˜I×; ï2(y…ˆÀ3”ð>ƒR+ä~³‚V †Ú^K°Ý”O!Ó‡'os)8A»òøVTá–²×Á%5/ÿ”ù»Ùöc®§·· 5%pì¥k${¦r­¢¶Š}1Þ%Bo¥ÜÍà'N›,˜§ Š·ƒé¹#M(ÓÃ01Š—K· ^GŽw]u‡Ÿ\¥’¦ŸÍ¡VÏ‘>:S5¼O›©)fúTµ1–UZ»­Zëûâ òÖ Ø™j¦nåÞº›e‡£´ÀbG¼Kâ{´ Œé7-vˆ]¨4âðt&pÄCydŠˆ–òKøÎ‰¨Y_$ÃÞw€¿x0w Øø(ŒÖ‰À9‹bÇçý;Æ‘ÀÑ @/ÀRûîÉSïúvHÆëNf0zZØ0S*Û!' d)P“ï½Â¤Ü…¥”îúÉôõõ[ÇëoB üÈ÷û©‡ê‰p¿?yþe…ø‰2¤íQ¯3øUàwà÷¨v?:æ…êoæž)Âf~ãâ›ÙrKIáQ,À9ËX¯²,xâ55\©B3ÉM7 Úèà@A¿ÕyÏ#”ÜŒV“ø”cìo‰‰œG²øn@ŸQÑ©~ÜX[êØ†óÞ^*}ÒvéN¸“ð&!’ [Æ aHpC45d²œ¹zgDL–»~ øšwêV·á[HÍDKýÊ’F'£LtÅž Š£ÙhÍ(e‘ÕY•€ÈnÔpg7Õ á´Å¾èfð|RIºß„®„‰2úŸVëkËc‡"ϤœÊŒ# Yn…½,oŸùó.Ûõ䡨dÙݬôˆ™Ï * $2Ù-´)´õÂS[S Vý½«“p˜œ”^Ž6Ï?ErXF‘GŽªè¾ `-–¤gLª¥Cœnf%»Ç^þ˃‹xN<šû`[ËüP¸v×µAÈÞ­Ä ðƒ¥H{3q÷¨ò÷âcká'q±8z›~b›Žà³Í†hžJÁ8Œß[tM¤I¾‰*]ÛªgP8’“:Î,@ò¢ñ)äNÉù/'üå°M“dª3{Ö3.¥„¼ôåL€'%oˆ)ra²!X¢¤Z»€ø2òç.J3*RQU*×UÚD¤Í3s¡ðR¬:·œZöœ#íÃó¬ÇÊʆ£Ë—z%‘¼­æ6CT`„W”fg1¼3ª¡¥VF §ñãT˜™Í¦pÀ¾‚‚É¢¸N ä1¢ ÃZú£°;zÌà‚D¼áB"‰c)”I•-@9Ù^Ÿ]Gñ(5´ ‚mìð1—Üðh€XÊ÷)||«øëÒ‹]]·½4M9Ó½ÜnæQPè§c8P7i4GD`Â-Œ!ôlªuMËUX!Ûá7Y;‡|y4=£WëÙtÍíÌ#g­‚ñ&ˆ€–ϘÚÜ“K„*'ïîn˜Fi¾àù™iT <‘&÷(t>ܽ¤®ìÃÌšî¼|ñÔ±ˆ<…éNßõ§¼«Å6ò:Ò àèé Iùè…kúçÉÄÃ…¶„«}Ø5€ ,×à*Øa«¼‘R¸Àæº2L®Ä…Ô3žpÎÊ$²Sùò(ÙáO‹Û’ß“¢íÉÕ`OŠf¯Ý4º¤*˜E3Îá4ÛXÒ¦/ç ÒȪ8œ±Ë«‡?È2ÞãÀØÝL¯ì=ίVµ”?¼,í¸Ý_Ý=ÿm1K^L¯¢KÔs‘ä+d@é–S½–ò¦d,Þ“Z‘Ü“ ÖK鸼2¨Kõàhm}„S&ŸTW ˆÿnù(Ò äµ7¡hó0}ûß~x$s BœV!æwâsÉdEÓÝ?3'’ÔÚ:Â,Ü+s¤¡/EÆ™Íè‘?œk6•¢A´NOG3÷ps:)hþ¾úîÏ>â\ð!wô«§O#KFD,Co6 ÕØD˜¢†ø¼£:‘šY”€šðnl”› &ÎåyëS%¸·˜ÈàãCªa‰eÝVÓ'S"ƒ“¨ôoHÑ:)¾®ð¦:u̱”IpvÍÄT§‡o^ht£À±oǵ嗫òâõ³†¶¶bÄ)[ÌÎç—>/píÇÕ©ß`·È·ËõêLCŽõYo+-îèËQ@je¶7î™æA°J;áj8C t´q ¡"[…;¥ú%Ü»,¥U‡ä>ĸ4Ï) îîFMšB8×Þ2 AæjúàNXP¤Aàþ_/sË‹È>Ä:c¨.Ä.³¨À5ýóÚ‘u ~ ea!ätMá0ÔÉýÂm]?[®-vŒö<:†]N9t©=¸mYIñÈïÊMùÐGËf‘†žEÌæçål"Loˆd§Ê¸.׿™î `ØÄ§A³Ö™‡~[K5ÂS»t)ÉÊr7ߣ/§‹Å&²„2Ñ£7f‹B1ižå¤Øû2rÿö1z6ÏEÎLq«.-ˆkÙÓÏ6™U@\Ûj}9%~D% éDû]K@÷ìÊZFH#Ð=Á½c®äf]]ßÁ!,á„—É¿ÞÍ ˆI›„”z¾ÑŒå^.àwñ´ËÓžvÊØD^r¿§ïÂí÷½û4Û`X~a“J5æ}#! `±‚.¯·àyLøãáfÂBr¡òÞ& íY'ωIÐ ½8 pøm R3¾Oú˜4e³±Dñ˜H‹\š,^óÿj¾uvCMN_ÆKÐ?³)±’ª¤Æa¯Ã¡=å‘Ô  >Ó ;‚V]|<ÝÁ=ÛYå>ÈéÑ+GÀ–XßPürê&éèäZiö-ÿrAÓp¥¦îêú_^#ŒìYÍdÈùž;fÄýGwªü€‡eÂIz€_³OÃ:ait4>z¥Ø ÞN8R{u%@ a¼ÄB,$Æ"h.CvÛ®˜6!VD´Ù¥nàŠ÷êYòŒê§µªQ&vË—ß|ùý#Ñ· GÉô )VѤnx¡Ö^.¯ŒÇ‹¯À_$ĵʒ—/måYŠàLÜú=â8Öã‘ûGÁšÑFŧ6£¿šü×o2Wl2šìïñ®C†ä)po5vÌ&rœ¬ÎE˜q8w7ÑÊRðˆ*͈]Ñxž #àè’úDØ“Á$ü©t4j¿ýñ›gÏ¿O$ýzÈd9»6Ÿî¾ö%×;;hµƒÇ~öMÜA»{» XîÛ.ð.²]M¼]Í{¶ €hú_¿]Áv¡É½‹”˜ÄM–^Øœ¼·ÛDU±¾ÑYïb-HfMN:B"AÂåá ä„Í›ÛÍ„E÷¬8ï ’ Ý·£ŽìÚÒ{{àžj÷oê}s€×Á½sȘH¨N>3ÜCÑ2á¯ïÁ}íË ¤8²pð½öÊ ¹8öJ’õ£"\*¹œYG‘]f¶L¬ó\Ö3Áó9›ŸºÕy}Ë€€0ä£è0n h٠׸#œ e§ã«°såZÙøFÜ»1U“~ÚájukîëA¶FºøôÃU»E¿wÌöé‡ë¾öeÒÁ}‡+Ž Œš„ÏûËÇO¿==NðÏ_B ùáñ‹ Ëd«m0½Q¿¿;»Þ[}ƒ|u}G–¶;šC瘂{×¼«{gîíAF.]¼ç¥¼ÚÀ<1˜4Ìက­§8žÐ±ˆVž¢Yè§è1ßÈ,j@QÇÀ÷g‹ù¿ÝÍ”ÓyÙ‡¹1…5¼°à"|ôøìì$©ó§¢%IúVÞµ¤L÷´QÐafű9A¬RO6<Øë1/œŒ.M1hP®>H4g ¦’/랥ý€Øù΃¼#¾þø¦ž¯9ÝAŒ»b).3[:\ÔÊ‘N IŽáT¹f‚à Nm7—}øà޹ʽ Z€Ñ‰a@“pß¼¡xy´ïh7}¯y*mb0Æ´tkøË|)\i–ôþ™Ë?WæV3‘o‚ⲦdáNø?ög"Í[æ%)ãNÓ®$±~eXwÜp½¿á§NâÝlW·WÉ‹òs'o×óE’0à} w÷Œøô›ç/ž‡¡þåËçø÷+üÏwî²ìý ¦5.R4ÌXTåUKMÿæ5 ^h«Ó.Ê\LÃÒ){ÚI#œžÿ –ùd³›t³J‘g¬K„¶ÈÛ Ÿ­å£rêíEçnC2ÞÜÛu”ÀX³Ov›JTœÍJL¹–{5Þ²”œìËBú`º Ñ­‰â˜$è7ŠŒòÙLtQhì5½’æ¸1Ó-ĤVNëМ°Õ‚œ¥"#ØVÏò£41(Œ#‡õµ‡všßá@3Øpèë\²n1“ç´Äª§h!µöÛC1ÑB€…Hã„“¹R{åmÂú-Ñ —ÛóÙëk1¯§fЪ*m='Ðá\±ÿ,C›|©I$÷¬…¢#+4>$ †€`~ê-ŸR`ú9ŸÏ¶ŽHKÖ°u° [Ö1DÑëÄnf‹scPÝéÞ>z Ÿ½,Hïº} –¹Fnm·ÒK1}£ðM¾9‘Ï>™¹d[^&$9:ŵG„bÌ;¸Šëd*îÕwðc›°²lµzÔÐO›‡¡ŸLø›-*rÂxãè«Õ¾ ·îa½s¯§:Üž¸]ú¯Ö°/€zÖÀè™[‡c "×W›Ù–»£È3Zt“./•ùúçG£?&¿úáùãÉ7ß}ùý/¿úæûï’QÕ0_îþ!£WeÄ(q×år{•$p,`™¶M“NX>hìâj¿Ã0uôãÆ8fƒ²|ø|-’ðÁ°‡Ìzønu’¼”ÝD4Ãò<ú€>mVô=4Ø£ä _|“HÒˆÞÉôÍåI²™¿›á-qTûì·-óJ¤‘RƸ7ßÐËqCŽË %- òw7ÔÑ“qCŽÂE µ»;*{#z¶cjiÜÿ½»!Û…¯Wëù;w§¦ ~£íU>XÔÊváGG}mXhúA^÷rk܉Ç.Ü&kÜ0iv’º?É_=NfÛ×Öó¨…—žŽ„åòa^âËD”ç_lf¯'¬¾e`™f£°í°y¿ÒõÀ·ÉÏG РÀÎ^‹ÛwȑʤÕ·u|´´Ê‹¶×à„5ç ¬|p18{“ˆò$1ßKdzc `8…µ/SHbºgeC{Û<=}ùe$Êí½š *p{$¸Õ|y7C0;"håÏG¿}±üyâ¾þmÂZ ª`ÒóÀ«RYž%Uü-ÖÀ§ªT÷ï!>°Úëp£l;‚ŸÓÄ=l7“ä@D»Ž|±ºL{`ÆÑ¹®"ö8KKí7DÎwÞÈ) ^4ÿ¯¼µvûÐ#QB)ªŠÞö8UgÌÏÎTôpk18ãªÑOÁ°Ê[)Œ¡1 ñ“õ\+‹#ílhˆ*¼\¬Î¦ÔEáXäLÍ.>7ñ›=¡ÁKä”\j ¼,g{­ÅaÝL®hàdËtúæL<–]Ç£@ìDz„†ü„›e Ÿ³Èœv2jWÛ˜#7p޼óÍŠƒ™(>'#ØßØ=¶~‹‘•TìR |â6ÿ­*c- ã߬Ä 7¬†â!"€ØR2ÄLÏœ€sK £õV Ù,mdÇ?FN#Þ”Ì¶Ž¯ÂÒ d‡Ûgmešy0ð–IaìR«´ëÄä!»¥Ž`àh¨íð|ôaÙk^ËÃÑVZ\—! ŽO2¬K™øˆ¯žøšYÞQøƒq˜Ð_²üÑ«ßnã4€NnÑ:‘àcH ™B柈Óx93F@Þ~6tIf€Á8¥Šz`I ø“êƒ=ñ8¹u¥ „,]*hf©~cÔ<‘ØØPö}ê¶µZ̽}wGR"þ¤†ßÄ LiªŽä£ò1#¤×pj_š÷ŸQϲë¤ò´<{uð.*G­Ÿ% pCòEX+jup‰^²1 ¶®Û~c–G¦¿lED"ùE?'§QÈÒFWd»®9šMÝÐê(ñÍo \G  À .££0>oJ È Âòæ#Š©™‰0bȳ5R3µ0^ª™Ûbé~É:pØÎnnWkubŽXqWX B ¼/çAjÌy² Ð|›;ýI»úå$ö®°¨ç±b ùÈÒò+Öcò0,¢ÿX{Üfıémïn‚×u¤1i*ƒ7LÂyÊZÈÈ*¤ÞÿY+µú`A–kª– žëgµV´›[É-+/ž>k­6LÊõ wé\ûõ˜¦©Ö€g\p±zc¼™eÙÔ,­`å€Äkžå`…8”·Ú]!-‡îÑ%ëÅìÒc˜ImÝY­|°Zþæ—´4L©#wï Ð…‡%—è¤J¸°Ê U…–Dê1=àØƒ’ T‡M“¤KJx€±%ýéâÚIî‘þ¬³A1!¤¦RR$Lc¯BÄ:X½ÕYÄ=óŒ%8šìÔ0¦ ž²-âß}Åâçî¬a¨Ùë’¶Vš×„§Ë§f÷G_›‚6òí\àò •ŒM©¤F¤öüä­‰ûrÉd5ÁÛ[C˜l%"¹ë“ËÙzêö^4]KÅØ\â½¶;±c–pªÊ•¹ssé¨zÂð‡ŸÞ<­í=82Š•Ò!’¦*˜¸Ê]æéz>=“hgr¦ /)¨ù<ÝðJ"k2¬bñŠÐ¬ãçÞ²ŒU ¸½æ979uâýå8 ?0Åk{è À†©Œ y†EÀͲZ×F· ]”Þ]“MhÁþ¡ÛÕ<æ×º.Óï¨~}%é… ý¨Í2^‘3'Wj|Eå1@=ôÙ²àcÅVR^<µæcé3˜Ö:±(u¬ BegÍ3¡«fÍîd?Àб‚L-ÐR¡NQ;èÖdåáÑY2Vð)Ü=„9ä“|L+˜A§Žþµ,SÙµR…vu›øÔu„×— n1?‡¨Š7¨wWœ”šC2ù¬…G4´xŸJ †x?f´jR-/ø mÝ’'0\Ÿåô¡||wq3[_;ÎW …EáiEÚih7»š.,vÅçuO3«âYž7y´mj©1ÎוÖ>øgš1„u7æFlj !!M ‹ šr†–1yVr(­ãdTYKñûŸœŸüp’œù[s»^9{³Xmé×lðƒH×ßÝèÿ‡‹99<Äëp¸™ûãl*} 7RÂõ­+±7Åû¬+øú}ÖxŸVÐKÀºZÝq¥ê‚v·tÛf¯q¥rÝ–-l+QJÄ ¹íöÚVÔðl+Ä-ÝcZI꺬ê¾:úRÿ·åë·«õù¦§¾u Я߸öá~äuüuoí•üµ»xª1îÚÈ|UßÛô@¡…fW -ÖïàŸ¦¿I¾$}Ý¥Eòvh¢óà–ÇflêOxš8Fáõõæîfê/Wý©wÒmºS‹®£©ûZ|'P]»sà5ø±Ó?©ÿr-ªßâÁ–åI–\ý.èÀÅ †£nûì¦;fè–‹«¾Ïm¢Î”ßÍ,ýË=Ö0»fOW·¿1[tÜÑr•¼¶ÂpÍ­ÑÍ ÊÁï])ò|fz_ãÓ +ù¯À_ñ«ç7·WÓÍ|3žÜr…D³½¯p¥OkBVZ~'Ã|7¬XætFr¥À¸jÄh)xƒ1AçL÷l‰‘…%#‡ŽªÖo gÙ xÖRÚ×hš% ú^À4v U²ÂI&mz‘´{y¨SÕŠƒ2>¸¡ä:vF%JýHÚÈJ„°äÓ˜3ÝTF&°´œVA³PZŠâ¢Ð‘f™$64Ûƒ%ztÜ•£%ºã•Ûè0–À•õÚ8Õë ¨£”ëÀQ2RÚ×{9ã÷+íÝ €9åâêÍÍ}pònyF å •jÚ&³Ÿ¡ß㗥ȧo‰L¶¯…¸Âß‘¾}¨áÇÚ[NZ<<¬éN à)l¸Cåyk̬nBáƒùÐôÓ™*¢Ómñ›3F$ìpÕsˆj¯ì¤d ,j°Y]ki_ÝjúP€¦²«N6ÑnLˆÁ¡% \ãnu¨Yó*àu(žéEÕ¡fækõ÷}êP Uo ›bœ‚®VšKiD|*„&µO{"¸¡räú)„Éœe*q‚ˆÊ´]³ŽÔÞºc¿Õ‰pDkæ'‡‘ú9,ÝL/°ˆ°T0ݼo€Q£™ÐKCÙåG£L T˜Â¶*i>‡˜=={ww&7\ŸŒ¹Ç®U…·¼hy¾0_²®´á“øJ²±¢“ðáá8_>7TLáÏëÛMšAéÚ›•„áÿ°ºÛR5fî\ô‡ºœÁ;jF[?ú­fYˆ“œS³‡}ø_—¸6ŽÕû_“c¡BÜÖ©·àÁDFpTŠR•xµg£½«§é•m\C8ãµAÖYŽË÷Ò½æ³H¾——ƒÅ¯ó†„½ç È,Á¨ ´×Dbñè Ö7ž¾*}†qCó×66W~ û6”…B?~HïÞ®¦ˆø)¨éÑËÅ¡àv é­r­V☀ñH^8Äuøå|q“®ÛѲ¯¾< $MB× ¡œ =1HÀ:% 6BHÂ, ŒÈ+»žªäã=Ürè#À¿½˜­/ÁgÍøzºþ-±#¶]%±H>áªi¤ aÓ=““„½O|̦çÙÉõî’”ú×ÛáñâwÌÞ+AÅ‚Y¼¢ßî„r‘F~Fv«¾áÊóRØ|÷F8~¸3åâò~‹àr,Ê­Ä’{¿£þŸÌ5T ãLàãT€#М¶|ï¶Sèc ¥.ë‘FÔÛõ ùôåé’›é¯à ®Ÿ†GT,T0’Ç7OcOóp;DRºÍ'¥o~ÂJ¾uq}xmžJãOΧ۩—¨þê꺄OÕD>j(b¾ƒ%v§ír¶¾üùhvryÂo«4Þm°J'ò©o¬õÛCo»ÛDv|óËùl1ým´;²ÏÃí¡?è {®~ƒšëlåÈÝ $­¾ü‘ ™ÎÀÚOk±Ñù—e &Åc:N7x;ÅÆ‡›Oþ&—äùëë·ô¥[q±ž^ò½É뿳2®øªŒ*Ø`{€8’û`üÂBíô×þ2G7âHñLl:êZ_l‡]VqÖD÷Úi*"2^ÓÆfË=#„Ûûjg™sD+¯Q(Ñ¿b¹¡0u¾ •Q/¯Hdmþ'[p²\ý˜uÕè'üçbä'™®Ø-âÀmøNåõ?‰<€2döáÔ sIâTÓ¹®Ancy¨¶Ñ0¨3,+,ý²ú[bÖ‡V¾Ù•S-Ou—ÁSœ5@¥ê4c[jv¢é: ¹¼.4Y\C×fͽRvÞj| S`œ*çÈâÕ VŸ#í´7·ñ$¼÷ŸÆŸà8=3Mï¼Rµ!Y]°øy%HÖ #vl4 “Ê"_öÎj^š´fS¸_˜Ñ±ÕðîÇÍíbþn;ªæi))ëàûo;/Îa}à1AíªNƒÆ ’Š‡Ç‡ó¨„T§sÑ)ºa‚H¨ÜEÓä¾u‰ÒÆ[רÄá`J8¿L݆²È2nò2péøn¦`òðTú×Z\vý1q­tÑ‹ªÑÀ•B3ã‰lÒ>T½ßPmda…ÎhÎ×8¹¸4ç‡Ùål9êPÅIÑöœ@"Ke 1ÍVjaG¹Íw’3qY5LbIØ)ìßß– –Ò!=‡¥?Kir¡6uš2ñ˜ˆxêéÖŸÈŒŽj÷b½°¯(ôøx•×)¦:®’‹›^†2'¦·RŒ|¼¼˜ŠØo.tx+XŒc³\õ2¶» ®5ÚÈ/£ÏQ«­R£G"ò¨§‡êäËøÄ™ú±+Cþ šK^j“q…È·§C§Ó—,Èéëv°úµ¥ŸnY©Ÿx4µTábéŸÙ“(“f%ËÐïz¦)âbqÚIÿ‘œyH‚\V½€N#ë@\ä ‹ÖNâ€T^ç«ó6O:Û…ª–Æ©‹¡Æ`ëbp›=àΡ‡/¼[@^yv®“s”þ{ÇhÃ&7ñéߘPHºˆó a'jMúBè¢9’!W¥:té&òAbúZ :ÈÚ+7=avT¹"…TˆYóè¤,ò 7"æ¨>JàÔx¤8ÿþMó¾H|îÛvŸ$'·ÅªJ)õ÷Ë\ø¶Ãn#xóLEjl>¥ÙP\ìó´%锨l¼«–±)À-fá ½™Ïï{TÑŠaË(tÀtÜNqF$Z@UÚî¼±Ê0ï¨1`UÊò ó2—ËJž>‹ àÅÇ&¡ltBzDŠL{ë;ê"5f¸çÍíÅ|v%£]äŽqt‡vo¦*j_5™ ñýzWɘ£TPæˆQÈRw”Œ UèÂQnIó;u½>ŽÈ:à6Z¥ºÌ•Y¨qÃß[Í”FëDb–ŒR6H¿J«K ˆ fÉ]3‹²\ËŒ&1H÷Ì5 fMì¼8ô&LBº;ò™ &l{iŒR¥£·»-·¢ãP ]5“IRa{A,—}Å_ë–ƒËà*¨W¡ÅtºBXûäï…¬8·"-ÛþV8Z3‡zÁ¯NÀzž$Q²]ŸY°ˆŸ”²þ˜ŸA.síÆI~͵[’l1&ºU½×£íê‘ê½Qï5aáabOÛ2ô¾õ¤ËõgÆÞÏ϶1¯…a±°&u:ŽìUÄðH5í0BA¢§ž¦ié Ž•Ž—}3Ï”Îp+” •çÕ6ÑcB·BéÙó'>ßq¡{Àx0|KöÄ'”¦:2ãUHû&+AG³‹èP!2€EãŒ'L†Ì"ïCuÉXà>‚< ب¨uå©?CK) ,åP¬+¾zô}]gý%ð.…©üްMªÃ-)·ê: ®ú;igꉚ¼Í JÒS[û}uݧ V})– Ͷ,^K\Öé2PUû:NÀGÏHï0˜Ü#ŸÓO7¥BÁ},®‰á)N¯¸‡ûÀ‚ïíêCïÒ 'VYðOû1A¦>+ ƒ‚ìá*´|d.«u©ýT|ê·^qÀ:5i)ëáÂÌ,Ô¡+…G^¢uDc—µ•øý2ß3;FŒä1«üĽÉ1kýK|9 /±ž¨š£‡`gÚù <¿†Éj¹Ú® (þ@{ºN;Øe$­½#h%•zV;ÏVÃ,çG £‘3\˜CoÄOñ*¡Ði¾\*jL1ùÐND›ê,ð ÞLE¿jÚ³BG#HÆ6ÚlÅq­½»µäzu|dYvƹÍ#¿S0qJbèâ‰Úу® \–k 5R Ê÷ÞÉ@õHA-ÛJƒÌ€Ì3 Èz8`RH¾Ü(•0 ¬ŠÍuØ8AzéY›ðbŠøO¿e¥Ëböf%°›ø;äÐò-gW>JÚ°µR'’=LƒGñÌEVeßÊJЍÂ\­c®«+õ3#‰uíÔÞIY®ñË=ý]Ö‘CGÖß›u •=$WÖ‘nÄ=&P¹}öÔB_Ô7Þ‹Õ鎙æÈˆGÉÀL¥”æö½?Šì 2Ø]ÍZ›P"m!…­~LÓ’ˆ9&,‰0éxÖõD“0àþÇ¢†âÁ&’¢«F§ àÝ]Õei+"(¤—‘nªve\`^)@æmš…7þÛ©½4ÈjîY¦EÆv,¹tL')¥(ð•g³Í|û»sŽÛ~)t)fÊ6“k²¦/%üpv2‘&å@spŸÃ5&«bqÞ÷Éà2ÊÜ=J÷ z-)n³%‰âdëLj "ú¯D+!PÐQÁ?@ „GFGˆv‡ÈÌ íq Jb wÚ¶W”½ ¨&Õ46£H™éS ",<3˜Ò'sfä ‘qlÖØE×sD”îO§#üSrÕòöM7M§m(j,<’$vޝ9h"³zåÓ„ÿ>Ãÿ‚ƒö>+fiöSnJåg0nÆ/J‘éw½‡×h|VXÒõ™ùa‹ÒáÐaË%ʦ;ñÆ=p=§b4°$¾woÉ÷Ⱥ¥ €W8y ÝÆÝHZݾÅÞT⥕aÜÇËùì|­ˆ¨*×HüXìÒW^yÃòè!Rl‚¶ÔŽ£·Æü!ô£= 0pR>S6å)PBdà-±q×Þ‘ÈR'žûÍ©´'îÀ™£nÇåi2cz­U"…¼i¼ñ>³›TÅwH9lŒ~ñ#¶–ÞDÒz-´£çN”3 [̬ú”´ÌJè5¯ŽŽ‹ÓÊóÙâbJË"¬ Ž¤=‘JŠ\ÕäÙF†³ÏA³«¢­EÀqªT½f™. g[?.}Dš*FtŒá­ ÓüjD…‰“0yõ^^é¥ÏX«êztÞï&“²€Ôa‘•~Õ;lÇÑãNNÖÂÛ0¼q«Ò¦¾‘9ZBH‘‘âÄ?>Ûܺ£ Ð5K'¹iÚ[Û<ÓÎPƃ^žýaQ–p×çñ-W*RVðš¼G¥ e›ß–¯¯ÖGæ}±6uÏvl¹1)¹þAUÊ"ÊgϦ`¦Ì”‰8ð‘ﺛG9+t\ˆuÓfÚõÜÍ–‡„å5·õr¾\ :zíW^çÉÑ_î6„ŸzUo0šÈ*·¿6å]ÇX·}' Lª)¢¡çz9½½D;‚®Õ­ršväf‘Š›9µ9 Ñ Dêr¶Ö4x¥Ì†Hwø ÍÖ[%0…Æ,WµŽ'c=ÙÆ,÷¨c©G¼´­³}LÍ0Ó¾‡áÚ›nmp£¥YöõÕüõ5q^EǸ¡ëijQÀ’¬Ã9$J¿oVˆî"B ô'k¨N*™.Œô4Ý«…ý}üü˯~þŸ!Ÿ+Öæ€X€8œ,²•:ñ…ÙJÝk b)µX?¾—üÕ H÷ˆyh¢¤qx4‘îžt§]Þ$0O¼€äø(kEûñHÿqo¶ÃøD`¨ãì“Àãjáä×4ƒ¤W»'•é¬?ç¸ÀŽÇÆ2Êå{s‹{'RKÿ;‹ÍC¬Ÿ]ÐË® @™jVBµåË ºfDŽÅÆ=îhU¥;:’á¾Yö±‚„Þ×aãˆî¾Yö±›æ¾‘äh_‡,Û×á(·®vèÞÊúÞ³.ô©f!(ÌÄ£¿JáÇNRîû}}b”û¦)…{û$ª+ª{ŽøðieœÍ{‡'‚eYï:Z¸û¨jáîc¥…»€îÙ.+ݽ°¼„Z J@Ñ¥L<†bL¶¸J¹R^´^NhO¿s\ì 2sé軽ß×(é¾ÁìélϾïk” ß`ötH¼Rwð]Ñô¿ÃQòePˆÆeÈl]IwoÐ&ùßT½Ýóî÷¤@ßrk$Éù:¥y—§‰ ÎzŸùPǼa$ÿ‡‘Ž76îï èuÓÁÄ÷“Zñ=iŸú¤”)o;ÂÊ“£kÀ¡ß›§ØhMÑíº0‡?nYYäûi ?š.ÂP{/᩺{è" ?ºO¤ð¼·O$6ÝÛ' ?’ïÙ’=ĘKùÔ8ƒÜ~ʸ{i­t÷"€ |ݼržäì!+üp÷÷5ëêýÚ×)¾Üßé½íõ~b._îëb§<.ûÚå¾îQwÏLñåþNïm—ÇåÞíë” s÷vzo»m»ÿé’/÷½OŸHëšÖ‰ìÌÑs'ðgŠ“üøÏ! ݧ6°ù.ÏãÆ`,nœ/$%&\îtüz²Ì-GU>ÈŒëVáR&Ï^~AÀ}ŸÝGºÌ†£‰Ên8X£ýÃùÔVy+„·pÍþåù7¯?ýúôyHcwXÃîÀT4ÁóÓ?}ÿôÛä‡ç_>ÿáùwOŸOXè¯5Q,ø°t©` zù0VT³ ¦AI€tyªËÝõ×:~W—«t ø{×è&ÑSgðÕ'O]”| ÁŽ=ýSK(Ã^_Q5ªú·QØÉ'öÍ$<Îø”èé00øÎi€ãO²P¼Ü ?‰;ÿÔ<ÛÐÞfj¨ÜFví:ùžX£g(Þ°@æ³DÄL‡Ñ˜‹HÑ eätlÞþüÛô<Ø­ ù·™W%ªt wféH+ Y?Í×ÁJçèIkÉ|¹œ­©·ðÍ<ÕO[º9GÎÃY%E}‹…ZÿRýZ÷·óÈäжZB¿}ŸÔҸǾƛà³òí8¡&YVé#$˜!¦-¢1SÛo&Æ °m8J Øc/X_ÌXc·Ñ¯ Ævˆ&iùpÀò®ŠœÑ" ¶¸ ²4†¦5!ŠL”âž1:3°½RK‡n æQÞí²í%ïP—l“²¨aœú&(ç;¦åiã ¨²ÌÌZÆqzn×+‰:W›´%«`”j1Œæ±æîò_[i)NØYäMåïGã@„ŽÀ|¬gâBÒx¯J­mšÏä’[ÿ{ì…™ÄÀ¹Ò,}äŽÁÄ\#¨]Jy­CZJ6Å;¢ÜÙI¡ÆßÆŽš-³K¡tHrƒj„7«„îcKWdõzºÌºEÈ=©Â•Ë „ÄY£b[ô䤨lHH¡$V$Ù s³ óµ¼ lÛ6ÊÚ&4!ƒöÄ9–ÆMsi­—oH/­èÓ6›2%qÌ]Ì)“D‰«›\*E¤Z#vÀå³Äû¸©Aº÷æ–è)Go§ë;M‚—{Ó¢ðú“âZžmöt˜¡>‹úÿl7ríµOÛíu]hVmäFjZý&rÚ$Z a)3KöÜP3òm(ŒÒäØ{Ðê<"‹fgd©Ž X–}ôµ£»×tM3OS]\µV†[¤.Í{s¶©S×ÓaCª‹Oëk€Þüuöv6—DÎzv:®þ.Ṳ̂™—3¨ÏY<¦ÉY×…"‰¹óAs­~µ3í™Òpn¸nšin»žÚõÀµ¶»û êÁ<©Ë¥š÷Ç0“6Q‚Ù@!––ì«ðæVH8¢d©ÒuÁƒx1Ûl}™úE9"¥~…†&ÕŸ•¡D“Wö¨~Ó'êÃTw•–Âö­Ñú†a>j©8?ÝŠN¼š[²'²††#ãeÅ®*8BÀ5г^Ãy…‘bÖ¡Mœz/©„34=Û¼93{7«|4}ÛAI½§±%@É”@tsØÕªÏz`› ¸¥ž!—‚t#,&,÷|ícÛÔ¥Yr9ÝLÇÑÕ,,ƒ2¹5’~…SÃHc–ö·Bz€x±”)~ÜL®Â@º\Ërì"ã3Ûp£8immà}6~,+mñz‰U-ܲ,Š#BëáTlKváGä)Iå`QÕ8A”‡ÀbåãðêÉ—\J N-‘_&…#Ÿ#(‹å³+¥:©Ô.”¹e©¶ß_(#­~h˜éÿIÄ'‹EÊ;õx ¯z¶îyÄTËû°Â¹±Ó©~OÇŸ•Õ,Oµ]/›Hÿ@Æ|èZDO€O‚£_ît1NAá !*Àkž[¿Š§’åRg7§°ZY«5ºHÖéù¼¥y-U¹õù3-Š‘}Pw¦ Þm»C… §fãÄex õ1TѤSÜç]Øt¥VÑpUs_m‹hÔç=—S¸„ÈÐà"þVÀ–yý}ôv%v;”f bØ‹²¨êBªDÄAÉ–Z¬k9 B"à~êR™×R+ò•5>Ó"âµ'j>P¸°Ñõù` ˜jqßµÐXðV¿Þ)ï—â¹ã…9ª CÃÀ¼¾p£› †ƒOR–ÛÒ¼+Gê6N½¢dAHܯuð†ÿ ¯Lùüå…4ŠúÑš”’¦´Pú&‡ãìtVDQäBøé‹)óÙ…šë2µu#,&ÝÏ„å²ëÔjˆDؼ釜ÓÔ£2Ö©ÎÀBÇ÷ª²&La{×CÑ$²òÕô,úªöëÕG35\›ZNGËÙ|{{·¼–ÇÓ˜N;¦ø)²RxÔ¾•° v¿L–n™‰›Tyd8ÈQ¾†à}±Z0mgœ?¶erOº…ï£ ‹¤‘~ pœÒ¯ûr)ñDæ›I'f¾bnçnfW.h¶ËÒJû)ÒµÆ.)ÆšFy-nªJk©0Jtè8ÎtçXkû„TêìÝ[ù0mM–i)öé§WÙìí°«6Ñí+LƒiñaÓÔ™¾ˆ}ÌB°,¥¤u·ÇÁ¨ÄÝ Pg•y*I%ÛË3jª‹V¿€ußì;Á ÈsSRT:’ÀT(ÃPj‡} Ÿû"ÕÒÚ#$nbn"Ï´÷8 É·åÅž^3XÄeÔ;ÞbŸµÔ‡ÝX3mž–ˇ±é´z~Í~?k—?Ô­g÷ý®”3ÝCÏË˪íÏ4 YAYFuþòÝôjfÞв¯Óһ˔³Õ=ì*5rë Ç ™.ȱ¥Z ÁÁë_yþ}¦t,&ê„ÜÀvS-¡¡ à†8iúe¥Ã¤æº‘ãx£û#Ü!|ºmÌ÷Lß]ÊR†FÐüƒ k[]ºq$“:òÛ<ÓÓ=cŽ Ô5.³Oå­Á1«£'ª¤Ó@±W3Qµ¹•w1ÎÕÒ(´¢’*Ø<‘5¾°äOÆÞv®Qh^°éI¤¢”"Å ÷ó-"e;}Ô^ª ÛiIêÊڮɬ¹™‹™Ã‡%t:ÉÞQöJ']›H«í‘I´åð0RíÊŠŽ"%  ¹é'‘(Béî+®a íÓ‚¥Œ.­È>l‡‘0UµRǘ«=Ô÷òÎÞõbz{«J]ã®,,ak„ës×ZÚWŸo¥Iºö|7A4R#"B&Då©“JKÞU{Å,=‰ÚŠì¾Ù¤)ÃI\2°åJ›hÁìôŽN™–«‘—A åIcFÞ£)«$§ª>v UCT…›‚*5£*ƒ€ÜJ¾Õ¢¥§ý’x¶ˆQ±”F¶Ö!^²•rµF¢ÈD²´à‹03L5ŠfåàWfÛ·Æëù•ÒŠñÒ¼»3ô@ Ö,›2*÷ †É©¸wÉìÕʬ—Ý0áŒC•)‚å"¦óq$°¸Ö©;âÙ|ò_KJOÑ¥NŽD‚çÛ5¦hÊ|‚Z54õŰ$@û"_ëà–Ÿ¯ õÐÙ=Jµt.¡,1)ƒ)å€Gñå8’-3pRŒ¥õv¿¶¤w6µž¾4Ž‹¢‹dd.³VÁï;™e»Ð¤¿þ5Vclð5ο±™õu¤¥ßè¢3ŒvγßZˆ¬º{jÏü—·…fª÷/ ™êa`• ?Ut4þ¦²JÔÈ­.tÁ–°íð Pl ø´fðz®ñÿÆõ‚R°4×½›6šãÎóÜú¸©<Ƶ6ß–†$húsãVÿjôí4M©Ûs—ìe©mØüÛõôz;ß0ô­ŽÔAL†6ÀâUø|,B—î8;ÆßíÒÐÕL&ÚÙØüÏ=OcùºH`ÙïŽÐé,Í‹Ðøå4~H¶©î:mLÊÄb,þÙÏݶg”€üÌ1Y\´qòp*ÆT¼Uk“C÷QÌžh$Ìúá¬KwÝÆÖºÑ  ®ZÒ{[ÅZ¢‰Ó”ÝÚ%Keë(J´ñ…Ûµn Ç®¦úWqjš}í’o¡%ªoUh\ý®-ÆJ+š8 èŒe@Ák‰Š3įúÔ*l¹ 44òvܾì9¸d°½±h$'J+lA,»]ªO3àS.˸¥H…–=›ñIÑ7"dúè ›_-J¾¹exj2¥–{Á–Ÿ(Çjo”ã?z`£÷AÛ™ÂHýÒÞ¹>ã²}¼¿XXCaYjJðÏÕKý`T# ØÏ£¤Bà®x ÍÀ÷Aµ¡ÚN½Äˆ¤%ÎÇèf«ÖŒÖËÕ%ëE¢7¢äòqE»K3ÿ7YKy„?aŒd.%#Ÿ¤] S­ŠàIÆy‰èÿ :FÔ]̓厶†8éÊ ¨©zùÑ&ümO÷Š`Òµ¶½¤;9•ïæù~†˜ìIò|K¢FÅm­NIºÛfÜ ôM9ŸFîÙÔ”:àÖ˜ŠytÃùX€_ësèÜÈQñ)4ÅOI¸’h»ÀPûqÞȃ 4Ã[X(Ún?[r ÏC¤È®@Çz-ó.!!•.é»CŸNÓ^wÒ8lñö´”ð)BÚ<¢øÖ±xª'ׄD`!WgN†äjÖ‘}Mò!ßÒë«ÙÍ4\Ë9´Ãf™¯3Vù­Ô•æ$êx£"H‚$²°Yó»Ü­:Mì3v‰Iëv˜ É[Ý*MíC¿3 ¯ûöeØÖÊ{A9*Í„dKìuÑ2œ8l[Òt>'P/³YÖèôp ÿ"jZŸ¬ÆRaæo"ë8âlŸ'é†*Yž‘¨ù„¨wr${y¾YAN¥õ2²o²N6Ügа|;äm„ÒŠ’û޳ö{ÐH^¢±±/óH%¦ê<—ªZÎËÚHÞ(Ýè1?~oú ËiaØÚ„ÛGV4/4òxµŸ'eÛôò¤¨1˜ÊÍÏRué§1ŽWT˜Ž_à—½ nåþ$±„6×:~ªu4f(f¤}¤i!#í„¿Ȳ·Q¾IIÓ”?÷¯xÿHù$Ê»bÖ¡¶ò û6^Xâî°›–®8['¸,Ô¶ä]ýº±iN™»F!ñHW· )¼°«°L I©j>ðK-ZÛ­’Uá#¨Ь`.å¤lp 瀱Ö%ªÝÐÏædÂ/ã«òÑy·“yrKÈ„}ÿßzÿ ™H3§z_èX$ ÿ-ÑPÀÄýM4Ñîo/§ççÈóý7gK˜uÛýËWµš£†™—äøoÉ©ÈÉž¿ITÊ—Ž™G7Û`ïàõ‹æ¨¸‹ªxàAB”¢ˆ)†¢´“ɳϴty-ÿ¤‰ý-KÆ¿Iþpü«LÝÜÜ_ŠøhéŠlÃù®†KÕõ¦›ç¸á{F\ìj¸îš¼ßp‰,磆Ë{F\îj¸Ë¥½ÐpÖº7sÜð=#®v4 䯴×pÞ75\Ý3âzWÃEWö7/o ¶Œ¾gÄÍ®†k¤àî5\Âl?j¸¾gÄí®†<Ôß¼uã†ïñ®+]–Pþç£ld»W:Ïïñ®+$6\íXŠñ›—ßßp ›<7‰Àö7<~ó|Ãù.ZQeìÙ0Ò—ðT@w2nxÿˆó]´¢*Ê*ï7ìNÖŽã6~óBûhEU5l^Ž1 ]SiEާ B÷ÉÉIHEÖ—‰²7h°IäL Ÿ_²ãÏ„E”hê¯+¦1F V£ºÁWãÓ¥C¸ëeüú ¶”6aÿ‡.»šÔj1éjÚ*ê4†FÌ€5shh­*–ËFJ˜.`gŽ1]¯¦ÖšT†lõ”üÔán¨ÒuQ4s°JáîÀR*N6ÛU¤ÇfŽ0m¿¡êb~)s0'œV\T€Îg¡Íˆh¡F~ïÌìææZåº])W-ʱεmfÞ9…)áMœU\RÍÿµLï™INë Š¡É_JÕÃa @~ÐaTKâX¦!œ…¸iHaد(­ôýhf7JšaN&Òèág¶HíÌÞ«Òøˆ3ëZ¬ Þ¬æ,ï>jeôEq‡–hÚ‘å¼(+0›oßâ•„p¶¦ÓjˆýqÛ~¬KxÁ¥¨Ø…;wŒ¥sˆÅ‘ïª÷:°/«¡/põYT 3wÅwsËkÊß>=¤@ûÔ¢iq• óD 8µ-S:ÓJ½#–¹º¶•­ÕðzXp]ÚI…ŠvzøäV”›æ<ç J8ÉŠßÆ?]6‘žu]=Î öÅ.šQ–æG 3;€m?+Ÿ¹¯ƒÀ°bMZ|mž»nåYÀ«Lh‹U­ÁÉ5K=ËJë‘^ Á(èƒW*7U©Òƒa1ýëìq‘;í”pQHG·=5]È@fÁŹ (¬¾×¥êü ¸ßH¸€OÓi“ôγئ 4– ²“3[¿%8 ]í³C/æaŽõ¿W8äØðü‰(ÉC§8îTðqZ·°ºäC†Ldn|?ür½@a+®àÛ"|± ÆŠ“×µ[íj·V"´[ÉÔî=ã­wµÛ6ªÝ(êV:n`¶;âyóöÞv[ZW…ýoó{Ú7´Ûìj·(T·Aº¿THD;lw¤å‰Úmwµ[5**úv¨ÍG펄Š$ùÛ˜¸BÑoIüçoã¿ Úéx¢ñv»ÆÛ¦ª1Ékëë& +‘ŠçÞQ~ìxGž¼»w¼]Z¨"ƱVåþñŽ<Ðnûí¶ŸI -LE¸¸Õrvœlon¬ó&YÏnVofç'f}C §pU!×Ú+–KÉ0zZC3‘DŘ¹,‚hP®äjW¹£2†oÛqÊÓ;6­ü!RKH­Nµ·küåBpœŒ¤‹hµ#õŽE×ÚOH¨`‚ еRK‹ýv¶€[ Û6·ÇT+ìNl.²ˆócµÈÇÑÐ9`6”i4ä¤ßÍË^ª §Ò ¼¡hÞu“´®edù`bBS;ÜÒÑ@lWšOªbl‘¹úîú*YWZŨ×ÞÅ’(ˆAó!?n¦Þ!Æ[iâãL› yZ -E[¦aµyªåô5—4¬d¹}ÞNíØM×\Û=΄ËÕ0';SÍ–ÛÍ-\ƒàÉR^2¢KjaÑnVçó‹ù;K2œ÷ >p19ÿL' ¬¢<"NάJ}k£x¶(¦RÒæ„z¡oîæÒÝ"®…ÚÛÂò*¸—ıp’¹]_$£¥E01^ÞO$c’’ï¶ p)’ßq‹Ì "ï'Š1O†\[íó \º·¨eµ¶d!¬Ä¬y: &+䲨3IieÎÚinKOˆåy]g=î.‹vÂRš@e…8b|RdÛteI2—ïJÇR›‘€Ã03_3ïØ,RC!V*¤â>%¥j¯ýœöâ©Û]‰ÉMBþJæýD•ÈÌ|ýR-Ân^_9îÒd5ŸE¼Ó¹õ}”ìÆ•¸ ù0)ªEXU…–FIQÓÈÛ/ÍÙl!ÄJJ£8C `ø‰çŒ‰^•~Jp&fîúr¾¸!Yk"²&^’åÊ+2NixiZSÄìùÌžô²ÓR+Ž‘q@ªÚÇᢗ#P“¬±Y¾k*Ó³)}ö`i•q´‡UQ¤Ú¾Ä–ÝùGÈþ´ÚˆÄ‚]-c´ Fc±´çæCOpÅ›r‡W‡à7}·'Ó‡!w7‡žV‚æo õM„úG[(¼ûñÂݹ§iûvv)þŽETLä;+¤³vr°D~¬LWHx‡|'תõš\i|7:—zXšÐÕ=Ñ#Q׃rDsè¸rà“øÔ“/@)Tâßßm½J\ÐåÊÄ™Ðqo©j]D½Ÿ½˜E‡—_Ê{¡Ã&¢’bï÷mÌMÕhÃ|ž5d!Be«­]xÓM—×Swý~Ç»xÖuX~}ˆ`í;¢Iº ``_ Uì Ó „e8Ϥ}Ëùǰ°ô•p>FÆ)< žnñ8®$ôk3»† ¡êÇó_Yö¿xÏpU[5m+Å;’jÛ«gî̼<vÁ't«mÜ}:8î[…Qð´G.(†s³P€‰U½lq¿ª,¬Ù>¶œF×…®1<ïômómmgmŒÑ3}J½Fë ±dÃZõp~0†AUÍ龕*4lD™È‚rµ.mA²xžÝ¡4´ÓBÓuOÚé »Ci¡ýDƒqªDëÖ×o»Sç™5‡$ú\¨Ö¤gÏ!i‹¼‘N¤¸$²Y;åº4!e²GxåqAþ:d¯ÖN¸”ŒÈTlç™Ô®Tud¡oŒ*—#ˬÚÁ÷ÌQie¦ÉnÐ%öVné'8›5|m>ƒÇTÓeA¬Hg³–r׃9›µt'¸ÏÙ¬¥ÒjìlÖvŸiéº2ZºfèMVÖuƒ†“‡Qeåé=#>D—÷£Ï¢ÌʳшFë”gŸáTèõ®ø}„›J>¸ gÅÈx‘û R ,Wxì¼ÑâÑ×Ó»Û­#(Žâ]ÌŽGün­@× ,3¸Ã¸÷ß"`Ó· œŸ"`¾\¯.×Ó››$Š! *M&¹Ž´FÑ0µµZ•òQÈnÓhkȰ|´g%&,UT)õó4ŽÔFUizL§'TøËËNèŸLïÜ ñ‡ÈV„eà#Ÿ3¬¬‡{ƒŽ¡n{„—ÅVÓMðNu »žcÏÙUºµH*AþTçsÙKš^Üê~ùÍ—ßþß{¶ZYüºÓŸ+°é˜Ù¡œ0üe]“%}'¼Þˆ»òŸ].¥ˆzû&ÊöZA ߺ×h)*É2è}osuÛIéP¦9 6ƒ00õÜ¢Caú¹®U'Gæz¶Ý*Šyg¸ ºÊ¨ñ§ù8:>2‹ YÑxŽX›Ý‰a«˜|…8É• Ò¹¸ñè6æ+ÛÙ'CÜðû8v¾ÊR›eW´GSÿâ=”YÒûÇ€wL ’u¡tÐ8cƶŽõ©G/­<|Š.Ò.ö9§îi/ßn˜5"e¯!Ðh”Œà¯ª¶‘âù3}°èšT`×@åZ[Þ‰ýŬõ(+ÃÓJ?ÌEùçdÑíTÒ0›¨”Û×=ì$Óý¶¥~Ï„4d¸ WÎ\€êÔØ¨/M¶ã@f¥~EÓ’ç ’È´æQ&/–fs')²"ÏžùÝ4ÚT­´’hQ¿z2VK-P¢ÕY¤‚‚x-ã@'ÜãHA¢Q÷(ǣʅû'»€t£8T?™¬fÙ {!EÕ.z‰OnELX¿xŸì—3ÌÃGûåpêøxíž;ˆ .*(ƒ6jh•ì-² ˆvô­Ëö(q tRÛFF:…X' à>Æm;#åŠõÚ‡ô=ÂK#J>s/^6Þ{«MEÒê˜"¼a³!Õ:g(ŠŽ$ƒ¼"­‡”ɵ†äGQt¯ÌFVwÚB„haxL•ö½|FKÊf¸LæD•éL£„Fù­+¨Ü"@² ƒ, çªkµÝ$αÿ•–÷ÓÌ>N‡ëºè?Ò>Ë&ž ¡]ôg£HÎ-:^>ÝAjv‘âß„ð/üpÈ$2¨á¦'>¦ôïæÎ×ü{uçëë>Ñ¡OD¯÷úù<xÐ}OIXå½JÓ}ž7~`¾œ.›„(Xlj#nŽZ)Yê­T÷EɈ'¨¤ût/\ŒðòÄ$áa¦kvQ²Î{ð©Ð{×BÈz(‚bžéUK•UŸæ(i BB¡ÁÝ| ™WÙ]ÙDo'[;ôµû؃o ÁY)yÀÆ º€zôËÀäÏÅ”;ˆ~”šndì$Í#úË’GN¡zŸ»õfJü’ŸÍÝ £O¶ëùŨÂ<¡Ú >(!ÔÄÕÚš¬•?OÿÐΓUŸçúÐîƒÛ±I1S4Ú$Ï­nÊ”ƒj1Ÿ8!ðå8’æqç‰fÒWQ©' }ªÒݪ‚Öí]Œƒ¢œDgxà1º!N„pn–ÀÙʉ?IÀ¿N3í§ ÜÂðh,y  “P>b« ÖBñæïÌ¥±£,_Y.w/¤?ø'š7 PŸU™êxv2¢ð“dq[©â‰¢]$ ckìvóÌ‘ã†åpu9Wp·4`r´žÊÑ‹’¦ÍÖW«šÃû÷bv>¿»Iþ:;ê5ЦîˆO†Ûñ à‹âŠ*]uSõòüÎ]Á‚‹}h:bî—&a/Vš%$7AÍívgŽoWÆb7–(VJ#¢2M×,æHC“<Ä4@bðQ,µžõ¯|‹²•¦5ƒÉ‘ îG<¢’ào˜•©N¦H{:Â$-·{cX’èDX<@6H­®jXKÄ1ØÊ*±0x…9·‘p‘¯'Ow¡’VåèGg®r ÙseÙaZ³½JaŽüñ38‰­ñFƹÞ7¸0ÕÔ.GaK‘i3=Ð4ŸtÝK{a‚vôØí.9dÇ‘ õÓðη® œòŽ|žU¿—MW æë“É52ø$‹µJý>ÉâÛ\Ó{_ÖSo-Y«g´úóõ¼¿‡Éjó;Rðš­M½¥#5¬6ÞÚÝ ¯Ö€›óéss¯ƒ.Õ]<ÈÓ¦êÌt:´\ʹ4"¦¹¨¬—¬QTÙÅLõy‘›U6”áÖÿ~d¿¶µuÕgÀò˜7}¤×°"­y²CÍI¯Yw@#C‚¹'¿CT¢Rcn‘ä„u{@Üæ'ÞiYÈÅ OW©Îà@.gOw .¦WâMéÓhQ|¿ ·7ß:lÙ=<qWŽüÔÍRÓêà"Û…iŒê,ò:לՑ"Ò‘Rs;ï6CÜoK-' ¡®;8ÛNø«_Ë\)î³8µj‘Wê}œ)Æfœ“º4—êXË«~ûÖ$ÉÐ ýEÒu«¡~B ¦ˆ'UQŸÿ¦òöØÍJªám—<× 0ZšÒ\¯²¬¹@5ÚsÏÑÉDA€Šji&܉ä8ò~æfë“ÙYqSuTYy™ÇÉ>Ý+ßFžà±¡ÞR5æ^S²¼#%ˆTCÁ ýl†W`‘yG¥«þ^{Ÿ/ï%>ô$TA³ë"OjK7çläG®Ä <¡:‚§À—½¹]­%kÝ2â[ Â*–â5)ðê Ž}ؼ÷a37ô^þ¯Çm´aÜéW¿ÝÆ9Üïµ}ëfü'Úõû7§´qEïáf~="1ÂÒÿÕ¶˜»=€ƒŸ²¹Éãùtgx)HÝÇþâ·¥¨`÷ç¨.ñrä(¹>~šjž;ƒ5ZÀ ëº{ß4+y>Ûý1Sêá d"7¢<øÖÑ7§ßÿ’![å/Ï¿{6áoû:ø@Ÿaú6bÆðU8Jž:V5éS¤¢êÅK*%éÄ}ö;âîè+®BqRžø› H– ÌK“¶ë»kdF[NøëaSGDõOý†7)ȨI7 ½„<š ÞÔµR`Mü§ç±b¢p¥(ã¡~¼Ì0ntÒÃ|êIm¬Iš/×–­EW¸ƒ?‹¬¹ÃÏÜé¸N">¦®52&x²{~.Â,cð2_7ÓrÕœ°ã(¶ÁÆÂSÅÆz Äw=ÍYÝêÔÇ®MÞa·Õ…„î¼%ad@F]3´„(PŠóÙÅ|9—+K¬ UÐñœ½ƒp8¨§ +}öI‡R3p(þéè[´fË7PU,ϦP °©Ê¼jtËitOP?ko†€‘œå?>•õµXNE`̦()­Y„–øÔÑX,wWÚIo…5˜ΜÅ.gæ<·!¬7t4sÒû½äÇ Äïñ¤/1›™Gäf:_žÄID>ù6Ö6àÇ7ç§¼m„Ûõ\ó>ÝGI¸*A‚Xß½Þ&[7@ÄþÂsȧ;wî®ÔÝþv;sÇ8ÙÓS­Œ”¸€Bã†ûó'‰{X6óËåì‡/FƒÖ!СvÿÍH]@õ<:[ˆßWýå¸:°$‘FнG?F3Äkô ¬}Þ¹•Š %ì`YÉ03WX‚ ¿©MÜ{&ßÖ‘ÀµZ%¸qLãö(¾~y£KÝM¦˜óÕ~vtòön+úÓ×?O&üýÀ‹Á¸NP{>½f­¿C÷?]Ÿ!!ˆè+¼BQkD( öÎÔð¥â‚Ž”( ÓcåÙ~%JG˜Á<dÅöÊv¼(†Ú‰)ÂëèxvÐÀÀiÑT’ «ˆösOªäÀ´p(Å2<™næ›H…”eý–øékrrÓ?ÖR:zþ€ó%ßðoÜ4gX›+ºõÚËÅmÎèÈ1ËRÙ¼ mp„fƒüx>=3:¬{O¹ŽyvÆ:›ÖXGn­Ü1‹µ-ÞÕ2×å .ŸÆn4~aû©°AÀ’Âxïézì*"Ø™¹S_[ÐjPøybî0̓+I¿~=Ûl’?;‘üLk‘l*õLî«9Á74ë gI$´Ý£¿ŸïTûŸ¾Så&…£y¸›Ô§=ða¥ Oè½ôÓ‡}éa¬ÞõÐO÷>ôpÒýˆw¾ä™ýЗnú?þq­®å”ÏB‹TÑÍ$TÑ£±‰ÅYí5Žs¢~Òs\#²ÇI‚ý×xzg¯±YJ³4Tû<¯qE䢂YâÈã{ÏãV—eø h& #"NuÍz¯©™ùf½’<n~º :×'Ú°þÀƒ^\‹y3åmé¶×N_µÆ2‚ÒÙîzÓÌq©Ôý'ͼ»‘5‰©ôv¾h¦’tKË6vJ¥ndšîÖÝÖ&H²ÅKÝ_¤Õ>4›7ùè<›*(|Èôx'üR†åL³þ b!>И˜3‹êº‚Å‘–ÏpDRù®§ãS½f*eŒ}rg`º€UdNÝi^Z&yí·!§Ò |¡Ù¢×¢ø8¾("•»‹ß 5Ïq%-Œ< ¸:!ô+K5ôÔݘϤ;ë~7Zm¨§Þª–æ¾!NÖ ^%™ÞꔃÊpUs9éáÍ¢gQW¤\¦Ã÷ ï¤Zʪ•Ò2 Š†ØB글†t/ÅCIÙ…h&ùÒõêö& ŽjYÈ·ã›a%އ[]> lÇå1áy‘›”g“ŽÎ³v_vP°|Hjê?R5ÿ0æ2ê> ²`¥Tç³_†M´’Ž «5Í¿’–¡I9ŸÝøÓ¦9¿ŠqöEÝj¤-®øf¾u4›‹$m)SŤØç‰IˆU”P‘Ð[¾`¸)Ç  Ë ˜øãj½¹Õ3ž{_…´ÔÆ=6Ž7£Ó•+Ân½¤{̨äY6'\˜¤Hȵ´=cq˜=_ ïžEÀQ.è#&•ÐéPèí*KÌ×êŒÅà7 )¬ ¸žb©Îgô õº¿?¡£Ãëë™9Ÿ#zØ1ê/%Ü»'ôh`5àr…Z—X6wEðrxƒæÉDzŒøæ x93Ô6A‹ãë%4 Œûdëüì*x« u±q7UÙZKbð“Éh"9ü"¢Z’üRÙÿ”x^Õm¿„±ÿÓi#´ ?‚ÆÛåÝÍ/›Ù¿ÝÍ–¯gIhU3œZ =Ýd¾| ¯^í£Ie‚åûûø°Z÷ôñœÅ÷öqÿô–ü÷oŽ_?9~öIÛU[ëÓ½mOß\îjÛŸ i¾Eó’ewØüÕj=çÿtñËfþnfÍíŽÓ8ÈCÁöË&ZšV`õvÞÀòµ¶†ÿ#~¾Þßz¹ÄѦìª]‹³¹½Þþ²¥6÷ BNf_|ÍT*³¤ï-t %œ¾3HãôtþBˆ‹¨ƒùâœ?±1@Ä2Ñ2ªfÔØÙ|k %½Æ¶Q[Ud‰¸Ât×À^¯nn ú¶LØžõ›-#g¶<ÌÐf×v½ùE\{ÇÁý¬¨aîÆ„¢UE^ °W;qa׈Ÿž¾ü2¯²¦‰Iážyw„©Ò¸»aÓSpRëé_ /7‘†}W9gg.ùÀ?/§¸*ˆ‚ƒãÿ©ÃÞÆŠæáùrƒ:,ßë7ó1v)8¶y¼åMЬ•‚8­8L`Äâ¡ÿDgØÚV¡ï6Ú˜gg'Å‘ÿ‘yn1/–´=Èo’1–Y#§p«b$ÿ‘9A”:ˆ Kx)¯Ô&úîo…ó2~dÏññeg‹3ªõ)µ"˜A#N9rR8âñúÊmÿ5<œ7ÄØŸ2 ΀y5s(C/fÇ}Š#èI$MµE!µ Ò|!hÅj…é0q—ÎfŽ“ßÎŽ# bCkŒs繎3ŽÎ0ßû¢Ðï"×=“¬í»Ê;*ýœÈîD¥­e±7-.ÓKÊø†ž¶fûé€À©"h‘çÏM6.t… ûC­µ ,?—(ÆóŽýv»‰Œ}ˆB’pŸ‹—•T« WE;YËÅ:iéTˆ( (‰ä•«¯´¤õbNAV»ýxí¤– À‘|âz˜lÙåÇ(+`·ä§»¢K2 ‹êZŪÑ—=CziL®‘ñI.Pø 9Óž™à,›áRžDÊ“œO(Áx¾éÁ=: ˆäÖœ:,38ûfÁ64„ÆÈu<õ¡.m8ëÚPÑM7ì­Š†@è1oÌ>¤É “OGJ‰n\ü–¨öS¯ið*#º’±,8—³ó©!Ö u›Y4 ùèÌíÊF×P¥r‘„è‚^ðË]KnÅ;ë9Þ vu*z`€{ÉÔ4UEUHtÕG§«‹íÛézöˆq,’on×󛹩\ÓoÑ>Nß8權2uõ<¬äc+:¯®ë¤dèòd„ 4dX†Û`3ÒT¿- ºÃè×¶­~N‚úÓj}½QqxŸü¢49ÝG`çY,ÀrPÌ"ñP‡µ FiTƒ—ß»“¿¢–^ãÚ s¢(ëêÝà°‚E¡NМýIáR¸ž¾Qg,hA®x„w„\™ò!€”ž»ïT¦÷§nµ¬@œ£xÛÔ%ÙG ¥RoHUT ’ó1@/é: «Qu‘·°\£â uŸüŸ#zùùŠD#†§d` ŒO—î•Ô÷ÁÔgð¬@9ÃHHä×>î;³Ê(sCÓfÖ8L5nàžÓP,w8À°JX}é¸#ÈS§ÉÙ¾•[68…VËHÀÕÍ>ÚáœûjäôtµÐ£j—r¶.Wc{èk¤ýjªþùvó‰$ã£)K3ÍXä\¡÷ž Ó£:gð +&—1`$`ÐN»9]@4tâEE2šú'"†–FH+ 7üdA0ª‚VIm33·q.„ÒîºÓ&ù(ê«#‘bŠÎW4Úôzv@ jwuî.Jb÷"Û[B55;üµ2¼t,`ÚQä‘Á7êG°FUOBjŠÊÖÈGSŒÎü¥l}B¨¬l%wˆ 6ošþE4°fxMhI¯Íù…{A^‚x4ž"Š\ôAw‚rÐûË+»PÆí8H  "ªh@=Õ¡1Ö!óM¤X’ùÝ}cºÿp¾1;}^°šþù¼@ú2g˜b¼Bµì—OsyÙ¥OíõëSáŠñàêÔR²­ìÒyPÓ©Š¿šÎ¾J0ÖvÀ{ÆÑÿ]Š©H#˜ï×b¬v¥“_“_ÿ9Sõ]“‰¡W»õ_`˜¢~ö+{ÇÊ/pP÷Æ/¦¿¹)lþÄŸ³ãü¸æ ³O°O€$ŸíZæÛõj;{MÇÚ¸¹¾˜ñô‡§ÉéÞpVJD¥jjÚ,,=2.>–­åqkw5u±5÷oý¦N§7·  Œ|)åïôh´Q£__…Q£H=µCö?ÿ÷›Õru¼s´:þëJŽ<þqrrb'£ ‡ºó7eg/¿Ì~EpV¼×ËsÿóèštµƒR¼O;H¤ÐýÚAµ¡Ø^0Ewju+hda€”›äOó(Œ¬•Tn‚ð‰/ñºå†5CeùÀ^ä„·ÎõSHáßNoÝöÄ&mw­µØçü¤ˆ Ö±Z….F@ÔzÙÃ8­òÆ**óǬs-¹çÚ2”)Q*m| AHMiv_NJböJ•=˜½â{0£È7|“0ãöL‰30J(TA>VJßUFå²R%2ÈG*„ˆ²”~h"¯˜˜šZ³=aд2¥5 Sš©—ƒ·ÎµF¤v4ã=1Ëòª4åà ñÈ=À &ê•! T¹–´«î ]&·J¿bQ ~œÉÔàËeܲø²\?‚rÛñ 8ÚGIÐY‡ÇÆ;h“ÔE 3ñÙœÄMW·´!N9ˆ-ç¤'~|(#3²þræ.ì2¾pi*¢¶x€ø ¤ßß sêgïCa2ÞåíÝï'ööK0ˆvŸùyJ’3'Tÿ÷ÿ¿¿œ>úêû~9ýæ/Ï#äˆÅ_È+VGHUî~ÂV^î²5'êSþËêâãðtM_oçofaפS3˜—C«óû;˜Ï_ΧÛiÔ”_jÆÐ AÜÑ -ŽÆT <Þ_î²ú^¾$žõ4§‰DJ~†o㱆¥Œ9 ˆôê3íãƒùÌg£ Ákz?~uÝÈJ¨Wî±R<ä ÃøI©©|NÕÏÕÚø0iXkã!ԳŒžYìl®ío¦Ö{ÒRËÆT¢ äé ŽÆHSØvfʈ‘|öÊVË™Fðîârv6½‹³Df5K»zäf‰ÚFûˆ’Ñ™f¢ª£U1åÉDX@iEåÝE?™=ñèë9Ãò‰ªmŒ½xïkÝu¶ôÁyÒçòœ>ö  ì°^X2Øm5d–Ì}›gƒ,î¸Óiáˆ×Rdß­Gä1²F@-Q?-e—öÍ|¦’ãÝj_iÃLêy6GHñð¯”*ñ:Û],Ó=ãÊJÁ–ÂPÍÌ‚¥c'c$n”‡À“>֥ȿª Ȉc‘t¼ì8¬9´¹ü¶I’ñžÃÉÈWó¼ol)ƒ…ûëÙ¸ü@fŽ´E‚Yl\ÜKÕDFMÀ[úíeâ^>~úí/_?üìy‹s< ·VWëɘ•kºÈhP“‰5·ÁïƒFû˜0‹®F:ô·û æÌûgÿÁ*žÉÉ»â¾ó†ØEyà¾ÛürʼnûE탥}ÂÖAôfüÚõÕd‘oYLIªïömàéÿït°~aÃißµ‘úÎ-e+7äà«Þ€þ8º¿»¥¦HÿÓRCK È ‰ÃÇ‹aùä0§Cˆ%KÓú¬ïÞ2Σ3k¯­Ð3ˤ1Ú«mâ[¹ÓJJ$™—ÇÈà©2¤”~£÷Õg)¤_¨Õ¿½[¿ƒÃD€´m}òzÍÙ° §€O^rÒàtÊ2×Öc Ž 9Ó§ N"}*„È¥-¤ó1ÖA+À<3mÏt>ñA]´wUÕÎGnŠ,ë"[Êé®`éø®Ü~ \h‹w|«›âžÛ\>Ë[C îa{„«LG<|p-.J‰1E r†ð#ºçóª”âûà8] ð)Îö²¿5–´š0!£1jÖ¹£_ôaŽmmD¹Çâ]FlE*h‡âžw #Ö¼~ ¹ª‹£=mêRýow³;$]mD€0¿K¯Ôï&Ö+Á§FØ‘IÕý¡kþûFX@mñƒœ‘;F¸øÒ²Åñx’ZÎ~Ýâ«ø¥…¯*SžD•L™Ò1’6UmÊ*ðûâ… ¥¼Øœx‚Œ0ò„³%EØGL'*Ž/&dוt5vZlÜ5ÜSäÓBŸm4™I‚#‹6v¦2Èm@§óÃÚ´A$Æ/Úz„˜ŠÚ‚¾ÿ–/¹Ö®FVØ"t³Or=Ú" RÑÕQâZuuÓøt»ÿ]£ãþèut ¹.`%_=ë_ÃZàÉR£ÏÇÉ7@$ž.ÔHÌ;Ʊ1ص)a„t;|Gà‰õ€r&äU‰7¡ÜB'>æ7€Ö1_hä’AÂχ·üûºÙ ¥Jþ~¸Pê&< ò÷âãÝ)ðd9µñpï›L?­u¶)^dЭ N ’|½i¦ÄØ_-9Jä‡6©?xŸŒQ­ãü²>D= e|óÅìæ‚A¦‹YH:r¸ Q2½ ”Í« ÁÐ…ð8"v9»±ë‚0 ôÕÍD¾8ü%bäÈ¢ç¿[¢Ò i†OFm‘z޽Ó(†½˜Éwxl½$bD“Ô:ñ¡îQhUâ×2¨ ŽþrGÀ)xE÷€k Ñ®±·bÃPà>Ù? ¹…ßAÏ&ïccV:Ó!à£Oé#­©hнËý¡I@€B¬˜€Èa+Xš²äÃþý2Ò… ;6?¸ñ³ÙFªyˆ•V[Óp:[¿™¿ž…xކi‹vÅ4ç.žbjŸÂîá÷±»4÷öEœd¸¬¥%0ÿî¼8ia~†k'Ò¡8âT)â6I¾ë›TC'K‘ê³j •*MBÊ*l‹ûÉ‘ yqn£„Êì$e”1†©mž|¹ $Égd«¤JPÉÂ2Åøb=¨Ù唤”Œ7ò2Œ»ú¸8zE°éå;%ànÒóÝÌ-º·J 6ž4@6ÿ7†s–>ëz#•4Ý»»ÆÎòÅtH jæERsÿ(äcqAcpÅÃ´ŠØ"x‘eâN×ÔõvË(¯ã¹Ìà°t9›A]àSÃÞB´v¿^Ü1,AÁ¶¼'xV¤ ŸØhÔ%Yä6܉8†áöÙ-̵nïÕt©áí#ßf„f²(áÈì Åyª¯ovÈR‹WÿËÝ%rà’²)_‚´v©z@idžˆšBJ"r¢f‡*Õ6kf½rœ—P˾‘[Ÿ¹jÒç'‘þšÒeôkó 0;€Iêà,žv#&Ép)ëVŠ—dšEú®àê26)8ŠgÈÑ)Åò´ìÎ/)ºÒ\Á=yV>”G,³Rljëÿd½šž¿ž"Õ¹Çÿp±‡œ )áÅás}{»ÐFM¤fð™¬0² ngWqŒ4=·XtÒµžçò—“ÀË®‹kÉ¡ÏIWH¥]9M¨÷Ê” ÞðéVªPãHd$¨õÂ×fÃT¥s µ+ FÀ]ºmÏE .ŠÇAáð‰æ‡}ˆO ȵ]&§¹œ_NÏ~ÛÎ.×+%FQzšÒªòmª"£7¥u™ËÝÞÍlûNÃT±Ë?•ߪ‘ï"šÃï!ªþD^Ìõt–¢ˆå'EýؾÛöáüò²Ï¢„PrEÔF71Íõ£æFÙix-zN9'¸iÈË ¦°¼ÞiFH9m´[f޽Åeá7|ÐJ-õÇaœ|§sb`£}- Ø  F²”M¼XÆèe:¾èU÷© ur{°3`ŸH…^Læ_}›:Vûzµ^Ï®·}psT~™èA¤9%FUȳŒ;' ²‰Ò¿n{5[­g[b¿*éÅjq‰tm뛩^Ú’áÙö‡‰4é;)]'ˆ:Ș$PŽ¢gÊ\¯àrϳˆ§Ìò ½›;«¥ó’‹1åÐiåWê!¬Nž“íý“:F¨sP9¤ëAbC#)tÈxÊݪGÉ­)¼É·p¹ØÜ)j@î•Ô•÷<‡íJWVÚ1 ïHŽt”M/ùöƒzIËgðµÄˆ»…ÕdºH™`WëDÀßÞµO—0ÍžŸ›ðßaß ÒDœöTîŽJ"Šc©iŸZýyN<% © ÎǪd”8ÀwyŸ[ó=&»ƒJˆö™ÞmN¹È²LËhýéNó4ZH~^{—ˆó=£sû¤uF{PÛ¬M `þ …v>üȸǞ;4²Þ°JO¤ñZgÅø@ ‘éÚàž¬ª‰˜ûduÖK*6.Šš°²,Óâs\E‰µ1ÄÏ™ä–?N ¤¹ß]£‚#|ÃÁ¬Ä¸ÁS3!×β:>Ò»¡U:öH­ä“¾–¶b–x'þ;ìmëÌUB׎××—Ñ™²Üñ5pS’÷½“•o¹ ´&4à2TW©ö‚Žç à±[·2¥œB×Ä"‰R˜¸¤Ù˜lÌ7Ðõ¤åð4øÌ1¥!Àþè[ˆÈÁqѼŠq•¥ï júÐxr¦éÓâ釾zóo¤áE±$Rïȿҭ©Ár[;x¥ÒN¡+ ~žÉKSúÜ 38¥ºór’<ß$7wޱW43š5&`þ¼có“ó“N8åâq9]¾SÄ”³VyÕ"Ò²>ù¶Áf6Lä{!W"zžÀÀ*–ºr÷…(rN耧ª{jÒHc›‹Æ¥†œ|n#&Àæâì´C5i®±v2TÀªèk¼¿Ô/wÙˆ/Å=1BÛmSûد·õ#ÂQ‚gÚÙo"^Z‹úÀqÅù]/ÚTMçmçûÞj»žm ÆÕ§µ®{CF§r ž²§†H‚G…åàý$šÕDÛ#?H¼O쨛ž þR §Š›©¥”2“a[j!ˆÈ¬irV»f ËšN¡Ð™üÝãc/_pCJS¨¿©nNuИ/û¼ºZÊ\?Ûm½ö.Ë£¤z™6³Fƒ Y¡dˆµÌP¦bp£É=šoImC{ U©å_ ï¡îÂ#E5kŒM‹qË›|‡+SUQ¿š&ê·A*yYÊxwÍNˤäìtôÜþÃά±mÎäNR¬—Ô{™½YœxÌnjU6#9FCÅ5P•‘R™{$Ðå§‚ç³\.V›8ò A]e\ö÷oÜú:a# Fõ O¥vgößq5™¶îËQ8c,m¡ÁƒHÜ'E\æ’å¾cj©1`ºüM«¤ÂD Îu9Uo<>qj MòJét¤à¿–3ð©­We4 /l XÈ:ß!« ÂÑ)… ÃÁÈ´Œ¹f‹ó¾$ Œåz‡Æ<ˆW,½Kðé‘wH Æb:ða‹”}T¸9öÁ>õ½«Àt‚R¡Ïs6·î¿jfp _¦*o™HVŸÄ¸Ž¤­$˜È*‚‚“ V9s9ÎŽ†{…«PG «>% muŸ1VúEðžÿRÉQì,£Ö„ª¯sI5!.KÏý¡Ê©°¥_Ð*.KC<Ƀdü£¼j…yì ˆšu[ºP¸³¨N[¬øÍMt³®Ñy*½X­ÏEÓSEoyc C ÖÏ™Š£±w%XéÔ¡‰L$D`ÑEQÿìÔ÷þøîâ­s§CÜgпžìä•=ÚE$;ÙBëFme‚bÍ”}bD·EÎR©õ¨î^a‡%åÈI==|« ¹äLa×äöi¬ãñ¹TmJàRæW7AwÔV‹ {ÄãèD6š—AÉi©~iz.¼þ"¤¥–*}½^M¨k*Fv9R5Åà„ÿе0 ?°$­Ú¯/§‘ß&¢N¥ÅÝòyiÅQÊJ“u YH)HÌÛÙ¤ù8:@ŽgJ¥FÐ\™ÙB#¿%‹¹\’8‹”!ŽPêlGÊyG¦ZýzHýLøgÜÓ_fm¦ßâ ×?5ÇÉܰp ʃJê`÷:(E|²M}¯±V]®&¡Y›GÇ^Z­3BxÑG£ÔFb­‘kÇôõ|åäB·Ô1— åý‹f¶™Ú¾Î2Mw’î…qMRŒwžI¤íË­iúdOÏ€¯x))!£d¶Rcø‚˜ ô¨™½|4#a£º¾_±ñc™u &é” æç‘˜YÚí› M.­´[†.»ãíÏì#PN1Qµ0“T¼‹ [ؼž2öI þ–>›ÚßiZnçówâz0‘&ÙÉß+¦(ÿ÷Sôž"±Ã½7°¨pÿùA»èÀ*B#m.(Ééõü¬’³5yˆ»-,l pêXî7"ýaÂoãCUâ?a<þãv±Bö†¼w¬Ôö8šãÅì|~w“„çkÂúèÒÝåÍ=]¿§´ÛÙÕžuéÎIú§ÜÙÕ>ÚjWßñÆ3 Ý‘†Ãiw v 7áDZ¶’ĨÕDšC°û'’˜þ©ÛË—½gÍX¥m…Ö>ªòþóѹ˜[êáO×Íê\EEÆg ²Ú|BwãéÜ÷ÍUÚLÈÞ#DuÞ3£éÕ{ÿ޶Ÿ¼…°²UÕ ê9%mÝ„ßØ §Éh<ŸøXC´]O8˜Á´ÈG¬÷O0È'<ð¨¼ë¡ìõžyŽÿ}«‡*HuÉ&1µñ**A0ïïþò ÇI¬‹Nú牴Ì5¦¯oÖìºÖ¼E°f@CŽ&Ö…o 6)j°cŸ *aŒ6Qíºô«Êklb><“QYÊì)£BwfuÛœGy¾£°iÈþ Ï §Âý`LJîx¨áž© šÄبÃÓ.gwf$ZNø¥ñvYM(/„}3©ŒÉïK¿aÀ C{ØD ž")»»uü;®.…æ¹>ÜâÓžbYSuó—®îÕffirZ·ú¢àÿ“›é‚Žñ ´æFƒ«‡A9!þ “¡6÷ÝÝ›ùlèO#ªÏ¡™¶½>·Éî?ÊÅT£PÐ Æ9Áv!FŠKGˆ5´X\QèqÂAy¯žk¸<Éî9义‚äÞ­.R)@9=¬œVwÈ-éÌ &pïE¯ÿï ¿xIFÿ4mvëLà駪ÉwwnwÞa‹¹ÂiÏ›üÓùDæH¡¶I…Ol“¯Ô«gJ’[Ë2„`ª“ØY6¯ý<"qèßÇ$æðqŠ*Ž› ¿[bèöBçEä™ír¾Ù Ý#R§Élã"€Yd}x¶OD†Éá°Ø š» ˜‰RËÔ•)£"/)PŽîèôõÕÛ9<è¯%®ùÒ60 .ăødß•õÂ@; Ölµ0Ø*ͯ“NAÌ­‚¼=N³¢5Y4]‰\ˆ¦›µ~kº&œŸÏÆI™Õ"Ãéqp—°`µNEkèxZP¤Åð¦Ýâ´§PµPMß "òWEÝ&P@§f\h¤Ê\k~kõŒ¡ëO¡ ?)ò©÷g/µéØ-Ê[ák#ߎ<Íï fTÖè».Ú––¹?B¾„²†>±cT25¸A3±¹<1seªãó¡Ú>Ïy­+Óƒ{5/šÆÖ“në~ÞžšÁGEäâ®1xKAÔøizµÆi›/!§ñyê=Vʸ‚¡ÝCl¯×Ô>IÆåˆ ‘Lg'_ÇqÝPΰ–T(VÏ[^PЇÔjÛF€Ö!â Ýj…~蔑J„Hyís%ÒGÀ» d:ÆÞŠ›o¦_Ç£!uÂÒ/-;:÷|Ü*Í1— Ö‹±Û|©RmyW¦ïÒßN*1‘7ðÚè‚2YñÉœÅñÉÂN™–ÇÒ¾?§RoÆ¡8\›žÉ6Ä¿‘…~éÝ<Çá)Y(©IZNïxãll²‘³„_fñIÕ³…ä$ ÏŽŠ¥  ›@blðhŒ¸aûÞÏÇš®µå€w”œT·«2Êf‚`0fØ|çä·´éJâCCˆ°:Ýßæî1 \”¶ÍÇ0ÍâÇÒî@ijAÂP¹­+\3 ´ù‡K>y2àŒyÝ{ø„©¤dS@‹Ú6AÏ ieÜÀ=É|湞»æÂPj…€ïZéd‚‡˜hÐaê[àB­sŠ<ˆì!,µY„¦Ÿ¾zƽ-£ËÇqîº|]5†[  D,pk–´¢ž6ä5“Ãpmtmó¬ÿ¤.ÞªÖG´¶ƇYiTÑR—vGÕ׳¹˜3/¸xV/Älùz7(‚ã4lÒ`yΧ&„€Çþ—œ[I'òÍåì3”›d;Uêàî½¶AßâMãøzX8þi´ÙsÊê3„•ÐõMŽ~'á·Ë±+CWoõ˜ÁÄÒ@±ôZ}¶ÃÑÁøRÚƒ¬z³ü æîíT1Z<º_®C¡R …%CV pÒbŽG9,äÙe)Ó£yta&í¦f©ÔA Ê_D"õl£“:Þ>'i]Uµ±Fº”ËÙY¿ƒºµµÊ†±ÐÉØÌ>…VçœîjʉÙXé’Âwë|µÞzß-Áèõ†4·n7¢Ïó±ášJ>TŸú'š¶bzt¹–VL xW–[¬J­ôÂ¥2#±öqì©¶àŽ)˜ÓQ‰Ï€\Ùè+  ˜ZJæ)©ö 9¨p'±p Bm(”øãÄjîëõÂFϧ2`ÝC°{|ö ïôÆz§ÎjñÎy•ao‹Š¤ü-ŽÇÚ–ßûÓT*Ñ:r›!52Öc…³¨h)½»N{ >¾úB§U¥%7Ñ(^V†oâk•!¨t×wî5Ù;³©áÚ!æòl®ä̌ޕ;OÒ„Ü,Ø‹"È_…áð.”˜ÝÌgê„ó;¢($ EÒ‡8ûÝ‹½ÎƒÿÓø ~ ùHûú^GBw¤ÊGBšqÞFßK¨Ò•-¿.)­®—z'kå™…5L#fJe–N3ní|ó$ˆ’)¢z€Òi—êÏ1{n„×Å7©ÖeµègáÂw!ïBnÓ•æé"a_Ì,Æ6ý÷QLnƒoËùì$âDQ®Ÿ¦ú}dz`\qäU„×ɲRè~®SÒ4Á…šÓ±GEž€ó©#m‰§÷Ç€ïô°‚CÈ£ä‹G‘‘C`V‚f´ÔEûiº‰4L€r+{FPN òØ)®X!Ž"ÔÍ@ÈÊ"l}Ýs…F»<_žŸû0BC<çÅfKÉ`{¡ asƇf˜å»5.àQ_‡Oó4“O£³b`Óî~±dGVíºH‡ÑU6PHáÑWÙ×½Qiò7Q)cU¤>çÐ0¡¢-ÔfÜUÓhFbô^Æ ;â^øéh|ø±çâÌŽá^Oø%·tyåpúqKü^ÈÚ2p Às„;›JìXnA>µL Gáítã ÑßÓjceCg­ç¨6¦þ!ú¼ZÀqÿbÛÓïCG,&‹N·- =RáA;ïq9 >Áa.5úðÄ_èK¥N¨cXýPÞSzZ0àôÓŠúó}N±VûìEÖÚIaÿj„U™Êœ; È'™^Ï!K‡´\s{VCåIiY·’#•Cgná$ÿ¥åïe²€6íilF–,)"ùÑCBd ŸéN{‚aR;3 ®T‰k|Ú é†e1¬RÀáÝ5’‰îF`·àG@ž7ö¤úTE1äyËL˜î„þè$LJÜyzÃhpnû/€gÜ)n5…e¾v_²YšAáÎ¥K¤p³¦Cl|»#UM Œ|æ8·ÄóçS»f–ndðƒ›kaË­4å‚0m¯;Ò4¼Ðà¢ûý¨p§[cýji½d8,8dQSû©Òþ¾txn²¬£Ì JgIÁ¨ÌœöJ>CåÀðG5Ày0’‘ʨ#<ãÍš&ŒˆTKu}¿htÆe®[ú(V§d1Þý³wjò4åmÖ±{Fk©?&zÂD‹*#8jÄisÌAï듟Ù"µïqØcÁŽb…¸å7î~ݹc¬QzF®_ñˆp‘.ÒòŠæ1·!’gÕCZú3aÄ#xà¬eãµ(ßTJE,æQJÈlŸRbG+Eк}=]ŸC•اUz! AcÕ:Ê’‚ØÀiS*o%Í¥B.ˆMâÖ¢7Éë *ÊèP™ÎqY¸ ‹9ø·ñ¹“g 3ÝñÚº‘…ôë}«²Œ‡_/¤Ô3W^\[¿UP­˜y •ÜêòúlºŽ.¡`v»rÄÚ;®–ÞæT¶~ŒãT I%Î$jÄ.´ƒžl |·•²™´© Á°šEâQY ®ÍÑtáMIx½q;Ï÷´Ñ§™ŸÃGm³ZnúTÕúQŽCpNáš“As¼Àä3 E¢8$/0Kz]ë‡ýOÍÞT‚Šíßµ-rgᑃ”Å}¼LAZÇïÐFËAŽ5‚÷+öƒ»O‚bWÎ]ÓÉÁ¢É v.©^Ei]f@da&¤4ÇFŠG;Ú*‚BB¬^˜¤ ©Yš^ Gâ®®pLFqª§´)GF>tL̬Ó»Z „a½pS÷·ê!šÕÄ’×A¨#”)r˜ƒqLCäÔ¦ÖAPA}¹^‰–½8¿·“}nÚÓf³Ÿ÷'Ã4ͪUÖË•žœ]‰$aŠçY)(âv+èZJµá7 ÉÔBÛáÂ@»•Ur§ä)ñm3R<@E,9{-Nê›–]ts˜-ĆiZïÂêŒ3É ™‹vè‘LïÆ#Íœñ=æÇ›2@ÏAÌ`·2W€Ýòˆ8œ“Ïà}Ö$„ðù,”ýL@ÝjæWß2É4k¥Ô2ƒÍqô¨ƒáfá®L<â(Ê —C½šR r*„f‹3ˆ±0‰ÑÌ#T ÓóÈ”Ú138üϘÉ+䟆ã­L…cÓ[7]ÉnèÀî3˜A‡¥+8Œ5DÀ‹{F2±«¥±öׄ¤FÇ5²ÍPXÓ]i¤È©G)ܳВ´ëà’úç­ZrŒA)³\êä€Z­ÆFÌ”ÆR/IK­@¯ºÞd ŒŽ¶PõW¦À ¬3»TY%Å™í¢[Å¢,Ð,Ux7¤ÕLN@ÚÝ5ßHyH*å±Ck-ñ2ží+N›ò#˜?5¼æ>9Gª+7†ãh@p+S>À@Fd÷)Õu€<"'~“Çû ¸³W)JÓuäùÃóz#„ŒQc§[÷ªžÍçšeÚÑ^¥m;0ÇuƒuÅ)újƒª¸¹yU£‰;¥_ëÌK ÇÑ&fU®‹Ý'ãä½ÓÒpi¼›„íRJ*óVbx't_ЪÐÃãe£MÎŽ™©!ˆÉŒXD9禟ʨõ€æèåE1Ÿ4˜ï–“–à s Òb±’úÔ@×Zí·R–©üÄÉ[ÍŒŒŽ¬‹þÚ\¤ì[Þç!ãø½td8–Ÿè+(-W|O¢ (l.»?Ð$‹Çjæ "Š‚zÂRK4Z2À·=ït8—d/25}nB[gCæ µœnyýD)²—N`Ô8¶É4ÞÃ#l‰ü˜Çu£yžX.%‘§¤aŽçÚAf>ÊAMÑSÍ ]­ßÁÓ¾o¨ÓÚlà‡3ÃΚ?ˆÏSCñÖU[ ð0(Ú—g1û¬€#ûî.Æ«‘NŒ#€Ÿ‰{ÑHF/5+«WCW:Nâ["šHÒ¢Ë‹ÔØçòâ$q'Íæ —{’€ÃÕÛåcC’wo§ëDd•z€Øó)DN¹°<ÁzôÍé÷¿dÈ_öËóïžtóh%#0-Ï= ¡ŸŒÑ¡0dc¸L±rÒŒ©M–jqšy<¸>®ßSǶhÇ· 7zÄÀhæ7à rvçëuÄ´.Jß2X# Ex ÿe„9UV—Y#%ä^Uá¦ÃP kÌÖIP°Õœ(¾{ú“:Äzà†ü¨1´‰+ÏŽøzß÷µùhÙJ¦¥ ­/¤Y˜I£Cë3ÖfBÐKÇ)8L5Óú ìü¬KëŠ|s¡H"?©¦Ñ^Æ–Yjéùñð2›áQ®8@Š w–;‰Ø*U½R+¸šµ¡ŒfñžH:òé­@gL¼3_æZŒ5qöæÎŒ­ºaX4T=w¼üt—¸X,EtÏÑ0”uÂd‰²+ð¼a3837@‹»s½_éõÁY4 ¶ W= |ö«D>T­†ãÌÁ7"H’6$Á³Ä‘Þèíq2¦~<ÌBí®´.ÎɸÂ::@þÝ…eXr…c‘©„#0Š:½U‰?Xà AÝ™Mrr Ñì]¥ßF {D8¿…mw³:›.DG§ºÛB‹Gð·YJT}|Ùç<Ì8Ÿ(¦¡š1CW«³½±¶&ÙP õ?/œ„~&yׯÕtA퀉—MV‡a«rÍà3;ýŒ Úïfww> € W’DV”Ä‹Ì0½—À [Æ##Qr¸ˆÎDE&ìË!hŠQÈi*¤—òשÐ7%àPY:R”"•ß¼P¤=¯…ž5Z FI‰(L}–>­1JšAË*EA™â™ÓΆ eÇ™^}S”GDq¤63J]ë€w©ÍL1–faºAã3¨7Y´Ì$crGcã™)Há¡ÉÓÔÖ#ÏLö8÷„q¸$›è^ž³ÇWË; IÀ®3[ûè²éRü\ À‡Í´”DP z¦åk<8°éÊçôåÔ‘¤—‹éog@{ø"ùaövzSU‡ÒF‰˜D^äN»ñhÀðâfß$ë}â£1ïÊ¿1ÅŸ*Í/Ü“KxÀù%°A›3„Å Cjô ³ÓgÚ4õÄ_ªVDôÄÆFd:ú±µ ºAŒDDa¼‰Uî1ù3÷q®¬üÞ;½Ô l—¥·§Zahª±—¨)læ…1êᮑí`1¨>_O’(£lŽøÚ]ð½ÆÇƒ`]V6FŽ¢4²X[ÇÎÚî¹kY¶ŒZJj²WН’n'N3[¨ËÛ4b8 æÆÿdnhô¦,„pÄòˆÁ±ÆóÆOÁ½Z-ÍHïÓ1‹›%†˜JâR…ÈÕÄ–1´mF]”’•«Œ;Z9GmÓ°t áoÆþZ¿  #N™­êŽT>šÊ¼—û@¶+†x2Ï%O…ø4ös¼Yê!„D?R NÈ'øX«.ÕVÃ"„¬iY­#¢Ðب“XLÅ`•RëMât—朴èUò6azýê>÷d¼?“³p€`YäŠãJ!þ/Wk'ÌÆi#2&'@…@“Z³‘¶:<¸ÞÌo`” [ EáYó/‚TPTSJµmLÕïµ º¼gQýܰµŸðŠšz!eä!4Ã<\–6†±¯¨@¿z/̇—´Í¨Ø%»@Ôx3G°†ÔÎâ†G#‚‡ø/´mM—tù$”„›@•܇$ÙjžJ$Âpd…±ëð©záÃ{ƒéÙ+ÓH²Iö­œC@ê,·z=Ã+V7Zimôb$¨½_Aæ2§¤²²QÕ¸ [x±à4Š^ϧ&Î*­7dp½QÑÊ ÷0æe_ºøÂ™Or%QNu¬Võò¥6ŠÁýÕ‚½qªÓbX|~}´S22Ÿæ–6ª÷þdúi%‰ÛŒ©yOø“ß0ÝÀ%ž\°Òà>©äQW˜K͑άŽ’]þÁ 2gaS©å@/rc1j¥Vè»áù Ói1¤!IÝl˜ï·¦Rgœ„§¨uÔc}cVV™õìÖvíYR#^tÇÒ´áªÎ‚Z’7Þçˆ/µ2Äø£Èk${‰E Æ-å`Q_ÌT $-¥®q?HúHõr­Ô(mµä·+qö)`Jm‚·jE Êò+•…µNrÇÆí;S™ú£ÒÁ&ÌÆŒ`®h_xy#u»tÛõavk”R}6‹ž´Ü'id i/M²E±á Ëçˆ{•,x27A>‘`A.>*QZ/á o0uðZóKÞ€«9ô©SGKx6ïœZfN&Ò\̼ÿîrå¢ì‡à8àÊœOƒH«ÊöñqŽa€6®gÆöÜÆ¿ËÔPCÂÀðS#K¹n¤ˆšáM9S#i6Mrw… Qß)ñ*>?ë;½*ùε°&¸ód¢f¥ZTx5w¶æªJ›ÏÝíîjy\t§}KvÈY´Ú…û Ç ß÷+††™´ÈÁ^Ä¢µ[¦™AÎS$1x+7Y^d‹õÝõö®ï*ýZ#èzªC÷@J ¸^(©yy†Ñ‹«j2–,à¸(n­{PI6.à»×íž@܇ÚBȘs~#ˆÕT¿øluUÃj!¹—ºkµñØ…Û´L}(C'ÚnP|!í1¿k3oî«à]££}†ï\f5Š©Y–ÿ‰Ù`SYÍ=ä¶+mXfw"VÝÄÇó2oGœ”>¹e^H1–cu%"œz‚Á¡®ˆ™@íYc^Àâ5îC‚,‘ðNÕ‘WóÜ[t*",ä×#âx«8 b8ä~æmïœÉ˜!Iÿy©® &”úo¹LÍ5©Ît=ú: ïÞê÷u…ÉŠù;ѱJ¬ôð~‹v¹#`m/€Še•«X-¢õj%C`±Ô¡!Ç@tÿ£GIpl囑6™qQPµÓKGŽpüþ<¥9¼‚þ°ãFƒh,Oº§éÞg ¨£Þ@ăçµ`4˜:9“‘€ˆý…1Üã×ʲ€`„~Mîwóîí *Õ Ël »¾çm *ú¸ª?‘r“Pu1F·(›c¼6в@Ðjw«>ÞãS˽›JT8Àýb±ÂiP\{Os醑ØÂ“l"ÞŒŽ9]ß3½Â˜Ø¢í.9eiÛ‚³Œõ6Uk=÷µv¦§¬êÝ+–!“|8pëðò²Ö‘¹Ê’#7²$Ì? Ùá¹; Cø"_L¯Ö=›<ÌQ!²É‡P¹ŽE-=îÉø@`ùˆÁ[ÇÆ%ÁþÓÀ»e𙼜9}i(ˆj̯¤Â8+œrPR‚Søzzw»Ò•Ó{ çÄC,=Ó’K; 6xD{ê5d7Þ7B‚¥¡0 ?73 s½kà£8,õ¼Ž2 O±Œ[4¾M<Èš„EJD€¤xäY¶Õ©~(˜ðô™GR‚R„¿ô„âŠl|Õ{ý•øÛ#JÕ¤úÍàP+jM¡# ¹óùòüà³e¹É{J+7ãSZÍppëÞbAeò6ÍÚÖ ¯j¶'AE,ßå£>Å5Ê”…®c?m„ >Àƒ™Û3Þú)¤’B`Ž †$r©h+ëGú['K­Wšâ³³@!•¦úˆ(>Œ×úxÔ"íddz¹%ëx‘öwmYõŸÚ² -«Ý×–!‹—;4ò÷âÓ´eÃïRÚ¤®€Eñø8­¦) Z݉ԌŽQ/¥Až|ñÔÍÄ}õ?Jf@% RëB|ø“{(€Q}á–Ü-ðbå.åÉÕìW$Üí»ôzJ}OÒIº«63·ùÑ£ú3‘öŸÕ)æ÷&¤/ÚOŸ,„Ó7 $•?á¥hõ9ƒ0Ú7]ûOÿ6üKö7G¥ŸeKF&òõak›•î¦á°dÀ¿hrd‹˜ð׃ŽTSÚ$ÇÿÁ”1aÎÿ'ÙÐEØí÷Õj}’læïfýý&^s*Èaù'M¬˜DCšøéë¤sÒs&'23$ôîòÔáèv¶8™nngŽÌSðŸ4G<à-¶~­}€:MÍ5Èí >|Ò쪬qíBÙ ‰›]ØP·“›Hž…/ûW'^¶<û›ü{ÿ<Ü­è˜QfÎùV—Ì-Ÿ|ç»î¾;Ÿýž³Ã¡ šhº¾vc>â¸9˜|òü²ô~¢¦$ä4ÝFB™ýôôå—^ÿé3Ë>üUÚ9µœYfp±šž'ßü닸€¦NÞå½óKøØfÊudiø‹¼Ã€ümÀ»½ð”UÌ`@vòŠ˜x$›O{ljCaÜ¢Üîl¸”1\ûŽNN’ŸaZO“½C*¸wnL/¦ÛõÉÏ“ÄâŸRWî5ß;¥¬ªtN4-«Ë˜–eIË0Ü@˾[-“{èÙCÒ2Ì)в|D˚ϹÇÒƒ?§©*ž8!9üKæÿ¢§Òþ’ÙÍìÀf»Îi+ ö7œ‰æà³^õFù1¹ä–sI¹¬0uw›H” è¿ÌàljjzïáÜÞ£Fá*Gk HÿÀw¿û w¿ëß“|pO˜7ö³Þ“<O è~Ö+÷ÂÓùzuûËÅzz3ûåb1½|á)„§Ôk³þNÓ4õÞvî&ˆ»øË•ûvóÓJRi¤»û§™™Ž+Lóf¾¼ƒJã —Ìs7›õ~eÆg˜g_©ñËÃ(5ò|eU:ú{Î0ïäföz'´Ãw2¿ŸaÖ‡ã÷™g7š§h/bžÅé8öàœgQê‰}½XmfçÉWß¿|ˆ[|˜è³w/r†’¦þª+=,æËë8øéS,?PQ%§ö³N±´Çr9ûuû ùº_úF"±[‰Nš¦‡p€õ»Î¸} ¼ôÙ¹»ù?ÿËD¾õíÊF¸û×ús-på©Þìævµž.’5gB ª]wÅ­ÌßcžFõ세³‹ö71ÏúþW,:Ÿ}žµé{~|òcr>[L{uH^°¾g÷ r‚¶‘Ž 8¤‡{¾>Âpü¹)_óa”2qAL™ÅüuL÷Àhwn̽+Â?<év®Àû(µ –‘â0¹4oÍåŸNõ—7ð¬{=]ür»ÚÌáVz /  ‰sJú)¼©ß{øçÿ¯&ò•ß–` ?ÿ ~>ðË„_|v ¿ˆ$üý6Ð{þ<ÜÕ-¼„ÿo^¹qõ!Ì£ÅÀ<úw”ð‹Ô(ñr•bì.çPâb(â0Ïðð󤈰°›éëõ*™ž¯“ùò5Þ›¿w Ðú߇¯¦îDäï͇$ Ýí½é¶­9Ü{óãoXPaœª>?±KCþ»œâ ·¢¿Á!Þþv;{i˜øÝ}~ *ï¿Ë--D>wç3™m_Ÿœœ<€,\ ÊØ(Ö±«%×ø±¦dúK&’L;}[ñι€B¶‰›i2xiξÊ÷{ñ}˜k®Ÿýgxµ›=ÂŽ˜‰aãaò‘•¢þœ‹A_ЬÖËÄs%'ËÌÈb_3çïPàúV¦ÃÖÑ7|؇2Åøm6¤ˆí3Øc!c"ßÛªµž ¤$CG‚Úìó,g¹›á9¦dâÀkgClÁžDeò“¸vƒz=ØMD °ÏL‡ÉöJˆ²´~pJÄL¾ž•i=t,È>çzHþÀ‰Ë@fŽzt†i@(õÅX¹ÙÍ—ÓŘé¼Ù{"KF³Nó!'iœèìæöjº™oUâÃ"J¢? x^ü燈ü%bmþ÷ôÑÿñô‡§Éé2)µ†£\Œë—O_$šè ].`A_¹?`Mˆm ò F ÄPêZXzA;„](Zн™/ñÞ‰Æ ÷Jƒüã± U¥ú·“*3ˆ•µØ¤<@øßMÝÓþS÷|¤ž[ÛîIägÕ=êß×Aõ,À[`¨þÓý™°²]DÜCù—˜y£ÂqL’o–’éÜŸáÇUüñÓ«õÜŠÛ«äÅjº>FsÓõë+äÂ+w|\÷z>ýæù‹çߺ¿ýåËçø÷+üÏw |àv}|Èœ f@²vúzº\BmÆ‰ßøkxîŽ7AÒ—‹“›ÛK·ÚëD±çaI6'²ÖiIº_JbQ40:(5þd %ù~åÔ‡“§ÖŸo]';7>™ðC†5ô(y;ß^%§Oà­;Ý:-QDÉ"+ó kÙä»J'Ï÷àæî×_ ³&󙛇û¬(Ûú¡&q ÐGÞ¥_doz«PU‡2®À×e('¤Û¿˜-/Ýš`BYBA„ÓMã Ä~¶j6ÿ W@>A•qS¼áÑ7®0~ê_ÌÝYeT²¯~¯ý§§/O£ê;êéx<‹•;Ìûê÷ÚlØ{ë—é¸þ}óqCÆ©úê‡ç_$ß<óãÏór =Î"ôpúêÙ/‚÷ Iþkc¯‡ª·Ëqýù»™ë1&½]áºoHY—†TW7$à¹Ü7¤bxð¨GÍìƒûõ|vÉŠ IMͺðã7ÏžŸÜ’šõ/Ù!Ö…¶­dè-òÈ*Éýƒ HÚ›Ü7ltÛNX3Øí{×m³ukDóþoŽêœÏÀ9ÏÎ×­­>ú“îã{é>n¿‰Kò1GÈßÈ%¼|uªD¹;Ï_OXâ«‚&…ªÏ|ÕvZdU4‘fŸï-"8Å{£êbðåùG½F<áÁoxöÜ¢äÀ·Š9†1v¤9zÏ-*ÒzŠ~ÖÅG_‰¼üè+‘—ßKõñ½TßKýñ½ÔßKóñ½4ßËÇÄüã bþñ1ÿH‚X| A<Œt1ºo=†p]†nCƒ7î÷ý»ÿýïýK·%é?Žè_#õàŸæÈ·½CÉw³ùë«%””uQÿ]nÍ¿‡ƒô‘ç#sÿùÇ9L“÷Øq³> û„‘¹÷‹i©J}6¿œo§‹äÔ­«›,3¾LÝ-»aŠTü÷éŠydŽ]דÄÔ¤l aЍæ¹²Ì:®~:aq¨_-C’èùæœ]Û›ùòn“¸Ý[n¼Žä8)ÿ˜4d‡MŸ¡êe-m¾a9óÝ.OÈÂêØÁÇÈõ÷ËWº™W¸ÏÖÓ‹m šKŽK)ÉÒeÅ*½>ò[ Šž¾xôô©ÔÀöŒ• r¿Cx¶2)ÙìK‘þî[ªÜJd±sì¹kÆ-XV¹j)ªºÿÂÓ/ ¬m庨Hêñkw7 ²×¹¯²?ö¿tÿÎë k´æ2§79zî3Ã}ú¢sni˜tëñ«ÿöÊ ¾žøäzTï¹)fp~üê…¬kfÉ,1š4y'ž¿¾Ú:úº½^ÝÜ®ÝZð¼¡z™Eü!3¡XH¢UÛ`Ù&, mwX¤fÐöüfάorÊ:ʬ‘ki¶îØúõÝëc·ú!‘4›møL•ÈWå.àí\3«³I·cÐî§‘†C.;m4ªŠ‹ä67Cý²{€Eæh¤ðûÒ'ì:lc[,G×èÈÿÍÑûùÖHH=a‘_“Ö=NrÄ~énGò¥ 9CòÁ)OXÑ«Y±<—çb´\.NûǤÓõ©…à”šrŽÝu99KíîåbúÛ™ãöÜ^u!ö‡R&¤ÑÄ%yò—DFÜPËáFüå+¿Y”jà ÷ 0]Ÿ˜ ÕèjÂ_ü´³4Ï$GÜ—ß|ù½›n5á?CŽ@XûÑ“Ùúz¶˜ýöè)rù'Å„¿G-5™ô†¼·Éóå¹´fÝ©ÔÙŸÌ•â¹ãŒ!Q )Ä‘Í9š{6]ºÝhCštU‚KÉé%²í‰»_¸y•ÇÓEàËùz*žÖcž¬˜°8ôQ§è£ØÑ‡dv90)4ˆ’t¡yÓ»‹ca>pâÚÉ©Î]XlÀ×µâ)àÀ%c¿«7y×ÓûÕ,ý~!Q4.ÖbëĹ£läÎøÇÛÖóh}}’×™ã'!­æ!ÏKÖ4 9ß§Åùfv äÀþšÆ­È´yLëÊÂÄÚÁUn_»åpm/y Ýõµ‡wÂâ lw›–ÁÌúôÑÓ»³™²yÝ2€ŒE’Ú:I Äø!ŽF ]3ÛÓ§ßüÔi¦ü|L”:LNrOŸ Ûå1iêê`©nPá1þ#îO^DdG¥vƒF$"¤÷æ‰@—fàÿrŠ{„žºØ„à†–w[ýá{0Í $)Eܰ"Ïæ7§ßñÍó§áhJ+ðú€úôÙ£gIK}BÒ±Ôyæ–#ùxæÜü‘[$PxtSF¨tÖ é˜]3ßè¶kfmÀ‡“4““×È"·¦<ÃH <ýêùWRìÓÙ£„ÏD-ã°s†úô+“0tŒÚ‚žÎ£yõ4ûâôiþÅO_µÂôôŒ-áú\3N˜¾Þ&NÞ}-Ï»ÏêŽæ~Q쾹ε—eÒ`«ÀNåÚ ÔÊuä³àÆ•MÇ}ú…Süåùw8tµRœ(>Ç-Eº{×"s_Ï—³su2I^Nqáuží˜\X]póÁ„qÀà ²ÁºÊÞ3ÓÙV˺Ší n HÙŸþà¨ÍÕìõõæîæf&ìšuw‡À\lü“oôh± çÁDHÇ% fÑDªm)+á4ÿe5w8uƒš­’Žg6–(J9@?:míTÆ=h £’à_^ò ÿ‘ïEl ©IFÝYxú…\££ÁãäuÝð‰ýÖ?±j¯hùÔ<{¨§Æ Ã5£Õ޾]ÝÜÜ-ç×âA³œ9![›2¦DM­ŸÅ´”¹‰Þ¤¼iô6}T}-LÞ:Òšá.={üJHš^¹¸m^‹Ä:ÝüæNÌvíî÷Ռ϶I«ÒŒQÓ1øv¶ÑÄ/¾ÜØÜ¬Q·P·ð³¨C õ¸¿&†ö̰3õ7;¿{ë Š:~0:¬.¬èÑ2l.¦×ÛÕZŽKÎó‹‹]öôU¬Ÿ³ÇNÛtã,tÇ|›2o0JÑn)rIâM{6Ó{œ‹„6ZÊ#V)z­6~öŠ[ÙñÛÕj횉8“¥;7þ²È5íüœœÙ;ðÒ—¶@å„¿ EÚµêÿô@š¯ÂsXê 8.V—nøËÍÖ&+XñàU8'ʈ»e®_8.ê9TéuSž"õFÖRS ‹îëÕôv&Òfó@ÑËÅÇš" 1EdŸ`Ѝ»1EÔÿ@¦ˆ²O`í·O|üùîÛ&™LÛênND øu?ÿðOf Ó£/€y6И±–U¬ñÃô$ÒQ‚®Pt¸&[_ qÜœQ­K…J¤Æ@M˜I´­ÛÙål¡:š@WJèhñ–¼˜n¬¹™ü®Ýõ4ù&æÒPŸòͳ·s*ú ß°Aè’e²¾Á[ŠËÕ æÃ&«eCQÐCë.âé$ÉBT®¸Ouoèogk³Å:„ªÉ„ "„o–üÀ'BŒAUYuº›0JQ{T‡ÍÍ;ôXnˆG§OPÜÞP輊@Þ ÿϰ›/^zá Úìº!D”kh6ƒ~·ðŸ\”T4üye*jÒUU­æññkr:Ö¡yFÉ»)o‡vžO7 Ë6JOùÚ4L#dPÏi5Ó¥"ɨ[¸°(mtÛ~Ú¹[žãü¬7·0+ÏÖ7¶šp T#Z…m//\Ç?ÂÅRøJ•E£ ¼,¹Ä\ÎQPë¯x‹5ƒÍ‰ŽÒ§p]?¦6)ï¢æ¨a‡ŠÓ7§W»êë7;7¸Öq˜úlpÞ®¹?Ú(eC e¨Z3fAG˜†1uUÒÉ5ˆ¸zñiÝ9ízº-+ˆƒ(Æ© šo·óÙÅLMM± (å&g2ÔÜNm·ÒÐu¬ÇŠ%0úSP*0™l&ynñu©[t‘l+zqì¯w7‹9DáÐbt>\ƒX»xl]¬A±TŠçÜ_b¶Dªého³ d Ø?ܾžÞÝn¡\ÌæXœÙ2fND-ìt±ÚªR¼ˆýŽK½dÞ©>¨í›¸šÐß½¥ÖI㦌v‡¦¼¦¾§©Æéƒ-ëTïÆl¾¼šÍUZ,æ­OSÁuÎçð»SÁA¿žw2êk'ô.¦Ë팢:¶)ö".iÇqÛôÝ“§2¯T šñ¢ -Ár¹ZÎ\{öÔ‘! „õ />Y>™¾¾~ –PͱŸa裊¹~”óÍ;›/Î…¾æy¤&«H9]¥ï~û·»9˜[ÌX•ˆ*ežÂ]qºÞ"•âìµ£›_¿åÚŸ?€MÎ= ¢ÄÿþtÈ:v·%èÎ)ÙÊHiJòŽ‘Ç„(ûV8éôÕ35‰”jÉÿ4:uÏa<“õ÷‹ùr6¶oÇ&ëŒlТ‹ÍΚž&;õà÷Pb;,7aÖÐ&‡CDëÝå\Aþ®YCˆäèåX›u¼<8HwggîHndòyß < ô¯8ýmùúj½ZÎ7&ZÒ@Õ÷¯ ž;‡­þeߨ[óðr–å¸ÉÍ[È¡óRKTÜ.óפüDß ¼ŸÔ œ*ÄŠZýúš¬Ãøà<Á(#{±Á$åMLñ–³Hž’ÛþPîq>–™ÇÁ¤ó-4Ò2ôl.qPð‚§=5¨-LÚ¸ #S³”™T;íÚ…•IÚÝ$·ëU"«€1UOG „U[~5]_ζ U œ¨ZAcDÐ<DÞr´º9ŽT2þšÇëʧXšwbæ|9÷žJ´zÄjŸ FøEÁ5tóh»z$.Õ›GŒê’m,ˇ°wåh•»õ¯H×g’?«r~nNºª@,"«}žŠhý¨uócËdž“>• IŽtƸãù±zû-y޳_sîh:ÃóUÇûRu 79ns ?-˜%}Óŵ¦Êƒ`á†^ˆ>÷åÓTM™:WÛ­rJ±G¯®Üzm’¯§WKѶµ‘Ö·ÀH×ÈÕ|1¿5%k·Ä 4 _Tny·‚<´v%î&pÕŒ3Ôy«×`·%߈üˆ’kÈhW´1’£©í«lÞÄ·¦rƒk ‚óÁÑ[SE:ÉÒÌîÖôÞ…ØC¬§—³õ|E‚Z›ˆvæÆ^¤n–#_¿ Ôß…Ö¨ ‡©xÁ™ˆq¨ÛIåàÊ~| %E^“ºż]m¶7€MíŠ_ƒfÞÍ®„îþ%ëÆ±Zò8Öójæø‚ÅåL•‘±»Ÿ|½Å›éz>u¬Ö#‰Ï ã€±[‹r#‚cú£é™î pLÏÞ$â0ŸÀaÞàX½t!^GÇVذ?Hië^Û»·´!ãV¼û»«[wH×§bCß¼¬¤‚ÛÍo¯¯VÓë»Í–êï%í'‹Å±h6'¬)¡ø]Á>îdÚ˜ƒgÔMX+tÇýÙÑÝÆw‡¥n{]á¡~tÂ5*Có±é3CelyÂk\ü˜ó¦_/ Ññ¡.<[Ð8¸|´=]¾-ÏEm§¤Šõ ô¥/ï ¤ÄñÀÈïzÝ"+°v€RýoÜj¹•ztCÛ”p¦ÙaNôïp£p·ÿ_Ч.Ró™øñëS3Öö,n^\¨ÎH¾_:vNÍf@y0UÓæ_ '¾‰\(M{Þ ¼aŠŒ÷>Õn¼3'ï}O5߯õ64@¨€Þ¤.ÈŠõü߇bý#ôçnâÅ?ˆþÜmØOCüÀCåÐþ´Zƒà'ôNúSdút‹}Nfó/ÄlR5€Ü¸™Í¡:šÍÏŒ¡©ÿÎw¢øs'|§?>[½NÜÓˆ¾þ—ÿÂΤÙÍäÂ$¯Öw³W¿ÝΤ¡¥“t“ëÙo@‘ûóâôÕ«‚ ÔÉÿžô~{¥ûÍÑä‹gì>ùnö6á¾°Ô|*@Ôÿoð±;+÷~l(Ö»?žÝÿqYßóqå?¶ˆZ÷¹ yvχõôž¥ÇüìõŽ›ú½îîÑñ‹ïjèñ¿º­¾ƒ—çéÝííb>;NŽ“´_oœøüÓ|YTÏp*ýû_þKüÕwîdö¾áyøøp½ á ߟ-æÿv7‹ÊN»9[->̈ú B”^ï»øýù÷îVþ¿þËÿ£–é,°mjpegtools-2.1.0/mplex/stream_params.hpp0000644000175000017500000000652711574675627020743 0ustar glowwormglowworm/* * streamparams.hpp: User specifiable parameter classes for various types of stream * * The class constructors etc are defined so that it is impossible to build * objects with illegal combinations of constructors. * * Copyright (C) 2002 Andrew Stevens * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __STREAM_PARAMS_HH__ #define __STREAM_PARAMS_HH__ #include class LpcmParams { public: static LpcmParams *Checked( unsigned int samples, unsigned int chans, unsigned int bits ); static LpcmParams *Default( unsigned int opt_mux_format ); inline unsigned int SamplesPerSec() { return samples_per_sec; } inline unsigned int Channels() { return channels; } inline unsigned int BitsPerSample() { return bits_per_sample; } private: LpcmParams(unsigned int samples, unsigned int chans, unsigned int bits); unsigned int samples_per_sec; unsigned int channels; unsigned int bits_per_sample; }; class VideoParams { public: static VideoParams *Checked(unsigned int bufsiz); static VideoParams *Default(unsigned int mux_format); bool Force(unsigned int mux_format); inline unsigned int DecodeBufferSize() { return decode_buffer_size; } private: VideoParams(unsigned int bufsiz); unsigned int decode_buffer_size; }; class SubtitleStreamParams { public: static SubtitleStreamParams *Checked(const int64_t stream_offset,int8_t stream_id){ return new SubtitleStreamParams (stream_offset,stream_id);} ; static SubtitleStreamParams *Default(unsigned int mux_format) { return Checked(0,-1);}; bool Force(unsigned int mux_format); inline int64_t Offset() { return _stream_offset; } inline int8_t StreamId() { return _stream_id; } private: SubtitleStreamParams(const int64_t stream_offset, int8_t stream_id) {_stream_offset = stream_offset; _stream_id = stream_id;}; int64_t _stream_offset; int8_t _stream_id; }; // // Class of sequence of frame intervals. // class FrameIntervals { public: virtual ~FrameIntervals() {} virtual int NextFrameInterval() = 0; }; class ConstantFrameIntervals : public FrameIntervals { public: ConstantFrameIntervals( int _frame_interval ) : frame_interval( _frame_interval ) { } int NextFrameInterval() { return frame_interval; }; private: int frame_interval; }; class StillsParams : public VideoParams { public: StillsParams( VideoParams *parms, FrameIntervals *ints ) : VideoParams(*parms), intervals(ints) {} inline FrameIntervals *Intervals() { return intervals; } private: FrameIntervals *intervals; }; #endif /* * Local variables: * c-file-style: "gnu" * tab-width: 8 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/padstrm.cpp0000644000175000017500000000272611011315330017507 0ustar glowwormglowworm /* * padstrm.cc: Padding stream pseudo-input streams * * Copyright (C) 2001 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "padstrm.hpp" // // Generator for padding packets in a padding stream... // unsigned int PaddingStream::ReadPacketPayload(uint8_t *dst, unsigned int to_read) { memset( dst, STUFFING_BYTE, to_read ); return to_read; } unsigned int VCDAPadStream::ReadPacketPayload(uint8_t *dst, unsigned int to_read) { memset( dst, STUFFING_BYTE, to_read ); return to_read; } unsigned int DVDPriv2Stream::ReadPacketPayload(uint8_t *dst, unsigned int to_read) { memset( dst, 0, to_read ); return to_read; } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/Makefile.am0000644000175000017500000000312012052075212017362 0ustar glowwormglowworm# Process this file with Automake to produce Makefile.in EXTRA_DIST = \ README \ INSTRUCT \ mpeg_systems_paper_0.99.ps.gz \ Doxyfile \ TODO MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I $(top_srcdir) -I $(top_srcdir)/utils bin_PROGRAMS = mplex lib_LTLIBRARIES = libmplex2.la libmplex2_la_SOURCES = \ ac3strm_in.cpp \ audiostrm_out.cpp \ bits.cpp \ decodebufmodel.cpp \ dtsstrm_in.cpp \ inputstrm.cpp \ interact.cpp \ lpcmstrm_in.cpp \ mpastrm_in.cpp \ multiplexor.cpp \ padstrm.cpp \ stillsstream.cpp \ stream_params.cpp \ systems.cpp \ videostrm_in.cpp \ videostrm_out.cpp \ subpstream.cpp libmplex_includedir = $(pkgincludedir)/mplex libmplex_include_HEADERS = \ audiostrm.hpp \ aunit.hpp \ aunitbuffer.hpp \ bits.hpp \ decodebufmodel.hpp \ inputstrm.hpp \ interact.hpp \ mplexconsts.hpp \ multiplexor.hpp \ outputstrm.hpp \ padstrm.hpp \ stillsstream.hpp \ stream_params.hpp \ systems.hpp \ videostrm.hpp libmplex2_la_LDFLAGS = \ $(LT_STATIC) \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -release $(LT_RELEASE) $(EXTRA_LDFLAGS) libmplex2_la_LIBADD = \ $(top_builddir)/utils/libmjpegutils.la # Need to do this because of the way utils/altivec/* was done - it makes a # reference to a function (next_larger_quant) in mpeg2enc's library. OSX # doesn't care but Fedora4/PPC's linker gives an undefined symbol error if HAVE_ALTIVEC libmplex2_la_LIBADD += $(top_builddir)/mpeg2enc/libmpeg2encpp.la endif libmplex2_la_CXXFLAGS = mplex_SOURCES = main.cpp mplex_DEPENDENCIES = libmplex2.la mplex_LDADD = libmplex2.la @LIBGETOPT_LIB@ $(LIBM_LIBS) mjpegtools-2.1.0/mplex/videostrm_in.cpp0000644000175000017500000003517310346361606020562 0ustar glowwormglowworm/* * inptstrm.c: Members of video stream class related to raw stream * scanning and buffering. * * Copyright (C) 2001 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "videostrm.hpp" #include "interact.hpp" #include "multiplexor.hpp" static void marker_bit (IBitStream &bs, unsigned int what) { if (what != bs.Get1Bit()) { mjpeg_error ("Illegal MPEG stream at offset (bits) %lld: supposed marker bit not found.",bs.bitcount()); exit (1); } } void VideoStream::ScanFirstSeqHeader() { if (bs.GetBits( 32)==SEQUENCE_HEADER) { num_sequence++; horizontal_size = bs.GetBits( 12); vertical_size = bs.GetBits( 12); aspect_ratio = bs.GetBits( 4); picture_rate = bs.GetBits( 4); bit_rate = bs.GetBits( 18); marker_bit( bs, 1); vbv_buffer_size = bs.GetBits( 10); CSPF = bs.Get1Bit(); } else { mjpeg_error ("Invalid MPEG Video stream header."); exit (1); } if (mpeg_valid_framerate_code(picture_rate)) { frame_rate = Y4M_RATIO_DBL(mpeg_framerate(picture_rate)); } else { frame_rate = 25.0; } } void VideoStream::Init ( const int stream_num ) { mjpeg_debug( "SETTING video buffer to %d", parms->DecodeBufferSize() ); MuxStream::Init( VIDEO_STR_0+stream_num, 1, // Buffer scale parms->DecodeBufferSize()*1024, 0, // Zero stuffing muxinto.buffers_in_video, muxinto.always_buffers_in_video); mjpeg_info( "Scanning for header info: Video stream %02x (%s) ", VIDEO_STR_0+stream_num, bs.StreamName() ); SetBufSize( 4*1024*1024 ); ScanFirstSeqHeader(); /* Skip to the end of the 1st AU (*2nd* Picture start!) */ AU_hdr = SEQUENCE_HEADER; AU_pict_data = 0; AU_start = 0; fields_presented = 0; group_start_pic = 0; group_start_field = 0; OutputSeqhdrInfo(); } // // Set the Maximum STD buffer delay for this video stream. // By default we set 1 second but if we have specified a video // buffer that can hold more than 1.0 seconds demuxed data we // set the delay to the time to fill the buffer. // void VideoStream::SetMaxStdBufferDelay( unsigned int dmux_rate ) { double max_delay = CLOCKS; if( static_cast(BufferSize()) / dmux_rate > 1.0 ) max_delay *= static_cast(BufferSize()) / dmux_rate; // // To enforce a maximum STD buffer residency the // calculation is a bit tricky as when we decide to mux we may // (but not always) have some of the *previous* picture left to // mux in which case it is the timestamp of the next picture that counts. // For simplicity we simply reduce the limit by 1.5 frame intervals // and use the timestamp for the current picture. // if( frame_rate > 10.0 ) max_STD_buffer_delay = static_cast(max_delay * (frame_rate-1.5)/frame_rate); else max_STD_buffer_delay = static_cast(10.0 * max_delay / frame_rate); } // // Refill the AU unit buffer setting AU PTS DTS from the scanned // header information... // void VideoStream::FillAUbuffer(unsigned int frames_to_buffer) { if( eoscan ) return; last_buffered_AU += frames_to_buffer; mjpeg_debug( "Scanning %d video frames to start of frame %d", frames_to_buffer, last_buffered_AU ); // We set a limit of 2M to seek before we give up. // This is intentionally very high because some heavily // padded still frames may have a loooong gap before // a following sequence end marker. // IMPORTANT: SeekSync *must* come last otherwise a header // will be lost!!!! while(!bs.eos() && decoding_order < last_buffered_AU && !muxinto.AfterMaxPTS(access_unit.PTS) && bs.SeekSync( SYNCWORD_START, 24, 2*1024*1024) ) { syncword = (SYNCWORD_START<<8) + bs.GetBits( 8); if( AU_pict_data ) { /* Handle the header *ending* an AU... If we have the AU picture data an AU and have now reached a header marking the end of an AU fill in the the AU length and append it to the list of AU's and start a new AU. I.e. sequence and gop headers count as part of the AU of the corresponding picture */ stream_length = bs.bitcount()-static_cast(32); switch (syncword) { case SEQUENCE_HEADER : mjpeg_debug( "Seq hdr @ %lld", bs.bitcount() / 8-4 ); case GROUP_START : mjpeg_debug( "Group hdr @ %lld", bs.bitcount() / 8-4 ); case PICTURE_START : access_unit.start = AU_start; access_unit.length = static_cast(stream_length - AU_start)>>3; access_unit.end_seq = 0; avg_frames[access_unit.type-1]+=access_unit.length; mjpeg_debug( "AU %d %d %d @ %lld: DTS=%ud", decoding_order, access_unit.type, access_unit.length, bs.bitcount() / 8-4, static_cast(access_unit.DTS/300) ); aunits.Append( access_unit ); decoding_order++; AU_hdr = syncword; AU_start = stream_length; AU_pict_data = 0; break; case SEQUENCE_END: access_unit.length = ((stream_length - AU_start)>>3)+4; access_unit.end_seq = 1; aunits.Append( access_unit ); mjpeg_info( "Scanned to end AU %d", access_unit.dorder ); avg_frames[access_unit.type-1]+=access_unit.length; /* Do we have a sequence split in the video stream? */ if( !bs.eos() && bs.GetBits( 32) ==SEQUENCE_HEADER ) { stream_length = bs.bitcount()-static_cast(32); AU_start = stream_length; syncword = AU_hdr = SEQUENCE_HEADER; AU_pict_data = 0; if( !muxinto.split_at_seq_end ) mjpeg_warn("Sequence end marker found in video stream but single-segment splitting specified!" ); } else { if( !bs.eos() && muxinto.split_at_seq_end ) mjpeg_warn("No seq. header starting new sequence after seq. end!"); } decoding_order++; num_seq_end++; break; } } /* Handle the headers starting an AU... */ switch (syncword) { case SEQUENCE_HEADER: /* TODO: Really we should update the info here so we can handle streams where parameters change on-the-fly... */ num_sequence++; break; case GROUP_START: num_groups++; break; case PICTURE_START: /* We have reached AU's picture data... */ AU_pict_data = 1; mjpeg_debug( "Picture start @ %lld", bs.bitcount() / 8-4 ); prev_temp_ref = temporal_reference; temporal_reference = bs.GetBits( 10); access_unit.type = bs.GetBits( 3); /* Now scan forward a little for an MPEG-2 picture coding extension so we can get pulldown info (if present). We ignore the possibility MPEG-1's ghastly 'extra_information_picture' bytes. So the extension must come in under 9 bytes (4 for the sync-code itself 5 for the rest of the picture header) */ if( bs.SeekSync(EXT_START_CODE, 32, 9) && bs.GetBits(4) == CODING_EXT_ID) { /* Skip: 4 F-codes (4)... */ (void)bs.GetBits(16); /* Skip: DC Precision(2) */ (void)bs.GetBits(2); pict_struct = bs.GetBits(2); /* Skip: topfirst (1) frame pred dct (1), concealment_mv(1), q_scale_type (1), */ (void)bs.GetBits(4); /* Skip: intra_vlc_format(1), alternate_scan (1) */ (void)bs.GetBits(2); repeat_first_field = bs.Get1Bit(); pulldown_32 |= repeat_first_field; } else { repeat_first_field = 0; pict_struct = PIC_FRAME; } if( access_unit.type == IFRAME ) { double bits_persec = static_cast( stream_length - prev_offset) * 2.0 * frame_rate / static_cast(fields_presented - group_start_field); if( bits_persec > max_bits_persec ) { max_bits_persec = bits_persec; } prev_offset = stream_length; group_start_pic = decoding_order; group_start_field = fields_presented; } NextDTSPTS( ); access_unit.dorder = decoding_order; access_unit.porder = temporal_reference + group_start_pic; access_unit.seq_header = ( AU_hdr == SEQUENCE_HEADER); if ((access_unit.type>0) && (access_unit.type<5)) { num_frames[access_unit.type-1]++; } if ( decoding_order >= old_frames+1000 ) { mjpeg_debug("Got %d picture headers.", decoding_order); old_frames = decoding_order; } break; } } last_buffered_AU = decoding_order; num_pictures = decoding_order; eoscan = bs.eos() || muxinto.AfterMaxPTS(access_unit.PTS); } void VideoStream::Close() { unsigned int comp_bit_rate ; unsigned int peak_bit_rate ; stream_length = bs.bitcount() / 8; for( int i=0; i<4; i++) { avg_frames[i] /= num_frames[i] == 0 ? 1 : num_frames[i]; } /* Average and Peak bit rate in 50B/sec units... */ comp_bit_rate = static_cast( static_cast( stream_length / fields_presented * 2 ) * frame_rate + 25) / 50; peak_bit_rate = static_cast((max_bits_persec / 8 + 25) / 50); mjpeg_info ("VIDEO_STATISTICS: %02x", stream_id); mjpeg_info ("Video Stream length: %11llu bytes", stream_length); mjpeg_info ("Sequence headers: %8u",num_sequence); mjpeg_info ("Sequence ends : %8u",num_seq_end); mjpeg_info ("No. Pictures : %8u",num_pictures); mjpeg_info ("No. Groups : %8u",num_groups); mjpeg_info ("No. I Frames : %8u avg. size%6u bytes", num_frames[0], (uint32_t)avg_frames[0]); mjpeg_info ("No. P Frames : %8u avg. size%6u bytes", num_frames[1], (uint32_t)avg_frames[1]); mjpeg_info ("No. B Frames : %8u avg. size%6u bytes", num_frames[2], (uint32_t)avg_frames[2]); mjpeg_info("Average bit-rate : %8u bits/sec",comp_bit_rate*400); mjpeg_info("Peak bit-rate : %8u bits/sec",peak_bit_rate*400); } /************************************************************************* OutputSeqHdrInfo Display sequence header parameters *************************************************************************/ void VideoStream::OutputSeqhdrInfo () { const char *str; mjpeg_info("VIDEO STREAM: %02x", stream_id); mjpeg_info ("Frame width : %u",horizontal_size); mjpeg_info ("Frame height : %u",vertical_size); if (mpeg_valid_aspect_code(muxinto.mpeg, aspect_ratio)) str = mpeg_aspect_code_definition(muxinto.mpeg,aspect_ratio); else str = "forbidden"; mjpeg_info ("Aspect ratio : %s", str ); if (picture_rate == 0) mjpeg_info( "Picture rate : forbidden"); else if (mpeg_valid_framerate_code(picture_rate)) mjpeg_info( "Picture rate : %2.3f frames/sec", Y4M_RATIO_DBL(mpeg_framerate(picture_rate)) ); else mjpeg_info( "Picture rate : %x reserved",picture_rate); if (bit_rate == 0x3ffff) { bit_rate = 0; mjpeg_info( "Bit rate : variable"); } else if (bit_rate == 0) mjpeg_info( "Bit rate : forbidden"); else mjpeg_info( "Bit rate : %u bits/sec", bit_rate*400); mjpeg_info("Vbv buffer size : %u bytes",vbv_buffer_size*2048); mjpeg_info("CSPF : %u",CSPF); } // // Compute PTS DTS of current AU in the video sequence being // scanned. This is is the PTS/DTS calculation for normal video only. // It is virtual and over-ridden for non-standard streams (Stills // etc!). // int gopfields_32pd( int temporal_ref, bool repeat_first_field ) { int frames2field; int frames3field; // // Assume first presented frame of GOP has temporal ref 0 if( repeat_first_field ) { frames2field = (temporal_ref+1) / 2; frames3field = temporal_ref / 2; } else { frames2field = (temporal_ref) / 2; frames3field = (temporal_ref+1) / 2; } return frames2field*2 + frames3field*3; } /**************************************************** * * Work out DTS PTS stamps for the current AU. * Note: Current strategy assumes decoders model 'ideal' * timing with instantaneous decoding. * This makes sense it is what is assumed for B-frames anyway * (no seperate DTS). * ******************************************************/ void VideoStream::NextDTSPTS() { const int decode_delay = 0; int startup_skew = 2; int decode_fields, present_fields; if( pict_struct != PIC_FRAME ) { decode_fields = fields_presented; present_fields = temporal_reference*2 + group_start_field+decode_delay/2; if( temporal_reference == prev_temp_ref ) present_fields += 1; fields_presented += 1; } else if( pulldown_32 ) { present_fields = group_start_field + startup_skew + decode_delay + gopfields_32pd( temporal_reference, repeat_first_field ); if( decoding_order == 0 ) { // Special case... first IFRAME is not decoded during presentation // of previous ref frame but immediately at start decode_fields = 0; prev_ref_present = present_fields ; } else if( access_unit.type == IFRAME || access_unit.type == PFRAME ) { decode_fields = prev_ref_present-decode_delay; prev_ref_present = present_fields; } else { decode_fields = present_fields - decode_delay; } fields_presented += repeat_first_field ? 3 : 2; } else { decode_fields = decoding_order*2; present_fields = (temporal_reference + group_start_pic)*2 + startup_skew + decode_delay; fields_presented += 2; } access_unit.DTS = static_cast (decode_fields * (double)(CLOCKS/2) / frame_rate); access_unit.PTS = static_cast (present_fields * (double)(CLOCKS/2) / frame_rate); } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/padstrm.hpp0000644000175000017500000000312207622537137017533 0ustar glowwormglowworm /* * padstrm.hpp: Padding stream pseudo input-streamsin * * Copyright (C) 2001 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __PADSTRM_H__ #define __PADSTRM_H__ #include "inputstrm.hpp" class PaddingStream : public MuxStream { public: PaddingStream() { MuxStream::Init( PADDING_STR, 0, 0, 0, false,false ); } unsigned int ReadPacketPayload(uint8_t *dst, unsigned int to_read); }; class VCDAPadStream : public MuxStream { public: VCDAPadStream() { Init( PADDING_STR, 0, 0, 20, false, false ); } unsigned int ReadPacketPayload(uint8_t *dst, unsigned int to_read); }; class DVDPriv2Stream : public MuxStream { public: DVDPriv2Stream() { Init( PRIVATE_STR_2, 0, 0, 0, false, false ); } unsigned int ReadPacketPayload(uint8_t *dst, unsigned int to_read); }; #endif // __PADSTRM_H__ /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/audiostrm.hpp0000644000175000017500000001417511346706603020074 0ustar glowwormglowworm /* * audiostrm.hpp: Audio stream class sub-hierarchy for MPEG multiplexing * * Copyright (C) 2001 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __AUDIOSTRM_H__ #define __AUDIOSTRM_H__ #include "inputstrm.hpp" #include "stream_params.hpp" // TODO AudioStream is reall NonVideoStream as it is also a base for // SUBPStream (sub)classes class AudioStream : public ElementaryStream { public: AudioStream(IBitStream &ibs, Multiplexor &into ); virtual void Init(const int stream_num) = 0; virtual void Close() = 0; void OutputSector(); bool RunOutComplete(); virtual unsigned int NominalBitRate() = 0; unsigned int num_syncword; protected: virtual void FillAUbuffer(unsigned int frames_to_buffer) = 0; /* State variables for scanning source bit-stream */ AUnit access_unit; unsigned int header_skip; }; class MPAStream : public AudioStream { public: MPAStream(IBitStream &ibs, Multiplexor &into ); virtual void Init(const int stream_num); static bool Probe(IBitStream &bs); virtual void Close(); virtual unsigned int NominalBitRate(); private: void OutputHdrInfo(); unsigned int SizeFrame( int bit_rate, int padding_bit ); virtual void FillAUbuffer(unsigned int frames_to_buffer); /* Stream information for logging and parsing purposes */ unsigned int samples_per_second; unsigned int version_id ; unsigned int layer ; unsigned int protection ; unsigned int bit_rate_code; unsigned int frequency ; unsigned int mode ; unsigned int mode_extension ; unsigned int copyright ; unsigned int original_copy ; unsigned int emphasis ; /* State variables for scanning source bit-stream */ unsigned int framesize; unsigned int num_frames [2]; unsigned int size_frames[2]; }; class AC3Stream : public AudioStream { public: AC3Stream(IBitStream &ibs,Multiplexor &into ); virtual void Init(const int stream_num); static bool Probe(IBitStream &bs); virtual void Close(); virtual unsigned int NominalBitRate(); virtual unsigned int ReadPacketPayload(uint8_t *dst, unsigned int to_read); virtual unsigned int StreamHeaderSize() { return 4; } private: void OutputHdrInfo(); void DisplayAc3HeaderInfo(); virtual void FillAUbuffer(unsigned int frames_to_buffer); static const unsigned int default_buffer_size; /* State variables for scanning source bit-stream */ unsigned int framesize; unsigned int frequency; unsigned int samples_per_second; unsigned int bit_rate; unsigned int stream_num; unsigned int num_frames; }; class DTSStream : public AudioStream { public: DTSStream(IBitStream &ibs,Multiplexor &into ); virtual void Init(const int stream_num); static bool Probe(IBitStream &bs); virtual void Close(); virtual unsigned int NominalBitRate(); virtual unsigned int ReadPacketPayload(uint8_t *dst, unsigned int to_read); virtual unsigned int StreamHeaderSize() { return 4; } private: void OutputHdrInfo(); #ifdef DEBUG_DTS void DisplayDtsHeaderInfo(); #endif virtual void FillAUbuffer(unsigned int frames_to_buffer); static const unsigned int default_buffer_size; /* State variables for scanning source bit-stream */ unsigned int framesize; unsigned int samples_per_second; unsigned int bit_rate; unsigned int stream_num; unsigned int frequency ; unsigned int num_frames; }; class LPCMStream : public AudioStream { public: LPCMStream(IBitStream &ibs, LpcmParams *parms, Multiplexor &into ); virtual void Init(const int stream_num); static bool Probe(IBitStream &bs); virtual void Close(); virtual unsigned int NominalBitRate(); virtual unsigned int ReadPacketPayload(uint8_t *dst, unsigned int to_read); virtual unsigned int StreamHeaderSize() { return 7; } private: void OutputHdrInfo(); virtual void FillAUbuffer(unsigned int frames_to_buffer); static const unsigned int default_buffer_size; static const unsigned int ticks_per_frame_90kHz; unsigned int num_frames; /* State variables for scanning source bit-stream */ unsigned int stream_num; unsigned int samples_per_second; unsigned int channels; unsigned int bits_per_sample; unsigned int whole_unit; unsigned int bytes_per_frame; unsigned int frame_index; unsigned int dynamic_range_code; LpcmParams *parms; }; class SUBPStream : public AudioStream { public: SUBPStream(IBitStream &ibs,SubtitleStreamParams* params,Multiplexor &into ); virtual void Init(const int stream_num); virtual void Close(); static bool Probe(IBitStream &bs ); // TODO: rough and ready measure... virtual unsigned int NominalBitRate() {return 50*1024;} virtual unsigned int ReadPacketPayload(uint8_t *dst, unsigned int to_read); virtual unsigned int StreamHeaderSize() { return 1; } private: virtual void FillAUbuffer(unsigned int frames_to_buffer); bool ParseAUBitwise(); static const unsigned int default_buffer_size; /* State variables for scanning source bit-stream */ unsigned int framesize; unsigned int samples_per_second; unsigned int bit_rate; unsigned int stream_num; unsigned int num_frames; int64_t initial_offset; // DTS of first Subp. SubtitleStreamParams* parms; int8_t sub_stream_id; // substream_id }; #endif // __AUDIOSTRM_H__ /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/stillsstream.cpp0000644000175000017500000001276010025375117020577 0ustar glowwormglowworm /* * stillsstreams.c: Class for elemenary still video streams * Most functionality is inherited from VideoStream * * Copyright (C) 2001 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "stillsstream.hpp" #include "interact.hpp" #include "multiplexor.hpp" void StillsStream::Init ( ) { int stream_id = -1; int buffer_size = -1; SetBufSize( 4*1024*1024 ); ScanFirstSeqHeader(); mjpeg_debug( "Stills: Video buffer suggestion ignored!" ); switch( muxinto.mux_format ) { case MPEG_FORMAT_VCD_STILL : if( horizontal_size > 352 ) { stream_id = VIDEO_STR_0+2 ; buffer_size = vbv_buffer_size*2048; mjpeg_info( "Stills Stream %02x: high-resolution VCD stills %d KB each", stream_id, buffer_size ); if( buffer_size < 46*1024 ) mjpeg_error_exit1( "I Can't multiplex high-res stills smaller than normal res stills - sorry!"); } else { stream_id = VIDEO_STR_0+1 ; buffer_size = 46*1024; mjpeg_info( "Stills Stream %02x: normal VCD stills", stream_id ); } break; case MPEG_FORMAT_SVCD_STILL : if( horizontal_size > 480 ) { stream_id = VIDEO_STR_0+1; buffer_size = 230*1024; mjpeg_info( "Stills Stream %02x: high-resolution SVCD stills.", stream_id ); } else { stream_id = VIDEO_STR_0+1 ; buffer_size = 230*1024; mjpeg_info( "Stills Stream %02x: normal-resolution SVCD stills.", stream_id ); } break; default: mjpeg_error_exit1( "Only SVCD and VCD Still currently supported"); } MuxStream::Init( stream_id, 1, // Buffer scale buffer_size, 0, // Zero stuffing muxinto.buffers_in_video, muxinto.always_buffers_in_video); /* Skip to the end of the 1st AU (*2nd* Picture start!) */ AU_hdr = SEQUENCE_HEADER; AU_pict_data = 0; AU_start = 0; OutputSeqhdrInfo(); } /* * Compute DTS / PTS for a VCD/SVCD Stills sequence * TODO: Very crude. Simply assumes each still stays for the specified * frame interval and that enough run-in delay is present for the first * frame to be loaded. * */ void StillsStream::NextDTSPTS( ) { StillsParams *sparms = static_cast(parms); clockticks interval = static_cast (sparms->Intervals()->NextFrameInterval() * CLOCKS / frame_rate); clockticks time_for_xfer; muxinto.ByteposTimecode( BufferSize(), time_for_xfer ); access_unit.DTS = current_PTS + time_for_xfer; // This frame decoded just after // Predecessor completed. access_unit.PTS = current_PTS + time_for_xfer + interval; current_PTS = access_unit.PTS; current_DTS = access_unit.DTS; fields_presented += 2; } /* * VCD mixed stills segment items have the constraint that both stills * streams must end together. To do this each stream has to know * about its "sibling". * */ void VCDStillsStream::SetSibling( VCDStillsStream *_sibling ) { assert( _sibling != 0 ); sibling = _sibling; if( sibling->stream_id == stream_id ) { mjpeg_error_exit1("VCD mixed stills stream cannot contain two streams of the same type!"); } } /* * Check if we've reached the last sector of the last AU. Note: that * we know no PTS/DTS time-stamps will be needed because no new AU * will appear in the last sector. WARNING: We assume a still won't * fit into a single secotr. * */ bool VCDStillsStream::LastSectorLastAU() { return ( Lookahead() == 0 && au_unsent <= muxinto.PacketPayload( *this, buffers_in_header, false, false ) ); } /* * The requirement that VCD mixed stills segment items constituent streams * end together means we can't mux the last sector of the last AU of * such streams until its sibling has already completed muxing or is * also ready to mux the last sector of its last AU. * * NOTE: Will not work right if sector_align_iframe_AUs not set as this * will allow multiple AU's in a sector. * */ bool VCDStillsStream::MuxPossible(clockticks currentSCR) { if( bufmodel.Size() < au_unsent ) { mjpeg_error_exit1( "Illegal VCD still: larger than maximum permitted by its buffering parameters!"); } if (RunOutComplete() || bufmodel.Space() < au_unsent) { return false; } if( LastSectorLastAU() ) { if( sibling != 0 ) { if( !stream_mismatch_warned && sibling->NextAUType() != NOFRAME ) { mjpeg_warn( "One VCD stills stream runs significantly longer than the other!"); mjpeg_warn( "Simultaneous stream ending recommended by standard not possible" ); return true; } return sibling->MuxCompleted() || sibling->LastSectorLastAU(); } else return true; } else return true; } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/interact.cpp0000644000175000017500000001461312052075212017654 0ustar glowwormglowworm /* * interact.cc: Simple command-line front-end * * Copyright (C) 2001 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include "interact.hpp" #include "videostrm.hpp" #include "audiostrm.hpp" #include "mplexconsts.hpp" #include "aunit.hpp" static const char *KindNames[] = { "MPEG audio", "AC3 audio", "LPCM audio", "DTS audio", "MPEG video", "MPEG Subtitle", "Z Alpha channel" }; const char *JobStream::NameOfKind() { return KindNames[kind]; } Workarounds::Workarounds() { } MultiplexJob::MultiplexJob() { verbose = 1; data_rate = 0; /* 3486 = 174300B/sec would be right for VCD */ video_offset = 0; audio_offset = 0; sector_size = 2048; VBR = false; CBR = false; mpeg = 1; mux_format = MPEG_FORMAT_MPEG1; multifile_segment = false; always_system_headers = false; packets_per_pack = 1; max_timeouts = 10; max_PTS = 0; max_segment_size = 0; // MB, default is unlimited (suitable for DVD) outfile_pattern = 0; packets_per_pack = 1; run_in_frames = 0; // Select default run-in... audio_tracks = 0; video_tracks = 0; subtitle_tracks = 0; lpcm_tracks = 0; vdr_index_pathname = 0; outfile_pattern = 0; } MultiplexJob::~MultiplexJob() { std::vector::iterator i; for( i = streams.begin(); i < streams.end(); ++i ) delete *i; } unsigned int MultiplexJob::NumberOfTracks( StreamKind kind ) { unsigned int count = 0; std::vector::iterator i; for( i = streams.begin(); i < streams.end(); ++i ) if( (*i)->kind == kind ) ++count; return count; } void MultiplexJob::GetInputStreams( vector &res, StreamKind kind ) { res.erase( res.begin(), res.end() ); std::vector::iterator i; for( i = streams.begin(); i < streams.end(); ++i ) if( (*i)->kind == kind ) res.push_back( *i ); } void MultiplexJob::SetupInputStreams( std::vector< IBitStream *> &inputs ) { IBitStream *bs; IBitStreamUndo undo; unsigned int i; bool bad_file = false; for( i = 0; i < inputs.size(); ++i ) { bs = inputs[i]; // Remember the streams initial state... bs->PrepareUndo( undo ); if( LPCMStream::Probe( *bs ) ) { mjpeg_info ("File %s looks like an LPCM Audio stream.", bs->StreamName()); bs->UndoChanges( undo ); streams.push_back( new JobStream( bs, LPCM_AUDIO) ); ++audio_tracks; ++lpcm_tracks; continue; } bs->UndoChanges( undo ); if( MPAStream::Probe( *bs ) ) { mjpeg_info ("File %s looks like an MPEG Audio stream.", bs->StreamName() ); bs->UndoChanges( undo ); streams.push_back( new JobStream( bs, MPEG_AUDIO) ); ++audio_tracks; continue; } bs->UndoChanges( undo ); if( AC3Stream::Probe( *bs ) ) { mjpeg_info ("File %s looks like an AC3 Audio stream.", bs->StreamName()); bs->UndoChanges( undo ); streams.push_back( new JobStream( bs, AC3_AUDIO) ); ++audio_tracks; continue; } bs->UndoChanges( undo ); if( DTSStream::Probe( *bs ) ) { mjpeg_info ("File %s looks like a dts Audio stream.", bs->StreamName()); bs->UndoChanges( undo); streams.push_back( new JobStream( bs, DTS_AUDIO) ); ++audio_tracks; continue; } bs->UndoChanges( undo ); if( VideoStream::Probe( *bs ) ) { mjpeg_info ("File %s looks like an MPEG Video stream.", bs->StreamName()); bs->UndoChanges( undo ); streams.push_back( new JobStream( bs, MPEG_VIDEO) ); ++video_tracks; continue; } bs->UndoChanges( undo ); if( SUBPStream::Probe( *bs ) ) { mjpeg_info ("File %s looks like an Subpicture stream.", bs->StreamName()); bs->UndoChanges( undo ); streams.push_back( new JobStream( bs, SUBP_STREAM) ); ++subtitle_tracks; continue; } bad_file = true; mjpeg_error ("File %s unrecogniseable!", bs->StreamName()); delete bs; } if( bad_file ) { mjpeg_error_exit1( "Unrecogniseable file(s)... exiting."); } // // Where no parameters for streams have been specified // simply set the default values (these will depend on the format // we're muxing of course...) // for( i = video_param.size(); i < video_tracks; ++i ) { video_param.push_back(VideoParams::Default( mux_format )); } for( i = lpcm_param.size(); i < lpcm_tracks; ++i ) { lpcm_param.push_back(LpcmParams::Default(mux_format)); } for( i = subtitle_params.size(); i < subtitle_tracks; ++i ) { subtitle_params.push_back(SubtitleStreamParams::Default(mux_format)); } // // Set standard values if the selected profile implies this... // for( i = 0; i Force(mux_format) ) { mjpeg_info( "Video stream %d: profile %d selected - ignoring non-standard options!", i, mux_format ); } } mjpeg_info( "Found %d audio streams, %d video streams and %d subtitle streams", audio_tracks, video_tracks, subtitle_tracks ); } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/Doxyfile0000644000175000017500000011324307537641213017060 0ustar glowwormglowworm# Doxyfile 1.2.17 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # General configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = mplex # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = 1.6.0 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = doc # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, # Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en # (Japanese with english messages), Korean, Norwegian, Polish, Portuguese, # Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish and Ukrainian. OUTPUT_LANGUAGE = English # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these class will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited # members of a class in the documentation of that class as if those members were # ordinary class members. Constructors, destructors and assignment operators of # the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. It is allowed to use relative paths in the argument list. STRIP_FROM_PATH = # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = YES # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower case letters. If set to YES upper case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # users are adviced to set this option to NO. CASE_SENSE_NAMES = YES # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explict @brief command for a brief description. JAVADOC_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # reimplements. INHERIT_DOCS = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consist of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. # For instance some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources # only. Doxygen will then generate output that is more tailored for Java. # For instance namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. EXCLUDE_PATTERNS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. INPUT_FILTER = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse. FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output dir. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non empty doxygen will try to run # the html help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the Html help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript and frames is required (for instance Mozilla, Netscape 4.0+, # or Internet explorer 4.0+). Note that for large projects the tree generation # can take a very long time. In such cases it is better to disable this feature. # Windows users are probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimised for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assigments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_XML = NO #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse the # parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::addtions related to external references #--------------------------------------------------------------------------- # The TAGFILES tag can be used to specify one or more tagfiles. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or # super classes. Setting the tag to NO turns the diagrams off. Note that this # option is superceded by the HAVE_DOT option below. This is only a fallback. It is # recommended to install and use dot, since it yield more powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermedate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::addtions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO # The CGI_NAME tag should be the name of the CGI script that # starts the search engine (doxysearch) with the correct parameters. # A script with this name will be generated by doxygen. CGI_NAME = search.cgi # The CGI_URL tag should be the absolute URL to the directory where the # cgi binaries are located. See the documentation of your http daemon for # details. CGI_URL = # The DOC_URL tag should be the absolute URL to the directory where the # documentation is located. If left blank the absolute path to the # documentation, with file:// prepended to it, will be used. DOC_URL = # The DOC_ABSPATH tag should be the absolute path to the directory where the # documentation is located. If left blank the directory on the local machine # will be used. DOC_ABSPATH = # The BIN_ABSPATH tag must point to the directory where the doxysearch binary # is installed. BIN_ABSPATH = /usr/local/bin/ # The EXT_DOC_PATHS tag can be used to specify one or more paths to # documentation generated for other projects. This allows doxysearch to search # the documentation for these projects as well. EXT_DOC_PATHS = mjpegtools-2.1.0/mplex/mpastrm_in.cpp0000644000175000017500000002255110427364460020226 0ustar glowwormglowworm/* * audiostrm_in.c: MPEG Audio strem class members handling scanning * and buffering raw input stream. * * Copyright (C) 2001 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "audiostrm.hpp" #include "interact.hpp" #include "multiplexor.hpp" static const char *mpa_audio_version[4] = { "2.5", "2.0", "reserved", "1.0" }; static const unsigned int mpa_bitrates_kbps [4][3][16] = { { /* MPEG audio V2.5 */ {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0}, {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0}, {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0} }, { /*RESERVED*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }, { /* MPEG audio V2 */ {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0}, {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0}, {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0} }, { /* MPEG audio V1 */ {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0}, {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0}, {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0} } }; static const int mpa_freq_table [4][4] = { /* MPEG audio V2.5 */ {11025,12000,8000,0}, /* RESERVED */ { 0, 0, 0, 0 }, /* MPEG audio V2 */ {22050,24000, 16000,0}, /* MPEG audio V1 */ {44100, 48000, 32000, 0} }; static const char mpa_stereo_mode [4][15] = { "stereo", "joint stereo", "dual channel", "single channel" }; static const char mpa_copyright_status [2][20] = { "no copyright","copyright protected" }; static const char mpa_original_bit [2][10] = { "copy","original" }; static const char mpa_emphasis_mode [4][20] = { "none", "50/15 microseconds", "reserved", "CCITT J.17" }; static const unsigned int mpa_slots [4] = {12, 144, 144, 0}; static const unsigned int mpa_samples [4] = {384, 1152, 1152, 0}; MPAStream::MPAStream(IBitStream &ibs, Multiplexor &into) : AudioStream( ibs, into ) { for( int i = 0; i <2 ; ++i ) num_frames[i] = size_frames[i] = 0; } bool MPAStream::Probe(IBitStream &bs ) { return bs.GetBits(11) == AUDIO_SYNCWORD; } /************************************************************************* * * Reads initial stream parameters and displays feedback banner to users * *************************************************************************/ void MPAStream::Init ( const int stream_num ) { int padding_bit; MuxStream::Init( AUDIO_STR_0 + stream_num, 0, // Buffer scale muxinto.audio_buffer_size, muxinto.vcd_zero_stuffing, muxinto.buffers_in_audio, muxinto.always_buffers_in_audio ); mjpeg_info ("Scanning for header info: Audio stream %02x (%s)", AUDIO_STR_0 + stream_num, bs.StreamName() ); /* A.Stevens 2000 - update to be compatible up to MPEG2.5 */ AU_start = bs.bitcount(); if (bs.GetBits(11)==AUDIO_SYNCWORD) { num_syncword++; version_id = bs.GetBits( 2); layer = 3-bs.GetBits( 2); /* 0..2 not 1..3!! */ protection = bs.Get1Bit(); bit_rate_code = bs.GetBits( 4); frequency = bs.GetBits( 2); padding_bit = bs.Get1Bit(); bs.Get1Bit(); mode = bs.GetBits( 2); mode_extension = bs.GetBits( 2); copyright = bs.Get1Bit(); original_copy = bs.Get1Bit (); emphasis = bs.GetBits( 2); framesize = mpa_bitrates_kbps[version_id][layer][bit_rate_code] * mpa_slots[layer] *1000 / mpa_freq_table[version_id][frequency]; size_frames[0] = framesize * ( layer == 0 ? 4 : 1); size_frames[1] = (framesize+1) * ( layer == 0 ? 4 : 1); num_frames[padding_bit]++; access_unit.start = AU_start; access_unit.length = size_frames[padding_bit]; samples_per_second = mpa_freq_table[version_id][frequency]; if (!samples_per_second) { mjpeg_error ( "Invalid frequency in MPEG Audio stream header."); exit(1); } /* Presentation time-stamping */ access_unit.PTS = static_cast(decoding_order) * static_cast(mpa_samples [layer]) * static_cast(CLOCKS) / samples_per_second; access_unit.DTS = access_unit.PTS; access_unit.dorder = decoding_order; ++decoding_order; aunits.Append( access_unit ); } else { mjpeg_error ( "Invalid MPEG Audio stream header."); exit (1); } OutputHdrInfo(); } unsigned int MPAStream::NominalBitRate() { return mpa_bitrates_kbps[version_id][layer][bit_rate_code]*1024; } unsigned int MPAStream::SizeFrame( int rate_code, int padding ) { return ( mpa_bitrates_kbps[version_id][layer][rate_code] * mpa_slots [layer] *1000 / mpa_freq_table[version_id][frequency] + padding ) * ( layer == 0 ? 4 : 1); } void MPAStream::FillAUbuffer(unsigned int frames_to_buffer ) { unsigned int padding_bit; last_buffered_AU += frames_to_buffer; if( eoscan ) return; mjpeg_debug( "Scanning %d MPA frames to frame %d", frames_to_buffer, last_buffered_AU ); while( !bs.eos() && decoding_order < last_buffered_AU && !muxinto.AfterMaxPTS(access_unit.PTS) ) { int skip=access_unit.length-4; bs.SeekFwdBits( skip ); prev_offset = AU_start; AU_start = bs.bitcount(); if( AU_start - prev_offset != access_unit.length*8 ) { mjpeg_warn("Discarding incomplete final frame MPEG audio stream %02x!", stream_id ); aunits.DropLast(); --decoding_order; break; } /* Check we have reached the end of have another catenated stream to process before finishing ... */ if ( (syncword = bs.GetBits( 11))!=AUDIO_SYNCWORD ) { // // Handle a broken last frame... if( !bs.eos() ) { mjpeg_warn( "Data follows end of last recogniseable MPEG audio frame - bad stream?"); eoscan = true; return; } break; } // Skip version_id:2, layer:2, protection:1 (void) bs.GetBits( 5); int rate_code = bs.GetBits( 4); // Skip frequency (void) bs.GetBits( 2); padding_bit=bs.Get1Bit(); access_unit.start = AU_start; access_unit.length = SizeFrame( rate_code, padding_bit ); access_unit.PTS = static_cast(decoding_order) * static_cast(mpa_samples[layer]) * static_cast(CLOCKS) / samples_per_second; access_unit.DTS = access_unit.PTS; access_unit.dorder = decoding_order; decoding_order++; aunits.Append( access_unit ); num_frames[padding_bit]++; bs.GetBits( 9); num_syncword++; if (num_syncword >= old_frames+10 ) { mjpeg_debug ("Got %d frame headers.", num_syncword); old_frames=num_syncword; } } last_buffered_AU = decoding_order; eoscan = bs.eos() || muxinto.AfterMaxPTS(access_unit.PTS); } void MPAStream::Close() { stream_length = AU_start >> 3; mjpeg_info ("AUDIO_STATISTICS: %02x", stream_id); mjpeg_info ("Audio stream length %lld bytes.", stream_length); mjpeg_info ("Syncwords : %8u",num_syncword); mjpeg_info ("Frames : %8u padded", num_frames[0]); mjpeg_info ("Frames : %8u unpadded", num_frames[1]); } /************************************************************************* OutputAudioInfo gibt gesammelte Informationen zu den Audio Access Units aus. Prints information on audio access units *************************************************************************/ void MPAStream::OutputHdrInfo () { unsigned int bitrate; bitrate = mpa_bitrates_kbps[version_id][layer][bit_rate_code]; mjpeg_info("MPEG AUDIO STREAM: %02x", stream_id); mjpeg_info("Audio version : %s", mpa_audio_version[version_id]); mjpeg_info("Layer : %8u",layer+1); if (protection == 0) mjpeg_info ("CRC checksums : yes"); else mjpeg_info ("CRC checksums : no"); if (bit_rate_code == 0) mjpeg_info ("Bit rate : free"); else if (bit_rate_code == 0xf) mjpeg_info ("Bit rate : reserved"); else mjpeg_info ("Bit rate : %8u bytes/sec (%3u kbit/sec)", bitrate*128, bitrate); if (frequency == 3) mjpeg_info ("Frequency : reserved"); else mjpeg_info ("Frequency : %d Hz", mpa_freq_table[version_id][frequency]); mjpeg_info ("Mode : %8u %s", mode,mpa_stereo_mode[mode]); mjpeg_info ("Mode extension : %8u",mode_extension); mjpeg_info ("Copyright bit : %8u %s", copyright,mpa_copyright_status[copyright]); mjpeg_info ("Original/Copy : %8u %s", original_copy,mpa_original_bit[original_copy]); mjpeg_info ("Emphasis : %8u %s", emphasis,mpa_emphasis_mode[emphasis]); } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/interact.hpp0000644000175000017500000000765512052075212017671 0ustar glowwormglowworm /* * interact.hpp: Simple command-line front-end * * Copyright (C) 2001 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __INTERACT_HH__ #define __INTERACT_HH__ #ifndef _WIN32 #include #endif #include #include "mjpeg_types.h" #include "stream_params.hpp" #include "systems.hpp" class IBitStream; using std::vector; /************************************************************************* * * The Multiplexor job Parameters: * The various parametes of a multiplexing job: muxing options * *************************************************************************/ struct Workarounds { Workarounds(); }; class MultiplexParams { public: unsigned int data_rate; unsigned int packets_per_pack; int video_offset; // A/V sync offset. Always one 0 and the // other positive. Specified in int audio_offset; // MPEG-2 CLOCKS: 1/(90000*300)-th sec unsigned int sector_size; bool VBR; // Force VBR even if profile suggests CBR bool CBR; // Force CBR even if profile suggests VBR int mpeg; int mux_format; bool multifile_segment; bool always_system_headers; unsigned int max_PTS; bool stills; int verbose; int max_timeouts; const char *outfile_pattern; const char *vdr_index_pathname; int max_segment_size; int min_pes_header_len; int run_in_frames; // Run-in expressed in Frame intervals Workarounds workarounds; // Special work-around flags that // constrain the syntax to suit // the foibles of particular MPEG // parsers that are (guessed) to be // actually slightly broken. Always // off by default... }; /*********************************************************************** * * Multiplexor job - paramters plus the streams to mux. * * **********************************************************************/ enum StreamKind { MPEG_AUDIO, AC3_AUDIO, LPCM_AUDIO, DTS_AUDIO, MPEG_VIDEO, SUBP_STREAM, }; class JobStream { public: JobStream( IBitStream *_bs, StreamKind _kind ) : bs(_bs), kind(_kind) { } const char *NameOfKind(); IBitStream *bs; StreamKind kind; }; class MultiplexJob : public MultiplexParams { public: MultiplexJob(); virtual ~MultiplexJob(); unsigned int NumberOfTracks( StreamKind kind ); void GetInputStreams( vector &streams, StreamKind kind ); void SetupInputStreams( vector &inputs ); protected: public: vector streams; vector lpcm_param; vector video_param; vector subtitle_params; unsigned int audio_tracks; unsigned int video_tracks; unsigned int subtitle_tracks; unsigned int lpcm_tracks; }; /************************************************************************* Program ID *************************************************************************/ #define MPLEX_VER "2.2.7" #define MPLEX_DATE "$Date: 2012/11/17 01:55:16 $" #endif // __INTERACT_H__ /* * Local variables: * c-file-style: "gnu" * tab-width: 8 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/videostrm.hpp0000644000175000017500000000727110362454754020104 0ustar glowwormglowworm /* * videostrm.hpp: Video stream elementary input stream * * Copyright (C) 2001 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __VIDEOSTRM_H__ #define __VIDEOSTRM_H__ #include "inputstrm.hpp" #include "interact.hpp" #include "stream_params.hpp" class VideoStream : public ElementaryStream { public: VideoStream(IBitStream &ibs, VideoParams *parms, Multiplexor &into); void Init( const int stream_num ); static bool Probe(IBitStream &bs ); void Close(); inline int DecoderOrder() { return au->dorder; } inline int AUType() { return au->type; } bool SeqEndRunOut(); const AUnit *NextIFrame(); inline int NextAUType() { AUnit *p_au = Lookahead(); if( p_au != 0 ) return p_au->type; else return NOFRAME; } virtual unsigned int NominalBitRate() { return bit_rate * 400; } virtual void OutputGOPControlSector(); bool RunOutComplete(); virtual bool MuxPossible(clockticks currentSCR); virtual void AUMuxed( bool first_in_sector ) ; void SetMaxStdBufferDelay( unsigned int demux_rate ); void OutputSector(); inline double FrameRate() const { return frame_rate; } protected: static const unsigned int MAX_GOP_LENGTH = 128; void OutputSeqhdrInfo(); virtual void FillAUbuffer(unsigned int frames_to_buffer); virtual void NextDTSPTS( ); void ScanFirstSeqHeader(); uint8_t NewAUTimestamps( int AUtype ); bool NewAUBuffers( int AUtype ); unsigned int ExcludeNextIFramePayload(); public: unsigned int num_sequence ; unsigned int num_seq_end ; unsigned int num_pictures ; unsigned int num_groups ; unsigned int num_frames[4] ; int64_t avg_frames[4] ; unsigned int horizontal_size; unsigned int vertical_size ; unsigned int aspect_ratio ; unsigned int picture_rate ; unsigned int bit_rate ; unsigned int vbv_buffer_size; unsigned int CSPF ; double secs_per_frame; bool dtspts_for_all_au; // Ensure every AU has a timestamp // (no two AU can start in one sector) bool gop_control_packet; protected: /* State variables for scanning source bit-stream */ AUnit access_unit; int fields_presented; int group_start_pic; int group_start_field; int group_start_SCR; int temporal_reference; unsigned int pict_struct; int pulldown_32; int repeat_first_field; int prev_temp_ref; int ref_present; int prev_ref_present; double frame_rate; double max_bits_persec; int AU_pict_data; int AU_hdr; clockticks max_STD_buffer_delay; VideoParams *parms; }; // // DVD's generate control sectors for each GOP... // class DVDVideoStream : public VideoStream { public: DVDVideoStream(IBitStream &ibs,VideoParams *parms,Multiplexor &into) : VideoStream( ibs, parms, into ) { gop_control_packet = true; } void OutputGOPControlSector(); }; #endif // __INPUTSTRM_H__ /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/bits.hpp0000644000175000017500000001272610370232305017013 0ustar glowwormglowworm#ifndef __BITS_H__ #define __BITS_H__ #include #include typedef uint64_t bitcount_t; class BitStreamBuffering { public: BitStreamBuffering(); void Release(); void Empty(); void SetBufSize( unsigned int buf_size); uint8_t *StartAppendPoint(unsigned int additional); inline void Appended(unsigned int additional) { buffered += additional; assert( buffered <= bfr_size ); } private: inline uint8_t *BufferEnd() { return bfr+buffered; } protected: // // TODO: really we should set these based on system parameters etc. // static const unsigned int BUFFER_SIZE; static const unsigned int BUFFER_CEILING; uint8_t *bfr; // The read/write buffer tiself unsigned int bfr_size; // The physical size of the buffer = // maximum buffered data-bytes possible unsigned int buffered; // Number of data-bytes in buffer }; /******* * * the input bit stream class (see below) provides a mechanism to * restore the scanning state to a marked point, provided no flush has * taken place. * * This base class contains the state information needed to mark/restore * between flushes. * * N.b. not that we override the BitStreamBuffering destructor so * we don't cheerfully deallocate the buffer when an undo * goes out of scope! * ******/ class IBitStreamUndo { public: IBitStreamUndo() : bfr_start(0), bitreadpos(0), bitidx(8), bytereadpos(0), eobs(true), scandone(false) {} inline bool eos() { return eobs; } inline bitcount_t bitcount() { return bitreadpos; } protected: bitcount_t bfr_start; // The position in the underlying // data-stream of the first byte of // the buffer. unsigned int byteidx; // Byte in buffer holding bit at current // to current bit read position bitcount_t bitreadpos; // Total bits read at current bit read position int bitidx; // Position in byteidx buffer byte of // bit at current bit read position // N.b. coded as bits-left-to-read count-down bitcount_t bytereadpos; // Bit position of the current *byte* // read position bool eobs; // End-of-bitstream flag: true iff // Bit read position has reached the end // of the underlying bitstream... bool scandone; // Caller signals scanning completed. }; /*************************************** * * IBitStream - Input bit stream base class. Supports the * "scanning" of a stream held in a large buffer which is flushed * once it has been "read". * * I.e. there are in effect two file-pointers: * * A bit-level parsing file-pointers intended for bit-level parsing * through the 'Get*' and 'Seek*'. Scanning/seeking using these entry * points keeps appending the got/sought data from the underlying * stream to a (dynamically sized) internal buffer. * * A byte-level I/O file pointer used for reading chunks of data * identified through parsing. * * A final set of entry-points allow parsed/read data that no longer * needs to buffered to be flushed from the buffer (and buffer space * reclaimed!). * * * INVARIANT: only data items up to the bit-level file-pointer can be 'read' * It is possible to undo bit-level parsing calls back up the last flush. * * The actual source of the bit stream to be parsed/read is *abstract* * in this base class. Access in derived classes is through the * virtual member function 'ReadStreamBytes' which should behave in * the same way as 'fread'. I.e. it should only return a short count * at EOF or ERROR and further calls after EOF or ERROR should return * a zero count. * * Hence the actual source of the bit stream need not support seeking. * ******************************************/ class IBitStream : public IBitStreamUndo, public BitStreamBuffering { public: IBitStream() : IBitStreamUndo(), streamname( "unnamed" ) { } virtual ~IBitStream() { Release(); } // Bit-level Parsing file-pointer entry-points uint32_t Get1Bit(); uint32_t GetBits(int N); bool SeekSync( uint32_t sync, int N, int lim); void SeekFwdBits( unsigned int bytes_to_seek_fwd ); // Bit-level parsing state undo mechanism void PrepareUndo(IBitStreamUndo &undobuf); void UndoChanges(IBitStreamUndo &undobuf); // Byte-level file-I/O entry-points inline bitcount_t GetBytePos() { return bytereadpos; } inline unsigned int BufferedBytes() { return static_cast(bfr_start+buffered-bytereadpos); } unsigned int GetBytes( uint8_t *dst, unsigned int length_bytes); // // Byte data buffer management void Flush( bitcount_t byte_position ); // // Reading from stream is done... void ScanDone(); inline const char *StreamName() { return streamname; } protected: bool ReadIntoBuffer( unsigned int to_read = BUFFER_SIZE ); virtual size_t ReadStreamBytes( uint8_t *buf, size_t number ) = 0; virtual bool EndOfStream() = 0; const char *streamname; }; #ifdef REDUNDANT_CODE class OBitStreamUndo : public BitStreamBuffering { protected: uint8_t outbyte; unsigned int byteidx; unsigned int bitidx; unsigned int buffered; bitcount_t bitwritepos; uint8_t *bfr; unsigned int bfr_size; }; class BitStream : public OBitStreamUndo { }; class OBitStream : public OBitStreamUndo { public: inline bitcount_t bitcount() { return bitwritepos; } void open( char *bs_filename, unsigned int buf_size = BUFFER_SIZE); void close(); void putbits( int val, int n); void put1bit( int val); void alignbits(); private: FILE *fileh; const char *filename; void putbyte(); }; #endif #endif // __BITS_H__ mjpegtools-2.1.0/mplex/outputstrm.hpp0000644000175000017500000000247610566454642020342 0ustar glowwormglowworm /* * outputstream.h: Base Class for output * * * Copyright (C) 2001 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __OUTPUTSTRM_H__ #define __OUTPUTSTRM_H__ class OutputStream { public: OutputStream() : segment_num( 1 ), segment_len( 0 ) {} virtual ~OutputStream() {} virtual int Open( ) = 0; virtual void Close() = 0; virtual uint64_t SegmentSize( ) = 0; virtual void NextSegment() = 0; virtual void Write(uint8_t *data, unsigned int len) = 0; int SegmentNum() const { return segment_num; } protected: int segment_num; uint64_t segment_len; }; #endif /* __OUTPUTSTRM_H__ */ mjpegtools-2.1.0/mplex/README0000644000175000017500000000406607605554426016241 0ustar glowwormglowworm * mplex-2 - MPEG1/2 SYSTEMS/PROGRAM stream multiplexer * * Orginally based on mplex * Copyright (C) 1994 1995 Christoph Moar * Reengineered version in C++ * Copyright (C) 2000,2001, 2002 Andrew Stevens * * Andrew.stevens@philips.com (Andrew Stevens) * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License in the file COPYING for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. MODIFICATIONS TO ORIGINAL July 2000 Andrew Stevens Trivial modifications to support catenated audio stremas and non-intractive use. August 2000 Andrew Stevens Modifed to support multiplexing of variable bit-rate video streams. Seems to work well. August 2000 Andrew Stevens Removed use of temporary files for storing stream data. Increased performance through the use of a more efficient bitstream library. Eliminated arithmetic overflow errors for large streams. Initial support for multiplexing variable bit-rate streams. Novermber 2000 Andrew Stevens Clean up code to suit modern compilers with 64-bit int support. Cleaned up packet size calculations to make the code more flexible. Initial MPEG-2 support Support for splitting output streams (not yet completely implemented) Support for multiplexing for VCD. Jan 2001-Dec 2002 Reengineered in C++ Support for SVCD. Support for basic DVD (dummy navigation sectors) Support for AC3 and LPCM audio VBR Audio as well as video. Clean stream splitting support. Class structure to simplify adding new stream types Encapsulation and modularistion mjpegtools-2.1.0/mplex/multiplexor.cpp0000644000175000017500000014364112052075212020433 0ustar glowwormglowworm/* * multiplexor.cpp: Program/System stream Multiplex despatcher * * Copyright (C) 2003 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define STREAM_LOGGING #include #include #include #include #include #include #include #include "interact.hpp" #include "videostrm.hpp" #include "stillsstream.hpp" #include "audiostrm.hpp" #include "multiplexor.hpp" /**************** * * Constructor - sets up per-run stuff and initialised parameters * that control syntax of generated stream from the job options set * by the user. * ***************/ Multiplexor::Multiplexor(MultiplexJob &job, OutputStream &output, OutputStream *index) { underrun_ignore = 0; underruns = 0; start_of_new_pack = false; InitSyntaxParameters(job); InitInputStreams(job); psstrm = new PS_Stream(mpeg, sector_size, output, max_segment_size ); vdr_index = index; } Multiplexor::~Multiplexor() { delete psstrm; while (!estreams.empty()) { delete estreams.back(); estreams.pop_back(); } vstreams.clear(); astreams.clear(); } /****************************************************************** * * Initialisation of stream syntax paramters based on selected user * options. Depending of mux_format some selections may only act as * defaults or may simply be ignored if they are inconsistent with the * selected output format. * ******************************************************************/ void Multiplexor::InitSyntaxParameters(MultiplexJob &job) { seg_starts_with_video = false; audio_buffer_size = 4 * 1024; mux_format = job.mux_format; packets_per_pack = job.packets_per_pack; data_rate = job.data_rate; mpeg = job.mpeg; always_sys_header_in_pack = job.always_system_headers; sector_transport_size = job.sector_size; sector_size = job.sector_size; split_at_seq_end = !job.multifile_segment; workarounds = job.workarounds; run_in_frames = job.run_in_frames; max_segment_size = static_cast(job.max_segment_size) * static_cast(1024 * 1024); max_PTS = static_cast(job.max_PTS) * CLOCKS; video_delay = static_cast(job.video_offset); audio_delay = static_cast(job.audio_offset); switch( mux_format ) { case MPEG_FORMAT_VCD : data_rate = 75*2352; /* 75 raw CD sectors/sec */ case MPEG_FORMAT_VCD_NSR : /* VCD format, non-standard rate */ mjpeg_info( "Selecting VCD output profile"); video_buffers_iframe_only = false; mpeg = 1; packets_per_pack = 1; sys_header_in_pack1 = 0; always_sys_header_in_pack = 0; sector_transport_size = 2352; /* Each 2352 bytes with 2324 bytes payload */ transport_prefix_sectors = 30; sector_size = 2324; buffers_in_video = 1; always_buffers_in_video = 0; buffers_in_audio = 1; // This is needed as otherwise we have always_buffers_in_audio = 1; // to stuff the packer header which // must be 13 bytes for VCD audio vcd_zero_stuffing = 20; // The famous 20 zero bytes for VCD // audio sectors. dtspts_for_all_vau = false; sector_align_iframeAUs = false; timestamp_iframe_only = false; seg_starts_with_video = true; if( job.video_tracks == 0 ) { mjpeg_info( "Audio-only VCD track - variable-bit-rate (VCD2.0)"); vbr = true; } else vbr = false; break; case MPEG_FORMAT_MPEG2 : mjpeg_info( "Selecting generic MPEG2 output profile"); mpeg = 2; packets_per_pack = 1; sys_header_in_pack1 = 1; always_sys_header_in_pack = 0; sector_transport_size = 2048; /* Each 2352 bytes with 2324 bytes payload */ transport_prefix_sectors = 0; sector_size = 2048; buffers_in_video = 1; always_buffers_in_video = 0; buffers_in_audio = 1; always_buffers_in_audio = 1; vcd_zero_stuffing = 0; vbr = true; dtspts_for_all_vau = 0; timestamp_iframe_only = false; video_buffers_iframe_only = false; break; case MPEG_FORMAT_SVCD : data_rate = 150*2324; case MPEG_FORMAT_SVCD_NSR : /* Non-standard data-rate */ mjpeg_info( "Selecting SVCD output profile"); mpeg = 2; packets_per_pack = 1; sys_header_in_pack1 = 0; always_sys_header_in_pack = 0; sector_transport_size = 2324; transport_prefix_sectors = 0; sector_size = 2324; vbr = true; buffers_in_video = 1; always_buffers_in_video = 0; buffers_in_audio = 1; always_buffers_in_audio = 0; vcd_zero_stuffing = 0; dtspts_for_all_vau = 0; sector_align_iframeAUs = true; seg_starts_with_video = true; timestamp_iframe_only = false; video_buffers_iframe_only = false; break; case MPEG_FORMAT_VCD_STILL : data_rate = 75*2352; /* 75 raw CD sectors/sec */ vbr = false; mpeg = 1; split_at_seq_end = false; packets_per_pack = 1; sys_header_in_pack1 = 0; always_sys_header_in_pack = 0; sector_transport_size = 2352; /* Each 2352 bytes with 2324 bytes payload */ transport_prefix_sectors = 0; sector_size = 2324; buffers_in_video = 1; always_buffers_in_video = 0; buffers_in_audio = 1; always_buffers_in_audio = 0; vcd_zero_stuffing = 20; dtspts_for_all_vau = 1; sector_align_iframeAUs = true; timestamp_iframe_only = false; video_buffers_iframe_only = false; break; case MPEG_FORMAT_SVCD_STILL : mjpeg_info( "Selecting SVCD output profile"); if( data_rate == 0 ) data_rate = 150*2324; mpeg = 2; packets_per_pack = 1; sys_header_in_pack1 = 0; always_sys_header_in_pack = 0; sector_transport_size = 2324; transport_prefix_sectors = 0; sector_size = 2324; vbr = true; buffers_in_video = 1; always_buffers_in_video = 0; buffers_in_audio = 1; always_buffers_in_audio = 0; vcd_zero_stuffing = 0; dtspts_for_all_vau = 0; sector_align_iframeAUs = true; timestamp_iframe_only = false; video_buffers_iframe_only = false; break; case MPEG_FORMAT_DVD : mjpeg_info( "Selecting generic DVD output profile (PROVISIONAL)"); if( data_rate == 0 ) data_rate = 1260000; mpeg = 2; packets_per_pack = 1; sys_header_in_pack1 = false; // Handle by control packets always_sys_header_in_pack = false; sector_transport_size = 2048; transport_prefix_sectors = 0; sector_size = 2048; buffers_in_video = true; always_buffers_in_video = false; buffers_in_audio = true; always_buffers_in_audio = false; vcd_zero_stuffing = 0; dtspts_for_all_vau = 0; sector_align_iframeAUs = true; timestamp_iframe_only = true; video_buffers_iframe_only = true; vbr = true; break; case MPEG_FORMAT_DVD_NAV : mjpeg_info( "Selecting dvdauthor DVD output profile"); if( data_rate == 0 ) data_rate = 1260000; mpeg = 2; packets_per_pack = 1; sys_header_in_pack1 = false; // Handle by control packets always_sys_header_in_pack = false; sector_transport_size = 2048; transport_prefix_sectors = 0; sector_size = 2048; buffers_in_video = true; always_buffers_in_video = false; buffers_in_audio = true; always_buffers_in_audio = false; vcd_zero_stuffing = 0; dtspts_for_all_vau = 0; sector_align_iframeAUs = true; timestamp_iframe_only = true; video_buffers_iframe_only = true; vbr = true; seg_starts_with_video = true; // Needs special NAV sector 1st! break; default : /* MPEG_FORMAT_MPEG1 - auto format MPEG1 */ mjpeg_info( "Selecting generic MPEG1 output profile"); //mpeg = 1; sys_header_in_pack1 = 1; transport_prefix_sectors = 0; buffers_in_video = 1; always_buffers_in_video = 1; buffers_in_audio = 0; always_buffers_in_audio = 1; vcd_zero_stuffing = 0; dtspts_for_all_vau = 0; sector_align_iframeAUs = false; timestamp_iframe_only = false; video_buffers_iframe_only = false; vbr = false; break; } if( job.VBR ) vbr = true; if( job.CBR ) vbr = false; } /************************************** * * Initialise the elementary stream readers / output sector formatter * objects for the various kinds of input stream. * *************************************/ void Multiplexor::InitInputStreams(MultiplexJob &job) { // // S(VCD) Stills are sufficiently unusual to require their own // special initialisation // if( MPEG_STILLS_FORMAT(job.mux_format) ) InitInputStreamsForStills( job ); else InitInputStreamsForVideo( job ); } void Multiplexor::InitInputStreamsForStills(MultiplexJob & job ) { std::vector::iterator vidparm = job.video_param.begin(); unsigned int frame_interval; unsigned int i; vector video_strms; job.GetInputStreams( video_strms, MPEG_VIDEO ); vector mpa_strms; job.GetInputStreams( mpa_strms, MPEG_AUDIO ); switch( job.mux_format ) { case MPEG_FORMAT_VCD_STILL : mjpeg_info( "Multiplexing VCD stills: %d stills streams.", video_strms.size() ); { frame_interval = 30; // 30 Frame periods if( mpa_strms.size() > 0 && video_strms.size() > 2 ) mjpeg_error_exit1("VCD stills: no more than two streams (one normal one hi-res) possible"); VCDStillsStream *str[2]; for( i = 0; i< video_strms.size(); ++i ) { FrameIntervals *ints = new ConstantFrameIntervals( frame_interval ); str[i] = new VCDStillsStream( *(video_strms[i]->bs), new StillsParams( *vidparm, ints), *this ); estreams.push_back( str[i] ); vstreams.push_back( str[i] ); str[i]->Init(); ++vidparm; } if( video_strms.size() == 2 ) { str[0]->SetSibling(str[1]); str[1]->SetSibling(str[0]); } } break; case MPEG_FORMAT_SVCD_STILL : mjpeg_info( "Multiplexing SVCD stills: %d stills streams %d audio streams", video_strms.size(), mpa_strms.size() ); frame_interval = 30; if( video_strms.size() > 1 ) { mjpeg_error_exit1("SVCD stills streams may only contain a single video stream"); } else if( video_strms.size() > 0 ) { ConstantFrameIntervals *intervals; StillsStream *str; intervals = new ConstantFrameIntervals( frame_interval ); str = new StillsStream( *(video_strms[0]->bs), new StillsParams( *vidparm, intervals ), *this ); estreams.push_back( str ); vstreams.push_back( str ); str->Init(); } for( i = 0 ; i < mpa_strms.size() ; ++i ) { AudioStream *audioStrm = new MPAStream( *(mpa_strms[i]->bs), *this); audioStrm->Init ( i); estreams.push_back(audioStrm); astreams.push_back(audioStrm); } break; default: mjpeg_error_exit1("Only VCD and SVCD stills format for the moment..."); } } void Multiplexor::InitInputStreamsForVideo(MultiplexJob & job ) { mjpeg_info( "Multiplexing video program stream!" ); unsigned int audio_track = 0; unsigned int video_track = 0; unsigned int subp_track = 0; std::vector::iterator vidparm = job.video_param.begin(); std::vector::iterator lpcmparm = job.lpcm_param.begin(); std::vector::iterator subpparm = job.subtitle_params.begin(); std::vector::iterator i; for( i = job.streams.begin() ; i < job.streams.end() ; ++i ) { switch( (*i)->kind ) { case MPEG_VIDEO : { VideoStream *videoStrm; // // The first video stream is made the master stream... // if( video_track == 0 && job.mux_format == MPEG_FORMAT_DVD_NAV ) videoStrm = new DVDVideoStream( *(*i)->bs, *vidparm, *this); else videoStrm = new VideoStream( *(*i)->bs, *vidparm, *this); videoStrm->Init( video_track ); ++video_track; ++vidparm; estreams.push_back( videoStrm ); vstreams.push_back( videoStrm ); } break; case MPEG_AUDIO : { AudioStream *audioStrm = new MPAStream( *(*i)->bs, *this); audioStrm->Init ( audio_track ); estreams.push_back(audioStrm); astreams.push_back(audioStrm); ++audio_track; } break; case AC3_AUDIO : { AudioStream *audioStrm = new AC3Stream( *(*i)->bs, *this); audioStrm->Init ( audio_track ); estreams.push_back(audioStrm); astreams.push_back(audioStrm); ++audio_track; } break; case DTS_AUDIO : { AudioStream *audioStrm = new DTSStream( *(*i)->bs, *this); audioStrm->Init ( audio_track ); estreams.push_back(audioStrm); astreams.push_back(audioStrm); ++audio_track; } break; case LPCM_AUDIO : { AudioStream *audioStrm = new LPCMStream( *(*i)->bs, *lpcmparm, *this); audioStrm->Init ( audio_track ); estreams.push_back(audioStrm); astreams.push_back(audioStrm); ++lpcmparm; ++audio_track; } break; case SUBP_STREAM : { // we use audios stream as base class SUBPStream *subpStrm = new SUBPStream( *(*i)->bs, *subpparm,*this); subpStrm ->Init ( subp_track ); estreams.push_back(subpStrm ); astreams.push_back(subpStrm ); ++subpparm; ++subp_track; } break; } } } /******************************************************************* Find the timecode corresponding to given position in the system stream (assuming the SCR starts at 0 at the beginning of the stream @param bytepos byte position in the stream @param ts returns the number of clockticks the bytepos is from the file start ****************************************************************** */ void Multiplexor::ByteposTimecode(bitcount_t bytepos, clockticks &ts) { ts = (bytepos*CLOCKS)/static_cast(dmux_rate); } /********** * * NextPosAndSCR - Update nominal (may be >= actual) byte count * and SCR to next output sector. * ********/ void Multiplexor::NextPosAndSCR() { bytes_output += sector_transport_size; ByteposTimecode( bytes_output, current_SCR ); if (start_of_new_pack) { psstrm->CreatePack (&pack_header, current_SCR, mux_rate); pack_header_ptr = &pack_header; if( include_sys_header ) sys_header_ptr = &sys_header; else sys_header_ptr = NULL; } else pack_header_ptr = NULL; } /********** * * SetPosAndSCR - Update nominal (may be >= actual) byte count * and SCR to next output sector. * @param bytepos byte position in the stream ********/ void Multiplexor::SetPosAndSCR( bitcount_t bytepos ) { bytes_output = bytepos; ByteposTimecode( bytes_output, current_SCR ); if (start_of_new_pack) { psstrm->CreatePack (&pack_header, current_SCR, mux_rate); pack_header_ptr = &pack_header; if( include_sys_header ) sys_header_ptr = &sys_header; else sys_header_ptr = NULL; } else pack_header_ptr = NULL; } /* Stream syntax parameters. */ typedef enum { start_segment, mid_segment, runout_segment } segment_state; /** * Compute the number of run-in sectors needed to fill up the buffers to * suit the type of stream being muxed. * * For stills we have to ensure an entire buffer is loaded as we only * ever process one frame at a time. * @returns the number of run-in sectors needed to fill up the buffers to suit the type of stream being muxed. */ #if 0 unsigned int Multiplexor::RunInSectors() { std::vector::iterator str; unsigned int sectors_delay = 1; for( str = vstreams.begin(); str < vstreams.end(); ++str ) { if( MPEG_STILLS_FORMAT( mux_format ) ) { sectors_delay += static_cast(1.02*(*str)->BufferSize()) / sector_size+2; } else if( vbr ) sectors_delay += 3*(*str)->BufferSize() / ( 4 * sector_size ); else sectors_delay += 5 *(*str)->BufferSize() / ( 6 * sector_size ); } sectors_delay += astreams.size(); return sectors_delay; } #endif clockticks Multiplexor::RunInDelay() { std::vector::iterator str; double frame_interval = 0.0; clockticks delay; // User has specified a particular run-in if(vstreams.size() != 0 ) { frame_interval = CLOCKS / dynamic_cast(vstreams[0])->FrameRate(); } if( run_in_frames != 0 ) { if( frame_interval == 0.0 ) { mjpeg_warn( "Run-in specified in frame intervals but no video stream - using 25Hz" ); frame_interval = CLOCKS / 25.0; } delay = static_cast(run_in_frames * frame_interval); } else { // No run-in specified: choose something reasonable based on the // specified buffer sizes unsigned int data_delay = 0; for( str = vstreams.begin(); str < vstreams.end(); ++str ) { if( MPEG_STILLS_FORMAT( mux_format ) ) { data_delay += static_cast(1.1*(*str)->BufferSize()); } else if( vbr ) data_delay += (*str)->BufferSize() / 2 ; else data_delay += 2*(*str)->BufferSize() / 3 ; } for( str = astreams.begin(); str < astreams.end(); ++str ) { data_delay += 3*(*str)->BufferSize()/4; } ByteposTimecode( data_delay, delay ); } // Round delay a multiple of frame interval if its known... if( frame_interval != 0.0 ) { return static_cast(static_cast( delay / frame_interval+0.5) * frame_interval); } else { return delay; } } /********************************************************************** * * Initializes the output stream proper. Traverses the input files * and calculates their payloads. Estimates the multiplex * rate. Estimates the necessary stream delay for the different * substreams. * *********************************************************************/ void Multiplexor::Init() { std::vector::iterator str; clockticks delay; Pack_struc dummy_pack; Sys_header_struc dummy_sys_header; Sys_header_struc *sys_hdr; unsigned int nominal_rate_sum; mjpeg_info("SYSTEMS/PROGRAM stream:"); psstrm->Open(); if( vdr_index != 0 ) vdr_index->Open(); /* These are used to make (conservative) decisions about whether a packet should fit into the recieve buffers... Audio packets always have PTS fields, video packets needn'. TODO: Really this should be encapsulated in Elementary stream...? */ psstrm->CreatePack (&dummy_pack, 0, mux_rate); if( always_sys_header_in_pack ) { vector muxstreams; AppendMuxStreamsOf( estreams, muxstreams ); psstrm->CreateSysHeader (&dummy_sys_header, mux_rate, !vbr, 1, true, true, muxstreams); sys_hdr = &dummy_sys_header; } else sys_hdr = NULL; nominal_rate_sum = 0; for( str = estreams.begin(); str < estreams.end(); ++str ) { switch( (*str)->Kind() ) { case ElementaryStream::audio : (*str)->SetMaxPacketData( psstrm->PacketPayload( **str, NULL, NULL, false, true, false ) ); (*str)->SetMinPacketData( psstrm->PacketPayload( **str, sys_hdr, &dummy_pack, always_buffers_in_audio, true, false ) ); break; case ElementaryStream::video : (*str)->SetMaxPacketData( psstrm->PacketPayload( **str, NULL, NULL, false, false, false ) ); (*str)->SetMinPacketData( psstrm->PacketPayload( **str, sys_hdr, &dummy_pack, always_buffers_in_video, true, true ) ); break; default : mjpeg_error_exit1("INTERNAL: Only audio and video payload calculations implemented!"); } if( (*str)->NominalBitRate() == 0 && data_rate == 0) mjpeg_error_exit1( "Variable bit-rate stream present: output stream (max) data-rate *must* be specified!"); nominal_rate_sum += (*str)->NominalBitRate(); } /* Attempt to guess a sensible mux rate for the given video and * audio estreams. This is a rough and ready guess for MPEG-1 like formats. */ dmux_rate = static_cast(1.0205 * nominal_rate_sum); dmux_rate = (dmux_rate/50 + 25)*50/8; mjpeg_info ("rough-guess multiplexed stream data rate : %07d", dmux_rate*8 ); if( data_rate != 0 ) mjpeg_info ("target data-rate specified : %7d", data_rate*8 ); if( data_rate == 0 ) { mjpeg_info( "Setting best-guess data rate."); } else if ( data_rate >= dmux_rate) { mjpeg_info( "Setting specified specified data rate: %7d", data_rate*8 ); dmux_rate = data_rate; } else if ( data_rate < dmux_rate ) { mjpeg_warn( "Target data rate lower than computed requirement!"); mjpeg_warn( "N.b. a 20%% or so discrepancy in variable bit-rate"); mjpeg_warn( "streams is common and harmless provided no time-outs will occur"); dmux_rate = data_rate; } mux_rate = dmux_rate/50; // // Now that all mux parameters are set we can trigger parsing // of actual input stream data and calculation of associated // PTS/DTS by causing the read of the first AU's... // for( str = estreams.begin(); str < estreams.end(); ++str ) { (*str)->NextAU(); } // // Now that we have both output and input streams initialised and // data-rates set we can make a decent job of setting the maximum // STD buffer delay in video streams. // for( str = vstreams.begin(); str < vstreams.end(); ++str ) { static_cast(*str)->SetMaxStdBufferDelay( dmux_rate ); } /* To avoid Buffer underflow, the DTS of the first video and audio AU's must be offset sufficiently forward of the SCR to allow the buffer time to fill before decoding starts. Calculate the necessary delays... */ //sectors_delay = RunInSectors(); //ByteposTimecode( // static_cast(sectors_delay*sector_transport_size), // delay ); delay = RunInDelay(); video_delay += delay; audio_delay += delay; /* * The PTS of the first frame may be different from its DTS. * Thus to hit perfect A/V sync we need to delay audio by the difference * PTS-DTS. * */ if( vstreams.size() != 0 ) { audio_delay += vstreams[0]->BasePTS()-vstreams[0]->BaseDTS(); } mjpeg_info( "Run-in delay = %lld Video delay = %lld Audio delay = %lld", delay / 300, video_delay / 300, audio_delay / 300 ); if( max_PTS != 0 ) mjpeg_info( "Multiplexed stream will be ended at %lld seconds playback time\n", max_PTS/CLOCKS ); } /** Prints the current status of the substreams. @param level the desired log level */ void Multiplexor::MuxStatus(log_level_t level) { std::vector::iterator str; for( str = estreams.begin(); str < estreams.end(); ++str ) { switch( (*str)->Kind() ) { case ElementaryStream::video : if( (*str)->MuxCompleted() ) mjpeg_log( level, "Video %02x: completed", (*str)->stream_id ); else mjpeg_log( level, "Video %02x: buf=%7d frame=%06d sector=%08d", (*str)->stream_id, (*str)->BufferSize()-(*str)->bufmodel.Space(), (*str)->DecodeOrder(), (*str)->nsec ); break; case ElementaryStream::audio : if( (*str)->MuxCompleted() ) mjpeg_log( level, "Audio %02x: completed", (*str)->stream_id ); else mjpeg_log( level, "Audio %02x: buf=%7d frame=%06d sector=%08d", (*str)->stream_id, (*str)->BufferSize()-(*str)->bufmodel.Space(), (*str)->DecodeOrder(), (*str)->nsec ); break; default : if( (*str)->MuxCompleted() ) mjpeg_log( level, "Other %02x: completed", (*str)->stream_id ); else mjpeg_log( level, "Other %02x: buf=%7d sector=%08d", (*str)->stream_id, (*str)->bufmodel.Space(), (*str)->nsec ); break; } } if( !vbr ) mjpeg_log( level, "Padding : sector=%08d", pstrm.nsec ); } /** Append input substreams to the output multiplex stream. */ void Multiplexor::AppendMuxStreamsOf( vector &elem, vector &mux ) { std::vector::iterator str; for( str = elem.begin(); str < elem.end(); ++str ) { mux.push_back( static_cast( *str ) ); } } /****************************************************************** Program start-up packets. Generate any irregular packets needed at the start of the stream... Note: *must* leave a sensible in-stream system header in sys_header. TODO: get rid of this grotty sys_header global. ******************************************************************/ void Multiplexor::OutputPrefix( ) { vector vmux,amux,emux; AppendMuxStreamsOf( vstreams, vmux ); AppendMuxStreamsOf( astreams, amux ); AppendMuxStreamsOf( estreams, emux ); /* Deal with transport padding */ SetPosAndSCR( bytes_output + transport_prefix_sectors*sector_transport_size ); /* VCD: Two padding packets with video and audio system headers */ switch (mux_format) { case MPEG_FORMAT_VCD : case MPEG_FORMAT_VCD_NSR : /* Annoyingly VCD generates seperate system headers for audio and video ... DOH... */ if( astreams.size() > 1 || vstreams.size() > 1 || astreams.size() + vstreams.size() != estreams.size() ) { mjpeg_error_exit1("VCD man only have max. 1 audio and 1 video stream"); } if( vstreams.size() > 0 ) { /* First packet carries video-info-only sys_header */ psstrm->CreateSysHeader (&sys_header, mux_rate, false, true, true, true, vmux ); sys_header_ptr = &sys_header; pack_header_ptr = &pack_header; OutputPadding( false); } if( astreams.size() > 0 ) { /* Second packet carries audio-info-only sys_header */ psstrm->CreateSysHeader (&sys_header, mux_rate, false, true, true, true, amux ); sys_header_ptr = &sys_header; pack_header_ptr = &pack_header; OutputPadding( true ); } break; case MPEG_FORMAT_SVCD : case MPEG_FORMAT_SVCD_NSR : /* First packet carries sys_header */ psstrm->CreateSysHeader (&sys_header, mux_rate, !vbr, true, true, true, emux ); sys_header_ptr = &sys_header; pack_header_ptr = &pack_header; OutputPadding(false); break; case MPEG_FORMAT_VCD_STILL : /* First packet carries small-still sys_header */ /* TODO No support mixed-mode stills sequences... */ psstrm->CreateSysHeader (&sys_header, mux_rate, false, false, true, true, emux ); sys_header_ptr = &sys_header; pack_header_ptr = &pack_header; OutputPadding( false); break; case MPEG_FORMAT_SVCD_STILL : /* TODO: Video only at present */ /* First packet carries video-info-only sys_header */ psstrm->CreateSysHeader (&sys_header, mux_rate, false, true, true, true, vmux ); sys_header_ptr = &sys_header; pack_header_ptr = &pack_header; OutputPadding( false); break; case MPEG_FORMAT_DVD_NAV : /* A DVD System header is a weird thing. We seem to need to include buffer info about streams 0xb8, 0xb9, 0xbd, 0xbf even if they're not physically present but the buffers for the actual video streams aren't included. */ { // MANY DVD streams appear not to include system headers // and some tools have weak parsers that can't handle all // the possible variations. Soooo probably best not to generate // them DummyMuxStream dvd_0xb9_strm_dummy( 0xb9, 1, 232*1024 ); DummyMuxStream dvd_0xb8_strm_dummy( 0xb8, 0, 4096 ); DummyMuxStream dvd_0xbf_strm_dummy( 0xbf, 1, 2048 ); vector dvdmux; std::vector::iterator muxstr; dvdmux.push_back( &dvd_0xb9_strm_dummy ); dvdmux.push_back( &dvd_0xb8_strm_dummy ); unsigned int max_priv1_buffer = 58*1024; for( muxstr = amux.begin(); muxstr < amux.end(); ++muxstr ) { // We mux *many* substreams on PRIVATE_STR_1 // we set the system header buffer size to the maximum // of all those we find if( (*muxstr)->stream_id == PRIVATE_STR_1 ) { if( (*muxstr)->BufferSize() > max_priv1_buffer ) max_priv1_buffer = (*muxstr)->BufferSize(); } // Now the *sane* thing to do if MPEG audio is present would be // record this in the system header. However, dvdauthor lacks // a header parser and barfs if the system headers aren't exactly // 18 bytes. Soooo we simply skip them for now... // TOOD: Add back in when dvdauthor can parse system headers //else // dvdmux.push_back( *muxstr ); } DummyMuxStream dvd_priv1_strm_dummy( PRIVATE_STR_1, 1, max_priv1_buffer ); dvdmux.push_back( &dvd_priv1_strm_dummy ); dvdmux.push_back( &dvd_0xbf_strm_dummy ); psstrm->CreateSysHeader (&sys_header, mux_rate, !vbr, false, true, true, dvdmux ); sys_header_ptr = &sys_header; pack_header_ptr = &pack_header; /* It is then followed up by a pair of PRIVATE_STR_2 packets which we keep empty 'cos we don't know what goes there... */ } break; default : /* Create the in-stream header in case it is needed */ psstrm->CreateSysHeader (&sys_header, mux_rate, !vbr, false, true, true, emux ); } } /****************************************************************** Program shutdown packets. Generate any irregular packets needed at the end of the stream... ******************************************************************/ void Multiplexor::OutputSuffix() { psstrm->CreatePack (&pack_header, current_SCR, mux_rate); psstrm->CreateSector (&pack_header, NULL, 0, pstrm, false, true, 0, 0, TIMESTAMPBITS_NO ); } /****************************************************************** Main multiplex iteration. Opens and closes all needed files and manages the correct call od the respective Video- and Audio- packet routines. The basic multiplexing is done here. Buffer capacity and Timestamp checking is also done here, decision is taken wether we should genereate a Video-, Audio- or Padding- packet. ******************************************************************/ void Multiplexor::Multiplex() { segment_state seg_state; std::vector completed; std::vector::iterator pcomp; std::vector::iterator str; unsigned int packets_left_in_pack = 0; /* Suppress warning */ bool padding_packet; bool video_first = true; Init( ); unsigned int i; for(i = 0; i < estreams.size() ; ++i ) completed.push_back(false); /* Let's try to read in unit after unit and to write it out into the outputstream. The only difficulty herein lies into the buffer management, and into the fact the the actual access unit *has* to arrive in time, that means the whole unit (better yet, packet data), has to arrive before arrival of DTS. If both buffers are full we'll generate a padding packet Of course, when we start we're starting a new segment with no bytes output... */ ByteposTimecode( sector_transport_size, ticks_per_sector ); seg_state = start_segment; running_out = false; for(;;) { bool completion = true; for( str = estreams.begin(); str < estreams.end() ; ++str ) completion &= (*str)->MuxCompleted(); if( completion ) break; /* A little state-machine for handling the transition from one segment to the next */ bool runout_incomplete; VideoStream *master; switch( seg_state ) { /* Audio and slave video access units at end of segment. If there are any audio AU's whose PTS implies they should be played *before* the video AU starting the next segement is presented we mux them out. Once they're gone we've finished this segment so we write the suffix switch file, and start muxing a new segment. */ case runout_segment : runout_incomplete = false; for( str = estreams.begin(); str < estreams.end(); ++str ) { runout_incomplete |= !(*str)->RunOutComplete(); } if( runout_incomplete ) break; /* Otherwise we write the stream suffix and start a new stream file */ OutputSuffix(); psstrm->NextSegment(); running_out = false; seg_state = start_segment; /* Starting a new segment. We send the segment prefix, video and audio reciever buffers are assumed to start empty. We reset the segment length count and hence the SCR. */ case start_segment : mjpeg_info( "New sequence commences..." ); SetPosAndSCR(0); MuxStatus( mjpeg_loglev_t("info") ); for( str = estreams.begin(); str < estreams.end(); ++str ) { (*str)->AllDemuxed(); } packets_left_in_pack = packets_per_pack; start_of_new_pack = true; include_sys_header = sys_header_in_pack1; buffers_in_video = always_buffers_in_video; video_first = seg_starts_with_video & (vstreams.size() > 0); OutputPrefix(); /* Set the offset applied to the raw PTS/DTS of AU's to make the DTS of the first AU in the master (video) stream precisely the video delay plus whatever time we wasted in the sequence pre-amble. The DTS of the remaining streams are set so that (modulo the relevant delay offset) they maintain the same relative timing to the master stream. */ clockticks ZeroSCR; if( vstreams.size() != 0 ) ZeroSCR = vstreams[0]->BaseDTS(); else ZeroSCR = estreams[0]->BaseDTS(); for( str = vstreams.begin(); str < vstreams.end(); ++str ) (*str)->SetSyncOffset(video_delay + current_SCR - ZeroSCR ); for( str = astreams.begin(); str < astreams.end(); ++str ) (*str)->SetSyncOffset(audio_delay + current_SCR - ZeroSCR ); pstrm.nsec = 0; for( str = estreams.begin(); str < estreams.end(); ++str ) (*str)->nsec = 0; seg_state = mid_segment; break; case mid_segment : /* Once we exceed our file size limit, we need to start a new file soon. If we want a single stream we simply switch. Otherwise we're in the last gop of the current segment (and need to start running streams out ready for a clean continuation in the next segment). TODO: runout_PTS really needs to be expressed in sync delay adjusted units... */ master = vstreams.size() > 0 ? static_cast(vstreams[0]) : 0 ; if( psstrm->SegmentLimReached() ) { if( split_at_seq_end ) mjpeg_warn( "File size exceeded before split-point in video stream" ); mjpeg_info( "Starting new output file..."); psstrm->NextSegment(); } else if( master != 0 && master->SeqEndRunOut() ) { const AUnit *nextIframe = master->NextIFrame(); if( split_at_seq_end && nextIframe != 0) { runout_PTS = master->RequiredPTS(nextIframe); mjpeg_info( "Sequence end marker! Running out..."); mjpeg_info("Run out PTS limit to AU %d %lld SCR=%lld", nextIframe->dorder, runout_PTS/300, current_SCR/300 ); MuxStatus( mjpeg_loglev_t("info") ); running_out = true; seg_state = runout_segment; } else { mjpeg_warn( "Sequence end without following I-frame!" ); } } break; } padding_packet = false; start_of_new_pack = (packets_left_in_pack == packets_per_pack); for( str = estreams.begin(); str < estreams.end(); ++str ) { (*str)->DemuxedTo(current_SCR); } // // Find the ready-to-mux stream with the most urgent DTS // ElementaryStream *despatch = 0; clockticks earliest = 0; for( str = estreams.begin(); str < estreams.end(); ++str ) { #ifdef STREAM_LOGGING if( (*str)->MuxCompleted() ) mjpeg_debug( "%02x: complete", (*str)->stream_id ); else mjpeg_debug("%02x: SCR=%lld (%.3f) mux=%d %d reqDTS=%lld ", (*str)->stream_id, current_SCR, static_cast(current_SCR) /(90.0*300.0), (*str)->MuxPossible(current_SCR), (*str)->BufferSize()-(*str)->bufmodel.Space(), (*str)->RequiredDTS()/300 ); #endif if( (*str)->MuxPossible(current_SCR) && ( !video_first || (*str)->Kind() == ElementaryStream::video ) ) { if( despatch == 0 || earliest > (*str)->RequiredDTS() ) { despatch = *str; earliest = (*str)->RequiredDTS(); } } } if( underrun_ignore > 0 ) --underrun_ignore; if( despatch ) { despatch->BufferAndOutputSector(); video_first = false; if( current_SCR >= earliest && underrun_ignore == 0) { mjpeg_warn( "Stream %02x: data will arrive too late sent(SCR)=%lld required(DTS)=%lld", despatch->stream_id, current_SCR/300, earliest/300 ); MuxStatus( mjpeg_loglev_t("warn") ); // Give the stream a chance to recover underrun_ignore = 300; ++underruns; if( underruns > 10 ) { mjpeg_error_exit1("Too many frame drops -exiting" ); } } if( despatch->nsec > 50 && despatch->Lookahead( ) != 0 && ! running_out) despatch->UpdateBufferMinMax(); padding_packet = false; } else { // // If we got here no stream could be muxed out. // We therefore generate padding packets if necessary // usually this is because reciever buffers are likely to be // full. // if( vbr ) { // // VBR: For efficiency we bump SCR up to five times or // until it looks like buffer status will change NextPosAndSCR(); clockticks next_change = static_cast(0); for( str = estreams.begin(); str < estreams.end(); ++str ) { clockticks change_time = (*str)->bufmodel.NextChange(); if( next_change == 0 || change_time < next_change ) { next_change = change_time; } } unsigned int bumps = 5; while( bumps > 0 && next_change > current_SCR + ticks_per_sector) { NextPosAndSCR(); --bumps; } } else { // Just output a padding packet OutputPadding ( false); } padding_packet = true; } /* Update the counter for pack packets. VBR is a tricky case as here padding packets are "virtual" */ if( ! (vbr && padding_packet) ) { --packets_left_in_pack; if (packets_left_in_pack == 0) packets_left_in_pack = packets_per_pack; } MuxStatus( mjpeg_loglev_t("debug") ); /* Unless sys headers are always required we turn them off after the first packet has been generated */ include_sys_header = always_sys_header_in_pack; pcomp = completed.begin(); str = estreams.begin(); while( str < estreams.end() ) { if( !(*pcomp) && (*str)->MuxCompleted() ) { mjpeg_info( "STREAM %02x completed", (*str)->stream_id ); MuxStatus( mjpeg_loglev_t("debug") ); (*pcomp) = true; } ++str; ++pcomp; } } // Tidy up OutputSuffix( ); psstrm->Close(); if( vdr_index != 0) vdr_index->Close(); mjpeg_info( "Multiplex completion at SCR=%lld.", current_SCR/300); MuxStatus( mjpeg_loglev_t("info") ); for( str = estreams.begin(); str < estreams.end(); ++str ) { (*str)->Close(); if( (*str)->nsec <= 50 ) mjpeg_info( "BUFFERING stream too short for useful statistics"); else mjpeg_info( "BUFFERING min %d Buf max %d", (*str)->BufferMin(), (*str)->BufferMax() ); } if( underruns> 0 ) { mjpeg_error_exit1( "MUX STATUS: Frame data under-runs detected!" ); } else { mjpeg_info( "MUX STATUS: no under-runs detected."); } } /** Calculate the packet payload of the output stream at a certain timestamp. @param strm the output stream @param buffers the number of buffers @param PTSstamp presentation time stamp @param DTSstamp decoding time stamp */ unsigned int Multiplexor::PacketPayload( MuxStream &strm, bool buffers, bool PTSstamp, bool DTSstamp ) { return psstrm->PacketPayload( strm, sys_header_ptr, pack_header_ptr, buffers, PTSstamp, DTSstamp) - strm.StreamHeaderSize(); } /*************************************************** WritePacket - Write out a normal packet carrying data from one of the elementary stream being muxed. @param max_packet_data_size the maximum packet data size allowed @param strm output mux stream @param buffers ? @param PTSstamp presentation time stamp of the packet @param DTSstamp decoding time stamp of the packet @param timestamps ? @param returns the written bytes/packets (?) ***************************************************/ struct VDRtIndex { uint32_t offset; uint8_t type; uint8_t number; uint16_t reserved; }; unsigned int Multiplexor::WritePacket( unsigned int max_packet_data_size, MuxStream &strm, bool buffers, clockticks PTS, clockticks DTS, uint8_t timestamps ) { unsigned int written = psstrm->CreateSector ( pack_header_ptr, sys_header_ptr, max_packet_data_size, strm, buffers, false, PTS, DTS, timestamps ); NextPosAndSCR(); return written; } /*************************************************** IndexLastPacket - Generate the index data (if any) for the latest packet generated in the specified stream. N.b. should usually called immediately after WritePacket. Its not part of WritePacket because it is not needed for all stream types... ***************************************************/ void Multiplexor::IndexLastPacket( ElementaryStream &strm, int index_type ) { switch( strm.Kind() ) { case ElementaryStream::video : if( index_type != NOFRAME && vdr_index != 0 ) { union _ibuf { uint8_t bytes[sizeof(VDRtIndex)]; VDRtIndex istruct; } indexbuf; indexbuf.istruct.offset = (int)psstrm->LastPackStart(); indexbuf.istruct.type = index_type; indexbuf.istruct.number = (int)psstrm->SegmentNum(); indexbuf.istruct.reserved = 0; vdr_index->Write( indexbuf.bytes, sizeof(VDRtIndex) ); } break; default : abort(); // Currently only video indexing implemented } } /*************************************************** * * WriteRawSector - Write out a packet carrying data for * a control packet with irregular content. @param rawsector data for the raw sector @param length length of the raw sector ***************************************************/ void Multiplexor::WriteRawSector( uint8_t *rawsector, unsigned int length ) { // // Writing raw sectors when packs stretch over multiple sectors // is a recipe for disaster! // assert( packets_per_pack == 1 ); psstrm->RawWrite( rawsector, length ); NextPosAndSCR(); } /****************************************************************** OutputPadding generates Pack/Sys Header/Packet information for a padding stream and saves the sector We have to pass in a special flag to cope with appalling mess VCD makes of audio packets (the last 20 bytes being dropped thing) 0 = Fill the packet completetely. This include "audio packets" that include no actual audio, only a system header and padding. @param vcd_audio_pad flag for VCD audio padding ******************************************************************/ void Multiplexor::OutputPadding (bool vcd_audio_pad) { if( vcd_audio_pad ) psstrm->CreateSector ( pack_header_ptr, sys_header_ptr, 0, vcdapstrm, false, false, 0, 0, TIMESTAMPBITS_NO ); else psstrm->CreateSector ( pack_header_ptr, sys_header_ptr, 0, pstrm, false, false, 0, 0, TIMESTAMPBITS_NO ); ++pstrm.nsec; NextPosAndSCR(); } /****************************************************************** * OutputGOPControlSector * DVD System headers are carried in peculiar sectors carrying 2 * PrivateStream2 packets. We're sticking 0's in the packets * for anything other than the substream IDs as they're * merely being inserted as place-holders to provide gaps the * DVD authoring SW can fill in later. * * Thanks to Brent Byeler who worked out this work-around. * ******************************************************************/ void Multiplexor::OutputDVDPriv2 ( ) { uint8_t *packet_size_field; uint8_t *index; uint8_t *sector_buf = new uint8_t[sector_size]; unsigned int tozero; assert( sector_size == 2048 ); psstrm->BufferSectorHeader( sector_buf, pack_header_ptr, &sys_header, index ); psstrm->BufferPacketHeader( index, PRIVATE_STR_2, 2, // MPEG 2 false, // No buffers 0, 0, 0, // No timestamps 0, TIMESTAMPBITS_NO, 0, // Natural PES header length packet_size_field, index ); tozero = sector_buf+1024-index; memset( index, 0, tozero); index[0] = 0x00; // Substream 1 (PCI) index += tozero; psstrm->BufferPacketSize( packet_size_field, index ); psstrm->BufferPacketHeader( index, PRIVATE_STR_2, 2, // MPEG 2 false, // No buffers 0, 0, 0, // No timestamps 0, TIMESTAMPBITS_NO, 0, // Natural PES header length packet_size_field, index ); tozero = sector_buf+2048-index; memset( index, 0, tozero ); index[0] = 0x01; // Substream 1 (DSI) index += tozero; psstrm->BufferPacketSize( packet_size_field, index ); WriteRawSector( sector_buf, sector_size ); delete [] sector_buf; } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/INSTRUCT0000644000175000017500000000545007133030460016534 0ustar glowwormglowworm////////////////////////////////////////////////////////////////////////// // // // INSTRUCTIONS FOR MPLEX - THE MPEG1/SYSTEMS MULTIPLEXER // // // ////////////////////////////////////////////////////////////////////////// Please note that I do not have a comprehensive instruction manual for this release. I suggest you try the program out with some default values and learn something more about ISO/IEC 11172-1 (aka MPEG1/Systems). For those of you that can read *German*, you can download a postscript paper discussing implementation and problems of this software, with introductions to MPEG1/Audio, MPEG1/Video and MPEG1/Systems. You should find the paper with the same distribution you got this program from. If not, you should find the postscript version of this 40-page paper on ftp.informatik.tu-muenchen.de in /pub/comp/graphics/mpeg/mplex (121822 bytes, Jun 30 , 1994 , mpeg_systems_paper_0.99.ps.gz) If you have any questions you cannot figure out by running the program, feel free to ask me. -------------------------------------------------------------------------- One more thing that might save me many emails: when asked about the startup packet delay, try something like half the video buffer size divided by your sector size. Say you have a 40 kByte video buffer and a 2324 Byte Sector size, then a startup delay of 8 sectors will work just fine. What does the above parameter mean? Normally, the Decoding/Presentation Time Stamp of the first access unit is set to the clock value that will happen exactly after the last packet containig data from this first unit arrives into the system target decoder. This works fine if the video/audio streams are of *very perfectly constant* or the packet size are *very* small (ideally: the size of one access unit, that would mean variable packet length). Anyway: this parameter allows you to say that the System Target Decoder should start decoding the first access unit after he gets (startup_packet_delay + size_of_first_access_units[av]) packets of data. This guarantees that the buffers are conveniently filled up. Note that both the video stream offset and audio stream offset (ms) add up even more bytes to this startup delay, but you can tell conveniently that audio should start so many ms after video, for example. Sorry for no further doc, enjoy multiplexing A/V :) Christoph. moar@heaven.zfe.siemens.de +---------------------------------------+--------------------------------+ | http://www.informatik.tu-muenchen.de/ | Christoph Moar | | cgi-bin/nph-gateway/hphalle6/~moar/ | Kaulbachstr.29a | | index.html | 80539 Munich | | email:moar@informatik.tu-muenchen.de | voice: ++49 - 89 - 23862874 | +---------------------------------------+--------------------------------+ mjpegtools-2.1.0/mplex/decodebufmodel.hpp0000644000175000017500000000311410115434307021005 0ustar glowwormglowworm /* * buffer.hpp: Classes for decoder buffer models for mux despatch * * Copyright (C) 2001 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DECODEBUFMODEL_H__ #define __DECODEBUFMODEL_H__ #include "aunit.hpp" #include struct DecodeBufEntry { unsigned int size ; /* als verkettete Liste implementiert */ clockticks DTS ; }; class DecodeBufModel { public: DecodeBufModel() : buffer_size(0) {} void Init ( unsigned int size) { buffer_size = size; } void Cleaned( clockticks timenow); clockticks NextChange(); void Flushed( ); unsigned int Space(); void Queued( unsigned int bytes, clockticks removaltime); inline unsigned int Size() { return buffer_size; } private: unsigned int buffer_size; std::deque bufstate ; }; #endif // __DECODEBUFMODEL_H__ /* * Local variables: * c-file-style: "gnu" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/dtsstrm_in.cpp0000644000175000017500000002763510075410011020232 0ustar glowwormglowworm/* * dtsstrm_in.c: dts Audio stream class members handling scanning and * buffering raw input stream. * * Copyright (C) 2003 Markus Plail * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "audiostrm.hpp" #include "interact.hpp" #include "multiplexor.hpp" #define DTS_SYNCWORD 0x7ffe8001 #define DTS_PACKET_SAMPLES 1536 const unsigned int DTSStream::default_buffer_size = 16*1024; /// table for the available dts bitrates static const unsigned int dts_bitrate_index[32] = { 32,56,64,96,112,128,192,224, 256,320,384,448,512,576,640,768, 960,1024,1152,1280,1344,1408,1411,1472, 1536,1920,2048,3072,3840,0,0,0 }; /// table for the available dts frequencies static const unsigned int dts_frequency[17] = { 0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, 12000, 24000, 48000, 0, 0 }; /// samples per frame static const unsigned int dts_packet_samples[4] = { 256, 512, 1024, 2048 }; DTSStream::DTSStream(IBitStream &ibs, Multiplexor &into) : AudioStream( ibs, into ) { num_frames = 0; } bool DTSStream::Probe(IBitStream &bs ) { return bs.GetBits(32) == DTS_SYNCWORD; } #ifdef DEBUG_DTS static char *binString(int value, int length) { char *bin = (char *) malloc((length + 1) * sizeof(char)); int index; int dummy = 1 << (length - 1); for(index = 0; index < length; index++) { if(value & dummy) bin[index] = '1'; else bin[index] = '0'; dummy >>= 1; } bin[index] = '\0'; return(bin); } /************************************************************************* * * Reads initial stream parameters and displays feedback banner to users * @param stream_num dts substream ID *************************************************************************/ void DTSStream::DisplayDtsHeaderInfo() { /* Some stuff to generate frame-header information */ printf( "normal/termination? = %i\n", bs.GetBits(1) ); printf( "deficit sample count = %i\n", bs.GetBits(5) ); int crc = bs.GetBits(1); printf( "CRC present? = %i\n", crc ); printf( "PCM samples = %i\n", bs.GetBits(7) ); printf( "frame byte size = %i\n", bs.GetBits(14) ); int acmode = bs.GetBits(6); printf( "audio channel = %s\n", binString(acmode, 6) ); printf( "audio sampling freqency = %s\n", binString(bs.GetBits(4), 4) ); printf( "bit rate = %s\n", binString(bs.GetBits(5), 5) ); printf( "downmix enabled = %i\n", bs.GetBits(1) ); printf( "dynamic range flag = %i\n", bs.GetBits(1) ); printf( "time stamp = %i\n", bs.GetBits(1) ); printf( "auxiliary data = %i\n", bs.GetBits(1) ); printf( "HDCD = %i\n", bs.GetBits(1) ); printf( "extended coding flag = %i\n", bs.GetBits(1) ); printf( "audio sync word insert = %i\n", bs.GetBits(1) ); printf( "low frequency effects = %i\n", bs.GetBits(1) ); printf( "predictor history = %i\n", bs.GetBits(1) ); if (crc) printf( "CRC = %i\n", bs.GetBits(16) ); printf( "multirate interpolator = %i\n", bs.GetBits(1) ); printf( "encoder software revision = %i\n", bs.GetBits(4) ); printf( "copy history = %i\n", bs.GetBits(2) ); printf( "PCM resolution = %s\n", binString(bs.GetBits(3), 3) ); printf( "front sums difference flags = %i\n", bs.GetBits(1) ); printf( "surround sums difference flags = %i\n", bs.GetBits(1) ); printf( "dialog normalization parameter = %i\n", bs.GetBits(4) ); } #endif void DTSStream::Init ( const int _stream_num) { stream_num = _stream_num; MuxStream::Init( PRIVATE_STR_1, 1, // Buffer scale default_buffer_size, false, muxinto.buffers_in_audio, muxinto.always_buffers_in_audio ); mjpeg_info ("Scanning for header info: dts Audio stream %02x (%s)", stream_num, bs.StreamName() ); AU_start = bs.bitcount(); if (bs.GetBits(32)==DTS_SYNCWORD) { num_syncword++; bs.GetBits(6); // additional sync bs.GetBits(1); // CRC bs.GetBits(7); // pcm samples framesize = bs.GetBits(14) + 1; // frame size bs.GetBits(6); // audio channels frequency = bs.GetBits(4); // sample rate code bit_rate = dts_bitrate_index[bs.GetBits(5)]; bs.GetBits(5); // misc. header_skip = 10; // Initially skipped past 10 bytes of header num_frames++; access_unit.start = AU_start; access_unit.length = framesize; mjpeg_info( "dts frame size = %d", framesize ); samples_per_second = dts_frequency[frequency]; /* Presentation time-stamping */ access_unit.PTS = static_cast(decoding_order) * static_cast(DTS_PACKET_SAMPLES) * static_cast(CLOCKS) / samples_per_second; access_unit.DTS = access_unit.PTS; access_unit.dorder = decoding_order; ++decoding_order; aunits.Append( access_unit ); } else { mjpeg_error ( "Invalid dts Audio stream header."); exit (1); } OutputHdrInfo(); } /// @returns the current bitrate unsigned int DTSStream::NominalBitRate() { return bit_rate*1024; } /// Prefills the internal buffer for output multiplexing. /// @param frames_to_buffer the number of audio frames to read ahead void DTSStream::FillAUbuffer(unsigned int frames_to_buffer ) { unsigned int packet_samples; last_buffered_AU += frames_to_buffer; mjpeg_debug( "Scanning %d dts audio frames to frame %d", frames_to_buffer, last_buffered_AU ); while( !bs.eos() && decoding_order < last_buffered_AU && !muxinto.AfterMaxPTS(access_unit.PTS) ) { int skip = access_unit.length - header_skip; bs.SeekFwdBits(skip); prev_offset = AU_start; AU_start = bs.bitcount(); if( AU_start - prev_offset != access_unit.length*8 ) { mjpeg_warn( "Discarding incomplete final frame dts stream %d!", stream_num); aunits.DropLast(); decoding_order--; break; } /* Check if we have reached the end or have another catenated stream to process before finishing ... */ if ( (syncword = bs.GetBits(32))!=DTS_SYNCWORD ) { if( !bs.eos() ) { mjpeg_error_exit1( "Can't find next dts frame: @ %lld we have %04x - broken bit-stream?", AU_start/8, syncword ); } break; } bs.GetBits(6); // additional sync bs.GetBits(1); // CRC packet_samples = (bs.GetBits(7) + 1) * 32; // pcm samples framesize = bs.GetBits(14) + 1; // frame size bs.GetBits(6); // audio channels bs.GetBits(4); // sample rate code bs.GetBits(5); // bitrate bs.GetBits(5); // misc. access_unit.start = AU_start; access_unit.length = framesize; access_unit.PTS = static_cast(decoding_order) * static_cast(packet_samples) * static_cast(CLOCKS) / samples_per_second; access_unit.DTS = access_unit.PTS; access_unit.dorder = decoding_order; decoding_order++; aunits.Append( access_unit ); num_frames++; num_syncword++; if (num_syncword >= old_frames+10 ) { mjpeg_debug ("Got %d frame headers.", num_syncword); old_frames=num_syncword; } } last_buffered_AU = decoding_order; eoscan = bs.eos() || muxinto.AfterMaxPTS(access_unit.PTS); } /// Closes the dts stream and prints some statistics. void DTSStream::Close() { stream_length = AU_start >> 3; mjpeg_info ("DTS STATISTICS: %02x", stream_id); mjpeg_info ("Audio stream length %lld bytes.", stream_length); mjpeg_info ("Frames : %8u", num_frames); } /************************************************************************* OutputAudioInfo gibt gesammelte Informationen zu den Audio Access Units aus. Prints information on audio access units *************************************************************************/ void DTSStream::OutputHdrInfo () { mjpeg_info("dts AUDIO STREAM:"); mjpeg_info ("Bit rate : %8u bytes/sec (%3u kbit/sec)", bit_rate*128, bit_rate); if (frequency == 3) mjpeg_info ("Frequency : reserved"); else mjpeg_info ("Frequency : %d Hz", dts_frequency[frequency]); } /** Reads the bytes neccessary to complete the current packet payload. @param to_read number of bytes to read @param dst byte buffer pointer to read to @returns the number of bytes read */ unsigned int DTSStream::ReadPacketPayload(uint8_t *dst, unsigned int to_read) { clockticks decode_time; // TODO: BUG BUG BUG: if there is a change in format in the stream // this framesize will be invalid! It only *looks* like it works... // really each AU should store its own framesize... unsigned int frames = to_read / framesize; bitcount_t read_start = bs.GetBytePos(); unsigned int bytes_read = bs.GetBytes( dst + 4, framesize * frames); unsigned int bytes_muxed = bytes_read; assert( bytes_read > 0 ); // Should never try to read nothing bs.Flush( read_start ); unsigned int first_header = (new_au_next_sec || au_unsent > bytes_read ) ? 0 : au_unsent; // BUG BUG BUG: how do we set the 1st header pointer if we have // the *middle* part of a large frame? assert( first_header+2 <= to_read ); unsigned int syncwords = 0; if (bytes_muxed == 0 || MuxCompleted() ) { goto completion; } /* Work through what's left of the current AU and the following AU's updating the info until we reach a point where an AU had to be split between packets. NOTE: It *is* possible for this loop to iterate. The DTS/PTS field for the packet in this case would have been given the that for the first AU to start in the packet. */ decode_time = RequiredDTS(); while (au_unsent < bytes_muxed) { // BUG BUG BUG: if we ever had odd payload / packet size we might // split a DTS frame in the middle of the syncword! assert( bytes_muxed > 1 ); bufmodel.Queued(au_unsent, decode_time); bytes_muxed -= au_unsent; if( new_au_next_sec ) ++syncwords; if( !NextAU() ) { goto completion; } new_au_next_sec = true; decode_time = RequiredDTS(); }; // We've now reached a point where the current AU overran or // fitted exactly. We need to distinguish the latter case // so we can record whether the next packet starts with an // existing AU or not - info we need to decide what PTS/DTS // info to write at the start of the next packet. if (au_unsent > bytes_muxed) { if( new_au_next_sec ) ++syncwords; bufmodel.Queued( bytes_muxed, decode_time); au_unsent -= bytes_muxed; new_au_next_sec = false; } else // if (au_unsent == bytes_muxed) { bufmodel.Queued(bytes_muxed, decode_time); if( new_au_next_sec ) ++syncwords; new_au_next_sec = NextAU(); } completion: // Generate the dts header... // Note the index counts from the low byte of the offset so // the smallest value is 1! dst[0] = DTS_SUB_STR_0 + stream_num; dst[1] = frames; dst[2] = (first_header+1)>>8; dst[3] = (first_header+1)&0xff; return bytes_read + 4; } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/systems.hpp0000644000175000017500000001245510747735115017577 0ustar glowwormglowworm /* * interact.h: Program/System stream packet generator * * Copyright (C) 2003 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SYSTEMS_HH__ #define __SYSTEMS_HH__ #include "inputstrm.hpp" #include "outputstrm.hpp" #include using std::vector; /* Buffer size parameters */ #define MAX_SECTOR_SIZE 16384 #define MAX_PACK_HEADER_SIZE 255 #define MAX_SYS_HEADER_SIZE 255 typedef struct sector_struc /* Ein Sektor, kann Pack, Sys Header */ /* und Packet enthalten. */ { unsigned char buf [MAX_SECTOR_SIZE] ; unsigned int length_of_packet_data ; //clockticks TS ; } Sector_struc; struct Pack_struc /* Pack Info */ { uint8_t buf[MAX_PACK_HEADER_SIZE]; int length; clockticks SCR; }; struct Sys_header_struc /* System Header Info */ { uint8_t buf[MAX_SYS_HEADER_SIZE]; int length; }; class PS_Stream { public: PS_Stream( unsigned _mpeg, unsigned int _sector_size, OutputStream &_output_strm, uint64_t max_segment_size // 0 = No Limit ); virtual ~PS_Stream(); unsigned int PacketPayload( MuxStream &strm, Sys_header_struc *sys_header, Pack_struc *pack_header, int buffers, int PTSstamp, int DTSstamp ); unsigned int CreateSector (Pack_struc *pack, Sys_header_struc *sys_header, unsigned int max_packet_data_size, MuxStream &strm, bool buffers, bool end_marker, clockticks PTS, clockticks DTS, uint8_t timestamps ); void BufferSectorHeader( uint8_t *buf, Pack_struc *pack, Sys_header_struc *sys_header, uint8_t *&header_end ); void BufferPacketHeader( uint8_t *buf, uint8_t type, unsigned int mpeg_version, bool buffers, unsigned int buffer_size, uint8_t buffer_scale, clockticks PTS, clockticks DTS, uint8_t timestamps, unsigned int min_pes_hdr_len, uint8_t *&size_field, uint8_t *&header_end ); static inline void BufferPacketSize( uint8_t *size_field, uint8_t *packet_end ) { unsigned int packet_size = packet_end-size_field-2; size_field[0] = static_cast(packet_size>>8); size_field[1] = static_cast(packet_size&0xff); } virtual void CreatePack ( Pack_struc *pack, clockticks SCR, unsigned int mux_rate ); virtual void CreateSysHeader ( Sys_header_struc *sys_header, unsigned int rate_bound, bool fixed, int CSPS, bool audio_lock, bool video_lock, vector &streams ); inline int Open() { return output_strm.Open(); } inline void Close() { output_strm.Close(); } inline void RawWrite(uint8_t *data, unsigned int len) { return output_strm.Write( data, len ); } inline void NextSegment() { output_strm.NextSegment(); } bool SegmentLimReached(); inline int SegmentNum() const { return output_strm.SegmentNum(); } inline bitcount_t LastPackStart() const { return last_pack_start; } protected: static void BufferDtsPtsMpeg1ScrTimecode (clockticks timecode, uint8_t marker, uint8_t *&buffer); static void BufferMpeg2ScrTimecode( clockticks timecode, uint8_t *&buffer); void BufferPaddingPacket( int padding, uint8_t *&buffer ); virtual bool StreamWithMPeg2HeaderExt( uint8_t type ); private: OutputStream &output_strm; unsigned int mpeg_version; unsigned int sector_size; uint64_t max_segment_size; uint8_t *sector_buf; bitcount_t last_pack_start; }; #endif // __SYSTEMS_HH__ /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/systems.cpp0000644000175000017500000005745510747735115017603 0ustar glowwormglowworm /* * systems.cpp: Program/System stream packet generator * * * Copyright (C) 2001 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include "systems.hpp" #include "mplexconsts.hpp" PS_Stream:: PS_Stream( unsigned _mpeg, unsigned int _sector_size, OutputStream &_output_strm, uint64_t max_seg_size ) : output_strm(_output_strm ), mpeg_version( _mpeg), sector_size( _sector_size ), max_segment_size( max_seg_size ) { sector_buf = new uint8_t[sector_size]; max_segment_size = max_seg_size; } PS_Stream::~PS_Stream() { delete [] sector_buf; } bool PS_Stream::SegmentLimReached() { uint64_t written = output_strm.SegmentSize(); return max_segment_size != 0 && written > max_segment_size; } /************************************************************** Packet payload compute how much payload a sector-sized packet with the specified headers can carry... TODO: Should really be called "Sector Payload" **************************************************************/ unsigned int PS_Stream::PacketPayload( MuxStream &mux_strm, Sys_header_struc *sys_header, Pack_struc *pack_header, int buffers, int PTSstamp, int DTSstamp ) { int payload = sector_size - (PACKET_HEADER_SIZE + mux_strm.zero_stuffing); if( sys_header != NULL ) payload -= sys_header->length; if( mpeg_version == 2 ) { if( buffers ) payload -= MPEG2_BUFFERINFO_LENGTH; payload -= MPEG2_AFTER_PACKET_LENGTH_MIN; if( pack_header != NULL ) payload -= pack_header->length; if( DTSstamp ) payload -= DTS_PTS_TIMESTAMP_LENGTH; if ( PTSstamp ) payload -= DTS_PTS_TIMESTAMP_LENGTH; } else { if( buffers ) payload -= MPEG1_BUFFERINFO_LENGTH; payload -= MPEG1_AFTER_PACKET_LENGTH_MIN; if( pack_header != NULL ) payload -= pack_header->length; if( DTSstamp ) payload -= DTS_PTS_TIMESTAMP_LENGTH; if (PTSstamp ) payload -= DTS_PTS_TIMESTAMP_LENGTH; if( DTSstamp || PTSstamp ) payload += 1; /* No need for nostamp marker ... */ } return payload; } /************************************************************************* Kopiert einen TimeCode in einen Bytebuffer. Dabei wird er nach MPEG-Verfahren in bits aufgesplittet. Makes a Copy of a TimeCode in a Buffer, splitting it into bitfields for MPEG-1/2 DTS/PTS fields and MPEG-1 pack scr fields *************************************************************************/ void PS_Stream::BufferDtsPtsMpeg1ScrTimecode (clockticks timecode, uint8_t marker, uint8_t *&buffer) { clockticks thetime_base; uint8_t temp; unsigned int msb, lsb; /* MPEG-1 uses a 90KHz clock, extended to 300*90KHz = 27Mhz in MPEG-2 */ /* For these fields we only encode to MPEG-1 90Khz resolution... */ thetime_base = timecode /300; msb = (thetime_base >> 32) & 1; lsb = (thetime_base & static_cast(0xFFFFFFFF)); temp = (marker << 4) | (msb <<3) | ((lsb >> 29) & 0x6) | 1; *(buffer++)=temp; temp = (lsb & 0x3fc00000) >> 22; *(buffer++)=temp; temp = ((lsb & 0x003f8000) >> 14) | 1; *(buffer++)=temp; temp = (lsb & 0x7f80) >> 7; *(buffer++)=temp; temp = ((lsb & 0x007f) << 1) | 1; *(buffer++)=temp; } /************************************************************************* Makes a Copy of a TimeCode in a Buffer, splitting it into bitfields for MPEG-2 pack scr fields which use the full 27Mhz resolution Did they *really* need to put a 27Mhz clock source into the system stream. Does anyone really need it for their decoders? Get real... I guess they thought it might allow someone somewhere to save on a proper clock circuit. *************************************************************************/ void PS_Stream::BufferMpeg2ScrTimecode( clockticks timecode, uint8_t *&buffer ) { clockticks thetime_base; unsigned int thetime_ext; uint8_t temp; unsigned int msb, lsb; thetime_base = timecode /300; thetime_ext = timecode % 300; msb = (thetime_base>> 32) & 1; lsb = thetime_base & static_cast(0xFFFFFFFF); temp = (MARKER_MPEG2_SCR << 6) | (msb << 5) | ((lsb >> 27) & 0x18) | 0x4 | ((lsb >> 28) & 0x3); *(buffer++)=temp; temp = (lsb & 0x0ff00000) >> 20; *(buffer++)=temp; temp = ((lsb & 0x000f8000) >> 12) | 0x4 | ((lsb & 0x00006000) >> 13); *(buffer++)=temp; temp = (lsb & 0x00001fe0) >> 5; *(buffer++)=temp; temp = ((lsb & 0x0000001f) << 3) | 0x4 | ((thetime_ext & 0x00000180) >> 7); *(buffer++)=temp; temp = ((thetime_ext & 0x0000007F) << 1) | 1; *(buffer++)=temp; } /************************************************************************* BufferPaddingPacket - Insert a padding packet of the desired length into the specified Program/System stream buffer **************************************************************************/ void PS_Stream::BufferPaddingPacket( int padding, uint8_t *&buffer ) { uint8_t *index = buffer; int i; assert( (mpeg_version == 2 && padding >= 6) || (mpeg_version == 1 && padding >= 7) ); *(index++) = static_cast(PACKET_START)>>16; *(index++) = static_cast(PACKET_START & 0x00ffff)>>8; *(index++) = static_cast(PACKET_START & 0x0000ff); *(index++) = PADDING_STR; *(index++) = static_cast((padding - 6) >> 8); *(index++) = static_cast((padding - 6) & 0xff); if (mpeg_version == 2) { for (i = 0; i < padding - 6; i++) *(index++) = static_cast(STUFFING_BYTE); } else { *(index++) = 0x0F; for (i = 0; i < padding - 7; i++) *(index++) = static_cast(STUFFING_BYTE); } buffer = index; } void PS_Stream::BufferSectorHeader( uint8_t *index, Pack_struc *pack, Sys_header_struc *sys_header, uint8_t *&header_end ) { /* Pack header if present */ if (pack != NULL) { memcpy ( index, pack->buf, pack->length); index += pack->length; } /* System header if present */ if (sys_header != NULL) { memcpy (index, sys_header->buf, sys_header->length); index += sys_header->length; } header_end = index; } /************************ * * Is this a stream where for the MPEG-2 * header extensionsappear? * * The version below is correct at least forDVD * authoring. The function is virtual in case sometime * someplace a different format where PRIVATE_STR_2 is used * differently is encountered. * ************************/ bool PS_Stream::StreamWithMPeg2HeaderExt( uint8_t type ) { return type != PADDING_STR && type != PRIVATE_STR_2; } /****************************************** * * BufferPacketHeader * Construct an MPEG-1/2 header for a packet in the specified * buffer (which *MUST* be long enough) and set points to the start of * the payload and packet length fields. * ******************************************/ void PS_Stream::BufferPacketHeader( uint8_t *buf, uint8_t type, unsigned int mpeg_version, bool buffers, unsigned int buffer_size, uint8_t buffer_scale, clockticks PTS, clockticks DTS, uint8_t timestamps, unsigned int min_pes_hdr_len, uint8_t *&size_field, uint8_t *&header_end ) { uint8_t *index = buf; uint8_t *pes_header_len_field = 0; /* konstante Packet Headerwerte eintragen */ /* write constant packet header data */ *(index++) = static_cast(PACKET_START)>>16; *(index++) = static_cast(PACKET_START & 0x00ffff)>>8; *(index++) = static_cast(PACKET_START & 0x0000ff); *(index++) = type; /* we remember this offset so we can fill in the packet size field once we know the actual size... */ size_field = index; index += 2; if( mpeg_version == 1 ) { /* MPEG-1: buffer information */ if (buffers) { *(index++) = static_cast (0x40 | (buffer_scale << 5) | (buffer_size >> 8)); *(index++) = static_cast (buffer_size & 0xff); } /* MPEG-1: PTS, PTS & DTS, oder gar nichts? */ /* should we write PTS, PTS & DTS or nothing at all ? */ switch (timestamps) { case TIMESTAMPBITS_NO: *(index++) = MARKER_NO_TIMESTAMPS; break; case TIMESTAMPBITS_PTS: BufferDtsPtsMpeg1ScrTimecode (PTS, MARKER_JUST_PTS, index); break; case TIMESTAMPBITS_PTS_DTS: BufferDtsPtsMpeg1ScrTimecode (PTS, MARKER_PTS, index); BufferDtsPtsMpeg1ScrTimecode (DTS, MARKER_DTS, index); break; } } else if( StreamWithMPeg2HeaderExt( type ) ) { /* MPEG-2 packet syntax header flags. */ /* These *DO NOT* appear in padding packets */ /* TODO: They don't appear in several others either! */ /* First byte: <1,0> */ *(index++) = 0x81; /* Second byte: PTS PTS_DTS or neither? Buffer info? */ *(index++) = (timestamps << 6) | (!!buffers); /* Third byte: */ pes_header_len_field = index; /* To fill in later! */ index++; /* MPEG-2: the timecodes if required */ switch (timestamps) { case TIMESTAMPBITS_PTS: BufferDtsPtsMpeg1ScrTimecode(PTS, MARKER_JUST_PTS, index); break; case TIMESTAMPBITS_PTS_DTS: BufferDtsPtsMpeg1ScrTimecode(PTS, MARKER_PTS, index); BufferDtsPtsMpeg1ScrTimecode(DTS, MARKER_DTS, index); break; } /* MPEG-2 The buffer information in a PES_extension */ if( buffers ) { /* MPEG-2 PES extension header <{PES_extension_flag_2=0> */ *(index++) = static_cast(0x1e); *(index++) = static_cast (0x40 | (buffer_scale << 5) | (buffer_size >> 8)); *(index++) = static_cast (buffer_size & 0xff); } /* If required pad the PES header: needed for some workarounds */ while( index-(pes_header_len_field+1) < static_cast(min_pes_hdr_len) ) *(index++)=static_cast(STUFFING_BYTE); } if( mpeg_version != 1 && StreamWithMPeg2HeaderExt( type ) ) { *pes_header_len_field = static_cast(index-(pes_header_len_field+1)); } header_end = index; } /************************************************************************* * CreateSector * * Creates a complete sector to carry a padding packet or a packet * from one of the elementary streams. Pack and System headers are * prepended if required. * * We allow for situations where want to * deliberately reduce the payload carried by stuffing. * This allows us to deal with tricky situations where the * header overhead of adding in additional information * would exceed the remaining payload capacity. * * Header stuffing and/or a padding packet is appended if the sector is * unfilled. Zero stuffing after the end of a packet is also supported * to allow thos wretched audio packets from VCD's to be handled. * * TODO: Should really be called "WriteSector" * * TODO: We need to add a generic mechanism for sub-headers of * private streams to be generated... * *************************************************************************/ unsigned int PS_Stream::CreateSector (Pack_struc *pack, Sys_header_struc *sys_header, unsigned int max_packet_data_size, MuxStream &mux_strm, bool buffers, bool end_marker, clockticks PTS, clockticks DTS, uint8_t timestamps ) { int i; uint8_t *index; uint8_t *size_offset; unsigned int target_packet_data_size; unsigned int actual_packet_data_size; int packet_data_to_read; int bytes_short; uint8_t type = mux_strm.stream_id; uint8_t buffer_scale = mux_strm.BufferScale(); unsigned int buffer_size = mux_strm.BufferSizeCode(); unsigned int sector_pack_area; index = sector_buf; sector_pack_area = sector_size - mux_strm.zero_stuffing; if( end_marker ) sector_pack_area -= 4; BufferSectorHeader( index, pack, sys_header, index ); last_pack_start = output_strm.SegmentSize() + static_cast(index-sector_buf); BufferPacketHeader( index, type, mpeg_version, buffers, buffer_size, buffer_scale, PTS, DTS, timestamps, mux_strm.min_pes_header_len, size_offset, index ); /* MPEG-1, MPEG-2: data available to be filled is packet_size less * header and MPEG-1 trailer... */ target_packet_data_size = sector_pack_area - (index - sector_buf ); /* DEBUG: A handy consistency check when we're messing around */ #ifdef MUX_DEBUG if( type != PADDING_STR && (end_marker ? target_packet_data_size+4 : target_packet_data_size) != PacketPayload( mux_strm, sys_header, pack, buffers, timestamps & TIMESTAMPBITS_PTS, timestamps & TIMESTAMPBITS_DTS) ) { printf("\nPacket size calculation error %d S%d P%d B%d %d %d!\n ", timestamps, sys_header!=0, pack!=0, buffers, target_packet_data_size , PacketPayload( mux_strm, sys_header, pack, buffers, timestamps & TIMESTAMPBITS_PTS, timestamps & TIMESTAMPBITS_DTS)); exit(1); } #endif /* If a maximum payload data size is specified (!=0) and is smaller than the space available thats all we read (the remaining space is stuffed) */ if( max_packet_data_size != 0 && max_packet_data_size < target_packet_data_size ) { packet_data_to_read = max_packet_data_size; } else packet_data_to_read = target_packet_data_size; /* MPEG-1, MPEG-2: read in available packet data ... */ actual_packet_data_size = mux_strm.ReadPacketPayload(index,packet_data_to_read); bytes_short = target_packet_data_size - actual_packet_data_size; #ifdef MUX_DEBUG if( type == PRIVATE_STR_1 ) { mjpeg_info( "Substream %02x short %d", index[0], bytes_short ); } #endif /* Handle the situations where we don't have enough data to fill the packet size fully ... small shortfalls are dealt with here by stuffing, big ones dealt with later by appending padding packets. */ if( bytes_short < MINIMUM_PADDING_PACKET_SIZE && bytes_short > 0 ) { if (mpeg_version == 1 ) { /* MPEG-1 stuffing happens *before* header data fields. */ uint8_t *fixed_packet_header_end = size_offset + 2; memmove( fixed_packet_header_end+bytes_short, fixed_packet_header_end, actual_packet_data_size+(index-fixed_packet_header_end) ); for( i=0; i< bytes_short; ++i) fixed_packet_header_end[i] = static_cast(STUFFING_BYTE); } else { memmove( index+bytes_short, index, actual_packet_data_size ); for( i=0; i< bytes_short; ++i) *(index+i)=static_cast(STUFFING_BYTE); // Correct PES length field (if present) if( type != PADDING_STR ) { uint8_t *pes_header_len_offset = size_offset + 4; unsigned int pes_header_len = index+bytes_short-(pes_header_len_offset+1); *pes_header_len_offset = static_cast(pes_header_len); } } index += bytes_short; bytes_short = 0; } /* MPEG-2: We now know the final PES header after padding... */ index += actual_packet_data_size; /* MPEG-1, MPEG-2: Now we know that actual packet size */ size_offset[0] = static_cast((index-size_offset-2)>>8); size_offset[1] = static_cast((index-size_offset-2)&0xff); /* The case where we have fallen short enough to allow it to be dealt with by inserting a stuffing packet... */ if ( bytes_short != 0 ) { *(index++) = static_cast(PACKET_START)>>16; *(index++) = static_cast(PACKET_START & 0x00ffff)>>8; *(index++) = static_cast(PACKET_START & 0x0000ff); *(index++) = PADDING_STR; *(index++) = static_cast((bytes_short - 6) >> 8); *(index++) = static_cast((bytes_short - 6) & 0xff); if (mpeg_version == 2) { for (i = 0; i < bytes_short - 6; i++) *(index++) = static_cast(STUFFING_BYTE); } else { *(index++) = 0x0F; for (i = 0; i < bytes_short - 7; i++) *(index++) = static_cast(STUFFING_BYTE); } bytes_short = 0; } if( end_marker ) { *(index++) = static_cast((ISO11172_END)>>24); *(index++) = static_cast((ISO11172_END & 0x00ff0000)>>16); *(index++) = static_cast((ISO11172_END & 0x0000ff00)>>8); *(index++) = static_cast(ISO11172_END & 0x000000ff); } unsigned int j; for (j = 0; j < mux_strm.zero_stuffing; j++) *(index++) = static_cast(0); /* At this point padding or stuffing will have ensured the packet is filled to target_packet_data_size */ RawWrite(sector_buf, sector_size); return actual_packet_data_size; } /************************************************************************* Create_Pack erstellt in einem Buffer die spezifischen Pack-Informationen. Diese werden dann spaeter von der Sector-Routine nochmals in dem Sektor kopiert. writes specifical pack header information into a buffer later this will be copied from the sector routine into the sector buffer *************************************************************************/ void PS_Stream::CreatePack ( Pack_struc *pack, clockticks SCR, unsigned int mux_rate ) { uint8_t *index; index = pack->buf; *(index++) = static_cast((PACK_START)>>24); *(index++) = static_cast((PACK_START & 0x00ff0000)>>16); *(index++) = static_cast((PACK_START & 0x0000ff00)>>8); *(index++) = static_cast(PACK_START & 0x000000ff); if (mpeg_version == 2) { /* Annoying: MPEG-2's SCR pack header time is different from all the rest... */ BufferMpeg2ScrTimecode(SCR, index); *(index++) = static_cast(mux_rate >> 14); *(index++) = static_cast(0xff & (mux_rate >> 6)); *(index++) = static_cast(0x03 | ((mux_rate & 0x3f) << 2)); *(index++) = (uint8_t)(RESERVED_BYTE << 3 | 0); /* No pack stuffing */ } else { BufferDtsPtsMpeg1ScrTimecode(SCR, MARKER_MPEG1_SCR, index); *(index++) = static_cast(0x80 | (mux_rate >> 15)); *(index++) = static_cast(0xff & (mux_rate >> 7)); *(index++) = static_cast(0x01 | ((mux_rate & 0x7f) << 1)); } pack->SCR = SCR; pack->length = index-pack->buf; } /************************************************************************* Create_Sys_Header erstelle in einem Buffer die spezifischen Sys_Header Informationen. Diese werden spaeter von der Sector-Routine nochmals zum Sectorbuffer kopiert. writes specifical system header information into a buffer later this will be copied from the sector routine into the sector buffer RETURN: Length of header created... *************************************************************************/ void PS_Stream::CreateSysHeader ( Sys_header_struc *sys_header, unsigned int rate_bound, bool fixed, int CSPS, bool audio_lock, bool video_lock, vector &streams ) { uint8_t *index; uint8_t *len_index; int system_header_size; index = sys_header->buf; int video_bound = 0; int audio_bound = 0; std::vector::iterator str; for( str = streams.begin(); str < streams.end(); ++str ) { switch( ((*str)->stream_id & 0xf0) ) { case 0xe0 : // MPEG Video ++video_bound; break; case 0xb0 : // DVD seems to use these stream id in // system headers for buffer size counts if( (*str)->stream_id == 0xb9 ) ++video_bound; if( (*str)->stream_id == 0xbd ) ++audio_bound; break; case 0xc0 : ++audio_bound; // MPEG Audio break; default : break; } } /* if we are not using both streams, we should clear some options here */ *(index++) = static_cast((SYS_HEADER_START)>>24); *(index++) = static_cast((SYS_HEADER_START & 0x00ff0000)>>16); *(index++) = static_cast((SYS_HEADER_START & 0x0000ff00)>>8); *(index++) = static_cast(SYS_HEADER_START & 0x000000ff); len_index = index; /* Skip length field for now... */ index +=2; *(index++) = static_cast(0x80 | (rate_bound >>15)); *(index++) = static_cast(0xff & (rate_bound >> 7)); *(index++) = static_cast(0x01 | ((rate_bound & 0x7f)<<1)); *(index++) = static_cast((audio_bound << 2)|(fixed << 1)|CSPS); *(index++) = static_cast((audio_lock << 7)| (video_lock << 6)|0x20|video_bound); *(index++) = static_cast(RESERVED_BYTE); for( str = streams.begin(); str < streams.end(); ++str ) { *(index++) = (*str)->stream_id; *(index++) = static_cast (0xc0 | ((*str)->BufferScale() << 5) | ((*str)->BufferSizeCode() >> 8)); *(index++) = static_cast((*str)->BufferSizeCode() & 0xff); } system_header_size = (index - sys_header->buf); len_index[0] = static_cast((system_header_size-6) >> 8); len_index[1] = static_cast((system_header_size-6) & 0xff); sys_header->length = system_header_size; } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/Makefile.in0000644000175000017500000012647712217306407017426 0ustar glowwormglowworm# Makefile.in generated by automake 1.12.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Process this file with Automake to produce Makefile.in VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = mplex$(EXEEXT) # Need to do this because of the way utils/altivec/* was done - it makes a # reference to a function (next_larger_quant) in mpeg2enc's library. OSX # doesn't care but Fedora4/PPC's linker gives an undefined symbol error @HAVE_ALTIVEC_TRUE@am__append_1 = $(top_builddir)/mpeg2enc/libmpeg2encpp.la subdir = mplex DIST_COMMON = README $(libmplex_include_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(top_srcdir)/depcomp COPYING TODO ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(libmplex_includedir)" LTLIBRARIES = $(lib_LTLIBRARIES) libmplex2_la_DEPENDENCIES = $(top_builddir)/utils/libmjpegutils.la \ $(am__append_1) am_libmplex2_la_OBJECTS = libmplex2_la-ac3strm_in.lo \ libmplex2_la-audiostrm_out.lo libmplex2_la-bits.lo \ libmplex2_la-decodebufmodel.lo libmplex2_la-dtsstrm_in.lo \ libmplex2_la-inputstrm.lo libmplex2_la-interact.lo \ libmplex2_la-lpcmstrm_in.lo libmplex2_la-mpastrm_in.lo \ libmplex2_la-multiplexor.lo libmplex2_la-padstrm.lo \ libmplex2_la-stillsstream.lo libmplex2_la-stream_params.lo \ libmplex2_la-systems.lo libmplex2_la-videostrm_in.lo \ libmplex2_la-videostrm_out.lo libmplex2_la-subpstream.lo libmplex2_la_OBJECTS = $(am_libmplex2_la_OBJECTS) libmplex2_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(libmplex2_la_CXXFLAGS) \ $(CXXFLAGS) $(libmplex2_la_LDFLAGS) $(LDFLAGS) -o $@ PROGRAMS = $(bin_PROGRAMS) am_mplex_OBJECTS = main.$(OBJEXT) mplex_OBJECTS = $(am_mplex_OBJECTS) am__DEPENDENCIES_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libmplex2_la_SOURCES) $(mplex_SOURCES) DIST_SOURCES = $(libmplex2_la_SOURCES) $(mplex_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(libmplex_include_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALTIVEC_EXTRA_LIBS = @ALTIVEC_EXTRA_LIBS@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDV_CFLAGS = @LIBDV_CFLAGS@ LIBDV_LIBS = @LIBDV_LIBS@ LIBGETOPT_LIB = @LIBGETOPT_LIB@ LIBM_LIBS = @LIBM_LIBS@ LIBOBJS = @LIBOBJS@ LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ LIBPNG_LIBS = @LIBPNG_LIBS@ LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@ LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ LT_STATIC = @LT_STATIC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROGRAM_NOPIC = @PROGRAM_NOPIC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ SDLgfx_LIBS = @SDLgfx_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ V4LCONF_LIBS = @V4LCONF_LIBS@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ README \ INSTRUCT \ mpeg_systems_paper_0.99.ps.gz \ Doxyfile \ TODO MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I $(top_srcdir) -I $(top_srcdir)/utils lib_LTLIBRARIES = libmplex2.la libmplex2_la_SOURCES = \ ac3strm_in.cpp \ audiostrm_out.cpp \ bits.cpp \ decodebufmodel.cpp \ dtsstrm_in.cpp \ inputstrm.cpp \ interact.cpp \ lpcmstrm_in.cpp \ mpastrm_in.cpp \ multiplexor.cpp \ padstrm.cpp \ stillsstream.cpp \ stream_params.cpp \ systems.cpp \ videostrm_in.cpp \ videostrm_out.cpp \ subpstream.cpp libmplex_includedir = $(pkgincludedir)/mplex libmplex_include_HEADERS = \ audiostrm.hpp \ aunit.hpp \ aunitbuffer.hpp \ bits.hpp \ decodebufmodel.hpp \ inputstrm.hpp \ interact.hpp \ mplexconsts.hpp \ multiplexor.hpp \ outputstrm.hpp \ padstrm.hpp \ stillsstream.hpp \ stream_params.hpp \ systems.hpp \ videostrm.hpp libmplex2_la_LDFLAGS = \ $(LT_STATIC) \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -release $(LT_RELEASE) $(EXTRA_LDFLAGS) libmplex2_la_LIBADD = $(top_builddir)/utils/libmjpegutils.la \ $(am__append_1) libmplex2_la_CXXFLAGS = mplex_SOURCES = main.cpp mplex_DEPENDENCIES = libmplex2.la mplex_LDADD = libmplex2.la @LIBGETOPT_LIB@ $(LIBM_LIBS) all: all-am .SUFFIXES: .SUFFIXES: .cpp .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu mplex/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu mplex/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libmplex2.la: $(libmplex2_la_OBJECTS) $(libmplex2_la_DEPENDENCIES) $(EXTRA_libmplex2_la_DEPENDENCIES) $(libmplex2_la_LINK) -rpath $(libdir) $(libmplex2_la_OBJECTS) $(libmplex2_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list mplex$(EXEEXT): $(mplex_OBJECTS) $(mplex_DEPENDENCIES) $(EXTRA_mplex_DEPENDENCIES) @rm -f mplex$(EXEEXT) $(CXXLINK) $(mplex_OBJECTS) $(mplex_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmplex2_la-ac3strm_in.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmplex2_la-audiostrm_out.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmplex2_la-bits.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmplex2_la-decodebufmodel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmplex2_la-dtsstrm_in.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmplex2_la-inputstrm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmplex2_la-interact.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmplex2_la-lpcmstrm_in.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmplex2_la-mpastrm_in.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmplex2_la-multiplexor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmplex2_la-padstrm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmplex2_la-stillsstream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmplex2_la-stream_params.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmplex2_la-subpstream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmplex2_la-systems.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmplex2_la-videostrm_in.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmplex2_la-videostrm_out.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< libmplex2_la-ac3strm_in.lo: ac3strm_in.cpp @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -MT libmplex2_la-ac3strm_in.lo -MD -MP -MF $(DEPDIR)/libmplex2_la-ac3strm_in.Tpo -c -o libmplex2_la-ac3strm_in.lo `test -f 'ac3strm_in.cpp' || echo '$(srcdir)/'`ac3strm_in.cpp @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libmplex2_la-ac3strm_in.Tpo $(DEPDIR)/libmplex2_la-ac3strm_in.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='ac3strm_in.cpp' object='libmplex2_la-ac3strm_in.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -c -o libmplex2_la-ac3strm_in.lo `test -f 'ac3strm_in.cpp' || echo '$(srcdir)/'`ac3strm_in.cpp libmplex2_la-audiostrm_out.lo: audiostrm_out.cpp @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -MT libmplex2_la-audiostrm_out.lo -MD -MP -MF $(DEPDIR)/libmplex2_la-audiostrm_out.Tpo -c -o libmplex2_la-audiostrm_out.lo `test -f 'audiostrm_out.cpp' || echo '$(srcdir)/'`audiostrm_out.cpp @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libmplex2_la-audiostrm_out.Tpo $(DEPDIR)/libmplex2_la-audiostrm_out.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='audiostrm_out.cpp' object='libmplex2_la-audiostrm_out.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -c -o libmplex2_la-audiostrm_out.lo `test -f 'audiostrm_out.cpp' || echo '$(srcdir)/'`audiostrm_out.cpp libmplex2_la-bits.lo: bits.cpp @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -MT libmplex2_la-bits.lo -MD -MP -MF $(DEPDIR)/libmplex2_la-bits.Tpo -c -o libmplex2_la-bits.lo `test -f 'bits.cpp' || echo '$(srcdir)/'`bits.cpp @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libmplex2_la-bits.Tpo $(DEPDIR)/libmplex2_la-bits.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='bits.cpp' object='libmplex2_la-bits.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -c -o libmplex2_la-bits.lo `test -f 'bits.cpp' || echo '$(srcdir)/'`bits.cpp libmplex2_la-decodebufmodel.lo: decodebufmodel.cpp @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -MT libmplex2_la-decodebufmodel.lo -MD -MP -MF $(DEPDIR)/libmplex2_la-decodebufmodel.Tpo -c -o libmplex2_la-decodebufmodel.lo `test -f 'decodebufmodel.cpp' || echo '$(srcdir)/'`decodebufmodel.cpp @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libmplex2_la-decodebufmodel.Tpo $(DEPDIR)/libmplex2_la-decodebufmodel.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='decodebufmodel.cpp' object='libmplex2_la-decodebufmodel.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -c -o libmplex2_la-decodebufmodel.lo `test -f 'decodebufmodel.cpp' || echo '$(srcdir)/'`decodebufmodel.cpp libmplex2_la-dtsstrm_in.lo: dtsstrm_in.cpp @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -MT libmplex2_la-dtsstrm_in.lo -MD -MP -MF $(DEPDIR)/libmplex2_la-dtsstrm_in.Tpo -c -o libmplex2_la-dtsstrm_in.lo `test -f 'dtsstrm_in.cpp' || echo '$(srcdir)/'`dtsstrm_in.cpp @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libmplex2_la-dtsstrm_in.Tpo $(DEPDIR)/libmplex2_la-dtsstrm_in.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dtsstrm_in.cpp' object='libmplex2_la-dtsstrm_in.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -c -o libmplex2_la-dtsstrm_in.lo `test -f 'dtsstrm_in.cpp' || echo '$(srcdir)/'`dtsstrm_in.cpp libmplex2_la-inputstrm.lo: inputstrm.cpp @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -MT libmplex2_la-inputstrm.lo -MD -MP -MF $(DEPDIR)/libmplex2_la-inputstrm.Tpo -c -o libmplex2_la-inputstrm.lo `test -f 'inputstrm.cpp' || echo '$(srcdir)/'`inputstrm.cpp @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libmplex2_la-inputstrm.Tpo $(DEPDIR)/libmplex2_la-inputstrm.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='inputstrm.cpp' object='libmplex2_la-inputstrm.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -c -o libmplex2_la-inputstrm.lo `test -f 'inputstrm.cpp' || echo '$(srcdir)/'`inputstrm.cpp libmplex2_la-interact.lo: interact.cpp @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -MT libmplex2_la-interact.lo -MD -MP -MF $(DEPDIR)/libmplex2_la-interact.Tpo -c -o libmplex2_la-interact.lo `test -f 'interact.cpp' || echo '$(srcdir)/'`interact.cpp @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libmplex2_la-interact.Tpo $(DEPDIR)/libmplex2_la-interact.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='interact.cpp' object='libmplex2_la-interact.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -c -o libmplex2_la-interact.lo `test -f 'interact.cpp' || echo '$(srcdir)/'`interact.cpp libmplex2_la-lpcmstrm_in.lo: lpcmstrm_in.cpp @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -MT libmplex2_la-lpcmstrm_in.lo -MD -MP -MF $(DEPDIR)/libmplex2_la-lpcmstrm_in.Tpo -c -o libmplex2_la-lpcmstrm_in.lo `test -f 'lpcmstrm_in.cpp' || echo '$(srcdir)/'`lpcmstrm_in.cpp @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libmplex2_la-lpcmstrm_in.Tpo $(DEPDIR)/libmplex2_la-lpcmstrm_in.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='lpcmstrm_in.cpp' object='libmplex2_la-lpcmstrm_in.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -c -o libmplex2_la-lpcmstrm_in.lo `test -f 'lpcmstrm_in.cpp' || echo '$(srcdir)/'`lpcmstrm_in.cpp libmplex2_la-mpastrm_in.lo: mpastrm_in.cpp @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -MT libmplex2_la-mpastrm_in.lo -MD -MP -MF $(DEPDIR)/libmplex2_la-mpastrm_in.Tpo -c -o libmplex2_la-mpastrm_in.lo `test -f 'mpastrm_in.cpp' || echo '$(srcdir)/'`mpastrm_in.cpp @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libmplex2_la-mpastrm_in.Tpo $(DEPDIR)/libmplex2_la-mpastrm_in.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='mpastrm_in.cpp' object='libmplex2_la-mpastrm_in.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -c -o libmplex2_la-mpastrm_in.lo `test -f 'mpastrm_in.cpp' || echo '$(srcdir)/'`mpastrm_in.cpp libmplex2_la-multiplexor.lo: multiplexor.cpp @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -MT libmplex2_la-multiplexor.lo -MD -MP -MF $(DEPDIR)/libmplex2_la-multiplexor.Tpo -c -o libmplex2_la-multiplexor.lo `test -f 'multiplexor.cpp' || echo '$(srcdir)/'`multiplexor.cpp @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libmplex2_la-multiplexor.Tpo $(DEPDIR)/libmplex2_la-multiplexor.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='multiplexor.cpp' object='libmplex2_la-multiplexor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -c -o libmplex2_la-multiplexor.lo `test -f 'multiplexor.cpp' || echo '$(srcdir)/'`multiplexor.cpp libmplex2_la-padstrm.lo: padstrm.cpp @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -MT libmplex2_la-padstrm.lo -MD -MP -MF $(DEPDIR)/libmplex2_la-padstrm.Tpo -c -o libmplex2_la-padstrm.lo `test -f 'padstrm.cpp' || echo '$(srcdir)/'`padstrm.cpp @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libmplex2_la-padstrm.Tpo $(DEPDIR)/libmplex2_la-padstrm.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='padstrm.cpp' object='libmplex2_la-padstrm.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -c -o libmplex2_la-padstrm.lo `test -f 'padstrm.cpp' || echo '$(srcdir)/'`padstrm.cpp libmplex2_la-stillsstream.lo: stillsstream.cpp @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -MT libmplex2_la-stillsstream.lo -MD -MP -MF $(DEPDIR)/libmplex2_la-stillsstream.Tpo -c -o libmplex2_la-stillsstream.lo `test -f 'stillsstream.cpp' || echo '$(srcdir)/'`stillsstream.cpp @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libmplex2_la-stillsstream.Tpo $(DEPDIR)/libmplex2_la-stillsstream.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='stillsstream.cpp' object='libmplex2_la-stillsstream.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -c -o libmplex2_la-stillsstream.lo `test -f 'stillsstream.cpp' || echo '$(srcdir)/'`stillsstream.cpp libmplex2_la-stream_params.lo: stream_params.cpp @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -MT libmplex2_la-stream_params.lo -MD -MP -MF $(DEPDIR)/libmplex2_la-stream_params.Tpo -c -o libmplex2_la-stream_params.lo `test -f 'stream_params.cpp' || echo '$(srcdir)/'`stream_params.cpp @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libmplex2_la-stream_params.Tpo $(DEPDIR)/libmplex2_la-stream_params.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='stream_params.cpp' object='libmplex2_la-stream_params.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -c -o libmplex2_la-stream_params.lo `test -f 'stream_params.cpp' || echo '$(srcdir)/'`stream_params.cpp libmplex2_la-systems.lo: systems.cpp @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -MT libmplex2_la-systems.lo -MD -MP -MF $(DEPDIR)/libmplex2_la-systems.Tpo -c -o libmplex2_la-systems.lo `test -f 'systems.cpp' || echo '$(srcdir)/'`systems.cpp @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libmplex2_la-systems.Tpo $(DEPDIR)/libmplex2_la-systems.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='systems.cpp' object='libmplex2_la-systems.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -c -o libmplex2_la-systems.lo `test -f 'systems.cpp' || echo '$(srcdir)/'`systems.cpp libmplex2_la-videostrm_in.lo: videostrm_in.cpp @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -MT libmplex2_la-videostrm_in.lo -MD -MP -MF $(DEPDIR)/libmplex2_la-videostrm_in.Tpo -c -o libmplex2_la-videostrm_in.lo `test -f 'videostrm_in.cpp' || echo '$(srcdir)/'`videostrm_in.cpp @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libmplex2_la-videostrm_in.Tpo $(DEPDIR)/libmplex2_la-videostrm_in.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='videostrm_in.cpp' object='libmplex2_la-videostrm_in.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -c -o libmplex2_la-videostrm_in.lo `test -f 'videostrm_in.cpp' || echo '$(srcdir)/'`videostrm_in.cpp libmplex2_la-videostrm_out.lo: videostrm_out.cpp @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -MT libmplex2_la-videostrm_out.lo -MD -MP -MF $(DEPDIR)/libmplex2_la-videostrm_out.Tpo -c -o libmplex2_la-videostrm_out.lo `test -f 'videostrm_out.cpp' || echo '$(srcdir)/'`videostrm_out.cpp @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libmplex2_la-videostrm_out.Tpo $(DEPDIR)/libmplex2_la-videostrm_out.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='videostrm_out.cpp' object='libmplex2_la-videostrm_out.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -c -o libmplex2_la-videostrm_out.lo `test -f 'videostrm_out.cpp' || echo '$(srcdir)/'`videostrm_out.cpp libmplex2_la-subpstream.lo: subpstream.cpp @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -MT libmplex2_la-subpstream.lo -MD -MP -MF $(DEPDIR)/libmplex2_la-subpstream.Tpo -c -o libmplex2_la-subpstream.lo `test -f 'subpstream.cpp' || echo '$(srcdir)/'`subpstream.cpp @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libmplex2_la-subpstream.Tpo $(DEPDIR)/libmplex2_la-subpstream.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='subpstream.cpp' object='libmplex2_la-subpstream.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmplex2_la_CXXFLAGS) $(CXXFLAGS) -c -o libmplex2_la-subpstream.lo `test -f 'subpstream.cpp' || echo '$(srcdir)/'`subpstream.cpp mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-libmplex_includeHEADERS: $(libmplex_include_HEADERS) @$(NORMAL_INSTALL) @list='$(libmplex_include_HEADERS)'; test -n "$(libmplex_includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libmplex_includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libmplex_includedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libmplex_includedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libmplex_includedir)" || exit $$?; \ done uninstall-libmplex_includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(libmplex_include_HEADERS)'; test -n "$(libmplex_includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libmplex_includedir)'; $(am__uninstall_files_from_dir) ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libmplex_includedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-libmplex_includeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libmplex_includeHEADERS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libLTLIBRARIES clean-libtool cscopelist \ ctags distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-libmplex_includeHEADERS install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-libLTLIBRARIES uninstall-libmplex_includeHEADERS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mjpegtools-2.1.0/mplex/stream_params.cpp0000644000175000017500000000550307771103762020715 0ustar glowwormglowworm/* * params.hpp: User specifiable parameters for various types of stream * * The CheckParams pseudo-constructors are constructed so that * they will only construct legal combinations of parameters. * * Copyright (C) 2002 Andrew Stevens * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "stream_params.hpp" #include "format_codes.h" LpcmParams *LpcmParams::Default(unsigned int mux_format) { return new LpcmParams(48000,2,16); } LpcmParams::LpcmParams( unsigned int samples, unsigned int chans, unsigned int bits ) : samples_per_sec( samples ), channels(chans), bits_per_sample(bits) { } LpcmParams *LpcmParams::Checked(unsigned int samples, unsigned int chans, unsigned int bits ) { if( samples != 48000 && samples != 96000 ) return 0; if( chans < 1 || chans > 7 ) return 0; if( bits != 16 && bits != 20 && bits != 24 ) return 0; return new LpcmParams(samples,chans,bits); } bool VideoParams::Force( unsigned int mux_format ) { unsigned int bufsiz; // // Handle formats that force the buffer size parameter to a // standard-conforming value // switch( mux_format ) { case MPEG_FORMAT_SVCD : bufsiz = 230; break; case MPEG_FORMAT_VCD : bufsiz = 46; break; case MPEG_FORMAT_DVD : case MPEG_FORMAT_DVD_NAV : bufsiz = 232; break; default : return false; } decode_buffer_size = bufsiz; return true; } VideoParams *VideoParams::Checked( unsigned int bufsiz) { if( bufsiz < 20 && bufsiz >= 4096 ) // In KB here... return 0; return new VideoParams(bufsiz); } VideoParams::VideoParams( unsigned int bufsiz ) : decode_buffer_size(bufsiz) { } VideoParams *VideoParams::Default(unsigned int mux_format) { unsigned int bufsiz; switch( mux_format ) { case MPEG_FORMAT_MPEG2 : case MPEG_FORMAT_SVCD : case MPEG_FORMAT_SVCD_NSR : case MPEG_FORMAT_SVCD_STILL : bufsiz = 230; break; case MPEG_FORMAT_DVD : case MPEG_FORMAT_DVD_NAV : bufsiz = 232; break; default : bufsiz = 46; } return new VideoParams(bufsiz); } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/main.cpp0000644000175000017500000004565511671067647017024 0ustar glowwormglowworm /************************************************************************* * @mainpage * mplex - General-purpose MPEG-1/2 multiplexer. * (C) 2000, 2001 Andrew Stevens * * Doxygen documentation and MPEG Z/Alpha multiplexing part by * Gernot Ziegler * Constructed using mplex - MPEG-1/SYSTEMS multiplexer as starting point * Copyright (C) 1994 1995 Christoph Moar * Siemens ZFE ST SN 11 / T SN 6 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *************************************************************************/ #include #include #ifdef HAVE_GETOPT_H #include #endif #include #include #include #include #if !defined(_WIN32) || defined(__MINGW32__) #include #endif #include #include #include "cpu_accel.h" #include "mjpeg_types.h" #include "mjpeg_logging.h" #include "mpegconsts.h" #include "interact.hpp" #include "bits.hpp" #include "outputstrm.hpp" #include "multiplexor.hpp" using std::auto_ptr; /************************************************************************* Command line wrapper. Basically, all the command line and file (actually pipe and FIFO is what would be more normal) I/O specific sub-classes Plus the top-level entry point. That's all!! *************************************************************************/ #if !defined(HAVE_LROUND) extern "C" { long lround(double x) { long l = ceil(x); return(l); } }; #endif class FileOutputStream : public OutputStream { public: FileOutputStream( const char *filename_pat ); virtual int Open( ); virtual void Close(); virtual uint64_t SegmentSize( ); virtual void NextSegment(); virtual void Write(uint8_t *data, unsigned int len); private: FILE *strm; char filename_pat[MAXPATHLEN]; char cur_filename[MAXPATHLEN]; }; FileOutputStream::FileOutputStream( const char *name_pat ) { strncpy( filename_pat, name_pat, MAXPATHLEN ); snprintf( cur_filename, MAXPATHLEN, filename_pat, segment_num ); } int FileOutputStream::Open() { segment_len = 0; strm = fopen( cur_filename, "wb" ); if( strm == NULL ) { mjpeg_error_exit1( "Could not open for writing: %s", cur_filename ); } return 0; } void FileOutputStream::Close() { fclose(strm); } uint64_t FileOutputStream::SegmentSize() { return segment_len; } void FileOutputStream::NextSegment( ) { auto_ptr prev_filename_buf( new char[strlen(cur_filename)+1] ); char *prev_filename = prev_filename_buf.get(); fclose(strm); ++segment_num; strcpy( prev_filename, cur_filename ); snprintf( cur_filename, MAXPATHLEN, filename_pat, segment_num ); if( strcmp( prev_filename, cur_filename ) == 0 ) { mjpeg_error_exit1( "Need to split output but there appears to be no %%d in the filename pattern %s", filename_pat ); } strm = fopen( cur_filename, "wb" ); if( strm == NULL ) { mjpeg_error_exit1( "Could not open for writing: %s", cur_filename ); } segment_len = 0; } void FileOutputStream::Write( uint8_t *buf, unsigned int len ) { if( fwrite( buf, 1, len, strm ) != len ) { mjpeg_error_exit1( "Failed write: %s", cur_filename ); } segment_len += static_cast(len); } /******************************** * * IFileBitStream - Input bit stream class for bit streams sourced * from standard file I/O (this of course *includes* network sockets, * fifo's, et al). * * OLAF: To hook into your PES reader/reconstructor you need to define * a class like this one, where 'ReadStreamBytes' calls you code to * generate the required number of bytes of ES data and transfer it * to the specified buffer. The logical way to do this would be to * inherit IBitStream as a base class of the top-level classes for the ES * reconstructors. * ********************************/ class IFileBitStream : public IBitStream { public: IFileBitStream( const char *bs_filename, unsigned int buf_size = BUFFER_SIZE); ~IFileBitStream(); private: FILE *fileh; char *filename; virtual size_t ReadStreamBytes( uint8_t *buf, size_t number ) { return fread(buf,sizeof(uint8_t), number, fileh ); } virtual bool EndOfStream() { return feof(fileh) != 0; } }; IFileBitStream::IFileBitStream( const char *bs_filename, unsigned int buf_size) : IBitStream() { if ((fileh = fopen(bs_filename, "rb")) == NULL) { mjpeg_error_exit1( "Unable to open file %s for reading.", bs_filename); } filename = strcpy( new char[strlen(bs_filename)+1], bs_filename ); streamname = filename; SetBufSize(buf_size); eobs = false; byteidx = 0; if (!ReadIntoBuffer()) { if (buffered==0) { mjpeg_error_exit1( "Unable to read from %s.", bs_filename); } } } /** Destructor: close the device containing the bit stream after a read process */ IFileBitStream::~IFileBitStream() { if (fileh) { fclose(fileh); delete filename; } fileh = 0; Release(); } /******************************* * * Command line job class - sets up a Multiplex Job based on command * line and File I/O... * ******************************/ class CmdLineMultiplexJob : public MultiplexJob { public: CmdLineMultiplexJob( unsigned int argc, char *argv[]); private: void InputStreamsFromCmdLine (unsigned int argc, char* argv[] ); void Usage(char *program_name); bool ParseVideoOpt( const char *optarg ); bool ParseLpcmOpt( const char *optarg ); bool ParseWorkaroundOpt( const char *optarg ); bool ParseTimeOffset( const char *optarg ); bool ParseSubtitleOptions( const char *optarg ); static const char short_options[]; #if defined(HAVE_GETOPT_LONG) static struct option long_options[]; #endif }; const char CmdLineMultiplexJob::short_options[] = "o:i:b:r:O:v:f:l:s:S:p:W:L:R:VCMhd:"; #if defined(HAVE_GETOPT_LONG) struct option CmdLineMultiplexJob::long_options[] = { { "verbose", 1, 0, 'v' }, { "vdr-index", 1, 0, 'i' }, { "format", 1, 0, 'f' }, { "mux-bitrate", 1, 0, 'r' }, { "video-buffer", 1, 0, 'b' }, { "lpcm-params", 1, 0, 'L' }, { "output", 1, 0, 'o' }, { "sync-offset", 1, 0, 'O' }, { "vbr", 0, 0, 'V' }, { "cbr", 0, 0, 'C' }, { "system-headers", 0, 0, 'h' }, { "ignore-seqend-markers", 0, 0, 'M' }, { "run-in", 1, 0, 'R' }, { "max-segment-size", 1, 0, 'S' }, { "mux-limit", 1, 0, 'l' }, { "packets-per-pack", 1, 0, 'p' }, { "sector-size", 1, 0, 's' }, { "workarounds", 1, 0, 'W' }, { "help", 0, 0, '?' }, { "subpicture-delay", 1, 0, 'd' }, { 0, 0, 0, 0 } }; #endif CmdLineMultiplexJob::CmdLineMultiplexJob(unsigned int argc, char *argv[]) : MultiplexJob() { int n; outfile_pattern = NULL; #if defined(HAVE_GETOPT_LONG) while( (n=getopt_long(argc,argv,short_options,long_options, NULL)) != -1 ) #else while( (n=getopt(argc,argv,short_options)) != -1 ) #endif { switch(n) { case 0 : break; case 'o' : outfile_pattern = optarg; break; case 'i' : vdr_index_pathname = optarg; break; case 'v' : verbose = atoi(optarg); if( verbose < 0 || verbose > 2 ) Usage(argv[0]); break; case 'V' : VBR = true; break; case 'C' : CBR = true; break; case 'h' : always_system_headers = true; break; case 'b' : if( ! ParseVideoOpt( optarg ) ) { mjpeg_error( "Illegal video decoder buffer size(s): %s", optarg ); Usage(argv[0]); } break; case 'L': if( ! ParseLpcmOpt( optarg ) ) { mjpeg_error( "Illegal LPCM option(s): %s", optarg ); Usage(argv[0]); } break; case 'r': data_rate = atoi(optarg); if( data_rate < 0 ) Usage(argv[0]); /* Convert from kbit/sec (user spec) to 50B/sec units... */ data_rate = (( data_rate * 1000 / 8 + 49) / 50 ) * 50; break; case 'R': run_in_frames = atoi(optarg); if( run_in_frames < 0 || run_in_frames > 100 ) Usage(argv[0]); break; case 'O': if( ! ParseTimeOffset(optarg) ) { mjpeg_error( "Time offset units if specified must: ms|s|mpt" ); Usage(argv[0]); } break; case 'l' : max_PTS = atoi(optarg); if( max_PTS < 1 ) Usage(argv[0]); break; case 'p' : packets_per_pack = atoi(optarg); if( packets_per_pack < 1 || packets_per_pack > 100 ) Usage(argv[0]); break; case 'f' : mux_format = atoi(optarg); if( mux_format < MPEG_FORMAT_MPEG1 || mux_format > MPEG_FORMAT_LAST ) Usage(argv[0]); break; case 's' : sector_size = atoi(optarg); if( sector_size < 256 || sector_size > 16384 ) Usage(argv[0]); break; case 'S' : max_segment_size = atoi(optarg); if( max_segment_size < 0 ) Usage(argv[0]); break; case 'M' : multifile_segment = true; break; case 'W' : if( ! ParseWorkaroundOpt( optarg ) ) { Usage(argv[0]); } break; case 'd' : if( ! ParseSubtitleOptions( optarg ) ) { mjpeg_error( "Illegal Subtitle option(s): %s", optarg ); Usage(argv[0]); } break; case '?' : default : Usage(argv[0]); break; } } if (argc - optind < 1 || outfile_pattern == NULL) { Usage(argv[0]); } (void)mjpeg_default_handler_verbosity(verbose); mjpeg_info( "mplex version %s (%s %s)",VERSION,MPLEX_VER,MPLEX_DATE ); InputStreamsFromCmdLine( argc-(optind-1), argv+optind-1); } /************************************************************************* Usage banner for the command line wrapper. *************************************************************************/ void CmdLineMultiplexJob::Usage(char *str) { fprintf( stderr, "mjpegtools mplex-2 version " VERSION " (" MPLEX_VER ")\n" "Usage: %s [params] -o ... \n" " %%d in the output file name is by segment count\n" " where possible params are:\n" "--verbose|-v num\n" " Level of verbosity. 0 = quiet, 1 = normal 2 = verbose/debug\n" "--format|-f fmt\n" " Set defaults for particular MPEG profiles\n" " [0 = Generic MPEG1, 1 = VCD, 2 = user-rate VCD, 3 = Generic MPEG2,\n" " 4 = SVCD, 5 = user-rate SVCD\n" " 6 = VCD Stills, 7 = SVCD Stills, 8 = DVD with NAV sectors, 9 = DVD]\n" "--mux-bitrate|-r num\n" " Specify data rate of output stream in kbit/sec\n" " (default 0=Compute from source streams)\n" "--video-buffer|-b num [, num...] \n" " Specifies decoder buffers size in kB. [ 20...2000]\n" "--lpcm-params | -L samppersec:chan:bits [, samppersec:chan:bits]\n" "--mux-limit|-l num\n" " Multiplex only num seconds of material (default 0=multiplex all)\n" "--sync-offset|-O num ms|s|mpt|c\n" " Specify offset of timestamps (video-audio) in mSec\n" "--subpicture-delay|-d delay [ms|s|mpt|c] [:stream-id] [, delay[:stream-id]]\n" " Specify offset of timestamps (video-subpicture) in msec (default) sec, mpt or clock-ticks\n" "--sector-size|-s num\n" " Specify sector size in bytes for generic formats [256..16384]\n" "--vbr|-V\n" " Force variable bit-rate video multiplexing\n" "--cbr|-C\n" " Force constant bit-rate video multiplexing\n" "--run-in|-R num\n" " Force a 'run-in' of exactly num frame intervals\n" "--packets-per-pack|-p num\n" " Number of packets per pack generic formats [1..100]\n" "--system-headers|-h\n" " Create System header in every pack in generic formats\n" "--max-segment-size|-S size\n" " Maximum size of output file(s) in Mbyte (default: 0) (no limit)\n" "--ignore-seqend-markers|-M\n" " Don't switch to a new output file if a sequence end marker\n" " is encountered in the input video.\n" "--vdr-index|-i \n" " Generate a VDR index file with the output stream\n" "--workaround|-W workaround [, workaround ]\n" "--help|-?\n" " Print this lot out!\n", str); exit (1); } bool CmdLineMultiplexJob::ParseSubtitleOptions( const char *optarg ) { double f; double persecond=1000.0; const char *e; uint64_t subtitle_offset; uint8_t stream_id; e=optarg-1; do { e++; subtitle_offset =0; persecond=1000.0; stream_id=0x20; // default f=strtod(e,const_cast(&e)); if( *e ) { while(isspace(*e)) e++; if(!strcmp(e,"ms")) { persecond=1000.0; e+=2;} else if(!strcmp(e,"s")) {persecond=1.0; e++;} else if(!strcmp(e,"mpt")){ persecond=90000.0;e+=3;} else if(!strcmp(e,"c")){ persecond=CLOCKS;e++;} } subtitle_offset = static_cast(f*CLOCKS/(persecond)); if( subtitle_offset < 0 ) subtitle_offset = 0; // always positive if (*e ==':'){ ++e; int nr; sscanf(e,"%hhd%n",&stream_id,&nr); e+=nr; mjpeg_info("Stream will be mapped to 0x%02hhX",stream_id); } subtitle_params.push_back(SubtitleStreamParams::Checked(subtitle_offset,stream_id)); } while (*e == ','); return true; } bool CmdLineMultiplexJob::ParseLpcmOpt( const char *optarg ) { char *endptr, *startptr; unsigned int samples_sec; unsigned int channels; unsigned int bits_sample; endptr = const_cast(optarg); do { startptr = endptr; samples_sec = static_cast(strtol(startptr, &endptr, 10)); if( startptr == endptr || *endptr != ':' ) return false; startptr = endptr+1; channels = static_cast(strtol(startptr, &endptr, 10)); if(startptr == endptr || *endptr != ':' ) return false; startptr = endptr+1; bits_sample = static_cast(strtol(startptr, &endptr, 10)); if( startptr == endptr ) return false; LpcmParams *params = LpcmParams::Checked( samples_sec, channels, bits_sample ); if( params == 0 ) return false; lpcm_param.push_back(params); if( *endptr == ',' ) ++endptr; } while( *endptr != '\0' ); return true; } bool CmdLineMultiplexJob::ParseWorkaroundOpt( const char *optarg ) { char *endptr, *startptr; endptr = const_cast(optarg); struct { const char *longname; char shortname; bool *flag; } flag_table[] = { { 0, '\0', 0 } }; for(;;) { // Find start of next flag... while( isspace(*endptr) || *endptr == ',' ) ++endptr; if( *endptr == '\0' ) break; startptr = endptr; // Find end of current flag... while( *endptr != ' ' && *endptr != ',' && *endptr != '\0' ) ++endptr; size_t len = endptr - startptr; int flag = 0; while( flag_table[flag].longname != 0 ) { if( (len == 1 && *startptr == flag_table[flag].shortname ) || strncmp( startptr, flag_table[flag].longname, len ) == 0 ) { *flag_table[flag].flag = true; break; } ++flag; } if( flag_table[flag].longname == 0 ) { std::string message( "Illegal work-around option: not one of " ); flag = 0; char sep[] = ","; while( flag_table[flag].longname != 0 ) { message += flag_table[flag].longname; message += sep; message += flag_table[flag].shortname; ++flag; if( flag_table[flag].longname != 0 ) message += sep; } mjpeg_error( message.c_str() ); return false; } } return true; } bool CmdLineMultiplexJob::ParseVideoOpt( const char *optarg ) { char *endptr, *startptr; unsigned int buffer_size; endptr = const_cast(optarg); do { startptr = endptr; buffer_size = static_cast(strtol(startptr, &endptr, 10)); if( startptr == endptr ) return false; VideoParams *params = VideoParams::Checked( buffer_size ); if( params == 0 ) return false; video_param.push_back(params); if( *endptr == ',' ) ++endptr; } while( *endptr != '\0' ); return true; } bool CmdLineMultiplexJob::ParseTimeOffset(const char *optarg) { double f; double persecond=1000.0; char *e; f=strtod(optarg,&e); if( *e ) { while(isspace(*e)) e++; if(!strcmp(e,"ms")) persecond=1000.0; else if(!strcmp(e,"s")) persecond=1.0; else if(!strcmp(e,"mpt")) persecond=90000.0; else if(!strcmp(e,"c")) persecond=CLOCKS; else return false; } video_offset = static_cast(f*CLOCKS/(persecond)); if( video_offset < 0 ) { audio_offset = - video_offset; video_offset = 0; } return true; } void CmdLineMultiplexJob::InputStreamsFromCmdLine(unsigned int argc, char* argv[] ) { vector inputs; unsigned int i; for( i = 1; i < argc; ++i ) { inputs.push_back( new IFileBitStream( argv[i] ) ); } SetupInputStreams( inputs ); } int main (int argc, char* argv[]) { CmdLineMultiplexJob job(argc,argv); FileOutputStream output( job.outfile_pattern ); FileOutputStream *index = job.vdr_index_pathname != 0 ? new FileOutputStream( job.vdr_index_pathname ) : 0; Multiplexor mux(job, output, index ); mux.Multiplex(); if( index != 0 ) delete index; return (0); } mjpegtools-2.1.0/mplex/ac3strm_in.cpp0000644000175000017500000003410611346706603020116 0ustar glowwormglowworm/* * ac3strm_in.c: AC3 Audio strem class members handling scanning and * buffering raw input stream. * * Copyright (C) 2001 Andrew Stevens * Copyright (C) 2000,2001 Brent Byeler for original header-structure * parsing code. * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "audiostrm.hpp" #include "interact.hpp" #include "multiplexor.hpp" //#define DEBUG_AC3_HEADERS #define AC3_SYNCWORD 0x0b77 #define AC3_PACKET_SAMPLES 1536 const unsigned int AC3Stream::default_buffer_size = 16*1024; /// table for the available AC3 bitrates static const unsigned int ac3_bitrate_index[32] = { 32,40,48,56,64,80,96,112,128,160,192, 224,256,320,384,448,512,576,640, 0,0,0,0,0,0,0,0,0,0,0,0,0 }; static const unsigned int ac3_frame_size[3][32] = { { 64,80,96,112,128,160,192,224,256,320,384, 448,512,640,768,896,1024, 1152,1280, 0,0,0,0,0,0,0,0,0,0,0,0,0 }, { 69,87,104,121,139,174,208,243,278,348,417, 487,557,696,835,975,1114, 1253,1393, 0,0,0,0,0,0,0,0,0,0,0,0,0 }, { 96,120,144,168,192,240,288,336,384,480,576, 672,768,960,1152,1344, 1536,1728,1920, 0,0,0,0,0,0,0,0,0,0,0,0,0 } }; /// table for the available AC3 frequencies static const unsigned int ac3_frequency[4] = { 48000, 44100, 32000, 0}; AC3Stream::AC3Stream(IBitStream &ibs, Multiplexor &into) : AudioStream( ibs, into ) { num_frames = 0; } bool AC3Stream::Probe(IBitStream &bs ) { return bs.GetBits(16) == AC3_SYNCWORD; } /************************************************************************* * * Reads initial stream parameters and displays feedback banner to users * @param stream_num AC3 substream ID *************************************************************************/ void AC3Stream::DisplayAc3HeaderInfo() { /* Some stuff to generate frame-header information */ printf( "bsid = %d\n", bs.GetBits(5) ); printf( "bsmode = 0x%1x\n", bs.GetBits(3) ); int acmode = bs.GetBits(3); int nfchans = 0; switch( acmode ) { case 0x0 : nfchans = 2; break; case 0x1 : nfchans = 1; break; case 0x2 : nfchans = 2; break; case 0x3 : case 0x4 : nfchans = 3; break; case 0x5 : case 0x6 : nfchans = 4; break; case 0x7 : nfchans = 5; break; } printf( "acmode = 0x%1x (%d channels)\n", acmode, nfchans ); if( (acmode & 0x1) && (acmode != 1 ) ) printf( "cmixlev = %d\n", bs.GetBits(2) ); if( (acmode & 0x4) ) printf( "smixlev = %d\n", bs.GetBits(2) ); if( acmode == 2 ) printf( "dsurr = %d\n", bs.GetBits(2) ); printf( "lfeon = %d\n", bs.GetBits(1) ); printf( "dialnorm = %02d\n", bs.GetBits(5) ); int compre = bs.GetBits(1); printf( "compre = %d\n", compre ); if( compre ) printf( "compr = %02d\n", bs.GetBits(8) ); int langcode = bs.GetBits(1); printf( "langcode = %d\n", langcode ); if( langcode ) printf( "langcod = 0x%02x\n", bs.GetBits(8) ); int audprodie = bs.GetBits(1); printf( "audprodie = %d\n", audprodie ); if( audprodie ) { printf( "mixlevel = 0x%02x\n", bs.GetBits(5) ); printf( "roomtyp = 0x%02x\n", bs.GetBits(2) ); } if( acmode == 0 ) { printf( "Skipping 1+1 mode parameters\n" ); bs.GetBits(5+1+8+1+8); if( bs.GetBits(1) ) bs.GetBits(7); } printf( "Copyright = %d\n", bs.GetBits(1) ); printf( "Original = %d\n", bs.GetBits(1) ); int timecod1e = bs.GetBits(1); if( timecod1e ) { printf( "timecod1 = 0x%03x\n", bs.GetBits(14) ); } int timecod2e = bs.GetBits(1); if( timecod2e ) { printf( "timecod2 = 0x%03x\n", bs.GetBits(14) ); } int addbsie = bs.GetBits(1); if( addbsie ) { printf( "addbsil = %02x\n", bs.GetBits(6) ); } // FROM This point on we're actually right into the actual audio block printf( "Audio block header...\n" ); printf( "blksw [ch] = %02x\n", bs.GetBits(nfchans) ); printf( "dithflg[ch] = %02x\n", bs.GetBits(nfchans) ); int dynrnge = bs.GetBits(1); printf( "Dynrange = %d\n", bs.GetBits(1) ); if( dynrnge ) { printf( "dynrng = %02x\n", bs.GetBits(8) ); } if( acmode == 0 && bs.GetBits(1) ) { printf( "dynrng2 = %02x\n", bs.GetBits(8) ); } int cplstre = bs.GetBits(1); printf( "cplstre = %d\n", cplstre ); int cplinu = 0; if( cplstre ) { cplinu = bs.GetBits(1); printf( "cplinu = %d\n", cplinu ); if( cplinu ) { printf( "Skipping cplinu=1 info...\n"); bs.GetBits(nfchans); if( acmode == 2 ) bs.GetBits(1); int cplbegf = bs.GetBits(4); int cplendf = bs.GetBits(4); bs.GetBits(3+cplbegf-cplendf); } } if( cplinu ) { printf( "Warning: no parser for coupling co-ordinates mess\n"); return; } if( acmode == 2 ) { int rmatstr = bs.GetBits(1); printf( "rmatstr = %d\n", rmatstr ); printf( "Warning: no parser for rematrixing...\n" ); } } void AC3Stream::Init ( const int _stream_num) { unsigned int framesize_code; stream_num = _stream_num; MuxStream::Init( PRIVATE_STR_1, 1, // Buffer scale default_buffer_size, false, muxinto.buffers_in_audio, muxinto.always_buffers_in_audio ); mjpeg_info ("Scanning for header info: AC3 Audio stream %02x (%s)", stream_num, bs.StreamName() ); AU_start = bs.bitcount(); if (bs.GetBits(16)==AC3_SYNCWORD) { num_syncword++; bs.GetBits(16); // CRC field frequency = bs.GetBits(2); // Sample rate code framesize_code = bs.GetBits(6); // Frame size code framesize = ac3_frame_size[frequency][framesize_code>>1]; framesize = (framesize_code&1) && frequency == 1 ? (framesize + 1) << 1: (framesize <<1); header_skip = 5; // Initially skipped past 5 bytes of header num_frames++; access_unit.start = AU_start; access_unit.length = framesize; mjpeg_info( "AC3 frame size = %d", framesize ); bit_rate = ac3_bitrate_index[framesize_code>>1]; samples_per_second = ac3_frequency[frequency]; /* Presentation time-stamping */ access_unit.PTS = static_cast(decoding_order) * static_cast(AC3_PACKET_SAMPLES) * static_cast(CLOCKS) / samples_per_second; access_unit.DTS = access_unit.PTS; access_unit.dorder = decoding_order; ++decoding_order; aunits.Append( access_unit ); } else { mjpeg_error ( "Invalid AC3 Audio stream header."); exit (1); } OutputHdrInfo(); } /// @returns the current bitrate unsigned int AC3Stream::NominalBitRate() { return bit_rate*1024; } /// Prefills the internal buffer for output multiplexing. /// @param frames_to_buffer the number of audio frames to read ahead void AC3Stream::FillAUbuffer(unsigned int frames_to_buffer ) { unsigned int framesize_code; last_buffered_AU += frames_to_buffer; mjpeg_debug( "Scanning %d AC3 audio frames to frame %d", frames_to_buffer, last_buffered_AU ); int skip; while( !bs.eos() && decoding_order < last_buffered_AU && !muxinto.AfterMaxPTS(access_unit.PTS) ) { skip=access_unit.length-header_skip; bs.SeekFwdBits(skip); prev_offset = AU_start; AU_start = bs.bitcount(); if( AU_start - prev_offset != access_unit.length*8 ) { mjpeg_warn( "Discarding incomplete final frame AC3 stream %d!", stream_num); aunits.DropLast(); --decoding_order; break; } /* Check we have reached the end of have another catenated stream to process before finishing ... */ if ( (syncword = bs.GetBits(16))!=AC3_SYNCWORD ) { if( !bs.eos() ) { mjpeg_error_exit1( "Can't find next AC3 frame: @ %lld we have %04x - broken bit-stream?", AU_start/8, syncword ); } break; } bs.GetBits(16); // CRC field bs.GetBits(2); // Sample rate code TOOD: check for change! framesize_code = bs.GetBits(6); framesize = ac3_frame_size[frequency][framesize_code>>1]; framesize = (framesize_code&1) && frequency == 1 ? (framesize + 1) << 1: (framesize <<1); access_unit.start = AU_start; access_unit.length = framesize; access_unit.PTS = static_cast(decoding_order) * static_cast(AC3_PACKET_SAMPLES) * static_cast(CLOCKS) / samples_per_second;; access_unit.DTS = access_unit.PTS; access_unit.dorder = decoding_order; decoding_order++; aunits.Append( access_unit ); num_frames++; num_syncword++; if (num_syncword >= old_frames+10 ) { mjpeg_debug ("Got %d frame headers.", num_syncword); old_frames=num_syncword; } } last_buffered_AU = decoding_order; eoscan = bs.eos() || muxinto.AfterMaxPTS(access_unit.PTS); } /// Closes the AC3 stream and prints some statistics. void AC3Stream::Close() { stream_length = AU_start >> 3; mjpeg_info ("AUDIO_STATISTICS: %02x", stream_id); mjpeg_info ("Audio stream length %lld bytes.", stream_length); mjpeg_info ("Frames : %8u", num_frames); } /************************************************************************* OutputAudioInfo gibt gesammelte Informationen zu den Audio Access Units aus. Prints information on audio access units *************************************************************************/ void AC3Stream::OutputHdrInfo () { mjpeg_info("AC3 AUDIO STREAM:"); mjpeg_info ("Bit rate : %8u bytes/sec (%3u kbit/sec)", bit_rate*128, bit_rate); if (frequency == 3) mjpeg_info ("Frequency : reserved"); else mjpeg_info ("Frequency : %d Hz", ac3_frequency[frequency]); } /** Reads the bytes neccessary to complete the current packet payload. @param to_read number of bytes to read @param dst byte buffer pointer to read to @returns the number of bytes read */ unsigned int AC3Stream::ReadPacketPayload(uint8_t *dst, unsigned int to_read) { bitcount_t read_start = bs.GetBytePos(); // Remember to change StreamHeaderLen if you write a different // length re-using this code... unsigned int bytes_read = bs.GetBytes( dst+4, to_read-4 ); assert( bytes_read > 0 ); // Should never try to read nothing bs.Flush( read_start ); clockticks decode_time; unsigned int first_header = (new_au_next_sec || au_unsent > bytes_read ) ? 0 : au_unsent; // BUG BUG BUG: how do we set the 1st header pointer if we have // the *middle* part of a large frame? assert( first_header+2 <= to_read ); unsigned int syncwords = 0; unsigned int bytes_muxed = bytes_read; if (bytes_muxed == 0 || MuxCompleted() ) { goto completion; } /* Work through what's left of the current AU and the following AU's updating the info until we reach a point where an AU had to be split between packets. NOTE: It *is* possible for this loop to iterate. The DTS/PTS field for the packet in this case would have been given the that for the first AU to start in the packet. */ decode_time = RequiredDTS(); while (au_unsent < bytes_muxed) { // BUG BUG BUG: if we ever had odd payload / packet size we might // split an AC3 frame in the middle of the syncword! assert( bytes_muxed > 1 ); bufmodel.Queued(au_unsent, decode_time); bytes_muxed -= au_unsent; if( new_au_next_sec ) ++syncwords; if( !NextAU() ) { goto completion; } new_au_next_sec = true; decode_time = RequiredDTS(); }; // We've now reached a point where the current AU overran or // fitted exactly. We need to distinguish the latter case // so we can record whether the next packet starts with an // existing AU or not - info we need to decide what PTS/DTS // info to write at the start of the next packet. if (au_unsent > bytes_muxed) { if( new_au_next_sec ) ++syncwords; bufmodel.Queued( bytes_muxed, decode_time); au_unsent -= bytes_muxed; new_au_next_sec = false; } else // if (au_unsent == bytes_muxed) { bufmodel.Queued(bytes_muxed, decode_time); if( new_au_next_sec ) ++syncwords; new_au_next_sec = NextAU(); } completion: // Generate the AC3 header... // Note the index counts from the low byte of the offset so // the smallest value is 1! dst[0] = AC3_SUB_STR_0 + stream_num; dst[1] = syncwords; dst[2] = (first_header+1)>>8; dst[3] = (first_header+1)&0xff; return bytes_read+4; } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/TODO0000644000175000017500000000317610025375117016036 0ustar glowwormglowwormTODO -Fix the bug with excessibe run-in in AC3 with small packets (no buffering time limit) validate using stereo-96-1min-1st-five.tar.gz - Replace the stream-specific ReadPacketPayload stuff with proper AUMuxed StreamHeaderSize based stuff - Replace the current peak rate estimation with one based on monitoring SCR and position in original stream every so-and-so many muxed out frames... - Support for muxing subtitles... - Reduce use of muxinto. by encapsulating run-out info... - Complete encapsulation by utilising stream interface rather than direct access to C-style file I/O - Need to add general facility for enforcing max STD buffer delay for audio and for warning if constraints for particular formats are exceeded. - Add checking for changed sequence parameters in mid-sequence sequence headers. - Currently the VCD HR Stills muxing stuff assumes *all* HR stills are the same size which is given in the initial vbv_buffer_size... This will work with mpeg2enc (which does this) but will fail fail fail with other streams. - Rebuild initial delay / sequence splitting DTS adjustment stuff so different streams can have different starting delays based on *stream* parameters. I.e. delay should be delegated to the elementary streams with only a sector_prefix offset set centrally. - Tidy code so Elementary streams handle their mux parameter initialisation from cmd-line parameters *not* the output stream. Eventually: - Multi-channel SVCD (MPEG audio extension) support. N.b. multi-track two-channel audio already works. - DVD muxing and generation of info to help authoring tools produce .IFO's etc. mjpegtools-2.1.0/mplex/inputstrm.hpp0000644000175000017500000001732010566454642020133 0ustar glowwormglowworm /* * inptstrm.hpp: Input stream classes for MPEG multiplexing * * Copyright (C) 2001 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __INPUTSTRM_H__ #define __INPUTSTRM_H__ #include #include #include #include #include "mjpeg_types.h" #include "mpegconsts.h" #include "format_codes.h" #include "mjpeg_logging.h" #include "mplexconsts.hpp" #include "bits.hpp" #include "aunitbuffer.hpp" #include "decodebufmodel.hpp" using std::vector; class Multiplexor; class MuxStream { public: MuxStream(); virtual ~MuxStream() {} void Init( const int strm_id, const unsigned int _buf_scale, const unsigned int buf_size, const unsigned int _zero_stuffing, const bool bufs_in_first, const bool always_bufs ); unsigned int BufferSizeCode(); inline unsigned int BufferSize() { return buffer_size; } inline unsigned int BufferScale() { return buffer_scale; } inline void SetMaxPacketData( unsigned int max ) { max_packet_data = max; } inline void SetMinPacketData( unsigned int min ) { min_packet_data = min; } inline unsigned int MaxPacketData() { return max_packet_data; } inline unsigned int MinPacketData() { return min_packet_data; } inline bool NewAUNextSector() { return new_au_next_sec; } // // Read the next packet payload (sub-stream headers plus // parsed and spliced stream data) for a packet with the // specified payload capacity. Update the AU info. // virtual unsigned int ReadPacketPayload(uint8_t *dst, unsigned int to_read) = 0; // // Return the size of the substream headers... // virtual unsigned int StreamHeaderSize() { return 0; } public: // TODO should go protected once encapsulation complete int stream_id; unsigned int buffer_scale; unsigned int buffer_size; DecodeBufModel bufmodel; unsigned int max_packet_data; unsigned int min_packet_data; unsigned int zero_stuffing; unsigned int nsec; unsigned int min_pes_header_len; bool buffers_in_header; bool always_buffers_in_header; bool new_au_next_sec; bool init; }; class DummyMuxStream : public MuxStream { public: DummyMuxStream( const int strm_id, const unsigned int buf_scale, unsigned int buf_size ) { stream_id = strm_id; buffer_scale = buf_scale; buffer_size = buf_size; } unsigned int ReadPacketPayload(uint8_t *dst, unsigned int to_read) { abort(); return 0; } }; class ElementaryStream : //public InputStream, public MuxStream { public: enum stream_kind { audio, video, dummy }; ElementaryStream( IBitStream &ibs, Multiplexor &into, stream_kind kind ); void SetBufSize( unsigned int buf_size ) { bs.SetBufSize( buf_size ); } virtual ~ElementaryStream (); inline stream_kind Kind() const { return kind; } virtual void Close() = 0; bool NextAU(); AUnit *Lookahead( unsigned int n = 0); unsigned int BytesToMuxAUEnd(unsigned int sector_transport_size); bool MuxCompleted(); virtual bool MuxPossible(clockticks currentSCR ); void DemuxedTo( clockticks SCR ); void SetTSOffset( clockticks baseTS ); void AllDemuxed(); inline stream_kind Kind() { return kind; } inline unsigned int BufferMin() { return buffer_min; } inline unsigned int BufferMax() { return buffer_max; } inline clockticks BaseDTS() { return au->DTS; }; inline clockticks BasePTS() { return au->PTS; }; inline int DecodeOrder() { return au->dorder; } inline clockticks RequiredDTS( const AUnit *unit ) { return unit->DTS + timestamp_delay; }; inline clockticks RequiredPTS( const AUnit *unit ) { return unit->PTS + timestamp_delay; }; inline clockticks RequiredDTS() { assert(au != 0 ); return RequiredDTS(au); }; inline clockticks RequiredPTS() { assert(au != 0 ); return RequiredPTS(au); }; inline clockticks NextRequiredDTS() { AUnit *next = Lookahead(); if( next != 0 ) return RequiredDTS(next); else return 0; }; inline clockticks NextRequiredPTS() { AUnit *next = Lookahead(); if( next != 0 ) return RequiredPTS(next); else return 0; }; void UpdateBufferMinMax(); void SetSyncOffset( clockticks timestamp_delay ); void BufferAndOutputSector(); inline bool BuffersInHeader() { return buffers_in_header; } virtual unsigned int NominalBitRate() = 0; virtual bool RunOutComplete() = 0; /****************************************************************** * Reads the stream data from actual input stream, updates decode * buffer model and current access unit information from the * look-ahead scanning buffer to account for bytes_muxed bytes being * muxed out. * TODO: No longer needs to be virtual * ******************************************************************/ virtual unsigned int ReadPacketPayload(uint8_t *dst, unsigned int to_read); /******************************************************************** * Update stream-specific mux state information to reflect muxing of * current AU. first_in_sector is set true if AU is first muxed into * the current sector. * *******************************************************************/ virtual void AUMuxed( bool first_in_sector ) {} /************************************************************** * The size of the stream-specific sub-header (if any) *************************************************************/ virtual unsigned int StreamHeaderSize() { return 0; } /***************************************************************** * Reads/generates the stream-specific sub-header for AUs muxed * since last call AUMuxed( true ); ****************************************************************/ virtual void ReadStreamHeader( uint8_t *dst, unsigned int len ) {} bitcount_t bytes_read; private: void AUBufferLookaheadFill( unsigned int look_ahead); protected: bitcount_t stream_length; IBitStream &bs; bool eoscan; unsigned int last_buffered_AU; // decode seq num of last buffered frame + 1 bitcount_t AU_start; uint32_t syncword; bitcount_t prev_offset; unsigned int decoding_order; unsigned int old_frames; //protected: public: virtual void FillAUbuffer(unsigned int frames_to_buffer) = 0; virtual void OutputSector() = 0; AUStream aunits; void Muxed( unsigned int bytes_muxed ); AUnit *au; clockticks timestamp_delay; unsigned int au_unsent; AUnit *OLDnext(); Multiplexor &muxinto; stream_kind kind; unsigned int buffer_min; unsigned int buffer_max; int FRAME_CHUNK; }; #endif // __INPUTSTRM_H__ /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/bits.cpp0000644000175000017500000002715610602035624017014 0ustar glowwormglowworm/** @file bits.cc, bit-level output */ /* Copyright (C) 2001, Andrew Stevens * * * 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. * */ #include #include #include #include #include #include "mjpeg_logging.h" #include "bits.hpp" const unsigned int BitStreamBuffering::BUFFER_SIZE = 64 * 1024; const unsigned int BitStreamBuffering::BUFFER_CEILING = 32 * 1024 * 1024; BitStreamBuffering::BitStreamBuffering() : bfr(0), bfr_size(0), buffered(0) { } /***** * * Pseudo-destructor. Frees the internal buffer and marks buffer as * empty. * *****/ void BitStreamBuffering::Release() { if( bfr != 0) delete [] bfr; bfr = 0; bfr_size = 0; buffered = 0; } /***** * * Empty the buffer. * *****/ void BitStreamBuffering::Empty() { buffered = 0; } /** sets the internal buffer size. @param new_buf_size requests new internal buffer size */ void BitStreamBuffering::SetBufSize( unsigned int new_buf_size) { // // If size has changed and we won't lose buffered data // we adjust the buffer size, otherwise we ignore the request // if( new_buf_size > BUFFER_CEILING ) { mjpeg_error_exit1("INTERNAL ERROR: additional data required but " " input buffer size would exceed ceiling"); } if( new_buf_size > buffered && bfr_size != new_buf_size ) { uint8_t *new_buf = new uint8_t[new_buf_size]; memcpy( new_buf, bfr, static_cast(buffered) ); if( bfr != 0 ) delete [] bfr; bfr_size = new_buf_size; bfr = new_buf; } } /**************************** * * Return the pointer to where (after, if necessary extending the * buffer) up to to_append bytes may be appended to the buffered bytes * ****************************/ uint8_t *BitStreamBuffering::StartAppendPoint( unsigned int to_append ) { unsigned int resize_size = bfr_size; assert( resize_size != 0 ); while( resize_size - buffered < to_append ) { resize_size *= 2; } if( resize_size != bfr_size ) SetBufSize( resize_size ); return bfr+buffered; } /** Refills an IBitStream's input buffer based on the internal variables buffered and bfr_size. Strategy: we read 1/4 of a buffer, always. */ bool IBitStream::ReadIntoBuffer(unsigned int to_read) { size_t i; unsigned int read_pow2 = BUFFER_SIZE/4; while( read_pow2 < to_read ) read_pow2 <<= 1; i = ReadStreamBytes( StartAppendPoint(read_pow2), static_cast(read_pow2) ); //i = fread(StartAppendPoint(read_pow2), sizeof(uint8_t), // static_cast(read_pow2), fileh); Appended(static_cast(i)); if ( i == 0 ) { eobs = true; return false; } return true; } #define masks(idx) (1<<(idx)) /*read 1 bit from the bit stream @returns the read bit, 0 on EOF */ uint32_t IBitStream::Get1Bit() { unsigned int bit; if (eobs) return 0; bit = (bfr[byteidx] & masks(bitidx - 1)) >> (bitidx - 1); bitreadpos++; bitidx--; if (!bitidx) { bitidx = 8; byteidx++; if (byteidx == buffered) { ReadIntoBuffer(); } } return bit; } /*read N bits from the bit stream @returns the read bits, 0 on EOF */ uint32_t IBitStream::GetBits(int N) { uint32_t val = 0; int i = N; unsigned int j; // Optimize: we are on byte boundary and want to read multiple of bytes! if ((bitidx == 8) && ((N & 7) == 0)) { i = N >> 3; while (i > 0) { if (eobs) return 0; val = (val << 8) | bfr[byteidx]; byteidx++; bitreadpos += 8; if (byteidx == buffered) { ReadIntoBuffer(); } i--; } } else { while (i > 0) { if (eobs) return 0; j = (bfr[byteidx] & masks(bitidx - 1)) >> (bitidx - 1); bitreadpos++; bitidx--; if (!bitidx) { bitidx = 8; byteidx++; if (byteidx == buffered) { ReadIntoBuffer(); } } val = (val << 1) | j; i--; } } return val; } /** This function seeks for a byte aligned sync word (max 32 bits) in the bit stream and places the bit stream pointer right after the sync. This function returns 1 if the sync was found otherwise it returns 0 @param sync the sync word to search for @param N the number of bits to retrieve @param lim number of bytes to search through @returns false on error */ bool IBitStream::SeekSync(uint32_t sync, int N, int lim) { uint32_t val, val1; uint32_t maxi = ((1U<= buffered && !eobs) { ReadIntoBuffer( req_byteidx - (buffered-1) ); } eobs = ( req_byteidx >= buffered ); if( eobs ) bitreadpos += (buffered - byteidx)*8; else bitreadpos += bytes_to_seek_fwd*8; byteidx = req_byteidx; } /** Flushes all read input up-to *but not including* byte flush_upto. @param flush_to the number of bits to flush */ void IBitStream::Flush(bitcount_t flush_upto ) { if( flush_upto > bfr_start+buffered ) mjpeg_error_exit1("INTERNAL ERROR: attempt to flush input beyond buffered amount" ); if( flush_upto < bfr_start ) mjpeg_error_exit1("INTERNAL ERROR: attempt to flush input stream before first buffered byte %lld last is %lld", flush_upto, bfr_start ); unsigned int bytes_to_flush = static_cast(flush_upto - bfr_start); // // Don't bother actually flushing until a good fraction of a buffer // will be cleared. // if( bytes_to_flush < bfr_size/2 ) return; buffered -= bytes_to_flush; bfr_start = flush_upto; byteidx -= bytes_to_flush; memmove( bfr, bfr+bytes_to_flush, static_cast(buffered)); } /** Undo scanning / reading N.b buffer *must not* be flushed between prepareundo and undochanges. @param undo handle to store the undo information */ void IBitStream::PrepareUndo( IBitStreamUndo &undo) { undo = *(static_cast(this)); } /** Undoes changes committed to an IBitStream. @param undo handle to retrieve the undo information */ void IBitStream::UndoChanges( IBitStreamUndo &undo) { *(static_cast(this)) = undo; } /** Read a number bytes over an IBitStream, using the buffer. @param dst buffer to read to @param length the number of bytes to read */ unsigned int IBitStream::GetBytes(uint8_t *dst, unsigned int length) { unsigned int to_read = length; if( bytereadpos < bfr_start) mjpeg_error_exit1("INTERNAL ERROR: access to input stream buffer @ %lld: before first buffered byte (%lld)", bytereadpos, bfr_start ); if( bytereadpos+length > bfr_start+buffered ) { if( !EndOfStream() && !scandone ) { mjpeg_error("INTERNAL ERROR: access to input stream buffer beyond last buffered byte @POS=%lld END=%d REQ=%lld + %d bytes", bytereadpos, buffered, bytereadpos-bfr_start, length ); abort(); } to_read = static_cast( (bfr_start+buffered)- bytereadpos ); } memcpy( dst, bfr+(static_cast( bytereadpos-bfr_start)), to_read); // We only ever flush up to the start of a read as we // have only scanned up to a header *beginning* a block that is then // read //flush( bytereadpos ); bytereadpos += to_read; return to_read; } /***** * * Bitstream reading is complete... * * Currently mainly there to allow Bug detection. Doesn't actually *do* anything! * *****/ void IBitStream::ScanDone() { scandone = true; } #ifdef REDUNDANT_CODE /** Initialize buffer, call once before first putbits or alignbits. @param bs_filename output filename @param buf_size size of the temporary output buffer to use */ void OBitStream::open(char *bs_filename, unsigned int buf_size) { if ((fileh = fopen(bs_filename, "wb")) == NULL) { mjpeg_error_exit1( "Unable to open file %s for writing; %s", bs_filename, strerror(errno)); } filename = strcpy( new char[strlen(bs_filename)+1], bs_filename ); SetBufSize(buf_size); // Save multiple buffering... setvbuf(fileh, 0, _IONBF, 0 ); bitidx = 8; byteidx = 0; bitwritepos = 0LL; outbyte = 0; } /** Closes the OBitStream. Flushes the output buffer and closes the output file if one was open. */ void OBitStream::close() { if (fileh) { if (byteidx != 0) fwrite(bfr, sizeof(uint8_t), byteidx, fileh); fclose(fileh); delete filename; fileh = NULL; } } /** Puts a byte into the OBitStream. Puts the byte into the internal buffer; if the buffer is full, it flushes the buffer to disk. */ void OBitStream::putbyte() { bfr[byteidx++] = outbyte; if (byteidx == bfr_size) { if (fwrite(bfr, sizeof(uint8_t), bfr_size, fileh) != bfr_size) mjpeg_error_exit1( "Write failed: %s", strerror(errno)); byteidx = 0; } bitidx = 8; } /** write rightmost n (0<=n<=32) bits of val to outfile @param val value to write bitwise @param n number of bits to write */ void OBitStream::putbits(uint32_t val, int n) { int i; unsigned int mask; bitwritepos += n; while( n >= bitidx ) { outbyte = (outbyte<> (n-bitidx)) & ((1u< 0 ) { bitidx -= n; outbyte = val & ((1u<>= 1; /* select next bit */ bitidx--; if (bitidx == 0) /* 8 bit buffer full */ putbyte(); } #endif } /** write rightmost bit of val to outfile @param val value to write one bit of */ void OBitStream::put1bit(int val) { ++bitwritepos; outbyte = (outbyte<<1) | (val & 0x1); --bitidx; if (bitidx == 0) /* 8 bit buffer full */ putbyte(); } /** zero bit stuffing to next byte boundary (5.2.3, 6.2.1) */ void OBitStream::alignbits() { if (bitidx != 8) putbits( 0, bitidx); flush_bytes(); } #endif /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/subpstream.cpp0000644000175000017500000001744211614717215020244 0ustar glowwormglowworm// // C++ Implementation: subpstream // // Description: // // // Author: grotti , (C) 2010 // // Copyright: See COPYING file that comes with this distribution // Most of the code is stolen from ac3stream.cpp // // #include #include #include #include #include "audiostrm.hpp" #include "interact.hpp" #include "multiplexor.hpp" // minimum version code for subtitle stream that // can be handled by the program #define MIN_VERSION_CODE 0x00030000 // common part of the subtitle header struct for major version 3 // taken from subtitle2vobsub typedef struct { unsigned int header_length; unsigned int header_version; unsigned int payload_length; unsigned int lpts; double rpts; // version 0x00030001 unsigned int discont_ctr; } subtitle_header_v3_t; typedef struct { char marker[8]; subtitle_header_v3_t header; } vobsub_header; static unsigned int minor_version(unsigned int version) { // bit 0-15 contain the minor version number return version & 0xffff; } // get the major version number from the version code static unsigned int major_version(unsigned int version) { // bit 16-31 contain the major version number return version >> 16; } static const char* SUBPHEADER="SUBTITLE"; SUBPStream::SUBPStream(IBitStream &ibs, SubtitleStreamParams* subpparm, Multiplexor &into) : AudioStream( ibs, into ),parms(subpparm) { num_frames =0; initial_offset = -1; } bool SUBPStream::Probe(IBitStream &bs ) { //char *last_dot = strrchr( bs, '.' ); char buffer[20]; bs.GetBytes((uint8_t*)buffer,strlen(SUBPHEADER)); if (strncmp(buffer,SUBPHEADER,strlen(SUBPHEADER)) == 0) return true; return false; } void SUBPStream::Init(const int stream_num) { MuxStream::Init( PRIVATE_STR_1, 1, // Buffer scale 8192, // default buffer size false, muxinto.buffers_in_audio, muxinto.always_buffers_in_audio ); mjpeg_info ("Scanning for header info: Subpicture stream %02x (%s)", stream_num, bs.StreamName() ); sub_stream_id =parms->StreamId(); ParseAUBitwise(); } bool SUBPStream::ParseAUBitwise() { vobsub_header vobsub; uint8_t* ptr = reinterpret_cast (&vobsub); subtitle_header_v3_t &header = vobsub.header; char buffer[20]; int i; for (i=0; i0); bs.SeekFwdBits(skip_len); } uint8_t subpid; prev_offset = AU_start; AU_start = bs.bitcount(); // packet starts here... subpid = bs.GetBits(8); access_unit.start = AU_start; access_unit.length = header.payload_length; if(header.rpts > 0){ access_unit.PTS=header.rpts*300.0*90000.0; if (initial_offset == -1) { if (sub_stream_id == -1) sub_stream_id = subpid; mjpeg_info( "SUBTITLE id 0x%02X => 0x%02X", subpid,sub_stream_id); initial_offset = access_unit.PTS; mjpeg_info("Stream offset is : %lld (PTS)",access_unit.PTS); mjpeg_info("Initial offset is : %lld (PTS)",initial_offset); mjpeg_info("Cmd line offset is: %lld (PTS)",parms->Offset()); initial_offset -= parms->Offset(); mjpeg_info("Adjustment offset : %lld (PTS)",initial_offset); } access_unit.PTS-=initial_offset; mjpeg_debug("Subtitle: appending PTS/DTS (int64_t) %lld",access_unit.PTS); } else { // calculate the time from lpts mjpeg_info( "Subtitle: fallback to lpts", subpid); access_unit.PTS= (double)(header.lpts/300)/90000.0; } access_unit.DTS = access_unit.PTS; access_unit.dorder = decoding_order; mjpeg_debug("appending PTS/DTS %lld",access_unit.DTS); decoding_order++; aunits.Append( access_unit ); bs.SeekFwdBits(header.payload_length-1); num_frames++; return true; } void SUBPStream::Close() { stream_length = AU_start >> 3; mjpeg_info ("SUBTITLE STATISTICS: 0x%02x", sub_stream_id); mjpeg_info ("Subtitle stream length %lld bytes.", stream_length); mjpeg_info ("Nr. of subtitle packets:%d", num_frames); } void SUBPStream::FillAUbuffer(unsigned int frames_to_buffer) { uint32_t discont_ctr; last_buffered_AU += frames_to_buffer; mjpeg_debug( "Scanning %d Subpicture frames to frame %d", frames_to_buffer, last_buffered_AU ); prev_offset = AU_start; AU_start = bs.bitcount(); while (decoding_order < last_buffered_AU && !bs.eos() && !muxinto.AfterMaxPTS(access_unit.PTS)) { if (!ParseAUBitwise()) break; } last_buffered_AU = decoding_order; eoscan = bs.eos() || muxinto.AfterMaxPTS(access_unit.PTS); } unsigned int SUBPStream::ReadPacketPayload(uint8_t *dst, unsigned int to_read) { bitcount_t read_start = bs.GetBytePos(); mjpeg_debug( "SUBPStream called: ReadPacketPayload at 0x%08lld", read_start); vobsub_header vobsub; subtitle_header_v3_t &header = vobsub.header; bs.GetBytes((uint8_t*) &vobsub,sizeof(vobsub)); int16_t skip_len = header.header_length-sizeof(header); if (strncmp(vobsub.marker,SUBPHEADER,strlen(SUBPHEADER)) != 0) { mjpeg_error( "Subtitle: expected header %s!",SUBPHEADER); return 0; } assert (skip_len>=0); if (skip_len) { uint8_t* b = (uint8_t* ) malloc(skip_len); bs.GetBytes(b,skip_len); free (b); } unsigned int bytes_read = bs.GetBytes( dst, header.payload_length ); bs.Flush( read_start ); dst[0] = sub_stream_id; clockticks decode_time; unsigned int first_header = (new_au_next_sec || au_unsent > bytes_read ) ? 0 : au_unsent; // BUG BUG BUG: how do we set the 1st header pointer if we have // the *middle* part of a large frame? assert( first_header+2 <= to_read ); unsigned int syncwords = 0; unsigned int bytes_muxed = bytes_read; if (bytes_muxed == 0 || MuxCompleted() ) { goto completion; } /* Work through what's left of the current AU and the following AU's updating the info until we reach a point where an AU had to be split between packets. NOTE: It *is* possible for this loop to iterate. The DTS/PTS field for the packet in this case would have been given the that for the first AU to start in the packet. */ decode_time = RequiredDTS(); mjpeg_debug("SUBPStream: Required DTS is %lld",decode_time); while (au_unsent < bytes_muxed) { // BUG BUG BUG: if we ever had odd payload / packet size we might // split an AC3 frame in the middle of the syncword! assert( bytes_muxed > 1 ); bufmodel.Queued(au_unsent, decode_time); bytes_muxed -= au_unsent; if( new_au_next_sec ) ++syncwords; if( !NextAU() ) { goto completion; } new_au_next_sec = true; decode_time = RequiredDTS(); mjpeg_debug("Required DTS is %lld (while-loop)",decode_time); }; // We've now reached a point where the current AU overran or // fitted exactly. We need to distinguish the latter case // so we can record whether the next packet starts with an // existing AU or not - info we need to decide what PTS/DTS // info to write at the start of the next packet. if (au_unsent > bytes_muxed) { if( new_au_next_sec ) ++syncwords; bufmodel.Queued( bytes_muxed, decode_time); au_unsent -= bytes_muxed; new_au_next_sec = false; } else // if (au_unsent == bytes_muxed) { bufmodel.Queued(bytes_muxed, decode_time); if( new_au_next_sec ) ++syncwords; new_au_next_sec = NextAU(); } completion: return bytes_read; } mjpegtools-2.1.0/mplex/inputstrm.cpp0000644000175000017500000001660011011315327020104 0ustar glowwormglowworm /* * inputstrm.c: Base classes related to muxing out input streams into * the output stream. * * Copyright (C) 2001 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "mjpeg_types.h" #include "inputstrm.hpp" #include "multiplexor.hpp" MuxStream::MuxStream() : init(false) { } void MuxStream::Init( const int strm_id, const unsigned int _buf_scale, const unsigned int buf_size, const unsigned int _zero_stuffing, bool bufs_in_first, bool always_bufs) { stream_id = strm_id; nsec = 0; zero_stuffing = _zero_stuffing; buffer_scale = _buf_scale; buffer_size = buf_size; bufmodel.Init( buf_size ); buffers_in_header = bufs_in_first; always_buffers_in_header = always_bufs; new_au_next_sec = true; init = true; min_pes_header_len = 0; } unsigned int MuxStream::BufferSizeCode() { if( buffer_scale == 1 ) return buffer_size / 1024; else if( buffer_scale == 0 ) return buffer_size / 128; else assert(false); return 0; // Never reached... } ElementaryStream::ElementaryStream( IBitStream &ibs, Multiplexor &into, stream_kind _kind) : stream_length(0), bs( ibs ), eoscan(false), last_buffered_AU(0), decoding_order(0), old_frames(0), au(0), muxinto( into ), kind(_kind), buffer_min(INT_MAX), buffer_max(1) { } ElementaryStream::~ElementaryStream () { if( au != 0 ) delete au; } /*********************************** * * Scan ahead to buffer enough info on the coming Access Units to * permit look-ahead of look_ahead/processing AUs forward from the * current AU *and* the muxing of at least one sector. * **********************************/ void ElementaryStream::AUBufferLookaheadFill( unsigned int look_ahead) { while( !eoscan && ( look_ahead+1 > aunits.MaxAULookahead() || bs.BufferedBytes() < muxinto.sector_size ) ) { FillAUbuffer(FRAME_CHUNK); } if( eoscan ) bs.ScanDone(); } /****************************************** * * Move on to the next Access unit in the Elementary stream * *****************************************/ bool ElementaryStream::NextAU() { // Free up no longer needed AU record if( au != 0 ) delete au; // Ensure we have enough in the AU buffer! AUBufferLookaheadFill(1); // Get the details of the next AU to be muxed.... AUnit *p_au = aunits.Next(); if( p_au != NULL ) { au = p_au; au_unsent = p_au->length; return true; } else { // We signal no MORE AU left to Mux in this stream... au_unsent = 0; au = 0; return false; } } AUnit * ElementaryStream::Lookahead( unsigned int n) { AUBufferLookaheadFill(n); return aunits.Lookahead( n ); } unsigned int ElementaryStream::BytesToMuxAUEnd(unsigned int sector_transport_size) { return (au_unsent/min_packet_data)*sector_transport_size + (au_unsent%min_packet_data)+(sector_transport_size-min_packet_data); } /****************************************************************** * ElementaryStream::ReadPacketPayload * * Reads the stream data from actual input stream, updates decode * buffer model and current access unit information from the * look-ahead scanning buffer to account for bytes_muxed bytes being * muxed out. Particular important is the maintenance of "au_unsent" * the count of how much data in the current AU remains umuxed. It * not only allows us to keep track of AU's but is also used for * generating substream headers * * Unless we need to over-ride it to handle sub-stream headers * The packet payload for an elementary stream is simply the parsed and * spliced buffered stream data.. * ******************************************************************/ unsigned int ElementaryStream::ReadPacketPayload(uint8_t *dst, unsigned int to_read) { // // Allow for the possibility that stream sub-headers might be needed // E.g. AC3, LPCM, DTS.... unsigned int header_size = StreamHeaderSize(); bitcount_t read_start = bs.GetBytePos(); unsigned int actually_read = bs.GetBytes( dst+header_size, to_read-header_size ); bs.Flush( read_start ); Muxed( actually_read ); ReadStreamHeader(dst, header_size); return actually_read; } void ElementaryStream::Muxed (unsigned int bytes_muxed) { clockticks decode_time; if (bytes_muxed == 0 || MuxCompleted() ) return; /* Work through what's left of the current AU and the following AU's updating the info until we reach a point where an AU had to be split between packets. NOTE: It *is* possible for this loop to iterate. The DTS/PTS field for the packet in this case would have been given the that for the first AU to start in the packet. Whether Joe-Blow's hardware VCD player handles this properly is another matter of course! */ decode_time = RequiredDTS(); while (au_unsent < bytes_muxed) { AUMuxed(true); // Update stream specific tracking // of AUs muxed... bufmodel.Queued(au_unsent, decode_time); bytes_muxed -= au_unsent; new_au_next_sec = NextAU(); if( !new_au_next_sec ) return; decode_time = RequiredDTS(); }; // We've now reached a point where the current AU overran or // fitted exactly. We need to distinguish the latter case // so we can record whether the next packet starts with an // existing AU or not - info we need to decide what PTS/DTS // info to write at the start of the next packet. if (au_unsent > bytes_muxed) { AUMuxed(false); bufmodel.Queued( bytes_muxed, decode_time); au_unsent -= bytes_muxed; new_au_next_sec = false; } else // if (au_unsent == bytes_muxed) { AUMuxed(false); bufmodel.Queued(bytes_muxed, decode_time); new_au_next_sec = NextAU(); } } bool ElementaryStream::MuxPossible(clockticks currentSCR) { return (!RunOutComplete() && bufmodel.Space() > max_packet_data); } void ElementaryStream::UpdateBufferMinMax() { buffer_min = buffer_min < bufmodel.Space() ? buffer_min : bufmodel.Space(); buffer_max = buffer_max > bufmodel.Space() ? buffer_max : bufmodel.Space(); } void ElementaryStream::AllDemuxed() { bufmodel.Flushed(); } void ElementaryStream::DemuxedTo( clockticks SCR ) { bufmodel.Cleaned( SCR ); } bool ElementaryStream::MuxCompleted() { return au_unsent == 0; } void ElementaryStream::SetSyncOffset( clockticks sync_offset ) { timestamp_delay = sync_offset; } void ElementaryStream::BufferAndOutputSector( ) { AUBufferLookaheadFill(1); // TODO is this really needed here? OutputSector(); } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/aunit.hpp0000644000175000017500000000142110025375117017166 0ustar glowwormglowworm#ifndef __AUNIT_H__ #define __AUNIT_H__ #include "mjpeg_types.h" #include "bits.hpp" typedef int64_t clockticks; // This value *must* be signed // because we frequently compute *offsets* class AUnit { public: AUnit() : length(0), PTS(0), DTS(0) {} // // How many payload bytes muxing AU will require. Eventually will be more // complex for input streams where AU are no contiguous // inline unsigned int PayloadSize() const { return length; } void markempty() { length = 0; } bitcount_t start; unsigned int length; clockticks PTS; int dorder; // // Remainder Used only for video AU's... // clockticks DTS; int porder; unsigned int type; bool seq_header; bool end_seq; }; #endif // __AUNIT_H__ mjpegtools-2.1.0/mplex/multiplexor.hpp0000644000175000017500000001006010602035624020426 0ustar glowwormglowworm #ifndef __OUTPUTSTREAM_H__ #define __OUTPUTSTREAM_H__ #include #include "mjpeg_types.h" #include "interact.hpp" #include "inputstrm.hpp" #include "padstrm.hpp" #include "systems.hpp" class Multiplexor { public: Multiplexor(MultiplexJob &job, OutputStream &output, OutputStream *index); ~Multiplexor (); void Multiplex (); void ByteposTimecode( bitcount_t bytepos, clockticks &ts ); inline Sys_header_struc *SystemHeader() { return &sys_header; } unsigned int PacketPayload( MuxStream &strm, bool buffers, bool PTSstamp, bool DTSstamp ); unsigned int WritePacket( unsigned int max_packet_data_size, MuxStream &strm, bool buffers, clockticks PTS, clockticks DTS, uint8_t timestamps ); void IndexLastPacket( ElementaryStream &strm, int index_type ); bool AfterMaxPTS(clockticks ×tamp) { return max_PTS != 0 && timestamp >= max_PTS; } /* Special "unusual" sector types needed for particular formats */ void OutputDVDPriv2 (); /* Syntax control parameters, public becaus they're partly referenced by the input stream objects. */ bool always_sys_header_in_pack; bool dtspts_for_all_vau; bool sys_header_in_pack1; bool buffers_in_video; bool always_buffers_in_video; bool buffers_in_audio; bool always_buffers_in_audio; bool sector_align_iframeAUs; bool split_at_seq_end; bool seg_starts_with_video; bool timestamp_iframe_only; bool video_buffers_iframe_only; unsigned int audio_buffer_size; unsigned int packets_per_pack; unsigned int min_pes_header_len; clockticks max_PTS; int mpeg; int data_rate; unsigned int run_in_frames; int mux_format; uint64_t max_segment_size; Workarounds workarounds; /* In some situations the system/PES packets are embedded with external transport data which has to be taken into account for SCR calculations to be correct. E.g. VCD streams. Where each 2324 byte system packet is embedded in a 2352 byte CD sector and the actual MPEG data is preceded by 30 empty sectors. */ unsigned int sector_transport_size; unsigned int transport_prefix_sectors; unsigned int sector_size; unsigned int vcd_zero_stuffing; /* VCD audio sectors have 20 0 bytes :-( */ int dmux_rate; /* Actual data mux-rate for calculations always a multiple of 50 */ int mux_rate; /* MPEG mux rate (50 byte/sec units */ /* Sequence run-out control */ bool running_out; clockticks runout_PTS; private: /* Stream packet component buffers */ Sys_header_struc sys_header; Pack_struc pack_header; Pack_struc *pack_header_ptr; Sys_header_struc *sys_header_ptr; bool start_of_new_pack; bool include_sys_header; /* Under-run error messages */ unsigned int underruns; unsigned int underrun_ignore; /* Output data stream... */ PS_Stream *psstrm; bitcount_t bytes_output; clockticks ticks_per_sector; OutputStream *vdr_index; public: clockticks current_SCR; private: clockticks audio_delay; clockticks video_delay; bool vbr; /* Source data streams */ /* Note: 1st video stream is regarded as the "master" stream for the purpose of splitting sequences etc... */ vector estreams; // Complete set vector vstreams; // Video streams in estreams vector astreams; // Audio streams in estreams PaddingStream pstrm; VCDAPadStream vcdapstrm; DVDPriv2Stream dvdpriv2strm; private: void InitSyntaxParameters(MultiplexJob &job); void InitInputStreams(MultiplexJob &job); void InitInputStreamsForStills(MultiplexJob & job ); void InitInputStreamsForVideo(MultiplexJob & job ); clockticks RunInDelay(); void Init(); void NextPosAndSCR(); void SetPosAndSCR( bitcount_t bytepos ); void OutputPrefix( ); void OutputSuffix(); void OutputPadding ( bool vcd_audio_pad ); void MuxStatus( log_level_t level ); void WriteRawSector( uint8_t *rawpackets, unsigned int length ); void AppendMuxStreamsOf( vector &elem, vector &mux ); }; #endif //__OUTPUTSTREAM_H__ mjpegtools-2.1.0/mplex/videostrm_out.cpp0000644000175000017500000002526310747735115020767 0ustar glowwormglowworm /* * inptstrm.c: Members of input stream classes related to muxing out into * the output stream. * * Copyright (C) 2001 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "mjpeg_types.h" #include "videostrm.hpp" #include "multiplexor.hpp" VideoStream::VideoStream(IBitStream &ibs, VideoParams *parms, Multiplexor &into ) : ElementaryStream( ibs, into, ElementaryStream::video ), num_sequence(0), num_seq_end(0), num_pictures(0), num_groups(0), dtspts_for_all_au( into.dtspts_for_all_vau ), gop_control_packet( false ), parms(parms) { prev_offset=0; decoding_order=0; fields_presented=0; group_start_pic=0; group_start_field=0; temporal_reference=0; pulldown_32 = 0; temporal_reference = -1; // Needed to recognise 2nd field of 1st // frame in a field pic sequence last_buffered_AU=0; max_bits_persec = 0; AU_hdr = SEQUENCE_HEADER; /* GOP or SEQ Header starting AU? */ for( int i =0; i<4; ++i ) num_frames[i] = avg_frames[i] = 0; FRAME_CHUNK = 6; } bool VideoStream::Probe(IBitStream &bs ) { return bs.GetBits( 32) == 0x1b3; } /********************************* * Signals when video stream has completed mux run-out specified * in associated mux stream. Run-out is always to complete GOP's. *********************************/ bool VideoStream::RunOutComplete() { return (au_unsent == 0 || ( muxinto.running_out && au->type == IFRAME && RequiredPTS() >= muxinto.runout_PTS)); } /********************************* * Signals if it is permissible/possible to Mux out a sector from the Stream. * The universal constraints that muxing should not be complete and that * that the reciever buffer should have sufficient it also insists that * the muxed data won't hang around in the receiver buffer for more than * one second. This is mainly for the benefit of (S)VCD and DVD applications * where long delays mess up random access. *******************************/ bool VideoStream::MuxPossible( clockticks currentSCR ) { return ( ElementaryStream::MuxPossible(currentSCR) && RequiredDTS() < currentSCR + max_STD_buffer_delay ); } void VideoStream::AUMuxed( bool first_in_sector ) { //DEBUG //mjpeg_info( "VidMuxed: %d %lld ", au->dorder, RequiredDTS()/300 ); } /********************************* * Work out the timestamps to be set in the header of sectors starting * new AU's. *********************************/ uint8_t VideoStream::NewAUTimestamps( int AUtype ) { uint8_t timestamps; if( AUtype == BFRAME) timestamps=TIMESTAMPBITS_PTS; else timestamps=TIMESTAMPBITS_PTS_DTS; if( muxinto.timestamp_iframe_only && AUtype != IFRAME) timestamps=TIMESTAMPBITS_NO; return timestamps; } /********************************* * Work out the buffer records to be set in the header of sectors * starting new AU's. *********************************/ bool VideoStream::NewAUBuffers( int AUtype ) { return buffers_in_header & !(muxinto.video_buffers_iframe_only && AUtype != IFRAME); } /******************************** * * Check if the next sector could potentially include parts of AUs * following a sequence end marker... in this case a run-out may be needed * *******************************/ bool VideoStream::SeqEndRunOut() { unsigned int payload = au_unsent; unsigned int ahead = 0; AUnit *next_au = au; if( next_au == 0 ) return false; for(;;) { if( next_au->end_seq || payload >= muxinto.sector_size) break; ++ahead; next_au = Lookahead(ahead); if( next_au == 0 ) break; payload += next_au->PayloadSize(); } // We don't need to start run-out if the next sector cannot contain // next sequence or there is no next sequence (no AU after the one with // the sequence end marker return next_au != 0 && next_au->end_seq && payload < muxinto.sector_size && Lookahead(ahead+1) != 0; } /******************************** * * Check if the next sector could potentially include a seq_end marker * *******************************/ const AUnit *VideoStream::NextIFrame() { unsigned int ahead = 0; AUnit *au_ahead = Lookahead(ahead); while( au_ahead != 0 && au_ahead->type != IFRAME && ahead < MAX_GOP_LENGTH ) { ++ahead; au_ahead = Lookahead(ahead); } return au_ahead; } /******************************** * * Calculate how much payload can be muxed next sector without * including the next IFRAME. * *******************************/ unsigned int VideoStream::ExcludeNextIFramePayload() { unsigned int payload = au_unsent; unsigned int ahead = 0; AUnit *au_ahead; for(;;) { au_ahead = Lookahead(ahead); if( au_ahead == 0 || payload >= muxinto.sector_size || au_ahead->type == IFRAME ) break; payload += au_ahead->PayloadSize(); ++ahead; } assert( eoscan || au_ahead != 0 ); return payload; } /****************************************************************** Output_Video generiert Pack/Sys_Header/Packet Informationen aus dem Video Stream und speichert den so erhaltenen Sektor ab. generates Pack/Sys_Header/Packet information from the video stream and writes out the new sector ******************************************************************/ void VideoStream::OutputSector ( ) { unsigned int max_packet_payload; unsigned int actual_payload; unsigned int old_au_then_new_payload; clockticks DTS,PTS; int autype; max_packet_payload = 0; /* 0 = Fill sector */ /* I-frame aligning. For the last AU of segment or for formats with ACCESS-POINT sectors where I-frame (and preceding headers) are sector aligned. We need to look ahead to see how much we may put into the current packet without without touching the next I-frame (which is supposed to be placed at the start of its own sector). N.b.runout_PTS is the PTS of the after which the next I frame marks the start of the next sequence. */ if( muxinto.sector_align_iframeAUs || muxinto.running_out ) { max_packet_payload = ExcludeNextIFramePayload(); } /* Figure out the threshold payload size below which we can fit more than one AU into a packet N.b. because fitting more than one in imposses an overhead of additional header fields so there is a dead spot where we *have* to stuff the packet rather than start fitting in an extra AU. Slightly over-conservative in the case of the last packet... */ old_au_then_new_payload = muxinto.PacketPayload( *this, buffers_in_header, true, true); /* CASE: Packet starts with new access unit */ if (new_au_next_sec ) { autype = AUType(); // Some types of output format (e.g. DVD) require special // control sectors before the sector starting a new GOP // N.b. this implies muxinto.sector_align_iframeAUs // if( gop_control_packet && autype == IFRAME ) { OutputGOPControlSector(); } // // If we demand every AU should have its own timestamp // We can't start two in the same sector... // if( dtspts_for_all_au && max_packet_payload == 0 ) max_packet_payload = au_unsent; PTS = RequiredPTS(); DTS = RequiredDTS(); actual_payload = muxinto.WritePacket ( max_packet_payload, *this, NewAUBuffers(autype), PTS, DTS, NewAUTimestamps(autype) ); muxinto.IndexLastPacket(*this, autype ); } /* CASE: Packet begins with old access unit, no new one */ /* can begin in the very same packet */ else if ( au_unsent >= old_au_then_new_payload || (max_packet_payload != 0 && au_unsent >= max_packet_payload) ) { actual_payload = muxinto.WritePacket( au_unsent, *this, false, 0, 0, TIMESTAMPBITS_NO ); // No new frame starts so no indexing... } /* CASE: Packet begins with old access unit, a new one */ /* could begin in the very same packet */ else /* if ( !new_au_next_sec && (au_unsent < old_au_then_new_payload)) */ { /* Is there a new access unit ? */ if( Lookahead() != 0 ) { autype = NextAUType(); if( dtspts_for_all_au && max_packet_payload == 0 ) max_packet_payload = au_unsent + Lookahead()->length; PTS = NextRequiredPTS(); DTS = NextRequiredDTS(); actual_payload = muxinto.WritePacket ( max_packet_payload, *this, NewAUBuffers(autype), PTS, DTS, NewAUTimestamps(autype) ); muxinto.IndexLastPacket(*this, autype ); } else { actual_payload = muxinto.WritePacket ( au_unsent, *this, false, 0, 0, TIMESTAMPBITS_NO); } } ++nsec; buffers_in_header = always_buffers_in_header; } /*********************************************** OutputControlSector - Write control sectors prefixing a GOP For "normal" video streams this doesn't happen and so represents a bug and triggers an abort. In DVD's these sectors carry a system header and what is presumably indexing and/or sub-title information in private_stream_2 packets. I have no idea what to put in here so we simply pad the sector out. ***********************************************/ void VideoStream::OutputGOPControlSector() { abort(); } /****************************************************************** * OutputGOPControlSector * DVD System headers are carried in peculiar sectors carrying 2 * PrivateStream2 packets. We're sticking 0's in the packets * as we have no idea what's supposed to be in there. ******************************************************************/ void DVDVideoStream::OutputGOPControlSector() { muxinto.OutputDVDPriv2 (); } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/audiostrm_out.cpp0000644000175000017500000000755510162204571020752 0ustar glowwormglowworm /* * audiostrm_out.cpp: Members of audio stream classes related to * muxing out into the output stream. * * Copyright (C) 2001 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "mjpeg_types.h" #include "audiostrm.hpp" #include "multiplexor.hpp" AudioStream::AudioStream(IBitStream &ibs, Multiplexor &into) : ElementaryStream( ibs, into, ElementaryStream::audio ), num_syncword(0) { FRAME_CHUNK = 24; } /********************************* * Signals when audio stream has completed mux run-out specified * in associated mux stream. *********************************/ bool AudioStream::RunOutComplete() { return (au_unsent == 0 || ( muxinto.running_out && RequiredPTS() >= muxinto.runout_PTS)); } /****************************************************************** Output_Audio generates Pack/Sys Header/Packet information from the audio stream and saves them into the sector ******************************************************************/ void AudioStream::OutputSector ( ) { clockticks PTS; unsigned int max_packet_data; unsigned int actual_payload; unsigned int old_au_then_new_payload; PTS = RequiredDTS(); old_au_then_new_payload = muxinto.PacketPayload( *this, buffers_in_header, false, false ); bool last_packet = Lookahead() == 0; // Ensure we have access units data buffered to allow a sector to be // written. max_packet_data = 0; if( (muxinto.running_out && NextRequiredPTS() > muxinto.runout_PTS) || last_packet) { /* We're now in the last AU of a segment. So we don't want to go beyond it's end when writing sectors. Hence we limit packet payload size to (remaining) AU length. */ max_packet_data = au_unsent+StreamHeaderSize(); } /* CASE: packet starts with new access unit */ if (new_au_next_sec) { actual_payload = muxinto.WritePacket ( max_packet_data, *this, buffers_in_header, PTS, 0, TIMESTAMPBITS_PTS); } /* CASE: packet starts with old access unit, no new one */ /* starts in this very same packet */ else if (!(new_au_next_sec) && (au_unsent >= old_au_then_new_payload)) { actual_payload = muxinto.WritePacket ( max_packet_data, *this, buffers_in_header, 0, 0, TIMESTAMPBITS_NO ); } /* CASE: packet starts with old access unit, a new one */ /* starts in this very same packet */ else /* !(new_au_next_sec) && (au_unsent < old_au_then_new_payload)) */ { /* is there another access unit anyway ? */ if( !last_packet ) { PTS = NextRequiredDTS(); actual_payload = muxinto.WritePacket ( max_packet_data, *this, buffers_in_header, PTS, 0, TIMESTAMPBITS_PTS ); } else { actual_payload = muxinto.WritePacket ( max_packet_data, *this, buffers_in_header, 0, 0, TIMESTAMPBITS_NO ); }; } ++nsec; buffers_in_header = always_buffers_in_header; } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/mplexconsts.hpp0000644000175000017500000000543712052075212020433 0ustar glowwormglowworm#ifndef __MPLEXCONSTS_H__ #define __MPLEXCONSTS_H__ #define SEQUENCE_HEADER 0x000001b3 #define SEQUENCE_END 0x000001b7 #define PICTURE_START 0x00000100 #define EXT_START_CODE 0x000001b5 #define GROUP_START 0x000001b8 #define SYNCWORD_START 0x000001 #define ZA_SEQUENCE_HEADER 0x000001f8 #define IFRAME 1 #define PFRAME 2 #define BFRAME 3 #define DFRAME 4 #define NOFRAME 5 #define PIC_TOP_FIELD 1 #define PIC_BOT_FIELD 2 #define PIC_FRAME 3 #define CODING_EXT_ID 8 #define AUDIO_SYNCWORD 0x7ff #define PACK_START 0x000001ba #define SYS_HEADER_START 0x000001bb #define ISO11172_END 0x000001b9 #define PACKET_START 0x000001 #define MAX_FFFFFFFF 4294967295.0 /* = 0xffffffff in dec. */ #define CLOCKS_per_90Kth_sec 300 #define CLOCKS (CLOCKS_per_90Kth_sec*90000) /* MPEG-2 System Clock Hertz - we divide down by 300.0 for MPEG-1*/ /* Range of sizes of the fields following the packet length field in packet header: used to calculate if recieve buffers will have enough space... */ #define MPEG2_BUFFERINFO_LENGTH 3 #define MPEG1_BUFFERINFO_LENGTH 2 #define DTS_PTS_TIMESTAMP_LENGTH 5 #define MPEG2_AFTER_PACKET_LENGTH_MIN 3 #define MPEG1_AFTER_PACKET_LENGTH_MIN (0+1) /* Sector under-size below which header stuffing rather than padding packets or post-packet zero stuffing is used. *Must* be less than 20 for VCD multiplexing to work correctly! */ #define MINIMUM_PADDING_PACKET_SIZE 10 #define PACKET_HEADER_SIZE 6 #define AUDIO_STREAMS 0xb8 /* Marker Audio Streams */ #define VIDEO_STREAMS 0xb9 /* Marker Video Streams */ #define AUDIO_STR_0 0xc0 /* Marker Audio Stream0 */ #define VIDEO_STR_0 0xe0 /* Marker Video Stream0 */ #define PADDING_STR 0xbe /* Marker Padding Stream*/ #define PRIVATE_STR_1 0xbd /* private stream 1 */ #define PRIVATE_STR_2 0xbf /* private stream 2 */ #define AC3_SUB_STR_0 0x80 /* AC3 substream id 0 */ #define DTS_SUB_STR_0 0x88 /* DTS substream id 0 */ #define LPCM_SUB_STR_0 0xa0 /* LPCM substream id 0 */ #define ZERO_STUFFING_BYTE 0 #define STUFFING_BYTE 0xff #define RESERVED_BYTE 0xff #define TIMESTAMPBITS_NO 0 /* Flag NO timestamps */ #define TIMESTAMPBITS_PTS 2 /* Flag PTS timestamp */ #define TIMESTAMPBITS_DTS 1 /* Flag PTS timestamp */ #define TIMESTAMPBITS_PTS_DTS (TIMESTAMPBITS_DTS|TIMESTAMPBITS_PTS) /* Flag BOTH timestamps */ #define MARKER_MPEG1_SCR 2 /* Marker SCR */ #define MARKER_MPEG2_SCR 1 /* These don't need to be distinct! */ #define MARKER_JUST_PTS 2 /* Marker only PTS */ #define MARKER_PTS 3 /* Marker PTS */ #define MARKER_DTS 1 /* Marker DTS */ #define MARKER_NO_TIMESTAMPS 0x0f /* Marker NO timestamps */ #endif // __MPLEXCONSTS_H__ mjpegtools-2.1.0/mplex/stillsstream.hpp0000644000175000017500000000371310025375117020602 0ustar glowwormglowworm /* * stillsstreams.c: Class for elemenary still video streams * Most functionality is inherited from VideoStream * * Copyright (C) 2001 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "videostrm.hpp" // // Class for video stills sequence for (S)VCD non-mixed stills segment // item // class StillsStream : public VideoStream { public: StillsStream( IBitStream &ibs, StillsParams *parms, Multiplexor &into) : VideoStream( ibs, parms, into ), current_PTS(0), current_DTS(0) {} void Init( ); private: virtual void NextDTSPTS( ); clockticks current_PTS; clockticks current_DTS; }; // // Class for video stills sequence for VCD mixed stills Segment item. // class VCDStillsStream : public StillsStream { public: VCDStillsStream( IBitStream &ibs, StillsParams *vparms, Multiplexor &into ) : StillsStream( ibs, vparms, into ), sibling( 0 ), stream_mismatch_warned( false ) {} void SetSibling( VCDStillsStream * ); virtual bool MuxPossible(clockticks currentSCR); private: bool LastSectorLastAU(); VCDStillsStream *sibling; bool stream_mismatch_warned; }; /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mplex/aunitbuffer.hpp0000644000175000017500000000200111321127404020345 0ustar glowwormglowworm#ifndef __AUNITBUFFER_H__ #define __AUNITBUFFER_H__ #include #include "mjpeg_logging.h" #include "aunit.hpp" class AUStream { public: AUStream() {} ~AUStream() { for( std::deque::iterator i = buf.begin(); i != buf.end(); ++i ) delete *i; } void Append( AUnit &rec ) { if( buf.size() >= BUF_SIZE_SANITY ) mjpeg_error_exit1( "INTERNAL ERROR: AU buffer overflow" ); buf.push_back( new AUnit(rec) ); } inline AUnit *Next( ) { if( buf.size()==0 ) { return 0; } else { AUnit *res = buf.front(); buf.pop_front(); return res; } } inline void DropLast() { if( buf.empty() ) mjpeg_error_exit1( "INTERNAL ERROR: droplast empty AU buffer" ); buf.pop_back(); } inline AUnit *Lookahead( unsigned int n) { return buf.size() <= n ? 0 : buf[n]; } inline unsigned int MaxAULookahead() const { return buf.size(); } private: static const unsigned int BUF_SIZE_SANITY = 1000; std::deque buf; }; #endif // __AUSTREAM_H__ mjpegtools-2.1.0/utils/0000755000175000017500000000000012217306500015345 5ustar glowwormglowwormmjpegtools-2.1.0/utils/mmxsse/0000755000175000017500000000000012217306500016661 5ustar glowwormglowwormmjpegtools-2.1.0/utils/mmxsse/motion.c0000644000175000017500000000311510164607764020351 0ustar glowwormglowworm#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "cpu_accel.h" #include "mmxsse_motion.h" #include "mjpeg_logging.h" #define SIMD_DO(x,y) if(disable_simd( #x )) mjpeg_info(" Disabling " #x); else p##x = x##_##y #define SIMD_MMX(x) SIMD_DO(x,mmx) #define SIMD_MMXE(x) SIMD_DO(x,mmxe) void enable_mmxsse_motion(int cpucap) { if(cpucap & ACCEL_X86_MMXEXT ) /* AMD MMX or SSE... */ { mjpeg_info( "SETTING EXTENDED MMX for MOTION!"); SIMD_MMXE(sad_00); SIMD_MMXE(sad_01); SIMD_MMXE(sad_10); SIMD_MMXE(sad_11); SIMD_MMXE(sad_sub22); SIMD_MMXE(sad_sub44); SIMD_MMXE(find_best_one_pel); SIMD_MMX(sumsq); SIMD_MMX(sumsq_sub22); SIMD_MMX(bsumsq); SIMD_MMX(bsumsq_sub22); SIMD_MMX(variance); SIMD_MMXE(bsad); SIMD_MMXE(build_sub22_mests); SIMD_MMX(build_sub44_mests); SIMD_MMXE(mblocks_sub44_mests); } else if(cpucap & ACCEL_X86_MMX) /* Ordinary MMX CPU */ { mjpeg_info( "SETTING MMX for MOTION!"); SIMD_MMX(sad_sub22); SIMD_MMX(sad_sub44); SIMD_MMX(sad_00); SIMD_MMX(sad_01); SIMD_MMX(sad_10); SIMD_MMX(sad_11); SIMD_MMX(bsad); SIMD_MMX(sumsq); SIMD_MMX(sumsq_sub22); SIMD_MMX(bsumsq); SIMD_MMX(bsumsq_sub22); SIMD_MMX(variance); // NOT CHANGED pfind_best_one_pel; // NOT CHANGED pbuild_sub22_mests = build_sub22_mests; SIMD_MMX(build_sub44_mests); SIMD_MMX(mblocks_sub44_mests); } } mjpegtools-2.1.0/utils/mmxsse/build_sub44_mests.c0000644000175000017500000000157010373223222022363 0ustar glowwormglowworm#include "config.h" #include "mmxsse_motion.h" int build_sub44_mests_mmx( me_result_set *sub44set, int ilow, int jlow, int ihigh, int jhigh, int i0, int j0, int null_ctl_sad, uint8_t *s44org, uint8_t *s44blk, int qrowstride, int qh, int reduction ) { uint8_t *s44orgblk; me_result_s *sub44_mests = sub44set->mests; int istrt = ilow-i0; int jstrt = jlow-j0; int iend = ihigh-i0; int jend = jhigh-j0; int mean_weight, threshold; threshold = 6*null_ctl_sad / (4*4*reduction); s44orgblk = s44org+(ilow>>2)+qrowstride*(jlow>>2); sub44set->len = (*pmblocks_sub44_mests)( s44orgblk, s44blk, istrt, jstrt, iend, jend, qh, qrowstride, threshold, sub44_mests); /* If we're really pushing quality we reduce once otherwise twice. */ sub_mean_reduction( sub44set, 1+(reduction>1), &mean_weight); return sub44set->len; } mjpegtools-2.1.0/utils/mmxsse/Makefile.am0000644000175000017500000000101610213713744020721 0ustar glowwormglowworm# Process this file with Automake to produce Makefile.in INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/utils noinst_LTLIBRARIES = libmmxsse.la libmmxsse_la_SOURCES = \ build_sub22_mests.c \ build_sub44_mests.c \ find_best_one_pel.c \ mblock_sad_mmx.c \ mblock_sad_mmxe.c \ mblock_sub44_sads_x86.c \ mblock_sumsq_mmx.c \ mblock_bsumsq_mmx.c \ mblock_bsad_mmx.c \ motion.c noinst_HEADERS = \ mblock_sub44_sads_x86.h \ mmxsse_motion.h EXTRA_DIST = \ mblock_sub44_sads_x86_h.c MAINTAINERCLEANFILES = Makefile.in mjpegtools-2.1.0/utils/mmxsse/build_sub22_mests.c0000644000175000017500000000264110177301170022360 0ustar glowwormglowworm#include "config.h" #include "mmxsse_motion.h" #include "fastintfns.h" #include int build_sub22_mests_mmxe( me_result_set *sub44set, me_result_set *sub22set, int i0, int j0, int ihigh, int jhigh, int null_ctl_sad, uint8_t *s22org, uint8_t *s22blk, int frowstride, int fh, int reduction) { int i,k,s; int threshold = 6*null_ctl_sad / (2 * 2*reduction); int min_weight; int ilim = ihigh-i0; int jlim = jhigh-j0; int x,y; uint8_t *s22orgblk; int32_t resvec[4]; me_result_s *mc = sub22set->mests; for( k = 0; k < sub44set->len; ++k ) { x = sub44set->mests[k].x; y = sub44set->mests[k].y; s22orgblk = s22org +((y+j0)>>1)*frowstride +((x+i0)>>1); /* Get SAD for 2*2 subsampled macroblocks: orgblk,orgblk(+2,0), orgblk(0,+2), and orgblk(+2,+2) Done all in one go to reduce memory bandwidth demand */ mblock_sub22_nearest4_sads_mmxe(s22orgblk, s22blk, frowstride, fh, resvec); for( i = 0; i < 4; ++i ) { if( x <= ilim && y <= jlim ) { s =resvec[i]+(intmax(abs(x), abs(y))<<3); if( s < threshold ) { mc->x = (int8_t)x; mc->y = (int8_t)y; mc->weight = s; mc++; } } if( i == 1 ) { x -= 2; y += 2; } else { x += 2; } } } sub22set->len = mc - sub22set->mests; sub_mean_reduction( sub22set, reduction, &min_weight ); return sub22set->len; } mjpegtools-2.1.0/utils/mmxsse/mblock_bsad_mmx.c0000644000175000017500000002576310164437410022167 0ustar glowwormglowworm/* * bdist1_mmx.s: mmX optimized bidirectional absolute distance sum * * Original believed to be Copyright (C) 2000 Brent Byeler * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "mjpeg_types.h" #include "mmx.h" // These rely on mm7 being zero // load 8 bytes at *ptr, and expand into 16-bit words in r1 and r2 #define BSAD_LOAD(ptr,r1,r2) \ movq_m2r(ptr, r1); \ movq_r2r(r1, r2); \ punpcklbw_r2r(mm7, r1); \ punpckhbw_r2r(mm7, r2); // load 8 bytes at *ptr, and add to 16-bit words in r1 and r2, using t1 and t2 as temporary registers #define BSAD_LOAD_ACC(ptr,t1,t2,r1,r2) \ BSAD_LOAD(ptr,t1,t2); \ paddw_r2r(t1,r1); \ paddw_r2r(t2,r2); /* * absolute difference error between a (16*h) block and a bidirectional * prediction * * p2: address of top left pel of block * pf,hxf,hyf: address and half pel flags of forward ref. block * pb,hxb,hyb: address and half pel flags of backward ref. block * h: height of block * lx: distance (in bytes) of vertically adjacent pels in p2,pf,pb * mmX version */ int bsad_mmx(uint8_t *pf, uint8_t *pb, uint8_t *p2, int lx, int hxf, int hyf, int hxb, int hyb, int h) { uint8_t *pfa,*pfb,*pfc,*pba,*pbb,*pbc; int s, s1, s2; pfa = pf + hxf; pfb = pf + lx * hyf; pfc = pfb + hxf; pba = pb + hxb; pbb = pb + lx * hyb; pbc = pbb + hxb; s = 0; /* the accumulator */ if (h > 0) { pxor_r2r(mm7, mm7); pxor_r2r(mm6, mm6); pcmpeqw_r2r(mm5, mm5); psubw_r2r(mm5, mm6); psllw_i2r(1, mm6); do { BSAD_LOAD(pf[0],mm0,mm1); BSAD_LOAD_ACC(pfa[0],mm2,mm3,mm0,mm1); BSAD_LOAD_ACC(pfb[0],mm2,mm3,mm0,mm1); BSAD_LOAD_ACC(pfc[0],mm2,mm3,mm0,mm1); paddw_r2r(mm6, mm0); paddw_r2r(mm6, mm1); psrlw_i2r(2, mm0); psrlw_i2r(2, mm1); BSAD_LOAD(pb[0],mm2,mm3); BSAD_LOAD_ACC(pba[0],mm4,mm5,mm2,mm3); BSAD_LOAD_ACC(pbb[0],mm4,mm5,mm2,mm3); BSAD_LOAD_ACC(pbc[0],mm4,mm5,mm2,mm3); paddw_r2r(mm6, mm2); paddw_r2r(mm6, mm3); psrlw_i2r(2, mm2); psrlw_i2r(2, mm3); paddw_r2r(mm2, mm0); paddw_r2r(mm3, mm1); psrlw_i2r(1, mm6); paddw_r2r(mm6, mm0); paddw_r2r(mm6, mm1); psllw_i2r(1, mm6); psrlw_i2r(1, mm0); psrlw_i2r(1, mm1); packuswb_r2r(mm1, mm0); movq_m2r(p2[0], mm1); movq_r2r(mm0, mm2); psubusb_r2r(mm1, mm0); psubusb_r2r(mm2, mm1); por_r2r(mm1, mm0); movq_r2r(mm0, mm1); punpcklbw_r2r(mm7, mm0); punpckhbw_r2r(mm7, mm1); paddw_r2r(mm1, mm0); movq_r2r(mm0, mm1); punpcklwd_r2r(mm7, mm0); punpckhwd_r2r(mm7, mm1); paddd_r2r(mm1, mm0); movd_r2g(mm0, s1); psrlq_i2r(32, mm0); movd_r2g(mm0, s2); s += s1 + s2; BSAD_LOAD(pf[8],mm0,mm1); BSAD_LOAD_ACC(pfa[8],mm2,mm3,mm0,mm1); BSAD_LOAD_ACC(pfb[8],mm2,mm3,mm0,mm1); BSAD_LOAD_ACC(pfc[8],mm2,mm3,mm0,mm1); paddw_r2r(mm6, mm0); paddw_r2r(mm6, mm1); psrlw_i2r(2, mm0); psrlw_i2r(2, mm1); BSAD_LOAD(pb[8],mm2,mm3); BSAD_LOAD_ACC(pba[8],mm4,mm5,mm2,mm3); BSAD_LOAD_ACC(pbb[8],mm4,mm5,mm2,mm3); BSAD_LOAD_ACC(pbc[8],mm4,mm5,mm2,mm3); paddw_r2r(mm6, mm2); paddw_r2r(mm6, mm3); psrlw_i2r(2, mm2); psrlw_i2r(2, mm3); paddw_r2r(mm2, mm0); paddw_r2r(mm3, mm1); psrlw_i2r(1, mm6); paddw_r2r(mm6, mm0); paddw_r2r(mm6, mm1); psllw_i2r(1, mm6); psrlw_i2r(1, mm0); psrlw_i2r(1, mm1); packuswb_r2r(mm1, mm0); movq_m2r(p2[8], mm1); movq_r2r(mm0, mm2); psubusb_r2r(mm1, mm0); psubusb_r2r(mm2, mm1); por_r2r(mm1, mm0); movq_r2r(mm0, mm1); punpcklbw_r2r(mm7, mm0); punpckhbw_r2r(mm7, mm1); paddw_r2r(mm1, mm0); movq_r2r(mm0, mm1); punpcklwd_r2r(mm7, mm0); punpckhwd_r2r(mm7, mm1); paddd_r2r(mm1, mm0); movd_r2g(mm0, s1); psrlq_i2r(32, mm0); movd_r2g(mm0, s2); s += s1 + s2; p2 += lx; pf += lx; pfa += lx; pfb += lx; pfc += lx; pb += lx; pba += lx; pbb += lx; pbc += lx; h--; } while (h > 0); } emms(); return s; } static int bsad_2quad_mmxe(uint8_t *pf, uint8_t *pb, uint8_t *p2, int lx, int h) { int s; s = 0; /* the accumulator */ if (h > 0) { pcmpeqw_r2r(mm6, mm6); psrlw_i2r(15, mm6); paddw_r2r(mm6, mm6); pxor_r2r(mm7, mm7); pxor_r2r(mm5, mm5); do { BSAD_LOAD(pf[0],mm0,mm1); BSAD_LOAD_ACC(pf[1],mm2,mm3,mm0,mm1); BSAD_LOAD_ACC(pf[lx],mm2,mm3,mm0,mm1); BSAD_LOAD_ACC(pf[lx+1],mm2,mm3,mm0,mm1); paddw_r2r(mm6, mm0); paddw_r2r(mm6, mm1); psrlw_i2r(2, mm0); psrlw_i2r(2, mm1); packuswb_r2r(mm1, mm0); BSAD_LOAD(pb[0],mm1,mm2); BSAD_LOAD_ACC(pb[1],mm3,mm4,mm1,mm2); BSAD_LOAD_ACC(pb[lx],mm3,mm4,mm1,mm2); BSAD_LOAD_ACC(pb[lx+1],mm3,mm4,mm1,mm2); paddw_r2r(mm6, mm1); paddw_r2r(mm6, mm2); psrlw_i2r(2, mm1); psrlw_i2r(2, mm2); packuswb_r2r(mm2, mm1); pavgb_r2r(mm1, mm0); psadbw_m2r(p2[0],mm0); paddd_r2r(mm0,mm5); BSAD_LOAD(pf[8],mm0,mm1); BSAD_LOAD_ACC(pf[9],mm2,mm3,mm0,mm1); BSAD_LOAD_ACC(pf[lx+8],mm2,mm3,mm0,mm1); BSAD_LOAD_ACC(pf[lx+9],mm2,mm3,mm0,mm1); paddw_r2r(mm6, mm0); paddw_r2r(mm6, mm1); psrlw_i2r(2, mm0); psrlw_i2r(2, mm1); packuswb_r2r(mm1, mm0); BSAD_LOAD(pb[8],mm1,mm2); BSAD_LOAD_ACC(pb[9],mm3,mm4,mm1,mm2); BSAD_LOAD_ACC(pb[lx+8],mm3,mm4,mm1,mm2); BSAD_LOAD_ACC(pb[lx+9],mm3,mm4,mm1,mm2); paddw_r2r(mm6, mm1); paddw_r2r(mm6, mm2); psrlw_i2r(2, mm1); psrlw_i2r(2, mm2); packuswb_r2r(mm2, mm1); pavgb_r2r(mm1, mm0); psadbw_m2r(p2[8],mm0); paddd_r2r(mm0,mm5); p2 += lx; pf += lx; pb += lx; h--; } while (h > 0); } movd_r2g(mm5,s); emms(); return s; } static int bsad_1quad_mmxe(uint8_t *pf, uint8_t *pb, uint8_t *pb2, uint8_t *p2, int lx, int h) { int s; s = 0; /* the accumulator */ if (h > 0) { pcmpeqw_r2r(mm6, mm6); psrlw_i2r(15, mm6); paddw_r2r(mm6, mm6); pxor_r2r(mm7, mm7); pxor_r2r(mm5, mm5); do { BSAD_LOAD(pf[0],mm0,mm1); BSAD_LOAD_ACC(pf[1],mm2,mm3,mm0,mm1); BSAD_LOAD_ACC(pf[lx],mm2,mm3,mm0,mm1); BSAD_LOAD_ACC(pf[lx+1],mm2,mm3,mm0,mm1); paddw_r2r(mm6, mm0); paddw_r2r(mm6, mm1); psrlw_i2r(2, mm0); psrlw_i2r(2, mm1); packuswb_r2r(mm1, mm0); movq_m2r(pb2[0],mm1); pavgb_m2r(pb[0],mm1); pavgb_r2r(mm1, mm0); psadbw_m2r(p2[0],mm0); paddd_r2r(mm0,mm5); BSAD_LOAD(pf[8],mm0,mm1); BSAD_LOAD_ACC(pf[9],mm2,mm3,mm0,mm1); BSAD_LOAD_ACC(pf[lx+8],mm2,mm3,mm0,mm1); BSAD_LOAD_ACC(pf[lx+9],mm2,mm3,mm0,mm1); paddw_r2r(mm6, mm0); paddw_r2r(mm6, mm1); psrlw_i2r(2, mm0); psrlw_i2r(2, mm1); packuswb_r2r(mm1, mm0); movq_m2r(pb2[8],mm1); pavgb_m2r(pb[8],mm1); pavgb_r2r(mm1, mm0); psadbw_m2r(p2[8],mm0); paddd_r2r(mm0,mm5); p2 += lx; pf += lx; pb += lx; pb2 += lx; h--; } while (h > 0); } movd_r2g(mm5,s); emms(); return s; } /* For a 16*h block, this computes (((((*pf + *pf2 + 1)>>1) + ((*pb + *pb2 + 1)>>1) + 1)>>1) + *p2 + 1)>>1 */ static int bsad_0quad_mmxe(uint8_t *pf,uint8_t *pf2,uint8_t *pb,uint8_t *pb2,uint8_t *p2,int lx,int h) { int32_t s=0; pxor_r2r(mm7, mm7); do { movq_m2r(pf2[0],mm0); movq_m2r(pf2[8],mm2); movq_m2r(pb2[0],mm1); movq_m2r(pb2[8],mm3); pavgb_m2r(pf[0],mm0); pavgb_m2r(pf[8],mm2); pavgb_m2r(pb[0],mm1); pavgb_m2r(pb[8],mm3); pavgb_r2r(mm1,mm0); pavgb_r2r(mm3,mm2); psadbw_m2r(p2[0],mm0); psadbw_m2r(p2[8],mm2); paddd_r2r(mm0,mm7); paddd_r2r(mm2,mm7); pf+=lx; pf2+=lx; pb+=lx; pb2+=lx; p2+=lx; h--; } while (h); movd_r2g(mm7,s); emms(); return s; } int bsad_mmxe(uint8_t *pf, uint8_t *pb, uint8_t *p2, int lx, int hxf, int hyf, int hxb, int hyb, int h) { uint8_t *pf2,*pb2; #if 0 static int c0=0,c1=0,c2=0,ct=0; if( hxf & hyf & hxb & hyb ) c2++; else if( (hxf & hyf) | (hxb & hyb) ) c1++; else c0++; ct++; if( !(ct&65535) ) fprintf(stderr,"bsad_mmxe: c0=%d%%, c1=%d%%, c2=%d%%\n",c0*100/ct,c1*100/ct,c2*100/ct); #endif if( hyf ) pf2=pf+lx; else pf2=pf+hxf; if( hyb ) pb2=pb+lx; else pb2=pb+hxb; // if either pf or pb have half pels in BOTH directions, then // use the slow routine if( (hxf & hyf) ) { if( (hxb & hyb) ) return bsad_2quad_mmxe(pf,pb,p2,lx,h); else return bsad_1quad_mmxe(pf,pb,pb2,p2,lx,h); } else { if( (hxb & hyb) ) return bsad_1quad_mmxe(pb,pf,pf2,p2,lx,h); else return bsad_0quad_mmxe(pf,pf2,pb,pb2,p2,lx,h); } } mjpegtools-2.1.0/utils/mmxsse/mblock_sumsq_mmx.c0000644000175000017500000003000510222310715022400 0ustar glowwormglowworm/* * dist2_mmx.s: mmX optimized squared distance sum * * Original believed to be Copyright (C) 2000 Brent Byeler * * This program is free software; you can reaxstribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "mjpeg_types.h" #include "mmx.h" /* * total squared difference between two (16*h) blocks * including optional half pel interpolation of [ebp+8] ; blk1 (hx,hy) * blk1,blk2: addresses of top left pels of both blocks * lx: distance (in bytes) of vertically adjacent pels * hx,hy: flags for horizontal and/or vertical interpolation * h: height of block (usually 8 or 16) * mmX version */ int sumsq_mmx(uint8_t *blk1, uint8_t *blk2, int lx, int hx, int hy, int h) { static const uint16_t twos[4]={2,2,2,2}; int sum,sum1,sum2; pxor_r2r(mm5, mm5); if (h>0) { pxor_r2r(mm7, mm7); if ((hx == 0) && (hy == 0)) { do { /* d2top00 */ movq_m2r(blk1[0], mm0); movq_r2r(mm0, mm1); punpcklbw_r2r(mm7, mm0); punpckhbw_r2r(mm7, mm1); movq_m2r(blk2[0], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); psubw_r2r(mm2, mm0); psubw_r2r(mm3, mm1); pmaddwd_r2r(mm0, mm0); pmaddwd_r2r(mm1, mm1); paddd_r2r(mm1, mm0); movq_m2r(blk1[8], mm1); movq_r2r(mm1, mm2); punpcklbw_r2r(mm7, mm1); punpckhbw_r2r(mm7, mm2); movq_m2r(blk2[8], mm3); movq_r2r(mm3, mm4); punpcklbw_r2r(mm7, mm3); punpckhbw_r2r(mm7, mm4); psubw_r2r(mm3, mm1); psubw_r2r(mm4, mm2); pmaddwd_r2r(mm1, mm1); pmaddwd_r2r(mm2, mm2); paddd_r2r(mm2, mm1); paddd_r2r(mm1, mm0); paddd_r2r(mm0, mm5); /* Accumulate sum in mm5 */ blk1 += lx; blk2 += lx; h--; } while (h); } else if ((hx != 0) && (hy == 0)) /* d2is10 */ { pxor_r2r(mm6, mm6); /* mm6 = 0 and isn't changed anyplace in the loop.. */ pcmpeqw_r2r(mm1, mm1); psubw_r2r(mm1, mm6); do { /* d2top10 */ movq_m2r(blk1[0], mm0); movq_r2r(mm0, mm1); punpcklbw_r2r(mm7, mm0); punpckhbw_r2r(mm7, mm1); movq_m2r(blk1[1], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); paddw_r2r(mm2, mm0); paddw_r2r(mm3, mm1); paddw_r2r(mm6, mm0); /* here we add mm6 = 0.... weird... */ paddw_r2r(mm6, mm1); psrlw_i2r(1, mm0); psrlw_i2r(1, mm1); movq_m2r(blk2[0], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); psubw_r2r(mm2, mm0); psubw_r2r(mm3, mm1); pmaddwd_r2r(mm0, mm0); pmaddwd_r2r(mm1, mm1); paddd_r2r(mm1, mm0); movq_m2r(blk1[8], mm1); movq_r2r(mm1, mm2); punpcklbw_r2r(mm7, mm1); punpckhbw_r2r(mm7, mm2); movq_m2r(blk1[9], mm3); movq_r2r(mm3, mm4); punpcklbw_r2r(mm7, mm3); punpckhbw_r2r(mm7, mm4); paddw_r2r(mm3, mm1); paddw_r2r(mm4, mm2); paddw_r2r(mm6, mm1); paddw_r2r(mm6, mm2); psrlw_i2r(1, mm1); psrlw_i2r(1, mm2); movq_m2r(blk2[8], mm3); movq_r2r(mm3, mm4); punpcklbw_r2r(mm7, mm3); punpckhbw_r2r(mm7, mm4); psubw_r2r(mm3, mm1); psubw_r2r(mm4, mm2); pmaddwd_r2r(mm1, mm1); pmaddwd_r2r(mm2, mm2); paddd_r2r(mm2, mm1); paddd_r2r(mm1, mm0); paddd_r2r(mm0, mm5); /* Accumulate mm0 sum on mm5 */ blk1 += lx; blk2 += lx; h--; } while (h); } else if ((hx == 0) && (hy != 0)) /* d2is01 */ { pxor_r2r(mm6, mm6); pcmpeqw_r2r(mm1, mm1); psubw_r2r(mm1, mm6); /* mm6 = 1 */ do { /* d2top01 */ movq_m2r(blk1[0], mm0); movq_r2r(mm0, mm1); punpcklbw_r2r(mm7, mm0); punpckhbw_r2r(mm7, mm1); movq_m2r(blk1[lx], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); paddw_r2r(mm2, mm0); paddw_r2r(mm3, mm1); paddw_r2r(mm6, mm0); paddw_r2r(mm6, mm1); psrlw_i2r(1, mm0); psrlw_i2r(1, mm1); movq_m2r(blk2[0], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); psubw_r2r(mm2, mm0); psubw_r2r(mm3, mm1); pmaddwd_r2r(mm0, mm0); pmaddwd_r2r(mm1, mm1); paddd_r2r(mm1, mm0); movq_m2r(blk1[8], mm1); movq_r2r(mm1, mm2); punpcklbw_r2r(mm7, mm1); punpckhbw_r2r(mm7, mm2); movq_m2r(blk1[lx+8], mm3); movq_r2r(mm3, mm4); punpcklbw_r2r(mm7, mm3); punpckhbw_r2r(mm7, mm4); paddw_r2r(mm3, mm1); paddw_r2r(mm4, mm2); paddw_r2r(mm6, mm1); paddw_r2r(mm6, mm2); psrlw_i2r(1, mm1); psrlw_i2r(1, mm2); movq_m2r(blk2[8], mm3); movq_r2r(mm3, mm4); punpcklbw_r2r(mm7, mm3); punpckhbw_r2r(mm7, mm4); psubw_r2r(mm3, mm1); psubw_r2r(mm4, mm2); pmaddwd_r2r(mm1, mm1); pmaddwd_r2r(mm2, mm2); paddd_r2r(mm1, mm0); paddd_r2r(mm2, mm0); paddd_r2r(mm0, mm5); blk1 += lx; blk2 += lx; h--; } while (h); } else /* d2is11 */ { do { /* d2top11 */ movq_m2r(blk1[0], mm0); movq_r2r(mm0, mm1); punpcklbw_r2r(mm7, mm0); punpckhbw_r2r(mm7, mm1); movq_m2r(blk1[1], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); paddw_r2r(mm2, mm0); paddw_r2r(mm3, mm1); movq_m2r(blk1[lx], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); movq_m2r(blk1[lx+1], mm4); movq_r2r(mm4, mm6); punpcklbw_r2r(mm7, mm4); punpckhbw_r2r(mm7, mm6); paddw_r2r(mm4, mm2); paddw_r2r(mm6, mm3); paddw_r2r(mm2, mm0); paddw_r2r(mm3, mm1); movq_m2r(*twos, mm6); paddw_r2r(mm6, mm0); /* round mm0 */ paddw_r2r(mm6, mm1); /* round mm1 */ psrlw_i2r(2, mm0); psrlw_i2r(2, mm1); movq_m2r(blk2[0], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); psubw_r2r(mm2, mm0); psubw_r2r(mm3, mm1); pmaddwd_r2r(mm0, mm0); pmaddwd_r2r(mm1, mm1); paddd_r2r(mm1, mm0); movq_m2r(blk1[8], mm1); movq_r2r(mm1, mm2); punpcklbw_r2r(mm7, mm1); punpckhbw_r2r(mm7, mm2); movq_m2r(blk1[9], mm3); movq_r2r(mm3, mm4); punpcklbw_r2r(mm7, mm3); punpckhbw_r2r(mm7, mm4); paddw_r2r(mm3, mm1); paddw_r2r(mm4, mm2); movq_m2r(blk1[lx+8], mm3); movq_r2r(mm3, mm4); punpcklbw_r2r(mm7, mm3); punpckhbw_r2r(mm7, mm4); paddw_r2r(mm3, mm1); paddw_r2r(mm4, mm2); movq_m2r(blk1[lx+9], mm3); movq_r2r(mm3, mm4); punpcklbw_r2r(mm7, mm3); punpckhbw_r2r(mm7, mm4); paddw_r2r(mm3, mm1); paddw_r2r(mm4, mm2); movq_m2r(*twos, mm6); paddw_r2r(mm6, mm1); paddw_r2r(mm6, mm2); psrlw_i2r(2, mm1); psrlw_i2r(2, mm2); movq_m2r(blk2[8], mm3); movq_r2r(mm3, mm4); punpcklbw_r2r(mm7, mm3); punpckhbw_r2r(mm7, mm4); psubw_r2r(mm3, mm1); psubw_r2r(mm4, mm2); pmaddwd_r2r(mm1, mm1); pmaddwd_r2r(mm2, mm2); paddd_r2r(mm2, mm1); paddd_r2r(mm1, mm0); paddd_r2r(mm0, mm5); blk1 += lx; blk2 += lx; h--; } while (h); } } movd_r2g(mm5, sum1); psrlq_i2r(32, mm5); movd_r2g(mm5, sum2); sum = sum1 + sum2; emms(); return sum; } /* * total squared difference between two (8*h) blocks * blk1,blk2: addresses of top left pels of both blocks * lx: distance (in bytes) of vertically adjacent pels * h: height of block (usually 4, or 8) * mmX version */ int sumsq_sub22_mmx(uint8_t *blk1, uint8_t *blk2, int lx, int h) { int sum,sum1,sum2; pxor_r2r(mm5, mm5); /* sum */ if (h > 0) { pxor_r2r(mm7, mm7); do { /* d2top22 */ movq_m2r(blk1[0], mm0); movq_r2r(mm0, mm1); punpcklbw_r2r(mm7, mm0); punpckhbw_r2r(mm7, mm1); movq_m2r(blk2[0], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); psubw_r2r(mm2, mm0); psubw_r2r(mm3, mm1); pmaddwd_r2r(mm0, mm0); pmaddwd_r2r(mm1, mm1); paddd_r2r(mm0, mm5); paddd_r2r(mm1, mm5); blk1 += lx; blk2 += lx; h--; } while (h); } movd_r2g(mm5, sum1); psrlq_i2r(32, mm5); movd_r2g(mm5, sum2); sum = sum1 + sum2; emms(); return sum; } /* * total squared difference between interpolation of two (8*h) blocks and * another 8*h block * blk1,blk2: addresses of top left pels of both blocks * lx: distance (in bytes) of vertically adjacent pels * h: height of block (usually 4, or 8) * mmX version */ int bsumsq_sub22_mmx(uint8_t *blk1f, uint8_t *blk1b, uint8_t *blk2, int lx, int h) { static const uint16_t ones[4]={1,1,1,1}; int sum,sum1,sum2; pxor_r2r(mm5, mm5); if (h > 0) { pxor_r2r(mm7, mm7); do { /* bd2top22 */ movq_m2r(blk1f[0], mm0); movq_r2r(mm0, mm1); movq_m2r(blk1b[0], mm4); movq_r2r(mm4, mm6); punpcklbw_r2r(mm7, mm0); punpckhbw_r2r(mm7, mm1); punpcklbw_r2r(mm7, mm4); punpckhbw_r2r(mm7, mm6); movq_m2r(blk2[0], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); paddw_r2r(mm4, mm0); paddw_m2r(*ones, mm0); psrlw_i2r(1, mm0); psubw_r2r(mm2, mm0); pmaddwd_r2r(mm0, mm0); paddw_r2r(mm6, mm1); paddw_m2r(*ones, mm1); psrlw_i2r(1, mm1); psubw_r2r(mm3, mm1); pmaddwd_r2r(mm1, mm1); paddd_r2r(mm0, mm5); paddd_r2r(mm1, mm5); blk1f += lx; blk1b += lx; blk2 += lx; h--; } while (h); } movd_r2g(mm5, sum1); psrlq_i2r(32, mm5); movd_r2g(mm5, sum2); sum = sum1 + sum2; emms(); return sum; } /* * variance of a (size*size) block, multiplied by 256 * p: address of top left pel of block * lx: seperation (in bytes) of vertically adjacent pels * NOTE: size is 8 or 16 */ void variance_mmx(uint8_t *p, int size, int lx, unsigned int *p_var, unsigned int *p_mean) { uint8_t *p2; int col, row; unsigned int sum, sum_squared, squares_sum; /* * Use of MMX registers * mm0 = <0,0,0,0> * mm6 = Sum pixel squared * mm7 = Sum pixels */ pxor_r2r(mm0, mm0); pxor_r2r(mm7, mm7); /* Zero sum accumulator (4 words) */ pxor_r2r(mm6, mm6); /* Zero squares accumulator (2 dwords) */ for(col=0; col *p_mean */ /* Squares sum - sum squares / (size*size) -> *p_var */ sum >>= 6; /* Divide sum and sum squared by 64 for 8*8 */ sum_squared >>= 6; if (size != 8) /* If 16 * 16 divide again by 4 (256) */ { sum >>= 2; sum_squared >>= 2; } *p_mean = sum; *p_var = squares_sum-sum_squared; emms(); } mjpegtools-2.1.0/utils/mmxsse/mblock_bsumsq_mmx.c0000644000175000017500000001300410163446102022546 0ustar glowwormglowworm/* * bdist2_mmx.s: MMX optimized bidirectional squared distance sum * * Original believed to be Copyright (C) 2000 Brent Byeler * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "mjpeg_types.h" #include "mmx.h" /* * squared error between a (16*h) block and a bidirectional * prediction * * p2: address of top left pel of block * pf,hxf,hyf: address and half pel flags of forward ref. block * pb,hxb,hyb: address and half pel flags of backward ref. block * h: height of block * lx: distance (in bytes) of vertically adjacent pels in p2,pf,pb * mmX version */ int bsumsq_mmx(uint8_t *pf, uint8_t *pb, uint8_t *p2, int lx, int hxf, int hyf, int hxb, int hyb, int h) { uint8_t *pfa,*pfb,*pfc,*pba,*pbb,*pbc; int s,s1,s2; pfa = pf + hxf; pfb = pf + lx * hyf; pfc = pfb + hxf; pba = pb + hxb; pbb = pb + lx * hyb; pbc = pbb + hxb; s = 0; /* (accumulated sum) */ if (h > 0) { pxor_r2r(mm7, mm7); pxor_r2r(mm6, mm6); pcmpeqw_r2r(mm5, mm5); psubw_r2r(mm5, mm6); psllw_i2r(1, mm6); do { movq_m2r(pf[0], mm0); movq_r2r(mm0, mm1); punpcklbw_r2r(mm7, mm0); punpckhbw_r2r(mm7, mm1); movq_m2r(pfa[0], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); paddw_r2r(mm2, mm0); paddw_r2r(mm3, mm1); movq_m2r(pfb[0], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); paddw_r2r(mm2, mm0); paddw_r2r(mm3, mm1); movq_m2r(pfc[0], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); paddw_r2r(mm2, mm0); paddw_r2r(mm3, mm1); paddw_r2r(mm6, mm0); paddw_r2r(mm6, mm1); psrlw_i2r(2, mm0); psrlw_i2r(2, mm1); movq_m2r(pb[0], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); movq_m2r(pba[0], mm4); movq_r2r(mm4, mm5); punpcklbw_r2r(mm7, mm4); punpckhbw_r2r(mm7, mm5); paddw_r2r(mm4, mm2); paddw_r2r(mm5, mm3); movq_m2r(pbb[0], mm4); movq_r2r(mm4, mm5); punpcklbw_r2r(mm7, mm4); punpckhbw_r2r(mm7, mm5); paddw_r2r(mm4, mm2); paddw_r2r(mm5, mm3); movq_m2r(pbc[0], mm4); movq_r2r(mm4, mm5); punpcklbw_r2r(mm7, mm4); punpckhbw_r2r(mm7, mm5); paddw_r2r(mm4, mm2); paddw_r2r(mm5, mm3); paddw_r2r(mm6, mm2); paddw_r2r(mm6, mm3); psrlw_i2r(2, mm2); psrlw_i2r(2, mm3); paddw_r2r(mm2, mm0); paddw_r2r(mm3, mm1); psrlw_i2r(1, mm6); paddw_r2r(mm6, mm0); paddw_r2r(mm6, mm1); psllw_i2r(1, mm6); psrlw_i2r(1, mm0); psrlw_i2r(1, mm1); movq_m2r(p2[0], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); psubw_r2r(mm2, mm0); psubw_r2r(mm3, mm1); pmaddwd_r2r(mm0, mm0); pmaddwd_r2r(mm1, mm1); paddd_r2r(mm1, mm0); movd_r2g(mm0, s1); psrlq_i2r(32, mm0); movd_r2g(mm0, s2); s += s1 + s2; movq_m2r(pf[8], mm0); movq_r2r(mm0, mm1); punpcklbw_r2r(mm7, mm0); punpckhbw_r2r(mm7, mm1); movq_m2r(pfa[8], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); paddw_r2r(mm2, mm0); paddw_r2r(mm3, mm1); movq_m2r(pfb[8], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); paddw_r2r(mm2, mm0); paddw_r2r(mm3, mm1); movq_m2r(pfc[8], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); paddw_r2r(mm2, mm0); paddw_r2r(mm3, mm1); paddw_r2r(mm6, mm0); paddw_r2r(mm6, mm1); psrlw_i2r(2, mm0); psrlw_i2r(2, mm1); movq_m2r(pb[8], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); movq_m2r(pba[8], mm4); movq_r2r(mm4, mm5); punpcklbw_r2r(mm7, mm4); punpckhbw_r2r(mm7, mm5); paddw_r2r(mm4, mm2); paddw_r2r(mm5, mm3); movq_m2r(pbb[8], mm4); movq_r2r(mm4, mm5); punpcklbw_r2r(mm7, mm4); punpckhbw_r2r(mm7, mm5); paddw_r2r(mm4, mm2); paddw_r2r(mm5, mm3); movq_m2r(pbc[8], mm4); movq_r2r(mm4, mm5); punpcklbw_r2r(mm7, mm4); punpckhbw_r2r(mm7, mm5); paddw_r2r(mm4, mm2); paddw_r2r(mm5, mm3); paddw_r2r(mm6, mm2); paddw_r2r(mm6, mm3); psrlw_i2r(2, mm2); psrlw_i2r(2, mm3); paddw_r2r(mm2, mm0); paddw_r2r(mm3, mm1); psrlw_i2r(1, mm6); paddw_r2r(mm6, mm0); paddw_r2r(mm6, mm1); psllw_i2r(1, mm6); psrlw_i2r(1, mm0); psrlw_i2r(1, mm1); movq_m2r(p2[8], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); psubw_r2r(mm2, mm0); psubw_r2r(mm3, mm1); pmaddwd_r2r(mm0, mm0); pmaddwd_r2r(mm1, mm1); paddd_r2r(mm1, mm0); movd_r2g(mm0, s1); psrlq_i2r(32, mm0); movd_r2g(mm0, s2); s += s1 + s2; p2 += lx; pf += lx; pfa += lx; pfb += lx; pfc += lx; pb += lx; pba += lx; pbb += lx; pbc += lx; h--; } while(h > 0); } emms(); return s; } mjpegtools-2.1.0/utils/mmxsse/mblock_sub44_sads_x86_h.c0000644000175000017500000000616010177070532023354 0ustar glowwormglowworm/* * * mblock_sub44_sads_x86_h.c * Copyright (C) 2000 Andrew Stevens * * Fast block sum-absolute difference computation for a rectangular area 4*x * by y where y > h against a 4 by h block. * * Used for 4*4 sub-sampled motion compensation calculations. * * * This file is part of mpeg2enc, a free MPEG-2 video stream encoder * based on the original MSSG reference design * * mpeg2enc is free software; you can redistribute new parts * and/or modify under the terms of the GNU General Public License * as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * mpeg2enc is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * See the files for those sections (c) MSSG * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #define PREFETCH_OPT /* * * Generates a vector sad's for 4*4 sub-sampled pel (qpel) data (with * co-ordinates and top-left qpel address) from specified rectangle * against a specified 16*h pel (4*4 qpel) reference block. The * generated vector contains results only for those sad's that fall * below twice the running best sad and are aligned on 8-pel * boundaries * * Invariant: blk points to top-left sub-sampled pel for macroblock * at (ilow,ihigh) * i{low,high) j(low,high) must be multiples of 4. * * sad = Sum Absolute Differences * * NOTES: for best efficiency i{low,high) should be multiples of 16. * * */ int SIMD_SUFFIX(mblocks_sub44_mests)( uint8_t *blk, uint8_t *ref, int ilow,int jlow, int ihigh, int jhigh, int h, int rowstride, int threshold, me_result_s *resvec) { int32_t x,y; uint8_t *currowblk = blk; uint8_t *curblk; me_result_s *cres = resvec; int gridrowstride = rowstride; int weight; SIMD_SUFFIX(init_qblock_sad)(ref, h, rowstride); for( y=jlow; y <= jhigh ; y+=4) { curblk = currowblk; // You'd think prefetching curblk+4*rowstride would help here. // I have found *NO* measurable increase in performance... for( x = ilow; x <= ihigh; x += 4) { if( (x & 15) == (ilow & 15) ) { load_blk( curblk, rowstride, h ); curblk += 4; } weight = SIMD_SUFFIX(qblock_sad)(ref, h, rowstride); shift_blk(8); if( weight <= threshold ) { threshold = intmin(weight<<2,threshold); /* Rough and-ready absolute distance penalty */ /* NOTE: This penalty is *vital* to correct operation as otherwise the sub-mean filtering won't work on very uniform images. */ cres->weight = (uint16_t)(weight+(intmax(abs(x),abs(y))<<2)); cres->x = (uint8_t)x; cres->y = (uint8_t)y; ++cres; } } currowblk += gridrowstride; } emms(); return cres - resvec; } mjpegtools-2.1.0/utils/mmxsse/mblock_sub44_sads_x86.c0000644000175000017500000001333010314351424023035 0ustar glowwormglowworm/* * * mblock_sub44_sads.c * Copyright (C) 2000 Andrew Stevens * * Fast block sum-absolute difference computation for a rectangular area 4*x * by y where y > h against a 4 by h block. * * Used for 4*4 sub-sampled motion compensation calculations. * * This is actually just a shell that uses templates from the included * file "mblock_sub44_sads_x86_h.c". I didn't trust the compiler to do a good * job on nested inlining. One day I'll experiment. * * * This file is part of mpeg2enc, a free MPEG-2 video stream encoder * based on the original MSSG reference design * * mpeg2enc is free software; you can redistribute new parts * and/or modify under the terms of the GNU General Public License * as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * mpeg2dec is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * See the files for those sections (c) MSSG * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "mjpeg_types.h" #include "mmx.h" #include "fastintfns.h" #include "motionsearch.h" #include "mblock_sub44_sads_x86.h" /* * Load a 8*4 block of 4*4 sub-sampled pels (qpels) into the MMX * registers * */ static inline void load_blk(uint8_t *blk,uint32_t rowstride,int h) { movq_m2r( *blk, mm0); movq_m2r( *(blk+rowstride), mm1); blk += 2*rowstride; if( h == 2 ) return; movq_m2r( *blk, mm2); movq_m2r( *(blk+rowstride), mm3); } /* * Do a shift right on the 4*4 block in the MMX registers * We do this as a macro as otherwise we get warnings from the * pre-optimised asm generated. */ #define shift_blk(shift)\ psrlq_i2r( shift,mm0);\ psrlq_i2r( shift,mm1);\ psrlq_i2r( shift,mm2);\ psrlq_i2r( shift,mm3); /* * Compute the Sum absolute differences between the 4*h block in * the MMX registers (4 least sig. bytes in mm0..mm3) * * and the 4*h block pointed to by refblk * * h == 2 || h == 4 * * TODO: Currently always loads and shifts 4*4 even if 4*2 is required. * */ static inline void init_qblock_sad_mmxe(uint8_t *refblk,uint32_t h,uint32_t rowstride) { /* load refblk into mm6 and mm7 */ movd_m2r(refblk[0],mm6); movd_m2r(refblk[rowstride],mm4); punpcklbw_r2r(mm4,mm6); if( h == 4 ) { refblk+=rowstride*2; movd_m2r(refblk[0],mm7); movd_m2r(refblk[rowstride],mm5); punpcklbw_r2r(mm5,mm7); } else { pxor_r2r(mm7,mm7); pxor_r2r(mm2,mm2); pxor_r2r(mm3,mm3); } } static inline int qblock_sad_mmxe(uint8_t *refblk, uint32_t h, uint32_t rowstride) { int res; /* On input, mm0 = first row mm1 = second row mm2 = third row mm3 = fourth row mm6 = refblk for first and second roww packed together (ala init_qblock_sad_mmxe) mm7 = refblk for third and fourth rows packed together (ala init_qblock_sad_mmxe) */ /* Do the first two rows together, by packing the two rows of 4 bytes into one eight byte register; then perform only one SAD for both rows at once. */ movq_r2r (mm0,mm4); punpcklbw_r2r(mm1,mm4); psadbw_r2r (mm6,mm4); movq_r2r (mm2,mm5); punpcklbw_r2r(mm3,mm5); psadbw_r2r (mm7,mm5); paddw_r2r (mm5,mm4); movd_r2g ( mm4, res ); return res; } /* Register usage: mm0-mm3 Hold the current row mm4 Used for accumulating partial SAD */ static inline void init_qblock_sad_mmx(uint8_t *refblk,uint32_t h,uint32_t rowstride) { } static inline int qblock_sad_mmx(uint8_t *refblk, uint32_t h, uint32_t rowstride) { int res; pxor_r2r (mm4,mm4); movq_r2r (mm0,mm5); /* First row */ movd_m2r (*refblk, mm6); pxor_r2r ( mm7, mm7); refblk += rowstride; punpcklbw_r2r ( mm7, mm5); punpcklbw_r2r ( mm7, mm6); movq_r2r ( mm5, mm7); psubusw_r2r ( mm6, mm5); psubusw_r2r ( mm7, mm6); paddw_r2r ( mm5, mm4); paddw_r2r ( mm6, mm4 ); movq_r2r (mm1,mm5); /* Second row */ movd_m2r (*refblk, mm6); pxor_r2r ( mm7, mm7); refblk += rowstride; punpcklbw_r2r ( mm7, mm5); punpcklbw_r2r ( mm7, mm6); movq_r2r ( mm5, mm7); psubusw_r2r ( mm6, mm5); psubusw_r2r ( mm7, mm6); paddw_r2r ( mm5, mm4); paddw_r2r ( mm6, mm4 ); if( h == 4 ) { movq_r2r (mm2,mm5); /* Third row */ movd_m2r (*refblk, mm6); pxor_r2r ( mm7, mm7); refblk += rowstride; punpcklbw_r2r ( mm7, mm5); punpcklbw_r2r ( mm7, mm6); movq_r2r ( mm5, mm7); psubusw_r2r ( mm6, mm5); psubusw_r2r ( mm7, mm6); paddw_r2r ( mm5, mm4); paddw_r2r ( mm6, mm4 ); movq_r2r (mm3,mm5); /* Fourth row */ movd_m2r (*refblk, mm6); pxor_r2r ( mm7, mm7); punpcklbw_r2r ( mm7, mm5); punpcklbw_r2r ( mm7, mm6); movq_r2r ( mm5, mm7); psubusw_r2r ( mm6, mm5); psubusw_r2r ( mm7, mm6); paddw_r2r ( mm5, mm4); paddw_r2r ( mm6, mm4 ); } movq_r2r ( mm4, mm5 ); psrlq_i2r ( 32, mm5 ); paddw_r2r ( mm5, mm4 ); movq_r2r ( mm4, mm6 ); psrlq_i2r ( 16, mm6 ); paddw_r2r ( mm6, mm4 ); movd_r2g ( mm4, res ); return res & 0xffff; } /* * Do the Extended MMX versions */ #define SIMD_SUFFIX(x) x##_mmxe #include "mblock_sub44_sads_x86_h.c" #undef SIMD_SUFFIX /* * Do the original MMX versions */ #define SIMD_SUFFIX(x) x##_mmx #include "mblock_sub44_sads_x86_h.c" #undef SIMD_SUFFIX mjpegtools-2.1.0/utils/mmxsse/mblock_sub44_sads_x86.h0000644000175000017500000000237207771103762023063 0ustar glowwormglowworm/* (C) 2000/2002 Andrew Stevens */ /* This software is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #ifndef __MBLOCK_SUB44_SADS_X86_H__ #define __MBLOCK_SUB44_SADS_X86__ #include "mjpeg_types.h" int mblocks_sub44_mests_mmxe( uint8_t *blk, uint8_t *ref, int ilow, int jlow, int ihigh, int jhigh, int h, int rowstride, int threshold, me_result_s *resvec); int mblocks_sub44_mests_mmx( uint8_t *blk, uint8_t *ref, int ilow, int jlow, int ihigh, int jhigh, int threshold, int h, int rowstride, me_result_s *resvec); #endif mjpegtools-2.1.0/utils/mmxsse/find_best_one_pel.c0000644000175000017500000000300010222165716022462 0ustar glowwormglowworm#include "config.h" #include #include #include #include "mmxsse_motion.h" #include "fastintfns.h" void find_best_one_pel_mmxe( me_result_set *sub22set, uint8_t *org, uint8_t *blk, int i0, int j0, int ihigh, int jhigh, int rowstride, int h, me_result_s *best_so_far ) { int i,k; int d; me_result_s minpos = *best_so_far; int ilim = ihigh-i0; int jlim = jhigh-j0; int dmin = INT_MAX; uint8_t *orgblk; int penalty; me_result_s matchrec; int32_t resvec[4]; for( k = 0; k < sub22set->len; ++k ) { int x; matchrec = sub22set->mests[k]; orgblk = org + (i0+matchrec.x)+rowstride*(j0+matchrec.y); penalty = (abs(matchrec.x) + abs(matchrec.y))<<3; /* Get SAD for macroblocks: orgblk,orgblk(+1,0), orgblk(0,+1), and orgblk(+1,+1) Done all in one go to reduce memory bandwidth demand */ if( penalty>=dmin ) continue; x=mblock_nearest4_sads_mmxe(orgblk,blk,rowstride,h,resvec,dmin-penalty); if( x+penalty>=dmin ) continue; for( i = 0; i < 4; ++i ) { if( matchrec.x <= ilim && matchrec.y <= jlim ) { d = penalty+resvec[i]; if (d/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = utils/mmxsse DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libmmxsse_la_LIBADD = am_libmmxsse_la_OBJECTS = build_sub22_mests.lo build_sub44_mests.lo \ find_best_one_pel.lo mblock_sad_mmx.lo mblock_sad_mmxe.lo \ mblock_sub44_sads_x86.lo mblock_sumsq_mmx.lo \ mblock_bsumsq_mmx.lo mblock_bsad_mmx.lo motion.lo libmmxsse_la_OBJECTS = $(am_libmmxsse_la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libmmxsse_la_SOURCES) DIST_SOURCES = $(libmmxsse_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALTIVEC_EXTRA_LIBS = @ALTIVEC_EXTRA_LIBS@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDV_CFLAGS = @LIBDV_CFLAGS@ LIBDV_LIBS = @LIBDV_LIBS@ LIBGETOPT_LIB = @LIBGETOPT_LIB@ LIBM_LIBS = @LIBM_LIBS@ LIBOBJS = @LIBOBJS@ LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ LIBPNG_LIBS = @LIBPNG_LIBS@ LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@ LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ LT_STATIC = @LT_STATIC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROGRAM_NOPIC = @PROGRAM_NOPIC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ SDLgfx_LIBS = @SDLgfx_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ V4LCONF_LIBS = @V4LCONF_LIBS@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/utils noinst_LTLIBRARIES = libmmxsse.la libmmxsse_la_SOURCES = \ build_sub22_mests.c \ build_sub44_mests.c \ find_best_one_pel.c \ mblock_sad_mmx.c \ mblock_sad_mmxe.c \ mblock_sub44_sads_x86.c \ mblock_sumsq_mmx.c \ mblock_bsumsq_mmx.c \ mblock_bsad_mmx.c \ motion.c noinst_HEADERS = \ mblock_sub44_sads_x86.h \ mmxsse_motion.h EXTRA_DIST = \ mblock_sub44_sads_x86_h.c MAINTAINERCLEANFILES = Makefile.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu utils/mmxsse/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu utils/mmxsse/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libmmxsse.la: $(libmmxsse_la_OBJECTS) $(libmmxsse_la_DEPENDENCIES) $(EXTRA_libmmxsse_la_DEPENDENCIES) $(LINK) $(libmmxsse_la_OBJECTS) $(libmmxsse_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/build_sub22_mests.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/build_sub44_mests.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/find_best_one_pel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mblock_bsad_mmx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mblock_bsumsq_mmx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mblock_sad_mmx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mblock_sad_mmxe.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mblock_sub44_sads_x86.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mblock_sumsq_mmx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/motion.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist ctags \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mjpegtools-2.1.0/utils/mmxsse/mblock_sad_mmxe.c0000644000175000017500000002713510370237326022170 0ustar glowwormglowworm/* ;;; ;;; mblock_sad_mmxe.s: ;;; ;;; Enhanced MMX optimized Sum Absolute Differences routines for macroblocks ;;; (interpolated, 1-pel, 2*2 sub-sampled pel and 4*4 sub-sampled pel) ; ; Original MMX sad_* Copyright (C) 2000 Chris Atenasio ; Enhanced MMX and rest Copyright (C) 2000 Andrew Stevens ;; Yes, I tried prefetch-ing. It makes no difference or makes ;; stuff *slower*. ; ; This program is free software; you can reaxstribute it and/or ; modify it under the terms of the GNU General Public License ; as published by the Free Software Foundation; either version 2 ; of the License, or (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ; ; ; */ #include #include #include #include "mjpeg_types.h" #include "mmx.h" #include "mmxsse_motion.h" #define SHUFFLEMAP(A,B,C,D) ((A)*1+(B)*4+(C)*16+(D)*64) int sad_00_mmxe(uint8_t *blk1,uint8_t *blk2,int rowstride,int h,int distlim) { int32_t rv; pxor_r2r(mm0,mm0); // accumulator do { movq_m2r (blk1[0],mm4); psadbw_m2r(blk2[0],mm4); movq_m2r (blk1[8],mm6); psadbw_m2r(blk2[8],mm6); blk1+=rowstride; paddd_r2r (mm4, mm0); blk2+=rowstride; paddd_r2r (mm6, mm0); movq_m2r (blk1[0],mm4); psadbw_m2r(blk2[0],mm4); movq_m2r (blk1[8],mm6); psadbw_m2r(blk2[8],mm6); blk1+=rowstride; paddd_r2r (mm4, mm0); blk2+=rowstride; paddd_r2r (mm6, mm0); h-=2; } while(h); movd_r2g(mm0, rv); emms(); return rv; } int sad_01_mmxe(uint8_t *blk1,uint8_t *blk2,int rowstride,int h) { int32_t rv; pxor_r2r(mm0,mm0); // accumulator do { movq_m2r (blk1[0],mm4); pavgb_m2r (blk1[1],mm4); psadbw_m2r(blk2[0],mm4); movq_m2r (blk1[8],mm6); pavgb_m2r (blk1[9],mm6); psadbw_m2r(blk2[8],mm6); blk1+=rowstride; paddd_r2r (mm4, mm0); blk2+=rowstride; paddd_r2r (mm6, mm0); movq_m2r (blk1[0],mm4); pavgb_m2r (blk1[1],mm4); psadbw_m2r(blk2[0],mm4); movq_m2r (blk1[8],mm6); pavgb_m2r (blk1[9],mm6); psadbw_m2r(blk2[8],mm6); blk1+=rowstride; paddd_r2r (mm4, mm0); blk2+=rowstride; paddd_r2r (mm6, mm0); h-=2; } while(h); movd_r2g(mm0, rv); emms(); return rv; } int sad_10_mmxe(uint8_t *blk1,uint8_t *blk2,int rowstride,int h) { int32_t rv; pxor_r2r(mm0,mm0); // accumulator movq_m2r(blk1[0],mm4); movq_m2r(blk1[8],mm6); blk1+=rowstride; do { movq_m2r (blk1[0],mm5); pavgb_r2r (mm5,mm4); psadbw_m2r(blk2[0],mm4); movq_m2r (blk1[8],mm7); pavgb_r2r (mm7,mm6); psadbw_m2r(blk2[8],mm6); blk1+=rowstride; paddd_r2r (mm4, mm0); blk2+=rowstride; paddd_r2r (mm6, mm0); movq_m2r (blk1[0],mm4); pavgb_r2r (mm4,mm5); psadbw_m2r(blk2[0],mm5); movq_m2r (blk1[8],mm6); pavgb_r2r (mm6,mm7); psadbw_m2r(blk2[8],mm7); blk1+=rowstride; paddd_r2r (mm5, mm0); blk2+=rowstride; paddd_r2r (mm7, mm0); h-=2; } while(h); movd_r2g(mm0, rv); emms(); return rv; } int sad_11_mmxe_fast(uint8_t *blk1,uint8_t *blk2,int rowstride,int h) { int l = h; int32_t rv; uint8_t *b1,*b2; pxor_r2r(mm6,mm6); // zero accumulator b1=blk1; b2=blk2; movq_m2r(b1[0],mm0); // Invariant mm0mm1 - current row H interpolated movq_m2r(b1[8],mm1); pavgb_m2r(b1[1],mm0); pavgb_m2r(b1[9],mm1); b1 += rowstride; do { movq_m2r(b1[0],mm2); // mm2mm3 := next row H interpolated movq_m2r(b1[8],mm3); pavgb_m2r(b1[1],mm2); pavgb_m2r(b1[9],mm3); b1+=rowstride; movq_r2r( mm2, mm4 ); // mm4mm5 := interpolate mm0mm1 and mm2mm3 movq_r2r( mm3, mm5 ); // I.e. H and V interpolated pixels pavgb_r2r( mm0, mm4 ); // Interleaved with mm0mm1 := mm2mm3 movq_r2r( mm2, mm0 ); pavgb_r2r( mm1, mm5 ); movq_r2r( mm3, mm1 ); psadbw_m2r(b2[0],mm4); // mm4mm5 := SAD H+H interpolated with block b1 psadbw_m2r(b2[8],mm5); b2+=rowstride; paddd_r2r(mm4,mm6); // Accumulated SAD paddd_r2r(mm5,mm6); l--; } while(l); movd_r2g(mm6, rv); emms(); return rv; } int sad_11_mmxe(uint8_t *blk1,uint8_t *blk2,int rowstride,int h) { int l; int32_t rv; uint8_t *b1,*b2; static int16_t two[4]={2,2,2,2}; #define SAD11_UNPACK(src,r1,r2) \ movq_m2r(src,r1); \ movq_r2r(r1,r2); \ punpcklbw_r2r(mm1,r1); \ punpckhbw_r2r(mm1,r2); pxor_r2r(mm0,mm0); // accumulator pxor_r2r(mm1,mm1); // zero value b1=blk1; b2=blk2; l=h; SAD11_UNPACK(b1[0],mm6,mm7); SAD11_UNPACK(b1[1],mm2,mm3); paddw_r2r(mm2,mm6); paddw_r2r(mm3,mm7); // mm6mm7 := 'sums of neighbouring pixels, prev row' b1+=rowstride; do { SAD11_UNPACK(b1[0],mm2,mm3); SAD11_UNPACK(b1[1],mm4,mm5); paddw_m2r(*two,mm6); paddw_m2r(*two,mm7); paddw_r2r(mm4,mm2); paddw_r2r(mm5,mm3); // mm2mm3 := 'sums of neighbouring pixels, cur row' paddw_r2r(mm2,mm6); paddw_r2r(mm3,mm7); psrlw_i2r(2,mm6); psrlw_i2r(2,mm7); packuswb_r2r(mm7,mm6); //mm6mm7 := 'mean neighbouring pixels prev + cur row' psadbw_m2r(b2[0],mm6); paddd_r2r(mm6,mm0); b1+=rowstride; b2+=rowstride; movq_r2r(mm2,mm6); movq_r2r(mm3,mm7); l--; } while(l); b1=blk1+8; b2=blk2+8; l=h; SAD11_UNPACK(b1[0],mm6,mm7); SAD11_UNPACK(b1[1],mm2,mm3); paddw_r2r(mm2,mm6); paddw_r2r(mm3,mm7); b1+=rowstride; do { SAD11_UNPACK(b1[0],mm2,mm3); SAD11_UNPACK(b1[1],mm4,mm5); paddw_m2r(*two,mm6); paddw_m2r(*two,mm7); paddw_r2r(mm4,mm2); paddw_r2r(mm5,mm3); paddw_r2r(mm2,mm6); paddw_r2r(mm3,mm7); psrlw_i2r(2,mm6); psrlw_i2r(2,mm7); packuswb_r2r(mm7,mm6); psadbw_m2r(b2[0],mm6); paddd_r2r(mm6,mm0); b1+=rowstride; b2+=rowstride; movq_r2r(mm2,mm6); movq_r2r(mm3,mm7); l--; } while(l); #undef SAD11_UNPACK movd_r2g(mm0, rv); emms(); // int nrv = sad_11_mmxe_fast( blk1, blk2, rowstride, h ); // if( abs(nrv-rv) > 8 ) // printf( "Ooops %d\n", nrv-rv ); return rv; } int sad_sub22_mmxe(uint8_t *blk1,uint8_t *blk2,int rowstride,int h) { int32_t rv; pxor_r2r(mm0,mm0); // accumulator do { movq_m2r (blk1[0],mm4); blk1+=rowstride; psadbw_m2r(blk2[0],mm4); blk2+=rowstride; paddd_r2r (mm4, mm0); movq_m2r (blk1[0],mm4); blk1+=rowstride; psadbw_m2r(blk2[0],mm4); blk2+=rowstride; paddd_r2r (mm4, mm0); h-=2; } while(h); movd_r2g(mm0, rv); emms(); return rv; } int sad_sub44_mmxe(uint8_t *blk1,uint8_t *blk2,int rowstride,int h) { int32_t rv; pxor_r2r(mm0,mm0); // accumulator do { // only perform one at a time; h might be 1 movd_m2r (blk1[0],mm4); movd_m2r (blk2[0],mm5); psadbw_r2r(mm5,mm4); blk1+=rowstride; blk2+=rowstride; paddd_r2r (mm4, mm0); h-=1; } while(h); movd_r2g(mm0, rv); emms(); return rv; } /* ;;; ;;; mblock_*nearest4_sad_mmxe.s: ;;; ;;; Enhanced MMX optimized Sum Absolute Differences routines for ;;; quads macroblocks offset by (0,0) (0,1) (1,0) (1,1) pel ;;; ;;; Explanation: the motion compensation search at 1-pel and 2*2 sub-sampled ;;; evaluates macroblock quads. A lot of memory accesses can be saved ;;; if each quad is done together rather than each macroblock in the ;;; quad handled individually. ;;; TODO: Really there ought to be MMX versions and the function's ;;; specification should be documented... ; ; Copyright (C) 2000 Andrew Stevens */ /* ; mm0 = SAD (x+0,y+0),SAD (x+2,y+0) ; mm1 = SAD (x+0,y+2),SAD (x+2,y+2) ; mm2 = blk1[0] cache ; mm3 = blk1[8] cache ; mm4 = blk1[1] cache ; mm5 = blk1[9] cache ; mm6 = blk2[0] cache ; mm7 = blk2[8] cache */ int mblock_nearest4_sads_mmxe(uint8_t *blk1,uint8_t *blk2,int lx,int h,int32_t *weightvec,int peakerror) { int32_t rv; movq_m2r(blk1[0],mm2); movq_m2r(blk1[8],mm3); movq_m2r(blk1[1],mm4); movq_m2r(blk1[9],mm5); pxor_r2r(mm0,mm0); // zero accumulators pxor_r2r(mm1,mm1); do { /* Yes, the idea of using packssdw is kinda silly. But it efficiently moves the result into place, reducing the number of instructions. Instead of: mm0 += mm2; mm4 <<= 32; mm0 += mm4; we get: mm2 = pack(mm4,mm2); mm0 += mm2; Yes, this makes a difference (though admittedly slight). */ movq_m2r(blk2[0],mm6); psadbw_r2r(mm6,mm2); psadbw_r2r(mm6,mm4); packssdw_r2r(mm4,mm2); paddd_r2r(mm2,mm0); movq_m2r(blk2[8],mm7); psadbw_r2r(mm7,mm3); psadbw_r2r(mm7,mm5); packssdw_r2r(mm5,mm3); paddd_r2r(mm3,mm0); // advance pointers to next row blk1+=lx; blk2+=lx; // check for early exit movq_r2r(mm1, mm3); pminsw_r2r(mm0,mm3); pshufw_r2ri(mm3,mm2,SHUFFLEMAP(2,3,0,1)); pminsw_r2r(mm2,mm3); movd_r2g(mm3,rv); if( rv > peakerror ) goto safeexit; movq_m2r(blk1[0],mm2); movq_m2r(blk1[1],mm4); movq_r2r(mm6,mm3); psadbw_r2r(mm2,mm6); psadbw_r2r(mm4,mm3); packssdw_r2r(mm3,mm6); paddd_r2r(mm6,mm1); movq_m2r(blk1[8],mm3); movq_m2r(blk1[9],mm5); movq_r2r(mm7,mm6); psadbw_r2r(mm3,mm7); psadbw_r2r(mm5,mm6); packssdw_r2r(mm6,mm7); paddd_r2r(mm7,mm1); h--; } while(h); movq_r2m(mm0,weightvec[0]); movq_r2m(mm1,weightvec[2]); pminsw_r2r(mm1,mm0); pshufw_r2ri(mm0,mm1,SHUFFLEMAP(2,3,0,1)); pminsw_r2r(mm1,mm0); movd_r2g(mm0,rv); safeexit: emms(); return rv; } void mblock_sub22_nearest4_sads_mmxe(uint8_t *blk1, uint8_t *blk2, int rowstride, int h, int32_t *resvec) { pxor_r2r(mm0, mm0); pxor_r2r(mm1, mm1); movq_m2r(blk1[0], mm2); movq_m2r(blk1[1], mm3); do { movq_m2r(blk2[0], mm5); psadbw_r2r(mm5, mm2); psadbw_r2r(mm5, mm3); packssdw_r2r(mm3,mm2); paddd_r2r(mm2,mm0); blk1+=rowstride; blk2+=rowstride; movq_m2r(blk1[0], mm2); movq_m2r(blk1[1], mm3); movq_r2r(mm5, mm6); psadbw_r2r(mm2, mm5); psadbw_r2r(mm3, mm6); packssdw_r2r(mm6,mm5); paddd_r2r(mm5,mm1); h--; } while(h); movq_r2m(mm0,resvec[0]); movq_r2m(mm1,resvec[2]); emms(); } mjpegtools-2.1.0/utils/mmxsse/mblock_sad_mmx.c0000644000175000017500000006022310164611442022012 0ustar glowwormglowworm/* * mblock_sad_mmxe.s: * * * Enhanced MMX optimized Sum Absolute Differences routines for macroblocks * (interpolated, 1-pel, 2*2 sub-sampled pel and 4*4 sub-sampled pel) * * sad_* Original Copyright (C) 2000 Chris Atenasio * Enhancements and rest Copyright (C) 2000 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "mjpeg_types.h" #include "mmx.h" int sad_00_mmx(uint8_t *blk1,uint8_t *blk2,int lx,int h, int distlim) { int rv; /* * N.b. distlim is *ignored* as testing for it is more expensive than the * occasional saving by aborting the computionation early... * * mm0 = distance accumulators (4 words) * mm1 = temp * mm2 = temp * mm3 = temp * mm4 = temp * mm5 = temp * mm6 = 0 * mm7 = temp */ pxor_r2r(mm0, mm0); pxor_r2r(mm6, mm6); do { movq_m2r(blk1[0], mm4); /* load first 8 bytes of p1 row */ movq_m2r(blk2[0], mm5); /* load first 8 bytes of p2 row */ movq_r2r(mm4, mm7); /* mm5 = abs(mm4-mm5) */ psubusb_r2r(mm5, mm7); psubusb_r2r(mm4, mm5); paddb_r2r(mm7, mm5); /* Add the abs(mm4-mm5) bytes to the accumulators */ movq_m2r(blk1[8], mm2); /* load second 8 bytes of p1 row (interleaved) */ movq_r2r(mm5, mm7); /* mm7 := [i : B0..3, mm1]W */ punpcklbw_r2r(mm6, mm7); movq_m2r(blk2[8], mm3); paddw_r2r(mm7, mm0); punpckhbw_r2r(mm6, mm5); paddw_r2r(mm5, mm0); /* This is logically where the mm2, mm3 loads would go... */ movq_r2r(mm2, mm7); /* mm3 = abs(mm2-mm3) */ psubusb_r2r(mm3, mm7); psubusb_r2r(mm2, mm3); paddb_r2r(mm7, mm3); /* Add the abs(mm4-mm5) bytes to the accumulators */ movq_r2r(mm3, mm7); punpcklbw_r2r(mm6, mm7); punpckhbw_r2r(mm6, mm3); paddw_r2r(mm7, mm0); blk1 += lx; /* update pointers to next row */ blk2 += lx; paddw_r2r(mm3, mm0); h--; } while(h); /* Sum the Accumulators */ movq_r2r(mm0, mm5); /* mm5 := [W0+W2,W1+W3, mm0 */ psrlq_i2r(32, mm5); movq_r2r(mm0, mm4); paddw_r2r(mm5, mm4); movq_r2r(mm4, mm7); /* mm6 := [W0+W2+W1+W3, mm0] */ psrlq_i2r(16, mm7); paddw_r2r(mm7, mm4); movd_r2g(mm4, rv); /* store return value */ rv &= 0xffff; emms(); return rv; } /* * sad_01_mmx.s: mmx1 optimised 7bit*8 word absolute difference sum * We're reduce to seven bits as otherwise we also have to mess * horribly with carries and signed only comparisons make the code * simply enormous (and probably barely faster than a simple loop). * Since signals with a bona-fide 8bit res will be rare we simply * take the precision hit... * Actually we don't worry about carries from the low-order bits * either so 1/4 of the time we'll be 1 too low... * * Copyright (C) 2000 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ int sad_01_mmx(uint8_t *p1, uint8_t *p2, int lx, int h) { int rv; /* * mm0 = distance accumulators (4 words) * mm1 = bytes p2 * mm2 = bytes p1 * mm3 = bytes p1+1 * mm4 = temp 4 bytes in words interpolating p1, p1+1 * mm5 = temp 4 bytes in words from p2 * mm6 = temp comparison bit mask p1,p2 * mm7 = temp comparison bit mask p2,p1 */ pxor_r2r(mm0, mm0); do { /* First 8 bytes of row */ /* First 4 bytes of 8 */ movq_m2r(p1[0], mm4); /* mm4 := first 4 bytes p1 */ pxor_r2r(mm7, mm7); movq_r2r(mm4, mm2); /* mm2 records all 8 bytes */ punpcklbw_r2r(mm7, mm4); /* First 4 bytes p1 in Words... */ movq_m2r(p1[1], mm6); /* mm6 := first 4 bytes p1+1 */ movq_r2r(mm6, mm3); /* mm3 records all 8 bytes */ punpcklbw_r2r(mm7, mm6); paddw_r2r(mm6, mm4); /* mm4 := First 4 bytes interpolated in words */ psrlw_i2r(1, mm4); movq_m2r(p2[0], mm5); /* mm5:=first 4 bytes of p2 in words */ movq_r2r(mm5, mm1); punpcklbw_r2r(mm7, mm5); movq_r2r(mm4, mm7); pcmpgtw_r2r(mm5, mm7); /* mm7 := [i : W0..3,mm4>mm5] */ movq_r2r(mm4, mm6); /* mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)] */ psubw_r2r(mm5, mm6); pand_r2r(mm7, mm6); paddw_r2r(mm6, mm0); /* Add to accumulator */ movq_r2r(mm5, mm6); /* mm6 := [i : W0..3,mm5>mm4] */ pcmpgtw_r2r(mm4, mm6); psubw_r2r(mm4, mm5); /* mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)] */ pand_r2r(mm6, mm5); paddw_r2r(mm5, mm0); /* Add to accumulator */ /* Second 4 bytes of 8 */ movq_r2r(mm2, mm4); /* mm4 := Second 4 bytes p1 in words */ pxor_r2r(mm7, mm7); punpckhbw_r2r(mm7, mm4); movq_r2r(mm3, mm6); /* mm6 := Second 4 bytes p1+1 in words */ punpckhbw_r2r(mm7, mm6); paddw_r2r(mm6, mm4); /* mm4 := First 4 Interpolated bytes in words */ psrlw_i2r(1, mm4); movq_r2r(mm1, mm5); /* mm5:= second 4 bytes of p2 in words */ punpckhbw_r2r(mm7, mm5); movq_r2r(mm4, mm7); pcmpgtw_r2r(mm5, mm7); /* mm7 := [i : W0..3,mm4>mm5] */ movq_r2r(mm4, mm6); /* mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)] */ psubw_r2r(mm5, mm6); pand_r2r(mm7, mm6); paddw_r2r(mm6, mm0); /* Add to accumulator */ movq_r2r(mm5, mm6); /* mm6 := [i : W0..3,mm5>mm4] */ pcmpgtw_r2r(mm4, mm6); psubw_r2r(mm4, mm5); /* mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)] */ pand_r2r(mm6, mm5); paddw_r2r(mm5, mm0); /* Add to accumulator */ /* Second 8 bytes of row */ /* First 4 bytes of 8 */ movq_m2r(p1[8], mm4); /* mm4 := first 4 bytes p1+8 */ pxor_r2r(mm7, mm7); movq_r2r(mm4, mm2); /* mm2 records all 8 bytes */ punpcklbw_r2r(mm7, mm4); /* First 4 bytes p1 in Words... */ movq_m2r(p1[9], mm6); /* mm6 := first 4 bytes p1+9 */ movq_r2r(mm6, mm3); /* mm3 records all 8 bytes */ punpcklbw_r2r(mm7, mm6); paddw_r2r(mm6, mm4); /* mm4 := First 4 bytes interpolated in words */ psrlw_i2r(1, mm4); movq_m2r(p2[8], mm5); /* mm5:=first 4 bytes of p2+8 in words */ movq_r2r(mm5, mm1); punpcklbw_r2r(mm7, mm5); movq_r2r(mm4, mm7); pcmpgtw_r2r(mm5, mm7); /* mm7 := [i : W0..3,mm4>mm5] */ movq_r2r(mm4, mm6); /* mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)] */ psubw_r2r(mm5, mm6); pand_r2r(mm7, mm6); paddw_r2r(mm6, mm0); /* Add to accumulator */ movq_r2r(mm5, mm6); /* mm6 := [i : W0..3,mm5>mm4] */ pcmpgtw_r2r(mm4, mm6); psubw_r2r(mm4, mm5); /* mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)] */ pand_r2r(mm6, mm5); paddw_r2r(mm5, mm0); /* Add to accumulator */ /* Second 4 bytes of 8 */ movq_r2r(mm2, mm4); /* mm4 := Second 4 bytes p1 in words */ pxor_r2r(mm7, mm7); punpckhbw_r2r(mm7, mm4); movq_r2r(mm3, mm6); /* mm6 := Second 4 bytes p1+1 in words */ punpckhbw_r2r(mm7, mm6); paddw_r2r(mm6, mm4); /* mm4 := First 4 Interpolated bytes in words */ psrlw_i2r(1, mm4); movq_r2r(mm1, mm5); /* mm5:= second 4 bytes of p2 in words */ punpckhbw_r2r(mm7, mm5); movq_r2r(mm4, mm7); pcmpgtw_r2r(mm5, mm7); /* mm7 := [i : W0..3,mm4>mm5] */ movq_r2r(mm4, mm6); /* mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)] */ psubw_r2r(mm5, mm6); pand_r2r(mm7, mm6); paddw_r2r(mm6, mm0); /* Add to accumulator */ movq_r2r(mm5, mm6); /* mm6 := [i : W0..3,mm5>mm4] */ pcmpgtw_r2r(mm4, mm6); psubw_r2r(mm4, mm5); /* mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)] */ pand_r2r(mm6, mm5); paddw_r2r(mm5, mm0); /* Add to accumulator */ p1 += lx; /* update pointers to next row */ p2 += lx; h--; } while (h); /* Sum the Accumulators */ movq_r2r(mm0, mm4); psrlq_i2r(32, mm4); paddw_r2r(mm4, mm0); movq_r2r(mm0, mm6); psrlq_i2r(16, mm6); paddw_r2r(mm6, mm0); movd_r2g(mm0, rv); /* store return value */ rv &= 0xffff; emms(); return rv; } /* * sad_01_mmx.s: mmx1 optimised 7bit*8 word absolute difference sum * We're reduce to seven bits as otherwise we also have to mess * horribly with carries and signed only comparisons make the code * simply enormous (and probably barely faster than a simple loop). * Since signals with a bona-fide 8bit res will be rare we simply * take the precision hit... * Actually we don't worry about carries from the low-order bits * either so 1/4 of the time we'll be 1 too low... * * Copyright (C) 2000 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ int sad_10_mmx(uint8_t *p1, uint8_t *p2, int lx, int h) { int rv; /* * mm0 = distance accumulators (4 words) * mm1 = bytes p2 * mm2 = bytes p1 * mm3 = bytes p1+1 * mm4 = temp 4 bytes in words interpolating p1, p1+1 * mm5 = temp 4 bytes in words from p2 * mm6 = temp comparison bit mask p1,p2 * mm7 = temp comparison bit mask p2,p1 */ pxor_r2r(mm0, mm0); do { /* First 8 bytes of row */ /* First 4 bytes of 8 */ movq_m2r(p1[0], mm4); /* mm4 := first 4 bytes p1 */ pxor_r2r(mm7, mm7); movq_r2r(mm4, mm2); /* mm2 records all 8 bytes */ punpcklbw_r2r(mm7, mm4); /* First 4 bytes p1 in Words... */ movq_m2r(p1[lx], mm6); /* mm6 := first 4 bytes p1+lx */ movq_r2r(mm6, mm3); /* mm3 records all 8 bytes */ punpcklbw_r2r(mm7, mm6); paddw_r2r(mm6, mm4); /* mm4 := First 4 bytes interpolated in words */ psrlw_i2r(1, mm4); movq_m2r(p2[0], mm5); /* mm5:=first 4 bytes of p2 in words */ movq_r2r(mm5, mm1); punpcklbw_r2r(mm7, mm5); movq_r2r(mm4, mm7); pcmpgtw_r2r(mm5, mm7); /* mm7 := [i : W0..3,mm4>mm5] */ movq_r2r(mm4, mm6); /* mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)] */ psubw_r2r(mm5, mm6); pand_r2r(mm7, mm6); paddw_r2r(mm6, mm0); /* Add to accumulator */ movq_r2r(mm5, mm6); /* mm6 := [i : W0..3,mm5>mm4] */ pcmpgtw_r2r(mm4, mm6); psubw_r2r(mm4, mm5); /* mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)] */ pand_r2r(mm6, mm5); paddw_r2r(mm5, mm0); /* Add to accumulator */ /* Second 4 bytes of 8 */ movq_r2r(mm2, mm4); /* mm4 := Second 4 bytes p1 in words */ pxor_r2r(mm7, mm7); punpckhbw_r2r(mm7, mm4); movq_r2r(mm3, mm6); /* mm6 := Second 4 bytes p1+lx in words */ punpckhbw_r2r(mm7, mm6); paddw_r2r(mm6, mm4); /* mm4 := First 4 Interpolated bytes in words */ psrlw_i2r(1, mm4); movq_r2r(mm1, mm5); /* mm5:= second 4 bytes of p2 in words */ punpckhbw_r2r(mm7, mm5); movq_r2r(mm4, mm7); pcmpgtw_r2r(mm5, mm7); /* mm7 := [i : W0..3,mm4>mm5] */ movq_r2r(mm4, mm6); /* mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)] */ psubw_r2r(mm5, mm6); pand_r2r(mm7, mm6); paddw_r2r(mm6, mm0); /* Add to accumulator */ movq_r2r(mm5, mm6); /* mm6 := [i : W0..3,mm5>mm4] */ pcmpgtw_r2r(mm4, mm6); psubw_r2r(mm4, mm5); /* mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)] */ pand_r2r(mm6, mm5); paddw_r2r(mm5, mm0); /* Add to accumulator */ /* Second 8 bytes of row */ /* First 4 bytes of 8 */ movq_m2r(p1[8], mm4); /* mm4 := first 4 bytes p1+8 */ pxor_r2r(mm7, mm7); movq_r2r(mm4, mm2); /* mm2 records all 8 bytes */ punpcklbw_r2r(mm7, mm4); /* First 4 bytes p1 in Words... */ movq_m2r(p1[lx+8], mm6); /* mm6 := first 4 bytes p1+lx+8 */ movq_r2r(mm6, mm3); /* mm3 records all 8 bytes */ punpcklbw_r2r(mm7, mm6); paddw_r2r(mm6, mm4); /* mm4 := First 4 bytes interpolated in words */ psrlw_i2r(1, mm4); movq_m2r(p2[8], mm5); /* mm5:=first 4 bytes of p2+8 in words */ movq_r2r(mm5, mm1); punpcklbw_r2r(mm7, mm5); movq_r2r(mm4, mm7); pcmpgtw_r2r(mm5, mm7); /* mm7 := [i : W0..3,mm4>mm5] */ movq_r2r(mm4, mm6); /* mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)] */ psubw_r2r(mm5, mm6); pand_r2r(mm7, mm6); paddw_r2r(mm6, mm0); /* Add to accumulator */ movq_r2r(mm5, mm6); /* mm6 := [i : W0..3,mm5>mm4] */ pcmpgtw_r2r(mm4, mm6); psubw_r2r(mm4, mm5); /* mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)] */ pand_r2r(mm6, mm5); paddw_r2r(mm5, mm0); /* Add to accumulator */ /* Second 4 bytes of 8 */ movq_r2r(mm2, mm4); /* mm4 := Second 4 bytes p1 in words */ pxor_r2r(mm7, mm7); punpckhbw_r2r(mm7, mm4); movq_r2r(mm3, mm6); /* mm6 := Second 4 bytes p1+lx in words */ punpckhbw_r2r(mm7, mm6); paddw_r2r(mm6, mm4); /* mm4 := First 4 Interpolated bytes in words */ psrlw_i2r(1, mm4); movq_r2r(mm1, mm5); /* mm5:= second 4 bytes of p2 in words */ punpckhbw_r2r(mm7, mm5); movq_r2r(mm4, mm7); pcmpgtw_r2r(mm5, mm7); /* mm7 := [i : W0..3,mm4>mm5] */ movq_r2r(mm4, mm6); /* mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)] */ psubw_r2r(mm5, mm6); pand_r2r(mm7, mm6); paddw_r2r(mm6, mm0); /* Add to accumulator */ movq_r2r(mm5, mm6); /* mm6 := [i : W0..3,mm5>mm4] */ pcmpgtw_r2r(mm4, mm6); psubw_r2r(mm4, mm5); /* mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)] */ pand_r2r(mm6, mm5); paddw_r2r(mm5, mm0); /* Add to accumulator */ p1 += lx; p2 += lx; h--; } while (h); /* Sum the Accumulators */ movq_r2r(mm0, mm4); psrlq_i2r(32, mm4); paddw_r2r(mm4, mm0); movq_r2r(mm0, mm6); psrlq_i2r(16, mm6); paddw_r2r(mm6, mm0); movd_r2g(mm0, rv); /* store return value */ rv &= 0xffff; emms(); return rv; } /* * sad_01_mmx.s: * * Copyright (C) 2000 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ int sad_11_mmx(uint8_t *p1, uint8_t *p2, int lx, int h) { int rv; /* * mm0 = distance accumulators (4 words) * mm1 = bytes p2 * mm2 = bytes p1 * mm3 = bytes p1+lx * I'd love to find someplace to stash p1+1 and p1+lx+1's bytes * but I don't think thats going to happen in iA32-land... * mm4 = temp 4 bytes in words interpolating p1, p1+1 * mm5 = temp 4 bytes in words from p2 * mm6 = temp comparison bit mask p1,p2 * mm7 = temp comparison bit mask p2,p1 */ pxor_r2r(mm0, mm0); do { /* First 8 bytes of row */ /* First 4 bytes of 8 */ movq_m2r(p1[0], mm4); /* mm4 := first 4 bytes p1 */ pxor_r2r(mm7, mm7); movq_r2r(mm4, mm2); /* mm2 records all 8 bytes */ punpcklbw_r2r(mm7, mm4); /* First 4 bytes p1 in Words... */ movq_m2r(p1[lx], mm6); /* mm6 := first 4 bytes p1+lx */ movq_r2r(mm6, mm3); /* mm3 records all 8 bytes */ punpcklbw_r2r(mm7, mm6); paddw_r2r(mm6, mm4); movq_m2r(p1[1], mm5); /* mm5 := first 4 bytes p1+1 */ punpcklbw_r2r(mm7, mm5); /* First 4 bytes p1 in Words... */ paddw_r2r(mm5, mm4); movq_m2r(p1[lx+1], mm6); /* mm6 := first 4 bytes p1+lx+1 */ punpcklbw_r2r(mm7, mm6); paddw_r2r(mm6, mm4); psrlw_i2r(2, mm4); /* mm4 := First 4 bytes interpolated in words */ movq_m2r(p2[0], mm5); /* mm5:=first 4 bytes of p2 in words */ movq_r2r(mm5, mm1); punpcklbw_r2r(mm7, mm5); movq_r2r(mm4, mm7); pcmpgtw_r2r(mm5, mm7); /* mm7 := [i : W0..3,mm4>mm5] */ movq_r2r(mm4, mm6); /* mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)] */ psubw_r2r(mm5, mm6); pand_r2r(mm7, mm6); paddw_r2r(mm6, mm0); /* Add to accumulator */ movq_r2r(mm5, mm6); /* mm6 := [i : W0..3,mm5>mm4] */ pcmpgtw_r2r(mm4, mm6); psubw_r2r(mm4, mm5); /* mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)] */ pand_r2r(mm6, mm5); paddw_r2r(mm5, mm0); /* Add to accumulator */ /* Second 4 bytes of 8 */ movq_r2r(mm2, mm4); /* mm4 := Second 4 bytes p1 in words */ pxor_r2r(mm7, mm7); punpckhbw_r2r(mm7, mm4); movq_r2r(mm3, mm6); /* mm6 := Second 4 bytes p1+1 in words */ punpckhbw_r2r(mm7, mm6); paddw_r2r(mm6, mm4); movq_m2r(p1[1], mm5); /* mm5 := first 4 bytes p1+1 */ punpckhbw_r2r(mm7, mm5); /* First 4 bytes p1 in Words... */ paddw_r2r(mm5, mm4); movq_m2r(p1[lx+1], mm6); /* mm6 := first 4 bytes p1+lx+1 */ punpckhbw_r2r(mm7, mm6); paddw_r2r(mm6, mm4); psrlw_i2r(2, mm4); /* mm4 := First 4 bytes interpolated in words */ movq_r2r(mm1, mm5); /* mm5:= second 4 bytes of p2 in words */ punpckhbw_r2r(mm7, mm5); movq_r2r(mm4, mm7); pcmpgtw_r2r(mm5, mm7); /* mm7 := [i : W0..3,mm4>mm5] */ movq_r2r(mm4, mm6); /* mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)] */ psubw_r2r(mm5, mm6); pand_r2r(mm7, mm6); paddw_r2r(mm6, mm0); /* Add to accumulator */ movq_r2r(mm5, mm6); /* mm6 := [i : W0..3,mm5>mm4] */ pcmpgtw_r2r(mm4, mm6); psubw_r2r(mm4, mm5); /* mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)] */ pand_r2r(mm6, mm5); paddw_r2r(mm5, mm0); /* Add to accumulator */ /* Second 8 bytes of row */ /* First 4 bytes of 8 */ movq_m2r(p1[8], mm4); /* mm4 := first 4 bytes p1+8 */ pxor_r2r(mm7, mm7); movq_r2r(mm4, mm2); /* mm2 records all 8 bytes */ punpcklbw_r2r(mm7, mm4); /* First 4 bytes p1 in Words... */ movq_m2r(p1[lx+8], mm6); /* mm6 := first 4 bytes p1+lx+8 */ movq_r2r(mm6, mm3); /* mm3 records all 8 bytes */ punpcklbw_r2r(mm7, mm6); paddw_r2r(mm6, mm4); movq_m2r(p1[9], mm5); /* mm5 := first 4 bytes p1+9 */ punpcklbw_r2r(mm7, mm5); /* First 4 bytes p1 in Words... */ paddw_r2r(mm5, mm4); movq_m2r(p1[lx+9], mm6); /* mm6 := first 4 bytes p1+lx+9 */ punpcklbw_r2r(mm7, mm6); paddw_r2r(mm6, mm4); psrlw_i2r(2, mm4); /* mm4 := First 4 bytes interpolated in words */ movq_m2r(p2[8], mm5); /* mm5:=first 4 bytes of p2+8 in words */ movq_r2r(mm5, mm1); punpcklbw_r2r(mm7, mm5); movq_r2r(mm4, mm7); pcmpgtw_r2r(mm5, mm7); /* mm7 := [i : W0..3,mm4>mm5] */ movq_r2r(mm4, mm6); /* mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)] */ psubw_r2r(mm5, mm6); pand_r2r(mm7, mm6); paddw_r2r(mm6, mm0); /* Add to accumulator */ movq_r2r(mm5, mm6); /* mm6 := [i : W0..3,mm5>mm4] */ pcmpgtw_r2r(mm4, mm6); psubw_r2r(mm4, mm5); /* mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)] */ pand_r2r(mm6, mm5); paddw_r2r(mm5, mm0); /* Add to accumulator */ /* Second 4 bytes of 8 */ movq_r2r(mm2, mm4); /* mm4 := Second 4 bytes p1 in words */ pxor_r2r(mm7, mm7); punpckhbw_r2r(mm7, mm4); movq_r2r(mm3, mm6); /* mm6 := Second 4 bytes p1+1 in words */ punpckhbw_r2r(mm7, mm6); paddw_r2r(mm6, mm4); movq_m2r(p1[9], mm5); /* mm5 := first 4 bytes p1+9 */ punpckhbw_r2r(mm7, mm5); /* First 4 bytes p1 in Words... */ paddw_r2r(mm5, mm4); movq_m2r(p1[lx+9], mm6); /* mm6 := first 4 bytes p1+lx+9 */ punpckhbw_r2r(mm7, mm6); paddw_r2r(mm6, mm4); psrlw_i2r(2, mm4); /* mm4 := First 4 bytes interpolated in words */ movq_r2r(mm1, mm5); /* mm5:= second 4 bytes of p2 in words */ punpckhbw_r2r(mm7, mm5); movq_r2r(mm4, mm7); pcmpgtw_r2r(mm5, mm7); /* mm7 := [i : W0..3,mm4>mm5] */ movq_r2r(mm4, mm6); /* mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)] */ psubw_r2r(mm5, mm6); pand_r2r(mm7, mm6); paddw_r2r(mm6, mm0); /* Add to accumulator */ movq_r2r(mm5, mm6); /* mm6 := [i : W0..3,mm5>mm4] */ pcmpgtw_r2r(mm4, mm6); psubw_r2r(mm4, mm5); /* mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)] */ pand_r2r(mm6, mm5); paddw_r2r(mm5, mm0); /* Add to accumulator */ p1 += lx; /* update pointers to next row */ p2 += lx; h--; } while (h); /* Sum the Accumulators */ movq_r2r(mm0, mm4); psrlq_i2r(32, mm4); paddw_r2r(mm4, mm0); movq_r2r(mm0, mm6); psrlq_i2r(16, mm6); paddw_r2r(mm6, mm0); movd_r2g(mm0, rv); /* store return value */ rv &= 0xffff; return rv; } int sad_sub22_mmx(uint8_t *blk1,uint8_t *blk2,int lx,int h) { int rv; /* * mm0 = distance accumulators (4 words) * mm1 = temp * mm2 = temp * mm3 = temp * mm4 = temp * mm5 = temp * mm6 = 0 * mm7 = temp */ pxor_r2r(mm0, mm0); pxor_r2r(mm6, mm6); do { movq_m2r(blk1[0], mm4); /* load 8 bytes of p1 */ movq_m2r(blk2[0], mm5); /* load 8 bytes of p2 */ movq_r2r(mm4, mm7); /* mm5 = abs(*p1-*p2) */ psubusb_r2r(mm5, mm7); psubusb_r2r(mm4, mm5); blk1 += lx; /* update pointer to next row */ paddb_r2r(mm7, mm5); /* Add the mm5 bytes to the accumulatores */ movq_r2r(mm5, mm7); punpcklbw_r2r(mm6, mm7); paddw_r2r(mm7, mm0); punpckhbw_r2r(mm6, mm5); blk2 += lx; /* update pointer to next row */ paddw_r2r(mm5, mm0); movq_m2r(blk1[0], mm4); /* load 8 bytes of p1 (next row) */ movq_m2r(blk2[0], mm5); /* load 8 bytes of p2 (next row) */ movq_r2r(mm4, mm7); /* mm5 = abs(*p1-*p2) */ psubusb_r2r(mm5, mm7); psubusb_r2r(mm4, mm5); blk1 += lx; /* update pointer to next row */ paddb_r2r(mm7, mm5); /* Add the mm5 bytes to the accumulatores */ movq_r2r(mm5, mm7); punpcklbw_r2r(mm6, mm7); blk2 += lx; /* update pointer to next row */ paddw_r2r(mm7, mm0); punpckhbw_r2r(mm6, mm5); h -= 2; paddw_r2r(mm5, mm0); } while (h); /* Sum the Accumulators */ movq_r2r(mm0, mm1); psrlq_i2r(16, mm1); movq_r2r(mm0, mm2); psrlq_i2r(32, mm2); movq_r2r(mm0, mm3); psrlq_i2r(48, mm3); paddw_r2r(mm1, mm0); paddw_r2r(mm3, mm2); paddw_r2r(mm2, mm0); movd_r2g(mm0, rv); /* store return value */ rv &= 0xffff; emms(); return rv; } int sad_sub44_mmx(uint8_t *blk1, uint8_t *blk2, int qlx, int qh) { int rv; /* * mm0 = distance accumulator left block p1 * mm1 = distance accumulator right block p1 * mm2 = 0 * mm3 = right block of p1 * mm4 = left block of p1 * mm5 = p2 * mm6 = temp * mm7 = temp */ pxor_r2r(mm0, mm0); pxor_r2r(mm1, mm1); pxor_r2r(mm2, mm2); do { /* * Beware loop obfuscated by interleaving to try to * hide latencies... */ movq_m2r(blk1[0], mm4); /* mm4 = first 4 bytes of p1 in words */ movq_m2r(blk2[0], mm5); /* mm5 = 4 bytes of p2 in words */ movq_r2r(mm4, mm3); punpcklbw_r2r(mm2, mm4); punpcklbw_r2r(mm2, mm5); movq_r2r(mm4, mm7); movq_r2r(mm5, mm6); psubusw_r2r(mm5, mm7); psubusw_r2r(mm4, mm6); blk1 += qlx; /* update a pointer to next row */ paddw_r2r(mm6, mm7); paddw_r2r(mm7, mm0); /* Add absolute differences to left block accumulators */ blk2 += qlx; qh--; } while (qh); /* Sum the accumulators */ movq_r2r(mm0, mm4); psrlq_i2r(32, mm4); paddw_r2r(mm4, mm0); movq_r2r(mm0, mm6); psrlq_i2r(16, mm6); paddw_r2r(mm6, mm0); movd_r2g(mm0, rv); rv &= 0xffff; emms(); return rv; } mjpegtools-2.1.0/utils/mmxsse/mmxsse_motion.h0000644000175000017500000000760510164607764021762 0ustar glowwormglowworm/* Optimised lowlevel motion estimation routines for mpeg2enc */ /* (C) 2000/2001 Andrew Stevens */ /* This is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "motionsearch.h" #include "mblock_sub44_sads_x86.h" void enable_mmxsse_motion(int); void sub_mean_reduction( me_result_set *matchset, int times, int *minweight_res); void mblock_sub22_nearest4_sads_mmxe(uint8_t *blk1,uint8_t *blk2, int frowstride,int fh, int32_t *resvec); int mblock_nearest4_sads_mmxe(uint8_t *blk1, uint8_t *blk2, int rowstride, int h, int32_t *resvec, int peakerror); int sad_00_mmxe(uint8_t *blk1, uint8_t *blk2, int rowstride, int h, int distlim); int sad_01_mmxe(uint8_t *blk1, uint8_t *blk2, int rowstride, int h); int sad_10_mmxe(uint8_t *blk1, uint8_t *blk2, int rowstride, int h); int sad_11_mmxe(uint8_t *blk1, uint8_t *blk2, int rowstride, int h); int sad_sub22_mmxe ( uint8_t *blk1, uint8_t *blk2, int frowstride, int fh); int sad_sub44_mmxe ( uint8_t *blk1, uint8_t *blk2, int qrowstride, int qh); int sumsq_mmx( uint8_t *blk1, uint8_t *blk2, int rowstride, int hx, int hy, int h); int sumsq_sub22_mmx( uint8_t *blk1, uint8_t *blk2, int rowstride, int h); int bsumsq_sub22_mmx( uint8_t *blk1f, uint8_t *blk1b, uint8_t *blk2, int rowstride, int h); int bsumsq_mmx (uint8_t *pf, uint8_t *pb, uint8_t *p2, int rowstride, int hxf, int hyf, int hxb, int hyb, int h); int bsad_mmx (uint8_t *pf, uint8_t *pb, uint8_t *p2, int rowstride, int hxf, int hyf, int hxb, int hyb, int h); int bsad_mmxe(uint8_t *pf, uint8_t *pb, uint8_t *p2, int rowstride, int hxf, int hyf, int hxb, int hyb, int h); void variance_mmx (uint8_t *p, int size, int rowstride, uint32_t *p_variance, uint32_t *p_mean); int sad_00_mmx ( uint8_t *blk1, uint8_t *blk2, int rowstride, int h, int distlim); int sad_01_mmx(uint8_t *blk1, uint8_t *blk2, int rowstride, int h); int sad_10_mmx(uint8_t *blk1, uint8_t *blk2, int rowstride, int h); int sad_11_mmx(uint8_t *blk1, uint8_t *blk2, int rowstride, int h); int sad_sub22_mmx ( uint8_t *blk1, uint8_t *blk2, int frowstride, int fh); int sad_sub44_mmx (uint8_t *blk1, uint8_t *blk2, int qrowstride, int qh); /* Assembler core routine used in x86 MMX/SSE implementation */ extern int (*pmblocks_sub44_mests)( uint8_t *blk, uint8_t *ref, int ilow, int jlow, int ihigh, int jhigh, int h, int rowstride, int threshold, me_result_s *resvec); void find_best_one_pel_mmxe( me_result_set *sub22set, uint8_t *org, uint8_t *blk, int i0, int j0, int ihigh, int jhigh, int rowstride, int h, me_result_s *best_so_far ); int build_sub44_mests_mmx( me_result_set *sub44set, int ilow, int jlow, int ihigh, int jhigh, int i0, int j0, int null_ctl_sad, uint8_t *s44org, uint8_t *s44blk, int qrowstride, int qh, int reduction); int build_sub22_mests_mmxe( me_result_set *sub44set, me_result_set *sub22set, int i0, int j0, int ihigh, int jhigh, int null_ctl_sad, uint8_t *s22org, uint8_t *s22blk, int frowstride, int fh, int reduction); mjpegtools-2.1.0/utils/yuv4mpeg.h0000644000175000017500000007266010314351424017312 0ustar glowwormglowworm/* * yuv4mpeg.h: Functions for reading and writing "new" YUV4MPEG2 streams. * * Stream format is described at the end of this file. * * * Copyright (C) 2004 Matthew J. Marjanovic * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __YUV4MPEG_H__ #define __YUV4MPEG_H__ #include #include #ifndef _WIN32 #include #endif #include /************************************************************************ * error codes returned by y4m_* functions ************************************************************************/ #define Y4M_OK 0 #define Y4M_ERR_RANGE 1 /* argument or tag value out of range */ #define Y4M_ERR_SYSTEM 2 /* failed system call, check errno */ #define Y4M_ERR_HEADER 3 /* illegal/malformed header */ #define Y4M_ERR_BADTAG 4 /* illegal tag character */ #define Y4M_ERR_MAGIC 5 /* bad header magic */ #define Y4M_ERR_EOF 6 /* end-of-file (clean) */ #define Y4M_ERR_XXTAGS 7 /* too many xtags */ #define Y4M_ERR_BADEOF 8 /* unexpected end-of-file */ #define Y4M_ERR_FEATURE 9 /* stream requires features beyond allowed level */ /* generic 'unknown' value for integer parameters (e.g. interlace, height) */ #define Y4M_UNKNOWN -1 /************************************************************************ * values for the "interlace" parameter [y4m_*_interlace()] ************************************************************************/ #define Y4M_ILACE_NONE 0 /* non-interlaced, progressive frame */ #define Y4M_ILACE_TOP_FIRST 1 /* interlaced, top-field first */ #define Y4M_ILACE_BOTTOM_FIRST 2 /* interlaced, bottom-field first */ #define Y4M_ILACE_MIXED 3 /* mixed, "refer to frame header" */ /************************************************************************ * values for the "chroma" parameter [y4m_*_chroma()] ************************************************************************/ #define Y4M_CHROMA_420JPEG 0 /* 4:2:0, H/V centered, for JPEG/MPEG-1 */ #define Y4M_CHROMA_420MPEG2 1 /* 4:2:0, H cosited, for MPEG-2 */ #define Y4M_CHROMA_420PALDV 2 /* 4:2:0, alternating Cb/Cr, for PAL-DV */ #define Y4M_CHROMA_444 3 /* 4:4:4, no subsampling, phew. */ #define Y4M_CHROMA_422 4 /* 4:2:2, H cosited */ #define Y4M_CHROMA_411 5 /* 4:1:1, H cosited */ #define Y4M_CHROMA_MONO 6 /* luma plane only */ #define Y4M_CHROMA_444ALPHA 7 /* 4:4:4 with an alpha channel */ /************************************************************************ * values for sampling parameters [y4m_*_spatial(), y4m_*_temporal()] ************************************************************************/ #define Y4M_SAMPLING_PROGRESSIVE 0 #define Y4M_SAMPLING_INTERLACED 1 /************************************************************************ * values for "presentation" parameter [y4m_*_presentation()] ************************************************************************/ #define Y4M_PRESENT_TOP_FIRST 0 /* top-field-first */ #define Y4M_PRESENT_TOP_FIRST_RPT 1 /* top-first, repeat top */ #define Y4M_PRESENT_BOTTOM_FIRST 2 /* bottom-field-first */ #define Y4M_PRESENT_BOTTOM_FIRST_RPT 3 /* bottom-first, repeat bottom */ #define Y4M_PRESENT_PROG_SINGLE 4 /* single progressive frame */ #define Y4M_PRESENT_PROG_DOUBLE 5 /* progressive frame, repeat once */ #define Y4M_PRESENT_PROG_TRIPLE 6 /* progressive frame, repeat twice */ #define Y4M_MAX_NUM_PLANES 4 /************************************************************************ * 'ratio' datatype, for rational numbers * (see 'ratio' functions down below) ************************************************************************/ typedef struct _y4m_ratio { int n; /* numerator */ int d; /* denominator */ } y4m_ratio_t; /************************************************************************ * useful standard framerates (as ratios) ************************************************************************/ extern const y4m_ratio_t y4m_fps_UNKNOWN; extern const y4m_ratio_t y4m_fps_NTSC_FILM; /* 24000/1001 film (in NTSC) */ extern const y4m_ratio_t y4m_fps_FILM; /* 24fps film */ extern const y4m_ratio_t y4m_fps_PAL; /* 25fps PAL */ extern const y4m_ratio_t y4m_fps_NTSC; /* 30000/1001 NTSC */ extern const y4m_ratio_t y4m_fps_30; /* 30fps */ extern const y4m_ratio_t y4m_fps_PAL_FIELD; /* 50fps PAL field rate */ extern const y4m_ratio_t y4m_fps_NTSC_FIELD; /* 60000/1001 NTSC field rate */ extern const y4m_ratio_t y4m_fps_60; /* 60fps */ /************************************************************************ * useful standard sample (pixel) aspect ratios (W:H) ************************************************************************/ extern const y4m_ratio_t y4m_sar_UNKNOWN; extern const y4m_ratio_t y4m_sar_SQUARE; /* square pixels */ extern const y4m_ratio_t y4m_sar_NTSC_CCIR601; /* 525-line (NTSC) Rec.601 */ extern const y4m_ratio_t y4m_sar_NTSC_16_9; /* 16:9 NTSC/Rec.601 */ extern const y4m_ratio_t y4m_sar_NTSC_SVCD_4_3; /* NTSC SVCD 4:3 */ extern const y4m_ratio_t y4m_sar_NTSC_SVCD_16_9;/* NTSC SVCD 16:9 */ extern const y4m_ratio_t y4m_sar_PAL_CCIR601; /* 625-line (PAL) Rec.601 */ extern const y4m_ratio_t y4m_sar_PAL_16_9; /* 16:9 PAL/Rec.601 */ extern const y4m_ratio_t y4m_sar_PAL_SVCD_4_3; /* PAL SVCD 4:3 */ extern const y4m_ratio_t y4m_sar_PAL_SVCD_16_9; /* PAL SVCD 16:9 */ extern const y4m_ratio_t y4m_sar_SQR_ANA16_9; /* anamorphic 16:9 sampled */ /* from 4:3 with square pixels */ /************************************************************************ * useful standard display aspect ratios (W:H) ************************************************************************/ extern const y4m_ratio_t y4m_dar_UNKNOWN; extern const y4m_ratio_t y4m_dar_4_3; /* standard TV */ extern const y4m_ratio_t y4m_dar_16_9; /* widescreen TV */ extern const y4m_ratio_t y4m_dar_221_100; /* word-to-your-mother TV */ #define Y4M_MAX_XTAGS 32 /* maximum number of xtags in list */ #define Y4M_MAX_XTAG_SIZE 32 /* max length of an xtag (including 'X') */ typedef struct _y4m_xtag_list y4m_xtag_list_t; typedef struct _y4m_stream_info y4m_stream_info_t; typedef struct _y4m_frame_info y4m_frame_info_t; #ifdef __cplusplus #define BEGIN_CDECLS extern "C" { #define END_CDECLS } #else #define BEGIN_CDECLS #define END_CDECLS #endif BEGIN_CDECLS /************************************************************************ * 'ratio' functions ************************************************************************/ /* 'normalize' a ratio (remove common factors) */ void y4m_ratio_reduce(y4m_ratio_t *r); /* parse "nnn:ddd" into a ratio (returns Y4M_OK or Y4M_ERR_RANGE) */ int y4m_parse_ratio(y4m_ratio_t *r, const char *s); /* quick test of two ratios for equality (i.e. identical components) */ #define Y4M_RATIO_EQL(a,b) ( ((a).n == (b).n) && ((a).d == (b).d) ) /* quick conversion of a ratio to a double (no divide-by-zero check!) */ #define Y4M_RATIO_DBL(r) ((double)(r).n / (double)(r).d) /************************************************************************* * * Guess the true SAR (sample aspect ratio) from a list of commonly * encountered values, given the "suggested" display aspect ratio (DAR), * and the true frame width and height. * * Returns y4m_sar_UNKNOWN if no match is found. * *************************************************************************/ y4m_ratio_t y4m_guess_sar(int width, int height, y4m_ratio_t dar); /************************************************************************* * * Chroma Subsampling Mode information * * x_ratio, y_ratio - subsampling of chroma planes * x_offset, y_offset - offset of chroma sample grid, * relative to luma (0,0) sample * *************************************************************************/ y4m_ratio_t y4m_chroma_ss_x_ratio(int chroma_mode); y4m_ratio_t y4m_chroma_ss_y_ratio(int chroma_mode); #if 0 y4m_ratio_t y4m_chroma_ss_x_offset(int chroma_mode, int field, int plane); y4m_ratio_t y4m_chroma_ss_y_offset(int chroma_mode, int field, int plane); #endif /* Given a string containing a (case-insensitive) chroma-tag keyword, return appropriate chroma mode (or Y4M_UNKNOWN) */ int y4m_chroma_parse_keyword(const char *s); /* Given a Y4M_CHROMA_* mode, return appropriate chroma-tag keyword, or NULL if there is none. */ const char *y4m_chroma_keyword(int chroma_mode); /* Given a Y4M_CHROMA_* mode, return appropriate chroma mode description, or NULL if there is none. */ const char *y4m_chroma_description(int chroma_mode); /************************************************************************ * 'xtag' functions * * o Before using an xtag_list (but after the structure/memory has been * allocated), you must initialize it via y4m_init_xtag_list(). * o After using an xtag_list (but before the structure is released), * call y4m_fini_xtag_list() to free internal memory. * ************************************************************************/ /* initialize an xtag_list structure */ void y4m_init_xtag_list(y4m_xtag_list_t *xtags); /* finalize an xtag_list structure */ void y4m_fini_xtag_list(y4m_xtag_list_t *xtags); /* make one xtag_list into a copy of another */ void y4m_copy_xtag_list(y4m_xtag_list_t *dest, const y4m_xtag_list_t *src); /* return number of tags in an xtag_list */ int y4m_xtag_count(const y4m_xtag_list_t *xtags); /* access n'th tag in an xtag_list */ const char *y4m_xtag_get(const y4m_xtag_list_t *xtags, int n); /* append a new tag to an xtag_list returns: Y4M_OK - success Y4M_ERR_XXTAGS - list is already full */ int y4m_xtag_add(y4m_xtag_list_t *xtags, const char *tag); /* remove a tag from an xtag_list returns: Y4M_OK - success Y4M_ERR_RANGE - n is out of range */ int y4m_xtag_remove(y4m_xtag_list_t *xtags, int n); /* remove all tags from an xtag_list returns: Y4M_OK - success */ int y4m_xtag_clearlist(y4m_xtag_list_t *xtags); /* append copies of tags from src list to dest list returns: Y4M_OK - success Y4M_ERR_XXTAGS - operation would overfill dest list */ int y4m_xtag_addlist(y4m_xtag_list_t *dest, const y4m_xtag_list_t *src); /************************************************************************ * '*_info' functions * * o Before using a *_info structure (but after the structure/memory has * been allocated), you must initialize it via y4m_init_*_info(). * o After using a *_info structure (but before the structure is released), * call y4m_fini_*_info() to free internal memory. * o Use the 'set' and 'get' accessors to modify or access the fields in * the structures; don't touch the structure directly. (Ok, so there * is no really convenient C syntax to prevent you from doing this, * but we are all responsible programmers here, so just don't do it!) * ************************************************************************/ /* initialize a stream_info structure */ void y4m_init_stream_info(y4m_stream_info_t *i); /* finalize a stream_info structure */ void y4m_fini_stream_info(y4m_stream_info_t *i); /* reset stream_info back to default/unknown values */ void y4m_clear_stream_info(y4m_stream_info_t *info); /* make one stream_info into a copy of another */ void y4m_copy_stream_info(y4m_stream_info_t *dest, const y4m_stream_info_t *src); /* access or set stream_info fields */ /* level 0 */ int y4m_si_get_width(const y4m_stream_info_t *si); int y4m_si_get_height(const y4m_stream_info_t *si); int y4m_si_get_interlace(const y4m_stream_info_t *si); y4m_ratio_t y4m_si_get_framerate(const y4m_stream_info_t *si); y4m_ratio_t y4m_si_get_sampleaspect(const y4m_stream_info_t *si); void y4m_si_set_width(y4m_stream_info_t *si, int width); void y4m_si_set_height(y4m_stream_info_t *si, int height); void y4m_si_set_interlace(y4m_stream_info_t *si, int interlace); void y4m_si_set_framerate(y4m_stream_info_t *si, y4m_ratio_t framerate); void y4m_si_set_sampleaspect(y4m_stream_info_t *si, y4m_ratio_t sar); /* level 1 */ void y4m_si_set_chroma(y4m_stream_info_t *si, int chroma_mode); int y4m_si_get_chroma(const y4m_stream_info_t *si); /* derived quantities (no setter) */ /* level 0 */ int y4m_si_get_framelength(const y4m_stream_info_t *si); /* level 1 */ int y4m_si_get_plane_count(const y4m_stream_info_t *si); int y4m_si_get_plane_width(const y4m_stream_info_t *si, int plane); int y4m_si_get_plane_height(const y4m_stream_info_t *si, int plane); int y4m_si_get_plane_length(const y4m_stream_info_t *si, int plane); /* access stream_info xtag_list */ y4m_xtag_list_t *y4m_si_xtags(y4m_stream_info_t *si); /* initialize a frame_info structure */ void y4m_init_frame_info(y4m_frame_info_t *i); /* finalize a frame_info structure */ void y4m_fini_frame_info(y4m_frame_info_t *i); /* reset frame_info back to default/unknown values */ void y4m_clear_frame_info(y4m_frame_info_t *info); /* make one frame_info into a copy of another */ void y4m_copy_frame_info(y4m_frame_info_t *dest, const y4m_frame_info_t *src); /* access or set frame_info fields (level 1) */ int y4m_fi_get_presentation(const y4m_frame_info_t *fi); int y4m_fi_get_temporal(const y4m_frame_info_t *fi); int y4m_fi_get_spatial(const y4m_frame_info_t *fi); void y4m_fi_set_presentation(y4m_frame_info_t *fi, int pres); void y4m_fi_set_temporal(y4m_frame_info_t *fi, int sampling); void y4m_fi_set_spatial(y4m_frame_info_t *fi, int sampling); /* access frame_info xtag_list */ y4m_xtag_list_t *y4m_fi_xtags(y4m_frame_info_t *fi); /************************************************************************ * blocking read and write functions * * o guaranteed to transfer entire payload (or fail) * o return values: * 0 (zero) complete success * -(# of remaining bytes) error (and errno left set) * +(# of remaining bytes) EOF (for y4m_read only) * ************************************************************************/ /* read len bytes from fd into buf */ ssize_t y4m_read(int fd, void *buf, size_t len); /* write len bytes from fd into buf */ ssize_t y4m_write(int fd, const void *buf, size_t len); /************************************************************************ * callback based read and write * * The structures y4m_cb_reader_t and y4m_cb_writer_t must be * set up by the caller before and of the *_read_*_cb() or * *_write_*_cb() functions are called. Te return values of * the read() and write() members have the same meaning as for * y4m_read() and y4m_write() * ************************************************************************/ typedef struct y4m_cb_reader_s { void * data; ssize_t (*read)(void * data, void *buf, size_t len); } y4m_cb_reader_t; typedef struct y4m_cb_writer_s { void * data; ssize_t (*write)(void * data, const void *buf, size_t len); } y4m_cb_writer_t; /* read len bytes from fd into buf */ ssize_t y4m_read_cb(y4m_cb_reader_t * fd, void *buf, size_t len); /* write len bytes from fd into buf */ ssize_t y4m_write_cb(y4m_cb_writer_t * fd, const void *buf, size_t len); /************************************************************************ * stream header processing functions * * o return values: * Y4M_OK - success * Y4M_ERR_* - error (see y4m_strerr() for descriptions) * ************************************************************************/ /* parse a string of stream header tags */ int y4m_parse_stream_tags(char *s, y4m_stream_info_t *i); /* read a stream header from file descriptor fd (the current contents of stream_info are erased first) */ int y4m_read_stream_header(int fd, y4m_stream_info_t *i); /* read a stream header with a callback reader (the current contents of stream_info are erased first) */ int y4m_read_stream_header_cb(y4m_cb_reader_t * fd, y4m_stream_info_t *i); /* write a stream header to file descriptor fd */ int y4m_write_stream_header(int fd, const y4m_stream_info_t *i); /* write a stream header with a callback writer */ int y4m_write_stream_header_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *i); /************************************************************************ * frame processing functions * * o return values: * Y4M_OK - success * Y4M_ERR_* - error (see y4m_strerr() for descriptions) * ************************************************************************/ /* write a frame header to file descriptor fd */ int y4m_write_frame_header(int fd, const y4m_stream_info_t *si, const y4m_frame_info_t *fi); /* write a frame header with a callback writer fd */ int y4m_write_frame_header_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *si, const y4m_frame_info_t *fi); /* write a complete frame (header + data) to file descriptor fd o planes[] points to 1-4 buffers, one each for image plane */ int y4m_write_frame(int fd, const y4m_stream_info_t *si, const y4m_frame_info_t *fi, uint8_t * const *planes); /* write a complete frame (header + data) with a callback writer fd o planes[] points to 1-4 buffers, one each for image plane */ int y4m_write_frame_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *si, const y4m_frame_info_t *fi, uint8_t * const *planes); /* write a complete frame (header + data), to file descriptor fd but interleave fields from two separate buffers o upper_field[] same as planes[] above, but for upper field only o lower_field[] same as planes[] above, but for lower field only */ int y4m_write_fields(int fd, const y4m_stream_info_t *si, const y4m_frame_info_t *fi, uint8_t * const *upper_field, uint8_t * const *lower_field); /* write a complete frame (header + data), with a callback writer fd but interleave fields from two separate buffers o upper_field[] same as planes[] above, but for upper field only o lower_field[] same as planes[] above, but for lower field only */ int y4m_write_fields_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *si, const y4m_frame_info_t *fi, uint8_t * const *upper_field, uint8_t * const *lower_field); /* read a frame header from file descriptor fd (the current contents of frame_info are erased first) */ int y4m_read_frame_header(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi); /* read a frame header with callback reader fd (the current contents of frame_info are erased first) */ int y4m_read_frame_header_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi); /* read frame data from file descriptor fd [to be called after y4m_read_frame_header()] o planes[] points to 1-4 buffers, one each for image plane */ int y4m_read_frame_data(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *planes); /* read frame data with callback reader fd [to be called after y4m_read_frame_header_cb()] o planes[] points to 1-4 buffers, one each for image plane */ int y4m_read_frame_data_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *planes); /* read frame data from file descriptor fd, but de-interleave fields into two separate buffers [to be called after y4m_read_frame_header()] o upper_field[] same as planes[] above, but for upper field only o lower_field[] same as planes[] above, but for lower field only */ int y4m_read_fields_data(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *upper_field, uint8_t * const *lower_field); /* read frame data with callback reader fd, but de-interleave fields into two separate buffers [to be called after y4m_read_frame_header_cb()] o upper_field[] same as planes[] above, but for upper field only o lower_field[] same as planes[] above, but for lower field only */ int y4m_read_fields_data_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *upper_field, uint8_t * const *lower_field); /* read a complete frame (header + data) from file descriptor fd, o planes[] points to 1-4 buffers, one each for image plane */ int y4m_read_frame(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *planes); /* read a complete frame (header + data) from callback reader fd, o planes[] points to 1-4 buffers, one each for image plane */ int y4m_read_frame_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *planes); /* read a complete frame (header + data) from file descriptor fd, but de-interleave fields into two separate buffers o upper_field[] same as planes[] above, but for upper field only o lower_field[] same as planes[] above, but for lower field only */ int y4m_read_fields(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *upper_field, uint8_t * const *lower_field); /* read a complete frame (header + data) from callback_reader fd, but de-interleave fields into two separate buffers o upper_field[] same as planes[] above, but for upper field only o lower_field[] same as planes[] above, but for lower field only */ int y4m_read_fields_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *upper_field, uint8_t * const *lower_field); /************************************************************************ * miscellaneous functions ************************************************************************/ /* convenient dump of stream header info via mjpeg_log facility * - each logged/printed line is prefixed by 'prefix' */ void y4m_log_stream_info(log_level_t level, const char *prefix, const y4m_stream_info_t *i); /* convert a Y4M_ERR_* error code into mildly explanatory string */ const char *y4m_strerr(int err); /* set 'allow_unknown_tag' flag for library... o yn = 0 : unknown header tags will produce a parsing error o yn = 1 : unknown header tags/values will produce a warning, but are otherwise passed along via the xtags list o yn = -1: don't change, just return current setting return value: previous setting of flag */ int y4m_allow_unknown_tags(int yn); /* set level of "accepted extensions" for the library... o level = 0: default - conform to original YUV4MPEG2 spec; yield errors when reading or writing a stream which exceeds it. o level = 1: allow reading/writing streams which contain non-420jpeg chroma and/or mixed-mode interlacing o level = -1: don't change, just return current setting return value: previous setting of level */ int y4m_accept_extensions(int level); END_CDECLS /************************************************************************ ************************************************************************ Description of the (new!, forever?) YUV4MPEG2 stream format: STREAM consists of o one '\n' terminated STREAM-HEADER o unlimited number of FRAMEs FRAME consists of o one '\n' terminated FRAME-HEADER o "length" octets of planar YCrCb 4:2:0 image data (if frame is interlaced, then the two fields are interleaved) STREAM-HEADER consists of o string "YUV4MPEG2" o unlimited number TAGGED-FIELDs, each preceded by ' ' separator o '\n' line terminator FRAME-HEADER consists of o string "FRAME" o unlimited number of TAGGED-FIELDs, each preceded by ' ' separator o '\n' line terminator TAGGED-FIELD consists of o single ascii character tag o VALUE (which does not contain whitespace) VALUE consists of o integer (base 10 ascii representation) or o RATIO or o single ascii character or o non-whitespace ascii string RATIO consists of o numerator (integer) o ':' (a colon) o denominator (integer) The currently supported tags for the STREAM-HEADER: W - [integer] frame width, pixels, should be > 0 H - [integer] frame height, pixels, should be > 0 C - [string] chroma-subsampling/data format 420jpeg (default) 420mpeg2 420paldv 411 422 444 - non-subsampled Y'CbCr 444alpha - Y'CbCr with alpha channel (with Y' black/white point) mono - Y' plane only I - [char] interlacing: p - progressive (none) t - top-field-first b - bottom-field-first m - mixed -- see 'I' tag in frame header ? - unknown F - [ratio] frame-rate, 0:0 == unknown A - [ratio] sample (pixel) aspect ratio, 0:0 == unknown X - [character string] 'metadata' (unparsed, but passed around) The currently supported tags for the FRAME-HEADER: Ixyz - framing/sampling (required if-and-only-if stream is "Im") x: t - top-field-first T - top-field-first and repeat b - bottom-field-first B - bottom-field-first and repeat 1 - single progressive frame 2 - double progressive frame (repeat) 3 - triple progressive frame (repeat twice) y: p - progressive: fields sampled at same time i - interlaced: fields sampled at different times z: p - progressive: subsampling over whole frame i - interlaced: each field subsampled independently ? - unknown (allowed only for non-4:2:0 subsampling) X - character string 'metadata' (unparsed, but passed around) ************************************************************************ ************************************************************************/ /* THAT'S ALL FOLKS! Thank you for reading the source code. We hope you have thoroughly enjoyed the experience. */ #ifdef INTERNAL_Y4M_LIBCODE_STUFF_QPX #define Y4MPRIVATIZE(identifier) identifier #else #define Y4MPRIVATIZE(identifier) PRIVATE##identifier #endif /* * Actual structure definitions of structures which you shouldn't touch. * */ /************************************************************************ * 'xtag_list' --- list of unparsed and/or meta/X header tags * * Do not touch this structure directly! * * Use the y4m_xtag_*() functions (see below). * You must initialize/finalize this structure before/after use. ************************************************************************/ struct _y4m_xtag_list { int Y4MPRIVATIZE(count); char *Y4MPRIVATIZE(tags)[Y4M_MAX_XTAGS]; }; /************************************************************************ * 'stream_info' --- stream header information * * Do not touch this structure directly! * * Use the y4m_si_*() functions (see below). * You must initialize/finalize this structure before/after use. ************************************************************************/ struct _y4m_stream_info { /* values from header/setters */ int Y4MPRIVATIZE(width); int Y4MPRIVATIZE(height); int Y4MPRIVATIZE(interlace); /* see Y4M_ILACE_* definitions */ y4m_ratio_t Y4MPRIVATIZE(framerate); /* see Y4M_FPS_* definitions */ y4m_ratio_t Y4MPRIVATIZE(sampleaspect); /* see Y4M_SAR_* definitions */ int Y4MPRIVATIZE(chroma); /* see Y4M_CHROMA_* definitions */ /* mystical X tags */ y4m_xtag_list_t Y4MPRIVATIZE(x_tags); }; /************************************************************************ * 'frame_info' --- frame header information * * Do not touch this structure directly! * * Use the y4m_fi_*() functions (see below). * You must initialize/finalize this structure before/after use. ************************************************************************/ struct _y4m_frame_info { int Y4MPRIVATIZE(spatial); /* see Y4M_SAMPLING_* definitions */ int Y4MPRIVATIZE(temporal); /* see Y4M_SAMPLING_* definitions */ int Y4MPRIVATIZE(presentation); /* see Y4M_PRESENT_* definitions */ /* mystical X tags */ y4m_xtag_list_t Y4MPRIVATIZE(x_tags); }; #undef Y4MPRIVATIZE #endif /* __YUV4MPEG_H__ */ mjpegtools-2.1.0/utils/mpegconsts.h0000644000175000017500000001033210346407114017703 0ustar glowwormglowworm /* * mpegconsts.c: Video format constants for MPEG and utilities for display * and conversion to format used for yuv4mpeg * * Copyright (C) 2001 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __MPEGCONSTS_H__ #define __MPEGCONSTS_H__ #include typedef unsigned int mpeg_framerate_code_t; typedef unsigned int mpeg_aspect_code_t; #ifdef __cplusplus #define START_CPP_WRAP extern "C" { #define END_CPP_WRAP }; #else #define START_CPP_WRAP #define END_CPP_WRAP #endif START_CPP_WRAP /* * Convert MPEG frame-rate code to corresponding frame-rate * y4m_fps_UNKNOWN = { 0, 0 } = Undefined/resrerved code. */ y4m_ratio_t mpeg_framerate( mpeg_framerate_code_t code ); /* * Is code a valid MPEG frame-rate code? * Return 1 if true; 0 otherwise. */ int mpeg_valid_framerate_code( mpeg_framerate_code_t code ); /* * Look-up MPEG frame rate code for a (exact) frame rate. * 0 = No MPEG code defined for frame-rate */ mpeg_framerate_code_t mpeg_framerate_code( y4m_ratio_t framerate ); /* * Convert floating-point framerate to an exact ratio. * Uses a standard MPEG rate, if it finds one within MPEG_FPS_TOLERANCE * (see mpegconsts.c), otherwise uses "fps:1000000" as the ratio. */ y4m_ratio_t mpeg_conform_framerate( double fps ); /* * Convert MPEG aspect ratio code to corresponding aspect ratio * * WARNING: The semantics of aspect ratio coding *changed* between * MPEG1 and MPEG2. In MPEG1 it is the *pixel* aspect ratio. In * MPEG2 it is the (far more sensible) aspect ratio of the eventual * display. * */ y4m_ratio_t mpeg_aspect_ratio( int mpeg_version, mpeg_aspect_code_t code ); /* * Is code a valid MPEG(1,2) aspect-ratio code? * Return 1 if true; 0 otherwise. */ int mpeg_valid_aspect_code( int mpeg_version, mpeg_aspect_code_t code ); /* * Look-up MPEG aspect ratio code for an aspect ratio - tolerance * is Y4M_ASPECT_MULT used by YUV4MPEG (see yuv4mpeg_intern.h) * * WARNING: The semantics of aspect ratio coding *changed* between * MPEG1 and MPEG2. In MPEG1 it is the *pixel* aspect ratio. In * MPEG2 it is the (far more sensible) aspect ratio of the eventual * display. * */ mpeg_aspect_code_t mpeg_frame_aspect_code( int mpeg_version, y4m_ratio_t aspect_ratio ); /* * Look-up MPEG explanatory definition string aspect ratio code for an * aspect ratio code * */ const char * mpeg_aspect_code_definition( int mpeg_version, mpeg_aspect_code_t code ); /* * Look-up MPEG explanatory definition string aspect ratio code for an * frame rate code * */ const char * mpeg_framerate_code_definition( mpeg_framerate_code_t code ); const char * mpeg_interlace_code_definition( int yuv4m_interlace_code ); /* * Guess the correct MPEG aspect ratio code, * given the true sample aspect ratio and frame size of a video stream * (and the MPEG version, 1 or 2). * * Returns 0 if it has no good answer. * */ mpeg_aspect_code_t mpeg_guess_mpeg_aspect_code(int mpeg_version, y4m_ratio_t sampleaspect, int frame_width, int frame_height); /* * Guess the true sample aspect ratio of a video stream, * given the MPEG aspect ratio code and the actual frame size * (and the MPEG version, 1 or 2). * * Returns y4m_sar_UNKNOWN if it has no good answer. * */ y4m_ratio_t mpeg_guess_sample_aspect_ratio(int mpeg_version, mpeg_aspect_code_t code, int frame_width, int frame_height); /* * Look-up MJPEGTOOLS MPEG preset format code explanatory definition string a * */ const char *mpeg_format_code_defintion( int format_code ); END_CPP_WRAP #endif /* __MPEGCONSTS_H__ */ mjpegtools-2.1.0/utils/Makefile.am0000644000175000017500000000204410623231604017402 0ustar glowwormglowworm# Process this file with Automake to produce Makefile.in if HAVE_ALTIVEC SUBDIRS = altivec endif if HAVE_ASM_MMX SUBDIRS = mmxsse endif DIST_SUBDIRS = altivec mmxsse EXTRA_DIST = cpuinfo.c INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/utils lib_LTLIBRARIES = libmjpegutils.la if HAVE_ALTIVEC altivec_lib = $(top_builddir)/utils/altivec/libaltivec.la endif if HAVE_ASM_MMX mmxsse_lib = $(top_builddir)/utils/mmxsse/libmmxsse.la endif libmjpegutils_la_LIBADD = $(mmxsse_lib) $(altivec_lib) libmjpegutils_la_LDFLAGS = \ $(LT_STATIC) \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -release $(LT_RELEASE) $(EXTRA_LDFLAGS) libmjpegutils_la_SOURCES = \ mjpeg_logging.c \ mpegconsts.c \ mpegtimecode.c \ yuv4mpeg.c \ yuv4mpeg_ratio.c \ motionsearch.c \ cpu_accel.c noinst_HEADERS = \ cpu_accel.h \ fastintfns.h \ mmx.h \ videodev_mjpeg.h \ yuv4mpeg_intern.h pkginclude_HEADERS = \ format_codes.h \ mjpeg_logging.h \ mjpeg_types.h \ mpegconsts.h \ mpegtimecode.h \ motionsearch.h \ yuv4mpeg.h MAINTAINERCLEANFILES = Makefile.in mjpegtools-2.1.0/utils/altivec/0000755000175000017500000000000012217306500016774 5ustar glowwormglowwormmjpegtools-2.1.0/utils/altivec/motion.c0000644000175000017500000000654710532365710020467 0ustar glowwormglowworm/* motion.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "cpu_accel.h" #include "altivec_motion.h" #include "../mjpeg_logging.h" #define SIMD_DO(x) if(disable_simd( #x)) mjpeg_info(" Disabling " #x); else p##x = x##_altivec void enable_altivec_motion() { #if ALTIVEC_TEST_MOTION # if defined(ALTIVEC_BENCHMARK) mjpeg_info("SETTING AltiVec BENCHMARK for MOTION!"); # elif defined(ALTIVEC_VERIFY) mjpeg_info("SETTING AltiVec VERIFY for MOTION!"); # endif #else mjpeg_info("SETTING AltiVec for MOTION!"); #endif /* psad_sub22 = sad_sub22; */ /* psad_sub44 = sad_sub44; */ /* disable sad_00_altivec when benchmarking find_best_one_pel */ #if !(defined(ALTIVEC_BENCHMARK) && ALTIVEC_TEST_FUNCTION(find_best_one_pel)) #if ALTIVEC_TEST_FUNCTION(sad_00) psad_00 = ALTIVEC_TEST_SUFFIX(sad_00); #else SIMD_DO(sad_00); #endif #endif #if ALTIVEC_TEST_FUNCTION(sad_01) psad_01 = ALTIVEC_TEST_SUFFIX(sad_01); #else SIMD_DO(sad_01); #endif #if ALTIVEC_TEST_FUNCTION(sad_10) psad_10 = ALTIVEC_TEST_SUFFIX(sad_10); #else SIMD_DO(sad_10); #endif #if ALTIVEC_TEST_FUNCTION(sad_11) psad_11 = ALTIVEC_TEST_SUFFIX(sad_11); #else SIMD_DO(sad_11); #endif #if ALTIVEC_TEST_FUNCTION(bsad) pbsad = ALTIVEC_TEST_SUFFIX(bsad); #else SIMD_DO(bsad); #endif #if ALTIVEC_TEST_FUNCTION(sumsq) psumsq = ALTIVEC_TEST_SUFFIX(sumsq); #else SIMD_DO(sumsq); #endif #if ALTIVEC_TEST_FUNCTION(sumsq_sub22) psumsq_sub22 = ALTIVEC_TEST_SUFFIX(sumsq_sub22); #else SIMD_DO(sumsq_sub22); #endif #if ALTIVEC_TEST_FUNCTION(bsumsq) pbsumsq = ALTIVEC_TEST_SUFFIX(bsumsq); #else SIMD_DO(bsumsq); #endif #if ALTIVEC_TEST_FUNCTION(bsumsq_sub22) pbsumsq_sub22 = ALTIVEC_TEST_SUFFIX(bsumsq_sub22); #else SIMD_DO(bsumsq_sub22); #endif #if ALTIVEC_TEST_FUNCTION(find_best_one_pel) pfind_best_one_pel = ALTIVEC_TEST_SUFFIX(find_best_one_pel); #else SIMD_DO(find_best_one_pel); #endif #if ALTIVEC_TEST_FUNCTION(build_sub22_mests) pbuild_sub22_mests = ALTIVEC_TEST_SUFFIX(build_sub22_mests); #else SIMD_DO(build_sub22_mests); #endif #if ALTIVEC_TEST_FUNCTION(build_sub44_mests) pbuild_sub44_mests = ALTIVEC_TEST_SUFFIX(build_sub44_mests); #else SIMD_DO(build_sub44_mests); #endif #if ALTIVEC_TEST_FUNCTION(variance) pvariance = ALTIVEC_TEST_SUFFIX(variance); #else SIMD_DO(variance); #endif #if ALTIVEC_TEST_FUNCTION(subsample_image) psubsample_image = ALTIVEC_TEST_SUFFIX(subsample_image); #else psubsample_image = subsample_image_altivec; #endif } mjpegtools-2.1.0/utils/altivec/altivec_quantize.h0000644000175000017500000000527607746062336022547 0ustar glowwormglowworm/* altivec_quantize.h, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "../../mpeg2enc/quantize_ref.h" /* next_larger_quant */ #include "altivec_conf.h" #define ALTIVEC_TEST_QUANTIZE /* {{{ */ \ ( ( defined(ALTIVEC_BENCHMARK) || defined(ALTIVEC_VERIFY) ) && \ ( ALTIVEC_TEST_FUNCTION(quant_non_intra) || \ ALTIVEC_TEST_FUNCTION(quant_weight_coeff_intra) || \ ALTIVEC_TEST_FUNCTION(quant_weight_coeff_inter) || \ ALTIVEC_TEST_FUNCTION(iquant_non_intra_m1) || \ ALTIVEC_TEST_FUNCTION(iquant_non_intra_m2) || \ ALTIVEC_TEST_FUNCTION(iquant_intra_m1) || \ ALTIVEC_TEST_FUNCTION(iquant_intra_m2) ) ) \ /* }}} */ #ifdef __cplusplus extern "C" { #endif void enable_altivec_quantization(struct QuantizerCalls *calls, int opt_mpeg1); ALTIVEC_FUNCTION(quant_non_intra, int, (struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int q_scale_type, int dctsatlim, int *nonsat_mquant)); ALTIVEC_FUNCTION(quant_weight_coeff_intra, int, (struct QuantizerWorkSpace *wsp, int16_t *blk)); ALTIVEC_FUNCTION(quant_weight_coeff_inter, int, (struct QuantizerWorkSpace *wsp, int16_t *blk)); ALTIVEC_FUNCTION(iquant_non_intra_m1, void, (struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int mquant)); ALTIVEC_FUNCTION(iquant_non_intra_m2, void, (struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int mquant)); ALTIVEC_FUNCTION(iquant_intra_m1, void, (struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int dc_prec, int mquant)); ALTIVEC_FUNCTION(iquant_intra_m2, void, (struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int dc_prec, int mquant)); #ifdef __cplusplus } #endif mjpegtools-2.1.0/utils/altivec/benchmark.h0000644000175000017500000002137007741374112021114 0ustar glowwormglowworm/* benchmark.h, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #define BENCHMARK_ARGS_BUFSIZE 256 struct benchmark_times { struct timeval total, min, max; char min_args[BENCHMARK_ARGS_BUFSIZE]; char max_args[BENCHMARK_ARGS_BUFSIZE]; }; struct benchmark_stats { unsigned long counter; /* number of times function is called */ unsigned long iterations; /* value is calibrated for each function */ unsigned long benchmark_runs; /* number of time benchmar is run */ struct benchmark_times times[2]; }; #ifdef __cplusplus extern "C" { #endif int calibrate_benchmark(double precision, double increment, int timelimit, int reqpasses, int *passes, int *iterations, int *calibration, struct timeval *time, struct timeval *last_time); void update_benchmark_times(const char *name, struct benchmark_times *times, struct timeval *time, const char *fmt, ...) __attribute__ ((format (printf, 4,5))); void print_calibration_stats(int count, char* name[], int *calibration, struct timeval *times); void print_benchmark_diff(int count, char* name[], struct timeval *times); void print_benchmark_stats(const char* name, struct benchmark_stats *stats); void print_benchmark_statistics(); #ifdef __cplusplus } #endif #define BENCHMARK_TIME(i,iterations,do,start,end,time) \ gettimeofday((start), (struct timezone*)0); \ for ((i) = 0; (i) < (iterations); (i)++) { \ do; do; do; do; do; do; do; do; do; do; \ } \ gettimeofday((end), (struct timezone*)0); \ timersub((end), (start), (time)); \ #define ALTIVEC_TEST_BENCHMARK(name,ret,defargs,pfmt,args) \ ret ALTIVEC_TEST_WITH(name) defargs; \ struct benchmark_stats name##_altivec_benchmark_stats; \ ret name##_altivec_benchmark defargs { \ int i, j, passes, done; \ struct timeval start, end, times[2], last_time; \ char *fnames[2]; \ ret (*pfuncs[2]) defargs; \ ret (*pfunc) defargs; \ int iterations, calibration[2]; \ AVRETDECL(ret,retval); \ \ if (name##_altivec_benchmark_stats.counter % BENCHMARK_FREQUENCY == 0 && \ name##_altivec_benchmark_stats.benchmark_runs < BENCHMARK_MAX_RUNS) \ { \ name##_altivec_benchmark_stats.benchmark_runs++; \ fnames[0] = AVSTR(name##_altivec); \ fnames[1] = AVSTR(ALTIVEC_TEST_WITH(name)); \ pfuncs[0] = name##_altivec; \ pfuncs[1] = ALTIVEC_TEST_WITH(name); \ \ /* make sure calibration has been done */ \ if (name##_altivec_benchmark_stats.iterations == 0) \ { \ mjpeg_info("starting benchmark calibration for " #name); \ \ for (i = 0; i < 2; i++) \ { \ pfunc = pfuncs[i]; \ passes = 0; \ iterations = BENCHMARK_ITERATIONS / 10; /* /10 for BENCHMARK_TIME */ \ last_time.tv_sec = last_time.tv_usec = 0; \ \ do \ { \ BENCHMARK_TIME(j,iterations,(*pfunc)(args),&start,&end,×[i]); \ done = calibrate_benchmark(BENCHMARK_PRECISION, \ BENCHMARK_INCREMENT, \ BENCHMARK_TIMELIMIT, \ BENCHMARK_PASSES, \ &passes, &iterations, &calibration[i], \ ×[i], &last_time); \ } while (!done); \ } \ \ calibration[0] *= 10; /* adjust for previous /10 for BENCHMARK_TIME */ \ calibration[1] *= 10; \ \ iterations = (calibration[0] > calibration[1] \ ? calibration[0] \ : calibration[1]); \ name##_altivec_benchmark_stats.iterations = iterations; \ \ print_calibration_stats(2, fnames, calibration, times); \ } \ \ BENCHMARK_PROLOG \ \ for (i = 0; i < 2; i++) \ { \ pfunc = pfuncs[i]; \ iterations = name##_altivec_benchmark_stats.iterations / 10; \ \ BENCHMARK_TIME(j,iterations,(*pfunc)(args),&start,&end,×[i]); \ \ update_benchmark_times(fnames[i], \ &name##_altivec_benchmark_stats.times[i], \ ×[i], "%s(" pfmt ")", fnames[i], args); \ } \ print_benchmark_diff(2, fnames, times); \ \ BENCHMARK_EPILOG \ } \ name##_altivec_benchmark_stats.counter++; \ \ AVRETSET(ret,retval,name##_altivec(args)); \ AVRETURN(ret,retval); \ } mjpegtools-2.1.0/utils/altivec/sub_mean_reduction_ppc.S0000644000175000017500000001156012165565411023644 0ustar glowwormglowworm/* sub_mean_reduction_ppc.S, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* register, local label and global macros */ #if defined(__linux__) || defined(__FreeBSD__) #define R(register_number) register_number #define L(label_name) .L##label_name #define G(global_name) global_name #else /* Mac OS X */ #define R(register_number) r##register_number #define L(label_name) L##label_name #define G(global_name) _##global_name #endif #ifdef __linux__ .section ".text" #endif .align 2 #undef AMBER_ENABLE #ifdef AMBER_ENABLE amber_signal: mfspr R(0), 1023 blr #endif .globl G(sub_mean_reduction_ppc) #ifdef __linux__ .type G(sub_mean_reduction_ppc),@function #endif /* arguments: * R(3): int len (matchset->len) * R(4): me_result_set* matchset * R(5): int reduction_times * * variables: * R(0): tmp * R(6): weight_sum * R(7): match * R(8): mean_weight * R(9): tail * R(10): w0 * R(11): w1 * R(12): m0 * R(14): m1 * R(15): len/2 * R(16): lr #if ALTIVEC_ENABLE */ G(sub_mean_reduction_ppc): #ifdef AMBER_ENABLE stw R(16),-12(R(1)) /* save nonvolatile register r16 */ mflr R(16) bl amber_signal #endif stw R(14),-4(R(1)) /* save nonvolatile register r14 */ cmpwi cr1,R(3),2 /* cmp len 2 */ stw R(15),-8(R(1)) /* save nonvolatile register r15 */ mr R(7),R(4) /* match = matchset, ((++match) == matchset->mests) */ li R(6),0 /* weight_sum = 0 */ blt cr1,L(sumLt2) srawi R(15),R(3),1 /* len/2 */ mtctr R(15) /* ctr = len/2 */ L(sumLoop): lhzu R(10),4(R(7)) /* w0 = *(++match).weight */ lhzu R(11),4(R(7)) /* w1 = *(++match).weight */ add R(6),R(10),R(6) /* weight_sum += w0 */ add R(6),R(11),R(6) /* weight_sum += w1 */ bdnz L(sumLoop) L(sumLt2): andi. R(0),R(3),1 /* if (len & 1) */ beq L(sumN1) lhz R(10), 4(R(7)) /* w0 = match->weight */ add R(6),R(10),R(6) /* weight_sum += w0 */ L(sumN1): L(reduce): mr R(7),R(4) /* match = matchset */ mr R(9),R(4) /* tail = matchset */ divw R(8),R(6),R(3) /* mean_weight = weight_sum / len */ li R(6),0 /* weight_sum = 0 */ blt cr1,L(reduceLt2) mtctr R(15) /* ctr = len/2 */ L(reduceLoop): lwzu R(12),4(R(7)) /* m0 = *(++match) */ srwi R(10),R(12),16 /* w0 = m0.weight */ lwzu R(14),4(R(7)) /* m1 = *(++match) */ srwi R(11),R(14),16 /* w1 = m1.weight */ cmpw cr0,R(10),R(8) /* cmp w0 mean_weight */ cmpw cr1,R(11),R(8) /* cmp w1 mean_weight */ bgt cr0,L(skip0) stwu R(12),4(R(9)) /* *(++tail) = m0 */ add R(6),R(10),R(6) /* weight_sum += w0 */ L(skip0): bgt cr1,L(skip1) stwu R(14),4(R(9)) /* *(++tail) = m1 */ add R(6),R(11),R(6) /* weight_sum += w1 */ L(skip1): bdnz L(reduceLoop) L(reduceLt2): andi. R(0),R(3),1 /* if (len & 1) */ beq L(reduceN1) lwzu R(12),4(R(7)) /* m0 = *(++match) */ srwi R(10),R(12),16 /* w0 = m0.weight */ cmpw cr0,R(10),R(8) /* cmp w0 mean_weight */ bgt cr0,L(skip3) stwu R(12),4(R(9)) /* *(++tail) = m0 */ add R(6),R(10),R(6) /* weight_sum += w0 */ L(skip3): L(reduceN1): subic. R(5),R(5),1 /* reduction_times-- (set cr0) */ subf R(3),R(4),R(9) /* len*4 = tail - matchset */ srawi R(3),R(3),2 /* len = (len*4) >> 2 */ cmpwi cr1,R(3),2 /* cmp len 2 */ cror 10,2,4 /* cr2[eq] = cr0[eq] | cr1[lt] */ srawi R(15),R(3),1 /* len/2 */ bne cr2,L(reduce) stwu R(3),0(R(4)) /* matchset->len = len */ lwz R(14),-4(R(1)) /* restore nonvolatile register r14 */ lwz R(15),-8(R(1)) /* restore nonvolatile register r15 */ #ifdef AMBER_ENABLE bl amber_signal mtlr R(16) lwz R(16),-12(R(1)) /* restore nonvolatile register r16 */ #endif blr #ifdef __linux__ L(end): .size G(sub_mean_reduction_ppc),L(end)-G(sub_mean_reduction_ppc) #endif mjpegtools-2.1.0/utils/altivec/build_sub44_mests.c0000644000175000017500000005551010532365710022507 0ustar glowwormglowworm/* build_sub44_mests.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_motion.h" #include "vectorize.h" #include "../fastintfns.h" #include "../mjpeg_logging.h" #include #include /* #define AMBER_ENABLE */ /* #define AMBER_MAX_TRACES 10 */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif #define USE_SMR_PPC #ifdef USE_SMR_PPC extern int sub_mean_reduction_ppc(int len, me_result_set *set, int reduction); #endif /* C skim rule */ #define SKIM(weight,threshold) (weight < threshold) /* MMX skim rule */ /* #define SKIM(weight,threshold) (weight <= threshold) */ /* Rough and-ready absolute distance penalty * NOTE: This penalty is *vital* to correct operation * as otherwise the sub-mean filtering won't work on very * uniform images. */ /* C penalty calculation */ #define DISTANCE_PENALTY(x,y) (intmax(abs(x - i0),abs(y - j0))<<1) /* MMX penalty calculation */ /* #define DISTANCE_PENALTY(x,y) (intmax(abs(x),abs(y))<<2) */ /* old MMX penalty calculation */ /* #define DISTANCE_PENALTY(x,y) (abs(x)+abs(y)) */ /* Do threshold lookahead? This also generates different results than * the C version, also slightly worse output. (should be faster though) */ #undef THRESHOLD_LOOKAHEAD #define THRESHOLD #ifdef THRESHOLD # define UPDATE_THRESHOLD(w,t) (t) = intmin((w) << 2, (t)) #else # define UPDATE_THRESHOLD(w,t) #endif #if 0 #undef THRESHOLD #undef SKIM #define SKIM(w,t) 1 #undef DISTANCE_PENALTY #define DISTANCE_PENALTY(x,y) 0 #endif /* * s44org % 16 == 0 * s44blk % 4 == 0 * h == 2 or 4 * (rowstride % 16) == 0 * (ihigh-ilow)+1 % 16 == 0 very often * (jhigh-jlow)+1 % 16 == 0 very often */ #define BUILD_SUB44_MESTS_PDECL /* {{{ */ \ me_result_set *sub44set, \ int ilow, int jlow, int ihigh, int jhigh, \ int i0, int j0, \ int null_ctl_sad, \ uint8_t *s44org, uint8_t *s44blk, \ int rowstride, int h, \ int reduction \ /* }}} */ #define BUILD_SUB44_MESTS_ARGS /* {{{ */ \ sub44set, \ ilow, jlow, ihigh, jhigh, \ i0, j0, \ null_ctl_sad, \ s44org, s44blk, \ rowstride, h, \ reduction \ /* }}} */ /* int build_sub44_mests_altivec(BUILD_SUB44_MESTS_PDECL) {{{ */ #if defined(ALTIVEC_VERIFY) && ALTIVEC_TEST_FUNCTION(build_sub44_mests) #define VERIFY_BUILD_SUB44_MESTS #define VERIFY_SADS(orgblk,s44blk,rowstride,h,sads,count) if (verify) \ { verify_sads(orgblk,s44blk,rowstride,h,sads,count); } /* declarations */ static int _build_sub44_mests_altivec(BUILD_SUB44_MESTS_PDECL, int verify); static void verify_sads(unsigned char *orgblk, unsigned char* s44blk, int rowstride, int h, unsigned int *sads, int count); int build_sub44_mests_altivec(BUILD_SUB44_MESTS_PDECL) { return _build_sub44_mests_altivec(BUILD_SUB44_MESTS_ARGS, 0 /* no verify */); } static int _build_sub44_mests_altivec(BUILD_SUB44_MESTS_PDECL, int verify) #else #define VERIFY_SADS(orgblk,s44blk,rowstride,h,sads,count) /* no verify */ int build_sub44_mests_altivec(BUILD_SUB44_MESTS_PDECL) #endif /* }}} */ { int i, j; int x, y; int xlow, xl, x16, xl1, xl2, xl3; uint8_t *currowblk, *curblk, *nextrowblk; int threshold; me_result_s *cres; me_result_s mres; vector unsigned char t1, t2, t3, perm; vector unsigned char shift, shifter, increment; vector unsigned char vr0, vr1; vector unsigned char vx0y0, vx16y0, vx0y1, vx16y1; vector signed int sads; unsigned int *psads; unsigned int *psad; #ifdef ALTIVEC_DST DataStreamControl dsc; #endif #ifndef USE_SMR_PPC int mean_weight; #endif #ifdef AMBER_ENABLE int stop_amber = 0; #endif #ifdef ALTIVEC_VERIFY if (NOT_VECTOR_ALIGNED(s44org)) mjpeg_error_exit1("build_sub44_mests: s44org %% 16 != 0 (0x%X)", s44org); if (NOT_VECTOR_ALIGNED(rowstride)) mjpeg_error_exit1("build_sub44_mests: rowstride %% 16 != 0 (%d)", rowstride); if (((unsigned long)s44blk) & 0x3 != 0) mjpeg_error_exit1("build_sub44_mests: s44blk %% 4 != 0 (0x%X)", s44blk); #endif if (h != 2 && h != 4) mjpeg_error_exit1("build_sub44_mests: h != [2|4], (%d)", h); #ifdef AMBER_ENABLE /* enable amber for non-edge bound search radii */ if (((ihigh - ilow) >> 1) == (ihigh - i0) && ((jhigh - jlow) >> 1) == (jhigh - j0)) { stop_amber = 1; AMBER_START; } #endif #ifdef ALTIVEC_DST dsc.control = DATA_STREAM_CONTROL(1,0,0); dsc.block.count = h; dsc.block.stride = rowstride; vec_dst(s44blk, dsc.control, 0); xl = ((ihigh - ilow) >> 2) + 1; currowblk = s44org+(ilow>>2)+rowstride*(jlow>>2); xl1 = (xl + 3 + 15 + ((unsigned long)currowblk & 0xf)) >> 4; dsc.block.size = xl1; vec_dst(currowblk, dsc.control, 1); dsc.block.count = 1; /* loading one row at a time from now on */ #else xl = ((ihigh - ilow) >> 2) + 1; currowblk = s44org+(ilow>>2)+rowstride*(jlow>>2); xl1 = (xl + 3 + 15 + ((unsigned long)currowblk & 0xf)) >> 4; #endif /* shift = (0x00010203, 0x01020304, 0x02030405, 0x03040506) {{{ */ shift = vec_lvsl(0, (unsigned char*) 0); /* tmp(shifter) = (0,0,0,0, 1,1,1,1, 2,2,2,2, 3,3,3,3) {{{ */ shifter = vec_splat_u8(2); shifter = vec_sr(shift /* lvsl */, shifter /* (2) */ ); /* }}} */ shift = vu8(vec_splat(vu32(shift), 0)); /* (0x00010203, ...) */ shift = vec_add(shift, shifter); increment = vec_splat_u8(4); /* }}} */ threshold = 6*null_ctl_sad / (4*4*reduction); y = jlow - j0; xlow = ilow - i0; perm = vec_lvsl(0, (unsigned char*)currowblk); perm = vec_splat(perm, 0); if (xl1 < 3) { /* if (xl1 == 1) # of vec_ld = ((yl + h - 1) */ /* if (xl1 == 2) # of vec_ld = ((yl + h - 1) * 2) */ x16 = 16 * (xl1 >> 1); /* if (xl1 == 1) x16=0 if (xl1 == 2) x16=16 */ xl1 = xl; xl2 = 0; xl3 = 0; } else { int sh; /* else (xl1 > 2) # of vec_ld = ((yl + h - 1) * (xl1)) */ x16 = 16; xl1 = 16; xl2 = xl - 16; xl3 = (((xl2 & 0xf) + 3) >> 2); sh = (xl2 >> 4) * 3; xl2 = (xl2 + 15) >> 4; /* (xl2 + 15) / 16 */ xl3 = (xl3 << sh) | (((unsigned int)(~0) >> (32 - sh)) & 0x4924); } xl1 = (xl1 + 3) >> 2; /* (xl1 + 3) / 4 */ j = ((jhigh - jlow) >> 2) + 1; vr0 = vec_ld(0, (unsigned char*)s44blk); vr1 = vec_ld(rowstride, (unsigned char*)s44blk); t1 = vec_lvsl(0, (unsigned char*)s44blk); t1 = vu8(vec_splat(vu32(t1), 0)); vr0 = vec_perm(vr0, vr0, t1); vr1 = vec_perm(vr1, vr1, t1); vx0y0 = vec_ld(0, (unsigned char*)currowblk); vx16y0 = vec_ld(x16, (unsigned char*)currowblk); cres = sub44set->mests; if (h < 4) { /* {{{ */ nextrowblk = currowblk + rowstride; do /* while (--j) */ { vx0y1 = vec_ld(0, (unsigned char*)nextrowblk); vx16y1 = vec_ld(x16, (unsigned char*)nextrowblk); nextrowblk += rowstride; #ifdef ALTIVEC_DST vec_dst(nextrowblk, dsc.control, 0); #endif shifter = vec_add(shift, perm); /* vector align for vec_st */ psad = psads = (unsigned int*)(((unsigned long)cres + 15) & (~0xf)); /* calculating sads in the X direction 4 at a time. */ i = xl1; do { sads = vec_splat_s32(0); t1 = vec_perm(vx0y0, vx16y0, shifter); t2 = vec_max(t1, vr0); /* find largest of two */ t3 = vec_min(t1, vr0); /* find smaller of two */ t3 = vec_sub(t2, t3); /* find absolute difference */ sads = vs32(vec_sum4s(t3, vu32(sads))); t1 = vec_perm(vx0y1, vx16y1, shifter); t2 = vec_max(t1, vr1); t3 = vec_min(t1, vr1); t3 = vec_sub(t2, t3); sads = vs32(vec_sum4s(t3, vu32(sads))); vec_st(vu32(sads), 0, psad); psad += 4; /* increment permute for next iteration */ shifter = vec_add(shifter, increment); } while (--i); if (xl2) { vector unsigned char vn0y0, vn16y0, vn0y1, vn16y1; int i2, i3; curblk = currowblk + 16; /* update to current pointer */ vn16y0 = vec_sld(vx16y0, vx16y0, 0); /* vn16y0 = vx16y0 (VPU) */ vn16y1 = vec_or(vx16y1, vx16y1); /* vn16y1 = vx16y1 (VALU) */ i = xl2; i2 = xl3; do { curblk += 16; /* update to next pointer */ vn0y0 = vec_sld(vn16y0, vn16y0, 0); vn16y0 = vec_ld(0, (unsigned char*)curblk); vn0y1 = vec_or(vn16y1, vn16y1); vn16y1 = vec_ld(rowstride, (unsigned char*)curblk); shifter = vec_add(shift, perm); i3 = i2 & 0x7; i2 >>= 3; do { sads = vec_splat_s32(0); t1 = vec_perm(vn0y0, vn16y0, shifter); t2 = vec_max(t1, vr0); /* find largest of two */ t3 = vec_min(t1, vr0); /* find smaller of two */ t3 = vec_sub(t2, t3); /* find absolute difference */ sads = vs32(vec_sum4s(t3, vu32(sads))); t1 = vec_perm(vn0y1, vn16y1, shifter); t2 = vec_max(t1, vr1); t3 = vec_min(t1, vr1); t3 = vec_sub(t2, t3); sads = vs32(vec_sum4s(t3, vu32(sads))); vec_st(vu32(sads), 0, psad); psad += 4; /* increment permute for next iteration */ shifter = vec_add(shifter, increment); } while (--i3); /* vn0y0 = vec_sld(vn16y0, vn16y0, 0); vn0y1 = vec_or(vn16y1, vn16y1); */ } while (--i); } #ifdef ALTIVEC_VERIFY VERIFY_SADS(currowblk, s44blk, rowstride, h, psads, xl); #endif psad = psads; mres.y = (int8_t)y; x = xlow; i = xl >> 2; while (i--) { int w0, w1, w2, w3, tx; w0 = *psad; psad++; w1 = *psad; psad++; w2 = *psad; psad++; w3 = *psad; psad++; if (SKIM(w0, threshold)) { UPDATE_THRESHOLD(w0,threshold); mres.weight = (uint16_t)(w0 + DISTANCE_PENALTY(x,y)); mres.x = (int8_t)x; *cres = mres; cres++; } if (SKIM(w1, threshold)) { UPDATE_THRESHOLD(w1,threshold); tx = x + 4; mres.weight = (uint16_t)(w1 + DISTANCE_PENALTY(tx,y)); mres.x = (int8_t)tx; *cres = mres; cres++; } if (SKIM(w2, threshold)) { UPDATE_THRESHOLD(w2,threshold); tx = x + 8; mres.weight = (uint16_t)(w2 + DISTANCE_PENALTY(tx,y)); mres.x = (int8_t)tx; *cres = mres; cres++; } if (SKIM(w3, threshold)) { UPDATE_THRESHOLD(w3,threshold); tx = x + 12; mres.weight = (uint16_t)(w3 + DISTANCE_PENALTY(tx,y)); mres.x = (int8_t)tx; *cres = mres; cres++; } x += 16; } i = xl & 0x3; while (i--) { int weight = *psad; psad++; if (SKIM(weight, threshold)) { UPDATE_THRESHOLD(weight,threshold); mres.weight = (uint16_t)(weight + DISTANCE_PENALTY(x,y)); mres.x = (int8_t)x; *cres = mres; cres++; } x += 4; } currowblk += rowstride; vx0y0 = vec_sld(vx0y1, vx0y1, 0); /* vx0y0 = vx0y1 (VPU) */ vx16y0 = vec_or(vx16y1, vx16y1); /* vx16y0 = vx16y1 (VALU) */ y += 4; } while (--j); /* }}} */ } else /* h == 4 */ { /* {{{ */ vector unsigned char vr2, vr3; vector unsigned char vx0y2, vx16y2, vx0y3, vx16y3; int rowstride2, rowstride3; rowstride2 = rowstride + rowstride; vr2 = vec_ld(rowstride2, (unsigned char*)s44blk); rowstride3 = rowstride2 + rowstride; vr3 = vec_ld(rowstride3, (unsigned char*)s44blk); vr2 = vec_perm(vr2, vr2, t1); vr3 = vec_perm(vr3, vr3, t1); curblk = currowblk + rowstride; vx0y1 = vec_ld(0, (unsigned char*)curblk); vx16y1 = vec_ld(x16, (unsigned char*)curblk); curblk += rowstride; vx0y2 = vec_ld(0, (unsigned char*)curblk); vx16y2 = vec_ld(x16, (unsigned char*)curblk); nextrowblk = curblk + rowstride; do { vx0y3 = vec_ld(0, (unsigned char*)nextrowblk); vx16y3 = vec_ld(x16, (unsigned char*)nextrowblk); nextrowblk += rowstride; #ifdef ALTIVEC_DST vec_dst(nextrowblk, dsc.control, 0); #endif shifter = vec_add(shift, perm); psad = psads = (unsigned int*)(((unsigned long)cres + 15) & (~0xf)); /* calculating sads in the X direction 4 at a time. */ i = xl1; do { sads = vec_splat_s32(0); t1 = vec_perm(vx0y0, vx16y0, shifter); t2 = vec_max(t1, vr0); /* find largest of two */ t3 = vec_min(t1, vr0); /* find smaller of two */ t3 = vec_sub(t2, t3); /* find absolute difference */ sads = vs32(vec_sum4s(t3, vu32(sads))); t1 = vec_perm(vx0y1, vx16y1, shifter); t2 = vec_max(t1, vr1); t3 = vec_min(t1, vr1); t3 = vec_sub(t2, t3); sads = vs32(vec_sum4s(t3, vu32(sads))); t1 = vec_perm(vx0y2, vx16y2, shifter); t2 = vec_max(t1, vr2); t3 = vec_min(t1, vr2); t3 = vec_sub(t2, t3); sads = vs32(vec_sum4s(t3, vu32(sads))); t1 = vec_perm(vx0y3, vx16y3, shifter); t2 = vec_max(t1, vr3); t3 = vec_min(t1, vr3); t3 = vec_sub(t2, t3); sads = vs32(vec_sum4s(t3, vu32(sads))); vec_st(vu32(sads), 0, psad); psad += 4; /* increment permute for next iteration */ shifter = vec_add(shifter, increment); } while (--i); if (xl2) { vector unsigned char vn0y0, vn16y0, vn0y1, vn16y1; vector unsigned char vn0y2, vn16y2, vn0y3, vn16y3; int i2, i3; curblk = currowblk + 16; /* update to current pointer */ vn16y0 = vec_sld(vx16y0, vx16y0, 0); vn16y1 = vec_or(vx16y1, vx16y1); vn16y2 = vec_sld(vx16y2, vx16y2, 0); vn16y3 = vec_or(vx16y3, vx16y3); i = xl2; i2 = xl3; do { curblk += 16; /* update to next pointer */ vn0y0 = vec_sld(vn16y0, vn16y0, 0); vn16y0 = vec_ld(0, (unsigned char*)curblk); vn0y1 = vec_or(vn16y1, vn16y1); vn16y1 = vec_ld(rowstride, (unsigned char*)curblk); vn0y2 = vec_sld(vn16y2, vn16y2, 0); vn16y2 = vec_ld(rowstride2, (unsigned char*)curblk); vn0y3 = vec_or(vn16y3, vn16y3); vn16y3 = vec_ld(rowstride3, (unsigned char*)curblk); shifter = vec_add(shift, perm); i3 = i2 & 0x7; i2 >>= 3; do { sads = vec_splat_s32(0); t1 = vec_perm(vn0y0, vn16y0, shifter); t2 = vec_max(t1, vr0); /* find largest of two */ t3 = vec_min(t1, vr0); /* find smaller of two */ t3 = vec_sub(t2, t3); /* find absolute difference */ sads = vs32(vec_sum4s(t3, vu32(sads))); t1 = vec_perm(vn0y1, vn16y1, shifter); t2 = vec_max(t1, vr1); t3 = vec_min(t1, vr1); t3 = vec_sub(t2, t3); sads = vs32(vec_sum4s(t3, vu32(sads))); t1 = vec_perm(vn0y2, vn16y2, shifter); t2 = vec_max(t1, vr2); t3 = vec_min(t1, vr2); t3 = vec_sub(t2, t3); sads = vs32(vec_sum4s(t3, vu32(sads))); t1 = vec_perm(vn0y3, vn16y3, shifter); t2 = vec_max(t1, vr3); t3 = vec_min(t1, vr3); t3 = vec_sub(t2, t3); sads = vs32(vec_sum4s(t3, vu32(sads))); vec_st(vu32(sads), 0, psad); psad += 4; /* increment permute for next iteration */ shifter = vec_add(shifter, increment); } while (--i3); } while (--i); } #ifdef ALTIVEC_VERIFY VERIFY_SADS(currowblk, s44blk, rowstride, h, psads, xl); #endif psad = psads; mres.y = (int8_t)y; x = xlow; i = xl >> 2; while (i--) { int w0, w1, w2, w3, tx; w0 = *psad; psad++; w1 = *psad; psad++; w2 = *psad; psad++; w3 = *psad; psad++; if (SKIM(w0, threshold)) { UPDATE_THRESHOLD(w0,threshold); mres.weight = (uint16_t)(w0 + DISTANCE_PENALTY(x,y)); mres.x = (int8_t)x; *cres = mres; cres++; } if (SKIM(w1, threshold)) { UPDATE_THRESHOLD(w1,threshold); tx = x + 4; mres.weight = (uint16_t)(w1 + DISTANCE_PENALTY(tx,y)); mres.x = (int8_t)tx; *cres = mres; cres++; } if (SKIM(w2, threshold)) { UPDATE_THRESHOLD(w2,threshold); tx = x + 8; mres.weight = (uint16_t)(w2 + DISTANCE_PENALTY(tx,y)); mres.x = (int8_t)tx; *cres = mres; cres++; } if (SKIM(w3, threshold)) { UPDATE_THRESHOLD(w3,threshold); tx = x + 12; mres.weight = (uint16_t)(w3 + DISTANCE_PENALTY(tx,y)); mres.x = (int8_t)tx; *cres = mres; cres++; } x += 16; } i = xl & 0x3; while (i--) { int weight = *psad; psad++; if (SKIM(weight, threshold)) { UPDATE_THRESHOLD(weight,threshold); mres.weight = (uint16_t)(weight + DISTANCE_PENALTY(x,y)); mres.x = (int8_t)x; *cres = mres; cres++; } x += 4; } currowblk += rowstride; vx0y0 = vec_sld(vx0y1, vx0y1, 0); /* vx0y0 = vx0y1 (VPU) */ vx16y0 = vec_or(vx16y1, vx16y1); /* vx16y0 = vx16y1 (VALU) */ vx0y1 = vec_sld(vx0y2, vx0y2, 0); /* vx0y1 = vx0y2 (VPU) */ vx16y1 = vec_or(vx16y2, vx16y2); /* vx16y1 = vx16y2 (VALU) */ vx0y2 = vec_sld(vx0y3, vx0y3, 0); /* vx0y2 = vx0y3 (VPU) */ vx16y2 = vec_or(vx16y3, vx16y3); /* vx16y2 = vx16y3 (VALU) */ y += 4; } while (--j); /* }}} */ } #ifdef ALTIVEC_DST vec_dss(0); #endif /* sub44set->len = cres - sub44set->mests; */ xl = cres - sub44set->mests; sub44set->len = xl; #ifdef AMBER_ENABLE if (stop_amber) { AMBER_STOP; } #endif #ifdef USE_SMR_PPC if (xl > 1) xl = sub_mean_reduction_ppc(xl, sub44set, 1+(reduction > 1)); return xl; #else # if ALTIVEC_TEST_FUNCTION(sub_mean_reduction) ALTIVEC_TEST_SUFFIX(sub_mean_reduction)(sub44set, 1+(reduction>1), &mean_weight); # else sub_mean_reduction_altivec(sub44set, 1+(reduction>1), &mean_weight); # endif return sub44set->len; #endif } #if 0 /* build_sub44_mests_altivec_test {{{ */ int build_sub44_mests_altivec_test(me_result_set *sub44set, int ilow, int jlow, int ihigh, int jhigh, int i0, int j0, int null_ctl_sad, uint8_t *s44org, uint8_t *s44blk, int qrowstride, int qh, int reduction) { uint8_t *s44orgblk; me_result_s *sub44_mests = sub44set->mests; int istrt = ilow-i0; int jstrt = jlow-j0; int iend = ihigh-i0; int jend = jhigh-j0; int mean_weight; int threshold; int i,j; int s1; uint8_t *old_s44orgblk; int sub44_num_mests; threshold = 6*null_ctl_sad / (4*4*reduction); s44orgblk = s44org+(ilow>>2)+qrowstride*(jlow>>2); sub44_num_mests = 0; s44orgblk = s44org+(ilow>>2)+qrowstride*(jlow>>2); for (j = jstrt; j <= jend; j += 4) { old_s44orgblk = s44orgblk; for (i = istrt; i <= iend; i += 4) { s1 = ((*psad_sub44)( s44orgblk,s44blk,qrowstride,qh) & 0xffff); #ifdef THRESHOLD if (s1 < threshold) { threshold = intmin(s1<<2,threshold); #endif sub44_mests[sub44_num_mests].x = i; sub44_mests[sub44_num_mests].y = j; sub44_mests[sub44_num_mests].weight = s1 + DISTANCE_PENALTY(i,j); ++sub44_num_mests; #ifdef THRESHOLD } #endif s44orgblk += 1; } s44orgblk = old_s44orgblk + qrowstride; } sub44set->len = sub44_num_mests; #if 0 sub_mean_reduction(sub44set, 1+(reduction>1), &mean_weight); #endif return sub44set->len; } #endif /* }}} */ #if ALTIVEC_TEST_FUNCTION(build_sub44_mests) /* {{{ */ #define BUILD_SUB44_MESTS_PFMT \ "sub44set=0x%X, ilow=%d, jlow=%d, ihigh=%d, jhigh=%d, i0=%d, j0=%d, " \ "null_ctl_sad=%d, s44org=0x%X, s44blk=0x%X, qrowstride=%d, qh=%d, " \ "reduction=%d" # ifdef ALTIVEC_VERIFY int build_sub44_mests_altivec_verify(BUILD_SUB44_MESTS_PDECL) { int i, len1, len2; unsigned long checksum1, checksum2; len1 = _build_sub44_mests_altivec(BUILD_SUB44_MESTS_ARGS, 1 /*verify*/); for (checksum1 = i = 0; i < len1; i++) { checksum1 += sub44set->mests[i].weight; checksum1 += abs(sub44set->mests[i].x); checksum1 += abs(sub44set->mests[i].y); } len2 = ALTIVEC_TEST_WITH(build_sub44_mests)(BUILD_SUB44_MESTS_ARGS); for (checksum2 = i = 0; i < len2; i++) { checksum2 += sub44set->mests[i].weight; checksum2 += abs(sub44set->mests[i].x); checksum2 += abs(sub44set->mests[i].y); } if (len1 != len2 || checksum1 != checksum2) { mjpeg_debug("build_sub44_mests(" BUILD_SUB44_MESTS_PFMT ")", BUILD_SUB44_MESTS_ARGS); mjpeg_debug("build_sub44_mests: checksums differ %d[%d] != %d[%d]", checksum1, len1, checksum2, len2); #if 1 len1 = _build_sub44_mests_altivec(BUILD_SUB44_MESTS_ARGS, 0 /*verify*/); for (i = 0; i < len1; i++) { mjpeg_debug("A: %3d, %3d, %5d", sub44set->mests[i].x, sub44set->mests[i].y, sub44set->mests[i].weight); } len2 = ALTIVEC_TEST_WITH(build_sub44_mests)(BUILD_SUB44_MESTS_ARGS); for (i = 0; i < len2; i++) { mjpeg_debug("C: %3d, %3d, %5d", sub44set->mests[i].x, sub44set->mests[i].y, sub44set->mests[i].weight); } #endif } return len2; } static void verify_sads(unsigned char *orgblk, unsigned char* s44blk, int rowstride, int h, unsigned int *sads, int count) { unsigned int i, weight, cweight; unsigned char *pblk; pblk = orgblk; for (i = 0; i < count; i++) { weight = sads[i]; /* pblk = orgblk + (rowstride * i); */ #if ALTIVEC_TEST_FUNCTION(sad_sub44) cweight = ALTIVEC_TEST_WITH(sad_sub44)(pblk,s44blk,rowstride,h) & 0xffff; #else cweight = sad_sub44(pblk,s44blk,rowstride,h) & 0xffff; #endif if (weight != cweight) mjpeg_debug("build_sub44_mests: %d != %d=" "sad_sub44(blk1=0x%X, blk2=0x%X, rowstride=%d, h=%d)", weight, cweight, pblk, s44blk, rowstride, h); pblk++; } } # else #undef BENCHMARK_FREQUENCY #define BENCHMARK_FREQUENCY 543 /* benchmark every (n) calls */ #undef BENCHMARK_EPILOG #define BENCHMARK_EPILOG \ mjpeg_info("build_sub44_mests: (ihigh-ilow)/4+1=%d, (jhigh-jlow)/4+1=%d", \ (ihigh-ilow)/4+1, (jhigh-jlow)/4+1); ALTIVEC_TEST(build_sub44_mests, int, (BUILD_SUB44_MESTS_PDECL), BUILD_SUB44_MESTS_PFMT, BUILD_SUB44_MESTS_ARGS); # endif #endif /* }}} */ /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/Makefile.am0000644000175000017500000000202310277040421021026 0ustar glowwormglowworm# Process this file with Automake to produce Makefile.in INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/utils LTCOMPILE = $(LIBTOOL) --mode=compile \ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) noinst_LTLIBRARIES = libaltivec.la libaltivec_la_SOURCES = \ add_pred.c \ amber.c \ benchmark.c \ bsad.c \ bsumsq.c \ bsumsq_sub22.c \ build_sub22_mests.c \ build_sub44_mests.c \ detect.c \ fdct.c \ fdct_idct.c \ field_dct_best.c \ find_best_one_pel.c \ idct.c \ iquant_intra.c \ iquant_non_intra.c \ motion.c \ pred_comp.c \ quant_non_intra.c \ quant_weight_coeff_sum.c \ quantize.c \ sad_00.c \ sad_01.c \ sad_10.c \ sad_11.c \ sub_mean_reduction.c \ sub_mean_reduction_ppc.S \ sub_pred.c \ subsample_image.c \ sumsq.c \ sumsq_sub22.c \ variance.c noinst_HEADERS = \ altivec_conf.h \ altivec_motion.h \ altivec_predict.h \ altivec_quantize.h \ altivec_transform.h \ amber.h \ benchmark.h \ vectorize.h \ verify.h MAINTAINERCLEANFILES = Makefile.in mjpegtools-2.1.0/utils/altivec/build_sub22_mests.c0000644000175000017500000005112610532365710022502 0ustar glowwormglowworm/* build_sub22_mests.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_motion.h" #include "vectorize.h" #include #include "../mjpeg_logging.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif #define USE_SMR_PPC #ifdef USE_SMR_PPC extern int sub_mean_reduction_ppc(int len, me_result_set *set, int reduction); #endif /* * Get SAD for 2*2 subsampled macroblocks: * (0,0) (+2,0) (0,+2) (+2,+2) pixel-space coordinates * (0,0) (+1,0) (0,+1) (+1,+1) 2*2 subsampled coordinates * * blk (blk) * blk(+2, 0) (blk += 1) * blk( 0, +2) (blk += rowstride-1) * blk(+2, +2) (blk += 1) * * Iterate through all rows 2 at a time, calculating all 4 sads as we go. * * Hints regarding input: * a) blk may be vector aligned, mostly not aligned * b) ref is about 50% vector aligned and 50% 8 byte aligned * c) rowstride is always a multiple of 16 * d) h == 4 or 8 * * NOTES: Since ref is always 8 byte aligned and we are only interested in * the first 8 bytes, the data can always be retreived with one vec_ld. * This "one vec_ld" optimization is also attempted for blk. * * The permutation vectors only need to be calculated once since * rowstride is always a multiple of 16. */ #define BUILD_SUB22_MESTS_PDECL /* {{{ */ \ me_result_set *sub44set, \ me_result_set *sub22set, \ int i0, int j0, int ihigh, int jhigh, \ int null_ctl_sad, \ uint8_t *s22org, uint8_t *s22blk, \ int rowstride, int h, \ int reduction \ /* }}} */ #define BUILD_SUB22_MESTS_ARGS /* {{{ */ \ sub44set, sub22set, \ i0, j0, ihigh, jhigh, \ null_ctl_sad, \ s22org, s22blk, \ rowstride, h, \ reduction \ /* }}} */ /* int build_sub22_mests_altivec(BUILD_SUB22_MESTS_PDECL) {{{ */ #if defined(ALTIVEC_VERIFY) && ALTIVEC_TEST_FUNCTION(build_sub22_mests) #define VERIFY_BUILD_SUB22_MESTS static void verify_sads(uint8_t *blk1, uint8_t *blk2, int stride, int h, int *sads, int count); static int _build_sub22_mests_altivec(BUILD_SUB22_MESTS_PDECL, int verify); int build_sub22_mests_altivec(BUILD_SUB22_MESTS_PDECL) { return _build_sub22_mests_altivec(BUILD_SUB22_MESTS_ARGS, 0 /* no verify */); } static int _build_sub22_mests_altivec(BUILD_SUB22_MESTS_PDECL, int verify) #else int build_sub22_mests_altivec(BUILD_SUB22_MESTS_PDECL) #endif /* }}} */ { int i, ih; int x, y; uint8_t *s22orgblk; int len; me_result_s *sub44mests; me_result_s *cres; me_result_s mres; /* */ vector unsigned int zero; vector unsigned char lvsl; vector unsigned char perm2; vector unsigned char align8x2; vector unsigned int sads; vector signed char xy22, xylim; vector unsigned char xint, yint; vector unsigned int vthreshold; unsigned int threshold; int stride1, stride2, stride1_16, stride2_16; union { vector unsigned char _align16; struct { me_result_s xylim; unsigned int threshold; } init; me_result_s xy; me_result_s mests[4]; } vio; #ifdef ALTIVEC_DST DataStreamControl dsc; #endif #ifndef USE_SMR_PPC int min_weight; #endif #ifdef ALTIVEC_VERIFY if (NOT_VECTOR_ALIGNED(rowstride)) mjpeg_error_exit1("build_sub22_mests: rowstride %% 16 != 0, (%d)", rowstride); if (NOT_VECTOR_ALIGNED(cres)) mjpeg_warn("build_sub22_mests: cres %% 16 != 0, (0x%X)",cres); if (((unsigned long)s22blk & 0x7) != 0) mjpeg_error_exit1("build_sub22_mests: s22blk %% 8 != 0, (0x%X)", s22blk); #endif if (h != 4 && h != 8) mjpeg_error_exit1("build_sub22_mests: h != [4|8], (%d)", h); AMBER_START; len = sub44set->len; if (len < 1) { /* sub44set->len is sometimes zero. we can */ sub22set->len = 0; /* save a lot of effort if we stop short. */ return 0; } #ifdef ALTIVEC_DST dsc.control = DATA_STREAM_CONTROL(1,0,0); dsc.block.count = h; dsc.block.stride = rowstride; vec_dst(s22blk, dsc.control, 0); /* increase size to 2 and increment count */ dsc.control += DATA_STREAM_CONTROL(1,1,0); #endif sub44mests = sub44set->mests; cres = sub22set->mests; cres--; /* decrement cres so all stores can be done with stwu */ /* execute instructions that are not dependent on pack_bits */ zero = vec_splat_u32(0); /* initialize to zero */ /* lvsl = 0x(00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F) {{{ */ lvsl = vec_lvsl(0, (unsigned char*) 0); /* }}} */ /* 8*8 or 8*4 calculated in 8*2 chunks */ /* align8x2 = 0x(00 01 02 03 04 05 06 07 10 11 12 13 14 15 16 17) {{{ */ align8x2 = vec_sld(lvsl, lvsl, 8); perm2 = vec_lvsr(0, (unsigned char*)0); align8x2 = vec_sld(align8x2, perm2, 8); /* }}} */ mres.weight = 0; /* weight must be zero */ mres.x = ihigh - i0; /* x <= (ihigh - i0) */ mres.y = jhigh - j0; /* y <= (jhigh - j0) */ vio.init.xylim = mres; threshold = 6 * null_ctl_sad / (reduction << 2); vio.init.threshold = threshold; xy22 = (vector signed char)VCONST(0,0,0,0, 0,0,2,0, 0,0,0,2, 0,0,2,2); xint = vu8(vec_splat_u32(0xf)); xint = vec_add(xint, lvsl); yint = vu8(vec_splat_u32(1)); yint = vec_add(yint, xint); perm2 = vec_lvsl(0, s22blk); perm2 = vec_splat(perm2, 0); perm2 = vec_add(perm2, align8x2); stride1 = rowstride; stride2 = rowstride + rowstride; stride1_16 = stride1 + 16; stride2_16 = stride2 + 16; ih = (h >> 1) - 1; vthreshold = vec_ld(0, (unsigned int*) &vio.init); xylim = vs8(vec_splat(vu32(vthreshold), 0)); /* vio.init.xylim */ vthreshold = vu32(vec_splat(vu32(vthreshold), 1)); /* vio.init.threshold */ do { /* while (--len) */ mres = *sub44mests; x = mres.x; y = mres.y; s22orgblk = s22org + ((y+j0)>>1)*rowstride + ((x+i0)>>1); #ifdef ALTIVEC_DST vec_dst(s22orgblk, dsc.control, 1); #endif mres.weight = 0; /* weight must be zero */ vio.xy = mres; sub44mests++; /* calculate SADs for 2*2 subsampled macroblocks: {{{ */ { vector unsigned int sad20, sad02, sad22; vector unsigned char max, min, dif; vector unsigned char perm1; vector unsigned char align8x2_0, align8x2_2; vector unsigned char ld0, ld1, ld3; vector unsigned char v8x1a, v8x1b; vector unsigned char vblk8x2; vector unsigned char vref8x2; uint8_t *pblk, *pref; sads = zero; sad20 = zero; sad02 = zero; sad22 = zero; pblk = s22orgblk; pref = s22blk; perm1 = vec_lvsl(0, pblk); /* initialize permute vector */ if (((unsigned long)pblk & 0xf) < 8) { /* {{{ */ v8x1a = vec_ld(0, pblk); /* pblk += rowstride; */ v8x1b = vec_ld(stride1, pblk); vref8x2 = vec_ld(0, pref); /* pref += rowstride; */ ld3 = vec_ld(stride1, pref); align8x2_0 = vec_splat(perm1, 0); align8x2_0 = vec_add(align8x2_0, align8x2); align8x2_2 = vec_splat(perm1, 1); align8x2_2 = vec_add(align8x2_2, align8x2); vref8x2 = vec_perm(vref8x2, ld3, perm2); i = ih; do { /* while (--i) */ /* load next row */ /* pblk += rowstride; */ pblk += stride2; ld0 = vec_ld(0, pblk); /* calculate (0,0) */ vblk8x2 = vec_perm(v8x1a, v8x1b, align8x2_0); max = vec_max(vblk8x2, vref8x2); min = vec_min(vblk8x2, vref8x2); dif = vec_sub(max, min); sads = vec_sum4s(dif, sads); /* calculate (2,0) */ vblk8x2 = vec_perm(v8x1a, v8x1b, align8x2_2); max = vec_max(vblk8x2, vref8x2); min = vec_min(vblk8x2, vref8x2); dif = vec_sub(max, min); sad20 = vec_sum4s(dif, sad20); /* load into v8x1a, then v8x1b will be the top row */ v8x1a = vec_sld(ld0, ld0, 0); /* v8x1a = ld0; */ /* load next row */ /* pblk += rowstride; */ ld0 = vec_ld(stride1, pblk); /* calculate (0,2) */ vblk8x2 = vec_perm(v8x1b, v8x1a, align8x2_0); max = vec_max(vblk8x2, vref8x2); min = vec_min(vblk8x2, vref8x2); dif = vec_sub(max, min); sad02 = vec_sum4s(dif, sad02); /* calculate (2,2) */ vblk8x2 = vec_perm(v8x1b, v8x1a, align8x2_2); max = vec_max(vblk8x2, vref8x2); min = vec_min(vblk8x2, vref8x2); /* pref += rowstride; */ pref += stride2; vref8x2 = vec_ld(0, pref); /* pref += rowstride; */ ld3 = vec_ld(stride1, pref); dif = vec_sub(max, min); sad22 = vec_sum4s(dif, sad22); v8x1b = vec_sld(ld0, ld0, 0); /* v8x1b = ld0; */ vref8x2 = vec_perm(vref8x2, ld3, perm2); } while (--i); /* load next row */ /* pblk += rowstride; */ pblk += stride2; ld0 = vec_ld(0, pblk); /* calculate (0,0) */ vblk8x2 = vec_perm(v8x1a, v8x1b, align8x2_0); max = vec_max(vblk8x2, vref8x2); min = vec_min(vblk8x2, vref8x2); dif = vec_sub(max, min); sads = vec_sum4s(dif, sads); /* calculate (2,0) */ vblk8x2 = vec_perm(v8x1a, v8x1b, align8x2_2); /* load into v8x1a, then v8x1b will be the top row */ v8x1a = vec_sld(ld0, ld0, 0); /* v8x1a = ld0; */ /* }}} */ } else { /* {{{ */ v8x1a = vec_ld(0, pblk); ld0 = vec_ld(16, pblk); /* pblk += rowstride; */ v8x1b = vec_ld(stride1, pblk); ld1 = vec_ld(stride1_16, pblk); /* align8x2_0 = align8x2 */ align8x2_0 = vec_sld(align8x2, align8x2, 0); align8x2_2 = vec_splat_u8(1); align8x2_2 = vec_add(align8x2, align8x2_2 /* (1) */ ); vref8x2 = vec_ld(0, pref); /* pref += rowstride; */ ld3 = vec_ld(stride1, pref); v8x1a = vec_perm(v8x1a, ld0, perm1); v8x1b = vec_perm(v8x1b, ld1, perm1); vref8x2 = vec_perm(vref8x2, ld3, perm2); i = ih; do { /* while (--i) */ /* load next row */ /* pblk += rowstride; */ pblk += stride2; ld0 = vec_ld(0, pblk); ld1 = vec_ld(16, pblk); /* calculate (0,0) */ vblk8x2 = vec_perm(v8x1a, v8x1b, align8x2_0); max = vec_max(vblk8x2, vref8x2); min = vec_min(vblk8x2, vref8x2); dif = vec_sub(max, min); sads = vec_sum4s(dif, sads); /* calculate (2,0) */ vblk8x2 = vec_perm(v8x1a, v8x1b, align8x2_2); max = vec_max(vblk8x2, vref8x2); min = vec_min(vblk8x2, vref8x2); dif = vec_sub(max, min); sad20 = vec_sum4s(dif, sad20); /* load into v8x1a, then v8x1b will be the top row */ v8x1a = vec_perm(ld0, ld1, perm1); /* load next row */ /* pblk += rowstride; */ ld0 = vec_ld(stride1, pblk); ld1 = vec_ld(stride1_16, pblk); /* calculate (0,2) */ vblk8x2 = vec_perm(v8x1b, v8x1a, align8x2_0); max = vec_max(vblk8x2, vref8x2); min = vec_min(vblk8x2, vref8x2); dif = vec_sub(max, min); sad02 = vec_sum4s(dif, sad02); /* calculate (2,2) */ vblk8x2 = vec_perm(v8x1b, v8x1a, align8x2_2); max = vec_max(vblk8x2, vref8x2); min = vec_min(vblk8x2, vref8x2); /* pref += rowstride; */ pref += stride2; vref8x2 = vec_ld(0, pref); /* pref += rowstride; */ ld3 = vec_ld(stride1, pref); dif = vec_sub(max, min); sad22 = vec_sum4s(dif, sad22); v8x1b = vec_perm(ld0, ld1, perm1); vref8x2 = vec_perm(vref8x2, ld3, perm2); } while (--i); /* load next row */ /* pblk += rowstride; */ pblk += stride2; ld0 = vec_ld(0, pblk); ld1 = vec_ld(16, pblk); /* calculate (0,0) */ vblk8x2 = vec_perm(v8x1a, v8x1b, align8x2_0); max = vec_max(vblk8x2, vref8x2); min = vec_min(vblk8x2, vref8x2); dif = vec_sub(max, min); sads = vec_sum4s(dif, sads); /* calculate (2,0) */ vblk8x2 = vec_perm(v8x1a, v8x1b, align8x2_2); /* load into v8x1a, then v8x1b will be the top row */ v8x1a = vec_perm(ld0, ld1, perm1); /* }}} */ } /* calculate (2,0) */ max = vec_max(vblk8x2, vref8x2); min = vec_min(vblk8x2, vref8x2); dif = vec_sub(max, min); sad20 = vec_sum4s(dif, sad20); /* calculate (0,2) */ vblk8x2 = vec_perm(v8x1b, v8x1a, align8x2_0); max = vec_max(vblk8x2, vref8x2); min = vec_min(vblk8x2, vref8x2); dif = vec_sub(max, min); sad02 = vec_sum4s(dif, sad02); /* calculate (2,2) */ vblk8x2 = vec_perm(v8x1b, v8x1a, align8x2_2); max = vec_max(vblk8x2, vref8x2); min = vec_min(vblk8x2, vref8x2); dif = vec_sub(max, min); sad22 = vec_sum4s(dif, sad22); /* calculate final sums {{{ */ sads = vu32(vec_sums(vs32(sads), vs32(zero))); sad20 = vu32(vec_sums(vs32(sad20), vs32(zero))); sad02 = vu32(vec_sums(vs32(sad02), vs32(zero))); sad22 = vu32(vec_sums(vs32(sad22), vs32(zero))); /* }}} */ /* sads = {sads, sad20, sad02, sad22} {{{ */ sads = vu32(vec_mergel(vu32(sads), vu32(sad02))); sad20 = vu32(vec_mergel(vu32(sad20), vu32(sad22))); sads = vu32(vec_mergel(vu32(sads), vu32(sad20))); /* }}} */ } /* }}} */ #ifdef VERIFY_BUILD_SUB22_MESTS /* {{{ */ if (verify) verify_sads(s22orgblk, s22blk, rowstride, h, (int*)&sads, 4); #endif /* }}} */ /* add penalty, clip xy, arrange into me_result_s ... {{{ */ { vector signed char xy; xy = vec_ld(0, (signed char*) &vio.xy); xy = vs8(vec_splat(vu32(xy), 0)); /* splat vio.xy */ xy = vs8(vec_add(xy, xy22)); /* adjust xy values for elements 1-3 */ /* add distance penalty {{{ */ /* penalty = (max(abs(x),abs(y))<<3) */ { vector signed char xyabs; vector unsigned int xxxx, yyyy; vector unsigned int xymax, penalty; /* (abs(x),abs(y)) */ xyabs = vec_subs(vs8(zero), xy); xyabs = vec_max(xyabs, xy); /* xxxx = (x, x, x, x), yyyy = (y, y, y, y) * (0,0,x,y, 0,0,x,y, 0,0,x,y, 0,0,x,y) |/- permute vector -\| * (0,0,0,x, 0,0,0,x, 0,0,0,x, 0,0,0,x) |lvsl+(0x0000000F,...)| * (0,0,0,y, 0,0,0,y, 0,0,0,y, 0,0,0,y) |lvsl+(0x00000010,...)| */ xxxx = vu32(vec_perm(vs8(zero), xyabs, xint)); yyyy = vu32(vec_perm(vs8(zero), xyabs, yint)); /* penalty = max(abs(x),abs(y)) << 3 */ xymax = vec_max(xxxx, yyyy); penalty = vec_splat_u32(3); penalty = vec_sl(xymax, penalty /* (3,...) */ ); sads = vec_add(sads, penalty); } /* }}} */ /* mask sads x <= (ihigh - i0) && y <= (jhigh - j0) {{{ */ /* the first cmpgt (s8) will flag any x and/or y coordinates... {{{ * as out of bounds. the second cmpgt (u32) will complete the * mask if the x or y flag for that result is set. * * Example: {{{ * X Y X Y X Y X Y * [0 0 < <] [0 0 < <] [0 0 > <] [0 0 < >] * vb8(xymask) = vec_cmpgt(vu8(xy), xylim) * [0 0 0 0] [0 0 0 0] [0 0 1 0] [0 0 0 1] * vb32(xymask) = vec_cmpgt(vu32(xymask), vu32(zero)) * [0 0 0 0] [0 0 0 0] [1 1 1 1] [1 1 1 1] * * Legend: 0=0x00 (<)=(xy[n] <= xymax[n]) * 1=0xff (>)=(xy[n] > xymax[n]) * }}} */ /* }}} */ { vector bool int xymask; xymask = vb32(vec_cmpgt(xy, xylim)); xymask = vec_cmpgt(vu32(xymask), zero); /* add (saturated) xymask to sads thereby forcing * masked values above the threshold. */ sads = vec_adds(sads, vu32(xymask)); } /* }}} */ /* arrange sad and xy into me_result_s form and store {{{ */ { vector unsigned int mests; /* mests = ( sad, xy, sad, xy, sad, xy, sad, xy ) {{{ * * ( 0, sad, 0, sad, 0, sad, 0, sad ) * ( sad, sad, sad, sad, sad, sad, sad, sad ) * * ( 0, xy, 0, xy, 0, xy, 0, xy ) * ( xy, xy, xy, xy, xy, xy, xy, xy ) * * ( sad, xy, sad, xy, sad, xy, sad, xy ) */ /* }}} */ xy = vs8(vec_pack(vu32(xy), vu32(xy))); mests = vu32(vec_pack(vu32(sads), vu32(sads))); mests = vu32(vec_mergeh(vu16(mests), vu16(xy))); vec_st(mests, 0, (unsigned int*)&vio.mests); } /* }}} */ } /* }}} */ if (vec_any_lt(sads, vthreshold)) { me_result_s m0, m1, m2, m3; unsigned int w0, w1, w2, w3; m0 = vio.mests[0]; m1 = vio.mests[1]; m2 = vio.mests[2]; m3 = vio.mests[3]; w0 = m0.weight; w1 = m1.weight; w2 = m2.weight; w3 = m3.weight; if (w0 < threshold) *(++cres) = m0; if (w1 < threshold) *(++cres) = m1; if (w2 < threshold) *(++cres) = m2; if (w3 < threshold) *(++cres) = m3; } } while (--len); cres++; /* increment to account for earlier decrement */ len = cres - sub22set->mests; sub22set->len = len; AMBER_STOP; #ifdef USE_SMR_PPC if ((len | reduction) > 0) len = sub_mean_reduction_ppc(len, sub22set, reduction); return len; #else #if ALTIVEC_TEST_FUNCTION(sub_mean_reduction) ALTIVEC_TEST_SUFFIX(sub_mean_reduction)(sub22set, reduction, &min_weight); #else sub_mean_reduction_altivec(sub22set, reduction, &min_weight); #endif return sub22set->len; #endif } #if ALTIVEC_TEST_FUNCTION(build_sub22_mests) /* {{{ */ #define BUILD_SUB22_MESTS_PFMT \ "sub44set=0x%X, sub22set=0x%X, i0=%d, j0=%d, ihigh=%d, jhigh=%d, " \ "null_ctl_sad=%d, s22org=0x%X, s22blk=0x%X, rowstride=%d, h=%d, " \ "reduction=%d" # ifdef ALTIVEC_VERIFY int build_sub22_mests_altivec_verify(BUILD_SUB22_MESTS_PDECL) { int i, len1, len2; unsigned long checksum1, checksum2; len1 = _build_sub22_mests_altivec(BUILD_SUB22_MESTS_ARGS, 1 /*verify*/); for (checksum1 = i = 0; i < len1; i++) { checksum1 += sub22set->mests[i].weight; checksum1 += abs(sub22set->mests[i].x); checksum1 += abs(sub22set->mests[i].y); } len2 = ALTIVEC_TEST_WITH(build_sub22_mests)(BUILD_SUB22_MESTS_ARGS); for (checksum2 = i = 0; i < len2; i++) { checksum2 += sub22set->mests[i].weight; checksum2 += abs(sub22set->mests[i].x); checksum2 += abs(sub22set->mests[i].y); } if (len1 != len2 || checksum1 != checksum2) { mjpeg_debug("build_sub22_mests(" BUILD_SUB22_MESTS_PFMT ")", BUILD_SUB22_MESTS_ARGS); mjpeg_debug("build_sub22_mests: sub44set->len=%d", sub44set->len); mjpeg_debug("build_sub22_mests: checksums differ %d[%d] != %d[%d]", checksum1, len1, checksum2, len2); } #if 0 else { mjpeg_info("build_sub22_mests(" BUILD_SUB22_MESTS_PFMT ")", BUILD_SUB22_MESTS_ARGS); mjpeg_info("build_sub22_mests: sub44set->len=%d", sub44set->len); mjpeg_info("build_sub22_mests: checksum %d[%d]", checksum1, len1); } #endif return len2; } static void verify_sads(uint8_t *blk1, uint8_t *blk2, int stride, int h, int *sads, int count) { int i, s, s2; uint8_t *pblk; pblk = blk1; for (i = 0; i < count; i++) { s2 = sads[i]; /* s = sad_sub22(pblk, blk2, stride, h); {{{ */ #if ALTIVEC_TEST_FUNCTION(sad_sub22) s = ALTIVEC_TEST_WITH(sad_sub22)(pblk, blk2, stride, h); #else s = sad_sub22(pblk, blk2, stride, h); #endif /* }}} */ if (s2 != s) { mjpeg_debug("build_sub22_mests: sads[%d]=%d != %d" "=sad_sub22(blk1=0x%X(0x%X), blk2=0x%X, " "stride=%d, h=%d)", i, s2, s, pblk, blk1, blk2, stride, h); } if (i == 1) pblk += stride - 1; else pblk += 1; } } # else #undef BENCHMARK_EPILOG #define BENCHMARK_EPILOG \ mjpeg_info("build_sub22_mests: sub44set->len=%d", sub44set->len); \ mjpeg_info("build_sub22_mests: sub22set->len=%d", sub22set->len); ALTIVEC_TEST(build_sub22_mests, int, (BUILD_SUB22_MESTS_PDECL), BUILD_SUB22_MESTS_PFMT, BUILD_SUB22_MESTS_ARGS); # endif #endif /* }}} */ /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/verify.h0000644000175000017500000000307607565610177020501 0ustar glowwormglowworm/* verify.h, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define ALTIVEC_TEST_VERIFY(name,ret,defargs,pfmt,args) \ ret name##_altivec_verify defargs { \ ret correct, verify; \ correct = ALTIVEC_TEST_WITH(name)(args); \ verify = name##_altivec(args); \ if (verify != correct) \ mjpeg_debug(AVFMT(ret) " != " AVFMT(ret) "=" #name "(" pfmt ")", \ verify, correct, args); \ return correct; \ } mjpegtools-2.1.0/utils/altivec/sumsq_sub22.c0000644000175000017500000001262110464771010021333 0ustar glowwormglowworm/* sumsq_sub22.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_motion.h" #include "vectorize.h" #include "../mjpeg_logging.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif /* * Total squared difference between bidriection prediction of (8*h) * blocks of 2*2 subsampled pels. * * Iterate through all rows 2 at a time. * * Hints regarding input: * b) blk2 is about 50% vector aligned and 50% 8 byte aligned * c) rowstride is always a multiple of 16 * d) h == 4 or 8 * * for (j = 0; j < h; j++) { * for (i = 0; i < 8; i++) { * d = p1[i] - p2[i]; * sum += d * d; * } * p1 += rowstride; * p2 += rowstride; * } */ #define SUMSQ_SUB22_PDECL \ uint8_t *blk1, \ uint8_t *blk2, \ int rowstride, \ int h \ #define SUMSQ_SUB22_ARGS blk1, blk2, rowstride, h int sumsq_sub22_altivec(SUMSQ_SUB22_PDECL) { int i; unsigned char *pB, *pR; vector unsigned char align8x2; vector unsigned char lB0, lB1, lB2, lB3, lR0, lR1; vector unsigned char B, R; vector unsigned char min; vector unsigned char max; vector unsigned char dif; vector unsigned int sum; vector signed int zero; vector unsigned char perm1, perm2; union { vector signed int v; struct { signed int pad[3]; signed int sum; } s; } vo; #ifdef ALTIVEC_VERIFY if (NOT_VECTOR_ALIGNED(rowstride)) mjpeg_error_exit1("sumsq_sub22: rowstride %% 16 != 0, (%d)", rowstride); if (((unsigned long)blk2 % 8) != 0) mjpeg_error_exit1("sumsq_sub22: blk2 %% 8 != 0, (0x%X)", blk2); #endif if (h != 4 && h != 8) mjpeg_error_exit1("sumsq_sub22: h != [4|8], (%d)", h); /* 8*h blocks calculated in 8*2 chunks */ /* align8x2 = 0x( 00 01 02 03 04 05 06 07 10 11 12 13 14 15 16 17 ) {{{ */ align8x2 = vec_lvsl(0, (unsigned char*)0); align8x2 = vec_sld(align8x2, align8x2, 8); perm1 = vec_lvsr(0, (unsigned char*)0); align8x2 = vec_sld(align8x2, perm1, 8); /* }}} */ pB = blk1; pR = blk2; i = (h >> 1) - 1; zero = vec_splat_s32(0); sum = vec_splat_u32(0); perm1 = vec_lvsl(0, pB); perm2 = vec_lvsl(0, pR); perm2 = vec_splat(perm2, 0); perm2 = vec_add(perm2, align8x2); if (((unsigned long)pB & 0xf) <= 8) { perm1 = vec_splat(perm1, 0); perm1 = vec_add(perm1, align8x2); lB0 = vec_ld(0, pB); pB += rowstride; lB1 = vec_ld(0, pB); lR0 = vec_ld(0, pR); pR += rowstride; lR1 = vec_ld(0, pR); B = vec_perm(lB0, lB1, perm1); R = vec_perm(lR0, lR1, perm2); do { pB += rowstride; lB0 = vec_ld(0, pB); pB += rowstride; lB1 = vec_ld(0, pB); pR += rowstride; lR0 = vec_ld(0, pR); pR += rowstride; lR1 = vec_ld(0, pR); max = vec_max(B, R); min = vec_min(B, R); dif = vec_sub(max, min); sum = vec_msum(dif, dif, sum); B = vec_perm(lB0, lB1, perm1); R = vec_perm(lR0, lR1, perm2); } while (--i); } else { lB0 = vec_ld(0, pB); lB1 = vec_ld(16, pB); pB += rowstride; lB2 = vec_ld(0, pB); lB3 = vec_ld(16, pB); lR0 = vec_ld(0, pR); pR += rowstride; lR1 = vec_ld(0, pR); lB0 = vec_perm(lB0, lB1, perm1); lB2 = vec_perm(lB2, lB3, perm1); B = vec_perm(lB0, lB2, align8x2); R = vec_perm(lR0, lR1, perm2); do { pB += rowstride; lB0 = vec_ld(0, pB); lB1 = vec_ld(16, pB); pB += rowstride; lB2 = vec_ld(0, pB); lB3 = vec_ld(16, pB); pR += rowstride; lR0 = vec_ld(0, pR); pR += rowstride; lR1 = vec_ld(0, pR); max = vec_max(B, R); min = vec_min(B, R); dif = vec_sub(max, min); sum = vec_msum(dif, dif, sum); lB0 = vec_perm(lB0, lB1, perm1); lB2 = vec_perm(lB2, lB3, perm1); B = vec_perm(lB0, lB2, align8x2); R = vec_perm(lR0, lR1, perm2); } while (--i); } max = vec_max(B, R); min = vec_min(B, R); dif = vec_sub(max, min); sum = vec_msum(dif, dif, sum); vo.v = vec_sums(vs32(sum), zero); AMBER_STOP; return vo.s.sum; } #if ALTIVEC_TEST_FUNCTION(sumsq_sub22) ALTIVEC_TEST(sumsq_sub22, int, (SUMSQ_SUB22_PDECL), "blk1=0x%X, blk2=0x%X, rowstride=%d, h=%d", SUMSQ_SUB22_ARGS); #endif /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/sumsq.c0000644000175000017500000005234110462765417020335 0ustar glowwormglowworm/* sumsq.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_motion.h" #include "vectorize.h" #include "../mjpeg_logging.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif /* * Input requirements: * b) blk2 is always vector aligned * c) rowstride is a multiple of 16 * d) h is either 8 or 16 */ #define SUMSQ_PDECL \ uint8_t *blk1, \ uint8_t *blk2, \ int rowstride, \ int hx, \ int hy, \ int h \ #define SUMSQ_ARGS blk1, blk2, rowstride, hx, hy, h /* * for (j = 0; j < h; j++) { * for (i = 0; i < 16; i++) { * d = blk[i] - ref[i]; * sum += d * d; * } * } */ static int sumsq_00(SUMSQ_PDECL) /* {{{ */ { int i; unsigned char *pblk1, *pblk2; vector unsigned char blk1A, blk2A, blk1B, blk2B; vector unsigned char blk1A0, blk1B0; vector unsigned char blk1A1, blk1B1; vector unsigned char minA, minB; vector unsigned char maxA, maxB; vector unsigned char difA, difB; vector unsigned int sum; vector signed int zero; vector unsigned char perm; union { vector signed int v; struct { signed int pad[3]; signed int sum; } s; } vo; pblk1 = blk1; pblk2 = blk2; i = (h >> 1) - 1; zero = vec_splat_s32(0); sum = vec_splat_u32(0); if (VECTOR_ALIGNED(pblk1)) { blk1A = vec_ld(0, pblk1); pblk1 += rowstride; blk1B = vec_ld(0, pblk1); blk2A = vec_ld(0, pblk2); pblk2 += rowstride; blk2B = vec_ld(0, pblk2); do { maxA = vec_max(blk1A, blk2A); minA = vec_min(blk1A, blk2A); pblk1 += rowstride; blk1A = vec_ld(0, pblk1); pblk2 += rowstride; blk2A = vec_ld(0, pblk2); difA = vec_sub(maxA, minA); sum = vec_msum(difA, difA, sum); maxB = vec_max(blk1B, blk2B); minB = vec_min(blk1B, blk2B); pblk1 += rowstride; blk1B = vec_ld(0, pblk1); pblk2 += rowstride; blk2B = vec_ld(0, pblk2); difB = vec_sub(maxB, minB); sum = vec_msum(difB, difB, sum); } while (--i); } else { perm = vec_lvsl(0, pblk1); blk1A0 = vec_ld(0, pblk1); blk1A1 = vec_ld(16, pblk1); pblk1 += rowstride; blk1B0 = vec_ld(0, pblk1); blk1B1 = vec_ld(16, pblk1); blk2A = vec_ld(0, pblk2); pblk2 += rowstride; blk2B = vec_ld(0, pblk2); do { blk1A = vec_perm(blk1A0, blk1A1, perm); pblk1 += rowstride; blk1A0 = vec_ld(0, pblk1); blk1A1 = vec_ld(16, pblk1); maxA = vec_max(blk1A, blk2A); minA = vec_min(blk1A, blk2A); pblk2 += rowstride; blk2A = vec_ld(0, pblk2); difA = vec_sub(maxA, minA); sum = vec_msum(difA, difA, sum); blk1B = vec_perm(blk1B0, blk1B1, perm); pblk1 += rowstride; blk1B0 = vec_ld(0, pblk1); blk1B1 = vec_ld(16, pblk1); maxB = vec_max(blk1B, blk2B); minB = vec_min(blk1B, blk2B); pblk2 += rowstride; blk2B = vec_ld(0, pblk2); difB = vec_sub(maxB, minB); sum = vec_msum(difB, difB, sum); } while (--i); blk1A = vec_perm(blk1A0, blk1A1, perm); blk1B = vec_perm(blk1B0, blk1B1, perm); } maxA = vec_max(blk1A, blk2A); minA = vec_min(blk1A, blk2A); difA = vec_sub(maxA, minA); sum = vec_msum(difA, difA, sum); maxB = vec_max(blk1B, blk2B); minB = vec_min(blk1B, blk2B); difB = vec_sub(maxB, minB); sum = vec_msum(difB, difB, sum); vo.v = vec_sums(vs32(sum), zero); AMBER_STOP; return vo.s.sum; } /* }}} */ /* * s = rowstride * for (j = 0; j < h; j++) { * for (i = 0; i < 16; i++) { * d = ((int)(p1[i]+p1[i+1]+1)>>1) - p2[i]; * sum += d * d; * } * p1 += s; * p2 += s; * } */ static int sumsq_10(SUMSQ_PDECL) /* {{{ */ { int i; unsigned char *pB, *pR; vector unsigned char l0, l1, l2, l3, lR, lB0, lB1, perm0, perm1; vector unsigned short b0H, b0L, b1H, b1L; vector unsigned short bH, bL; vector unsigned char max, min, dif; vector unsigned int sum; vector unsigned char zero; vector unsigned short one; union { vector signed int v; struct { signed int pad[3]; signed int sum; } s; } vo; #define ISAD() /* {{{ */ \ /* pB[i] + pB[i+1] */ \ bH = vec_add(b0H, b1H); \ bL = vec_add(b0L, b1L); \ \ /* (pB[i]+pB[i+1]) + 1 */ \ bH = vec_add(bH, one); \ bL = vec_add(bL, one); \ \ /* (pB[i]+pB[i+1]+1) >> 1 */ \ bH = vec_sra(bH, one); \ bL = vec_sra(bL, one); \ \ /* d = abs( ((pB[i]+pB[i+1]+1)>>1) - pR[i] ) */ \ bH = vu16(vec_packsu(bH, bL)); \ min = vec_min(vu8(bH), lR); \ max = vec_max(vu8(bH), lR); \ dif = vec_sub(max, min); \ \ /* sum += d * d */ \ sum = vec_msum(dif, dif, sum); \ /* }}} */ pB = blk1, pR = blk2; l0 = vec_ld(0, pB); l1 = vec_ld(16, pB); pB += rowstride; l2 = vec_ld(0, pB); l3 = vec_ld(16, pB); lR = vec_ld(0, pR); /* initialize constants */ zero = vec_splat_u8(0); one = vec_splat_u16(1); sum = vec_splat_u32(0); perm0 = vec_lvsl(0, pB); perm1 = vec_splat_u8(1); perm1 = vec_add(perm0, perm1); i = (h >> 1) - 1; do { /* while (--i) */ lB0 = vec_perm(l0, l1, perm0); lB1 = vec_perm(l0, l1, perm1); pB += rowstride; l0 = vec_ld(0, pB); l1 = vec_ld(16, pB); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* (unsigned short[]) pB[1-8] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB[9-16] */ b1L = vu16(vec_mergel(zero, lB1)); ISAD(); pR += rowstride; lR = vec_ld(0, pR); lB0 = vec_perm(l2, l3, perm0); lB1 = vec_perm(l2, l3, perm1); pB += rowstride; l2 = vec_ld(0, pB); l3 = vec_ld(16, pB); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* (unsigned short[]) pB[1-8] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB[9-16] */ b1L = vu16(vec_mergel(zero, lB1)); ISAD(); pR += rowstride; lR = vec_ld(0, pR); } while (--i); lB0 = vec_perm(l0, l1, perm0); lB1 = vec_perm(l0, l1, perm1); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* (unsigned short[]) pB[1-8] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB[9-16] */ b1L = vu16(vec_mergel(zero, lB1)); ISAD(); pR += rowstride; lR = vec_ld(0, pR); lB0 = vec_perm(l2, l3, perm0); lB1 = vec_perm(l2, l3, perm1); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* (unsigned short[]) pB[1-8] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB[9-16] */ b1L = vu16(vec_mergel(zero, lB1)); ISAD(); vo.v = vec_sums(vs32(sum), vs32(zero)); return vo.s.sum; #undef ISAD } /* }}} */ /* * s = rowstride * for (j = 0; j < h; j++) { * for (i = 0; i < 16; i++) { * d = ((int)(p1[i]+p1[i+s]+1)>>1) - p2[i]; * sum += d * d; * } * p1 += s; * p2 += s; * } */ static int sumsq_01(SUMSQ_PDECL) /* {{{ */ { int i; unsigned char *pB, *pR; vector unsigned char l0, l1, lR, lB0, lB1, perm; vector unsigned short b0H, b0L, b1H, b1L; vector unsigned short bH, bL; vector unsigned char max, min, dif; vector unsigned int sum; vector unsigned char zero; vector unsigned short one; union { vector signed int v; struct { signed int pad[3]; signed int sum; } s; } vo; #define ISAD() /* {{{ */ \ /* pB[i] + pB[i+s] */ \ bH = vec_add(b0H, b1H); \ bL = vec_add(b0L, b1L); \ \ /* (pB[i]+pB[i+s]) + 1 */ \ bH = vec_add(bH, one); \ bL = vec_add(bL, one); \ \ /* (pB[i]+pB[i+s]+1) >> 1 */ \ bH = vec_sra(bH, one); \ bL = vec_sra(bL, one); \ \ /* d = abs( ((pB[i]+pB[i+s]+1)>>1) - pR[i] ) */ \ bH = vu16(vec_packsu(bH, bL)); \ min = vec_min(vu8(bH), lR); \ max = vec_max(vu8(bH), lR); \ dif = vec_sub(max, min); \ \ /* sum += d * d */ \ sum = vec_msum(dif, dif, sum); \ /* }}} */ pB = blk1, pR = blk2; /* initialize constants */ zero = vec_splat_u8(0); one = vec_splat_u16(1); sum = vec_splat_u32(0); i = (h >> 1) - 1; lB0 = vec_ld(0, pB); if (VECTOR_ALIGNED(pB)) { /* lB0 = vec_ld(0, pB); */ pB += rowstride; lB1 = vec_ld(0, pB); pB += rowstride; l0 = vec_ld(0, pB); lR = vec_ld(0, pR); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* (unsigned short[]) pB+s[0-7] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB+s[8-15] */ b1L = vu16(vec_mergel(zero, lB1)); lB0 = vec_sld(l0, l0, 0); do { /* while (--i) */ pB += rowstride; lB1 = vec_ld(0, pB); ISAD(); /* start loading next lR */ pR += rowstride; lR = vec_ld(0, pR); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); pB += rowstride; lB0 = vec_ld(0, pB); ISAD(); /* start loading next lR */ pR += rowstride; lR = vec_ld(0, pR); /* (unsigned short[]) pB[0-7] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB[8-15] */ b1L = vu16(vec_mergel(zero, lB1)); } while (--i); ISAD(); pR += rowstride; lR = vec_ld(0, pR); } else { perm = vec_lvsl(0, pB); /* lB0 = vec_ld(0, pB); */ l0 = vec_ld(16, pB); pB += rowstride; lB1 = vec_ld(0, pB); l1 = vec_ld(16, pB); lR = vec_ld(0, pR); lB0 = vec_perm(lB0, l0, perm); lB1 = vec_perm(lB1, l1, perm); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* (unsigned short[]) pB+s[0-7] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB+s[8-15] */ b1L = vu16(vec_mergel(zero, lB1)); pB += rowstride; l0 = vec_ld(0, pB); l1 = vec_ld(16, pB); do { /* while (--i) */ ISAD(); lB0 = vec_perm(l0, l1, perm); pB += rowstride; l0 = vec_ld(0, pB); l1 = vec_ld(16, pB); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* start loading next lR */ pR += rowstride; lR = vec_ld(0, pR); ISAD(); lB1 = vec_perm(l0, l1, perm); pB += rowstride; l0 = vec_ld(0, pB); l1 = vec_ld(16, pB); /* (unsigned short[]) pB[0-7] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB[8-15] */ b1L = vu16(vec_mergel(zero, lB1)); /* start loading next lR */ pR += rowstride; lR = vec_ld(0, pR); } while (--i); ISAD(); pR += rowstride; lR = vec_ld(0, pR); lB0 = vec_perm(l0, l1, perm); } /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); ISAD(); vo.v = vec_sums(vs32(sum), vs32(zero)); return vo.s.sum; #undef ISAD } /* }}} */ /* * s = rowstride * for (j = 0; j < h; j++) { * for (i = 0; i < 16; i++) * d = ((int)(pB[i]+pB[i+1]+pB[i+s]+pB[i+s+1]+2)>>2) - pR[i]; * sum += d * d; * pB += s; * pR += s; * } */ static int sumsq_11(SUMSQ_PDECL) /* {{{ */ { int i; unsigned char *pB, *pR; vector unsigned char l0, l1, l2, l3, lR, lB0, lB1, lB2, lB3, perm, perm1; vector unsigned short b0H, b0L, b1H, b1L, b2H, b2L, b3H, b3L; vector unsigned short bH, bL; vector unsigned char zero; vector unsigned short two; vector unsigned char max, min, dif; vector unsigned int sum; union { vector signed int v; struct { signed int pad[3]; signed int sum; } s; } vo; pB = blk1, pR = blk2; /* start loading first blocks */ l0 = vec_ld(0, pB); l1 = vec_ld(16, pB); pB += rowstride; l2 = vec_ld(0, pB); l3 = vec_ld(16, pB); /* initialize constants */ zero = vec_splat_u8(0); two = vec_splat_u16(2); sum = vec_splat_u32(0); perm = vec_lvsl(0, blk1); perm1 = vec_splat_u8(1); perm1 = vec_add(perm, perm1); /* permute 1st set of loaded blocks */ lB0 = vec_perm(l0, l1, perm); lB1 = vec_perm(l0, l1, perm1); /* start loading 3rd set */ pB += rowstride; l0 = vec_ld(0, pB); l1 = vec_ld(16, pB); /* permute 2nd set of loaded blocks */ lB2 = vec_perm(l2, l3, perm); lB3 = vec_perm(l2, l3, perm1); /* start loading lR */ lR = vec_ld(0, pR); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* (unsigned short[]) pB[1-8] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB[9-16] */ b1L = vu16(vec_mergel(zero, lB1)); /* (unsigned short[]) pB+s[0-7] */ b2H = vu16(vec_mergeh(zero, lB2)); /* (unsigned short[]) pB+s[8-15] */ b2L = vu16(vec_mergel(zero, lB2)); /* (unsigned short[]) pB+s[1-8] */ b3H = vu16(vec_mergeh(zero, lB3)); /* (unsigned short[]) pB+s[9-16] */ b3L = vu16(vec_mergel(zero, lB3)); #define ISUMSQ(b0H,b0L,b1H,b1L,b2H,b2L,b3H,b3L) /* {{{ */ \ /* pB[i] + pB[i+1] */ \ bH = vec_add(b0H, b1H); \ bL = vec_add(b0L, b1L); \ \ /* (pB[i]+pB[i+1]) + pB[i+s] */ \ bH = vec_add(bH, b2H); \ bL = vec_add(bL, b2L); \ \ /* (pB[i]+pB[i+1]+pB[i+s]) + pB[i+s+1] */ \ bH = vec_add(bH, b3H); \ bL = vec_add(bL, b3L); \ \ /* (pB[i]+pB[i+1]+pB[i+s]+pB[i+s+1]) + 2 */ \ bH = vec_add(bH, two); \ bL = vec_add(bL, two); \ \ /* (pB[i]+pB[i+1]+pB[i+s]+pB[i+s+1]+2) >> 2 */ \ bH = vec_sra(bH, two); \ bL = vec_sra(bL, two); \ \ /* absolute value is used increase parallelism, x16 instead of x8 */ \ /* d = abs( ((int)(pB[i]+pB[i+1]+pB[i+s]+pB[i+s+1]+2)>>2) - pR[i] ) */ \ bH = vu16(vec_packsu(bH, bL)); \ min = vec_min(vu8(bH), lR); \ max = vec_max(vu8(bH), lR); \ dif = vec_sub(max, min); \ \ /* sum += d * d; */ \ sum = vec_msum(dif, dif, sum); \ /* }}} */ i = (h >> 1) - 1; do { ISUMSQ(b0H,b0L,b1H,b1L,b2H,b2L,b3H,b3L); /* start loading next lR */ pR += rowstride; lR = vec_ld(0, pR); /* perm loaded set */ lB0 = vec_perm(l0, l1, perm); lB1 = vec_perm(l0, l1, perm1); /* start loading next set */ pB += rowstride; l0 = vec_ld(0, pB); l1 = vec_ld(16, pB); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* (unsigned short[]) pB[1-8] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB[9-16] */ b1L = vu16(vec_mergel(zero, lB1)); ISUMSQ(b2H,b2L,b3H,b3L,b0H,b0L,b1H,b1L); /* start loading next lR */ pR += rowstride; lR = vec_ld(0, pR); /* perm loaded set */ lB2 = vec_perm(l0, l1, perm); lB3 = vec_perm(l0, l1, perm1); /* start loading next set */ pB += rowstride; l0 = vec_ld(0, pB); l1 = vec_ld(16, pB); /* (unsigned short[]) pB+s[0-7] */ b2H = vu16(vec_mergeh(zero, lB2)); /* (unsigned short[]) pB+s[8-15] */ b2L = vu16(vec_mergel(zero, lB2)); /* (unsigned short[]) pB+s[1-8] */ b3H = vu16(vec_mergeh(zero, lB3)); /* (unsigned short[]) pB+s[9-16] */ b3L = vu16(vec_mergel(zero, lB3)); } while (--i); ISUMSQ(b0H,b0L,b1H,b1L,b2H,b2L,b3H,b3L); pR += rowstride; lR = vec_ld(0, pR); lB0 = vec_perm(l0, l1, perm); lB1 = vec_perm(l0, l1, perm1); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* (unsigned short[]) pB[1-8] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB[9-16] */ b1L = vu16(vec_mergel(zero, lB1)); ISUMSQ(b2H,b2L,b3H,b3L,b0H,b0L,b1H,b1L); vo.v = vec_sums(vs32(sum), vs32(zero)); return vo.s.sum; #undef ISUMSQ } /* }}} */ int sumsq_altivec(SUMSQ_PDECL) { int sumsq; #ifdef ALTIVEC_VERIFY if (NOT_VECTOR_ALIGNED(blk2)) mjpeg_error_exit1("sumsq: blk2 %% 16 != 0, (%d)", blk2); if (NOT_VECTOR_ALIGNED(rowstride)) mjpeg_error_exit1("sumsq: rowstride %% 16 != 0, (%d)", rowstride); #endif if (h != 8 && h != 16) mjpeg_error_exit1("sumsq: h != [8|16], (%d)", h); AMBER_START; if (hx == 0) { if (hy == 0) sumsq = sumsq_00(SUMSQ_ARGS); else sumsq = sumsq_01(SUMSQ_ARGS); } else { if (hy == 0) sumsq = sumsq_10(SUMSQ_ARGS); else sumsq = sumsq_11(SUMSQ_ARGS); } AMBER_STOP; return sumsq; } #if ALTIVEC_TEST_FUNCTION(sumsq) ALTIVEC_TEST(sumsq, int, (SUMSQ_PDECL), "blk1=0x%x, blk2=0x%x, rowstride=%d, hx=%d, hy=%d, h=%d", SUMSQ_ARGS); #endif /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/bsumsq.c0000644000175000017500000003564410464771010020472 0ustar glowwormglowworm/* bsumsq.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_motion.h" #include "vectorize.h" #include "../mjpeg_logging.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif /* * squared error between a (16*h) block and a bidirectional * prediction * * p2: address of top left pel of block * pf,hxf,hyf: address and half pel flags of forward ref. block * pb,hxb,hyb: address and half pel flags of backward ref. block * h: height of block * rowstride: distance (in bytes) of vertically adjacent pels in p2,pf,pb * * * Input hints: * a) values for h[xy][fb] are 0 and 1 * b) h is 8 or 16 * * { * d = ((((pf[i]+pfa[i]+pfb[i]+pfc[i]+2)>>2)+ * ((pb[i]+pba[i]+pbb[i]+pbc[i]+2)>>2)+1)>>1) - p2[i]; * sum += d * d; * } */ #define BSUMSQ_PDECL \ uint8_t *pf, \ uint8_t *pb, \ uint8_t *p2, \ int rowstride, \ int hxf, \ int hyf, \ int hxb, \ int hyb, \ int h \ #define BSUMSQ_ARGS pf, pb, p2, rowstride, hxf, hyf, hxb, hyb, h int bsumsq_altivec(BSUMSQ_PDECL) { int i; uint8_t *pfy, *pby; vector unsigned char l0, l1, lR; vector unsigned char permF0, permF1, permB0, permB1; vector unsigned char vf, vfa, vfb, vfc; vector unsigned char vb, vba, vbb, vbc; vector unsigned short tH, tL, fH, fL, bH, bL; vector unsigned char zero; vector unsigned short one, two; vector unsigned char max, min, dif; vector unsigned int sum; union { vector signed int v; struct { signed int pad[3]; signed int sum; } s; } vo; #ifdef ALTIVEC_VERIFY if (NOT_VECTOR_ALIGNED(p2)) mjpeg_error_exit1("bsumsq: p2 %% 16 != 0, (0x%X)", p2); if (NOT_VECTOR_ALIGNED(rowstride)) mjpeg_error_exit1("bsumsq: rowstride %% 16 != 0, (%d)", rowstride); if (hxf != 0 && hxf != 1) mjpeg_error_exit1("bsumsq: hxf != [0|1], (hxf=%d)", hxf); if (hyf != 0 && hyf != 1) mjpeg_error_exit1("bsumsq: hyf != [0|1], (hyf=%d)", hyf); if (hxb != 0 && hxb != 1) mjpeg_error_exit1("bsumsq: hxb != [0|1], (hxb=%d)", hxb); if (hyb != 0 && hyb != 1) mjpeg_error_exit1("bsumsq: hyb != [0|1], (hyb=%d)", hyb); #endif if (h != 8 && h != 16) mjpeg_error_exit1("bsumsq: h != [8|16], (%d)", h); AMBER_START; /* start loading first set */ vfb = vec_ld(0, pf); /* use vfb & vfc as temp for vf & vfa */ vfc = vec_ld(16, pf); pfy = pf + (rowstride * hyf); l0 = vec_ld(0, pfy); l1 = vec_ld(16, pfy); pby = pb + (rowstride * hyb); zero = vec_splat_u8(0); one = vec_splat_u16(1); two = vec_splat_u16(2); sum = vec_splat_u32(0); permF0 = vec_lvsl(0, pf); permF1 = vec_lvsl(hxf, (unsigned char*)0); permF1 = vec_splat(permF1, 0); permF1 = vec_add(permF0, permF1); permB0 = vec_lvsl(0, pb); permB1 = vec_lvsl(hxb, (unsigned char*)0); permB1 = vec_splat(permB1, 0); permB1 = vec_add(permB0, permB1); i = h - 1; do { /* while (--i) */ vf = vec_perm(vfb, vfc, permF0); vfa = vec_perm(vfb, vfc, permF1); vfb = vec_perm(l0, l1, permF0); vfc = vec_perm(l0, l1, permF1); vbb = vec_ld(0, pb); /* use vbb & vbc as temp for vb & vba */ vbc = vec_ld(16, pb); l0 = vec_ld(0, pby); l1 = vec_ld(16, pby); pb += rowstride; pby += rowstride; /* (unsigned short[]) pf[0-7] */ fH = vu16(vec_mergeh(zero, vf)); /* (unsigned short[]) pf[8-15] */ fL = vu16(vec_mergel(zero, vf)); /* (unsigned short[]) pfa[0-7] */ tH = vu16(vec_mergeh(zero, vfa)); /* (unsigned short[]) pfa[8-15] */ tL = vu16(vec_mergel(zero, vfa)); /* pf[i] + pfa[i] */ fH = vec_add(fH, tH); fL = vec_add(fL, tL); /* (unsigned short[]) pfb[0-7] */ tH = vu16(vec_mergeh(zero, vfb)); /* (unsigned short[]) pfb[8-15] */ tL = vu16(vec_mergel(zero, vfb)); /* (pf[i]+pfa[i]) + pfb[i] */ fH = vec_add(fH, tH); fL = vec_add(fL, tL); /* (unsigned short[]) pfc[0-7] */ tH = vu16(vec_mergeh(zero, vfc)); /* (unsigned short[]) pfc[8-15] */ tL = vu16(vec_mergel(zero, vfc)); /* (pf[i]+pfa[i]+pfb[i]) + pfc[i] */ fH = vec_add(fH, tH); fL = vec_add(fL, tL); /* (pf[i]+pfa[i]+pfb[i]+pfc[i]) + 2 */ fH = vec_add(fH, two); fL = vec_add(fL, two); /* (pf[i]+pfa[i]+pfb[i]+pfc[i]+2) >> 2 */ fH = vec_sra(fH, two); fL = vec_sra(fL, two); lR = vec_ld(0, p2); p2 += rowstride; vb = vec_perm(vbb, vbc, permB0); vba = vec_perm(vbb, vbc, permB1); vbb = vec_perm(l0, l1, permB0); vbc = vec_perm(l0, l1, permB1); pf += rowstride; vfb = vec_ld(0, pf); /* use vfb & vfc as temp for vf & vfa */ vfc = vec_ld(16, pf); pfy += rowstride; l0 = vec_ld(0, pfy); l1 = vec_ld(16, pfy); /* (unsigned short[]) pb[0-7] */ bH = vu16(vec_mergeh(zero, vb)); /* (unsigned short[]) pb[8-15] */ bL = vu16(vec_mergel(zero, vb)); /* (unsigned short[]) pba[0-7] */ tH = vu16(vec_mergeh(zero, vba)); /* (unsigned short[]) pba[8-15] */ tL = vu16(vec_mergel(zero, vba)); /* pb[i] + pba[i] */ bH = vec_add(bH, tH); bL = vec_add(bL, tL); /* (unsigned short[]) pbb[0-7] */ tH = vu16(vec_mergeh(zero, vbb)); /* (unsigned short[]) pbb[8-15] */ tL = vu16(vec_mergel(zero, vbb)); /* (pb[i]+pba[i]) + pbb[i] */ bH = vec_add(bH, tH); bL = vec_add(bL, tL); /* (unsigned short[]) pbc[0-7] */ tH = vu16(vec_mergeh(zero, vbc)); /* (unsigned short[]) pbc[8-15] */ tL = vu16(vec_mergel(zero, vbc)); /* (pb[i]+pba[i]+pbb[i]) + pbc[i] */ bH = vec_add(bH, tH); bL = vec_add(bL, tL); /* (pb[i]+pba[i]+pbb[i]+pbc[i]) + 2 */ bH = vec_add(bH, two); bL = vec_add(bL, two); /* (pb[i]+pba[i]+pbb[i]+pbc[i]+2) >> 2 */ bH = vec_sra(bH, two); bL = vec_sra(bL, two); /* ((pf[i]+pfa[i]+pfb[i]+pfc[i]+2)>>2) + * ((pb[i]+pba[i]+pbb[i]+pbc[i]+2)>>2) */ tH = vec_add(fH, bH); tL = vec_add(fL, bL); /* (((pf[i]+pfa[i]+pfb[i]+pfc[i]+2)>>2)+ * ((pb[i]+pba[i]+pbb[i]+pbc[i]+2)>>2)) + 1 */ tH = vec_add(tH, one); tL = vec_add(tL, one); /* (((pf[i]+pfa[i]+pfb[i]+pfc[i]+2)>>2)+ * ((pb[i]+pba[i]+pbb[i]+pbc[i]+2)>>2)+1) >> 1 */ tH = vec_sra(tH, one); tL = vec_sra(tL, one); /* absolute value increases parallelism (x16 instead of x8) * since a bit isn't lost on the sign. * * d = abs( ((((pf[i]+pfa[i]+pfb[i]+pfc[i]+2)>>2)+ * ((pb[i]+pba[i]+pbb[i]+pbc[i]+2)>>2)+1)>>1) - p2[i] ) */ tH = vu16(vec_packsu(tH, tL)); min = vec_min(vu8(tH), lR); max = vec_max(vu8(tH), lR); dif = vec_sub(max, min); /* sum += (d * d) */ sum = vec_msum(dif, dif, sum); } while (--i); vf = vec_perm(vfb, vfc, permF0); vfa = vec_perm(vfb, vfc, permF1); vfb = vec_perm(l0, l1, permF0); vfc = vec_perm(l0, l1, permF1); vbb = vec_ld(0, pb); /* use vbb & vbc as temp for vb & vba */ vbc = vec_ld(16, pb); l0 = vec_ld(0, pby); l1 = vec_ld(16, pby); /* (unsigned short[]) pf[0-7] */ fH = vu16(vec_mergeh(zero, vf)); /* (unsigned short[]) pf[8-15] */ fL = vu16(vec_mergel(zero, vf)); /* (unsigned short[]) pfa[0-7] */ tH = vu16(vec_mergeh(zero, vfa)); /* (unsigned short[]) pfa[8-15] */ tL = vu16(vec_mergel(zero, vfa)); /* pf[i] + pfa[i] */ fH = vec_add(fH, tH); fL = vec_add(fL, tL); /* (unsigned short[]) pfb[0-7] */ tH = vu16(vec_mergeh(zero, vfb)); /* (unsigned short[]) pfb[8-15] */ tL = vu16(vec_mergel(zero, vfb)); /* (pf[i]+pfa[i]) + pfb[i] */ fH = vec_add(fH, tH); fL = vec_add(fL, tL); /* (unsigned short[]) pfc[0-7] */ tH = vu16(vec_mergeh(zero, vfc)); /* (unsigned short[]) pfc[8-15] */ tL = vu16(vec_mergel(zero, vfc)); /* (pf[i]+pfa[i]+pfb[i]) + pfc[i] */ fH = vec_add(fH, tH); fL = vec_add(fL, tL); /* (pf[i]+pfa[i]+pfb[i]+pfc[i]) + 2 */ fH = vec_add(fH, two); fL = vec_add(fL, two); /* (pf[i]+pfa[i]+pfb[i]+pfc[i]+2) >> 2 */ fH = vec_sra(fH, two); fL = vec_sra(fL, two); lR = vec_ld(0, p2); vb = vec_perm(vbb, vbc, permB0); vba = vec_perm(vbb, vbc, permB1); vbb = vec_perm(l0, l1, permB0); vbc = vec_perm(l0, l1, permB1); /* (unsigned short[]) pb[0-7] */ bH = vu16(vec_mergeh(zero, vb)); /* (unsigned short[]) pb[8-15] */ bL = vu16(vec_mergel(zero, vb)); /* (unsigned short[]) pba[0-7] */ tH = vu16(vec_mergeh(zero, vba)); /* (unsigned short[]) pba[8-15] */ tL = vu16(vec_mergel(zero, vba)); /* pb[i] + pba[i] */ bH = vec_add(bH, tH); bL = vec_add(bL, tL); /* (unsigned short[]) pbb[0-7] */ tH = vu16(vec_mergeh(zero, vbb)); /* (unsigned short[]) pbb[8-15] */ tL = vu16(vec_mergel(zero, vbb)); /* (pb[i]+pba[i]) + pbb[i] */ bH = vec_add(bH, tH); bL = vec_add(bL, tL); /* (unsigned short[]) pbc[0-7] */ tH = vu16(vec_mergeh(zero, vbc)); /* (unsigned short[]) pbc[8-15] */ tL = vu16(vec_mergel(zero, vbc)); /* (pb[i]+pba[i]+pbb[i]) + pbc[i] */ bH = vec_add(bH, tH); bL = vec_add(bL, tL); /* (pb[i]+pba[i]+pbb[i]+pbc[i]) + 2 */ bH = vec_add(bH, two); bL = vec_add(bL, two); /* (pb[i]+pba[i]+pbb[i]+pbc[i]+2) >> 2 */ bH = vec_sra(bH, two); bL = vec_sra(bL, two); /* ((pf[i]+pfa[i]+pfb[i]+pfc[i]+2)>>2) + * ((pb[i]+pba[i]+pbb[i]+pbc[i]+2)>>2) */ tH = vec_add(fH, bH); tL = vec_add(fL, bL); /* (((pf[i]+pfa[i]+pfb[i]+pfc[i]+2)>>2)+ * ((pb[i]+pba[i]+pbb[i]+pbc[i]+2)>>2)) + 1 */ tH = vec_add(tH, one); tL = vec_add(tL, one); /* (((pf[i]+pfa[i]+pfb[i]+pfc[i]+2)>>2)+ * ((pb[i]+pba[i]+pbb[i]+pbc[i]+2)>>2)+1) >> 1 */ tH = vec_sra(tH, one); tL = vec_sra(tL, one); /* absolute value increases parallelism (x16 instead of x8) * since a bit isn't lost on the sign. * * d = abs( ((((pf[i]+pfa[i]+pfb[i]+pfc[i]+2)>>2)+ * ((pb[i]+pba[i]+pbb[i]+pbc[i]+2)>>2)+1)>>1) - p2[i] ) */ tH = vu16(vec_packsu(tH, tL)); min = vec_min(vu8(tH), lR); max = vec_max(vu8(tH), lR); dif = vec_sub(max, min); /* sum += (d * d) */ sum = vec_msum(dif, dif, sum); /* sum all parts of difference into one 32 bit quantity */ vo.v = vec_sums(vs32(sum), vs32(zero)); AMBER_STOP; return vo.s.sum; } #if ALTIVEC_TEST_FUNCTION(bsumsq) #undef BENCHMARK_FREQUENCY #define BENCHMARK_FREQUENCY 1000 /* benchmark every (n) calls */ ALTIVEC_TEST(bsumsq, int, (BSUMSQ_PDECL), "pf=0x%X, pb=0x%X, p2=0x%X, rowstride=%d, " "hxf=%d, hyf=%d, hxb=%d, hyb=%d, h=%d", BSUMSQ_ARGS); #endif /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/bsumsq_sub22.c0000644000175000017500000002543010464771010021477 0ustar glowwormglowworm/* bsumsq_sub22.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_motion.h" #include "vectorize.h" #include "../mjpeg_logging.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif /* * Total squared difference between bidirection prediction of (8*h) * blocks of 2*2 subsampled pels. * * Iterate through all rows 2 at a time. * * Hints regarding input: * b) ref is about 50% vector aligned and 50% 8 byte aligned * c) rowstride is always a multiple of 16 * d) h == 4 or 8 * * * for (j = 0; j < h; j++) { * for (i = 0; i < 8; i++) { * d = ((p1f[i]+p1b[i]+1)>>1) - p2[i]; * sum += d * d; * } * p1f += rowstride; * p1b += rowstride; * p2 += rowstride; * } */ #define BSUMSQ_SUB22_PDECL \ uint8_t *blk1f, \ uint8_t *blk1b, \ uint8_t *blk2, \ int rowstride, \ int h \ #define BSUMSQ_SUB22_ARGS blk1f, blk1b, blk2, rowstride, h int bsumsq_sub22_altivec(BSUMSQ_SUB22_PDECL) { int i; int lt8B, lt8F; unsigned char *pB, *pF, *pR; vector unsigned char align8x2; vector unsigned char permB, permF, permR; vector unsigned char lB0, lB1, lB2, lB3; vector unsigned char lF0, lF1, lF2, lF3; vector unsigned char lR0, lR1; vector unsigned char B, F, R; vector unsigned short bH, bL, fH, fL; vector unsigned char min; vector unsigned char max; vector unsigned char dif; vector unsigned int sum; vector unsigned char zero; vector unsigned short one; union { vector signed int v; struct { signed int pad[3]; signed int sum; } s; } vo; #ifdef ALTIVEC_VERIFY if (NOT_VECTOR_ALIGNED(rowstride)) mjpeg_error_exit1("bsumsq_sub22: rowstride %% 16 != 0, (%d)", rowstride); if (((unsigned long)blk2 % 8) != 0) mjpeg_error_exit1("bsumsq_sub22: blk2 %% 8 != 0, (0x%X)", blk2); #endif if (h != 4 && h != 8) mjpeg_error_exit1("bsumsq_sub22: h != [4|8], (%d)", h); /* 8*h blocks calculated in 8*2 chunks */ /* align8x2 = 0x( 00 01 02 03 04 05 06 07 10 11 12 13 14 15 16 17 ) {{{ */ align8x2 = vec_lvsl(0, (unsigned char*)0); align8x2 = vec_sld(align8x2, align8x2, 8); permB = vec_lvsr(0, (unsigned char*)0); align8x2 = vec_sld(align8x2, permB, 8); /* }}} */ i = (h >> 1) - 1; zero = vec_splat_u8(0); one = vec_splat_u16(1); sum = vec_splat_u32(0); pR = blk2; permR = vec_lvsl(0, pR); permR = vec_splat(permR, 0); permR = vec_add(permR, align8x2); lt8B = (((unsigned long)blk1b & 0xf) <= 8); lt8F = (((unsigned long)blk1f & 0xf) <= 8); if (lt8B && lt8F) { pB = blk1b; pF = blk1f; permB = vec_lvsl(0, pB); permB = vec_splat(permB, 0); permB = vec_add(permB, align8x2); permF = vec_lvsl(0, pF); permF = vec_splat(permF, 0); permF = vec_add(permF, align8x2); lB0 = vec_ld(0, pB); pB += rowstride; lB1 = vec_ld(0, pB); lF0 = vec_ld(0, pF); pF += rowstride; lF1 = vec_ld(0, pF); lR0 = vec_ld(0, pR); pR += rowstride; lR1 = vec_ld(0, pR); B = vec_perm(lB0, lB1, permB); F = vec_perm(lF0, lF1, permF); R = vec_perm(lR0, lR1, permR); do { pB += rowstride; lB0 = vec_ld(0, pB); pB += rowstride; lB1 = vec_ld(0, pB); pF += rowstride; lF0 = vec_ld(0, pF); pF += rowstride; lF1 = vec_ld(0, pF); pR += rowstride; lR0 = vec_ld(0, pR); pR += rowstride; lR1 = vec_ld(0, pR); /* (unsigned short[]) pB[0-7] */ bH = vu16(vec_mergeh(zero, B)); /* (unsigned short[]) pF[0-7] */ fH = vu16(vec_mergeh(zero, F)); /* pB[i] + pF[i] */ bH = vec_add(bH, fH); /* (unsigned short[]) pB[8-15] */ bL = vu16(vec_mergel(zero, B)); /* (unsigned short[]) pF[8-15] */ fL = vu16(vec_mergel(zero, F)); /* pB[i] + pF[i] */ bL = vec_add(bL, fL); /* (pB[i]+pF[i]) + 1 */ bH = vec_add(bH, one); bL = vec_add(bL, one); /* (pB[i]+pF[i]+1) >> 1 */ bH = vec_sra(bH, one); bL = vec_sra(bL, one); /* d = abs( ((pB[i]+pF[i]+1)>>1) - pR[i] ) */ bH = vu16(vec_packsu(bH, bL)); min = vec_min(vu8(bH), R); max = vec_max(vu8(bH), R); dif = vec_sub(max, min); /* sum += (d * d) */ sum = vec_msum(dif, dif, sum); B = vec_perm(lB0, lB1, permB); F = vec_perm(lF0, lF1, permF); R = vec_perm(lR0, lR1, permR); } while (--i); } else if (lt8B || lt8F) { if (lt8F) { pB = blk1b; pF = blk1f; } else { pB = blk1f; pF = blk1b; } permB = vec_lvsl(0, pB); permF = vec_lvsl(0, pF); permF = vec_splat(permF, 0); permF = vec_add(permF, align8x2); lB0 = vec_ld(0, pB); lB1 = vec_ld(16, pB); pB += rowstride; lB2 = vec_ld(0, pB); lB3 = vec_ld(16, pB); lF0 = vec_ld(0, pF); pF += rowstride; lF1 = vec_ld(0, pF); lR0 = vec_ld(0, pR); pR += rowstride; lR1 = vec_ld(0, pR); lB0 = vec_perm(lB0, lB1, permB); lB2 = vec_perm(lB2, lB3, permB); B = vec_perm(lB0, lB2, align8x2); F = vec_perm(lF0, lF1, permF); R = vec_perm(lR0, lR1, permR); do { pB += rowstride; lB0 = vec_ld(0, pB); lB1 = vec_ld(16, pB); pB += rowstride; lB2 = vec_ld(0, pB); lB3 = vec_ld(16, pB); pF += rowstride; lF0 = vec_ld(0, pF); pF += rowstride; lF1 = vec_ld(0, pF); pR += rowstride; lR0 = vec_ld(0, pR); pR += rowstride; lR1 = vec_ld(0, pR); /* (unsigned short[]) pB[0-7] */ bH = vu16(vec_mergeh(zero, B)); /* (unsigned short[]) pF[0-7] */ fH = vu16(vec_mergeh(zero, F)); /* pB[i] + pF[i] */ bH = vec_add(bH, fH); /* (unsigned short[]) pB[8-15] */ bL = vu16(vec_mergel(zero, B)); /* (unsigned short[]) pF[8-15] */ fL = vu16(vec_mergel(zero, F)); /* pB[i] + pF[i] */ bL = vec_add(bL, fL); /* (pB[i]+pF[i]) + 1 */ bH = vec_add(bH, one); bL = vec_add(bL, one); /* (pB[i]+pF[i]+1) >> 1 */ bH = vec_sra(bH, one); bL = vec_sra(bL, one); /* d = abs( ((pB[i]+pF[i]+1)>>1) - pR[i] ) */ bH = vu16(vec_packsu(bH, bL)); min = vec_min(vu8(bH), R); max = vec_max(vu8(bH), R); dif = vec_sub(max, min); /* sum += (d * d) */ sum = vec_msum(dif, dif, sum); lB0 = vec_perm(lB0, lB1, permB); lB2 = vec_perm(lB2, lB3, permB); B = vec_perm(lB0, lB2, align8x2); F = vec_perm(lF0, lF1, permF); R = vec_perm(lR0, lR1, permR); } while (--i); } else { pB = blk1b; pF = blk1f; permB = vec_lvsl(0, pB); permF = vec_lvsl(0, pF); lB0 = vec_ld(0, pB); lB1 = vec_ld(16, pB); pB += rowstride; lB2 = vec_ld(0, pB); lB3 = vec_ld(16, pB); lF0 = vec_ld(0, pF); lF1 = vec_ld(16, pF); pF += rowstride; lF2 = vec_ld(0, pF); lF3 = vec_ld(16, pF); lR0 = vec_ld(0, pR); pR += rowstride; lR1 = vec_ld(0, pR); lB0 = vec_perm(lB0, lB1, permB); lB2 = vec_perm(lB2, lB3, permB); B = vec_perm(lB0, lB2, align8x2); lF0 = vec_perm(lF0, lF1, permF); lF2 = vec_perm(lF2, lF3, permF); F = vec_perm(lF0, lF2, align8x2); R = vec_perm(lR0, lR1, permR); do { pB += rowstride; lB0 = vec_ld(0, pB); lB1 = vec_ld(16, pB); pB += rowstride; lB2 = vec_ld(0, pB); lB3 = vec_ld(16, pB); pF += rowstride; lF0 = vec_ld(0, pF); lF1 = vec_ld(16, pF); pF += rowstride; lF2 = vec_ld(0, pF); lF3 = vec_ld(16, pF); pR += rowstride; lR0 = vec_ld(0, pR); pR += rowstride; lR1 = vec_ld(0, pR); /* (unsigned short[]) pB[0-7] */ bH = vu16(vec_mergeh(zero, B)); /* (unsigned short[]) pF[0-7] */ fH = vu16(vec_mergeh(zero, F)); /* pB[i] + pF[i] */ bH = vec_add(bH, fH); /* (unsigned short[]) pB[8-15] */ bL = vu16(vec_mergel(zero, B)); /* (unsigned short[]) pF[8-15] */ fL = vu16(vec_mergel(zero, F)); /* pB[i] + pF[i] */ bL = vec_add(bL, fL); /* (pB[i]+pF[i]) + 1 */ bH = vec_add(bH, one); bL = vec_add(bL, one); /* (pB[i]+pF[i]+1) >> 1 */ bH = vec_sra(bH, one); bL = vec_sra(bL, one); /* d = abs( ((pB[i]+pF[i]+1)>>1) - pR[i] ) */ bH = vu16(vec_packsu(bH, bL)); min = vec_min(vu8(bH), R); max = vec_max(vu8(bH), R); dif = vec_sub(max, min); /* sum += (d * d) */ sum = vec_msum(dif, dif, sum); lB0 = vec_perm(lB0, lB1, permB); lB2 = vec_perm(lB2, lB3, permB); B = vec_perm(lB0, lB2, align8x2); lF0 = vec_perm(lF0, lF1, permF); lF2 = vec_perm(lF2, lF3, permF); F = vec_perm(lF0, lF2, align8x2); R = vec_perm(lR0, lR1, permR); } while (--i); } /* (unsigned short[]) pB[0-7] */ bH = vu16(vec_mergeh(zero, B)); /* (unsigned short[]) pF[0-7] */ fH = vu16(vec_mergeh(zero, F)); /* pB[i] + pF[i] */ bH = vec_add(bH, fH); /* (unsigned short[]) pB[8-15] */ bL = vu16(vec_mergel(zero, B)); /* (unsigned short[]) pF[8-15] */ fL = vu16(vec_mergel(zero, F)); /* pB[i] + pF[i] */ bL = vec_add(bL, fL); /* (pB[i]+pF[i]) + 1 */ bH = vec_add(bH, one); bL = vec_add(bL, one); /* (pB[i]+pF[i]+1) >> 1 */ bH = vec_sra(bH, one); bL = vec_sra(bL, one); /* d = abs( ((pB[i]+pF[i]+1)>>1) - pR[i] ) */ bH = vu16(vec_packsu(bH, bL)); min = vec_min(vu8(bH), R); max = vec_max(vu8(bH), R); dif = vec_sub(max, min); /* sum += d * d */ sum = vec_msum(dif, dif, sum); vo.v = vec_sums(vs32(sum), vs32(zero)); AMBER_STOP; return vo.s.sum; } #if ALTIVEC_TEST_FUNCTION(bsumsq_sub22) ALTIVEC_TEST(bsumsq_sub22, int, (BSUMSQ_SUB22_PDECL), "blk1f=0x%X, blk1b=0x%X, blk2=0x%X, rowstride=%d, h=%d", BSUMSQ_SUB22_ARGS); #endif /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/subsample_image.c0000644000175000017500000003115110464771010022302 0ustar glowwormglowworm/* subsample_image.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_motion.h" #if defined(ALTIVEC_VERIFY) && ALTIVEC_TEST_FUNCTION(subsample_image) #include #endif #include "vectorize.h" #include "../mjpeg_logging.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif #define SUBSAMPLE_IMAGE_PDECL /* {{{ */ \ uint8_t *image, int rowstride, \ uint8_t *sub22_image, \ uint8_t *sub44_image \ /* }}} */ #define SUBSAMPLE_IMAGE_ARGS image, rowstride, sub22_image, sub44_image #define SUBSAMPLE_IMAGE_PFMT /* {{{ */ \ "image=0x%X, rowstride=%d, sub22_image=0x%X, sub44_image=0x%X" \ /* }}} */ void subsample_image_altivec(SUBSAMPLE_IMAGE_PDECL) { int i, ii, j, stride1, stride2, stride3, stride4, halfstride; unsigned char *pB, *pB2, *pB4; vector unsigned char l0, l1, l2, l3; vector unsigned short s0, s1, s2, s3; vector unsigned short s22_0, s22_1, s22_2, s22_3; vector unsigned short s44, s44_0, s44_1; vector unsigned short zero, two; #ifdef ALTIVEC_DST DataStreamControl dsc; #endif #ifdef ALTIVEC_VERIFY if (NOT_VECTOR_ALIGNED(image)) mjpeg_error_exit1("subsample_image: %s %% %d != 0, (%d)", "image", 16, image); if (NOT_VECTOR_ALIGNED(sub22_image)) mjpeg_error_exit1("subsample_image: %s %% %d != 0, (%d)", "sub22_image", 16, sub22_image); if (NOT_VECTOR_ALIGNED(sub44_image)) mjpeg_error_exit1("subsample_image: %s %% %d != 0, (%d)", "sub44_image", 16, sub44_image); if ((rowstride & 63) != 0) mjpeg_error_exit1("subsample_image: %s %% %d != 0, (%d)", "rowstride", 64, rowstride); #endif AMBER_START; pB = image; #ifdef ALTIVEC_DST dsc.control = DATA_STREAM_CONTROL(6,4,0); dsc.block.stride = rowstride; vec_dst(pB, dsc.control, 0); #endif pB2 = sub22_image; pB4 = sub44_image; j = ((unsigned long)(pB2 - pB) / rowstride) >> 2; /* height/4 */ stride1 = rowstride; stride2 = stride1 + stride1; stride3 = stride2 + stride1; stride4 = stride2 + stride2; halfstride = stride1 >> 1; /* /2 */ ii = rowstride >> 6; /* rowstride/16/4 */ zero = vec_splat_u16(0); two = vec_splat_u16(2); do { i = ii; do { l0 = vec_ld(0, pB); l1 = vec_ld(stride1, pB); l2 = vec_ld(stride2, pB); l3 = vec_ld(stride3, pB); pB += 16; #ifdef ALTIVEC_DST vec_dst(pB + (16 * 3), dsc.control, 0); #endif /* l0 = 0x[00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F] */ /* l1 = 0x[10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F] */ /* l2 = 0x[20,21,22,23,24,25,26,27,28,29,2A,2B,2C,2D,2E,2F] */ /* l3 = 0x[30,31,32,33,34,35,36,37,38,39,3A,3B,3C,3D,3E,3F] */ /* s0 = 0x[00,01, 02,03, 04,05, 06,07, ] */ /* [ 10,11, 12,13, 14,15, 16,17] */ s0 = vu16(vec_mergeh(vu16(l0), vu16(l1))); /* s0 = 0x[00+01+10+11,02+03+12+13,04+05+14+15,06+07+16+17] */ s0 = vu16(vec_sum4s(vu8(s0), vu32(zero))); /* s1 = 0x[08,09, 0A,0B, 0C,0D, 0E,0F, ] */ /* [ 18,19, 1A,1B, 1C,1D, 1E,1F] */ s1 = vu16(vec_mergel(vu16(l0), vu16(l1))); /* s1 = 0x[08+09+18+19,0A+0B+1A+1B,0C+0D+1C+1D,0E+0F+1E+1F] */ s1 = vu16(vec_sum4s(vu8(s1), vu32(zero))); /* s2 = 0x[20,21, 22,23, 24,25, 26,27, ] */ /* [ 30,31, 32,33, 34,35, 36,37] */ s2 = vu16(vec_mergeh(vu16(l2), vu16(l3))); /* s2 = 0x[20+21+30+31,22+23+32+33,24+25+34+35,26+27+36+37] */ s2 = vu16(vec_sum4s(vu8(s2), vu32(zero))); /* s3 = 0x[28,29, 2A,2B, 2C,2D, 2E,2F, ] */ /* [ 38,39, 3A,3B, 3C,3D, 3E,3F] */ s3 = vu16(vec_mergel(vu16(l2), vu16(l3))); /* s3 = 0x[28+29+38+39,2A+2B+3A+3B,2C+2D+3C+3D,2E+2F+3E+3F] */ s3 = vu16(vec_sum4s(vu8(s3), vu32(zero))); /* start loading next block */ l0 = vec_ld(0, pB); l1 = vec_ld(stride1, pB); l2 = vec_ld(stride2, pB); l3 = vec_ld(stride3, pB); pB += 16; /* s0 = 0x[00+01+10+11, 02+03+12+13, 04+05+14+15, 06+07+16+17] */ /* s1 = 0x[08+09+18+19, 0A+0B+1A+1B, 0C+0D+1C+1D, 0E+0F+1E+1F] */ /* s2 = 0x[20+21+30+31, 22+23+32+33, 24+25+34+35, 26+27+36+37] */ /* s3 = 0x[28+29+38+39, 2A+2B+3A+3B, 2C+2D+3C+3D, 2E+2F+3E+3F] */ /* s22_0 = 0x[ 00, 02, 04, 06, 08, 0A, 0C, 0E] */ s22_0 = vec_packsu(vu32(s0), vu32(s1)); /* s22_1 = 0x[ 20, 22, 24, 26, 28, 2A, 2C, 2E] */ s22_1 = vec_packsu(vu32(s2), vu32(s3)); /* (pB[i]+pB[i+1]+pN[i]+pN[i+1]) + 2 */ s22_0 = vec_add(s22_0, two); /* (pNN[i]+pNN[i+1]+pNNN[i]+pNNN[i+1]) + 2 */ s22_1 = vec_add(s22_1, two); /* (pB[i]+pB[i+1]+pN[i]+pN[i+1]+2) >> 2 */ s22_0 = vec_sra(s22_0, two); /* (pNN[i]+pNN[i+1]+pNNN[i]+pNNN[i+1]+2) >> 2 */ s22_1 = vec_sra(s22_1, two); /* s22_0 = 0x[ 00, 02, 04, 06, 08, 0A, 0C, 0E] */ /* s22_1 = 0x[ 20, 22, 24, 26, 28, 2A, 2C, 2E] */ /* s44_0 = 0x[00+20,02+22,04+24,06+26,08+28,0A+2A,0C+2C,0E+2E] */ s44_0 = vec_add(s22_0, s22_1); /* s44_0 = 0x[00+20+02+22, 04+24+06+26, 08+28+0A+2A, 0C+2C+0E+2E] */ s44_0 = vu16(vec_sum4s(vs16(s44_0), vs32(zero))); /* - - - - - - - - - - - - - - - - - - - */ s0 = vu16(vec_mergeh(vu16(l0), vu16(l1))); s0 = vu16(vec_sum4s(vu8(s0), vu32(zero))); s1 = vu16(vec_mergel(vu16(l0), vu16(l1))); s1 = vu16(vec_sum4s(vu8(s1), vu32(zero))); s2 = vu16(vec_mergeh(vu16(l2), vu16(l3))); s2 = vu16(vec_sum4s(vu8(s2), vu32(zero))); s3 = vu16(vec_mergel(vu16(l2), vu16(l3))); s3 = vu16(vec_sum4s(vu8(s3), vu32(zero))); /* start loading next l[0-3] */ l0 = vec_ld(0, pB); l1 = vec_ld(stride1, pB); l2 = vec_ld(stride2, pB); l3 = vec_ld(stride3, pB); pB += 16; s22_2 = vec_packsu(vu32(s0), vu32(s1)); s22_3 = vec_packsu(vu32(s2), vu32(s3)); s22_2 = vec_add(s22_2, two); s22_3 = vec_add(s22_3, two); s22_2 = vec_sra(s22_2, two); s22_3 = vec_sra(s22_3, two); s44_1 = vec_add(s22_2, s22_3); s44_1 = vu16(vec_sum4s(vs16(s44_1), vs32(zero))); /* store s22 block */ s22_0 = vu16(vec_packsu(s22_0, s22_2)); s22_1 = vu16(vec_packsu(s22_1, s22_3)); vec_st(vu8(s22_0), 0, pB2); vec_st(vu8(s22_1), halfstride, pB2); pB2 += 16; /* - - - - - - - - - - - - - - - - - - - */ s0 = vu16(vec_mergeh(vu16(l0), vu16(l1))); s0 = vu16(vec_sum4s(vu8(s0), vu32(zero))); s1 = vu16(vec_mergel(vu16(l0), vu16(l1))); s1 = vu16(vec_sum4s(vu8(s1), vu32(zero))); s2 = vu16(vec_mergeh(vu16(l2), vu16(l3))); s2 = vu16(vec_sum4s(vu8(s2), vu32(zero))); s3 = vu16(vec_mergel(vu16(l2), vu16(l3))); s3 = vu16(vec_sum4s(vu8(s3), vu32(zero))); /* starting loading next l[0-3] */ l0 = vec_ld(0, pB); l1 = vec_ld(stride1, pB); l2 = vec_ld(stride2, pB); l3 = vec_ld(stride3, pB); pB += 16; s22_0 = vec_packsu(vu32(s0), vu32(s1)); s22_1 = vec_packsu(vu32(s2), vu32(s3)); s22_0 = vec_add(s22_0, two); s22_1 = vec_add(s22_1, two); s22_0 = vec_sra(s22_0, two); s22_1 = vec_sra(s22_1, two); s44 = vec_packsu(vu32(s44_0), vu32(s44_1)); s44 = vec_add(s44, two); s44 = vec_sra(s44, two); s44_0 = vec_add(s22_0, s22_1); s44_0 = vu16(vec_sum4s(vs16(s44_0), vs32(zero))); /* - - - - - - - - - - - - - - - - - - - */ s0 = vu16(vec_mergeh(vu16(l0), vu16(l1))); s0 = vu16(vec_sum4s(vu8(s0), vu32(zero))); s1 = vu16(vec_mergel(vu16(l0), vu16(l1))); s1 = vu16(vec_sum4s(vu8(s1), vu32(zero))); s2 = vu16(vec_mergeh(vu16(l2), vu16(l3))); s2 = vu16(vec_sum4s(vu8(s2), vu32(zero))); s3 = vu16(vec_mergel(vu16(l2), vu16(l3))); s3 = vu16(vec_sum4s(vu8(s3), vu32(zero))); s22_2 = vec_packsu(vu32(s0), vu32(s1)); s22_3 = vec_packsu(vu32(s2), vu32(s3)); s22_2 = vec_add(s22_2, two); s22_3 = vec_add(s22_3, two); s22_2 = vec_sra(s22_2, two); s22_3 = vec_sra(s22_3, two); s44_1 = vec_add(s22_2, s22_3); s44_1 = vu16(vec_sum4s(vs16(s44_1), vs32(zero))); /* store s22 block */ s22_0 = vu16(vec_packsu(s22_0, s22_2)); s22_1 = vu16(vec_packsu(s22_1, s22_3)); vec_st(vu8(s22_0), 0, pB2); vec_st(vu8(s22_1), halfstride, pB2); pB2 += 16; /* pack all four s44 chunks */ s44_0 = vec_packsu(vu32(s44_0), vu32(s44_1)); s44_0 = vec_add(s44_0, two); s44_0 = vec_sra(s44_0, two); s44 = vu16(vec_packsu(s44, s44_0)); vec_st(vu8(s44), 0, pB4); pB4 += 16; } while (--i); pB += stride3; pB2 += halfstride; } while (--j); #ifdef ALTIVEC_DST vec_dss(0); #endif AMBER_STOP; } #if ALTIVEC_TEST_FUNCTION(subsample_image) /* {{{ */ # ifdef ALTIVEC_VERIFY static void imgcpy(uint8_t *d, uint8_t *s, int width, int height, int stride) { int i, j; for (j = 0; j < height; j++) { for (i = 0; i < width; i++) d[i] = s[i]; d += width; s += stride; } } static unsigned long checksum(uint8_t *p, int width, int height, int stride) { int i, j; unsigned long checksum; for (checksum = j = 0; j < height; j++) { for (i = 0; i < width; i++) checksum += p[i]; p += stride; } return checksum; } static void imgcmp(const char *ss, uint8_t *a, uint8_t *b, int width, int height, int stride) { int i, j; for (j = 0; j < height; j++) { for (i = 0; i < width; i++) if (a[i] != b[i]) mjpeg_debug("subsample_image: %s[%d][%d] %d != %d", ss, j, i, a[i], b[i]); a += width; b += stride; } } void subsample_image_altivec_verify(SUBSAMPLE_IMAGE_PDECL) { int width, height; unsigned long checksum44_1, checksum44_2; unsigned long checksum22_1, checksum22_2; unsigned char *cpy22, *cpy44; width = rowstride; height = (unsigned long)(sub22_image - image) / rowstride; cpy22 = (unsigned char*)malloc((width/2) * (height/2)); cpy44 = (unsigned char*)malloc((width/4) * (height/4)); if (cpy22 == NULL || cpy44 == NULL) mjpeg_error_exit1("subsample_image: malloc failed"); subsample_image_altivec(SUBSAMPLE_IMAGE_ARGS); checksum22_1 = checksum(sub22_image, width/2, height/2, rowstride/2); checksum44_1 = checksum(sub44_image, width/4, height/4, rowstride/4); /* copy data for imgcmp */ imgcpy(cpy22, sub22_image, width/2, height/2, rowstride/2); imgcpy(cpy44, sub44_image, width/4, height/4, rowstride/4); ALTIVEC_TEST_WITH(subsample_image)(SUBSAMPLE_IMAGE_ARGS); checksum22_2 = checksum(sub22_image, width/2, height/2, rowstride/2); checksum44_2 = checksum(sub44_image, width/4, height/4, rowstride/4); if (checksum22_1 != checksum22_2 || checksum44_1 != checksum44_2) { mjpeg_debug("subsample_image(" SUBSAMPLE_IMAGE_PFMT ")", SUBSAMPLE_IMAGE_ARGS); if (checksum22_1 != checksum22_2) mjpeg_debug("subsample_image: %s checksums differ %d != %d", "2*2", checksum22_1, checksum22_2); if (checksum44_1 != checksum44_2) mjpeg_debug("subsample_image: %s checksums differ %d != %d", "4*4", checksum44_1, checksum44_2); imgcmp("2*2", cpy22, sub22_image, width/2, height/2, rowstride/2); imgcmp("4*4", cpy44, sub44_image, width/4, height/4, rowstride/4); } free(cpy22); free(cpy44); } # else #undef BENCHMARK_ITERATIONS #define BENCHMARK_ITERATIONS 1000 #undef BENCHMARK_FREQUENCY 1 #define BENCHMARK_FREQUENCY 1 ALTIVEC_TEST(subsample_image, void, (SUBSAMPLE_IMAGE_PDECL), SUBSAMPLE_IMAGE_PFMT, SUBSAMPLE_IMAGE_ARGS); # endif #endif /* }}} */ /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/quant_weight_coeff_sum.c0000644000175000017500000001253607746062336023715 0ustar glowwormglowworm/* quant_weight_coeff_sum.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_quantize.h" #include "vectorize.h" #include "../mjpeg_logging.h" #include "../../mpeg2enc/quantize_precomp.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif #define QUANT_WEIGHT_COEFF_INTRA_PDECL \ struct QuantizerWorkSpace *wsp, int16_t *blk #define QUANT_WEIGHT_COEFF_INTRA_ARGS wsp, blk #define QUANT_WEIGHT_COEFF_INTRA_PFMT "wsp=0x%X, blk=0x%X" #define QUANT_WEIGHT_COEFF_INTER_PDECL \ struct QuantizerWorkSpace *wsp, int16_t *blk #define QUANT_WEIGHT_COEFF_INTER_ARGS wsp, blk #define QUANT_WEIGHT_COEFF_INTER_PFMT "wsp=0x%X, blk=0x%X" static int quant_weight_coeff_sum_altivec(uint16_t *i_quant_mat, int16_t *blk) { int16_t *pb; uint16_t *pq; vector signed short zero; vector signed short vA, vB; vector signed short nA, nB; vector signed short absA, absB; vector unsigned short qA, qB; vector signed int sum; union { vector signed int v; struct { signed int pad[3]; signed int sum; } s; } vo; #ifdef ALTIVEC_VERIFY /* {{{ */ if (NOT_VECTOR_ALIGNED(i_quant_mat)) mjpeg_error_exit1("quant_weight_coeff_sum: i_quant_mat %% 16 != 0, (%d)", i_quant_mat); if (NOT_VECTOR_ALIGNED(blk)) mjpeg_error_exit1("quant_weight_coeff_sum: blk %% 16 != 0, (%d)", blk); #endif /* }}} */ AMBER_START; pb = blk; pq = i_quant_mat; #ifdef ALTIVEC_DST vec_dst(pb, 0x01080010, 0); /* vec_dst complete size of blk */ vec_dst(pq, 0x01080010, 1); /* vec_dst complete size of i_quant_mat */ #endif zero = vec_splat_s16(0); sum = vec_splat_s32(0); #define PREPARE_FIRST_ITERATION /* {{{ */ \ vA = vec_ld(0, pb); \ qA = vec_ld(0, pq); \ pb += 8; vB = vec_ld(0, pb); \ pq += 8; qB = vec_ld(0, pq); \ /* }}} */ #define PERFORM_ITERATION(iteration) /* i = iteration {{{ */ \ nA = vec_subs(zero, vA); \ nB = vec_subs(zero, vB); \ absA = vec_max(nA, vA); \ absB = vec_max(nB, vB); \ sum = vec_msum(absA, vs16(qA), sum); \ sum = vec_msum(absB, vs16(qB), sum); \ /* }}} */ #define PREPARE_ITERATION /* {{{ */ \ pb += 8; vA = vec_ld(0, pb); \ pq += 8; qA = vec_ld(0, pq); \ pb += 8; vB = vec_ld(0, pb); \ pq += 8; qB = vec_ld(0, pq); \ /* }}} */ #if 1 PREPARE_FIRST_ITERATION; PERFORM_ITERATION(0); PREPARE_ITERATION; PERFORM_ITERATION(1); PREPARE_ITERATION; PERFORM_ITERATION(2); PREPARE_ITERATION; PERFORM_ITERATION(3); #else int i; for (i = 0; i < 64/8/2; i++) { vA = vec_ld(0, pb); pb += 8; vB = vec_ld(0, pb); pb += 8; qA = vec_ld(0, pq); pq += 8; qB = vec_ld(0, pq); pq += 8; nA = vec_subs(zero, vA); nB = vec_subs(zero, vB); absA = vec_max(nA, vA); absB = vec_max(nB, vB); sum = vec_msum(absA, vs16(qA), sum); sum = vec_msum(absB, vs16(qB), sum); } #endif #ifdef ALTIVEC_DST vec_dssall(); #endif vo.v = vec_sums(vs32(sum), vs32(zero)); AMBER_STOP; return vo.s.sum; } int quant_weight_coeff_intra_altivec(QUANT_WEIGHT_COEFF_INTRA_PDECL) { return quant_weight_coeff_sum_altivec(wsp->i_intra_q_mat, blk); } int quant_weight_coeff_inter_altivec(QUANT_WEIGHT_COEFF_INTER_PDECL) { return quant_weight_coeff_sum_altivec(wsp->i_inter_q_mat, blk); } #if ALTIVEC_TEST_FUNCTION(quant_weight_coeff_intra) ALTIVEC_TEST(quant_weight_coeff_intra, int, (QUANT_WEIGHT_COEFF_INTRA_PDECL), QUANT_WEIGHT_COEFF_INTRA_PFMT, QUANT_WEIGHT_COEFF_INTRA_ARGS); #endif #if ALTIVEC_TEST_FUNCTION(quant_weight_coeff_inter) ALTIVEC_TEST(quant_weight_coeff_inter, int, (QUANT_WEIGHT_COEFF_INTER_PDECL), QUANT_WEIGHT_COEFF_INTER_PFMT, QUANT_WEIGHT_COEFF_INTER_ARGS); #endif /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/iquant_intra.c0000644000175000017500000003277310254174615021663 0ustar glowwormglowworm/* iquant_intra.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_quantize.h" #if defined(ALTIVEC_VERIFY) && ALTIVEC_TEST_FUNCTION(iquant_intra_m1) # include # include #endif #include "vectorize.h" #include "../mjpeg_logging.h" #include "../../mpeg2enc/quantize_precomp.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif #define IQUANT_INTRA_PDECL struct QuantizerWorkSpace *wsp, \ int16_t *src, int16_t *dst, int dc_prec, int mquant #define IQUANT_INTRA_ARGS wsp, src, dst, dc_prec, mquant #define IQUANT_INTRA_PFMT "wsp=0x%X, src=0x%X, dst=0x%X, dc_prec=%d, mquant=%d" void iquant_intra_m1_altivec(IQUANT_INTRA_PDECL) { int i; vector signed short vsrc; uint16_t *qmat; vector unsigned short vqmat; vector unsigned short vmquant; vector bool short eqzero, ltzero; vector signed short val, t0; vector signed short zero, one; vector unsigned int four; vector signed short min, max; int offset, offset2; int16_t dst0; union { vector unsigned short vu16; unsigned short mquant; vector signed int vs32; struct { signed int pad[3]; signed int sum; } s; } vu; #ifdef ALTIVEC_DST DataStreamControl dsc; #endif #ifdef ALTIVEC_VERIFY /* {{{ */ if (NOT_VECTOR_ALIGNED(wsp->intra_q_mat)) mjpeg_error_exit1("iquant_intra_m1: wsp->intra_q_mat %% 16 != 0, (%d)", wsp->intra_q_mat); if (NOT_VECTOR_ALIGNED(src)) mjpeg_error_exit1("iquant_intra_m1: src %% 16 != 0, (%d)", src); if (NOT_VECTOR_ALIGNED(dst)) mjpeg_error_exit1("iquant_intra_m1: dst %% 16 != 0, (%d)", dst); for (i = 0; i < 64; i++) if (src[i] < -256 || src[i] > 255) mjpeg_error_exit1("iquant_intra_m2: -256 > src[%i] > 255, (%d)", i, src[i]); #endif /* }}} */ AMBER_START; dst0 = src[0] << (3 - dc_prec); qmat = (uint16_t*)wsp->intra_q_mat; #ifdef ALTIVEC_DST dsc.control = DATA_STREAM_CONTROL(64/8,1,0); vec_dst(src, dsc.control, 0); vec_dst(qmat, dsc.control, 1); #endif /* vmquant = (vector unsigned short)(mquant); */ vu.mquant = (unsigned short)mquant; vmquant = vec_splat(vu.vu16, 0); zero = vec_splat_s16(0); one = vec_splat_s16(1); four = vec_splat_u32(4); /* max = (2047); min = (-2048); {{{ */ max = vs16(vec_splat_u8(0x7)); t0 = vec_splat_s16(-1); /* 0xffff */ max = vs16(vec_mergeh(vu8(max), vu8(t0))); /* 0x07ff == 2047 */ min = vec_sub(t0, max); /* }}} */ offset = 0; #if 1 vsrc = vec_ld(offset, (signed short*)src); vqmat = vec_ld(offset, (unsigned short*)qmat); i = (64/8) - 1; do { /* intra_q[i] * mquant */ vqmat = vu16(vec_mulo(vu8(vqmat), vu8(vmquant))); /* save sign */ ltzero = vec_cmplt(vsrc, zero); eqzero = vec_cmpeq(vsrc, zero); /* val = abs(src) */ t0 = vec_sub(zero, vsrc); val = vec_max(t0, vsrc); /* val = (src * quant) >> 4 */ t0 = vs16(vec_mule(val, vs16(vqmat))); val = vs16(vec_mulo(val, vs16(vqmat))); t0 = vs16(vec_sra(vs32(t0), four)); t0 = vs16(vec_pack(vs32(t0), vs32(t0))); val = vs16(vec_sra(vs32(val), four)); val = vs16(vec_pack(vs32(val), vs32(val))); val = vec_mergeh(vs16(t0), vs16(val)); offset2 = offset; offset += 8*sizeof(int16_t); vsrc = vec_ld(offset, (signed short*)src); vqmat = vec_ld(offset, (unsigned short*)qmat); /* val = val - 1&~(val|val==0) */ t0 = vec_or(val, eqzero); t0 = vec_andc(one, t0); val = vec_sub(val, t0); /* restore sign */ t0 = vec_sub(zero, val); val = vec_sel(val, t0, ltzero); /* val = (val > 2047) ? ((val < -2048) ? -2048 : val); */ val = vec_min(val, max); val = vec_max(val, min); vec_st(val, offset2, dst); } while (--i); /* intra_q[i] * mquant */ vqmat = vu16(vec_mulo(vu8(vqmat), vu8(vmquant))); /* save sign */ ltzero = vec_cmplt(vsrc, zero); eqzero = vec_cmpeq(vsrc, zero); /* val = abs(src) */ t0 = vec_sub(zero, vsrc); val = vec_max(t0, vsrc); /* val = (src * quant) >> 4 */ t0 = vs16(vec_mule(val, vs16(vqmat))); val = vs16(vec_mulo(val, vs16(vqmat))); t0 = vs16(vec_sra(vs32(t0), four)); t0 = vs16(vec_pack(vs32(t0), vs32(t0))); val = vs16(vec_sra(vs32(val), four)); val = vs16(vec_pack(vs32(val), vs32(val))); val = vec_mergeh(vs16(t0), vs16(val)); /* val = val - 1&~(val|val==0) */ t0 = vec_or(val, eqzero); t0 = vec_andc(one, t0); val = vec_sub(val, t0); /* restore sign */ t0 = vec_sub(zero, val); val = vec_sel(val, t0, ltzero); /* val = (val > 2047) ? ((val < -2048) ? -2048 : val); */ val = vec_min(val, max); val = vec_max(val, min); vec_st(val, offset, dst); #else /* {{{ */ i = (64/8); do { vsrc = vec_ld(offset, (signed short*)src); vqmat = vec_ld(offset, (unsigned short*)qmat); /* intra_q[i] * mquant */ vu16(vqmat) = vec_mulo(vu8(vqmat), vu8(vmquant)); /* save sign */ ltzero = vec_cmplt(vsrc, zero); eqzero = vec_cmpeq(vsrc, zero); /* val = abs(src) */ t0 = vec_sub(zero, vsrc); val = vec_max(t0, vsrc); /* val = (src * quant) >> 4 */ vs32(t0) = vec_mule(val, vs16(vqmat)); vs32(val) = vec_mulo(val, vs16(vqmat)); vs32(t0) = vec_sra(vs32(t0), four); vs16(t0) = vec_pack(vs32(t0), vs32(t0)); vs32(val) = vec_sra(vs32(val), four); vs16(val) = vec_pack(vs32(val), vs32(val)); val = vec_mergeh(vs16(t0), vs16(val)); /* val = val - 1&~(val|val==0) */ t0 = vec_or(val, eqzero); t0 = vec_andc(one, t0); val = vec_sub(val, t0); /* restore sign */ t0 = vec_sub(zero, val); val = vec_sel(val, t0, ltzero); /* val = (val > 2047) ? ((val < -2048) ? -2048 : val); */ val = vec_min(val, max); val = vec_max(val, min); vec_st(val, offset, dst); offset += 8*sizeof(int16_t); } while (--i); /* }}} */ #endif dst[0] = dst0; AMBER_STOP; } void iquant_intra_m2_altivec(IQUANT_INTRA_PDECL) { int i; vector signed short vsrc; uint16_t *qmat; vector unsigned short vqmat; vector unsigned short vmquant; vector bool short ltzero; vector signed short val, t0; vector signed short zero; vector unsigned int four; vector signed short min, max; vector signed int vsum; int sum; int offset, offset2; int16_t dst0; union { vector unsigned short vu16; unsigned short mquant; vector signed int vs32; struct { signed int pad[3]; signed int sum; } s; } vu; #ifdef ALTIVEC_DST DataStreamControl dsc; #endif #ifdef ALTIVEC_VERIFY /* {{{ */ if (NOT_VECTOR_ALIGNED(wsp->intra_q_mat)) mjpeg_error_exit1("iquant_intra_m2: wsp->intra_q_mat %% 16 != 0, (%d)", wsp->intra_q_mat); if (NOT_VECTOR_ALIGNED(src)) mjpeg_error_exit1("iquant_intra_m2: src %% 16 != 0, (%d)", src); if (NOT_VECTOR_ALIGNED(dst)) mjpeg_error_exit1("iquant_intra_m2: dst %% 16 != 0, (%d)", dst); for (i = 0; i < 64; i++) if (src[i] < -256 || src[i] > 255) mjpeg_error_exit1("iquant_intra_m2: -256 > src[%i] > 255, (%d)", i, src[i]); #endif /* }}} */ AMBER_START; dst0 = src[0] << (3 - dc_prec); qmat = (uint16_t*)wsp->intra_q_mat; #ifdef ALTIVEC_DST dsc.control = DATA_STREAM_CONTROL(64/8,1,0); vec_dst(src, dsc.control, 0); vec_dst(qmat, dsc.control, 1); #endif /* vmquant = (vector unsigned short)(mquant); */ vu.mquant = (unsigned short)mquant; vmquant = vec_splat(vu.vu16, 0); vsum = vec_splat_s32(0); zero = vec_splat_s16(0); four = vec_splat_u32(4); /* max = (2047); min = (-2048); {{{ */ max = vs16(vec_splat_u8(0x7)); t0 = vec_splat_s16(-1); /* 0xffff */ max = vs16(vec_mergeh(vu8(max), vu8(t0))); /* 0x07ff == 2047 */ min = vec_sub(t0, max); /* }}} */ offset = 0; #if 1 vsrc = vec_ld(offset, (signed short*)src); vqmat = vec_ld(offset, (unsigned short*)qmat); i = (64/8) - 1; do { /* intra_q[i] * mquant */ vqmat = vu16(vec_mulo(vu8(vqmat), vu8(vmquant))); /* save sign */ ltzero = vec_cmplt(vsrc, zero); /* val = abs(src) */ t0 = vec_sub(zero, vsrc); val = vec_max(t0, vsrc); /* val = (src * quant) >> 4 */ t0 = vs16(vec_mule(val, vs16(vqmat))); val = vs16(vec_mulo(val, vs16(vqmat))); t0 = vs16(vec_sra(vs32(t0), four)); t0 = vs16(vec_pack(vs32(t0), vs32(t0))); val = vs16(vec_sra(vs32(val), four)); val = vs16(vec_pack(vs32(val), vs32(val))); val = vec_mergeh(vs16(t0), vs16(val)); offset2 = offset; offset += 8*sizeof(int16_t); vsrc = vec_ld(offset, (signed short*)src); vqmat = vec_ld(offset, (unsigned short*)qmat); /* restore sign */ t0 = vec_sub(zero, val); val = vec_sel(val, t0, ltzero); /* val = (val > 2047) ? ((val < -2048) ? -2048 : val); */ val = vec_min(val, max); val = vec_max(val, min); vsum = vec_sum4s(val, vsum); vec_st(val, offset2, dst); } while (--i); /* intra_q[i] * mquant */ vqmat = vu16(vec_mulo(vu8(vqmat), vu8(vmquant))); /* save sign */ ltzero = vec_cmplt(vsrc, zero); /* val = abs(src) */ t0 = vec_sub(zero, vsrc); val = vec_max(t0, vsrc); /* val = (src * quant) >> 4 */ t0 = vs16(vec_mule(val, vs16(vqmat))); val = vs16(vec_mulo(val, vs16(vqmat))); t0 = vs16(vec_sra(vs32(t0), four)); t0 = vs16(vec_pack(vs32(t0), vs32(t0))); val = vs16(vec_sra(vs32(val), four)); val = vs16(vec_pack(vs32(val), vs32(val))); val = vec_mergeh(vs16(t0), vs16(val)); /* restore sign */ t0 = vec_sub(zero, val); val = vec_sel(val, t0, ltzero); /* val = (val > 2047) ? ((val < -2048) ? -2048 : val); */ val = vec_min(val, max); val = vec_max(val, min); vsum = vec_sum4s(val, vsum); vec_st(val, offset, dst); #else /* {{{ */ i = (64/8); do { vsrc = vec_ld(offset, (signed short*)src); vqmat = vec_ld(offset, (unsigned short*)qmat); /* intra_q[i] * mquant */ vu16(vqmat) = vec_mulo(vu8(vqmat), vu8(vmquant)); /* save sign */ ltzero = vec_cmplt(vsrc, zero); /* val = abs(src) */ t0 = vec_sub(zero, vsrc); val = vec_max(t0, vsrc); /* val = (src * quant) >> 4 */ vs32(t0) = vec_mule(val, vs16(vqmat)); vs32(val) = vec_mulo(val, vs16(vqmat)); vs32(t0) = vec_sra(vs32(t0), four); vs16(t0) = vec_pack(vs32(t0), vs32(t0)); vs32(val) = vec_sra(vs32(val), four); vs16(val) = vec_pack(vs32(val), vs32(val)); val = vec_mergeh(vs16(t0), vs16(val)); /* restore sign */ t0 = vec_sub(zero, val); val = vec_sel(val, t0, ltzero); /* val = (val > 2047) ? ((val < -2048) ? -2048 : val); */ val = vec_min(val, max); val = vec_max(val, min); vsum = vec_sum4s(val, vsum); vec_st(val, offset, dst); offset += 8*sizeof(int16_t); } while (--i); /* }}} */ #endif vu.vs32 = vec_sums(vsum, vs32(zero)); sum = vu.s.sum; sum -= dst[0]; sum += dst0; dst[0] = dst0; /* mismatch control */ #if 1 dst[63] ^= !(sum & 1); #else if ((sum & 1) == 0) dst[63] ^= 1; #endif AMBER_STOP; } /* iquant_intra_altivec_verify {{{ */ #if ALTIVEC_TEST_FUNCTION(iquant_intra_m1) || \ ALTIVEC_TEST_FUNCTION(iquant_intra_m2) static void iquant_intra_altivec_verify(IQUANT_INTRA_PDECL, void (*test)(IQUANT_INTRA_PDECL), void (*verify)(IQUANT_INTRA_PDECL)) { int i; unsigned long checksum1, checksum2; int16_t srccpy[64], dstcpy[64]; uint16_t *qmat; qmat = (uint16_t*) wsp->intra_q_mat; /* in case src == dst */ memcpy(srccpy, src, 64*sizeof(int16_t)); (*test)(IQUANT_INTRA_ARGS); for (checksum1 = i = 0; i < 64; i++) checksum1 += dst[i]; memcpy(dstcpy, dst, 64*sizeof(int16_t)); memcpy(src, srccpy, 64*sizeof(int16_t)); (*verify)(IQUANT_INTRA_ARGS); for (checksum2 = i = 0; i < 64; i++) checksum2 += dst[i]; if (checksum1 != checksum2) { mjpeg_debug("iquant_intra(" IQUANT_INTRA_PFMT ")", IQUANT_INTRA_ARGS); mjpeg_debug("iquant_intra: checksums differ %d != %d", checksum1, checksum2); } for (i = 0; i < 64; i++) { if (dstcpy[i] != dst[i]) { mjpeg_debug("iquant_intra: src[%d]=%d, qmat=%d, " "dst[%d]=%d != %d", i, srccpy[i], qmat[i]*mquant, i, dstcpy[i], dst[i]); } } } #endif /* }}} */ #if ALTIVEC_TEST_FUNCTION(iquant_intra_m1) /* {{{ */ # ifdef ALTIVEC_VERIFY void iquant_intra_m1_altivec_verify(IQUANT_INTRA_PDECL) { iquant_intra_altivec_verify(IQUANT_INTRA_ARGS, iquant_intra_m1_altivec, ALTIVEC_TEST_WITH(iquant_intra_m1)); } # else ALTIVEC_TEST(iquant_intra_m1, void, (IQUANT_INTRA_PDECL), IQUANT_INTRA_PFMT, IQUANT_INTRA_ARGS); # endif #endif /* }}} */ #if ALTIVEC_TEST_FUNCTION(iquant_intra_m2) /* {{{ */ # ifdef ALTIVEC_VERIFY void iquant_intra_m2_altivec_verify(IQUANT_INTRA_PDECL) { iquant_intra_altivec_verify(IQUANT_INTRA_ARGS, iquant_intra_m2_altivec, ALTIVEC_TEST_WITH(iquant_intra_m2)); } # else ALTIVEC_TEST(iquant_intra_m2, void, (IQUANT_INTRA_PDECL), IQUANT_INTRA_PFMT, IQUANT_INTRA_ARGS); # endif #endif /* }}} */ /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/fdct.c0000644000175000017500000004555510246212264020101 0ustar glowwormglowworm/* fdct.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2003 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_conf.h" #include "vectorize.h" #include "../mjpeg_logging.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif #define C1 0.98078525066375732421875000 /* cos(1*PI/16) */ #define C2 0.92387950420379638671875000 /* cos(2*PI/16) */ #define C3 0.83146959543228149414062500 /* cos(3*PI/16) */ #define C4 0.70710676908493041992187500 /* cos(4*PI/16) */ #define C5 0.55557024478912353515625000 /* cos(5*PI/16) */ #define C6 0.38268342614173889160156250 /* cos(6*PI/16) */ #define C7 0.19509032368659973144531250 /* cos(7*PI/16) */ #define SQRT_2 1.41421353816986083984375000 /* sqrt(2) */ #define W0 -(2 * C2) #define W1 (2 * C6) #define W2 (SQRT_2 * C6) #define W3 (SQRT_2 * C3) #define W4 (SQRT_2 * (-C1 + C3 + C5 - C7)) #define W5 (SQRT_2 * ( C1 + C3 - C5 + C7)) #define W6 (SQRT_2 * ( C1 + C3 + C5 - C7)) #define W7 (SQRT_2 * ( C1 + C3 - C5 - C7)) #define W8 (SQRT_2 * ( C7 - C3)) #define W9 (SQRT_2 * (-C1 - C3)) #define WA (SQRT_2 * (-C3 - C5)) #define WB (SQRT_2 * ( C5 - C3)) static vector float fdctconsts[3] = { (vector float)VCONST( W0, W1, W2, W3 ), (vector float)VCONST( W4, W5, W6, W7 ), (vector float)VCONST( W8, W9, WA, WB ) }; #define LD_W0 vec_splat(cnsts0, 0) #define LD_W1 vec_splat(cnsts0, 1) #define LD_W2 vec_splat(cnsts0, 2) #define LD_W3 vec_splat(cnsts0, 3) #define LD_W4 vec_splat(cnsts1, 0) #define LD_W5 vec_splat(cnsts1, 1) #define LD_W6 vec_splat(cnsts1, 2) #define LD_W7 vec_splat(cnsts1, 3) #define LD_W8 vec_splat(cnsts2, 0) #define LD_W9 vec_splat(cnsts2, 1) #define LD_WA vec_splat(cnsts2, 2) #define LD_WB vec_splat(cnsts2, 3) #define FDCTROW(b0,b1,b2,b3,b4,b5,b6,b7) /* {{{ */ \ x0 = vec_add(b0, b7); /* x0 = b0 + b7; */ \ x7 = vec_sub(b0, b7); /* x7 = b0 - b7; */ \ x1 = vec_add(b1, b6); /* x1 = b1 + b6; */ \ x6 = vec_sub(b1, b6); /* x6 = b1 - b6; */ \ x2 = vec_add(b2, b5); /* x2 = b2 + b5; */ \ x5 = vec_sub(b2, b5); /* x5 = b2 - b5; */ \ x3 = vec_add(b3, b4); /* x3 = b3 + b4; */ \ x4 = vec_sub(b3, b4); /* x4 = b3 - b4; */ \ \ b7 = vec_add(x0, x3); /* b7 = x0 + x3; */ \ b1 = vec_add(x1, x2); /* b1 = x1 + x2; */ \ b0 = vec_add(b7, b1); /* b0 = b7 + b1; */ \ b4 = vec_sub(b7, b1); /* b4 = b7 - b1; */ \ \ b2 = vec_sub(x0, x3); /* b2 = x0 - x3; */ \ b6 = vec_sub(x1, x2); /* b6 = x1 - x2; */ \ b5 = vec_add(b6, b2); /* b5 = b6 + b2; */ \ cnst = LD_W2; \ b5 = vec_madd(cnst, b5, mzero); /* b5 = b5 * W2; */ \ cnst = LD_W1; \ b2 = vec_madd(cnst, b2, b5); /* b2 = b5 + b2 * W1; */ \ cnst = LD_W0; \ b6 = vec_madd(cnst, b6, b5); /* b6 = b5 + b6 * W0; */ \ \ x0 = vec_add(x4, x7); /* x0 = x4 + x7; */ \ x1 = vec_add(x5, x6); /* x1 = x5 + x6; */ \ x2 = vec_add(x4, x6); /* x2 = x4 + x6; */ \ x3 = vec_add(x5, x7); /* x3 = x5 + x7; */ \ x8 = vec_add(x2, x3); /* x8 = x2 + x3; */ \ cnst = LD_W3; \ x8 = vec_madd(cnst, x8, mzero); /* x8 = x8 * W3; */ \ \ cnst = LD_W8; \ x0 = vec_madd(cnst, x0, mzero); /* x0 *= W8; */ \ cnst = LD_W9; \ x1 = vec_madd(cnst, x1, mzero); /* x1 *= W9; */ \ cnst = LD_WA; \ x2 = vec_madd(cnst, x2, x8); /* x2 = x2 * WA + x8; */ \ cnst = LD_WB; \ x3 = vec_madd(cnst, x3, x8); /* x3 = x3 * WB + x8; */ \ \ cnst = LD_W4; \ b7 = vec_madd(cnst, x4, x0); /* b7 = x4 * W4 + x0; */ \ cnst = LD_W5; \ b5 = vec_madd(cnst, x5, x1); /* b5 = x5 * W5 + x1; */ \ cnst = LD_W6; \ b3 = vec_madd(cnst, x6, x1); /* b3 = x6 * W6 + x1; */ \ cnst = LD_W7; \ b1 = vec_madd(cnst, x7, x0); /* b1 = x7 * W7 + x0; */ \ \ b7 = vec_add(b7, x2); /* b7 = b7 + x2; */ \ b5 = vec_add(b5, x3); /* b5 = b5 + x3; */ \ b3 = vec_add(b3, x2); /* b3 = b3 + x2; */ \ b1 = vec_add(b1, x3); /* b1 = b1 + x3; */ \ /* }}} */ #define FDCTCOL(b0,b1,b2,b3,b4,b5,b6,b7) /* {{{ */ \ x0 = vec_add(b0, b7); /* x0 = b0 + b7; */ \ x7 = vec_sub(b0, b7); /* x7 = b0 - b7; */ \ x1 = vec_add(b1, b6); /* x1 = b1 + b6; */ \ x6 = vec_sub(b1, b6); /* x6 = b1 - b6; */ \ x2 = vec_add(b2, b5); /* x2 = b2 + b5; */ \ x5 = vec_sub(b2, b5); /* x5 = b2 - b5; */ \ x3 = vec_add(b3, b4); /* x3 = b3 + b4; */ \ x4 = vec_sub(b3, b4); /* x4 = b3 - b4; */ \ \ b7 = vec_add(x0, x3); /* b7 = x0 + x3; */ \ b1 = vec_add(x1, x2); /* b1 = x1 + x2; */ \ b0 = vec_add(b7, b1); /* b0 = b7 + b1; */ \ b0 = vec_madd(b0, divby8, mzero); /* b0 = b0 / 8; */ \ b4 = vec_sub(b7, b1); /* b4 = b7 - b1; */ \ b4 = vec_madd(b4, divby8, mzero); /* b4 = b4 / 8; */ \ \ b2 = vec_sub(x0, x3); /* b2 = x0 - x3; */ \ b6 = vec_sub(x1, x2); /* b6 = x1 - x2; */ \ b5 = vec_add(b6, b2); /* b5 = b6 + b2; */ \ cnst = LD_W2; \ b5 = vec_madd(cnst, b5, mzero); /* b5 = b5 * W2; */ \ cnst = LD_W1; \ b2 = vec_madd(cnst, b2, b5); /* b2 = b5 + b2 * W1; */ \ cnst = LD_W0; \ b6 = vec_madd(cnst, b6, b5); /* b6 = b5 + b6 * W0; */ \ \ x0 = vec_add(x4, x7); /* x0 = x4 + x7; */ \ x1 = vec_add(x5, x6); /* x1 = x5 + x6; */ \ x2 = vec_add(x4, x6); /* x2 = x4 + x6; */ \ x3 = vec_add(x5, x7); /* x3 = x5 + x7; */ \ x8 = vec_add(x2, x3); /* x8 = x2 + x3; */ \ cnst = LD_W3; \ x8 = vec_madd(cnst, x8, mzero); /* x8 = x8 * W3; */ \ \ cnst = LD_W8; \ x0 = vec_madd(cnst, x0, mzero); /* x0 *= W8; */ \ cnst = LD_W9; \ x1 = vec_madd(cnst, x1, mzero); /* x1 *= W9; */ \ cnst = LD_WA; \ x2 = vec_madd(cnst, x2, x8); /* x2 = x2 * WA + x8; */ \ cnst = LD_WB; \ x3 = vec_madd(cnst, x3, x8); /* x3 = x3 * WB + x8; */ \ \ cnst = LD_W4; \ b7 = vec_madd(cnst, x4, x0); /* b7 = x4 * W4 + x0; */ \ cnst = LD_W5; \ b5 = vec_madd(cnst, x5, x1); /* b5 = x5 * W5 + x1; */ \ cnst = LD_W6; \ b3 = vec_madd(cnst, x6, x1); /* b3 = x6 * W6 + x1; */ \ cnst = LD_W7; \ b1 = vec_madd(cnst, x7, x0); /* b1 = x7 * W7 + x0; */ \ \ b7 = vec_add(b7, x2); /* b7 += x2; */ \ b5 = vec_add(b5, x3); /* b5 += x3; */ \ b3 = vec_add(b3, x2); /* b3 += x2; */ \ b1 = vec_add(b1, x3); /* b1 += x3; */ \ /* }}} */ #define FDCT_PDECL short *block #define FDCT_ARGS block #define FDCT_PFMT "block=0x%X" /* two dimensional discrete cosine transform */ void fdct_altivec(FDCT_PDECL) { vector signed short *bp; vector float *cp; vector float b00, b10, b20, b30, b40, b50, b60, b70; vector float b01, b11, b21, b31, b41, b51, b61, b71; vector float mzero, divby8, cnst, cnsts0, cnsts1, cnsts2; vector float x0, x1, x2, x3, x4, x5, x6, x7, x8; #ifdef ALTIVEC_VERIFY if (NOT_VECTOR_ALIGNED(block)) mjpeg_error_exit1("fdct: block %% 16 != 0, (%d)\n", block); #endif AMBER_START; /* setup constants {{{ */ /* mzero = -0.0 */ mzero = vfp(vec_splat_u32(-1)); mzero = vfp(vec_sl(vu32(mzero), vu32(mzero))); cp = fdctconsts; cnsts0 = vec_ld(0, cp); cp++; cnsts1 = vec_ld(0, cp); cp++; cnsts2 = vec_ld(0, cp); /* }}} */ /* 8x8 matrix transpose (vector short[8]) {{{ */ #define MERGE_S16(hl,a,b) vec_merge##hl(vs16(a), vs16(b)) bp = (vector signed short*)block; b00 = vfp(vec_ld(0, bp)); b40 = vfp(vec_ld(16*4, bp)); b01 = vfp(MERGE_S16(h, b00, b40)); b11 = vfp(MERGE_S16(l, b00, b40)); bp++; b10 = vfp(vec_ld(0, bp)); b50 = vfp(vec_ld(16*4, bp)); b21 = vfp(MERGE_S16(h, b10, b50)); b31 = vfp(MERGE_S16(l, b10, b50)); bp++; b20 = vfp(vec_ld(0, bp)); b60 = vfp(vec_ld(16*4, bp)); b41 = vfp(MERGE_S16(h, b20, b60)); b51 = vfp(MERGE_S16(l, b20, b60)); bp++; b30 = vfp(vec_ld(0, bp)); b70 = vfp(vec_ld(16*4, bp)); b61 = vfp(MERGE_S16(h, b30, b70)); b71 = vfp(MERGE_S16(l, b30, b70)); x0 = vfp(MERGE_S16(h, b01, b41)); x1 = vfp(MERGE_S16(l, b01, b41)); x2 = vfp(MERGE_S16(h, b11, b51)); x3 = vfp(MERGE_S16(l, b11, b51)); x4 = vfp(MERGE_S16(h, b21, b61)); x5 = vfp(MERGE_S16(l, b21, b61)); x6 = vfp(MERGE_S16(h, b31, b71)); x7 = vfp(MERGE_S16(l, b31, b71)); b00 = vfp(MERGE_S16(h, x0, x4)); b10 = vfp(MERGE_S16(l, x0, x4)); b20 = vfp(MERGE_S16(h, x1, x5)); b30 = vfp(MERGE_S16(l, x1, x5)); b40 = vfp(MERGE_S16(h, x2, x6)); b50 = vfp(MERGE_S16(l, x2, x6)); b60 = vfp(MERGE_S16(h, x3, x7)); b70 = vfp(MERGE_S16(l, x3, x7)); #undef MERGE_S16 /* }}} */ /* Some of the initial calculations can be done as vector short before * conversion to vector float. The following code section takes advantage * of this. */ #if 1 /* fdct rows {{{ */ x0 = vfp(vec_add(vs16(b00), vs16(b70))); x7 = vfp(vec_sub(vs16(b00), vs16(b70))); x1 = vfp(vec_add(vs16(b10), vs16(b60))); x6 = vfp(vec_sub(vs16(b10), vs16(b60))); x2 = vfp(vec_add(vs16(b20), vs16(b50))); x5 = vfp(vec_sub(vs16(b20), vs16(b50))); x3 = vfp(vec_add(vs16(b30), vs16(b40))); x4 = vfp(vec_sub(vs16(b30), vs16(b40))); b70 = vfp(vec_add(vs16(x0), vs16(x3))); b10 = vfp(vec_add(vs16(x1), vs16(x2))); b00 = vfp(vec_add(vs16(b70), vs16(b10))); b40 = vfp(vec_sub(vs16(b70), vs16(b10))); #define CTF0(n) \ b##n##1 = vfp(vec_unpackl(vs16(b##n##0))); \ b##n##0 = vfp(vec_unpackh(vs16(b##n##0))); \ b##n##1 = vec_ctf(vs32(b##n##1), 0); \ b##n##0 = vec_ctf(vs32(b##n##0), 0); CTF0(0); CTF0(4); b20 = vfp(vec_sub(vs16(x0), vs16(x3))); b60 = vfp(vec_sub(vs16(x1), vs16(x2))); CTF0(2); CTF0(6); #undef CTF0 x0 = vec_add(b60, b20); x1 = vec_add(b61, b21); cnst = LD_W2; x0 = vec_madd(cnst, x0, mzero); x1 = vec_madd(cnst, x1, mzero); cnst = LD_W1; b20 = vec_madd(cnst, b20, x0); b21 = vec_madd(cnst, b21, x1); cnst = LD_W0; b60 = vec_madd(cnst, b60, x0); b61 = vec_madd(cnst, b61, x1); #define CTFX(x,b) \ b##0 = vfp(vec_unpackh(vs16(x))); \ b##1 = vfp(vec_unpackl(vs16(x))); \ b##0 = vec_ctf(vs32(b##0), 0); \ b##1 = vec_ctf(vs32(b##1), 0); \ CTFX(x4, b7); CTFX(x5, b5); CTFX(x6, b3); CTFX(x7, b1); #undef CTFX x0 = vec_add(b70, b10); x1 = vec_add(b50, b30); x2 = vec_add(b70, b30); x3 = vec_add(b50, b10); x8 = vec_add(x2, x3); cnst = LD_W3; x8 = vec_madd(cnst, x8, mzero); cnst = LD_W8; x0 = vec_madd(cnst, x0, mzero); cnst = LD_W9; x1 = vec_madd(cnst, x1, mzero); cnst = LD_WA; x2 = vec_madd(cnst, x2, x8); cnst = LD_WB; x3 = vec_madd(cnst, x3, x8); cnst = LD_W4; b70 = vec_madd(cnst, b70, x0); cnst = LD_W5; b50 = vec_madd(cnst, b50, x1); cnst = LD_W6; b30 = vec_madd(cnst, b30, x1); cnst = LD_W7; b10 = vec_madd(cnst, b10, x0); b70 = vec_add(b70, x2); b50 = vec_add(b50, x3); b30 = vec_add(b30, x2); b10 = vec_add(b10, x3); x0 = vec_add(b71, b11); x1 = vec_add(b51, b31); x2 = vec_add(b71, b31); x3 = vec_add(b51, b11); x8 = vec_add(x2, x3); cnst = LD_W3; x8 = vec_madd(cnst, x8, mzero); cnst = LD_W8; x0 = vec_madd(cnst, x0, mzero); cnst = LD_W9; x1 = vec_madd(cnst, x1, mzero); cnst = LD_WA; x2 = vec_madd(cnst, x2, x8); cnst = LD_WB; x3 = vec_madd(cnst, x3, x8); cnst = LD_W4; b71 = vec_madd(cnst, b71, x0); cnst = LD_W5; b51 = vec_madd(cnst, b51, x1); cnst = LD_W6; b31 = vec_madd(cnst, b31, x1); cnst = LD_W7; b11 = vec_madd(cnst, b11, x0); b71 = vec_add(b71, x2); b51 = vec_add(b51, x3); b31 = vec_add(b31, x2); b11 = vec_add(b11, x3); /* }}} */ #else /* convert to float {{{ */ #define CTF(n) \ vs32(b##n##1) = vec_unpackl(vs16(b##n##0)); \ vs32(b##n##0) = vec_unpackh(vs16(b##n##0)); \ b##n##1 = vec_ctf(vs32(b##n##1), 0); \ b##n##0 = vec_ctf(vs32(b##n##0), 0); \ CTF(0); CTF(1); CTF(2); CTF(3); CTF(4); CTF(5); CTF(6); CTF(7); #undef CTF /* }}} */ FDCTROW(b00, b10, b20, b30, b40, b50, b60, b70); FDCTROW(b01, b11, b21, b31, b41, b51, b61, b71); #endif /* 8x8 matrix transpose (vector float[8][2]) {{{ */ x0 = vec_mergel(b00, b20); x1 = vec_mergeh(b00, b20); x2 = vec_mergel(b10, b30); x3 = vec_mergeh(b10, b30); b00 = vec_mergeh(x1, x3); b10 = vec_mergel(x1, x3); b20 = vec_mergeh(x0, x2); b30 = vec_mergel(x0, x2); x4 = vec_mergel(b41, b61); x5 = vec_mergeh(b41, b61); x6 = vec_mergel(b51, b71); x7 = vec_mergeh(b51, b71); b41 = vec_mergeh(x5, x7); b51 = vec_mergel(x5, x7); b61 = vec_mergeh(x4, x6); b71 = vec_mergel(x4, x6); x0 = vec_mergel(b01, b21); x1 = vec_mergeh(b01, b21); x2 = vec_mergel(b11, b31); x3 = vec_mergeh(b11, b31); x4 = vec_mergel(b40, b60); x5 = vec_mergeh(b40, b60); x6 = vec_mergel(b50, b70); x7 = vec_mergeh(b50, b70); b40 = vec_mergeh(x1, x3); b50 = vec_mergel(x1, x3); b60 = vec_mergeh(x0, x2); b70 = vec_mergel(x0, x2); b01 = vec_mergeh(x5, x7); b11 = vec_mergel(x5, x7); b21 = vec_mergeh(x4, x6); b31 = vec_mergel(x4, x6); /* }}} */ /* divby8 = (vector float)(0.125); {{{ */ divby8 = vfp(vec_splat_u8(-6)); divby8 = vfp(vec_sr(vu16(divby8),vu16(divby8))); divby8 = vfp(vec_unpackh(vs16(divby8))); divby8 = vec_sld(divby8, divby8, 3); /* }}} */ cnsts0 = vec_madd(cnsts0, divby8, mzero); cnsts1 = vec_madd(cnsts1, divby8, mzero); cnsts2 = vec_madd(cnsts2, divby8, mzero); FDCTCOL(b00, b10, b20, b30, b40, b50, b60, b70); FDCTCOL(b01, b11, b21, b31, b41, b51, b61, b71); /* round, convert back to short and clip {{{ */ /* cnsts0 = max = (2047); cnsts2 = min = (-2048); {{{ */ cnsts0 = vfp(vec_splat_u8(0x7)); x8 = vfp(vec_splat_s16(-1)); /* 0xffff */ cnsts0 = vfp(vec_mergeh(vu8(cnsts0), vu8(x8))); /* 0x07ff == 2047 */ cnsts2 = vfp(vec_sub(vs16(x8), vs16(cnsts0))); /* }}} */ #define CTS(n) \ b##n##0 = vfp(vec_round(b##n##0)); \ b##n##1 = vfp(vec_round(b##n##1)); \ b##n##0 = vfp(vec_cts(b##n##0, 0)); \ b##n##1 = vfp(vec_cts(b##n##1, 0)); \ b##n##0 = vfp(vec_pack(vs32(b##n##0), vs32(b##n##1))); \ b##n##0 = vfp(vec_min(vs16(b##n##0), vs16(cnsts0))); \ b##n##0 = vfp(vec_max(vs16(b##n##0), vs16(cnsts2))); \ vec_st(vs16(b##n##0), 0, bp); bp = (vector signed short*)block; CTS(0); bp++; CTS(1); bp++; CTS(2); bp++; CTS(3); bp++; CTS(4); bp++; CTS(5); bp++; CTS(6); bp++; CTS(7); #undef CTS /* }}} */ AMBER_STOP; } #if ALTIVEC_TEST_FUNCTION(fdct) /* {{{ */ #ifdef ALTIVEC_VERIFY void fdct_altivec_verify(FDCT_PDECL) { int i; fdct_altivec(FDCT_ARGS); for (i = 0; i < 64; i++) { if (block[i] < -2048) mjpeg_warn("fdct: block[%d]=%d < -2048\n", i, block[i]); else if (block[i] > 2047) mjpeg_warn("fdct: block[%d]=%d > 2047\n", i, block[i]); } } #else ALTIVEC_TEST(fdct, void, (FDCT_PDECL), FDCT_PFMT, FDCT_ARGS); #endif #endif /* }}} */ /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/benchmark.c0000644000175000017500000002372007742364041021111 0ustar glowwormglowworm/* benchmark.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_conf.h" #include "../mjpeg_logging.h" #ifdef ALTIVEC_BENCHMARK #include #include #include #define MAX_TIME_VALUE (long)(((unsigned long)-1L)>>1) #define TSECS(tvp) (((double)(tvp)->tv_sec)+(((double)(tvp)->tv_usec)*0.000001)) struct benchmark_info { char *name; char *cmpname; struct benchmark_stats *stats; }; #define EXTERN_STATS(n) \ extern struct benchmark_stats n##_altivec_benchmark_stats #if ALTIVEC_TEST_FUNCTION(sad_00) EXTERN_STATS(sad_00); #endif #if ALTIVEC_TEST_FUNCTION(sad_01) EXTERN_STATS(sad_01); #endif #if ALTIVEC_TEST_FUNCTION(sad_10) EXTERN_STATS(sad_10); #endif #if ALTIVEC_TEST_FUNCTION(sad_11) EXTERN_STATS(sad_11); #endif #if ALTIVEC_TEST_FUNCTION(bsad) EXTERN_STATS(bsad); #endif #if ALTIVEC_TEST_FUNCTION(sumsq) EXTERN_STATS(sumsq); #endif #if ALTIVEC_TEST_FUNCTION(sumsq_sub22) EXTERN_STATS(sumsq_sub22); #endif #if ALTIVEC_TEST_FUNCTION(bsumsq) EXTERN_STATS(bsumsq); #endif #if ALTIVEC_TEST_FUNCTION(bsumsq_sub22) EXTERN_STATS(bsumsq_sub22); #endif #if ALTIVEC_TEST_FUNCTION(find_best_one_pel) EXTERN_STATS(find_best_one_pel); #endif #if ALTIVEC_TEST_FUNCTION(build_sub22_mests) EXTERN_STATS(build_sub22_mests); #endif #if ALTIVEC_TEST_FUNCTION(build_sub44_mests) EXTERN_STATS(build_sub44_mests); #endif #if ALTIVEC_TEST_FUNCTION(quant_non_intra) EXTERN_STATS(quant_non_intra); #endif #if ALTIVEC_TEST_FUNCTION(quant_weight_coeff_sum) EXTERN_STATS(quant_weight_coeff_sum); #endif #if ALTIVEC_TEST_FUNCTION(iquant_non_intra_m1) EXTERN_STATS(iquant_non_intra_m1); #endif #if ALTIVEC_TEST_FUNCTION(iquant_non_intra_m2) EXTERN_STATS(iquant_non_intra_m2); #endif #if ALTIVEC_TEST_FUNCTION(iquant_intra_m1) EXTERN_STATS(iquant_intra_m1); #endif #if ALTIVEC_TEST_FUNCTION(iquant_intra_m2) EXTERN_STATS(iquant_intra_m2); #endif #if ALTIVEC_TEST_FUNCTION(variance) EXTERN_STATS(variance); #endif #if ALTIVEC_TEST_FUNCTION(sub_pred) EXTERN_STATS(sub_pred); #endif #if ALTIVEC_TEST_FUNCTION(add_pred) EXTERN_STATS(add_pred); #endif #if ALTIVEC_TEST_FUNCTION(pred_comp) EXTERN_STATS(pred_comp); #endif #if ALTIVEC_TEST_FUNCTION(subsample_image) EXTERN_STATS(subsample_image); #endif #if ALTIVEC_TEST_FUNCTION(sub_mean_reduction) EXTERN_STATS(sub_mean_reduction); #endif #if ALTIVEC_TEST_FUNCTION(fdct) EXTERN_STATS(fdct); #endif #if ALTIVEC_TEST_FUNCTION(idct) EXTERN_STATS(idct); #endif #define BENCHMARK_INFO(n) \ AVSTR(n##_altivec), AVSTR(ALTIVEC_TEST_WITH(n)), \ &n##_altivec_benchmark_stats, struct benchmark_info benchmarktab[] = { #if ALTIVEC_TEST_FUNCTION(sad_00) BENCHMARK_INFO(sad_00) #endif #if ALTIVEC_TEST_FUNCTION(sad_01) BENCHMARK_INFO(sad_01) #endif #if ALTIVEC_TEST_FUNCTION(sad_10) BENCHMARK_INFO(sad_10) #endif #if ALTIVEC_TEST_FUNCTION(sad_11) BENCHMARK_INFO(sad_11) #endif #if ALTIVEC_TEST_FUNCTION(bsad) BENCHMARK_INFO(bsad) #endif #if ALTIVEC_TEST_FUNCTION(sumsq) BENCHMARK_INFO(sumsq) #endif #if ALTIVEC_TEST_FUNCTION(sumsq_sub22) BENCHMARK_INFO(sumsq_sub22) #endif #if ALTIVEC_TEST_FUNCTION(bsumsq) BENCHMARK_INFO(bsumsq) #endif #if ALTIVEC_TEST_FUNCTION(bsumsq_sub22) BENCHMARK_INFO(bsumsq_sub22) #endif #if ALTIVEC_TEST_FUNCTION(find_best_one_pel) BENCHMARK_INFO(find_best_one_pel) #endif #if ALTIVEC_TEST_FUNCTION(build_sub22_mests) BENCHMARK_INFO(build_sub22_mests) #endif #if ALTIVEC_TEST_FUNCTION(build_sub44_mests) BENCHMARK_INFO(build_sub44_mests) #endif #if ALTIVEC_TEST_FUNCTION(quant_non_intra) BENCHMARK_INFO(quant_non_intra) #endif #if ALTIVEC_TEST_FUNCTION(quant_weight_coeff_sum) BENCHMARK_INFO(quant_weight_coeff_sum) #endif #if ALTIVEC_TEST_FUNCTION(iquant_non_intra_m1) BENCHMARK_INFO(iquant_non_intra_m1) #endif #if ALTIVEC_TEST_FUNCTION(iquant_non_intra_m2) BENCHMARK_INFO(iquant_non_intra_m2) #endif #if ALTIVEC_TEST_FUNCTION(iquant_intra_m1) BENCHMARK_INFO(iquant_intra_m1) #endif #if ALTIVEC_TEST_FUNCTION(iquant_intra_m2) BENCHMARK_INFO(iquant_intra_m2) #endif #if ALTIVEC_TEST_FUNCTION(variance) BENCHMARK_INFO(variance) #endif #if ALTIVEC_TEST_FUNCTION(sub_pred) BENCHMARK_INFO(sub_pred) #endif #if ALTIVEC_TEST_FUNCTION(add_pred) BENCHMARK_INFO(add_pred) #endif #if ALTIVEC_TEST_FUNCTION(pred_comp) BENCHMARK_INFO(pred_comp) #endif #if ALTIVEC_TEST_FUNCTION(subsample_image) BENCHMARK_INFO(subsample_image) #endif #if ALTIVEC_TEST_FUNCTION(sub_mean_reduction) BENCHMARK_INFO(sub_mean_reduction) #endif #if ALTIVEC_TEST_FUNCTION(fdct) BENCHMARK_INFO(fdct) #endif #if ALTIVEC_TEST_FUNCTION(idct) BENCHMARK_INFO(idct) #endif }; int calibrate_benchmark(double precision, double increment, int timelimit, int reqpasses, int *passes, int *iterations, int *calibration, struct timeval *time, struct timeval *last_time) { double secs0, secs1; double err = precision; int done = 0; if (last_time->tv_sec != 0 && last_time->tv_usec != 0) { /* calculate error amount */ secs0 = TSECS(time) / increment; secs1 = TSECS(last_time); if (secs0 > secs1) err = secs0 / secs1 - 1; else err = secs1 / secs0 - 1; } if (err >= precision) { *passes = 0; *calibration = *iterations; *iterations *= increment; last_time->tv_sec = time->tv_sec; last_time->tv_usec = time->tv_usec; } else { (*passes)++; } if (*passes == reqpasses) { time->tv_sec = last_time->tv_sec; time->tv_usec = last_time->tv_usec; done = 1; } else if (last_time->tv_sec >= timelimit) { done = 1; } if (done) mjpeg_debug("calibration passes=%d precision=%f time=%d.%06d", *passes, err, time->tv_sec, time->tv_usec); return done; } void update_benchmark_times(const char *name, struct benchmark_times *times, struct timeval *time, const char *fmt, ...) { va_list args; char buf[BENCHMARK_ARGS_BUFSIZE]; /* sprintf function arguments */ va_start(args, fmt); vsnprintf(buf, BENCHMARK_ARGS_BUFSIZE-1, fmt, args); va_end(args); if (times->total.tv_sec == 0 && times->total.tv_usec == 0) { /* first time, copy to both min & max */ times->min.tv_sec = times->max.tv_sec = time->tv_sec; times->min.tv_usec = times->max.tv_usec = time->tv_usec; strncpy(times->min_args, buf, BENCHMARK_ARGS_BUFSIZE); strncpy(times->max_args, buf, BENCHMARK_ARGS_BUFSIZE); } else if (timercmp(time, ×->min, <)) { times->min.tv_sec = time->tv_sec; times->min.tv_usec = time->tv_usec; strncpy(times->min_args, buf, BENCHMARK_ARGS_BUFSIZE); } else if (timercmp(time, ×->max, >)) { times->max.tv_sec = time->tv_sec; times->max.tv_usec = time->tv_usec; strncpy(times->max_args, buf, BENCHMARK_ARGS_BUFSIZE); } timeradd(time, ×->total, ×->total); /* add difference to total */ mjpeg_info("time: %d.%06d %s", time->tv_sec, time->tv_usec, buf); } void print_benchmark_times(const char* name, struct benchmark_times *times) { mjpeg_info("%s: min=%d.%06d %s", name, times->min.tv_sec, times->min.tv_usec, times->min_args); mjpeg_info("%s: max=%d.%06d %s", name, times->max.tv_sec, times->max.tv_usec, times->max_args); mjpeg_info("%s: total=%d.%06d", name, times->total.tv_sec, times->total.tv_usec); } void print_calibration_stats(int count, char* name[], int *calibration, struct timeval *times) { int i; for (i = 0; i < count; i++) { mjpeg_info("%s: calibration=%d in %d.%06d seconds", name[i], calibration[i], times[i].tv_sec, times[i].tv_usec); } } void print_benchmark_diff(int count, char* names[], struct timeval *times) { double secs0, secs1, percent; char *speed; secs0 = TSECS(×[0]); secs1 = TSECS(×[1]); if (secs0 < secs1) { percent = (secs1/secs0-1.0)*100.0; speed = "faster"; } else { percent = (secs0/secs1-1.0)*100.0; speed = "slower"; } mjpeg_info("%s was %.2f%% %s than %s", names[0], percent, speed, names[1]); } void print_benchmark_statistics() { int i; char *names[2]; struct timeval times[2]; for (i = 0; i < sizeof(benchmarktab) / sizeof(struct benchmark_info); i++) { mjpeg_info("%s: counter=%d, iterations=%d", benchmarktab[i].name, benchmarktab[i].stats->counter, benchmarktab[i].stats->iterations); print_benchmark_times(benchmarktab[i].name, &(benchmarktab[i].stats->times[0])); print_benchmark_times(benchmarktab[i].cmpname, &(benchmarktab[i].stats->times[1])); names[0] = benchmarktab[i].name; names[1] = benchmarktab[i].cmpname; times[0].tv_sec = benchmarktab[i].stats->times[0].total.tv_sec; times[0].tv_usec = benchmarktab[i].stats->times[0].total.tv_usec; times[1].tv_sec = benchmarktab[i].stats->times[1].total.tv_sec; times[1].tv_usec = benchmarktab[i].stats->times[1].total.tv_usec; print_benchmark_diff(2, names, times); } } #else void print_benchmark_statistics() { mjpeg_info("AltiVec benchmarking not enabled"); } #endif mjpegtools-2.1.0/utils/altivec/amber.c0000644000175000017500000000563207565610177020256 0ustar glowwormglowworm/* amber.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #ifdef HAVE_SYS_TYPES_H #include #endif #include #include #include #include "../mjpeg_logging.h" #define SIGNAL_AMBER() \ ({register long _value; \ asm volatile ("mfspr %0, 1023" : "=r" (_value) ); \ _value; }) long amber_start(const char *file, int line, int *trace_count, int max_traces) { long value; value = 0; if (*trace_count < max_traces) { mjpeg_info("amber start %s:%d", file, line); value = SIGNAL_AMBER(); } return value; } long amber_stop(const char *file, int line, int *trace_count, int max_traces, int max_exit) { long value; if (*trace_count < max_traces) { value = SIGNAL_AMBER(); mjpeg_info("amber stop %s:%d", file, line); (*trace_count)++; if (max_exit && *trace_count >= max_traces) exit(0); } else { value = 0; } return value; } void amber_symtrace(const char *name) { DIR *dp; struct dirent *dir; struct stat sb; char tracename[PATH_MAX], sympath[PATH_MAX], symname[PATH_MAX]; int found = 0; if ((dp = opendir(".")) == NULL) mjpeg_error_exit1("can't open current directory"); while ((dir = readdir(dp)) != NULL) { if (dir->d_ino == 0) continue; if (strncmp(dir->d_name, "trace_", 6) == 0) { if (!found) { found = 1; strncpy(tracename, dir->d_name, PATH_MAX); } else { if (strncmp(dir->d_name, tracename, PATH_MAX) > 0) strncpy(tracename, dir->d_name, PATH_MAX); } } } closedir(dp); if (found) { if (stat(name, &sb) != 0 && errno == ENOENT) { if (mkdir(name, 0777) != 0) mjpeg_error_exit1("can't make directory %s", name); } snprintf(sympath, PATH_MAX, "../%s", tracename); snprintf(symname, PATH_MAX, "%s/%s", name, tracename); if (symlink(sympath, symname) != 0) mjpeg_error_exit1("can't symlink %s to %s", tracename, symname); } else { mjpeg_error_exit1("trace not found"); } } mjpegtools-2.1.0/utils/altivec/pred_comp.c0000644000175000017500000011043210464771010021115 0ustar glowwormglowworm/* pred_comp.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_predict.h" #include "vectorize.h" #include "../mjpeg_logging.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif #define PRED_COMP_PDECL /* {{{ */ \ uint8_t *src, \ uint8_t *dst, \ int lx, \ int w, int h, \ int x, int y, \ int dx, int dy, \ int addflag \ /* }}} */ #define PRED_COMP_ARGS src, dst, lx, w, h, x, y, dx, dy, addflag #define PRED_COMP_PFMT /* {{{ */ \ "src=0x%X, dst=0x%X, lx=%d, w=%d, h=%d, x=%d, y=%d," \ " dx=%d, dy=%d, addflag=%d" \ /* }}} */ /* low level prediction routine * * src: prediction source * dst: prediction destination * lx: line width (for both src and dst) * x,y: destination coordinates * dx,dy: half pel motion vector * w,h: size of prediction block * addflag: store or add prediction * * src % 16 == 0 * dst % 16 == 0 * lx % 16 == 0 * w == 16 | 8 * h == 16 | 8 | 4 interlaced * w == h | h*2 interlaced */ void pred_comp_altivec(PRED_COMP_PDECL) { int xint, xh, yint, yh; int i, j; uint8_t *s, *d; vector unsigned char lS, lS0, lS1, lS2, lS3, lD, perm, perm1; vector unsigned short s0H, s0L, s1H, s1L, s2H, s2L, s3H, s3L, dH, dL; vector unsigned char zero, eight; vector unsigned short one, two; AMBER_START; /* half pel scaling */ xint = dx>>1; /* integer part */ xh = dx & 1; /* half pel flag */ yint = dy>>1; yh = dy & 1; /* origins */ s = src + lx*(y+yint) + (x+xint); /* motion vector */ d = dst + lx*y + x; #ifdef ALTIVEC_VERIFY if (NOT_VECTOR_ALIGNED(src)) mjpeg_error_exit1("pred_comp: src %% 16 != 0, (0x%X)", src); if (NOT_VECTOR_ALIGNED(dst)) mjpeg_error_exit1("pred_comp: dst %% 16 != 0, (0x%X)", dst); if (NOT_VECTOR_ALIGNED(lx)) mjpeg_error_exit1("pred_comp: lx %% 16 != 0, (%d)", lx); if (((unsigned long)d & 0x7) != 0) mjpeg_error_exit1("pred_comp: d %% 8 != 0 (0x%X)", d); if (((unsigned long)d & 0xf) > w) mjpeg_error_exit1("pred_comp: (d & 0xf) > w (d=0x%X, w=%d)", d, w); if (w != h && w != (h * 2)) mjpeg_error_exit1("pred_comp: w != h|(h*2), (w=%d, h=%d)", w, h); #endif if (w != 16 && w != 8) mjpeg_error_exit1("pred_comp: w != 16|8, (%d)", w); if (h != 16 && h != 8 && h != 4) mjpeg_error_exit1("pred_comp: h != 16|8|4, (%d)", h); #ifdef ALTIVEC_DST if (lx & (~0xffff) != 0) mjpeg_error_exit1("pred_comp: lx > vec_dst range", lx); #endif if (xh) { if (yh) { /* (xh && yh) {{{ */ if (addflag) { /* {{{ */ zero = vec_splat_u8(0); one = vec_splat_u16(1); two = vec_splat_u16(2); if (w == 8) { /* {{{ */ eight = vec_splat_u8(8); perm = vec_lvsl(0, (unsigned char*)s); if (((unsigned long)d & 0xf) == 0) { /* {{{ */ lS0 = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS0, lS1, perm); lS1 = vec_slo(lS0, eight); s += lx; for (i = 0; i < h; i++) { lS2 = vec_ld(0, (unsigned char*)s); lS3 = vec_ld(16, (unsigned char*)s); lS2 = vec_perm(lS2, lS3, perm); lS3 = vec_slo(lS2, eight); lD = vec_ld(0, (unsigned char*)d); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) s[1-8] */ s1H = vu16(vec_mergeh(zero, lS1)); /* (unsigned short[]) s+lx[0-7] */ s2H = vu16(vec_mergeh(zero, lS2)); /* (unsigned short[]) s+lx[1-8] */ s3H = vu16(vec_mergeh(zero, lS3)); /* (unsigned short[]) d[0-7] */ dH = vu16(vec_mergeh(zero, lD)); /* (unsigned short[]) d[8-15] */ dL = vu16(vec_mergel(zero, lD)); /* s[i] + s[i+1] */ s0H = vec_add(s0H, s1H); /* s[i+lx] + s[i+lx+1] */ s2H = vec_add(s2H, s3H); /* (s[i]+s[i+1]) + (s[i+lx]+s[i+lx+1]) */ s0H = vec_add(s0H, s2H); /* (s[i]+s[i+1]+s[i+lx]+s[i+lx+1]) + 2 */ s0H = vec_add(s0H, two); /* (s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2) >> 2 */ s0H = vec_sra(s0H, two); /* d[i] + ((s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2)>>2) */ dH = vec_add(dH, s0H); /* (d[i]+((s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2)>>2)) * + 1 */ dH = vec_add(dH, one); /* ((d[i]+((s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2)>>2)) * + 1) >> 1 */ dH = vec_sra(dH, one); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(dH, dL)); vec_st(vu8(dH), 0, (unsigned char*)d); lS0 = lS2; lS1 = lS3; s += lx; d += lx; } /* }}} */ } else { /* {{{ */ /* d is offset 8 bytes, work on dL (low bytes). */ lS0 = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS0, lS1, perm); lS1 = vec_slo(lS0, eight); s += lx; for (i = 0; i < h; i++) { lS2 = vec_ld(0, (unsigned char*)s); lS3 = vec_ld(16, (unsigned char*)s); lS2 = vec_perm(lS2, lS3, perm); lS3 = vec_slo(lS2, eight); lD = vec_ld(0, (unsigned char*)d); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) s[1-8] */ s1H = vu16(vec_mergeh(zero, lS1)); /* (unsigned short[]) s+lx[0-7] */ s2H = vu16(vec_mergeh(zero, lS2)); /* (unsigned short[]) s+lx[1-8] */ s3H = vu16(vec_mergeh(zero, lS3)); /* (unsigned short[]) d[0-7] */ dH = vu16(vec_mergeh(zero, lD)); /* (unsigned short[]) d[8-15] */ dL = vu16(vec_mergel(zero, lD)); /* s[i] + s[i+1] */ s0H = vec_add(s0H, s1H); /* s[i+lx] + s[i+lx+1] */ s2H = vec_add(s2H, s3H); /* (s[i]+s[i+1]) + (s[i+lx]+s[i+lx+1]) */ s0H = vec_add(s0H, s2H); /* (s[i]+s[i+1]+s[i+lx]+s[i+lx+1]) + 2 */ s0H = vec_add(s0H, two); /* (s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2) >> 2 */ s0H = vec_sra(s0H, two); /* d[i] + ((s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2)>>2) */ dL = vec_add(dL, s0H); /* (d[i]+((s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2)>>2)) * + 1 */ dL = vec_add(dL, one); /* ((d[i]+((s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2)>>2)) * + 1) >> 1 */ dL = vec_sra(dL, one); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(dH, dL)); vec_st(vu8(dH), 0, (unsigned char*)d); lS0 = lS2; lS1 = lS3; s += lx; d += lx; } /* }}} */ } /* }}} */ } else /* w == 16 */ { /* {{{ */ perm = vec_lvsl(0, s); perm1 = vec_splat_u8(1); perm1 = vec_add(perm, perm1); lS = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS, lS1, perm); lS1 = vec_perm(lS, lS1, perm1); s += lx; for (i = 0; i < h; i++) { lS = vec_ld(0, (unsigned char*)s); lS3 = vec_ld(16, (unsigned char*)s); lS2 = vec_perm(lS, lS3, perm); lS3 = vec_perm(lS, lS3, perm1); lD = vec_ld(0, (unsigned char*)d); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) s[8-15] */ s0L = vu16(vec_mergel(zero, lS0)); /* (unsigned short[]) s[1-8] */ s1H = vu16(vec_mergeh(zero, lS1)); /* (unsigned short[]) s[9-16] */ s1L = vu16(vec_mergel(zero, lS1)); /* (unsigned short[]) s+lx[0-7] */ s2H = vu16(vec_mergeh(zero, lS2)); /* (unsigned short[]) s+lx[8-15] */ s2L = vu16(vec_mergel(zero, lS2)); /* (unsigned short[]) s+lx[1-8] */ s3H = vu16(vec_mergeh(zero, lS3)); /* (unsigned short[]) s+lx[9-16] */ s3L = vu16(vec_mergel(zero, lS3)); /* (unsigned short[]) d[0-7] */ dH = vu16(vec_mergeh(zero, lD)); /* (unsigned short[]) d[8-15] */ dL = vu16(vec_mergel(zero, lD)); /* s[i] + s[i+1] */ s0H = vec_add(s0H, s1H); s0L = vec_add(s0L, s1L); /* s[i+lx] + s[i+lx+1] */ s2H = vec_add(s2H, s3H); s2L = vec_add(s2L, s3L); /* (s[i]+s[i+1]) + (s[i+lx]+s[i+lx+1]) */ s0H = vec_add(s0H, s2H); s0L = vec_add(s0L, s2L); /* (s[i]+s[i+1]+s[i+lx]+s[i+lx+1]) + 2 */ s0H = vec_add(s0H, two); s0L = vec_add(s0L, two); /* (s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2) >> 2 */ s0H = vec_sra(s0H, two); s0L = vec_sra(s0L, two); /* d[i] + ((s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2)>>2) */ dH = vec_add(dH, s0H); dL = vec_add(dL, s0L); /* (d[i]+((s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2)>>2)) * + 1 */ dH = vec_add(dH, one); dL = vec_add(dL, one); /* ((d[i]+((s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2)>>2)) * + 1) >> 1 */ dH = vec_sra(dH, one); dL = vec_sra(dL, one); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(dH, dL)); vec_st(vu8(dH), 0, (unsigned char*)d); lS0 = lS2; lS1 = lS3; s += lx; d += lx; } /* }}} */ } #if 0 for (j=0; j>2)+1)>>1; s+= lx; d+= lx; } #endif /* }}} */ } else /* !addflag */ { /* {{{ */ zero = vec_splat_u8(0); one = vec_splat_u16(1); two = vec_splat_u16(2); if (w == 8) { /* {{{ */ eight = vec_splat_u8(8); perm = vec_lvsl(0, (unsigned char*)s); if (((unsigned long)d & 0xf) == 0) { /* {{{ */ lS0 = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS0, lS1, perm); lS1 = vec_slo(lS0, eight); s += lx; for (i = 0; i < h; i++) { lS2 = vec_ld(0, (unsigned char*)s); lS3 = vec_ld(16, (unsigned char*)s); lS2 = vec_perm(lS2, lS3, perm); lS3 = vec_slo(lS2, eight); lD = vec_ld(0, (unsigned char*)d); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) s[1-8] */ s1H = vu16(vec_mergeh(zero, lS1)); /* (unsigned short[]) s+lx[0-7] */ s2H = vu16(vec_mergeh(zero, lS2)); /* (unsigned short[]) s+lx[1-8] */ s3H = vu16(vec_mergeh(zero, lS3)); /* (unsigned short[]) d[8-15] */ dL = vu16(vec_mergel(zero, lD)); /* s[i] + s[i+1] */ s0H = vec_add(s0H, s1H); /* s[i+lx] + s[i+lx+1] */ s2H = vec_add(s2H, s3H); /* (s[i]+s[i+1]) + (s[i+lx]+s[i+lx+1]) */ s0H = vec_add(s0H, s2H); /* (s[i]+s[i+1]+s[i+lx]+s[i+lx+1]) + 2 */ s0H = vec_add(s0H, two); /* (s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2) >> 2 */ s0H = vec_sra(s0H, two); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(s0H, dL)); vec_st(vu8(dH), 0, (unsigned char*)d); lS0 = lS2; lS1 = lS3; s += lx; d += lx; } /* }}} */ } else { /* {{{ */ /* d is offset 8 bytes, work on dL (low bytes). */ lS0 = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS0, lS1, perm); lS1 = vec_slo(lS0, eight); s += lx; for (i = 0; i < h; i++) { lS2 = vec_ld(0, (unsigned char*)s); lS3 = vec_ld(16, (unsigned char*)s); lS2 = vec_perm(lS2, lS3, perm); lS3 = vec_slo(lS2, eight); lD = vec_ld(0, (unsigned char*)d); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) s[1-8] */ s1H = vu16(vec_mergeh(zero, lS1)); /* (unsigned short[]) s+lx[0-7] */ s2H = vu16(vec_mergeh(zero, lS2)); /* (unsigned short[]) s+lx[1-8] */ s3H = vu16(vec_mergeh(zero, lS3)); /* (unsigned short[]) d[0-7] */ dH = vu16(vec_mergeh(zero, lD)); /* s[i] + s[i+1] */ s0H = vec_add(s0H, s1H); /* s[i+lx] + s[i+lx+1] */ s2H = vec_add(s2H, s3H); /* (s[i]+s[i+1]) + (s[i+lx]+s[i+lx+1]) */ s0H = vec_add(s0H, s2H); /* (s[i]+s[i+1]+s[i+lx]+s[i+lx+1]) + 2 */ s0H = vec_add(s0H, two); /* (s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2) >> 2 */ s0H = vec_sra(s0H, two); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(dH, s0H)); vec_st(vu8(dH), 0, (unsigned char*)d); lS0 = lS2; lS1 = lS3; s += lx; d += lx; } /* }}} */ } /* }}} */ } else /* w == 16 */ { /* {{{ */ perm = vec_lvsl(0, s); perm1 = vec_splat_u8(1); perm1 = vec_add(perm, perm1); lS = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS, lS1, perm); lS1 = vec_perm(lS, lS1, perm1); s += lx; for (i = 0; i < h; i++) { lS = vec_ld(0, (unsigned char*)s); lS3 = vec_ld(16, (unsigned char*)s); lS2 = vec_perm(lS, lS3, perm); lS3 = vec_perm(lS, lS3, perm1); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) s[8-15] */ s0L = vu16(vec_mergel(zero, lS0)); /* (unsigned short[]) s[1-8] */ s1H = vu16(vec_mergeh(zero, lS1)); /* (unsigned short[]) s[9-16] */ s1L = vu16(vec_mergel(zero, lS1)); /* (unsigned short[]) s+lx[0-7] */ s2H = vu16(vec_mergeh(zero, lS2)); /* (unsigned short[]) s+lx[8-15] */ s2L = vu16(vec_mergel(zero, lS2)); /* (unsigned short[]) s+lx[1-8] */ s3H = vu16(vec_mergeh(zero, lS3)); /* (unsigned short[]) s+lx[9-16] */ s3L = vu16(vec_mergel(zero, lS3)); /* s[i] + s[i+1] */ s0H = vec_add(s0H, s1H); s0L = vec_add(s0L, s1L); /* s[i+lx] + s[i+lx+1] */ s2H = vec_add(s2H, s3H); s2L = vec_add(s2L, s3L); /* (s[i]+s[i+1]) + (s[i+lx]+s[i+lx+1]) */ s0H = vec_add(s0H, s2H); s0L = vec_add(s0L, s2L); /* (s[i]+s[i+1]+s[i+lx]+s[i+lx+1]) + 2 */ s0H = vec_add(s0H, two); s0L = vec_add(s0L, two); /* (s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2) >> 2 */ s0H = vec_sra(s0H, two); s0L = vec_sra(s0L, two); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(s0H, s0L)); vec_st(vu8(dH), 0, (unsigned char*)d); lS0 = lS2; lS1 = lS3; s += lx; d += lx; } /* }}} */ } #if 0 for (j=0; j>2; s+= lx; d+= lx; } #endif /* }}} */ } /* }}} */ } else /* !yh */ { /* (xh && !yh) {{{ */ if (addflag) { /* {{{ */ zero = vec_splat_u8(0); one = vec_splat_u16(1); if (w == 8) { /* {{{ */ eight = vec_splat_u8(8); perm = vec_lvsl(0, (unsigned char*)s); if (((unsigned long)d & 0xf) == 0) { for (i = 0; i < h; i++) { lS0 = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS0, lS1, perm); lS1 = vec_slo(lS0, eight); lD = vec_ld(0, (unsigned char*)d); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) s[1-8] */ s1H = vu16(vec_mergeh(zero, lS1)); /* (unsigned short[]) d[0-7] */ dH = vu16(vec_mergeh(zero, lD)); /* (unsigned short[]) d[8-15] */ dL = vu16(vec_mergel(zero, lD)); /* s[i] + s[i+1] */ s0H = vec_add(s0H, s1H); /* (s[i]+s[i+1]) + 1 */ s0H = vec_add(s0H, one); /* (s[i]+s[i+1]+1) >> 1 */ s0H = vec_sra(s0H, one); /* d[i] + ((s[i]+s[i+1]+1)>>1) */ dH = vec_add(dH, s0H); /* (d[i]+((s[i]+s[i+1]+1)>>1)) + 1 */ dH = vec_add(dH, one); /* ((d[i]+((s[i]+s[i+1]+1)>>1))+1) >> 1 */ dH = vec_sra(dH, one); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(dH, dL)); vec_st(vu8(dH), 0, (unsigned char*)d); s += lx; d += lx; } /* }}} */ } else { /* {{{ */ /* d is offset 8 bytes, work on dL (low bytes). */ for (i = 0; i < h; i++) { lS0 = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS0, lS1, perm); lS1 = vec_slo(lS0, eight); lD = vec_ld(0, (unsigned char*)d); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) s[1-8] */ s1H = vu16(vec_mergeh(zero, lS1)); /* (unsigned short[]) d[8-15] */ dL = vu16(vec_mergel(zero, lD)); /* (unsigned short[]) d[0-7] */ dH = vu16(vec_mergeh(zero, lD)); /* s[i] + s[i+1] */ s0H = vec_add(s0H, s1H); /* (s[i]+s[i+1]) + 1 */ s0H = vec_add(s0H, one); /* (s[i]+s[i+1]+1) >> 1 */ s0H = vec_sra(s0H, one); /* d[i] + ((s[i]+s[i+1]+1)>>1) */ dL = vec_add(dL, s0H); /* (d[i]+((s[i]+s[i+1]+1)>>1)) + 1 */ dL = vec_add(dL, one); /* ((d[i]+((s[i]+s[i+1]+1)>>1))+1) >> 1 */ dL = vec_sra(dL, one); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(dH, dL)); vec_st(vu8(dH), 0, (unsigned char*)d); s += lx; d += lx; } /* }}} */ } } else /* w == 16 */ { /* {{{ */ perm = vec_lvsl(0, s); perm1 = vec_splat_u8(1); perm1 = vec_add(perm, perm1); for (i = 0; i < h; i++) { lS = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS, lS1, perm); lS1 = vec_perm(lS, lS1, perm1); lD = vec_ld(0, (unsigned char*)d); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) s[8-15] */ s0L = vu16(vec_mergel(zero, lS0)); /* (unsigned short[]) s[1-8] */ s1H = vu16(vec_mergeh(zero, lS1)); /* (unsigned short[]) s[9-16] */ s1L = vu16(vec_mergel(zero, lS1)); /* (unsigned short[]) d[0-7] */ dH = vu16(vec_mergeh(zero, lD)); /* (unsigned short[]) d[8-15] */ dL = vu16(vec_mergel(zero, lD)); /* s[i] + s[i+1] */ s0H = vec_add(s0H, s1H); s0L = vec_add(s0L, s1L); /* (s[i]+s[i+1]) + 1 */ s0H = vec_add(s0H, one); s0L = vec_add(s0L, one); /* (s[i]+s[i+1]+1) >> 1 */ s0H = vec_sra(s0H, one); s0L = vec_sra(s0L, one); /* d[i] + ((s[i]+s[i+1]+1)>>1) */ dH = vec_add(dH, s0H); dL = vec_add(dL, s0L); /* (d[i]+((s[i]+s[i+1]+1)>>1)) + 1 */ dH = vec_add(dH, one); dL = vec_add(dL, one); /* ((d[i]+((s[i]+s[i+1]+1)>>1))+1) >> 1 */ dH = vec_sra(dH, one); dL = vec_sra(dL, one); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(dH, dL)); vec_st(vu8(dH), 0, (unsigned char*)d); s += lx; d += lx; } #if 0 for (j=0; j>1)+1)>>1; s += lx; d += lx; } #endif /* }}} */ } /* }}} */ } else /* !addflag */ { /* {{{ */ zero = vec_splat_u8(0); one = vec_splat_u16(1); if (w == 8) { /* {{{ */ eight = vec_splat_u8(8); perm = vec_lvsl(0, (unsigned char*)s); if (((unsigned long)d & 0xf) == 0) { /* {{{ */ for (i = 0; i < h; i++) { lS0 = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS0, lS1, perm); lS1 = vec_slo(lS0, eight); lD = vec_ld(0, (unsigned char*)d); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) s[1-8] */ s1H = vu16(vec_mergeh(zero, lS1)); /* (unsigned short[]) d[8-15] */ dL = vu16(vec_mergel(zero, lD)); /* s[i] + s[i+1] */ s0H = vec_add(s0H, s1H); /* (s[i]+s[i+1]) + 1 */ s0H = vec_add(s0H, one); /* (s[i]+s[i+1]+1) >> 1 */ s0H = vec_sra(s0H, one); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(s0H, dL)); vec_st(vu8(dH), 0, (unsigned char*)d); s += lx; d += lx; } /* }}} */ } else { /* {{{ */ /* d is offset 8 bytes, work on dL (low bytes). */ for (i = 0; i < h; i++) { lS0 = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS0, lS1, perm); lS1 = vec_slo(lS0, eight); lD = vec_ld(0, (unsigned char*)d); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) s[1-8] */ s1H = vu16(vec_mergeh(zero, lS1)); /* (unsigned short[]) d[0-7] */ dH = vu16(vec_mergeh(zero, lD)); /* s[i] + s[i+1] */ s0H = vec_add(s0H, s1H); /* (s[i]+s[i+1]) + 1 */ s0H = vec_add(s0H, one); /* (s[i]+s[i+1]+1) >> 1 */ s0H = vec_sra(s0H, one); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(dH, s0H)); vec_st(vu8(dH), 0, (unsigned char*)d); s += lx; d += lx; } /* }}} */ } /* }}} */ } else /* w == 16 */ { /* {{{ */ perm = vec_lvsl(0, s); perm1 = vec_splat_u8(1); perm1 = vec_add(perm, perm1); for (i = 0; i < h; i++) { lS = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS, lS1, perm); lS1 = vec_perm(lS, lS1, perm1); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) s[8-15] */ s0L = vu16(vec_mergel(zero, lS0)); /* (unsigned short[]) s[1-8] */ s1H = vu16(vec_mergeh(zero, lS1)); /* (unsigned short[]) s[9-16] */ s1L = vu16(vec_mergel(zero, lS1)); /* s[i] + s[i+1] */ s0H = vec_add(s0H, s1H); s0L = vec_add(s0L, s1L); /* (s[i]+s[i+1]) + 1 */ s0H = vec_add(s0H, one); s0L = vec_add(s0L, one); /* (s[i]+s[i+1]+1) >> 1 */ s0H = vec_sra(s0H, one); s0L = vec_sra(s0L, one); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(s0H, s0L)); vec_st(vu8(dH), 0, (unsigned char*)d); s += lx; d += lx; } /* }}} */ } #if 0 for (j=0; j>1; s+= lx; d+= lx; } #endif /* }}} */ } /* }}} */ } } else /* !xh */ { if (yh) { /* (!xh && yh) {{{ */ if (addflag) { /* {{{ */ zero = vec_splat_u8(0); one = vec_splat_u16(1); if (w == 8) { /* {{{ */ perm = vec_lvsl(0, (unsigned char*)s); if (((unsigned long)d & 0xf) == 0) { /* {{{ */ lS0 = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS0, lS1, perm); s += lx; for (i = 0; i < h; i++) { lS2 = vec_ld(0, (unsigned char*)s); lS3 = vec_ld(16, (unsigned char*)s); lS2 = vec_perm(lS2, lS3, perm); lD = vec_ld(0, (unsigned char*)d); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) s+lx[0-7] */ s2H = vu16(vec_mergeh(zero, lS2)); /* (unsigned short[]) d[0-7] */ dH = vu16(vec_mergeh(zero, lD)); /* (unsigned short[]) d[8-15] */ dL = vu16(vec_mergel(zero, lD)); /* s[i] + s[i+lx] */ s0H = vec_add(s0H, s2H); /* (s[i]+s[i+lx]) + 1 */ s0H = vec_add(s0H, one); /* (s[i]+s[i+lx]+1) >> 1 */ s0H = vec_sra(s0H, one); /* d[i] + ((s[i]+s[i+lx]+1)>>1) */ dH = vec_add(dH, s0H); /* (d[i]+((s[i]+s[i+lx]+1)>>1)) + 1 */ dH = vec_add(dH, one); /* ((d[i]+((s[i]+s[i+lx]+1)>>1))+1) >> 1 */ dH = vec_sra(dH, one); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(dH, dL)); vec_st(vu8(dH), 0, (unsigned char*)d); lS0 = lS2; s += lx; d += lx; } /* }}} */ } else { /* {{{ */ /* d is offset 8 bytes, work on dL (low bytes). */ lS0 = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS0, lS1, perm); s += lx; for (i = 0; i < h; i++) { lS2 = vec_ld(0, (unsigned char*)s); lS3 = vec_ld(16, (unsigned char*)s); lS2 = vec_perm(lS2, lS3, perm); lD = vec_ld(0, (unsigned char*)d); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) s+lx[0-7] */ s2H = vu16(vec_mergeh(zero, lS2)); /* (unsigned short[]) d[0-7] */ dH = vu16(vec_mergeh(zero, lD)); /* (unsigned short[]) d[8-15] */ dL = vu16(vec_mergel(zero, lD)); /* s[i] + s[i+lx] */ s0H = vec_add(s0H, s2H); /* (s[i]+s[i+lx]) + 1 */ s0H = vec_add(s0H, one); /* (s[i]+s[i+lx]+1) >> 1 */ s0H = vec_sra(s0H, one); /* d[i] + ((s[i]+s[i+lx]+1)>>1) */ dL = vec_add(dL, s0H); /* (d[i]+((s[i]+s[i+lx]+1)>>1)) + 1 */ dL = vec_add(dL, one); /* ((d[i]+((s[i]+s[i+lx]+1)>>1))+1) >> 1 */ dL = vec_sra(dL, one); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(dH, dL)); vec_st(vu8(dH), 0, (unsigned char*)d); lS0 = lS2; s += lx; d += lx; } /* }}} */ } /* }}} */ } else /* w == 16 */ { /* {{{ */ perm = vec_lvsl(0, s); lS = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS, lS1, perm); s += lx; for (i = 0; i < h; i++) { lS = vec_ld(0, (unsigned char*)s); lS3 = vec_ld(16, (unsigned char*)s); lS2 = vec_perm(lS, lS3, perm); lD = vec_ld(0, (unsigned char*)d); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) s[8-15] */ s0L = vu16(vec_mergel(zero, lS0)); /* (unsigned short[]) s+lx[0-7] */ s2H = vu16(vec_mergeh(zero, lS2)); /* (unsigned short[]) s+lx[8-15] */ s2L = vu16(vec_mergel(zero, lS2)); /* (unsigned short[]) d[0-7] */ dH = vu16(vec_mergeh(zero, lD)); /* (unsigned short[]) d[8-15] */ dL = vu16(vec_mergel(zero, lD)); /* s[i] + s[i+lx] */ s0H = vec_add(s0H, s2H); s0L = vec_add(s0L, s2L); /* (s[i]+s[i+lx]) + 1 */ s0H = vec_add(s0H, one); s0L = vec_add(s0L, one); /* (s[i]+s[i+lx]+1) >> 1 */ s0H = vec_sra(s0H, one); s0L = vec_sra(s0L, one); /* d[i] + ((s[i]+s[i+lx]+1)>>1) */ dH = vec_add(dH, s0H); dL = vec_add(dL, s0L); /* (d[i]+((s[i]+s[i+lx]+1)>>1)) + 1 */ dH = vec_add(dH, one); dL = vec_add(dL, one); /* ((d[i]+((s[i]+s[i+lx]+1)>>1))+1) >> 1 */ dH = vec_sra(dH, one); dL = vec_sra(dL, one); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(dH, dL)); vec_st(vu8(dH), 0, (unsigned char*)d); lS0 = lS2; s += lx; d += lx; } /* }}} */ } #if 0 for (j=0; j>1)+1)>>1; s+= lx; d+= lx; } #endif /* }}} */ } else /* !addflag */ { /* {{{ */ zero = vec_splat_u8(0); one = vec_splat_u16(1); if (w == 8) { /* {{{ */ perm = vec_lvsl(0, (unsigned char*)s); if (((unsigned long)d & 0xf) == 0) { /* {{{ */ lS0 = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS0, lS1, perm); s += lx; for (i = 0; i < h; i++) { lS2 = vec_ld(0, (unsigned char*)s); lS3 = vec_ld(16, (unsigned char*)s); lS2 = vec_perm(lS2, lS3, perm); lD = vec_ld(0, (unsigned char*)d); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) s+lx[0-7] */ s2H = vu16(vec_mergeh(zero, lS2)); /* (unsigned short[]) d[8-15] */ dL = vu16(vec_mergel(zero, lD)); /* s[i] + s[i+lx] */ s0H = vec_add(s0H, s2H); /* (s[i]+s[i+lx]) + 1 */ s0H = vec_add(s0H, one); /* (s[i]+s[i+lx]+1) >> 1 */ s0H = vec_sra(s0H, one); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(s0H, dL)); vec_st(vu8(dH), 0, (unsigned char*)d); lS0 = lS2; s += lx; d += lx; } /* }}} */ } else { /* {{{ */ /* d is offset 8 bytes, work on dL (low bytes). */ lS0 = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS0, lS1, perm); s += lx; for (i = 0; i < h; i++) { lS2 = vec_ld(0, (unsigned char*)s); lS3 = vec_ld(16, (unsigned char*)s); lS2 = vec_perm(lS2, lS3, perm); lD = vec_ld(0, (unsigned char*)d); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) s+lx[0-7] */ s2H = vu16(vec_mergeh(zero, lS2)); /* (unsigned short[]) d[0-7] */ dH = vu16(vec_mergeh(zero, lD)); /* s[i] + s[i+lx] */ s0H = vec_add(s0H, s2H); /* (s[i]+s[i+lx]) + 1 */ s0H = vec_add(s0H, one); /* (s[i]+s[i+lx]+1) >> 1 */ s0H = vec_sra(s0H, one); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(dH, s0H)); vec_st(vu8(dH), 0, (unsigned char*)d); lS0 = lS2; s += lx; d += lx; } /* }}} */ } /* }}} */ } else /* w == 16 */ { /* {{{ */ perm = vec_lvsl(0, s); lS = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS, lS1, perm); s += lx; for (i = 0; i < h; i++) { lS = vec_ld(0, (unsigned char*)s); lS3 = vec_ld(16, (unsigned char*)s); lS2 = vec_perm(lS, lS3, perm); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) s[8-15] */ s0L = vu16(vec_mergel(zero, lS0)); /* (unsigned short[]) s+lx[0-7] */ s2H = vu16(vec_mergeh(zero, lS2)); /* (unsigned short[]) s+lx[8-15] */ s2L = vu16(vec_mergel(zero, lS2)); /* s[i] + s[i+lx] */ s0H = vec_add(s0H, s2H); s0L = vec_add(s0L, s2L); /* (s[i]+s[i+lx]) + 1 */ s0H = vec_add(s0H, one); s0L = vec_add(s0L, one); /* (s[i]+s[i+lx]+1) >> 1 */ s0H = vec_sra(s0H, one); s0L = vec_sra(s0L, one); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(s0H, s0L)); vec_st(vu8(dH), 0, (unsigned char*)d); lS0 = lS2; s += lx; d += lx; } /* }}} */ } #if 0 for (j=0; j>1; s+= lx; d+= lx; } #endif /* }}} */ } /* }}} */ } else /* !yh */ { /* (!xh && !yh) {{{ */ if (addflag) { /* {{{ */ zero = vec_splat_u8(0); one = vec_splat_u16(1); if (w == 8) { /* {{{ */ perm = vec_lvsl(0, (unsigned char*)s); if (((unsigned long)d & 0xf) == 0) { for (i = 0; i < h; i++) { lS0 = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS0, lS1, perm); lD = vec_ld(0, (unsigned char*)d); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) d[0-7] */ dH = vu16(vec_mergeh(zero, lD)); /* (unsigned short[]) d[8-15] */ dL = vu16(vec_mergel(zero, lD)); /* d[i] + s[i] */ dH = vec_add(dH, s0H); /* (d[i]+s[i]) + 1 */ dH = vec_add(dH, one); /* (d[i]+s[i]+1) >> 1 */ dH = vec_sra(dH, one); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(dH, dL)); vec_st(vu8(dH), 0, (unsigned char*)d); s += lx; d += lx; } /* }}} */ } else { /* {{{ */ /* d is offset 8 bytes, work on dL (low bytes). */ for (i = 0; i < h; i++) { lS0 = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS0, lS1, perm); lD = vec_ld(0, (unsigned char*)d); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) d[0-7] */ dH = vu16(vec_mergeh(zero, lD)); /* (unsigned short[]) d[8-15] */ dL = vu16(vec_mergel(zero, lD)); /* d[i] + s[i] */ dL = vec_add(dL, s0H); /* (d[i]+s[i]) + 1 */ dL = vec_add(dL, one); /* (d[i]+s[i]+1) >> 1 */ dL = vec_sra(dL, one); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(dH, dL)); vec_st(vu8(dH), 0, (unsigned char*)d); s += lx; d += lx; } /* }}} */ } } else /* w == 16 */ { /* {{{ */ perm = vec_lvsl(0, s); for (i = 0; i < h; i++) { lS0 = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS0, lS1, perm); lD = vec_ld(0, (unsigned char*)d); /* (unsigned short[]) s[0-7] */ s0H = vu16(vec_mergeh(zero, lS0)); /* (unsigned short[]) s[8-15] */ s0L = vu16(vec_mergel(zero, lS0)); /* (unsigned short[]) d[0-7] */ dH = vu16(vec_mergeh(zero, lD)); /* (unsigned short[]) d[8-15] */ dL = vu16(vec_mergel(zero, lD)); /* d[i] + s[i] */ dH = vec_add(dH, s0H); dL = vec_add(dL, s0L); /* (d[i]+s[i]) + 1 */ dH = vec_add(dH, one); dL = vec_add(dL, one); /* (d[i]+s[i]+1) >> 1 */ dH = vec_sra(dH, one); dL = vec_sra(dL, one); /* (unsigned char[]) d[0-7], d[8-15] */ dH = vu16(vec_packsu(dH, dL)); vec_st(vu8(dH), 0, (unsigned char*)d); s += lx; d += lx; } /* }}} */ } #if 0 for (j=0; j>1; s+= lx; d+= lx; } #endif /* }}} */ } else /* !addflag */ { /* {{{ */ if (w == 8) { /* {{{ */ /* w / 4, int size copying instead of byte size */ for (j = 0; j < h; j++) { *((unsigned int*)d) = *((unsigned int*)s); *((unsigned int*)d+1) = *((unsigned int*)s+1); s += lx; d += lx; } /* }}} */ } else /* w == 16 */ { /* {{{ */ perm = vec_lvsl(0, s); for (i = 0; i < h; i++) { lS0 = vec_ld(0, (unsigned char*)s); lS1 = vec_ld(16, (unsigned char*)s); lS0 = vec_perm(lS0, lS1, perm); vec_st(vu8(lS0), 0, (unsigned char*)d); s += lx; d += lx; } /* }}} */ } /* }}} */ } /* }}} */ } } AMBER_STOP; } #if ALTIVEC_TEST_FUNCTION(pred_comp) /* {{{ */ # ifdef ALTIVEC_VERIFY void pred_comp_altivec_verify(PRED_COMP_PDECL) { int i, j; uint8_t *s, *d; unsigned long checksum1, checksum2; /* dst is used as input and output, it must be saved/restored */ uint8_t dstcpy[16][16]; uint8_t dc; /* save dst */ d = dst + lx*y + x; for (j = 0; j < h; j++) { for (i = 0; i < w; i++) { dstcpy[j][i] = d[i]; } d += lx; } pred_comp_altivec(PRED_COMP_ARGS); d = dst + lx*y + x; for (checksum1 = j = 0; j < h; j++) { for (i = 0; i < w; i++) { checksum1 += d[i]; } d += lx; } /* restore/swap dst & dstcpy */ d = dst + lx*y + x; for (j = 0; j < h; j++) { for (i = 0; i < w; i++) { dc = d[i]; d[i] = dstcpy[j][i]; dstcpy[j][i] = dc; } d += lx; } ALTIVEC_TEST_WITH(pred_comp)(PRED_COMP_ARGS); d = dst + lx*y + x; for (checksum2 = j = 0; j < h; j++) { for (i = 0; i < w; i++) { checksum2 += d[i]; } d += lx; } if (checksum1 != checksum2) { s = src + lx*(y+(dy>>1)) + (x+(dx>>1)); d = dst + lx*y + x; mjpeg_debug("pred_comp(" PRED_COMP_PFMT ") s=0x%X, d=0x%x", PRED_COMP_ARGS, s, d); mjpeg_debug("pred_comp: checksums differ %d != %d", checksum1, checksum2); /* d = dst + lx*y + x; */ for (j = 0; j < h; j++) { for (i = 0; i < w; i++) { if (dstcpy[j][i] != d[i]) { mjpeg_debug("pred_comp: dst[%d][%d] %d != %d", j, i, dstcpy[j][i], d[i]); } } d += lx; } } } # else ALTIVEC_TEST(pred_comp, void, (PRED_COMP_PDECL), PRED_COMP_PFMT, PRED_COMP_ARGS); # endif #endif /* }}} */ /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/README0000644000175000017500000000027207474475200017672 0ustar glowwormglowwormAltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder ----------------------------------------------------------------------------- TODO: Write instructions for developers. mjpegtools-2.1.0/utils/altivec/amber.h0000644000175000017500000000565107565610177020264 0ustar glowwormglowworm/* amber.h, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef ALTIVEC_AMBER #ifndef AMBER_MAX_TRACES #define AMBER_MAX_TRACES 1 #endif void amber_symtrace(const char *name); #define ALTIVEC_TEST_AMBER(name,ret,defargs,pfmt,args) /* {{{ */ \ ret name##_altivec_amber defargs { \ static int trace_count = 0; \ register long sigreg; \ AVRETDECL(ret,retval); \ if (trace_count < AMBER_MAX_TRACES) { \ trace_count++; \ asm volatile ("mfspr %0, 1023" : "=r" (sigreg)); /* start amber */ \ AVRETSET(ret,retval,ALTIVEC_TEST_WITH(name)(args)); \ asm volatile ("mfspr %0, 1023" : "=r" (sigreg)); /* stop amber */ \ amber_symtrace(AVSTR(ALTIVEC_TEST_WITH(name))); \ } else { \ AVRETSET(ret,retval,ALTIVEC_TEST_WITH(name)(args)); \ } \ AVRETURN(ret,retval); \ } /* }}} */ #elif defined(AMBER_ENABLE) && !defined(ALTIVEC_VERIFY) #ifndef AMBER_MAX_TRACES #define AMBER_MAX_TRACES 1 #endif #ifndef AMBER_MAX_EXIT #define AMBER_MAX_EXIT 1 #endif long amber_start(const char *file, int line, int *trace_count, int max_traces); long amber_stop(const char *file, int line, int *trace_count, int max_traces, int max_exit); static int amber_trace_count = 0; #define AMBER_START amber_start(__FILE__, __LINE__, &amber_trace_count, \ AMBER_MAX_TRACES) #define AMBER_STOP amber_stop(__FILE__, __LINE__, &amber_trace_count, \ AMBER_MAX_TRACES, AMBER_MAX_EXIT) #endif #ifndef AMBER_START # define AMBER_START #endif #ifndef AMBER_STOP # define AMBER_STOP #endif mjpegtools-2.1.0/utils/altivec/add_pred.c0000644000175000017500000001547110464771010020716 0ustar glowwormglowworm/* add_pred.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_transform.h" #include "vectorize.h" #include "../mjpeg_logging.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif #define ADD_PRED_PDECL uint8_t *pred, uint8_t *cur, int lx, int16_t *blk #define ADD_PRED_ARGS pred, cur, lx, blk #define ADD_PRED_PFMT "pred=0x%X, cur=0x%X, lx=%d, blk=0x%X" /* * add prediction and prediction error, saturate to 0...255 * pred % 8 == 0 * cur % 8 == 0 * lx % 16 == 0 * blk % 16 == 0 */ void add_pred_altivec(ADD_PRED_PDECL) { #ifdef ALTIVEC_DST unsigned int dst; #endif uint8_t *pCA, *pCB, *pPA, *pPB; int16_t *pBA, *pBB; vector unsigned char zero; vector unsigned char predA, predB, curA, curB; vector signed short blkA, blkB; #ifdef ALTIVEC_VERIFY if (NOT_VECTOR_ALIGNED(lx)) mjpeg_error_exit1("add_pred: lx %% 16 != 0, (%d)", lx); if (NOT_VECTOR_ALIGNED(blk)) mjpeg_error_exit1("add_pred: blk %% 16 != 0, (%d)", blk); #ifdef ALTIVEC_DST if (lx & (~0xffff) != 0) mjpeg_error_exit1("add_pred: lx=%d > vec_dst range", lx); #endif if (((unsigned long)pred & 0xf) != ((unsigned long)cur & 0xf)) mjpeg_error_exit1("add_pred: (pred(0x%X) %% 16) != (cur(0x%X) %% 16)", pred, cur); if ((((unsigned long)pred) & 0x7) != 0) mjpeg_error_exit1("add_pred: pred %% 8 != 0, (0x%X)", pred); if ((((unsigned long)cur) & 0x7) != 0) mjpeg_error_exit1("add_pred: cur %% 8 != 0, (0x%X)", cur); #endif /* MACROS expand differently depending on input */ #define ABBA(symbol,ab) _ABBA(ABBA_##ab,symbol) /* {{{ */ #define _ABBA(abba_ab,symbol) abba_ab(symbol) #define ABBA_A(symbol) symbol##B #define ABBA_B(symbol) symbol##A /* }}} */ #define HLLH(symbol,hl) _HLLH(HLLH_##hl,symbol) /* {{{ */ #define _HLLH(hllh_hl,symbol) hllh_hl(symbol) #define HLLH_h(symbol) symbol##l #define HLLH_l(symbol) symbol##h /* }}} */ #define PACKSU(hl,st,ld) _PACKSU(PACKSU_##hl,st,ld) /* {{{ */ #define _PACKSU(psu,st,ld) psu(st,ld) #define PACKSU_h(st,ld) vec_packsu(st,ld) #define PACKSU_l(st,ld) vec_packsu(ld,st) /* }}} */ #define PERFORM_ITERATION(hl,ab,iter) /* iter {{{ */ \ pred##ab = vec_merge##hl(zero, pred##ab); \ cur##ab = HLLH(vec_merge,hl)(zero, cur##ab); \ blk##ab = vec_add(blk##ab, vs16(pred##ab)); \ blk##ab = vec_max(blk##ab, vs16(zero)); \ cur##ab = PACKSU(hl, vu16(blk##ab), vu16(cur##ab)); \ vec_st(cur##ab, 0, pC##ab); \ /* }}} */ #define PREPARE_ITERATION(hl,ab,iter) /* iter {{{ */ \ pP##ab = ABBA(pP,ab) + lx; \ pC##ab = ABBA(pC,ab) + lx; \ pB##ab = ABBA(pB,ab) + 8; \ pred##ab = vec_ld(0, pP##ab); \ cur##ab = vec_ld(0, pC##ab); \ blk##ab = vec_ld(0, pB##ab); \ /* }}} */ #define NO_RESCHEDULE asm volatile ("") AMBER_START; pPA = pred; pCA = cur; pBA = blk; #ifdef ALTIVEC_DST dst = 0x01080000 | lx; vec_dst(pPA, dst, 0); vec_dst(pCA, dst, 1); dst = 0x01080010; vec_dst(pBA, dst, 2); #endif predA = vec_ld(0, pPA); curA = vec_ld(0, pCA); NO_RESCHEDULE; pPB = pPA + lx; NO_RESCHEDULE; blkA = vec_ld(0, pBA); NO_RESCHEDULE; pCB = pCA + lx; NO_RESCHEDULE; predB = vec_ld(0, pPB); NO_RESCHEDULE; pBB = pBA + 8; NO_RESCHEDULE; curB = vec_ld(0, pCB); NO_RESCHEDULE; zero = vec_splat_u8(0); NO_RESCHEDULE; blkB = vec_ld(0, pBB); if (VECTOR_ALIGNED(pPA)) { PERFORM_ITERATION(h,A,0); PREPARE_ITERATION(h,A,2); /* prepare next A iteration */ PERFORM_ITERATION(h,B,1); PREPARE_ITERATION(h,B,3); /* prepare next B iteration */ PERFORM_ITERATION(h,A,2); PREPARE_ITERATION(h,A,4); PERFORM_ITERATION(h,B,3); PREPARE_ITERATION(h,B,5); PERFORM_ITERATION(h,A,4); PREPARE_ITERATION(h,A,6); PERFORM_ITERATION(h,B,5); PREPARE_ITERATION(h,B,7); PERFORM_ITERATION(h,A,6); PERFORM_ITERATION(h,B,7); } else { PERFORM_ITERATION(l,A,0); PREPARE_ITERATION(l,A,2); /* prepare next A iteration */ PERFORM_ITERATION(l,B,1); PREPARE_ITERATION(l,B,3); /* prepare next B iteration */ PERFORM_ITERATION(l,A,2); PREPARE_ITERATION(l,A,4); PERFORM_ITERATION(l,B,3); PREPARE_ITERATION(l,B,5); PERFORM_ITERATION(l,A,4); PREPARE_ITERATION(l,A,6); PERFORM_ITERATION(l,B,5); PREPARE_ITERATION(l,B,7); PERFORM_ITERATION(l,A,6); PERFORM_ITERATION(l,B,7); } #ifdef ALTIVEC_DST vec_dssall(); #endif AMBER_STOP; } #if ALTIVEC_TEST_FUNCTION(add_pred) /* {{{ */ # ifdef ALTIVEC_VERIFY void add_pred_altivec_verify(ADD_PRED_PDECL) { int i, j; unsigned long checksum1, checksum2; uint8_t *pcur; uint8_t curcpy[8][8]; add_pred_altivec(ADD_PRED_ARGS); pcur = cur; checksum1 = 0; for (j = 0; j < 8; j++) { for (i = 0; i < 8; i++) { checksum1 += pcur[i]; curcpy[j][i] = pcur[i]; } pcur += lx; } ALTIVEC_TEST_WITH(add_pred)(ADD_PRED_ARGS); pcur = cur; checksum2 = 0; for (j = 0; j < 8; j++) { for (i = 0; i < 8; i++) checksum2 += pcur[i]; pcur += lx; } if (checksum1 != checksum2) { mjpeg_debug("add_pred(" ADD_PRED_PFMT ")", ADD_PRED_ARGS); mjpeg_debug("add_pred: checksums differ %d != %d", checksum1, checksum2); pcur = cur; checksum1 = 0; for (j = 0; j < 8; j++) { for (i = 0; i < 8; i++) { if (curcpy[j][i] != pcur[i]) mjpeg_debug("add_pred: cur[%d][%d] %d != %d", j, i, curcpy[j][i], pcur[i]); } pcur += lx; } } } # else ALTIVEC_TEST(add_pred, void, (ADD_PRED_PDECL), ADD_PRED_PFMT, ADD_PRED_ARGS); # endif #endif /* }}} */ /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/quantize.c0000644000175000017500000000741110532365710021011 0ustar glowwormglowworm/* quantize.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "cpu_accel.h" #include "altivec_quantize.h" #include "vectorize.h" #include "../mjpeg_logging.h" void enable_altivec_quantization(struct QuantizerCalls *calls, int opt_mpeg1) { int d_quant_nonintra, d_weight_intra, d_weight_nonintra, d_iquant_intra; int d_iquant_nonintra; d_quant_nonintra = disable_simd("quant_nonintra"); d_weight_intra = disable_simd("quant_weight_intra"); d_weight_nonintra = disable_simd("quant_weight_nonintra"); d_iquant_intra = disable_simd("iquant_intra"); d_iquant_nonintra = disable_simd("iquant_nonintra"); #if ALTIVEC_TEST_QUANTIZE # if defined(ALTIVEC_BENCHMARK) mjpeg_info("SETTING AltiVec BENCHMARK for QUANTIZER!"); # elif defined(ALTIVEC_VERIFY) mjpeg_info("SETTING AltiVec VERIFY for QUANTIZER!"); # endif #else mjpeg_info("SETTING AltiVec for QUANTIZER!"); #endif #if ALTIVEC_TEST_FUNCTION(quant_non_intra) calls->pquant_non_intra = ALTIVEC_TEST_SUFFIX(quant_non_intra); #else if (d_quant_nonintra == 0) calls->pquant_non_intra = quant_non_intra_altivec; #endif #if ALTIVEC_TEST_FUNCTION(quant_weight_coeff_intra) calls->pquant_weight_coeff_intra = ALTIVEC_TEST_SUFFIX(quant_weight_coeff_intra); #else if (d_weight_intra == 0) calls->pquant_weight_coeff_intra = quant_weight_coeff_intra_altivec; #endif #if ALTIVEC_TEST_FUNCTION(quant_weight_coeff_inter) calls->pquant_weight_coeff_inter = ALTIVEC_TEST_SUFFIX(quant_weight_coeff_inter); #else if (d_weight_nonintra == 0) calls->pquant_weight_coeff_inter = quant_weight_coeff_inter_altivec; #endif if (opt_mpeg1) { #if ALTIVEC_TEST_FUNCTION(iquant_non_intra_m1) calls->piquant_non_intra = ALTIVEC_TEST_SUFFIX(iquant_non_intra_m1); #else if (d_iquant_nonintra == 0) calls->piquant_non_intra = iquant_non_intra_m1_altivec; #endif #if ALTIVEC_TEST_FUNCTION(iquant_intra_m1) calls->piquant_intra = ALTIVEC_TEST_SUFFIX(iquant_intra_m1); #else if (d_iquant_intra == 0) calls->piquant_intra = iquant_intra_m1_altivec; #endif } else { #if ALTIVEC_TEST_FUNCTION(iquant_non_intra_m2) calls->piquant_non_intra = ALTIVEC_TEST_SUFFIX(iquant_non_intra_m2); #else if (d_iquant_nonintra == 0) calls->piquant_non_intra = iquant_non_intra_m2_altivec; #endif #if ALTIVEC_TEST_FUNCTION(iquant_intra_m2) calls->piquant_intra = ALTIVEC_TEST_SUFFIX(iquant_intra_m2); #else if (d_iquant_intra == 0) calls->piquant_intra = iquant_intra_m2_altivec; #endif } if (d_quant_nonintra) mjpeg_info(" Disabling quant_non_intra"); if (d_iquant_intra) mjpeg_info(" Disabling iquant_intra"); if (d_iquant_nonintra) mjpeg_info(" Disabling iquant_nonintra"); if (d_weight_intra) mjpeg_info(" Disabling quant_weight_intra"); if (d_weight_nonintra) mjpeg_info(" Disabling quant_weight_nonintra"); } mjpegtools-2.1.0/utils/altivec/altivec_motion.h0000644000175000017500000001052407664066230022200 0ustar glowwormglowworm/* altivec_motion.h, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "../motionsearch.h" #include "altivec_conf.h" #define ALTIVEC_TEST_MOTION /* {{{ */ \ ( ( defined(ALTIVEC_BENCHMARK) || defined(ALTIVEC_VERIFY) ) && \ ( ALTIVEC_TEST_FUNCTION(build_sub44_mests) || \ ALTIVEC_TEST_FUNCTION(build_sub22_mests) || \ ALTIVEC_TEST_FUNCTION(find_best_one_pel) || \ ALTIVEC_TEST_FUNCTION(sub_mean_reduction) || \ ALTIVEC_TEST_FUNCTION(sad_00) || \ ALTIVEC_TEST_FUNCTION(sad_01) || \ ALTIVEC_TEST_FUNCTION(sad_10) || \ ALTIVEC_TEST_FUNCTION(sad_11) || \ ALTIVEC_TEST_FUNCTION(bsad) || \ ALTIVEC_TEST_FUNCTION(sumsq) || \ ALTIVEC_TEST_FUNCTION(sumsq_sub22) || \ ALTIVEC_TEST_FUNCTION(bsumsq) || \ ALTIVEC_TEST_FUNCTION(bsumsq_sub22) || \ ALTIVEC_TEST_FUNCTION(subsample_image) || \ ALTIVEC_TEST_FUNCTION(variance) ) ) \ /* }}} */ #ifdef __cplusplus extern "C" { #endif void enable_altivec_motion(void); ALTIVEC_FUNCTION(build_sub44_mests, int, ( me_result_set *sub44set, int ilow, int jlow, int ihigh, int jhigh, int i0, int j0, int null_ctl_sad, uint8_t *s44org, uint8_t *s44blk, int qrowstride, int qh, int reduction )); ALTIVEC_FUNCTION(build_sub22_mests, int, ( me_result_set *sub44set, me_result_set *sub22set, int i0, int j0, int ihigh, int jhigh, int null_ctl_sad, uint8_t *s22org, uint8_t *s22blk, int frowstride, int fh, int reduction )); ALTIVEC_FUNCTION(find_best_one_pel, void, ( me_result_set *sub22set, uint8_t *org, uint8_t *blk, int i0, int j0, int ihigh, int jhigh, int rowstride, int h, me_result_s *best_so_far )); ALTIVEC_FUNCTION(sub_mean_reduction, void, (me_result_set *matchset, int times, int *minweight_res)); ALTIVEC_FUNCTION(sad_00,int, (uint8_t *blk1, uint8_t *blk2, int rowstride, int h, int distlim)); ALTIVEC_FUNCTION(sad_01, int, (uint8_t *blk1, uint8_t *blk2, int rowstride, int h)); ALTIVEC_FUNCTION(sad_10, int, (uint8_t *blk1, uint8_t *blk2, int rowstride, int h)); ALTIVEC_FUNCTION(sad_11, int, (uint8_t *blk1, uint8_t *blk2, int rowstride, int h)); ALTIVEC_FUNCTION(bsad, int, (uint8_t *pf, uint8_t *pb, uint8_t *p2, int rowstride, int hxf, int hyf, int hxb, int hyb, int h)); ALTIVEC_FUNCTION(sumsq, int, (uint8_t *blk1, uint8_t *blk2, int rowstride, int hx, int hy, int h)); ALTIVEC_FUNCTION(sumsq_sub22, int, (uint8_t *blk1, uint8_t *blk2, int rowstride, int h)); ALTIVEC_FUNCTION(bsumsq, int, (uint8_t *pf, uint8_t *pb, uint8_t *p2, int rowstride, int hxf, int hyf, int hxb, int hyb, int h)); ALTIVEC_FUNCTION(bsumsq_sub22, int, (uint8_t *blk1f, uint8_t *blk1b, uint8_t *blk2, int rowstride, int h)); ALTIVEC_FUNCTION(subsample_image, void, (uint8_t *image, int rowstride, uint8_t *sub22_image, uint8_t *sub44_image)); ALTIVEC_FUNCTION(variance, void, (uint8_t *p, int size, int rowstride, unsigned int *p_var, unsigned int *p_mean)); #ifdef __cplusplus } #endif mjpegtools-2.1.0/utils/altivec/find_best_one_pel.c0000644000175000017500000003540410464771010022610 0ustar glowwormglowworm/* find_best_one_pel.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include #include "altivec_motion.h" #include "vectorize.h" #include "../mjpeg_logging.h" /* #define AMBER_ENABLE */ /* #define AMBER_MAX_TRACES 10 */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif /* * Search for the best 1-pel match within 1-pel of a good 2*2-pel * * Input requirements: * a) ref is always vector aligned * b) rowstride is a multiple of 16 * c) h is either 8 or 16 * */ #define FIND_BEST_ONE_PEL_PDECL /* {{{ */ \ me_result_set *sub22set, \ uint8_t *org, uint8_t *ref, \ int i0, int j0, \ int ihigh, int jhigh, \ int rowstride, int h, \ me_result_s *best_so_far \ /* }}} */ #define FIND_BEST_ONE_PEL_ARGS /* {{{ */ \ sub22set, org, ref, \ i0, j0, ihigh, jhigh, \ rowstride, h, best_so_far \ /* }}} */ /* void find_best_one_pel_altivec(FIND_BEST_ONE_PEL_PDECL) {{{ */ #if defined(ALTIVEC_VERIFY) && ALTIVEC_TEST_FUNCTION(find_best_one_pel) #define VERIFY_FIND_BEST_ONE_PEL static void verify_sads(uint8_t *blk1, uint8_t *blk2, int stride, int h, signed int *sads, int count); static void _find_best_one_pel_altivec(FIND_BEST_ONE_PEL_PDECL, int verify); void find_best_one_pel_altivec(FIND_BEST_ONE_PEL_PDECL) { _find_best_one_pel_altivec(FIND_BEST_ONE_PEL_ARGS, 0 /* no verify */); } static void _find_best_one_pel_altivec(FIND_BEST_ONE_PEL_PDECL, int verify) #else void find_best_one_pel_altivec(FIND_BEST_ONE_PEL_PDECL) #endif /* }}} */ { int i; uint8_t *orgblk; me_result_s *sub22mests; int len; uint8_t *pblk, *pref; int x, y; me_result_s mres; vector unsigned char t0, t1, t2; vector unsigned char l0, l1; vector unsigned char perm0, perm1; vector unsigned char blk1_0, blk1_1; vector unsigned char vref; vector unsigned int zero; vector unsigned int sad00, sad10, sad01, sad11; vector unsigned int sads; vector unsigned int minsad; vector bool int minsel; vector signed char xy; vector signed char xylim; vector signed char minxy; vector signed char xy11; vector unsigned char xint, yint; union { vector unsigned int _align16; struct { me_result_s xylim; } init; me_result_s xy; me_result_s best; } vio; #ifdef ALTIVEC_DST DataStreamControl dsc; #endif #ifdef VERIFY_FIND_BEST_ONE_PEL vector signed int versads; #endif #ifdef ALTIVEC_VERIFY if (NOT_VECTOR_ALIGNED(org)) mjpeg_error_exit1("find_best_one_pel: org %% 16 != 0, (0x%X)", org); if (NOT_VECTOR_ALIGNED(ref)) mjpeg_error_exit1("find_best_one_pel: ref %% 16 != 0, (0x%X)", ref); if (NOT_VECTOR_ALIGNED(rowstride)) mjpeg_error_exit1("find_best_one_pel: rowstride %% 16 != 0, (%d)", rowstride); #endif if (h != 8 && h != 16) mjpeg_error_exit1("find_best_one_pel: h != [8|16], (%d)", h); AMBER_START; len = sub22set->len; if (len < 1) { /* sub22set->len is sometimes zero. */ best_so_far->weight = 255*255; /* we can save a lot of effort if we */ return; /* stop short. */ } #ifdef ALTIVEC_DST dsc.control = DATA_STREAM_CONTROL(1,0,0); dsc.block.count = h; dsc.block.stride = rowstride; vec_dst(ref, dsc.control, 0); /* increase size to 2 and increment count */ dsc.control += DATA_STREAM_CONTROL(1,1,0); #endif xy11 = (vector signed char)VCONST(0,0,0,0, 0,0,1,0, 0,0,0,1, 0,0,1,1); mres.weight = 0; /* weight must be zero */ mres.x = ihigh - i0; /* x <= xylim.x */ mres.y = jhigh - j0; /* y <= xylim.y */ vio.init.xylim = mres; yint = vec_lvsl(0, (unsigned char*)0); xint = vu8(vec_splat_u32(0xf)); xint = vec_add(xint, yint /* lvsl */ ); yint = vu8(vec_splat_u32(1)); yint = vec_add(yint, xint); /* initialize to zero */ zero = vec_splat_u32(0); xylim = vec_ld(0, (signed char*) &vio.init.xylim); xylim = vs8(vec_splat(vu32(xylim), 0)); minsad = vu32(vec_splat_s8(-1)); sub22mests = sub22set->mests; do { mres = *sub22mests; x = mres.x; y = mres.y; orgblk = org + (i0 + x) + rowstride*(j0 + y); #ifdef ALTIVEC_DST vec_dst(orgblk, dsc.control, 1); #endif mres.weight = 0; /* weight must be zero */ vio.xy = mres; sub22mests++; /* orgblk alignment should always be a multiple of 2 {0,2,4,6,8,A,C,E} * this is important to avoid the edge case where (orgblk&15)==15 */ if (((unsigned int)orgblk & 1) != 0) mjpeg_warn("find_best_one_pel: orgblk %% 2 != 0 (0x%X)", orgblk); /* calculate SAD for macroblocks: * orgblk(0, 0), orgblk(+1, 0), * orgblk(0,+1), orgblk(+1,+1) */ /* initialize to sad vectors to zero {{{ */ sad00 = vec_splat_u32(0); sad10 = vec_splat_u32(0); sad01 = vec_splat_u32(0); sad11 = vec_splat_u32(0); /* }}} */ pblk = orgblk; /* always aligned by 2 {0,2,4,6,8,A,C,E} */ l0 = vec_ld(0, pblk); l1 = vec_ld(16, pblk); pref = ref; vref = vec_ld(0, pref); perm0 = vec_lvsl(0, pblk); perm1 = vec_splat_u8(1); perm1 = vec_add(perm0, perm1); blk1_0 = vec_perm(l0, l1, perm0); blk1_1 = vec_perm(l0, l1, perm1); i = h - 1; do { /* start loading next */ pblk += rowstride; l0 = vec_ld(0, pblk); l1 = vec_ld(16, pblk); t0 = vec_max(blk1_0, vref); t1 = vec_min(blk1_0, vref); t2 = vec_sub(t0, t1); sad00 = vec_sum4s(t2, sad00); t0 = vec_max(blk1_1, vref); t1 = vec_min(blk1_1, vref); t2 = vec_sub(t0, t1); sad10 = vec_sum4s(t2, sad10); blk1_0 = vec_perm(l0, l1, perm0); blk1_1 = vec_perm(l0, l1, perm1); t0 = vec_max(blk1_0, vref); t1 = vec_min(blk1_0, vref); t2 = vec_sub(t0, t1); sad01 = vec_sum4s(t2, sad01); t0 = vec_max(blk1_1, vref); t1 = vec_min(blk1_1, vref); pref += rowstride; vref = vec_ld(0, pref); t2 = vec_sub(t0, t1); sad11 = vec_sum4s(t2, sad11); } while (--i); /* start loading last */ pblk += rowstride; l0 = vec_ld(0, pblk); l1 = vec_ld(16, pblk); t0 = vec_max(blk1_0, vref); t1 = vec_min(blk1_0, vref); t2 = vec_sub(t0, t1); sad00 = vec_sum4s(t2, sad00); t0 = vec_max(blk1_1, vref); t1 = vec_min(blk1_1, vref); t2 = vec_sub(t0, t1); sad10 = vec_sum4s(t2, sad10); blk1_0 = vec_perm(l0, l1, perm0); blk1_1 = vec_perm(l0, l1, perm1); t0 = vec_max(blk1_0, vref); t1 = vec_min(blk1_0, vref); t2 = vec_sub(t0, t1); sad01 = vec_sum4s(t2, sad01); t0 = vec_max(blk1_1, vref); t1 = vec_min(blk1_1, vref); t2 = vec_sub(t0, t1); sad11 = vec_sum4s(t2, sad11); /* calculate final sums {{{ */ sad00 = vu32(vec_sums(vs32(sad00), vs32(zero))); sad10 = vu32(vec_sums(vs32(sad10), vs32(zero))); sad01 = vu32(vec_sums(vs32(sad01), vs32(zero))); sad11 = vu32(vec_sums(vs32(sad11), vs32(zero))); /* }}} */ /* sads = {sad00, sad10, sad01, sad11} {{{ */ sad00 = vu32(vec_mergel(vu32(sad00), vu32(sad01))); sad10 = vu32(vec_mergel(vu32(sad10), vu32(sad11))); sads = vu32(vec_mergel(vu32(sad00), vu32(sad10))); /* }}} */ #ifdef VERIFY_FIND_BEST_ONE_PEL /* {{{ */ if (verify) { vec_st(sads, 0, (unsigned int*)&versads); verify_sads(orgblk, ref, rowstride, h, (signed int*)&versads, 4); } #endif /* }}} */ /* add penalty, clip xy, arrange into me_result_s ... {{{ */ { xy = vec_ld(0, (signed char*) &vio.xy); xy = vs8(vec_splat(vu32(xy), 0)); /* splat vio.xy */ /* add distance penalty {{{ */ /* penalty = (abs(x) + abs(y)) << 3 */ { vector signed char xyabs; vector unsigned int xxxx, yyyy; vector unsigned int penalty; /* (abs(x),abs(y)) */ xyabs = vec_subs(vs8(zero), xy); xyabs = vec_max(xyabs, xy); /* xxxx = (x, x, x, x), yyyy = (y, y, y, y) * (0,0,x,y, 0,0,x,y, 0,0,x,y, 0,0,x,y) |/- permute vector -\| * (0,0,0,x, 0,0,0,x, 0,0,0,x, 0,0,0,x) |lvsl+(0x0000000F,...)| * (0,0,0,y, 0,0,0,y, 0,0,0,y, 0,0,0,y) |lvsl+(0x00000010,...)| */ xxxx = vu32(vec_perm(vs8(zero), xyabs, xint)); yyyy = vu32(vec_perm(vs8(zero), xyabs, yint)); /* penalty = (abs(x) + abs(y)) << 3 */ xxxx = vec_add(xxxx, yyyy); penalty = vec_splat_u32(3); penalty = vec_sl(xxxx, penalty /* (3,...) */ ); sads = vec_add(sads, penalty); } /* }}} */ /* original version adds same penalty for each sad * so xy adjustment must be after penalty calc. */ xy = vec_add(xy, xy11); /* adjust xy values for elements 1-3 */ /* mask sads x <= (ihigh - i0) && y <= (jhigh - j0) {{{ */ /* the first cmpgt (s8) will flag any x and/or y coordinates... {{{ * as out of bounds. the second cmpgt (u32) will complete the * mask if the x or y flag for that result is set. * * Example: {{{ * X Y X Y X Y X Y * [0 0 < <] [0 0 < <] [0 0 > <] [0 0 < >] * vb8(xymask) = vec_cmpgt(vu8(xy), xylim) * [0 0 0 0] [0 0 0 0] [0 0 1 0] [0 0 0 1] * vb32(xymask) = vec_cmpgt(vu32(xymask), vu32(zero)) * [0 0 0 0] [0 0 0 0] [1 1 1 1] [1 1 1 1] * * Legend: 0=0x00 (<)=(xy[n] <= xymax[n]) * 1=0xff (>)=(xy[n] > xymax[n]) * }}} */ /* }}} */ { vector bool int xymask; xymask = vb32(vec_cmpgt(xy, xylim)); xymask = vec_cmpgt(vu32(xymask), zero); /* 'or' xymask to sads thereby forcing * masked values above the threshold. */ sads = vec_or(sads, vu32(xymask)); } /* }}} */ } /* }}} */ /* find sads lower than minsad */ minsel = vec_cmplt(sads, minsad); minsad = vec_sel(minsad, sads, minsel); minxy = vec_sel(minxy, xy, vb8(minsel)); #define minsad32 vu32(t0) #define minxy32 vs8(t1) t0 = vu8(vec_sld(vu32(zero), vu32(minsad), 12)); t1 = vu8(vec_sld(vu32(zero), vu32(minxy), 12)); minsel = vec_cmplt(minsad, minsad32); minsad = vec_sel(minsad32, minsad, minsel); minxy = vec_sel(minxy32, minxy, vb8(minsel)); #undef minsad32 /* t0 */ #undef minxy32 /* t1 */ #define minsad64 vu32(t0) #define minxy64 vs8(t1) t0 = vu8(vec_sld(vu32(zero), vu32(minsad), 8)); t1 = vu8(vec_sld(vu32(zero), vu32(minxy), 8)); minsel = vec_cmplt(minsad, minsad64); minsad = vec_sel(minsad64, minsad, minsel); minxy = vec_sel(minxy64, minxy, vb8(minsel)); #undef minsad64 /* t0 */ #undef minxy64 /* t1 */ minsad = vec_splat(minsad, 3); minxy = vs8(vec_splat(vu32(minxy), 3)); /* }}} */ } while (--len); /* arrange sad and xy into me_result_s form {{{ */ /* ( 0, sad, 0, sad, 0, sad, 0, sad ) * ( sad, sad, sad, sad, sad, sad, sad, sad ) * * ( 0, xy, 0, xy, 0, xy, 0, xy ) * ( xy, xy, xy, xy, xy, xy, xy, xy ) * * ( sad, xy, sad, xy, sad, xy, sad, xy ) */ minsad = vu32(vec_pack(vu32(minsad), vu32(minsad))); minxy = vs8(vec_pack(vu32(minxy), vu32(minxy))); minsad = vu32(vec_mergeh(vu16(minsad), vu16(minxy))); /* }}} */ /* store mests to vo for scalar access */ vec_st(minsad, 0, (unsigned int*) &vio.best); mres = vio.best; if (mres.weight > 255*255) mres.weight = 255*255; *best_so_far = mres; AMBER_STOP; #undef sads } #if ALTIVEC_TEST_FUNCTION(find_best_one_pel) /* {{{ */ #define FIND_BEST_ONE_PEL_PFMT \ "sub22set=0x%X, org=0x%X, blk=0x%X, i0=%d, j0=%d, ihigh=%d, jhigh=%d, " \ "rowstride=%d, h=%d, best_so_far=0x%X" # ifdef ALTIVEC_VERIFY void find_best_one_pel_altivec_verify(FIND_BEST_ONE_PEL_PDECL) { me_result_s best, best1, best2; best = *best_so_far; /* save best */ _find_best_one_pel_altivec(FIND_BEST_ONE_PEL_ARGS, 1 /* verify */); best1 = *best_so_far; *best_so_far = best; /* restore best */ ALTIVEC_TEST_WITH(find_best_one_pel)(FIND_BEST_ONE_PEL_ARGS); best2 = *best_so_far; if (best1.weight != best2.weight || best1.x != best2.x || best1.y != best2.y) { mjpeg_debug("find_best_one_pel(" FIND_BEST_ONE_PEL_PFMT ")", FIND_BEST_ONE_PEL_ARGS); mjpeg_debug("find_best_one_pel: sub22set->len=%d", sub22set->len); mjpeg_debug("find_best_one_pel: best_so_far " "{weight=%d,x=%d,y=%d} != {weight=%d,x=%d,y=%d}", best1.weight, best1.x, best1.y, best2.weight, best2.x, best2.y); } } static void verify_sads(uint8_t *blk1, uint8_t *blk2, int stride, int h, signed int *sads, int count) { int i, d, d2, dmin; uint8_t *pblk; pblk = blk1; dmin = INT_MAX; for (i = 0; i < count; i++) { /* d = sad_00(blk1, blk2, stride, h, dmin); {{{ */ #if ALTIVEC_TEST_FUNCTION(sad_00) d = ALTIVEC_TEST_WITH(sad_00)(pblk, blk2, stride, h, dmin); #else d = sad_00_altivec(pblk, blk2, stride, h, dmin); #endif /* }}} */ d2 = sads[i]; if (d != d2 && d2 <= dmin) { mjpeg_debug("find_best_one_pel: %d[%d] != %d=sad_00" "(blk1=0x%X(0x%X), blk2=0x%X, stride=%d, h=%d, dmin=%d)", d2, i, d, pblk, blk1, blk2, stride, h, dmin); } if (i == 1) pblk += stride-1; else pblk += 1; } } # else #undef BENCHMARK_FREQUENCY #define BENCHMARK_FREQUENCY 543 #undef BENCHMARK_EPILOG #define BENCHMARK_EPILOG \ mjpeg_info("find_best_one_pel: sub22set->len=%d", sub22set->len); ALTIVEC_TEST(find_best_one_pel, void, (FIND_BEST_ONE_PEL_PDECL), FIND_BEST_ONE_PEL_PFMT, FIND_BEST_ONE_PEL_ARGS); # endif #endif /* }}} */ /* vim:set sw=4 softtabstop=4 foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/Makefile.in0000644000175000017500000005225412217306410021051 0ustar glowwormglowworm# Makefile.in generated by automake 1.12.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Process this file with Automake to produce Makefile.in VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = utils/altivec DIST_COMMON = README $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libaltivec_la_LIBADD = am_libaltivec_la_OBJECTS = add_pred.lo amber.lo benchmark.lo bsad.lo \ bsumsq.lo bsumsq_sub22.lo build_sub22_mests.lo \ build_sub44_mests.lo detect.lo fdct.lo fdct_idct.lo \ field_dct_best.lo find_best_one_pel.lo idct.lo iquant_intra.lo \ iquant_non_intra.lo motion.lo pred_comp.lo quant_non_intra.lo \ quant_weight_coeff_sum.lo quantize.lo sad_00.lo sad_01.lo \ sad_10.lo sad_11.lo sub_mean_reduction.lo \ sub_mean_reduction_ppc.lo sub_pred.lo subsample_image.lo \ sumsq.lo sumsq_sub22.lo variance.lo libaltivec_la_OBJECTS = $(am_libaltivec_la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CPPASCOMPILE = $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) LTCPPASCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libaltivec_la_SOURCES) DIST_SOURCES = $(libaltivec_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALTIVEC_EXTRA_LIBS = @ALTIVEC_EXTRA_LIBS@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDV_CFLAGS = @LIBDV_CFLAGS@ LIBDV_LIBS = @LIBDV_LIBS@ LIBGETOPT_LIB = @LIBGETOPT_LIB@ LIBM_LIBS = @LIBM_LIBS@ LIBOBJS = @LIBOBJS@ LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ LIBPNG_LIBS = @LIBPNG_LIBS@ LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@ LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ LT_STATIC = @LT_STATIC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROGRAM_NOPIC = @PROGRAM_NOPIC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ SDLgfx_LIBS = @SDLgfx_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ V4LCONF_LIBS = @V4LCONF_LIBS@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/utils LTCOMPILE = $(LIBTOOL) --mode=compile \ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) noinst_LTLIBRARIES = libaltivec.la libaltivec_la_SOURCES = \ add_pred.c \ amber.c \ benchmark.c \ bsad.c \ bsumsq.c \ bsumsq_sub22.c \ build_sub22_mests.c \ build_sub44_mests.c \ detect.c \ fdct.c \ fdct_idct.c \ field_dct_best.c \ find_best_one_pel.c \ idct.c \ iquant_intra.c \ iquant_non_intra.c \ motion.c \ pred_comp.c \ quant_non_intra.c \ quant_weight_coeff_sum.c \ quantize.c \ sad_00.c \ sad_01.c \ sad_10.c \ sad_11.c \ sub_mean_reduction.c \ sub_mean_reduction_ppc.S \ sub_pred.c \ subsample_image.c \ sumsq.c \ sumsq_sub22.c \ variance.c noinst_HEADERS = \ altivec_conf.h \ altivec_motion.h \ altivec_predict.h \ altivec_quantize.h \ altivec_transform.h \ amber.h \ benchmark.h \ vectorize.h \ verify.h MAINTAINERCLEANFILES = Makefile.in all: all-am .SUFFIXES: .SUFFIXES: .S .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu utils/altivec/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu utils/altivec/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libaltivec.la: $(libaltivec_la_OBJECTS) $(libaltivec_la_DEPENDENCIES) $(EXTRA_libaltivec_la_DEPENDENCIES) $(LINK) $(libaltivec_la_OBJECTS) $(libaltivec_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/add_pred.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amber.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/benchmark.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsad.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsumsq.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsumsq_sub22.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/build_sub22_mests.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/build_sub44_mests.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/detect.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdct.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdct_idct.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/field_dct_best.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/find_best_one_pel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idct.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iquant_intra.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iquant_non_intra.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/motion.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pred_comp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quant_non_intra.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quant_weight_coeff_sum.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quantize.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sad_00.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sad_01.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sad_10.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sad_11.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sub_mean_reduction.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sub_mean_reduction_ppc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sub_pred.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subsample_image.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sumsq.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sumsq_sub22.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/variance.Plo@am__quote@ .S.o: @am__fastdepCCAS_TRUE@ $(CPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCCAS_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCCAS_FALSE@ $(CPPASCOMPILE) -c -o $@ $< .S.obj: @am__fastdepCCAS_TRUE@ $(CPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCCAS_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCCAS_FALSE@ $(CPPASCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .S.lo: @am__fastdepCCAS_TRUE@ $(LTCPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCCAS_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCCAS_FALSE@ $(LTCPPASCOMPILE) -c -o $@ $< .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist ctags \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mjpegtools-2.1.0/utils/altivec/altivec_transform.h0000644000175000017500000000365007741374325022713 0ustar glowwormglowworm/* altivec_transform.h, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "altivec_conf.h" #define ALTIVEC_TEST_TRANSFORM /* {{{ */ \ ( ( defined(ALTIVEC_BENCHMARK) || defined(ALTIVEC_VERIFY) ) && \ ( ALTIVEC_TEST_FUNCTION(fdct) || \ ALTIVEC_TEST_FUNCTION(idct) || \ ALTIVEC_TEST_FUNCTION(add_pred) || \ ALTIVEC_TEST_FUNCTION(sub_pred) || \ ALTIVEC_TEST_FUNCTION(field_dct_best) ) ) \ /* }}} */ #ifdef __cplusplus extern "C" { #endif ALTIVEC_FUNCTION(fdct, void, (int16_t *blk)); ALTIVEC_FUNCTION(idct, void, (int16_t *blk)); ALTIVEC_FUNCTION(sub_pred, void, (uint8_t *pred, uint8_t *cur, int lx, int16_t *blk)); ALTIVEC_FUNCTION(add_pred, void, (uint8_t *pred, uint8_t *cur, int lx, int16_t *blk)); ALTIVEC_FUNCTION(field_dct_best, int, (uint8_t *cur_lum_mb, uint8_t *pred_lum_mb, int stride)); #ifdef __cplusplus } #endif mjpegtools-2.1.0/utils/altivec/altivec_predict.h0000644000175000017500000000256507610766245022337 0ustar glowwormglowworm/* altivec_predict.h, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "altivec_conf.h" #define ALTIVEC_TEST_PREDICT /* {{{ */ \ ( ( defined(ALTIVEC_BENCHMARK) || defined(ALTIVEC_VERIFY) ) && \ ALTIVEC_TEST_FUNCTION(pred_comp) ) \ /* }}} */ #ifdef __cplusplus extern "C" { #endif ALTIVEC_FUNCTION(pred_comp, void, (uint8_t *src, uint8_t *dst, int lx, int w, int h, int x, int y, int dx, int dy, int addflag)); #ifdef __cplusplus } #endif mjpegtools-2.1.0/utils/altivec/altivec_conf.h0000644000175000017500000003223607742364041021622 0ustar glowwormglowworm/* altivec_conf.h, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * development settings: VERIFY and BENCHMARK are mutually exclusive */ #undef ALTIVEC_VERIFY #undef ALTIVEC_BENCHMARK #undef ALTIVEC_AMBER #define ALTIVEC_DST /* use data stream touch */ #if defined(ALTIVEC_VERIFY) /* {{{ */ /* * define each function to verify with it's comparable function */ #define ALTIVEC_TEST_build_sub44_mests_WITH build_sub44_mests #define ALTIVEC_TEST_build_sub22_mests_WITH build_sub22_mests #define ALTIVEC_TEST_find_best_one_pel_WITH find_best_one_pel #define ALTIVEC_TEST_sub_mean_reduction_WITH sub_mean_reduction #define ALTIVEC_TEST_sad_00_WITH sad_00 #define ALTIVEC_TEST_sad_01_WITH sad_01 #define ALTIVEC_TEST_sad_10_WITH sad_10 #define ALTIVEC_TEST_sad_11_WITH sad_11 #define ALTIVEC_TEST_bsad_WITH bsad #define ALTIVEC_TEST_sumsq_WITH sumsq #define ALTIVEC_TEST_bsumsq_WITH bsumsq #define ALTIVEC_TEST_sumsq_sub22_WITH sumsq_sub22 #define ALTIVEC_TEST_bsumsq_sub22_WITH bsumsq_sub22 #define ALTIVEC_TEST_subsample_image_WITH subsample_image #define ALTIVEC_TEST_variance_WITH variance #define ALTIVEC_TEST_quant_non_intra_WITH quant_non_intra #define ALTIVEC_TEST_quant_weight_coeff_intra_WITH quant_weight_coeff_intra #define ALTIVEC_TEST_quant_weight_coeff_inter_WITH quant_weight_coeff_inter #define ALTIVEC_TEST_iquant_non_intra_m1_WITH iquant_non_intra_m1 #define ALTIVEC_TEST_iquant_non_intra_m2_WITH iquant_non_intra_m2 #define ALTIVEC_TEST_iquant_intra_m1_WITH iquant_intra_m1 #define ALTIVEC_TEST_iquant_intra_m2_WITH iquant_intra_m2 #define ALTIVEC_TEST_add_pred_WITH add_pred #define ALTIVEC_TEST_sub_pred_WITH sub_pred #define ALTIVEC_TEST_pred_comp_WITH pred_comp #define ALTIVEC_TEST_field_dct_best_WITH field_dct_best #define ALTIVEC_TEST_fdct_WITH /* output range test */ #define ALTIVEC_TEST_idct_WITH /* output range test */ # include "verify.h" # define ALTIVEC_TEST_SUFFIX(name) name##_altivec_verify # define ALTIVEC_FUNCTION(name,ret,def) \ ret name##_altivec def; \ ret name##_altivec_verify def; # define ALTIVEC_TEST ALTIVEC_TEST_VERIFY /* }}} */ #elif defined(ALTIVEC_BENCHMARK) /* {{{ */ /* define each function to benchmark with it's comparable function */ #undef ALTIVEC_TEST_sad_00_WITH sad_00 #undef ALTIVEC_TEST_sad_01_WITH sad_01 #undef ALTIVEC_TEST_sad_10_WITH sad_10 #undef ALTIVEC_TEST_sad_11_WITH sad_11 #undef ALTIVEC_TEST_bsad_WITH bsad #undef ALTIVEC_TEST_sumsq_WITH sumsq #undef ALTIVEC_TEST_bsumsq_WITH bsumsq #undef ALTIVEC_TEST_sumsq_sub22_WITH sumsq_sub22 #undef ALTIVEC_TEST_bsumsq_sub22_WITH bsumsq_sub22 #undef ALTIVEC_TEST_quant_non_intra_WITH quant_non_intra #undef ALTIVEC_TEST_quant_weight_coeff_intra_WITH quant_weight_coeff_intra #undef ALTIVEC_TEST_quant_weight_coeff_inter_WITH quant_weight_coeff_inter #undef ALTIVEC_TEST_variance_WITH variance #undef ALTIVEC_TEST_sub_pred_WITH sub_pred #undef ALTIVEC_TEST_add_pred_WITH add_pred #undef ALTIVEC_TEST_pred_comp_WITH pred_comp #undef ALTIVEC_TEST_subsample_image_WITH subsample_image #undef ALTIVEC_TEST_field_dct_best_WITH field_dct_best /* the following functions may call other functions and should be */ /* benchmarked separately. */ #undef ALTIVEC_TEST_find_best_one_pel_WITH find_best_one_pel #undef ALTIVEC_TEST_build_sub44_mests_WITH build_sub44_mests #undef ALTIVEC_TEST_build_sub22_mests_WITH build_sub22_mests /* can't benchmark the following functions since they modify their input */ #undef ALTIVEC_TEST_sub_mean_reduction_WITH sub_mean_reduction /* the following functions modify their input but it shouldn't affect timing */ #undef ALTIVEC_TEST_iquant_non_intra_m1_WITH iquant_non_intra_m1 #undef ALTIVEC_TEST_iquant_non_intra_m2_WITH iquant_non_intra_m2 #undef ALTIVEC_TEST_iquant_intra_m1_WITH iquant_intra_m1 #undef ALTIVEC_TEST_iquant_intra_m2_WITH iquant_intra_m2 #undef ALTIVEC_TEST_fdct_WITH fdct #undef ALTIVEC_TEST_idct_WITH idct /* turn off (undef) DST during benchmarking, it only slows the function down * since everything will be cached due to the benchmark loop. */ #undef ALTIVEC_DST /* default benchmark settings. these values can be redefined before * calling ALTIVEC_TEST() to customize values on a per function basis. */ #define BENCHMARK_FREQUENCY 2000 /* benchmark every (n) calls */ #define BENCHMARK_MAX_RUNS 20 /* benchmark only (n) times */ #define BENCHMARK_ITERATIONS 100000 /* starting point for calibration */ #define BENCHMARK_INCREMENT 1.5 /* multiply iterations by this amount */ #define BENCHMARK_PRECISION 0.005 /* calibration goal */ #define BENCHMARK_PASSES 2 /* number of times the calibration goal * must be met before continuting */ #define BENCHMARK_TIMELIMIT 4 /* time limit in seconds for benchmark * if calibration goal can't be met. */ #define BENCHMARK_PROLOG /* code to execute before benchmark */ #define BENCHMARK_EPILOG /* code to execute after benchmark */ # include "benchmark.h" # define ALTIVEC_TEST_SUFFIX(name) name##_altivec_benchmark # define ALTIVEC_FUNCTION(name,ret,def) \ ret name##_altivec def; \ ret name##_altivec_benchmark def; # define ALTIVEC_TEST ALTIVEC_TEST_BENCHMARK /* }}} */ #elif defined(ALTIVEC_AMBER) /* {{{ */ /* define each function to amber */ /* since some functions modify their input all are tested individually */ #if 1 /* altivec = 1, orignal C = 0 */ /* amber optimized functions */ #if 0 /* group1 = 1, group2 = 0 */ #define ALTIVEC_TEST_sad_00_WITH sad_00_altivec #define ALTIVEC_TEST_sad_01_WITH sad_01_altivec #define ALTIVEC_TEST_sad_10_WITH sad_10_altivec #define ALTIVEC_TEST_sad_11_WITH sad_11_altivec #undef ALTIVEC_TEST_bsad_WITH bsad_altivec #define ALTIVEC_TEST_sumsq_WITH sumsq_altivec #define ALTIVEC_TEST_bsumsq_WITH bsumsq_altivec #define ALTIVEC_TEST_sumsq_sub22_WITH sumsq_sub22_altivec #define ALTIVEC_TEST_bsumsq_sub22_WITH bsumsq_sub22_altivec #define ALTIVEC_TEST_quant_non_intra_WITH quant_non_intra_altivec #define ALTIVEC_TEST_quant_weight_coeff_intra_WITH quant_weight_coeff_intra_altivec #define ALTIVEC_TEST_quant_weight_coeff_inter_WITH quant_weight_coeff_inter_altivec #define ALTIVEC_TEST_iquant_non_intra_m1_WITH iquant_non_intra_m1_altivec #define ALTIVEC_TEST_iquant_non_intra_m2_WITH iquant_non_intra_m2_altivec #define ALTIVEC_TEST_iquant_intra_m1_WITH iquant_intra_m1_altivec #define ALTIVEC_TEST_iquant_intra_m2_WITH iquant_intra_m2_altivec #undef ALTIVEC_TEST_sub_mean_reduction_WITH sub_mean_reduction_altivec #define ALTIVEC_TEST_variance_WITH variance_altivec #define ALTIVEC_TEST_sub_pred_WITH sub_pred_altivec #define ALTIVEC_TEST_add_pred_WITH add_pred_altivec #define ALTIVEC_TEST_pred_comp_WITH pred_comp_altivec #define ALTIVEC_TEST_subsample_image_WITH subsample_image_altivec #define ALTIVEC_TEST_field_dct_best_WITH field_dct_best_altivec #define ALTIVEC_TEST_fdct_WITH fdct_altivec #define ALTIVEC_TEST_idct_WITH idct_altivec #else /* the following call other amber functions, must amber separately */ #define ALTIVEC_TEST_build_sub44_mests_WITH build_sub44_mests_altivec #define ALTIVEC_TEST_build_sub22_mests_WITH build_sub22_mests_altivec #define ALTIVEC_TEST_find_best_one_pel_WITH find_best_one_pel_altivec #endif #else /* amber original functions */ #if 0 /* group1 = 1, group2 = 0 */ #define ALTIVEC_TEST_sad_00_WITH sad_00 #define ALTIVEC_TEST_sad_01_WITH sad_01 #define ALTIVEC_TEST_sad_10_WITH sad_10 #define ALTIVEC_TEST_sad_11_WITH sad_11 #undef ALTIVEC_TEST_bsad_WITH bsad #define ALTIVEC_TEST_sumsq_WITH sumsq #define ALTIVEC_TEST_bsumsq_WITH bsumsq #define ALTIVEC_TEST_sumsq_sub22_WITH sumsq_sub22 #define ALTIVEC_TEST_bsumsq_sub22_WITH bsumsq_sub22 #define ALTIVEC_TEST_quant_non_intra_WITH quant_non_intra #define ALTIVEC_TEST_quant_weight_coeff_intra_WITH quant_weight_coeff_intra #define ALTIVEC_TEST_quant_weight_coeff_inter_WITH quant_weight_coeff_inter #define ALTIVEC_TEST_iquant_non_intra_m1_WITH iquant_non_intra_m1 #define ALTIVEC_TEST_iquant_non_intra_m2_WITH iquant_non_intra_m2 #define ALTIVEC_TEST_iquant_intra_m1_WITH iquant_intra_m1 #define ALTIVEC_TEST_iquant_intra_m2_WITH iquant_intra_m2 #undef ALTIVEC_TEST_sub_mean_reduction_WITH sub_mean_reduction #define ALTIVEC_TEST_variance_WITH variance #define ALTIVEC_TEST_sub_pred_WITH sub_pred #define ALTIVEC_TEST_add_pred_WITH add_pred #define ALTIVEC_TEST_pred_comp_WITH pred_comp #define ALTIVEC_TEST_subsample_image_WITH subsample_image #define ALTIVEC_TEST_field_dct_best_WITH field_dct_best #define ALTIVEC_TEST_fdct_WITH fdct #define ALTIVEC_TEST_idct_WITH idct #else /* the following call other amber functions, must amber separately */ #define ALTIVEC_TEST_build_sub44_mests_WITH build_sub44_mests #define ALTIVEC_TEST_build_sub22_mests_WITH build_sub22_mests #define ALTIVEC_TEST_find_best_one_pel_WITH find_best_one_pel #endif #endif #define AMBER_MAX_TRACES 50 /* number of times to trace each function */ #if 0 /* old global amber trace activation */ #define AMBER_ENABLE #define AMBER_MAX_TRACES 1 /* trace each function once */ #define AMBER_MAX_EXIT 0 #endif # define ALTIVEC_TEST_SUFFIX(name) name##_altivec_amber # define ALTIVEC_FUNCTION(name,ret,def) \ ret name##_altivec def; \ ret name##_altivec_amber def; # define ALTIVEC_TEST ALTIVEC_TEST_AMBER /* }}} */ #else /* PRODUCTION */ # define ALTIVEC_FUNCTION(name,ret,def) \ ret name##_altivec def; #endif /* non-configurable macro definitions {{{ */ #define ALTIVEC_SUFFIX(name) name##_altivec /* macros to assist in code generation */ #define AVCAT(a,b) _AVCAT(a,b) /* allow expansion */ #define _AVCAT(a,b) a##b /* concatenate */ #define AVSTR(a) _AVSTR(a) /* allow expansion */ #define _AVSTR(a) #a /* convert to string */ /* AVRET* expand differently depending on return type */ #define AVRETDECL(type,name) _AVRETDECL(_AVRETDECL_##type,name) #define _AVRETDECL(type,name) type(name) #define _AVRETDECL_int(name) int name #define _AVRETDECL_void(name) /* void name */ #define AVRETSET(type,var,call) _AVRETSET(_AVRETSET_##type,var,call) #define _AVRETSET(type,var,call) type(var,call) #define _AVRETSET_int(var,call) var = call #define _AVRETSET_void(var,call) /* var = */ call #define AVRETURN(type,var) _AVRETURN(_AVRETURN_##type,var) #define _AVRETURN(type,var) type(var) #define _AVRETURN_int(var) return var #define _AVRETURN_void(var) /* return var */ /* printf format codes used by ALTIVEC_VERIFY */ #define AVFMT(ret) _AVFMT(_AVFMT_##ret) #define _AVFMT(ret) ret #define _AVFMT_int "%d" #define _AVFMT_float "%f" #define ALTIVEC_TEST_FUNCTION(name) defined(ALTIVEC_TEST_##name##_WITH) #define ALTIVEC_TEST_WITH(name) \ _ALTIVEC_TEST_WITH(ALTIVEC_TEST_##name##_WITH) #define _ALTIVEC_TEST_WITH(name) name /* allow expansion */ /* }}} */ /* vim:set sw=4 softtabstop=4 foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/idct.c0000644000175000017500000004117510246216132020074 0ustar glowwormglowworm/* idct.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2003 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_conf.h" #include "vectorize.h" #include "../mjpeg_logging.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif #define W1 1.38703989982604980468750000 /* sqrt(2)*cos(1*PI/16) */ #define W2 1.30656301975250244140625000 /* sqrt(2)*cos(2*PI/16) */ #define W3 1.17587554454803466796875000 /* sqrt(2)*cos(3*PI/16) */ #define W5 0.78569495677947998046875000 /* sqrt(2)*cos(5*PI/16) */ #define W6 0.54119610786437988281250000 /* sqrt(2)*cos(6*PI/16) */ #define W7 0.27589938044548034667968750 /* sqrt(2)*cos(7*PI/16) */ #define SQRT_0_5 0.70710676908493041992187500 /* sqrt(0.5) */ #define DIVBY8 0.125 /* 1/8 */ static vector float idctconsts[3] = { (vector float)VCONST( W7, W1-W7, W1+W7, W3 ), (vector float)VCONST( W3-W5, W3+W5, W6, W2+W6 ), (vector float)VCONST( W2-W6, SQRT_0_5, DIVBY8, 0 ) }; #define LD_W7 vec_splat(cnsts0, 0) #define LD_W1mW7 vec_splat(cnsts0, 1) #define LD_W1pW7 vec_splat(cnsts0, 2) #define LD_W3 vec_splat(cnsts0, 3) #define LD_W3mW5 vec_splat(cnsts1, 0) #define LD_W3pW5 vec_splat(cnsts1, 1) #define LD_W6 vec_splat(cnsts1, 2) #define LD_W2pW6 vec_splat(cnsts1, 3) #define LD_W2mW6 vec_splat(cnsts2, 0) #define LD_SQRT_0_5 vec_splat(cnsts2, 1) #define LD_DIVBY8 vec_splat(cnsts2, 2) #define IDCTROW(b0,b1,b2,b3,b4,b5,b6,b7) /* {{{ */ \ x0 = b0; \ x1 = b4; \ x2 = b6; \ x3 = b2; \ x4 = b1; \ x5 = b7; \ x6 = b5; \ x7 = b3; \ \ /* first stage */ \ cnst = LD_W7; \ x8 = vec_add(x4, x5); \ x8 = vec_madd(cnst, x8, mzero); /* x8 = W7*(x4+x5); */ \ cnst = LD_W1mW7; \ x4 = vec_madd(cnst, x4, x8); /* x4 = x8 + (W1-W7)*x4; */ \ cnst = LD_W1pW7; \ x5 = vec_nmsub(cnst, x5, x8); /* x5 = x8 - (W1+W7)*x5; */ \ cnst = LD_W3; \ x8 = vec_add(x6, x7); \ x8 = vec_madd(cnst, x8, mzero); /* x8 = W3*(x6+x7); */ \ cnst = LD_W3mW5; \ x6 = vec_nmsub(cnst, x6, x8); /* x6 = x8 - (W3-W5)*x6; */ \ cnst = LD_W3pW5; \ x7 = vec_nmsub(cnst, x7, x8); /* x7 = x8 - (W3+W5)*x7; */ \ \ /* second stage */ \ x8 = vec_add(x0, x1); /* x8 = x0 + x1; */ \ x0 = vec_sub(x0, x1); /* x0 -= x1; */ \ cnst = LD_W6; \ x1 = vec_add(x3, x2); \ x1 = vec_madd(cnst, x1, mzero); /* x1 = W6*(x3+x2); */ \ cnst = LD_W2pW6; \ x2 = vec_nmsub(cnst, x2, x1); /* x2 = x1 - (W2+W6)*x2; */ \ cnst = LD_W2mW6; \ x3 = vec_madd(cnst, x3, x1); /* x3 = x1 + (W2-W6)*x3; */ \ x1 = vec_add(x4, x6); /* x1 = x4 + x6; */ \ x4 = vec_sub(x4, x6); /* x4 -= x6; */ \ x6 = vec_add(x5, x7); /* x6 = x5 + x7; */ \ x5 = vec_sub(x5, x7); /* x5 -= x7; */ \ \ /* third stage */ \ x7 = vec_add(x8, x3); /* x7 = x8 + x3; */ \ x8 = vec_sub(x8, x3); /* x8 -= x3; */ \ x3 = vec_add(x0, x2); /* x3 = x0 + x2; */ \ x0 = vec_sub(x0, x2); /* x0 -= x2; */ \ cnst = LD_SQRT_0_5; \ x2 = vec_add(x4, x5); \ x2 = vec_madd(cnst, x2, mzero); /* x2 = SQRT_0_5*(x4+x5); */ \ x4 = vec_sub(x4, x5); \ x4 = vec_madd(cnst, x4, mzero); /* x4 = SQRT_0_5*(x4-x5); */ \ \ /* fourth stage */ \ b0 = vec_add(x7, x1); /* x7+x1 */ \ b1 = vec_add(x3, x2); /* x3+x2 */ \ b2 = vec_add(x0, x4); /* x0+x4 */ \ b3 = vec_add(x8, x6); /* x8+x6 */ \ b4 = vec_sub(x8, x6); /* x8-x6 */ \ b5 = vec_sub(x0, x4); /* x0-x4 */ \ b6 = vec_sub(x3, x2); /* x3-x2 */ \ b7 = vec_sub(x7, x1); /* x7-x1 */ \ /* }}} */ #define IDCTCOL(b0,b1,b2,b3,b4,b5,b6,b7) /* {{{ */ \ x0 = b0; \ x1 = b4; \ x2 = b6; \ x3 = b2; \ x4 = b1; \ x5 = b7; \ x6 = b5; \ x7 = b3; \ \ /* first stage */ \ cnst = LD_W7; \ x8 = vec_add(x4, x5); \ x8 = vec_madd(cnst, x8, mzero); /* x8 = W7*(x4+x5); */ \ cnst = LD_W1mW7; \ x4 = vec_madd(cnst, x4, x8); /* x4 = (x8+(W1-W7)*x4); */ \ cnst = LD_W1pW7; \ x5 = vec_nmsub(cnst, x5, x8); /* x5 = (x8-(W1+W7)*x5); */ \ cnst = LD_W3; \ x8 = vec_add(x6, x7); \ x8 = vec_madd(cnst, x8, mzero); /* x8 = W3*(x6+x7); */ \ cnst = LD_W3mW5; \ x6 = vec_nmsub(cnst, x6, x8); /* x6 = (x8-(W3-W5)*x6); */ \ cnst = LD_W3pW5; \ x7 = vec_nmsub(cnst, x7, x8); /* x7 = (x8-(W3+W5)*x7); */ \ \ /* second stage */ \ cnst = LD_DIVBY8; \ x8 = vec_add(x0, x1); \ x8 = vec_madd(x8, cnst, mzero); /* x8 = (x0 + x1); */ \ x0 = vec_sub(x0, x1); \ x0 = vec_madd(x0, cnst, mzero); /* x0 = (x0 - x1); */ \ cnst = LD_W6; \ x1 = vec_add(x3, x2); \ x1 = vec_madd(cnst, x1, mzero); /* x1 = W6*(x3+x2); */ \ cnst = LD_W2pW6; \ x2 = vec_nmsub(cnst, x2, x1); /* x2 = (x1-(W2+W6)*x2); */ \ cnst = LD_W2mW6; \ x3 = vec_madd(cnst, x3, x1); /* x3 = (x1+(W2-W6)*x3); */ \ x1 = vec_add(x4, x6); /* x1 = x4 + x6; */ \ x4 = vec_sub(x4, x6); /* x4 -= x6; */ \ x6 = vec_add(x5, x7); /* x6 = x5 + x7; */ \ x5 = vec_sub(x5, x7); /* x5 -= x7; */ \ \ /* third stage */ \ x7 = vec_add(x8, x3); /* x7 = x8 + x3; */ \ x8 = vec_sub(x8, x3); /* x8 -= x3; */ \ x3 = vec_add(x0, x2); /* x3 = x0 + x2; */ \ x0 = vec_sub(x0, x2); /* x0 -= x2; */ \ cnst = LD_SQRT_0_5; \ x2 = vec_add(x4, x5); \ x2 = vec_madd(cnst, x2, mzero); /* x2 = SQRT_0_5*(x4+x5); */ \ x4 = vec_sub(x4, x5); \ x4 = vec_madd(cnst, x4, mzero); /* x4 = SQRT_0_5*(x4-x5); */ \ \ /* fourth stage */ \ b0 = vec_add(x7, x1); /* x7+x1 */ \ b1 = vec_add(x3, x2); /* x3+x2 */ \ b2 = vec_add(x0, x4); /* x0+x4 */ \ b3 = vec_add(x8, x6); /* x8+x6 */ \ b4 = vec_sub(x8, x6); /* x8-x6 */ \ b5 = vec_sub(x0, x4); /* x0-x4 */ \ b6 = vec_sub(x3, x2); /* x3-x2 */ \ b7 = vec_sub(x7, x1); /* x7-x1 */ \ /* }}} */ #define IDCT_PDECL short *block #define IDCT_ARGS block #define IDCT_PFMT "block=0x%X" /* two dimensional inverse discrete cosine transform */ void idct_altivec(IDCT_PDECL) { vector signed short *bp; vector float *cp; vector float b00, b10, b20, b30, b40, b50, b60, b70; vector float b01, b11, b21, b31, b41, b51, b61, b71; vector float mzero, cnst, cnsts0, cnsts1, cnsts2; vector float x0, x1, x2, x3, x4, x5, x6, x7, x8; #ifdef ALTIVEC_VERIFY if (NOT_VECTOR_ALIGNED(block)) mjpeg_error_exit1("idct: block %% 16 != 0, (%d)\n", block); #endif AMBER_START; /* 8x8 matrix transpose (vector short[8]) {{{ */ #define MERGE_S16(hl,a,b) vec_merge##hl(vs16(a), vs16(b)) bp = (vector signed short*)block; x0 = vfp(vec_ld(0, bp)); x4 = vfp(vec_ld(16*4, bp)); b00 = vfp(MERGE_S16(h, x0, x4)); b10 = vfp(MERGE_S16(l, x0, x4)); bp++; x1 = vfp(vec_ld(0, bp)); x5 = vfp(vec_ld(16*4, bp)); b20 = vfp(MERGE_S16(h, x1, x5)); b30 = vfp(MERGE_S16(l, x1, x5)); bp++; x2 = vfp(vec_ld(0, bp)); x6 = vfp(vec_ld(16*4, bp)); b40 = vfp(MERGE_S16(h, x2, x6)); b50 = vfp(MERGE_S16(l, x2, x6)); bp++; x3 = vfp(vec_ld(0, bp)); x7 = vfp(vec_ld(16*4, bp)); b60 = vfp(MERGE_S16(h, x3, x7)); b70 = vfp(MERGE_S16(l, x3, x7)); b01 = vfp(MERGE_S16(h, b00, b40)); b11 = vfp(MERGE_S16(l, b00, b40)); b21 = vfp(MERGE_S16(h, b10, b50)); b31 = vfp(MERGE_S16(l, b10, b50)); b41 = vfp(MERGE_S16(h, b20, b60)); b51 = vfp(MERGE_S16(l, b20, b60)); b61 = vfp(MERGE_S16(h, b30, b70)); b71 = vfp(MERGE_S16(l, b30, b70)); x0 = vfp(MERGE_S16(h, b01, b41)); x1 = vfp(MERGE_S16(l, b01, b41)); x2 = vfp(MERGE_S16(h, b11, b51)); x3 = vfp(MERGE_S16(l, b11, b51)); x4 = vfp(MERGE_S16(h, b21, b61)); x5 = vfp(MERGE_S16(l, b21, b61)); x6 = vfp(MERGE_S16(h, b31, b71)); x7 = vfp(MERGE_S16(l, b31, b71)); #undef MERGE_S16 /* }}} */ /* convert to float {{{ */ #define CTF(n) \ b##n##0 = vfp(vec_unpackh(vs16(x##n))); \ b##n##1 = vfp(vec_unpackl(vs16(x##n))); \ b##n##0 = vfp(vec_ctf(vs32(b##n##0), 0)); \ b##n##1 = vfp(vec_ctf(vs32(b##n##1), 0)); \ CTF(0); CTF(1); CTF(2); CTF(3); CTF(4); CTF(5); CTF(6); CTF(7); #undef CTF /* }}} */ /* setup constants {{{ */ /* mzero = -0.0 */ mzero = (vector float)vec_splat_u32(-1); mzero = (vector float)vec_sl(vu32(mzero), vu32(mzero)); cp = idctconsts; cnsts0 = vec_ld(0, cp); cp++; cnsts1 = vec_ld(0, cp); cp++; cnsts2 = vec_ld(0, cp); /* }}} */ IDCTROW(b00, b10, b20, b30, b40, b50, b60, b70); IDCTROW(b01, b11, b21, b31, b41, b51, b61, b71); /* 8x8 matrix transpose (vector float[8][2]) {{{ */ x0 = vec_mergel(b00, b20); x1 = vec_mergeh(b00, b20); x2 = vec_mergel(b10, b30); x3 = vec_mergeh(b10, b30); b00 = vec_mergeh(x1, x3); b10 = vec_mergel(x1, x3); b20 = vec_mergeh(x0, x2); b30 = vec_mergel(x0, x2); x4 = vec_mergel(b41, b61); x5 = vec_mergeh(b41, b61); x6 = vec_mergel(b51, b71); x7 = vec_mergeh(b51, b71); b41 = vec_mergeh(x5, x7); b51 = vec_mergel(x5, x7); b61 = vec_mergeh(x4, x6); b71 = vec_mergel(x4, x6); x0 = vec_mergel(b01, b21); x1 = vec_mergeh(b01, b21); x2 = vec_mergel(b11, b31); x3 = vec_mergeh(b11, b31); x4 = vec_mergel(b40, b60); x5 = vec_mergeh(b40, b60); x6 = vec_mergel(b50, b70); x7 = vec_mergeh(b50, b70); b40 = vec_mergeh(x1, x3); b50 = vec_mergel(x1, x3); b60 = vec_mergeh(x0, x2); b70 = vec_mergel(x0, x2); b01 = vec_mergeh(x5, x7); b11 = vec_mergel(x5, x7); b21 = vec_mergeh(x4, x6); b31 = vec_mergel(x4, x6); /* }}} */ /* divide constants by 8 {{{ */ cnst = LD_DIVBY8; cnsts0 = vec_madd(cnsts0, cnst, mzero); cnsts1 = vec_madd(cnsts1, cnst, mzero); /* cnts2 = (cnsts2[0]*DIVBY8, cnsts2[1], cnsts2[2], cnsts[3]) */ x0 = vec_sld(cnsts2, cnsts2, 4); x1 = vec_madd(x0, cnst, mzero); cnsts2 = vec_sld(x1, x0, 12); /* }}} */ IDCTCOL(b00, b10, b20, b30, b40, b50, b60, b70); IDCTCOL(b01, b11, b21, b31, b41, b51, b61, b71); /* round, convert back to short and clip {{{ */ /* cnsts0 = max = 255 = 0x00ff, cnsts2 = min = -256 = 0xff00 {{{ */ cnsts0 = vfp(vec_splat_u8(0)); x8 = vfp(vec_splat_u8(-1)); cnsts2 = vfp(vec_mergeh(vu8(x8), vu8(cnsts0))); cnsts0 = vfp(vec_mergeh(vu8(cnsts0), vu8(x8))); /* }}} */ #define CTS(n) \ b##n##0 = vfp(vec_round(b##n##0)); \ b##n##1 = vfp(vec_round(b##n##1)); \ b##n##0 = vfp(vec_cts(b##n##0, 0)); \ b##n##1 = vfp(vec_cts(b##n##1, 0)); \ b##n##0 = vfp(vec_pack(vs32(b##n##0), vs32(b##n##1))); \ b##n##0 = vfp(vec_min(vs16(b##n##0), vs16(cnsts0))); \ b##n##0 = vfp(vec_max(vs16(b##n##0), vs16(cnsts2))); \ vec_st(vs16(b##n##0), 0, bp); bp = (vector signed short*)block; CTS(0); bp++; CTS(1); bp++; CTS(2); bp++; CTS(3); bp++; CTS(4); bp++; CTS(5); bp++; CTS(6); bp++; CTS(7); #undef CTS /* }}} */ AMBER_STOP; } #if ALTIVEC_TEST_FUNCTION(idct) /* {{{ */ #ifdef ALTIVEC_VERIFY void idct_altivec_verify(IDCT_PDECL) { int i; idct_altivec(IDCT_ARGS); for (i = 0; i < 64; i++) { if (block[i] < -256) mjpeg_warn("idct: block[%d]=%d < -256\n", i, block[i]); else if (block[i] > 255) mjpeg_warn("idct: block[%d]=%d > 255\n", i, block[i]); } } #else ALTIVEC_TEST(idct, void, (IDCT_PDECL), IDCT_PFMT, IDCT_ARGS); #endif #endif /* }}} */ /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/vectorize.h0000644000175000017500000000404007722024711021163 0ustar glowwormglowworm/* vectorize.h, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Useful AltiVec macros * */ #define VECTOR_ALIGNED(p) (((unsigned long)(p) & 15) == 0) #define NOT_VECTOR_ALIGNED(p) (((unsigned long)(p) & 15) != 0) #define VECTOR_OFFSET(p) ((((unsigned long)(p))+15) & (~15)) #define vs8(v) ((vector signed char)(v)) #define vs16(v) ((vector signed short)(v)) #define vs32(v) ((vector signed int)(v)) #define vu8(v) ((vector unsigned char)(v)) #define vu16(v) ((vector unsigned short)(v)) #define vu32(v) ((vector unsigned int)(v)) #define vb8(v) ((vector bool char)(v)) #define vb16(v) ((vector bool short)(v)) #define vb32(v) ((vector bool int)(v)) #define vpx(v) ((vector pixel)(v)) #define vfp(v) ((vector float)(v)) typedef union { unsigned int control; struct { unsigned char size; /* 0 to 31, (size & 0x1F) */ unsigned char count; /* 0 to 255 */ signed short stride; /* -32768 to +32768 */ } block; } DataStreamControl; #define DATA_STREAM_CONTROL(size,count,stride) \ ((((size)&0x1F)<<24)|(((count)&0xFF)<<16)|((stride)&0xFFFF)) #ifdef HAVE_ALTIVEC_H /* GNU GCC3 style vector constants */ #define VCONST(v...) {v} #else /* Motorola style vector constants */ #define VCONST(v...) (v) #endif mjpegtools-2.1.0/utils/altivec/sad_00.c0000644000175000017500000001270410532365710020220 0ustar glowwormglowworm/* sad_00.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_motion.h" #include "vectorize.h" #include "../mjpeg_logging.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif /* * sum absolute difference * * Input requirements: * b) blk2 is always vector aligned * c) rowstride is a multiple of 16 * d) h is either 8 or 16 * */ #define SAD_00_PDECL \ uint8_t *blk1, \ uint8_t *blk2, \ int rowstride, \ int h, \ int dlim \ #define SAD_00_ARGS blk1, blk2, rowstride, h, dlim int sad_00_altivec(SAD_00_PDECL) { int i; unsigned char *pblk1, *pblk2; vector unsigned char blk1A, blk2A, blk1B, blk2B; vector unsigned char blk1A0, blk1B0; vector unsigned char blk1A1, blk1B1; vector unsigned char minA, minB; vector unsigned char maxA, maxB; vector unsigned char difA, difB; vector unsigned int sum; vector signed int zero; vector unsigned char perm; union { vector signed int v; struct { signed int pad[3]; signed int sum; } s; } vo; if (NOT_VECTOR_ALIGNED(blk2)) mjpeg_error_exit1("sad_00: blk2 %% 16 != 0, (%d)\n", blk2); #ifdef ALTIVEC_VERIFY if (NOT_VECTOR_ALIGNED(rowstride)) mjpeg_error_exit1("sad_00: rowstride %% 16 != 0, (%d)\n", rowstride); #endif if (h != 8 && h != 16) mjpeg_error_exit1("sad_00: h != [8|16], (%d)\n", h); AMBER_START; pblk1 = blk1; pblk2 = blk2; i = (h >> 1) - 1; zero = vec_splat_s32(0); sum = vec_splat_u32(0); if (VECTOR_ALIGNED(pblk1)) { blk1A = vec_ld(0, pblk1); pblk1 += rowstride; blk1B = vec_ld(0, pblk1); blk2A = vec_ld(0, pblk2); pblk2 += rowstride; blk2B = vec_ld(0, pblk2); do { maxA = vec_max(blk1A, blk2A); minA = vec_min(blk1A, blk2A); pblk1 += rowstride; blk1A = vec_ld(0, pblk1); pblk2 += rowstride; blk2A = vec_ld(0, pblk2); difA = vec_sub(maxA, minA); sum = vec_sum4s(difA, sum); maxB = vec_max(blk1B, blk2B); minB = vec_min(blk1B, blk2B); pblk1 += rowstride; blk1B = vec_ld(0, pblk1); pblk2 += rowstride; blk2B = vec_ld(0, pblk2); difB = vec_sub(maxB, minB); sum = vec_sum4s(difB, sum); } while (--i); } else { perm = vec_lvsl(0, pblk1); blk1A0 = vec_ld(0, pblk1); blk1A1 = vec_ld(16, pblk1); pblk1 += rowstride; blk1B0 = vec_ld(0, pblk1); blk1B1 = vec_ld(16, pblk1); blk2A = vec_ld(0, pblk2); pblk2 += rowstride; blk2B = vec_ld(0, pblk2); do { blk1A = vec_perm(blk1A0, blk1A1, perm); pblk1 += rowstride; blk1A0 = vec_ld(0, pblk1); blk1A1 = vec_ld(16, pblk1); maxA = vec_max(blk1A, blk2A); minA = vec_min(blk1A, blk2A); pblk2 += rowstride; blk2A = vec_ld(0, pblk2); difA = vec_sub(maxA, minA); sum = vec_sum4s(difA, sum); blk1B = vec_perm(blk1B0, blk1B1, perm); pblk1 += rowstride; blk1B0 = vec_ld(0, pblk1); blk1B1 = vec_ld(16, pblk1); maxB = vec_max(blk1B, blk2B); minB = vec_min(blk1B, blk2B); pblk2 += rowstride; blk2B = vec_ld(0, pblk2); difB = vec_sub(maxB, minB); sum = vec_sum4s(difB, sum); } while (--i); blk1A = vec_perm(blk1A0, blk1A1, perm); blk1B = vec_perm(blk1B0, blk1B1, perm); } maxA = vec_max(blk1A, blk2A); minA = vec_min(blk1A, blk2A); difA = vec_sub(maxA, minA); sum = vec_sum4s(difA, sum); maxB = vec_max(blk1B, blk2B); minB = vec_min(blk1B, blk2B); difB = vec_sub(maxB, minB); sum = vec_sum4s(difB, sum); vo.v = vec_sums(vs32(sum), zero); AMBER_STOP; return vo.s.sum; } #if ALTIVEC_TEST_FUNCTION(sad_00) /* {{{ */ #ifdef ALTIVEC_VERIFY int sad_00_altivec_verify(SAD_00_PDECL) { int value, test; value = ALTIVEC_TEST_WITH(sad_00)(SAD_00_ARGS); test = sad_00_altivec(SAD_00_ARGS); /* special case, test <= dlim */ if (test != value && test <= dlim) mjpeg_debug("%d != %d" "=sad_00(blk1=0x%X, blk2=0x%X, rowstride=%d, h=%d, dlim=%d)", test, value, SAD_00_ARGS); return value; } #else ALTIVEC_TEST(sad_00, int, (SAD_00_PDECL), "blk1=0x%X, blk2=0%X, rowstride=%d, h=%d, dlim=%d", SAD_00_ARGS); #endif #endif /* }}} */ /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/detect.c0000644000175000017500000000350510155665177020434 0ustar glowwormglowworm/* detect.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif /* * Functions containing AltiVec code have additional VRSAVE instructions * at the beginning and end of the function. To avoid executing any AltiVec * instructions before our signal handler is setup the AltiVec code is * encapsulated in a function. * * The automatic VRSAVE instructions can be disabled with * #pragma altivec_vrsave off * * Storing vector registers to memory shouldn't alter the state of the vectors * or the vector unit. The following function contains a single vector stvx * instruction. */ #pragma altivec_vrsave off int altivec_copy_v0() { register vector unsigned int v0 asm ("v0"); union { vector unsigned int align16; unsigned int v0[4]; } copy; vec_st(v0, 0, copy.v0); return copy.v0[0]; } /* * detect_altivec() moved to ../cpu_accel.c */ mjpegtools-2.1.0/utils/altivec/sub_pred.c0000644000175000017500000001363710464771010020761 0ustar glowwormglowworm/* sub_pred.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_motion.h" #include "vectorize.h" #include #include "../mjpeg_logging.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif #define SUB_PRED_PDECL uint8_t *pred, uint8_t *cur, int lx, int16_t *blk #define SUB_PRED_ARGS pred, cur, lx, blk #define SUB_PRED_PFMT "pred=0x%X, cur=0x%X, lx=%d, blk=0x%X" /* * subtract prediction from block data * pred % 8 == 0 * cur % 8 == 0 * lx % 16 == 0 * blk % 16 == 0 */ void sub_pred_altivec(SUB_PRED_PDECL) { unsigned int dst; uint8_t *pCA, *pCB, *pPA, *pPB; int16_t *pBA, *pBB; vector unsigned char zero; vector unsigned char predA, predB, curA, curB; vector signed short blkA, blkB; #ifdef ALTIVEC_VERIFY #ifdef ALTIVEC_DST if (lx & (~0xffff) != 0) mjpeg_error_exit1("sub_pred: lx > vec_dst range", lx); #endif if (NOT_VECTOR_ALIGNED(lx)) mjpeg_error_exit1("sub_pred: lx %% 16 != 0, (%d)", lx); if (NOT_VECTOR_ALIGNED(blk)) mjpeg_error_exit1("sub_pred: blk %% 16 != 0, (%d)", blk); if (((unsigned long)pred & 0xf) != ((unsigned long)cur & 0xf)) mjpeg_error_exit1("sub_pred: (pred(0x%X) %% 16) != (cur(0x%X) %% 16)", pred, cur); if ((((unsigned long)pred) & 0x7) != 0) mjpeg_error_exit1("sub_pred: pred %% 8 != 0, (0x%X)", pred); if ((((unsigned long)cur) & 0x7) != 0) mjpeg_error_exit1("sub_pred: cur %% 8 != 0, (0x%X)", cur); #endif /* A->B, B->A expand differently depending on input */ #define ABBA(symbol,ab) _ABBA(ABBA_##ab,symbol) /* {{{ */ #define _ABBA(abba_ab,symbol) abba_ab(symbol) #define ABBA_A(symbol) symbol##B #define ABBA_B(symbol) symbol##A /* }}} */ #define PERFORM_ITERATION(hl,ab,iter) /* iter {{{ */ \ pred##ab = vec_merge##hl(zero, pred##ab); \ cur##ab = vec_merge##hl(zero, cur##ab); \ blk##ab = vec_sub(vs16(cur##ab), vs16(pred##ab)); \ vec_st(blk##ab, 0, (signed short*)pB##ab); \ /* }}} */ #define PREPARE_ITERATION(hl,ab,iter) /* iter {{{ */ \ pP##ab = ABBA(pP,ab) + lx; \ pC##ab = ABBA(pC,ab) + lx; \ pB##ab = ABBA(pB,ab) + 8; \ pred##ab = vec_ld(0, pP##ab); \ cur##ab = vec_ld(0, pC##ab); \ /* }}} */ #define NO_RESCHEDULE asm volatile ("") AMBER_START; pPA = pred; pCA = cur; pBA = blk; #ifdef ALTIVEC_DST dst = 0x01080000 | lx; vec_dst(pPA, dst, 0); vec_dst(pCA, dst, 1); dst = 0x01080010; vec_dstst(pBA, dst, 2); #endif pPB = pPA + lx; NO_RESCHEDULE; predA = vec_ld(0, pPA); NO_RESCHEDULE; pCB = pCA + lx; NO_RESCHEDULE; curA = vec_ld(0, pCA); NO_RESCHEDULE; pBB = pBA + 8; NO_RESCHEDULE; predB = vec_ld(0, pPB); NO_RESCHEDULE; zero = vec_splat_u8(0); NO_RESCHEDULE; curB = vec_ld(0, pCB); if (VECTOR_ALIGNED(pPA)) { PERFORM_ITERATION(h,A,0); PREPARE_ITERATION(h,A,2); /* prepare next A iteration */ PERFORM_ITERATION(h,B,1); PREPARE_ITERATION(h,B,3); /* prepare next B iteration */ PERFORM_ITERATION(h,A,2); PREPARE_ITERATION(h,A,4); PERFORM_ITERATION(h,B,3); PREPARE_ITERATION(h,B,5); PERFORM_ITERATION(h,A,4); PREPARE_ITERATION(h,A,6); PERFORM_ITERATION(h,B,5); PREPARE_ITERATION(h,B,7); PERFORM_ITERATION(h,A,6); PERFORM_ITERATION(h,B,7); } else { PERFORM_ITERATION(l,A,0); PREPARE_ITERATION(l,A,2); /* prepare next A iteration */ PERFORM_ITERATION(l,B,1); PREPARE_ITERATION(l,B,3); /* prepare next B iteration */ PERFORM_ITERATION(l,A,2); PREPARE_ITERATION(l,A,4); PERFORM_ITERATION(l,B,3); PREPARE_ITERATION(l,B,5); PERFORM_ITERATION(l,A,4); PREPARE_ITERATION(l,A,6); PERFORM_ITERATION(l,B,5); PREPARE_ITERATION(l,B,7); PERFORM_ITERATION(l,A,6); PERFORM_ITERATION(l,B,7); } #ifdef ALTIVEC_DST vec_dssall(); #endif AMBER_STOP; } #if ALTIVEC_TEST_FUNCTION(sub_pred) /* {{{ */ # ifdef ALTIVEC_VERIFY void sub_pred_altivec_verify(SUB_PRED_PDECL) { int i; unsigned long checksum1, checksum2; signed short blkcpy[8*8]; sub_pred_altivec(SUB_PRED_ARGS); for (checksum1 = i = 0; i < 8*8; i++) checksum1 += abs(blk[i]); memcpy(blkcpy, blk, 8*8*sizeof(short)); ALTIVEC_TEST_WITH(sub_pred)(SUB_PRED_ARGS); for (checksum2 = i = 0; i < 8*8; i++) checksum2 += abs(blk[i]); if (checksum1 != checksum2) { mjpeg_debug("sub_pred(" SUB_PRED_PFMT ")", SUB_PRED_ARGS); mjpeg_debug("sub_pred: checksums differ %d != %d", checksum1, checksum2); for (i = 0; i < 8*8; i++) { if (blkcpy[i] != blk[i]) { mjpeg_debug("sub_pred: blk[%d] %d != %d", i, blkcpy[i], blk[i]); } } } } # else ALTIVEC_TEST(sub_pred, void, (SUB_PRED_PDECL), SUB_PRED_PFMT, SUB_PRED_ARGS); # endif #endif /* }}} */ /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/sad_01.c0000644000175000017500000001545610462765416020241 0ustar glowwormglowworm/* sad_01.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_motion.h" #include "vectorize.h" #include "../mjpeg_logging.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif /* * SAD with horizontal half pel interpolation * * Input requirements: * a) blk2 is always vector aligned * b) rowstride is a multiple of 16 * c) h is either 8 or 16 * * s = rowstride * for (j = 0; j < h; j++) { * for (i = 0; i < 16; i++) * sum += abs( ((int)(p1[i]+p1[i+1]+1)>>1) - p2[i] ); * p1 += s; * p2 += s; * } */ #define SAD_01_PDECL \ uint8_t *blk1, \ uint8_t *blk2, \ int rowstride, \ int h \ #define SAD_01_ARGS blk1, blk2, rowstride, h int sad_01_altivec(SAD_01_PDECL) { int i; unsigned char *pB, *pR; vector unsigned char l0, l1, l2, l3, lR, lB0, lB1, perm0, perm1; vector unsigned short b0H, b0L, b1H, b1L; vector unsigned short bH, bL; vector unsigned char max, min, dif; vector unsigned int sum; vector unsigned char zero; vector unsigned short one; union { vector signed int v; struct { signed int pad[3]; signed int sum; } s; } vo; #ifdef ALTIVEC_VERIFY if (NOT_VECTOR_ALIGNED(blk2)) mjpeg_error_exit1("sad_01: blk2 %% 16 != 0, (%d)", blk2); if (NOT_VECTOR_ALIGNED(rowstride)) mjpeg_error_exit1("sad_01: rowstride %% 16 != 0, (%d)", rowstride); #endif if (h != 8 && h != 16) mjpeg_error_exit1("sad_01: h != [8|16], (%d)", h); AMBER_START; #define ISAD() /* {{{ */ \ /* pB[i] + pB[i+1] */ \ bH = vec_add(b0H, b1H); \ bL = vec_add(b0L, b1L); \ \ /* (pB[i]+pB[i+1]) + 1 */ \ bH = vec_add(bH, one); \ bL = vec_add(bL, one); \ \ /* (pB[i]+pB[i+1]+1) >> 1 */ \ bH = vec_sra(bH, one); \ bL = vec_sra(bL, one); \ \ /* abs( ((pB[i]+pB[i+1]+1)>>1) - pR[i] ) */ \ bH = vu16(vec_packsu(bH, bL)); \ min = vec_min(vu8(bH), lR); \ max = vec_max(vu8(bH), lR); \ dif = vec_sub(max, min); \ \ /* sum += abs(((pB[i]+pB[i+1]+1)>>1)-pR[i]) */ \ sum = vec_sum4s(dif, sum); \ /* }}} */ pB = blk1, pR = blk2; l0 = vec_ld(0, pB); l1 = vec_ld(16, pB); pB += rowstride; l2 = vec_ld(0, pB); l3 = vec_ld(16, pB); lR = vec_ld(0, pR); /* initialize constants */ zero = vec_splat_u8(0); one = vec_splat_u16(1); sum = vec_splat_u32(0); perm0 = vec_lvsl(0, pB); perm1 = vec_splat_u8(1); perm1 = vec_add(perm0, perm1); i = (h >> 1) - 1; do { /* while (--i) */ lB0 = vec_perm(l0, l1, perm0); lB1 = vec_perm(l0, l1, perm1); pB += rowstride; l0 = vec_ld(0, pB); l1 = vec_ld(16, pB); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* (unsigned short[]) pB[1-8] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB[9-16] */ b1L = vu16(vec_mergel(zero, lB1)); ISAD(); pR += rowstride; lR = vec_ld(0, pR); lB0 = vec_perm(l2, l3, perm0); lB1 = vec_perm(l2, l3, perm1); pB += rowstride; l2 = vec_ld(0, pB); l3 = vec_ld(16, pB); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* (unsigned short[]) pB[1-8] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB[9-16] */ b1L = vu16(vec_mergel(zero, lB1)); ISAD(); pR += rowstride; lR = vec_ld(0, pR); } while (--i); lB0 = vec_perm(l0, l1, perm0); lB1 = vec_perm(l0, l1, perm1); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* (unsigned short[]) pB[1-8] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB[9-16] */ b1L = vu16(vec_mergel(zero, lB1)); ISAD(); pR += rowstride; lR = vec_ld(0, pR); lB0 = vec_perm(l2, l3, perm0); lB1 = vec_perm(l2, l3, perm1); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* (unsigned short[]) pB[1-8] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB[9-16] */ b1L = vu16(vec_mergel(zero, lB1)); ISAD(); vo.v = vec_sums(vs32(sum), vs32(zero)); AMBER_STOP; return vo.s.sum; } #if ALTIVEC_TEST_FUNCTION(sad_01) ALTIVEC_TEST(sad_01, int, (SAD_01_PDECL), "blk1=0x%X, blk2=0x%X, rowstride=%d, h=%d", SAD_01_ARGS); #endif /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/quant_non_intra.c0000644000175000017500000004500410246233040022340 0ustar glowwormglowworm/* quant_non_intra.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_quantize.h" #if defined(ALTIVEC_VERIFY) && ALTIVEC_TEST_FUNCTION(quant_non_intra) #include #include #endif #include "vectorize.h" #include #include "../mjpeg_logging.h" #include "../../mpeg2enc/syntaxconsts.h" #include "../../mpeg2enc/quantize_precomp.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif /* * The original C version would start-over from the beginning each time * clipping occurred (until saturated) which resulted in the possibility of * most dst[] values being re-calculated many times. This version, if clipping * is detected, restarts calculating from the current block. Once it's finished * it will re-calculate blocks that need it starting with block 0. */ #define QUANT_NON_INTRA_PDECL \ struct QuantizerWorkSpace *wsp, \ int16_t *src, int16_t *dst, \ int q_scale_type, int dctsatlim, int *nonsat_mquant \ #define QUANT_NON_INTRA_ARGS \ wsp, src, dst, q_scale_type, dctsatlim, nonsat_mquant #define QUANT_NON_INTRA_PFMT \ "wsp=0x%X, src=0x%X, dst=0x%X, q_scale_type=%d, dctsatlim=%d, " \ "nonsat_mquant=0x%X" int quant_non_intra_altivec(QUANT_NON_INTRA_PDECL) { int mquant = *nonsat_mquant; int i, j, N, nzblockbits, last_block, recalc_blocks; vector unsigned short *pqm; vector unsigned short *inter_q_mat = wsp->inter_q_mat; signed short *ps, *pd; vector unsigned short zero, four; vector float one; vector unsigned short qmA, qmB; /* quant matrix */ vector signed short srcA, srcB; /* source */ vector signed short dstA, dstB; /* destination */ vector float sA0, sA1, sB0, sB1; /* dividend */ vector float dA0, dA1, dB0, dB1; /* divisor */ vector float reA0, reA1, reB0, reB1; /* reciprocal */ vector float qtA0, qtA1, qtB0, qtB1; /* quotient */ vector float rmA0, rmA1, rmB0, rmB1; /* remainder */ vector bool short selA, selB; /* bool selector */ vector bool short nz; /* non-zero */ vector unsigned short max; /* max value */ vector unsigned short t1, t2, t3, t4; /* vuv & vu are used to share values between vector and scalar code. * vu lives on the stack and vuv is a vector register. Using vuv * instead of vu.v allows control over when read/writes to vu are done. */ vector unsigned short vuv; union { /* do not use v, load vu into vuv for vector access. */ vector unsigned short v; struct { unsigned short mquant; unsigned short clipvalue; unsigned int nz; } s; } vu; #ifdef ALTIVEC_VERIFY /* {{{ */ if (NOT_VECTOR_ALIGNED(wsp->inter_q_mat)) mjpeg_error_exit1("quant_non_intra: wsp->inter_q_mat %% 16 != 0, (%d)", wsp->inter_q_mat); if (NOT_VECTOR_ALIGNED(src)) mjpeg_error_exit1("quant_non_intra: src %% 16 != 0, (%d)", src); if (NOT_VECTOR_ALIGNED(dst)) mjpeg_error_exit1("quant_non_intra: dst %% 16 != 0, (%d)", dst); #endif /* }}} */ #define QUANT_NON_INTRA_AB /* {{{ */ \ qmA = vec_ld(0, pqm); \ pqm++; \ qmB = vec_ld(0, pqm); \ pqm++; \ srcA = vec_ld(0, ps); \ ps += 8; \ srcB = vec_ld(0, ps); \ ps += 8; \ \ /* calculate divisor */ \ dA0 = vfp(vec_mergeh(zero, qmA)); \ dA1 = vfp(vec_mergel(zero, qmA)); \ dB0 = vfp(vec_mergeh(zero, qmB)); \ dB1 = vfp(vec_mergel(zero, qmB)); \ vuv = vec_ld(0, (unsigned short*)&vu); \ vuv = vec_splat(vuv, 0); /* splat mquant */ \ dA0 = vfp(vec_mulo(vu16(dA0), vuv)); \ dA1 = vfp(vec_mulo(vu16(dA1), vuv)); \ dB0 = vfp(vec_mulo(vu16(dB0), vuv)); \ dB1 = vfp(vec_mulo(vu16(dB1), vuv)); \ dA0 = vec_ctf(vu32(dA0), 0); \ dA1 = vec_ctf(vu32(dA1), 0); \ dB0 = vec_ctf(vu32(dB0), 0); \ dB1 = vec_ctf(vu32(dB1), 0); \ reA0 = vec_re(dA0); \ reA1 = vec_re(dA1); \ reB0 = vec_re(dB0); \ reB1 = vec_re(dB1); \ \ /* refinement #1 */ \ t1 = vu16(vec_nmsub(reA0, vfp(dA0), vfp(one))); \ t2 = vu16(vec_nmsub(reA1, vfp(dA1), vfp(one))); \ t3 = vu16(vec_nmsub(reB0, vfp(dB0), vfp(one))); \ t4 = vu16(vec_nmsub(reB1, vfp(dB1), vfp(one))); \ reA0 = vec_madd(reA0, vfp(t1), reA0); \ reA1 = vec_madd(reA1, vfp(t2), reA1); \ reB0 = vec_madd(reB0, vfp(t3), reB0); \ reB1 = vec_madd(reB1, vfp(t4), reB1); \ \ /* refinement #2 */ \ t1 = vu16(vec_nmsub(reA0, vfp(dA0), vfp(one))); \ t2 = vu16(vec_nmsub(reA1, vfp(dA1), vfp(one))); \ t3 = vu16(vec_nmsub(reB0, vfp(dB0), vfp(one))); \ t4 = vu16(vec_nmsub(reB1, vfp(dB1), vfp(one))); \ reA0 = vec_madd(reA0, vfp(t1), reA0); \ reA1 = vec_madd(reA1, vfp(t2), reA1); \ reB0 = vec_madd(reB0, vfp(t3), reB0); \ reB1 = vec_madd(reB1, vfp(t4), reB1); \ \ /* (sA0,sB0) = abs(ps[n],ps[n+1]) << 4 {{{ */ \ t1 = vu16(vec_subs(vs16(zero), srcA)); \ t2 = vu16(vec_subs(vs16(zero), srcB)); \ t3 = vu16(vec_max(srcA, vs16(t1))); \ t4 = vu16(vec_max(srcB, vs16(t2))); \ four = vec_splat_u16(4); \ t1 = vu16(vec_sl(vu16(t3), four)); \ t2 = vu16(vec_sl(vu16(t4), four)); \ /* }}} */ \ \ sA0 = vfp(vec_mergeh(zero, vu16(t1))); \ sA1 = vfp(vec_mergel(zero, vu16(t1))); \ sB0 = vfp(vec_mergeh(zero, vu16(t2))); \ sB1 = vfp(vec_mergel(zero, vu16(t2))); \ sA0 = vfp(vec_ctf(vu32(sA0), 0)); \ sA1 = vfp(vec_ctf(vu32(sA1), 0)); \ sB0 = vfp(vec_ctf(vu32(sB0), 0)); \ sB1 = vfp(vec_ctf(vu32(sB1), 0)); \ \ /* calculate quotient */ \ qtA0 = vfp(vec_madd(vfp(sA0), reA0, vfp(zero))); \ qtA1 = vfp(vec_madd(vfp(sA1), reA1, vfp(zero))); \ qtB0 = vfp(vec_madd(vfp(sB0), reB0, vfp(zero))); \ qtB1 = vfp(vec_madd(vfp(sB1), reB1, vfp(zero))); \ \ /* calculate remainder */ \ rmA0 = vfp(vec_nmsub(vfp(dA0), vfp(qtA0), vfp(sA0))); \ rmA1 = vfp(vec_nmsub(vfp(dA1), vfp(qtA1), vfp(sA1))); \ rmB0 = vfp(vec_nmsub(vfp(dB0), vfp(qtB0), vfp(sB0))); \ rmB1 = vfp(vec_nmsub(vfp(dB1), vfp(qtB1), vfp(sB1))); \ \ /* round quotient with remainder */ \ qtA0 = vfp(vec_madd(vfp(rmA0), reA0, vfp(qtA0))); \ qtA1 = vfp(vec_madd(vfp(rmA1), reA1, vfp(qtA1))); \ qtB0 = vfp(vec_madd(vfp(rmB0), reB0, vfp(qtB0))); \ qtB1 = vfp(vec_madd(vfp(rmB1), reB1, vfp(qtB1))); \ \ /* convert to integer */ \ qtA0 = vfp(vec_ctu(vfp(qtA0), 0)); \ qtA1 = vfp(vec_ctu(vfp(qtA1), 0)); \ qtB0 = vfp(vec_ctu(vfp(qtB0), 0)); \ qtB1 = vfp(vec_ctu(vfp(qtB1), 0)); \ \ dstA = vs16(vec_pack(vu32(qtA0), vu32(qtA1))); \ dstB = vs16(vec_pack(vu32(qtB0), vu32(qtB1))); \ \ /* test for non-zero values */ \ selA = vec_cmpgt(vu16(dstA), zero); \ selB = vec_cmpgt(vu16(dstB), zero); \ nz = vec_or(nz, selA); \ nz = vec_or(nz, selB); \ /* }}} */ #define SIGN_AND_STORE /* {{{ */ \ /* sign dst blocks */ \ selA = vec_cmpgt(vs16(zero), srcA); \ selB = vec_cmpgt(vs16(zero), srcB); \ t1 = vu16(vec_subs(vs16(zero), dstA)); \ t2 = vu16(vec_subs(vs16(zero), dstB)); \ dstA = vec_sel(dstA, vs16(t1), selA); \ dstB = vec_sel(dstB, vs16(t2), selB); \ \ /* store dst blocks */ \ vec_st(dstA, 0, pd); \ pd += 8; \ vec_st(dstB, 0, pd); \ pd += 8; \ /* }}} */ #define UPDATE_NZBLOCKBITS /* {{{ */ \ /* quasi-count the non-zero values and store to vu.s.nz */ \ nz = vb16(vec_sums(vs32(nz), vs32(zero))); \ nz = vb16(vec_splat(vu32(nz), 3)); \ vuv = vec_ld(0, (unsigned short*)&vu); \ /* vuv = ( vuv(mquant, clipvalue), nz, (), () ) */ \ vuv = vu16(vec_mergeh(vu32(vuv), vu32(nz))); \ vec_st(vuv, 0, (unsigned short*)&vu); /* store for scalar access */ \ nzblockbits |= ((!!vu.s.nz) << i); /* set non-zero block bit */ \ /* }}} */ AMBER_START; /* 0x01080010 = ((1<<24) & 0x1F000000)|((8<<16) & 0x00FF0000)|(16 & 0xFFFF) */ ps = src; pd = dst; #ifdef ALTIVEC_DST vec_dst(inter_q_mat, 0x01080010, 0); vec_dst(ps, 0x01040010, 1); vec_dstst(pd, 0x01040010, 2); #endif vu.s.mquant = mquant; vu.s.clipvalue = dctsatlim; zero = vec_splat_u16(0); one = vfp(vec_splat_u32(1)); one = vec_ctf(vu32(one), 0); nzblockbits = 0; N = BLOCK_COUNT; i = N; last_block = 0; /* counting down from i */ recalc_blocks = 0; do { recalc: pqm = inter_q_mat; nz = vb16(vec_splat_u16(0)); max = vec_splat_u16(0); j = 4; do { #ifdef ALTIVEC_DST vec_dst(ps, 0x01040010, 1); vec_dstst(pd, 0x01040010, 2); #endif QUANT_NON_INTRA_AB; max = vec_max(max, vu16(dstA)); max = vec_max(max, vu16(dstB)); SIGN_AND_STORE; } while (--j); /* check for clipping/saturation {{{ */ vuv = vec_ld(0, (unsigned short*)&vu); vuv = vec_splat(vuv, 1); /* splat clipvalue */ if (vec_any_gt(max, vuv)) { int next_mquant = next_larger_quant(q_scale_type, mquant); if (next_mquant == mquant) { /* saturation has occured, clip values then * goto saturated jump point. */ pd -= 8*8; /* reset pointer to beginning of block */ j = 4; do { srcA = vec_ld(0, pd); pd += 8; srcB = vec_ld(0, pd); /* (dstA,dstB) = abs(srcA,srcB) {{{ */ t1 = vu16(vec_subs(vs16(zero), srcA)); t2 = vu16(vec_subs(vs16(zero), srcB)); dstA = vec_max(srcA, vs16(t1)); dstB = vec_max(srcB, vs16(t2)); /* }}} */ /* (dstA,dstB) = clip(dstA,dstB, vuv) {{{ */ dstA = vs16(vec_min(vu16(dstA), vuv)); dstB = vs16(vec_min(vu16(dstB), vuv)); /* }}} */ /* restore sign {{{ */ selA = vec_cmpgt(vs16(zero), srcA); selB = vec_cmpgt(vs16(zero), srcB); t1 = vu16(vec_subs(vs16(zero), dstA)); t2 = vu16(vec_subs(vs16(zero), dstB)); dstA = vec_sel(dstA, vs16(t1), selA); dstB = vec_sel(dstB, vs16(t2), selB); /* }}} */ pd -= 8; vec_st(dstA, 0, pd); pd += 8; vec_st(dstB, 0, pd); pd += 8; } while (--j); goto saturated; } /* load new (int)mquant into (short)vu.s.mquant */ mquant = next_mquant; vu.s.mquant = next_mquant; nzblockbits = 0; recalc_blocks = N - i; /* reset pointers to beginning of block */ ps -= 8*8; pd -= 8*8; goto recalc; } /* }}} */ i--; UPDATE_NZBLOCKBITS; } while (i); /* recalculate blocks if necessary. this branch of code does not * need to worry about saturation or clipping. */ if (recalc_blocks > 0) { i = N; last_block = N - recalc_blocks; ps = src; pd = dst; do { pqm = inter_q_mat; nz = vb16(vec_splat_u16(0)); j = 4; do { #ifdef ALTIVEC_DST vec_dst(ps, 0x01040010, 1); vec_dstst(pd, 0x01040010, 2); #endif QUANT_NON_INTRA_AB; SIGN_AND_STORE; } while (--j); i--; UPDATE_NZBLOCKBITS; } while (i > last_block); } goto done; /* * the following code is entered at the label 'saturated'. * this branch of code clips the destination values. */ do { i = N; last_block = N - recalc_blocks; ps = src; pd = dst; recalc_blocks = 0; /* no more blocks after next loop */ do { pqm = inter_q_mat; nz = vb16(vec_splat_u16(0)); j = 4; do { #ifdef ALTIVEC_DST vec_dst(ps, 0x01040010, 1); vec_dstst(pd, 0x01040010, 2); #endif QUANT_NON_INTRA_AB; /* clip {{{ */ vuv = vec_ld(0, (unsigned short*)&vu); vuv = vec_splat(vuv, 1); /* splat clipvalue */ dstA = vs16(vec_min(vu16(dstA), vuv)); dstB = vs16(vec_min(vu16(dstB), vuv)); /* }}} */ SIGN_AND_STORE; } while (--j); saturated: i--; UPDATE_NZBLOCKBITS; } while (i > last_block); } while (recalc_blocks > 0); done: #ifdef ALTIVEC_DST vec_dssall(); #endif *nonsat_mquant = mquant; AMBER_STOP; return nzblockbits; } #if ALTIVEC_TEST_FUNCTION(quant_non_intra) /* {{{ */ # ifdef ALTIVEC_VERIFY int quant_non_intra_altivec_verify(QUANT_NON_INTRA_PDECL) { int i, len, nzb1, nzb2, nsmq, nsmq1, nsmq2; unsigned long checksum1, checksum2; int16_t *dstcpy; uint16_t *inter_q = (uint16_t*)wsp->inter_q_mat; len = 64 * BLOCK_COUNT; dstcpy = (int16_t*)malloc(len*sizeof(int16_t)); if (dstcpy == NULL) mjpeg_error_exit1("quant_non_intra_verify: unable to malloc"); /* save nonsat_mquant */ nsmq = *nonsat_mquant; nzb1 = quant_non_intra_altivec(QUANT_NON_INTRA_ARGS); nsmq1 = *nonsat_mquant; for (checksum1 = i = 0; i < len; i++) checksum1 += abs(dst[i]); memcpy(dstcpy, dst, len*sizeof(int16_t)); /* restore nonsat_mquant */ *nonsat_mquant = nsmq; nzb2 = ALTIVEC_TEST_WITH(quant_non_intra)(QUANT_NON_INTRA_ARGS); nsmq2 = *nonsat_mquant; for (checksum2 = i = 0; i < len; i++) checksum2 += abs(dst[i]); if (nzb1 != nzb2 || checksum1 != checksum2 || nsmq1 != nsmq2) { mjpeg_debug("quant_non_intra(" QUANT_NON_INTRA_PFMT ")", QUANT_NON_INTRA_ARGS); mjpeg_debug("quant_non_intra: results differ " "{nzb=%d, checksum=%d, mquant=%d} != " "{nzb=%d, checksum=%d, mquant=%d}", nzb1, checksum1, nsmq1, nzb2, checksum2, nsmq2); } for (i = 0; i < len; i++) { if (dstcpy[i] != dst[i]) { mjpeg_debug("quant_non_intra: src[%d]=%d, qmat=%d, " "dst %d != %d", i, src[i], inter_q[i&63], dstcpy[i], dst[i]); } } free(dstcpy); return nzb2; } # else ALTIVEC_TEST(quant_non_intra, int, (QUANT_NON_INTRA_PDECL), QUANT_NON_INTRA_PFMT, QUANT_NON_INTRA_ARGS); # endif #endif /* }}} */ /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/field_dct_best.c0000644000175000017500000002005607741374325022115 0ustar glowwormglowworm/* field_dct_best.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2003 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_transform.h" #include "vectorize.h" #include "../mjpeg_logging.h" #include /* sqrt */ /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif #define FRAME_DCT 0 /* frame DCT */ #define FIELD_DCT 1 /* field DCT */ #define FIELD_DCT_BEST_PDECL uint8_t *cur_lum_mb, uint8_t *pred_lum_mb, int stride #define FIELD_DCT_BEST_ARGS cur_lum_mb, pred_lum_mb, stride int field_dct_best_altivec(FIELD_DCT_BEST_PDECL) { /* * calculate prediction error (cur-pred) for top (blk0) * and bottom field (blk1) */ double r, d; int sumtop, sumbot, sumsqtop, sumsqbot, sumbottop; int topvar, botvar; int whichdct; int i; vector unsigned char ct, pt, cb, pb; vector unsigned char *ctp, *ptp, *cbp, *pbp; unsigned int offset, stride2; vector signed short cur, pred; vector signed short dift, difb; vector signed int vsumtop, vsumbot, vsumsqtop, vsumsqbot, vsumbottop; vector signed int t0, t1, t2, t3; vector signed int zero; union { vector signed int v; struct { signed int top; signed int bot; signed int sqtop; signed int sqbot; } sum; struct { signed int pad[3]; signed int sum; } bottop; } vo; AMBER_START; #ifdef ALTIVEC_VERIFY if (NOT_VECTOR_ALIGNED(cur_lum_mb)) mjpeg_error_exit1("field_dct_best: cur_lum_mb %% 16 != 0, (%d)\n", cur_lum_mb); if (NOT_VECTOR_ALIGNED(pred_lum_mb)) mjpeg_error_exit1("field_dct_best: pred_lum_mb %% 16 != 0, (%d)\n", pred_lum_mb); if (NOT_VECTOR_ALIGNED(stride)) mjpeg_error_exit1("field_dct_best: stride %% 16 != 0, (%d)\n", stride); #endif zero = vec_splat_s32(0); vsumtop = vec_splat_s32(0); vsumbot = vec_splat_s32(0); vsumsqtop = vec_splat_s32(0); vsumsqbot = vec_splat_s32(0); vsumbottop = vec_splat_s32(0); ctp = (vector unsigned char*) cur_lum_mb; ptp = (vector unsigned char*) pred_lum_mb; cbp = (vector unsigned char*)(cur_lum_mb + stride); pbp = (vector unsigned char*)(pred_lum_mb + stride); offset = 0; stride2 = stride << 1; #if 1 ct = vec_ld(offset, ctp); pt = vec_ld(offset, ptp); cb = vec_ld(offset, cbp); pb = vec_ld(offset, pbp); i = 16/2 - 1; do { cur = (vector signed short)vec_mergeh(vu8(zero), ct); pred = (vector signed short)vec_mergeh(vu8(zero), pt); dift = vec_sub(cur, pred); cur = (vector signed short)vec_mergeh(vu8(zero), cb); pred = (vector signed short)vec_mergeh(vu8(zero), pb); difb = vec_sub(cur, pred); vsumtop = vec_sum4s(dift, vsumtop); vsumbot = vec_sum4s(difb, vsumbot); vsumsqtop = vec_msum(dift, dift, vsumsqtop); vsumsqbot = vec_msum(difb, difb, vsumsqbot); vsumbottop = vec_msum(dift, difb, vsumbottop); cur = (vector signed short)vec_mergel(vu8(zero), ct); pred = (vector signed short)vec_mergel(vu8(zero), pt); dift = vec_sub(cur, pred); cur = (vector signed short)vec_mergel(vu8(zero), cb); pred = (vector signed short)vec_mergel(vu8(zero), pb); difb = vec_sub(cur, pred); offset += stride2; ct = vec_ld(offset, ctp); pt = vec_ld(offset, ptp); cb = vec_ld(offset, cbp); pb = vec_ld(offset, pbp); vsumtop = vec_sum4s(dift, vsumtop); vsumbot = vec_sum4s(difb, vsumbot); vsumsqtop = vec_msum(dift, dift, vsumsqtop); vsumsqbot = vec_msum(difb, difb, vsumsqbot); vsumbottop = vec_msum(dift, difb, vsumbottop); } while (--i); cur = (vector signed short)vec_mergeh(vu8(zero), ct); pred = (vector signed short)vec_mergeh(vu8(zero), pt); dift = vec_sub(cur, pred); cur = (vector signed short)vec_mergeh(vu8(zero), cb); pred = (vector signed short)vec_mergeh(vu8(zero), pb); difb = vec_sub(cur, pred); vsumtop = vec_sum4s(dift, vsumtop); vsumbot = vec_sum4s(difb, vsumbot); vsumsqtop = vec_msum(dift, dift, vsumsqtop); vsumsqbot = vec_msum(difb, difb, vsumsqbot); vsumbottop = vec_msum(dift, difb, vsumbottop); cur = (vector signed short)vec_mergel(vu8(zero), ct); pred = (vector signed short)vec_mergel(vu8(zero), pt); dift = vec_sub(cur, pred); cur = (vector signed short)vec_mergel(vu8(zero), cb); pred = (vector signed short)vec_mergel(vu8(zero), pb); difb = vec_sub(cur, pred); vsumtop = vec_sum4s(dift, vsumtop); vsumbot = vec_sum4s(difb, vsumbot); vsumsqtop = vec_msum(dift, dift, vsumsqtop); vsumsqbot = vec_msum(difb, difb, vsumsqbot); vsumbottop = vec_msum(dift, difb, vsumbottop); #else for (i = 0; i < 16/2; i++) { /* {{{ */ ct = vec_ld(offset, ctp); pt = vec_ld(offset, ptp); cb = vec_ld(offset, cbp); pb = vec_ld(offset, pbp); cur = (vector signed short)vec_mergeh(vu8(zero), ct); pred = (vector signed short)vec_mergeh(vu8(zero), pt); dift = vec_sub(cur, pred); cur = (vector signed short)vec_mergeh(vu8(zero), cb); pred = (vector signed short)vec_mergeh(vu8(zero), pb); difb = vec_sub(cur, pred); vsumtop = vec_sum4s(dift, vsumtop); vsumbot = vec_sum4s(difb, vsumbot); vsumsqtop = vec_msum(dift, dift, vsumsqtop); vsumsqbot = vec_msum(difb, difb, vsumsqbot); vsumbottop = vec_msum(dift, difb, vsumbottop); cur = (vector signed short)vec_mergel(vu8(zero), ct); pred = (vector signed short)vec_mergel(vu8(zero), pt); dift = vec_sub(cur, pred); cur = (vector signed short)vec_mergel(vu8(zero), cb); pred = (vector signed short)vec_mergel(vu8(zero), pb); difb = vec_sub(cur, pred); vsumtop = vec_sum4s(dift, vsumtop); vsumbot = vec_sum4s(difb, vsumbot); vsumsqtop = vec_msum(dift, dift, vsumsqtop); vsumsqbot = vec_msum(difb, difb, vsumsqbot); vsumbottop = vec_msum(dift, difb, vsumbottop); offset += stride2; } /* }}} */ #endif /* transpose [sumtop, sumbot, sumsqtop, sumsqbot] {{{ */ t0 = vec_mergel(vsumtop, vsumsqtop); t1 = vec_mergeh(vsumtop, vsumsqtop); t2 = vec_mergel(vsumbot, vsumsqbot); t3 = vec_mergeh(vsumbot, vsumsqbot); vsumtop = vec_mergeh(t1, t3); vsumbot = vec_mergel(t1, t3); vsumsqtop = vec_mergeh(t0, t2); vsumsqbot = vec_mergel(t0, t2); /* }}} */ /* sum final values for sumtop, sumbot, sumsqtop, sumsqbot */ vsumtop = vec_add(vsumtop, vsumbot); vsumsqtop = vec_add(vsumsqtop, vsumsqbot); vo.v = vec_add(vsumtop, vsumsqtop); sumtop = vo.sum.top; sumbot = vo.sum.bot; sumsqtop = vo.sum.sqtop; sumsqbot = vo.sum.sqbot; vsumbottop = vec_sums(vsumbottop, zero); vo.v = vsumbottop; /* Calculate Variances top and bottom. If they're of similar sign estimate correlation if its good use frame DCT otherwise use field. */ whichdct = FIELD_DCT; r = 0.0; topvar = sumsqtop-sumtop*sumtop/128; botvar = sumsqbot-sumbot*sumbot/128; if (!((topvar > 0) ^ (botvar > 0))) { sumbottop = vo.bottop.sum; d = ((double) topvar) * ((double)botvar); r = (sumbottop-(sumtop*sumbot)/128); if (r > (0.5 * sqrt(d))) whichdct = FRAME_DCT; } AMBER_STOP; return whichdct; } #if ALTIVEC_TEST_FUNCTION(field_dct_best) /* {{{ */ ALTIVEC_TEST(field_dct_best, int, (FIELD_DCT_BEST_PDECL), "cur_lum_mb=0x%X, pred_lum_mb=0%X, stride=%d", FIELD_DCT_BEST_ARGS); #endif /* }}} */ /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/sub_mean_reduction.c0000644000175000017500000001314110162171523023007 0ustar glowwormglowworm/* sub_mean_reduction.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_motion.h" #if defined(ALTIVEC_VERIFY) && ALTIVEC_TEST_FUNCTION(sub_mean_reduction) #include /* malloc */ #include /* memcpy */ #endif #include "vectorize.h" #include #include "../mjpeg_logging.h" /* #define AMBER_ENABLE */ /* #define AMBER_MAX_TRACES 100 */ #include "amber.h" #define SUB_MEAN_REDUCTION_PDECL /* {{{ */ \ me_result_set *matchset, \ int rtimes, \ int *minweight_res \ /* }}} */ #define SUB_MEAN_REDUCTION_ARGS matchset, rtimes, minweight_res void sub_mean_reduction_altivec(SUB_MEAN_REDUCTION_PDECL) { me_result_s *matches, *match, *tail; me_result_s m0, m1; int w0, w1; int i; int len = matchset->len; int weight_sum; int mean_weight; AMBER_START; if (len <= 1) { *minweight_res = (len == 0 ? 100000 : matchset->mests[0].weight); } else { matches = matchset->mests; weight_sum = 0; match = matches - 1; if (len > 1) { i = len >> 1; do { w0 = (*(++match)).weight; weight_sum += w0; w1 = (*(++match)).weight; weight_sum += w1; } while (--i); } if (len & 1) weight_sum += (*(++match)).weight; mean_weight = weight_sum / len; while (rtimes--) { weight_sum = 0; match = matches - 1; tail = match; if (len > 1) { i = len >> 1; do { m0 = *(++match); w0 = m0.weight; m1 = *(++match); w1 = m1.weight; if (w0 <= mean_weight) { *(++tail) = m0; weight_sum += w0; } if (w1 <= mean_weight) { *(++tail) = m1; weight_sum += w1; } } while (--i); } if (len & 1) { m0 = *(++match); w0 = m0.weight; if (w0 <= mean_weight) { *(++tail) = m0; weight_sum += w0; } } tail++; /* adjust for -1 */ len = tail - matches; mean_weight = weight_sum / len; } matchset->len = len; *minweight_res = mean_weight; } AMBER_STOP; } #if ALTIVEC_TEST_FUNCTION(sub_mean_reduction) /* {{{ */ #define SUB_MEAN_REDUCTION_PFMT /* {{{ */ \ "matchset=0x%X, rtimes=%d, minweight_res=0x%X" \ /* }}} */ # ifdef ALTIVEC_VERIFY void sub_mean_reduction_altivec_verify(SUB_MEAN_REDUCTION_PDECL) { int i, len, len1, len2, mwr, mwr1, mwr2; me_result_s *mestscpy; unsigned long checksum1, checksum2; /* save len */ len = matchset->len; mestscpy = (me_result_s*)malloc(len*sizeof(me_result_s)); if (mestscpy == NULL) mjpeg_error_exit1("sub_mean_reduction: malloc failed"); /* save mests */ memcpy(mestscpy, matchset->mests, len*sizeof(me_result_s)); /* save minweight_res */ mwr = *minweight_res; sub_mean_reduction_altivec(SUB_MEAN_REDUCTION_ARGS); len1 = matchset->len; mwr1 = *minweight_res; for (checksum1 = i = 0; i < len1; i++) { checksum1 += matchset->mests[i].weight; checksum1 += abs(matchset->mests[i].x); checksum1 += abs(matchset->mests[i].y); } /* restore len */ matchset->len = len; /* restore mests */ memcpy(matchset->mests, mestscpy, len*sizeof(me_result_s)); /* restore minweight_res */ *minweight_res = mwr; ALTIVEC_TEST_WITH(sub_mean_reduction)(SUB_MEAN_REDUCTION_ARGS); len2 = matchset->len; mwr2 = *minweight_res; for (checksum2 = i = 0; i < len2; i++) { checksum2 += matchset->mests[i].weight; checksum2 += abs(matchset->mests[i].x); checksum2 += abs(matchset->mests[i].y); } if (len1 != len2 || checksum1 != checksum2 || mwr1 != mwr2) { mjpeg_debug("sub_mean_reduction(" SUB_MEAN_REDUCTION_PFMT ")", SUB_MEAN_REDUCTION_ARGS); mjpeg_debug("sub_mean_reduction: matchset->len=%d", len); mjpeg_debug("sub_mean_reduction: minweight_res %d, %d", mwr1, mwr2); mjpeg_debug("sub_mean_reduction: checksums %d[%d], %d[%d]", checksum1, len1, checksum2, len2); } free(mestscpy); } # else #undef BENCHMARK_PROLOG #define BENCHMARK_PROLOG /* {{{ */ \ mjpeg_info("sub_mean_reduction: in matchset->len=%d", \ matchset->len); \ /* }}} */ #undef BENCHMARK_EPILOG #define BENCHMARK_EPILOG /* {{{ */ \ mjpeg_info("sub_mean_reduction: out matchset->len=%d, *minweight_res=%d",\ matchset->len, *minweight_res); \ /* }}} */ ALTIVEC_TEST(sub_mean_reduction, void, (SUB_MEAN_REDUCTION_PDECL), SUB_MEAN_REDUCTION_PFMT, SUB_MEAN_REDUCTION_ARGS); # endif #endif /* }}} */ /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/iquant_non_intra.c0000644000175000017500000003200410254174615022520 0ustar glowwormglowworm/* iquant_non_intra_m1.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_quantize.h" #if defined(ALTIVEC_VERIFY) && ALTIVEC_TEST_FUNCTION(iquant_non_intra_m1) # include #endif #include "vectorize.h" #include "../mjpeg_logging.h" #include "../../mpeg2enc/quantize_precomp.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif #define IQUANT_NON_INTRA_PDECL \ struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int mquant #define IQUANT_NON_INTRA_ARGS wsp, src, dst, mquant #define IQUANT_NON_INTRA_PFMT "wsp=0x%X, src=0x%X, dst=0x%X, mquant=%d" void iquant_non_intra_m1_altivec(IQUANT_NON_INTRA_PDECL) { int i; vector signed short vsrc; uint16_t *qmat; vector unsigned short vqmat; vector unsigned short vmquant; vector signed short val, t0; vector bool short ltzero, eqzero; vector signed short zero, one; vector unsigned int five; vector signed short min, max; union { vector unsigned short v; unsigned short mquant[8]; } vu; #ifdef ALTIVEC_DST DataStreamControl dsc; #endif #ifdef ALTIVEC_VERIFY /* {{{ */ if (NOT_VECTOR_ALIGNED(wsp->inter_q_mat)) mjpeg_error_exit1("iquant_non_intra_m1: wsp->inter_q_mat %% 16 != 0, " "(%d)", wsp->inter_q_mat); if (NOT_VECTOR_ALIGNED(src)) mjpeg_error_exit1("iquant_non_intra_m1: src %% 16 != 0, (%d)", src); if (NOT_VECTOR_ALIGNED(dst)) mjpeg_error_exit1("iquant_non_intra_m1: dst %% 16 != 0, (%d)", dst); for (i = 0; i < 64; i++) if (src[i] < -256 || src[i] > 255) mjpeg_error_exit1("iquant_non_intra_m1: -256 > src[%i] > 255, (%d)", i, src[i]); #endif /* }}} */ AMBER_START; qmat = (uint16_t*)wsp->inter_q_mat; #ifdef ALTIVEC_DST dsc.control = DATA_STREAM_CONTROL(64/8,1,0); vec_dst(src, dsc.control, 0); vec_dst(qmat, dsc.control, 1); #endif vu.mquant[0] = (unsigned short)mquant; vmquant = vec_splat(vu.v, 0); vsrc = vec_ld(0, (signed short*)src); vqmat = vec_ld(0, qmat); zero = vec_splat_s16(0); one = vec_splat_s16(1); five = vec_splat_u32(5); /* max = (2047); min = (-2048); {{{ */ max = vs16(vec_splat_u8(0x7)); t0 = vec_splat_s16(-1); /* 0xffff */ max = vs16(vec_mergeh(vu8(max), vu8(t0))); /* 0x07ff == 2047 */ min = vec_sub(t0, max); /* }}} */ i = (64/8) - 1; do { /* inter_q[i] * mquant */ vqmat = vu16(vec_mulo(vu8(vqmat), vu8(vmquant))); ltzero = vec_cmplt(vsrc, zero); eqzero = vec_cmpeq(vsrc, zero); /* val = abs(src) */ t0 = vec_sub(zero, vsrc); val = vec_max(t0, vsrc); /* val = val + val + 1 */ val = vec_add(val, val); val = vec_add(val, one); /* val = (val * quant) >> 5 */ t0 = vs16(vec_mule(vu16(val), vqmat)); t0 = vs16(vec_sra(vu32(t0), five)); t0 = vs16(vec_pack(vu32(t0), vu32(t0))); val = vs16(vec_mulo(vu16(val), vqmat)); val = vs16(vec_sra(vu32(val), five)); val = vs16(vec_pack(vu32(val), vu32(val))); val = vs16(vec_mergeh(vu16(t0), vu16(val))); src += 8; vsrc = vec_ld(0, (signed short*)src); qmat += 8; vqmat = vec_ld(0, (unsigned short*)qmat); /* val = val - 1&~(val|val==0) */ t0 = vec_or(val, eqzero); t0 = vec_andc(one, t0); val = vec_sub(val, t0); /* val = samesign(src, val) */ t0 = vec_sub(zero, val); val = vec_sel(val, t0, ltzero); /* val = (val > 2047) ? ((val < -2048) ? -2048 : val); */ val = vec_min(val, max); val = vec_max(val, min); /* if (src[i] == 0) dst[i] = 0 */ val = vec_andc(val, eqzero); vec_st(val, 0, dst); dst += 8; } while (--i); /* inter_q[i] * mquant */ vqmat = vu16(vec_mulo(vu8(vqmat), vu8(vmquant))); ltzero = vec_cmplt(vsrc, zero); eqzero = vec_cmpeq(vsrc, zero); /* val = abs(src) */ t0 = vec_sub(zero, vsrc); val = vec_max(t0, vsrc); /* val = val + val + 1 */ val = vec_add(val, val); val = vec_add(val, one); /* val = (val * quant) >> 5 */ t0 = vs16(vec_mule(vu16(val), vqmat)); t0 = vs16(vec_sra(vu32(t0), five)); t0 = vs16(vec_pack(vu32(t0), vu32(t0))); val = vs16(vec_mulo(vu16(val), vqmat)); val = vs16(vec_sra(vu32(val), five)); val = vs16(vec_pack(vu32(val), vu32(val))); val = vs16(vec_mergeh(vu16(t0), vu16(val))); /* val = val - 1&~(val|val==0) */ t0 = vec_or(val, eqzero); t0 = vec_andc(one, t0); val = vec_sub(val, t0); /* val = samesign(src, val) */ t0 = vec_sub(zero, val); val = vec_sel(val, t0, ltzero); /* val = (val > 2047) ? ((val < -2048) ? -2048 : val); */ val = vec_min(val, max); val = vec_max(val, min); /* if (src[i] == 0) dst[i] = 0 */ val = vec_andc(val, eqzero); vec_st(val, 0, dst); AMBER_STOP; } void iquant_non_intra_m2_altivec(IQUANT_NON_INTRA_PDECL) { int i; vector signed short vsrc; uint16_t *qmat; vector unsigned short vqmat; vector unsigned short vmquant; vector signed short val, t0; vector bool short ltzero, eqzero; vector signed short zero, one; vector unsigned int five; vector signed short min, max; vector signed int sum; int offset, offset2; union { vector unsigned short vu16; unsigned short mquant; vector signed int vs32; struct { signed int pad[3]; signed int sum; } s; } vu; #ifdef ALTIVEC_DST DataStreamControl dsc; #endif #ifdef ALTIVEC_VERIFY /* {{{ */ if (NOT_VECTOR_ALIGNED(wsp->inter_q_mat)) mjpeg_error_exit1("iquant_non_intra_m2: wsp->inter_q_mat %% 16 != 0, " "(%d)", wsp->inter_q_mat); if (NOT_VECTOR_ALIGNED(src)) mjpeg_error_exit1("iquant_non_intra_m2: src %% 16 != 0, (%d)", src); if (NOT_VECTOR_ALIGNED(dst)) mjpeg_error_exit1("iquant_non_intra_m2: dst %% 16 != 0, (%d)", dst); for (i = 0; i < 64; i++) if (src[i] < -256 || src[i] > 255) mjpeg_error_exit1("iquant_non_intra_m2: -256 > src[%i] > 255, (%d)", i, src[i]); #endif /* }}} */ AMBER_START; qmat = (uint16_t*)wsp->inter_q_mat; #ifdef ALTIVEC_DST dsc.control = DATA_STREAM_CONTROL(64/8,1,0); vec_dst(src, dsc.control, 0); vec_dst(qmat, dsc.control, 1); #endif /* vmquant = (vector unsigned short)(mquant); */ vu.mquant = (unsigned short)mquant; vmquant = vec_splat(vu.vu16, 0); sum = vec_splat_s32(0); zero = vec_splat_s16(0); one = vec_splat_s16(1); five = vec_splat_u32(5); /* max = (2047); min = (-2048); {{{ */ max = vs16(vec_splat_u8(0x7)); t0 = vec_splat_s16(-1); /* 0xffff */ max = vs16(vec_mergeh(vu8(max), vu8(t0))); /* 0x07ff == 2047 */ min = vec_sub(t0, max); /* }}} */ offset = 0; #if 1 vsrc = vec_ld(offset, (signed short*)src); vqmat = vec_ld(offset, (unsigned short*)qmat); i = (64/8) - 1; do { /* inter_q[i] * mquant */ vqmat = vu16(vec_mulo(vu8(vqmat), vu8(vmquant))); ltzero = vec_cmplt(vsrc, zero); eqzero = vec_cmpeq(vsrc, zero); /* val = abs(src) */ t0 = vec_sub(zero, vsrc); val = vec_max(t0, vsrc); /* val = val + val + 1 */ val = vec_add(val, val); val = vec_add(val, one); /* val = (val * quant) >> 5 */ t0 = vs16(vec_mule(vu16(val), vqmat)); t0 = vs16(vec_sra(vu32(t0), five)); t0 = vs16(vec_pack(vu32(t0), vu32(t0))); val = vs16(vec_mulo(vu16(val), vqmat)); val = vs16(vec_sra(vu32(val), five)); val = vs16(vec_pack(vu32(val), vu32(val))); val = vs16(vec_mergeh(vu16(t0), vu16(val))); offset2 = offset; offset += 8*sizeof(int16_t); vsrc = vec_ld(offset, (signed short*)src); vqmat = vec_ld(offset, (unsigned short*)qmat); /* val = samesign(src, val) */ t0 = vec_sub(zero, val); val = vec_sel(val, t0, ltzero); /* val = (val > 2047) ? ((val < -2048) ? -2048 : val); */ val = vec_min(val, max); val = vec_max(val, min); /* if (src[i] == 0) dst[i] = 0 */ val = vec_andc(val, eqzero); sum = vec_sum4s(val, sum); vec_st(val, offset2, dst); } while (--i); /* inter_q[i] * mquant */ vqmat = vu16(vec_mulo(vu8(vqmat), vu8(vmquant))); ltzero = vec_cmplt(vsrc, zero); eqzero = vec_cmpeq(vsrc, zero); /* val = abs(src) */ t0 = vec_sub(zero, vsrc); val = vec_max(t0, vsrc); /* val = val + val + 1 */ val = vec_add(val, val); val = vec_add(val, one); /* val = (val * quant) >> 5 */ t0 = vs16(vec_mule(vu16(val), vqmat)); t0 = vs16(vec_sra(vu32(t0), five)); t0 = vs16(vec_pack(vu32(t0), vu32(t0))); val = vs16(vec_mulo(vu16(val), vqmat)); val = vs16(vec_sra(vu32(val), five)); val = vs16(vec_pack(vu32(val), vu32(val))); val = vs16(vec_mergeh(vu16(t0), vu16(val))); /* val = samesign(src, val) */ t0 = vec_sub(zero, val); val = vec_sel(val, t0, ltzero); /* val = (val > 2047) ? ((val < -2048) ? -2048 : val); */ val = vec_min(val, max); val = vec_max(val, min); /* if (src[i] == 0) dst[i] = 0 */ val = vec_andc(val, eqzero); sum = vec_sum4s(val, sum); vec_st(val, offset, dst); #else /* {{{ */ i = (64/8); do { vsrc = vec_ld(offset, (signed short*)src); vqmat = vec_ld(offset, (unsigned short*)qmat); /* inter_q[i] * mquant */ vu16(vqmat) = vec_mulo(vu8(vqmat), vu8(vmquant)); ltzero = vec_cmplt(vsrc, zero); eqzero = vec_cmpeq(vsrc, zero); /* val = abs(src) */ t0 = vec_sub(zero, vsrc); val = vec_max(t0, vsrc); /* val = val + val + 1 */ val = vec_add(val, val); val = vec_add(val, one); /* val = (val * quant) >> 5 */ vu32(t0) = vec_mule(vu16(val), vqmat); vu32(t0) = vec_sra(vu32(t0), five); vu16(t0) = vec_pack(vu32(t0), vu32(t0)); vu32(val) = vec_mulo(vu16(val), vqmat); vu32(val) = vec_sra(vu32(val), five); vu16(val) = vec_pack(vu32(val), vu32(val)); vu16(val) = vec_mergeh(vu16(t0), vu16(val)); /* val = samesign(src, val) */ t0 = vec_sub(zero, val); val = vec_sel(val, t0, ltzero); /* val = (val > 2047) ? ((val < -2048) ? -2048 : val); */ val = vec_min(val, max); val = vec_max(val, min); /* if (src[i] == 0) dst[i] = 0 */ val = vec_andc(val, eqzero); sum = vec_sum4s(val, sum); vec_st(val, offset, dst); offset += 8*sizeof(int16_t); } while (--i); /* }}} */ #endif /* mismatch control */ vu.vs32 = vec_sums(sum, vs32(zero)); #if 1 dst[63] ^= !(vu.s.sum & 1); #else if ((vu.s.sum & 1) == 0) dst[63] ^= 1; #endif AMBER_STOP; } /* iquant_non_intra_altivec_verify {{{ */ #if ALTIVEC_TEST_FUNCTION(iquant_non_intra_m1) || \ ALTIVEC_TEST_FUNCTION(iquant_non_intra_m2) static void iquant_non_intra_altivec_verify(IQUANT_NON_INTRA_PDECL, void (*test)(IQUANT_NON_INTRA_PDECL), void (*verify)(IQUANT_NON_INTRA_PDECL)) { int i; unsigned long checksum1, checksum2; int16_t srccpy[64], dstcpy[64]; uint16_t *qmat; qmat = (uint16_t*)wsp->inter_q_mat; /* in case src == dst */ memcpy(srccpy, src, 64*sizeof(int16_t)); (*test)(IQUANT_NON_INTRA_ARGS); for (checksum1 = i = 0; i < 64; i++) checksum1 += dst[i]; memcpy(dstcpy, dst, 64*sizeof(int16_t)); memcpy(src, srccpy, 64*sizeof(int16_t)); (*verify)(IQUANT_NON_INTRA_ARGS); for (checksum2 = i = 0; i < 64; i++) checksum2 += dst[i]; if (checksum1 != checksum2) { mjpeg_debug("iquant_non_intra(" IQUANT_NON_INTRA_PFMT ")", IQUANT_NON_INTRA_ARGS); mjpeg_debug("iquant_non_intra: checksums differ %d != %d", checksum1, checksum2); } for (i = 0; i < 64; i++) { if (dstcpy[i] != dst[i]) { mjpeg_debug("iquant_non_intra: src[%d]=%d, qmat=%d, " "dst %d != %d", i, srccpy[i], qmat[i]*mquant, dstcpy[i], dst[i]); } } } #endif /* }}} */ #if ALTIVEC_TEST_FUNCTION(iquant_non_intra_m1) /* {{{ */ # ifdef ALTIVEC_VERIFY void iquant_non_intra_m1_altivec_verify(IQUANT_NON_INTRA_PDECL) { iquant_non_intra_altivec_verify(IQUANT_NON_INTRA_ARGS, iquant_non_intra_m1_altivec, ALTIVEC_TEST_WITH(iquant_non_intra_m1)); } # else ALTIVEC_TEST(iquant_non_intra_m1, void, (IQUANT_NON_INTRA_PDECL), IQUANT_NON_INTRA_PFMT, IQUANT_NON_INTRA_ARGS); # endif #endif /* }}} */ #if ALTIVEC_TEST_FUNCTION(iquant_non_intra_m2) /* {{{ */ # ifdef ALTIVEC_VERIFY void iquant_non_intra_m2_altivec_verify(IQUANT_NON_INTRA_PDECL) { iquant_non_intra_altivec_verify(IQUANT_NON_INTRA_ARGS, iquant_non_intra_m2_altivec, ALTIVEC_TEST_WITH(iquant_non_intra_m2)); } # else ALTIVEC_TEST(iquant_non_intra_m2, void, (IQUANT_NON_INTRA_PDECL), IQUANT_NON_INTRA_PFMT, IQUANT_NON_INTRA_ARGS); # endif #endif /* }}} */ /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/sad_11.c0000644000175000017500000002112010462765416020223 0ustar glowwormglowworm/* sad_11.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_motion.h" #include "vectorize.h" #include "../mjpeg_logging.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif /* * SAD with horizontal and vertical half pel interpolation * * Input requirements: * a) blk2 is always vector aligned * b) rowstride is a multiple of 16 * c) h is either 8 or 16 * * s = rowstride * for (j = 0; j < h; j++) { * for (i = 0; i < 16; i++) * sum += abs( ((int)(pB[i]+pB[i+1]+pB[i+s]+pB[i+s+1]+2)>>2) - pR[i] ); * pB += s; * pR += s; * } */ #define SAD_11_PDECL /* {{{ */ \ uint8_t *blk1, \ uint8_t *blk2, \ int rowstride, \ int h \ /* }}} */ #define SAD_11_ARGS blk1, blk2, rowstride, h #define SAD_11_PFMT "blk1=0x%X, blk2=0x%X, rowstride=%d, h=%d" int sad_11_altivec(SAD_11_PDECL) { int i; unsigned char *pB, *pR; vector unsigned char l0, l1, l2, l3, lR, lB0, lB1, lB2, lB3, perm, perm1; vector unsigned short b0H, b0L, b1H, b1L, b2H, b2L, b3H, b3L; vector unsigned short bH, bL; vector unsigned char max, min, dif; vector unsigned int sum; vector unsigned char zero; vector unsigned short two; union { vector signed int v; struct { signed int pad[3]; signed int sum; } s; } vo; #ifdef ALTIVEC_VERIFY if (NOT_VECTOR_ALIGNED(blk2)) mjpeg_error_exit1("sad_11: blk2 %% 16 != 0, (%d)", blk2); if (NOT_VECTOR_ALIGNED(rowstride)) mjpeg_error_exit1("sad_11: rowstride %% 16 != 0, (%d)", rowstride); #endif if (h != 8 && h != 16) mjpeg_error_exit1("sad_11: h != [8|16], (%d)", h); AMBER_START; pB = blk1, pR = blk2; /* start loading first blocks */ l0 = vec_ld(0, pB); l1 = vec_ld(16, pB); pB += rowstride; l2 = vec_ld(0, pB); l3 = vec_ld(16, pB); /* initialize constants */ zero = vec_splat_u8(0); two = vec_splat_u16(2); sum = vec_splat_u32(0); perm = vec_lvsl(0, blk1); perm1 = vec_splat_u8(1); perm1 = vec_add(perm, perm1); /* permute 1st set of loaded blocks */ lB0 = vec_perm(l0, l1, perm); lB1 = vec_perm(l0, l1, perm1); /* start loading 3rd set */ pB += rowstride; l0 = vec_ld(0, pB); l1 = vec_ld(16, pB); /* permute 2nd set of loaded blocks */ lB2 = vec_perm(l2, l3, perm); lB3 = vec_perm(l2, l3, perm1); /* start loading lR */ lR = vec_ld(0, pR); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* (unsigned short[]) pB[1-8] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB[9-16] */ b1L = vu16(vec_mergel(zero, lB1)); /* (unsigned short[]) pB+s[0-7] */ b2H = vu16(vec_mergeh(zero, lB2)); /* (unsigned short[]) pB+s[8-15] */ b2L = vu16(vec_mergel(zero, lB2)); /* (unsigned short[]) pB+s[1-8] */ b3H = vu16(vec_mergeh(zero, lB3)); /* (unsigned short[]) pB+s[9-16] */ b3L = vu16(vec_mergel(zero, lB3)); /* * TODO: some of vec_add()'s might be consolidated since they * calculate the same values multiple times. */ #define ISAD(b0H,b0L,b1H,b1L,b2H,b2L,b3H,b3L) /* {{{ */ \ /* pB[i] + pB[i+1] */ \ bH = vec_add(b0H, b1H); \ bL = vec_add(b0L, b1L); \ \ /* (pB[i]+pB[i+1]) + pB[i+s] */ \ bH = vec_add(bH, b2H); \ bL = vec_add(bL, b2L); \ \ /* (pB[i]+pB[i+1]+pB[i+s]) + pB[i+s+1] */ \ bH = vec_add(bH, b3H); \ bL = vec_add(bL, b3L); \ \ /* (pB[i]+pB[i+1]+pB[i+s]+pB[i+s+1]) + 2 */ \ bH = vec_add(bH, two); \ bL = vec_add(bL, two); \ \ /* (pB[i]+pB[i+1]+pB[i+s]+pB[i+s+1]+2) >> 2 */ \ bH = vec_sra(bH, two); \ bL = vec_sra(bL, two); \ \ /* abs( ((pB[i]+pB[i+1]+pB[i+s]+pB[i+s+1]+2)>>2) - pR[i] )*/ \ bH = vu16(vec_packsu(bH, bL)); \ min = vec_min(vu8(bH), lR); \ max = vec_max(vu8(bH), lR); \ dif = vec_sub(max, min); \ \ /* d += abs(((pB[i]+pB[i+1]+pB[i+s]+pB[i+s+1]+2)>>2)-pR[i]) */ \ sum = vec_sum4s(dif, sum); \ /* }}} */ i = (h >> 1) - 1; do { ISAD(b0H,b0L,b1H,b1L,b2H,b2L,b3H,b3L); /* start loading next lR */ pR += rowstride; lR = vec_ld(0, pR); /* perm loaded set */ lB0 = vec_perm(l0, l1, perm); lB1 = vec_perm(l0, l1, perm1); /* start loading next set */ pB += rowstride; l0 = vec_ld(0, pB); l1 = vec_ld(16, pB); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* (unsigned short[]) pB[1-8] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB[9-16] */ b1L = vu16(vec_mergel(zero, lB1)); ISAD(b2H,b2L,b3H,b3L,b0H,b0L,b1H,b1L); /* start loading next lR */ pR += rowstride; lR = vec_ld(0, pR); /* perm loaded set */ lB2 = vec_perm(l0, l1, perm); lB3 = vec_perm(l0, l1, perm1); /* start loading next set */ pB += rowstride; l0 = vec_ld(0, pB); l1 = vec_ld(16, pB); /* (unsigned short[]) pB+s[0-7] */ b2H = vu16(vec_mergeh(zero, lB2)); /* (unsigned short[]) pB+s[8-15] */ b2L = vu16(vec_mergel(zero, lB2)); /* (unsigned short[]) pB+s[1-8] */ b3H = vu16(vec_mergeh(zero, lB3)); /* (unsigned short[]) pB+s[9-16] */ b3L = vu16(vec_mergel(zero, lB3)); } while (--i); ISAD(b0H,b0L,b1H,b1L,b2H,b2L,b3H,b3L); pR += rowstride; lR = vec_ld(0, pR); lB0 = vec_perm(l0, l1, perm); lB1 = vec_perm(l0, l1, perm1); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* (unsigned short[]) pB[1-8] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB[9-16] */ b1L = vu16(vec_mergel(zero, lB1)); ISAD(b2H,b2L,b3H,b3L,b0H,b0L,b1H,b1L); vo.v = vec_sums(vs32(sum), vs32(zero)); AMBER_STOP; return vo.s.sum; #undef ISAD } #if ALTIVEC_TEST_FUNCTION(sad_11) /* {{{ */ ALTIVEC_TEST(sad_11, int, (SAD_11_PDECL), SAD_11_PFMT, SAD_11_ARGS); #endif /* }}} */ /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/variance.c0000644000175000017500000002010010464771010020725 0ustar glowwormglowworm/* variance.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_motion.h" #include "vectorize.h" #include "../mjpeg_logging.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif #undef HANDLE_ALL #define VARIANCE_PDECL uint8_t *p, int size, int rowstride, \ unsigned int *p_var, unsigned int *p_mean #define VARIANCE_ARGS p, size, rowstride, p_var, p_mean #define VARIANCE_PFMT "p=0x%X, size=%d, rowstride=%d, p_var=0x%X, p_mean=0x%X" /* * variance of a (size*size) block, multiplied by 256 * p: address of top left pel of block * rowstride: distance (in bytes) of vertically adjacent pels * SIZE is a multiple of 8. */ void variance_altivec(VARIANCE_PDECL) { unsigned int s, s2, sz; #ifdef ALTIVEC_DST unsigned int dst; #endif vector unsigned char zero; vector unsigned char lA, lB, vA, vB; vector signed short sum; vector signed int msum; union { vector signed int v; struct { signed int pad[2]; signed int sum; signed int msum; } s; } vo; #ifdef ALTIVEC_VERIFY if (size == 16 && NOT_VECTOR_ALIGNED(p)) mjpeg_error_exit1("variance: size == 16 && p %% 16 != 0 (0x%X)", p); if (NOT_VECTOR_ALIGNED(rowstride)) mjpeg_error_exit1("variance: rowstride %% 16 != 0, (%d)", rowstride); if ((((unsigned long)p) & 0x7) != 0) mjpeg_error_exit1("variance: p %% 8 != 0, (0x%X)", p); if ((size & 0x7) != 0) mjpeg_error_exit1("variance: size %% 8 != 0, (%d)", size); if (rowstride & (~0xffff) != 0) mjpeg_error_exit1("variance: rowstride > vec_dst range", rowstride); #endif AMBER_START; #ifdef HANDLE_ALL if (size <= 16) { #endif zero = vec_splat_u8(0); sum = vec_splat_s16(0); msum = vec_splat_s32(0); if (size == 8) { #ifdef ALTIVEC_DST dst = 0x01080000 | rowstride; vec_dst(p, dst, 0); #endif sz = 6; #define PREPARE_FIRST_ITERATION(ab,hl) /* {{{ */ \ l##ab = vec_ld(0, (unsigned char*)p); \ v##ab = vec_merge##hl(zero, l##ab); \ /* }}} */ #define PERFORM_ITERATION(ab,iteration) /* {{{ */ \ sum = vec_add(vs16(v##ab), sum); \ msum = vec_msum(vs16(v##ab), vs16(v##ab), msum); \ /* }}} */ #define PREPARE_ITERATION(ab,hl) /* {{{ */ \ p += rowstride; \ l##ab = vec_ld(0, (unsigned char*)p); \ v##ab = vec_merge##hl(zero, l##ab); \ /* }}} */ if (((unsigned long)p & 0xf) == 0) { PREPARE_FIRST_ITERATION(A,h); PERFORM_ITERATION(A,0); PREPARE_ITERATION(B,h); PERFORM_ITERATION(B,1); PREPARE_ITERATION(A,h); PERFORM_ITERATION(A,2); PREPARE_ITERATION(B,h); PERFORM_ITERATION(B,3); PREPARE_ITERATION(A,h); PERFORM_ITERATION(A,4); PREPARE_ITERATION(B,h); PERFORM_ITERATION(B,5); PREPARE_ITERATION(A,h); PERFORM_ITERATION(A,6); PREPARE_ITERATION(B,h); PERFORM_ITERATION(B,7); } else { PREPARE_FIRST_ITERATION(A,l); PERFORM_ITERATION(A,0); PREPARE_ITERATION(B,l); PERFORM_ITERATION(B,1); PREPARE_ITERATION(A,l); PERFORM_ITERATION(A,2); PREPARE_ITERATION(B,l); PERFORM_ITERATION(B,3); PREPARE_ITERATION(A,l); PERFORM_ITERATION(A,4); PREPARE_ITERATION(B,l); PERFORM_ITERATION(B,5); PREPARE_ITERATION(A,l); PERFORM_ITERATION(A,6); PREPARE_ITERATION(B,l); PERFORM_ITERATION(B,7); } #undef PREPARE_FIRST_ITERATION #undef PERFORM_ITERATION #undef PREPARE_ITERATION } else /* size == 16 */ { #ifdef ALTIVEC_DST dst = 0x01100000 | rowstride; vec_dst(p, dst, 0); #endif sz = 8; #define PREPARE_FIRST_ITERATION(ab) /* {{{ */ \ l##ab = vec_ld(0, (unsigned char*)p); \ vA = vec_mergeh(zero, l##ab); \ vB = vec_mergel(zero, l##ab); \ /* }}} */ #define PERFORM_ITERATION(ab,iteration) /* {{{ */ \ sum = vec_add(vs16(vA), sum); \ sum = vec_add(vs16(vB), sum); \ msum = vec_msum(vs16(vA), vs16(vA), msum); \ msum = vec_msum(vs16(vB), vs16(vB), msum); \ /* }}} */ #define PREPARE_ITERATION(ab) /* {{{ */ \ p += rowstride; \ l##ab = vec_ld(0, (unsigned char*)p); \ vA = vec_mergeh(zero, l##ab); \ vB = vec_mergel(zero, l##ab); \ /* }}} */ PREPARE_FIRST_ITERATION(A); PERFORM_ITERATION(A,0); PREPARE_ITERATION(B); PERFORM_ITERATION(B,1); PREPARE_ITERATION(A); PERFORM_ITERATION(A,2); PREPARE_ITERATION(B); PERFORM_ITERATION(B,3); PREPARE_ITERATION(A); PERFORM_ITERATION(A,4); PREPARE_ITERATION(B); PERFORM_ITERATION(B,5); PREPARE_ITERATION(A); PERFORM_ITERATION(A,6); PREPARE_ITERATION(B); PERFORM_ITERATION(B,7); PREPARE_ITERATION(A); PERFORM_ITERATION(A,8); PREPARE_ITERATION(B); PERFORM_ITERATION(B,9); PREPARE_ITERATION(A); PERFORM_ITERATION(A,10); PREPARE_ITERATION(B); PERFORM_ITERATION(B,11); PREPARE_ITERATION(A); PERFORM_ITERATION(A,12); PREPARE_ITERATION(B); PERFORM_ITERATION(B,13); PREPARE_ITERATION(A); PERFORM_ITERATION(A,14); PREPARE_ITERATION(B); PERFORM_ITERATION(B,15); #undef PREPARE_FIRST_ITERATION #undef PERFORM_ITERATION #undef PREPARE_ITERATION } #ifdef HANDLE_ALL } else { /* I don't think this branch of code will be ever be used, but * just in case. */ mjpeg_info("variance(size > 16): altivec me"); return variance(VARIANCE_ARGS); } #endif sum = vs16(vec_sum4s(sum, vs32(zero))); sum = vs16(vec_sums(vs32(sum), vs32(zero))); msum = vec_sums(msum, vs32(zero)); #ifdef ALTIVEC_DST vec_dss(0); #endif vo.v = vec_mergel(vs32(sum), vs32(msum)); s = vo.s.sum; s2 = vo.s.msum; /* var = s2 - ((s * s) >> sz); */ /* ((s*s)/(size*size)) size=8|16 */ *p_var = s2 - ((s * s) >> sz); /* ((s*s)/(size*size)) size=8|16 */ *p_mean = s >> sz; /* (s/(size*size)) size=8|16 */ AMBER_STOP; } #if ALTIVEC_TEST_FUNCTION(variance) # ifdef ALTIVEC_VERIFY void variance_altivec_verify(VARIANCE_PDECL) { unsigned int c_var, c_mean; unsigned int v_var, v_mean; ALTIVEC_TEST_WITH(variance)(p, size, rowstride, &c_var, &c_mean); variance_altivec(p, size, rowstride, &v_var, &v_mean); if (v_var != c_var) mjpeg_debug("*p_var: %d != %d variance(" VARIANCE_PFMT ")", v_var, c_var, VARIANCE_ARGS); if (v_mean != c_mean) mjpeg_debug("*p_mean: %d != %d variance(" VARIANCE_PFMT ")", v_mean, c_mean, VARIANCE_ARGS); *p_var = c_var; *p_mean = c_mean; } # else ALTIVEC_TEST(variance, void, (VARIANCE_PDECL), VARIANCE_PFMT, VARIANCE_ARGS); # endif #endif /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/bsad.c0000644000175000017500000002643410464771010020066 0ustar glowwormglowworm/* bsad.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_motion.h" #include "vectorize.h" #include "../mjpeg_logging.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif /* * absolute difference error between a (16*h) block and a bidirectional * prediction * * * Input hints: * a) values for h[xy][fb] are 0 and 1 * b) h is 8 or 16 * * { * sum += abs( ((((pf[i]+pfa[i]+pfb[i]+pfc[i]+2)>>2)+ * ((pb[i]+pba[i]+pbb[i]+pbc[i]+2)>>2)+1)>>1) - p2[i] ); * } */ #define BSAD_PDECL \ uint8_t *pf, \ uint8_t *pb, \ uint8_t *p2, \ int rowstride, \ int hxf, \ int hyf, \ int hxb, \ int hyb, \ int h \ #define BSAD_ARGS pf, pb, p2, rowstride, hxf, hyf, hxb, hyb, h int bsad_altivec(BSAD_PDECL) { int i; uint8_t *pfy, *pby; vector unsigned char l0, l1, lR; vector unsigned char permF0, permF1, permB0, permB1; vector unsigned char vf, vfa, vfb, vfc; vector unsigned char vb, vba, vbb, vbc; vector unsigned short tH, tL, fH, fL, bH, bL; vector unsigned char zero; vector unsigned short one, two; vector unsigned char max, min, dif; vector unsigned int sum; union { vector signed int v; struct { signed int pad[3]; signed int sum; } s; } vo; #ifdef ALTIVEC_VERIFY if (NOT_VECTOR_ALIGNED(p2)) mjpeg_error_exit1("bsad: p2 %% 16 != 0, (0x%X)", p2); if (NOT_VECTOR_ALIGNED(rowstride)) mjpeg_error_exit1("bsad: rowstride %% 16 != 0, (%d)", rowstride); if (hxf != 0 && hxf != 1) mjpeg_error_exit1("bsad: hxf != [0|1], (hxf=%d)", hxf); if (hyf != 0 && hyf != 1) mjpeg_error_exit1("bsad: hyf != [0|1], (hyf=%d)", hyf); if (hxb != 0 && hxb != 1) mjpeg_error_exit1("bsad: hxb != [0|1], (hxb=%d)", hxb); if (hyb != 0 && hyb != 1) mjpeg_error_exit1("bsad: hyb != [0|1], (hyb=%d)", hyb); #endif if (h != 8 && h != 16) mjpeg_error_exit1("bsad: h != [8|16], (%d)", h); AMBER_START; /* start loading first set */ vfb = vec_ld(0, pf); /* use vfb & vfc as temp for vf & vfa */ vfc = vec_ld(16, pf); pfy = pf + (rowstride * hyf); l0 = vec_ld(0, pfy); l1 = vec_ld(16, pfy); pby = pb + (rowstride * hyb); zero = vec_splat_u8(0); one = vec_splat_u16(1); two = vec_splat_u16(2); sum = vec_splat_u32(0); permF0 = vec_lvsl(0, pf); permF1 = vec_lvsl(hxf, (unsigned char*)0); permF1 = vec_splat(permF1, 0); permF1 = vec_add(permF0, permF1); permB0 = vec_lvsl(0, pb); permB1 = vec_lvsl(hxb, (unsigned char*)0); permB1 = vec_splat(permB1, 0); permB1 = vec_add(permB0, permB1); i = h - 1; do { /* while (--i) */ vf = vec_perm(vfb, vfc, permF0); vfa = vec_perm(vfb, vfc, permF1); vfb = vec_perm(l0, l1, permF0); vfc = vec_perm(l0, l1, permF1); vbb = vec_ld(0, pb); /* use vbb & vbc as temp for vb & vba */ vbc = vec_ld(16, pb); l0 = vec_ld(0, pby); l1 = vec_ld(16, pby); pb += rowstride; pby += rowstride; /* (unsigned short[]) pf[0-7] */ fH = vu16(vec_mergeh(zero, vf)); /* (unsigned short[]) pf[8-15] */ fL = vu16(vec_mergel(zero, vf)); /* (unsigned short[]) pfa[0-7] */ tH = vu16(vec_mergeh(zero, vfa)); /* (unsigned short[]) pfa[8-15] */ tL = vu16(vec_mergel(zero, vfa)); /* pf[i] + pfa[i] */ fH = vec_add(fH, tH); fL = vec_add(fL, tL); /* (unsigned short[]) pfb[0-7] */ tH = vu16(vec_mergeh(zero, vfb)); /* (unsigned short[]) pfb[8-15] */ tL = vu16(vec_mergel(zero, vfb)); /* (pf[i]+pfa[i]) + pfb[i] */ fH = vec_add(fH, tH); fL = vec_add(fL, tL); /* (unsigned short[]) pfc[0-7] */ tH = vu16(vec_mergeh(zero, vfc)); /* (unsigned short[]) pfc[8-15] */ tL = vu16(vec_mergel(zero, vfc)); /* (pf[i]+pfa[i]+pfb[i]) + pfc[i] */ fH = vec_add(fH, tH); fL = vec_add(fL, tL); /* (pf[i]+pfa[i]+pfb[i]+pfc[i]) + 2 */ fH = vec_add(fH, two); fL = vec_add(fL, two); /* (pf[i]+pfa[i]+pfb[i]+pfc[i]+2) >> 2 */ fH = vec_sra(fH, two); fL = vec_sra(fL, two); lR = vec_ld(0, p2); p2 += rowstride; vb = vec_perm(vbb, vbc, permB0); vba = vec_perm(vbb, vbc, permB1); vbb = vec_perm(l0, l1, permB0); vbc = vec_perm(l0, l1, permB1); pf += rowstride; vfb = vec_ld(0, pf); /* use vfb & vfc as temp for vf & vfa */ vfc = vec_ld(16, pf); pfy += rowstride; l0 = vec_ld(0, pfy); l1 = vec_ld(16, pfy); /* (unsigned short[]) pb[0-7] */ bH = vu16(vec_mergeh(zero, vb)); /* (unsigned short[]) pb[8-15] */ bL = vu16(vec_mergel(zero, vb)); /* (unsigned short[]) pba[0-7] */ tH = vu16(vec_mergeh(zero, vba)); /* (unsigned short[]) pba[8-15] */ tL = vu16(vec_mergel(zero, vba)); /* pb[i] + pba[i] */ bH = vec_add(bH, tH); bL = vec_add(bL, tL); /* (unsigned short[]) pbb[0-7] */ tH = vu16(vec_mergeh(zero, vbb)); /* (unsigned short[]) pbb[8-15] */ tL = vu16(vec_mergel(zero, vbb)); /* (pb[i]+pba[i]) + pbb[i] */ bH = vec_add(bH, tH); bL = vec_add(bL, tL); /* (unsigned short[]) pbc[0-7] */ tH = vu16(vec_mergeh(zero, vbc)); /* (unsigned short[]) pbc[8-15] */ tL = vu16(vec_mergel(zero, vbc)); /* (pb[i]+pba[i]+pbb[i]) + pbc[i] */ bH = vec_add(bH, tH); bL = vec_add(bL, tL); /* (pb[i]+pba[i]+pbb[i]+pbc[i]) + 2 */ bH = vec_add(bH, two); bL = vec_add(bL, two); /* (pb[i]+pba[i]+pbb[i]+pbc[i]+2) >> 2 */ bH = vec_sra(bH, two); bL = vec_sra(bL, two); /* ((pf[i]+pfa[i]+pfb[i]+pfc[i]+2)>>2) + * ((pb[i]+pba[i]+pbb[i]+pbc[i]+2)>>2) */ tH = vec_add(fH, bH); tL = vec_add(fL, bL); /* (((pf[i]+pfa[i]+pfb[i]+pfc[i]+2)>>2)+ * ((pb[i]+pba[i]+pbb[i]+pbc[i]+2)>>2)) + 1 */ tH = vec_add(tH, one); tL = vec_add(tL, one); /* (((pf[i]+pfa[i]+pfb[i]+pfc[i]+2)>>2)+ * ((pb[i]+pba[i]+pbb[i]+pbc[i]+2)>>2)+1) >> 1 */ tH = vec_sra(tH, one); tL = vec_sra(tL, one); /* d = abs( ((((pf[i]+pfa[i]+pfb[i]+pfc[i]+2)>>2)+ * ((pb[i]+pba[i]+pbb[i]+pbc[i]+2)>>2)+1)>>1) - p2[i] ) */ tH = vu16(vec_packsu(tH, tL)); min = vec_min(vu8(tH), lR); max = vec_max(vu8(tH), lR); dif = vec_sub(max, min); /* sum += d */ sum = vec_sum4s(dif, sum); } while (--i); vf = vec_perm(vfb, vfc, permF0); vfa = vec_perm(vfb, vfc, permF1); vfb = vec_perm(l0, l1, permF0); vfc = vec_perm(l0, l1, permF1); vbb = vec_ld(0, pb); /* use vbb & vbc as temp for vb & vba */ vbc = vec_ld(16, pb); l0 = vec_ld(0, pby); l1 = vec_ld(16, pby); /* (unsigned short[]) pf[0-7] */ fH = vu16(vec_mergeh(zero, vf)); /* (unsigned short[]) pf[8-15] */ fL = vu16(vec_mergel(zero, vf)); /* (unsigned short[]) pfa[0-7] */ tH = vu16(vec_mergeh(zero, vfa)); /* (unsigned short[]) pfa[8-15] */ tL = vu16(vec_mergel(zero, vfa)); /* pf[i] + pfa[i] */ fH = vec_add(fH, tH); fL = vec_add(fL, tL); /* (unsigned short[]) pfb[0-7] */ tH = vu16(vec_mergeh(zero, vfb)); /* (unsigned short[]) pfb[8-15] */ tL = vu16(vec_mergel(zero, vfb)); /* (pf[i]+pfa[i]) + pfb[i] */ fH = vec_add(fH, tH); fL = vec_add(fL, tL); /* (unsigned short[]) pfc[0-7] */ tH = vu16(vec_mergeh(zero, vfc)); /* (unsigned short[]) pfc[8-15] */ tL = vu16(vec_mergel(zero, vfc)); /* (pf[i]+pfa[i]+pfb[i]) + pfc[i] */ fH = vec_add(fH, tH); fL = vec_add(fL, tL); /* (pf[i]+pfa[i]+pfb[i]+pfc[i]) + 2 */ fH = vec_add(fH, two); fL = vec_add(fL, two); /* (pf[i]+pfa[i]+pfb[i]+pfc[i]+2) >> 2 */ fH = vec_sra(fH, two); fL = vec_sra(fL, two); lR = vec_ld(0, p2); vb = vec_perm(vbb, vbc, permB0); vba = vec_perm(vbb, vbc, permB1); vbb = vec_perm(l0, l1, permB0); vbc = vec_perm(l0, l1, permB1); /* (unsigned short[]) pb[0-7] */ bH = vu16(vec_mergeh(zero, vb)); /* (unsigned short[]) pb[8-15] */ bL = vu16(vec_mergel(zero, vb)); /* (unsigned short[]) pba[0-7] */ tH = vu16(vec_mergeh(zero, vba)); /* (unsigned short[]) pba[8-15] */ tL = vu16(vec_mergel(zero, vba)); /* pb[i] + pba[i] */ bH = vec_add(bH, tH); bL = vec_add(bL, tL); /* (unsigned short[]) pbb[0-7] */ tH = vu16(vec_mergeh(zero, vbb)); /* (unsigned short[]) pbb[8-15] */ tL = vu16(vec_mergel(zero, vbb)); /* (pb[i]+pba[i]) + pbb[i] */ bH = vec_add(bH, tH); bL = vec_add(bL, tL); /* (unsigned short[]) pbc[0-7] */ tH = vu16(vec_mergeh(zero, vbc)); /* (unsigned short[]) pbc[8-15] */ tL = vu16(vec_mergel(zero, vbc)); /* (pb[i]+pba[i]+pbb[i]) + pbc[i] */ bH = vec_add(bH, tH); bL = vec_add(bL, tL); /* (pb[i]+pba[i]+pbb[i]+pbc[i]) + 2 */ bH = vec_add(bH, two); bL = vec_add(bL, two); /* (pb[i]+pba[i]+pbb[i]+pbc[i]+2) >> 2 */ bH = vec_sra(bH, two); bL = vec_sra(bL, two); /* ((pf[i]+pfa[i]+pfb[i]+pfc[i]+2)>>2) + * ((pb[i]+pba[i]+pbb[i]+pbc[i]+2)>>2) */ tH = vec_add(fH, bH); tL = vec_add(fL, bL); /* (((pf[i]+pfa[i]+pfb[i]+pfc[i]+2)>>2)+ * ((pb[i]+pba[i]+pbb[i]+pbc[i]+2)>>2)) + 1 */ tH = vec_add(tH, one); tL = vec_add(tL, one); /* (((pf[i]+pfa[i]+pfb[i]+pfc[i]+2)>>2)+ * ((pb[i]+pba[i]+pbb[i]+pbc[i]+2)>>2)+1) >> 1 */ tH = vec_sra(tH, one); tL = vec_sra(tL, one); /* d = abs( ((((pf[i]+pfa[i]+pfb[i]+pfc[i]+2)>>2)+ * ((pb[i]+pba[i]+pbb[i]+pbc[i]+2)>>2)+1)>>1) - p2[i] ) */ tH = vu16(vec_packsu(tH, tL)); min = vec_min(vu8(tH), lR); max = vec_max(vu8(tH), lR); dif = vec_sub(max, min); /* sum += d */ sum = vec_sum4s(dif, sum); /* sum all parts of difference into one 32 bit quantity */ vo.v = vec_sums(vs32(sum), vs32(zero)); AMBER_STOP; return vo.s.sum; } #if ALTIVEC_TEST_FUNCTION(bsad) #undef BENCHMARK_FREQUENCY #define BENCHMARK_FREQUENCY 1000 /* benchmark every (n) calls */ ALTIVEC_TEST(bsad, int, (BSAD_PDECL), "pf=0x%X, pb=0x%X, p2=0x%X, rowstride=%d, " "hxf=%d, hyf=%d, hxb=%d, hyb=%d, h=%d", BSAD_ARGS); #endif /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/altivec/fdct_idct.c0000644000175000017500000005034210206660053021071 0ustar glowwormglowworm/* fdct_idct.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /*************************************************************** * * AltiVec code optimizations from http://www.motorola.com * /SPS/RISC/smartnetworks/arch/powerpc/features/altivec/avcode.htm * * Adapted Aug 20, 2001 James Klicman * * Update Jan 30, 2002: code samples moved to http://e-www.motorola.com * /webapp/sps/site/taxonomy.jsp?nodeId=03M943030450467M0ymKF9DH * */ #ifdef HAVE_CONFIG_H #include #endif #include "vectorize.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif /*************************************************************** * * Copyright: (c) Copyright Motorola Inc. 1998 * * Date: April 17, 1998 * * Function: Matrix_Transpose * * Description: The following Matrix Transpose is adapted * from an algorithm developed by Brett Olsson * from IBM. It performs a 8x8 16-bit element * full matrix transpose. * * Inputs: array elements stored in input * input[0] = [ 00 01 02 03 04 05 06 07 ] * input[1] = [ 10 11 12 13 14 15 16 17 ] * input[2] = [ 20 21 22 23 24 25 26 27 ] * input[3] = [ 30 31 32 33 34 35 36 37 ] * input[4] = [ 40 41 42 43 44 45 46 47 ] * input[5] = [ 50 51 52 53 54 55 56 57 ] * input[6] = [ 60 61 62 63 64 65 66 67 ] * input[7] = [ 70 71 72 73 74 75 76 77 ] * * Outputs: transposed elements in output * **************************************************************/ static inline void Matrix_Transpose ( vector signed short *input, vector signed short *output ) { vector signed short a0, a1, a2, a3, a4, a5, a6, a7; vector signed short b0, b1, b2, b3, b4, b5, b6, b7; b0 = vec_mergeh( input[0], input[4] ); /* [ 00 40 01 41 02 42 03 43 ]*/ b1 = vec_mergel( input[0], input[4] ); /* [ 04 44 05 45 06 46 07 47 ]*/ b2 = vec_mergeh( input[1], input[5] ); /* [ 10 50 11 51 12 52 13 53 ]*/ b3 = vec_mergel( input[1], input[5] ); /* [ 14 54 15 55 16 56 17 57 ]*/ b4 = vec_mergeh( input[2], input[6] ); /* [ 20 60 21 61 22 62 23 63 ]*/ b5 = vec_mergel( input[2], input[6] ); /* [ 24 64 25 65 26 66 27 67 ]*/ b6 = vec_mergeh( input[3], input[7] ); /* [ 30 70 31 71 32 72 33 73 ]*/ b7 = vec_mergel( input[3], input[7] ); /* [ 34 74 35 75 36 76 37 77 ]*/ a0 = vec_mergeh( b0, b4 ); /* [ 00 20 40 60 01 21 41 61 ]*/ a1 = vec_mergel( b0, b4 ); /* [ 02 22 42 62 03 23 43 63 ]*/ a2 = vec_mergeh( b1, b5 ); /* [ 04 24 44 64 05 25 45 65 ]*/ a3 = vec_mergel( b1, b5 ); /* [ 06 26 46 66 07 27 47 67 ]*/ a4 = vec_mergeh( b2, b6 ); /* [ 10 30 50 70 11 31 51 71 ]*/ a5 = vec_mergel( b2, b6 ); /* [ 12 32 52 72 13 33 53 73 ]*/ a6 = vec_mergeh( b3, b7 ); /* [ 14 34 54 74 15 35 55 75 ]*/ a7 = vec_mergel( b3, b7 ); /* [ 16 36 56 76 17 37 57 77 ]*/ output[0] = vec_mergeh( a0, a4 ); /* [ 00 10 20 30 40 50 60 70 ]*/ output[1] = vec_mergel( a0, a4 ); /* [ 01 11 21 31 41 51 61 71 ]*/ output[2] = vec_mergeh( a1, a5 ); /* [ 02 12 22 32 42 52 62 72 ]*/ output[3] = vec_mergel( a1, a5 ); /* [ 03 13 23 33 43 53 63 73 ]*/ output[4] = vec_mergeh( a2, a6 ); /* [ 04 14 24 34 44 54 64 74 ]*/ output[5] = vec_mergel( a2, a6 ); /* [ 05 15 25 35 45 55 65 75 ]*/ output[6] = vec_mergeh( a3, a7 ); /* [ 06 16 26 36 46 56 66 76 ]*/ output[7] = vec_mergel( a3, a7 ); /* [ 07 17 27 37 47 57 67 77 ]*/ } /*************************************************************** * * Copyright: (c) Copyright Motorola Inc. 1998 * * Date: April 15, 1998 * * Macro: DCT_Transform * * Description: Discrete Cosign Transform implemented by the * Scaled Chen (II) Algorithm developed by Haifa * Research Lab. The major differnce between this * algorithm and the Scaled Chen (I) is that * certain multiply-subtracts are replaced by * multiply adds. A full description of the * Scaled Chen (I) algorithm can be found in: * W.C.Chen, C.H.Smith and S.C.Fralick, "A Fast * Computational Algorithm for the Discrete Cosine * Transform", IEEE Transactions on Cummnuications, * Vol. COM-25, No. 9, pp 1004-1009, Sept. 1997. * * Inputs: vx : array of vector short * t1-t10 : temporary vector variables set up by caller * c4 : cos(4*pi/16) * mc4 : -c4 * a0 : c6/c2 * a1 : c7/c1 * a2 : c5/c3 * ma2 : -a2 * zero : an array of zero elements * * Outputs: vy : array of vector short * **************************************************************/ #define DCT_Transform(vx,vy) \ \ /* 1st stage. */ \ t8 = vec_adds( vx[0], vx[7] ); /* t0 + t7 */ \ t9 = vec_subs( vx[0], vx[7] ); /* t0 - t7 */ \ t0 = vec_adds( vx[1], vx[6] ); /* t1 + t6 */ \ t7 = vec_subs( vx[1], vx[6] ); /* t1 - t6 */ \ t1 = vec_adds( vx[2], vx[5] ); /* t2 + t6 */ \ t6 = vec_subs( vx[2], vx[5] ); /* t2 - t6 */ \ t2 = vec_adds( vx[3], vx[4] ); /* t3 + t4 */ \ t5 = vec_subs( vx[3], vx[4] ); /* t3 - t4 */ \ \ /* 2nd stage. */ \ t3 = vec_adds( t8, t2 ); /* (t0+t7) + (t3+t4) */ \ t4 = vec_subs( t8, t2 ); /* (t0+t7) - (t3+t4) */ \ t2 = vec_adds( t0, t1 ); /* (t1+t6) + (t2+t5) */ \ t8 = vec_subs( t0, t1 ); /* (t1+t6) - (t2+t5) */ \ \ t1 = vec_adds( t7, t6 ); /* (t1-t6) + (t2-t5) */ \ t0 = vec_subs( t7, t6 ); /* (t1-t6) - (t2-t5) */ \ \ /* 3rd stage */ \ vy[0] = vec_adds( t3, t2 ); /* y0 = t3 + t2 */ \ vy[4] = vec_subs( t3, t2 ); /* y4 = t3 + t2 */ \ vy[2] = vec_mradds( t8, a0, t4 ); /* y2 = t8 * (a0) + t4 */ \ t10 = vec_mradds( t4, a0, zero ); \ vy[6] = vec_subs( t10, t8 ); /* y6 = t4 * (a0) - t8 */ \ \ t6 = vec_mradds( t0, c4, t5 ); /* t6 = t0 * (c4) + t5 */ \ t7 = vec_mradds( t0, mc4, t5 ); /* t7 = t0 * (-c4) + t5 */ \ t2 = vec_mradds( t1, mc4, t9 ); /* t2 = t1 * (-c4) + t9 */ \ t3 = vec_mradds( t1, c4, t9 ); /* t3 = t1 * (c4) + t9 */ \ \ /* 4th stage. */ \ vy[1] = vec_mradds( t6, a1, t3 ); /* y1 = t6 * (a1) + t3 */ \ t9 = vec_mradds( t3, a1, zero ); \ vy[7] = vec_subs( t9, t6 ) ; /* y7 = t3 * (a1) - t6 */ \ vy[5] = vec_mradds( t2, a2, t7 ); /* y5 = t2 + (a2) + t7 */ \ vy[3] = vec_mradds( t7, ma2, t2 ); /* y3 = t7 * (-a2) + t2 */ /* Post-scaling matrix -- scaled by 1 */ static const vector signed short PostScale[8] = { (vector signed short)VCONST(4095, 5681, 5351, 4816, 4095, 4816, 5351, 5681), (vector signed short)VCONST(5681, 7880, 7422, 6680, 5681, 6680, 7422, 7880), (vector signed short)VCONST(5351, 7422, 6992, 6292, 5351, 6292, 6992, 7422), (vector signed short)VCONST(4816, 6680, 6292, 5663, 4816, 5663, 6292, 6680), (vector signed short)VCONST(4095, 5681, 5351, 4816, 4095, 4816, 5351, 5681), (vector signed short)VCONST(4816, 6680, 6292, 5663, 4816, 5663, 6292, 6680), (vector signed short)VCONST(5351, 7422, 6992, 6292, 5351, 6292, 6992, 7422), (vector signed short)VCONST(5681, 7880, 7422, 6680, 5681, 6680, 7422, 7880) }; /*************************************************************** * * Copyright: (c) Copyright Motorola Inc. 1998 * * Date: April 17, 1998 * * Function: DCT * * Description: Scaled Chen (II) algorithm for DCT * Arithmetic is 16-bit fixed point. * * Inputs: input - Pointer to input data (short), which * must be between -255 to +255. * It is assumed that the allocated array * has been 128-bit aligned and contains * 8x8 short elements. * * Outputs: output - Pointer to output area for the transfored * data. The output values are between -2040 * and 2040. It is assumed that a 128-bit * aligned 8x8 array of short has been * pre-allocated. * * Return: None * ***************************************************************/ /* Note: these constants could all be loaded directly, but using the * SpecialConstants approach causes vsplth instructions to be generated instead * of lvx which is more efficient given the remainder of the instruction mix. */ static const vector signed short SpecialConstants = (const vector signed short)VCONST(23170, 13573, 6518, 21895, -23170, -21895, 0, 0); #ifdef ORIGINAL_SOURCE void DCT(short *input, short *output) { #else void fdct_altivec_old(short *blocks) { #endif vector signed short t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10; vector signed short a0, a1, a2, ma2, c4, mc4, zero; vector signed short vx[8], vy[8]; vector signed short *vec_ptr; /* used for conversion between arrays of short and vector signed short array. */ /* load the multiplication constants */ c4 = vec_splat( SpecialConstants, 0 ); /* c4 = cos(4*pi/16) */ a0 = vec_splat( SpecialConstants, 1 ); /* a0 = c6/c2 */ a1 = vec_splat( SpecialConstants, 2 ); /* a1 = c7/c1 */ a2 = vec_splat( SpecialConstants, 3 ); /* a2 = c5/c3 */ mc4 = vec_splat( SpecialConstants, 4 ); /* -c4 */ ma2 = vec_splat( SpecialConstants, 5 ); /* -a2 */ zero = vec_splat_s16(0); /* copy the rows of input data */ #ifdef ORIGINAL_SOURCE vec_ptr = ( vector signed short * ) input; #else vec_ptr = ( vector signed short * ) blocks; #endif vx[0] = vec_ptr[0]; vx[1] = vec_ptr[1]; vx[2] = vec_ptr[2]; vx[3] = vec_ptr[3]; vx[4] = vec_ptr[4]; vx[5] = vec_ptr[5]; vx[6] = vec_ptr[6]; vx[7] = vec_ptr[7]; /* Perform DCT first on the 8 columns */ DCT_Transform( vx, vy ); /* Transpose matrix to work on rows */ Matrix_Transpose( vy, vx ); /* Perform DCT first on the 8 rows */ DCT_Transform( vx, vy ); #ifndef ORIGINAL_SOURCE /* mpeg2enc requires the matrix transposed back */ Matrix_Transpose( vy, vx ); #endif /* Post-scale and store result. */ #ifdef ORIGINAL_SOURCE vec_ptr = (vector signed short *) output; #endif vec_ptr[0] = vec_mradds( PostScale[0], vx[0], zero ); vec_ptr[1] = vec_mradds( PostScale[1], vx[1], zero ); vec_ptr[2] = vec_mradds( PostScale[2], vx[2], zero ); vec_ptr[3] = vec_mradds( PostScale[3], vx[3], zero ); vec_ptr[4] = vec_mradds( PostScale[4], vx[4], zero ); vec_ptr[5] = vec_mradds( PostScale[5], vx[5], zero ); vec_ptr[6] = vec_mradds( PostScale[6], vx[6], zero ); vec_ptr[7] = vec_mradds( PostScale[7], vx[7], zero ); } /*************************************************************** * * Copyright: (c) Copyright Motorola Inc. 1998 * * Date: April 20, 1998 * * Macro: IDCT_Transform * * Description: Discrete Cosign Transform implemented by the * Scaled Chen (III) Algorithm developed by Haifa * Research Lab. The major difference between this * algorithm and the Scaled Chen (I) is that * certain multiply-subtracts are replaced by * multiply adds. A full description of the * Scaled Chen (I) algorithm can be found in: * W.C.Chen, C.H.Smith and S.C.Fralick, "A Fast * Computational Algorithm for the Discrete Cosine * Transform", IEEE Transactions on Commnuications, * Vol. COM-25, No. 9, pp 1004-1009, Sept. 1997. * * Inputs: vx : array of vector short * t1-t10 : temporary vector variables set up by caller * c4 : cos(4*pi/16) * mc4 : -c4 * a0 : c6/c2 * a1 : c7/c1 * a2 : c5/c3 * ma2 : -a2 * zero : an array of zero elements * * Outputs: vy : array of vector short * **************************************************************/ #define IDCT_Transform(vx,vy) \ \ /* 1st stage. */ \ t9 = vec_mradds( a1, vx[1], zero ); /* t8 = (a1) * x1 - x7 */ \ t8 = vec_subs( t9, vx[7]); \ t1 = vec_mradds( a1, vx[7], vx[1] ); /* t1 = (a1) * x7 + x1 */ \ t7 = vec_mradds( a2, vx[5], vx[3] ); /* t7 = (a2) * x5 + x3 */ \ t3 = vec_mradds( ma2, vx[3], vx[5] );/* t3 = (-a2) * x5 + x3 */ \ \ /* 2nd stage */ \ t5 = vec_adds( vx[0], vx[4] ); /* t5 = x0 + x4 */ \ t0 = vec_subs( vx[0], vx[4] ); /* t0 = x0 - x4 */ \ t9 = vec_mradds( a0, vx[2], zero ); /* t4 = (a0) * x2 - x6 */ \ t4 = vec_subs( t9, vx[6] ); \ t2 = vec_mradds( a0, vx[6], vx[2] ); /* t2 = (a0) * x6 + x2 */ \ \ t6 = vec_adds( t8, t3 ); /* t6 = t8 + t3 */ \ t3 = vec_subs( t8, t3 ); /* t3 = t8 - t3 */ \ t8 = vec_subs( t1, t7 ); /* t8 = t1 - t7 */ \ t1 = vec_adds( t1, t7 ); /* t1 = t1 + t7 */ \ \ /* 3rd stage. */ \ t7 = vec_adds( t5, t2 ); /* t7 = t5 + t2 */ \ t2 = vec_subs( t5, t2 ); /* t2 = t5 - t2 */ \ t5 = vec_adds( t0, t4 ); /* t5 = t0 + t4 */ \ t0 = vec_subs( t0, t4 ); /* t0 = t0 - t4 */ \ \ t4 = vec_subs( t8, t3 ); /* t4 = t8 - t3 */ \ t3 = vec_adds( t8, t3 ); /* t3 = t8 + t3 */ \ \ /* 4th stage. */ \ vy[0] = vec_adds( t7, t1 ); /* y0 = t7 + t1 */ \ vy[7] = vec_subs( t7, t1 ); /* y7 = t7 - t1 */ \ vy[1] = vec_mradds( c4, t3, t5 ); /* y1 = (c4) * t3 + t5 */ \ vy[6] = vec_mradds( mc4, t3, t5 ); /* y6 = (-c4) * t3 + t5 */ \ vy[2] = vec_mradds( c4, t4, t0 ); /* y2 = (c4) * t4 + t0 */ \ vy[5] = vec_mradds( mc4, t4, t0 ); /* y5 = (-c4) * t4 + t0 */ \ vy[3] = vec_adds( t2, t6 ); /* y3 = t2 + t6 */ \ vy[4] = vec_subs( t2, t6 ); /* y4 = t2 - t6 */ /* Pre-Scaling matrix -- scaled by 1 */ static const vector signed short PreScale[8] = { (vector signed short)VCONST(4095, 5681, 5351, 4816, 4095, 4816, 5351, 5681), (vector signed short)VCONST(5681, 7880, 7422, 6680, 5681, 6680, 7422, 7880), (vector signed short)VCONST(5351, 7422, 6992, 6292, 5351, 6292, 6992, 7422), (vector signed short)VCONST(4816, 6680, 6292, 5663, 4816, 5663, 6292, 6680), (vector signed short)VCONST(4095, 5681, 5351, 4816, 4095, 4816, 5351, 5681), (vector signed short)VCONST(4816, 6680, 6292, 5663, 4816, 5663, 6292, 6680), (vector signed short)VCONST(5351, 7422, 6992, 6292, 5351, 6292, 6992, 7422), (vector signed short)VCONST(5681, 7880, 7422, 6680, 5681, 6680, 7422, 7880) }; /*************************************************************** * * Copyright: (c) Copyright Motorola Inc. 1998 * * Date: April 17, 1998 * * Function: IDCT * * Description: Scaled Chen (III) algorithm for IDCT * Arithmetic is 16-bit fixed point. * * Inputs: input - Pointer to input data (short), which * must be between -2048 to +2047. * It is assumed that the allocated array * has been 128-bit aligned and contains * 8x8 short elements. * * Outputs: output - Pointer to output area for the transfored * data. The output values are between -255 * and 255 . It is assumed that a 128-bit * aligned 8x8 array of short has been * pre-allocated. * * Return: None * ***************************************************************/ #ifdef ORIGINAL_SOURCE void IDCT(short *input, short *output) { #else void idct_altivec_old(short *block) { #endif vector signed short t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; vector signed short a0, a1, a2, ma2, c4, mc4, zero; vector signed short vx[8], vy[8]; vector signed short *vec_ptr; /* used for conversion between arrays of short and vector signed short array. */ /* Load the multiplication constants. */ c4 = vec_splat( SpecialConstants, 0 ); /* c4 = cos(4*pi/16) */ a0 = vec_splat( SpecialConstants, 1 ); /* a0 = c6/c2 */ a1 = vec_splat( SpecialConstants, 2 ); /* a1 = c7/c1 */ a2 = vec_splat( SpecialConstants, 3 ); /* a2 = c5/c3 */ mc4 = vec_splat( SpecialConstants, 4 ); /* -c4 */ ma2 = vec_splat( SpecialConstants, 5 ); /* -a2 */ zero = vec_splat_s16(0); /* Load the rows of input data and Pre-Scale them. */ #ifdef ORIGINAL_SOURCE vec_ptr = ( vector signed short * ) input; #else vec_ptr = ( vector signed short * ) block; #endif vx[0] = vec_mradds( vec_ptr[0], PreScale[0], zero ); vx[1] = vec_mradds( vec_ptr[1], PreScale[1], zero ); vx[2] = vec_mradds( vec_ptr[2], PreScale[2], zero ); vx[3] = vec_mradds( vec_ptr[3], PreScale[3], zero ); vx[4] = vec_mradds( vec_ptr[4], PreScale[4], zero ); vx[5] = vec_mradds( vec_ptr[5], PreScale[5], zero ); vx[6] = vec_mradds( vec_ptr[6], PreScale[6], zero ); vx[7] = vec_mradds( vec_ptr[7], PreScale[7], zero ); /* Perform IDCT first on the 8 columns */ IDCT_Transform( vx, vy ); /* Transpose matrix to work on rows */ Matrix_Transpose( vy, vx ); /* Perform IDCT next on the 8 rows */ IDCT_Transform( vx, vy ); #ifndef ORIGINAL_SOURCE /* mpeg2enc requires the matrix transposed back */ Matrix_Transpose( vy, vx ); #endif /* Post-scale and store result. */ #ifdef ORIGINAL_SOURCE vec_ptr = (vector signed short *) output; #endif vec_ptr[0] = vx[0]; vec_ptr[1] = vx[1]; vec_ptr[2] = vx[2]; vec_ptr[3] = vx[3]; vec_ptr[4] = vx[4]; vec_ptr[5] = vx[5]; vec_ptr[6] = vx[6]; vec_ptr[7] = vx[7]; } mjpegtools-2.1.0/utils/altivec/sad_10.c0000644000175000017500000001703710462765416020236 0ustar glowwormglowworm/* sad_10.c, this file is part of the * AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include "altivec_motion.h" #include "vectorize.h" #include "../mjpeg_logging.h" /* #define AMBER_ENABLE */ #include "amber.h" #ifdef HAVE_ALTIVEC_H /* include last to ensure AltiVec type semantics, especially for bool. */ #include #endif /* * SAD with vertical half pel interpolation * * Input requirements: * a) blk2 is always vector aligned * b) rowstride is a multiple of 16 * c) h is either 8 or 16 * * s = rowstride; * for (j = 0; j < h; j++) { * for (i = 0; i < 16; i++) * sum += abs( ((int)(p1[i]+p1[i+s]+1)>>1) - p2[i] ); * p1 += s; * p2 += s; * } */ #define SAD_10_PDECL \ uint8_t *blk1, \ uint8_t *blk2, \ int rowstride, \ int h \ #define SAD_10_ARGS blk1, blk2, rowstride, h int sad_10_altivec(SAD_10_PDECL) { int i; unsigned char *pB, *pR; vector unsigned char l0, l1, lR, lB0, lB1, perm; vector unsigned short b0H, b0L, b1H, b1L; vector unsigned short bH, bL; vector unsigned char max, min, dif; vector unsigned int sum; vector unsigned char zero; vector unsigned short one; union { vector signed int v; struct { signed int pad[3]; signed int sum; } s; } vo; #ifdef ALTIVEC_VERIFY if (NOT_VECTOR_ALIGNED(blk2)) mjpeg_error_exit1("sad_10: blk2 %% 16 != 0, (%d)", blk2); if (NOT_VECTOR_ALIGNED(rowstride)) mjpeg_error_exit1("sad_10: rowstride %% 16 != 0, (%d)", rowstride); #endif if (h != 8 && h != 16) mjpeg_error_exit1("sad_10: h != [8|16], (%d)", h); AMBER_START; #define ISAD() /* {{{ */ \ /* pB[i] + pB[i+s] */ \ bH = vec_add(b0H, b1H); \ bL = vec_add(b0L, b1L); \ \ /* (pB[i]+pB[i+s]) + 1 */ \ bH = vec_add(bH, one); \ bL = vec_add(bL, one); \ \ /* (pB[i]+pB[i+s]+1) >> 1 */ \ bH = vec_sra(bH, one); \ bL = vec_sra(bL, one); \ \ /* abs( ((pB[i]+pB[i+s]+1)>>1) - pR[i] ) */ \ bH = vu16(vec_packsu(bH, bL)); \ min = vec_min(vu8(bH), lR); \ max = vec_max(vu8(bH), lR); \ dif = vec_sub(max, min); \ \ /* sum += abs(((pB[i]+pB[i+s]+1)>>1)-pR[i]) */ \ sum = vec_sum4s(dif, sum); \ /* }}} */ pB = blk1, pR = blk2; /* initialize constants */ zero = vec_splat_u8(0); one = vec_splat_u16(1); sum = vec_splat_u32(0); i = (h >> 1) - 1; lB0 = vec_ld(0, pB); if (VECTOR_ALIGNED(pB)) { /* lB0 = vec_ld(0, pB); */ pB += rowstride; lB1 = vec_ld(0, pB); pB += rowstride; l0 = vec_ld(0, pB); lR = vec_ld(0, pR); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* (unsigned short[]) pB+s[0-7] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB+s[8-15] */ b1L = vu16(vec_mergel(zero, lB1)); lB0 = vec_sld(l0, l0, 0); do { /* while (--i) */ pB += rowstride; lB1 = vec_ld(0, pB); ISAD(); /* start loading next lR */ pR += rowstride; lR = vec_ld(0, pR); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); pB += rowstride; lB0 = vec_ld(0, pB); ISAD(); /* start loading next lR */ pR += rowstride; lR = vec_ld(0, pR); /* (unsigned short[]) pB[0-7] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB[8-15] */ b1L = vu16(vec_mergel(zero, lB1)); } while (--i); ISAD(); pR += rowstride; lR = vec_ld(0, pR); } else { perm = vec_lvsl(0, pB); /* lB0 = vec_ld(0, pB); */ l0 = vec_ld(16, pB); pB += rowstride; lB1 = vec_ld(0, pB); l1 = vec_ld(16, pB); lR = vec_ld(0, pR); lB0 = vec_perm(lB0, l0, perm); lB1 = vec_perm(lB1, l1, perm); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* (unsigned short[]) pB+s[0-7] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB+s[8-15] */ b1L = vu16(vec_mergel(zero, lB1)); pB += rowstride; l0 = vec_ld(0, pB); l1 = vec_ld(16, pB); do { /* while (--i) */ ISAD(); lB0 = vec_perm(l0, l1, perm); pB += rowstride; l0 = vec_ld(0, pB); l1 = vec_ld(16, pB); /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); /* start loading next lR */ pR += rowstride; lR = vec_ld(0, pR); ISAD(); lB1 = vec_perm(l0, l1, perm); pB += rowstride; l0 = vec_ld(0, pB); l1 = vec_ld(16, pB); /* (unsigned short[]) pB[0-7] */ b1H = vu16(vec_mergeh(zero, lB1)); /* (unsigned short[]) pB[8-15] */ b1L = vu16(vec_mergel(zero, lB1)); /* start loading next lR */ pR += rowstride; lR = vec_ld(0, pR); } while (--i); ISAD(); pR += rowstride; lR = vec_ld(0, pR); lB0 = vec_perm(l0, l1, perm); } /* (unsigned short[]) pB[0-7] */ b0H = vu16(vec_mergeh(zero, lB0)); /* (unsigned short[]) pB[8-15] */ b0L = vu16(vec_mergel(zero, lB0)); ISAD(); vo.v = vec_sums(vs32(sum), vs32(zero)); AMBER_STOP; return vo.s.sum; } #if ALTIVEC_TEST_FUNCTION(sad_10) ALTIVEC_TEST(sad_10, int, (SAD_10_PDECL), "blk1=0x%X, blk2=0x%X, rowstride=%d, h=%d", SAD_10_ARGS); #endif /* vim:set foldmethod=marker foldlevel=0: */ mjpegtools-2.1.0/utils/videodev_mjpeg.h0000644000175000017500000001353707342745270020534 0ustar glowwormglowworm/* These are the MJPEG API extensions for the Video4Linux API, first introduced by the Iomega Buz driver by Rainer Johanni */ /* This is identical with the mgavideo internal params struct, please tell me if you change this struct here ! top-field-first */ int APPn; /* Number of APP segment to be written, must be 0..15 */ int APP_len; /* Length of data in JPEG APPn segment */ char APP_data[60]; /* Data in the JPEG APPn segment. */ int COM_len; /* Length of data in JPEG COM segment */ char COM_data[60]; /* Data in JPEG COM segment */ unsigned long jpeg_markers; /* Which markers should go into the JPEG output. Unless you exactly know what you do, leave them untouched. Inluding less markers will make the resulting code smaller, but there will be fewer aplications which can read it. The presence of the APP and COM marker is influenced by APP0_len and COM_len ONLY! */ #define JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */ #define JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */ #define JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ #define JPEG_MARKER_COM (1<<6) /* Comment segment */ #define JPEG_MARKER_APP (1<<7) /* App segment, driver will allways use APP0 */ int VFIFO_FB; /* Flag for enabling Video Fifo Feedback. If this flag is turned on and JPEG decompressing is going to the screen, the decompress process is stopped every time the Video Fifo is full. This enables a smooth decompress to the screen but the video output signal will get scrambled */ /* Misc */ char reserved[312]; /* Makes 512 bytes for this structure */ }; struct mjpeg_requestbuffers { unsigned long count; /* Number of buffers for MJPEG grabbing */ unsigned long size; /* Size PER BUFFER in bytes */ }; struct mjpeg_sync { unsigned long frame; /* Frame (0 - n) for double buffer */ unsigned long length; /* number of code bytes in buffer (capture only) */ unsigned long seq; /* frame sequence number */ struct timeval timestamp; /* timestamp */ }; struct mjpeg_status { int input; /* Input channel, has to be set prior to BUZIOC_G_STATUS */ int signal; /* Returned: 1 if valid video signal detected */ int norm; /* Returned: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */ int color; /* Returned: 1 if color signal detected */ }; /* Private IOCTL to set up for displaying MJPEG */ #define MJPIOC_G_PARAMS _IOR ('v', BASE_VIDIOCPRIVATE+0, struct mjpeg_params) #define MJPIOC_S_PARAMS _IOWR('v', BASE_VIDIOCPRIVATE+1, struct mjpeg_params) #define MJPIOC_REQBUFS _IOWR('v', BASE_VIDIOCPRIVATE+2, struct mjpeg_requestbuffers) #define MJPIOC_QBUF_CAPT _IOW ('v', BASE_VIDIOCPRIVATE+3, int) #define MJPIOC_QBUF_PLAY _IOW ('v', BASE_VIDIOCPRIVATE+4, int) #define MJPIOC_SYNC _IOR ('v', BASE_VIDIOCPRIVATE+5, struct mjpeg_sync) #define MJPIOC_G_STATUS _IOWR('v', BASE_VIDIOCPRIVATE+6, struct mjpeg_status) mjpegtools-2.1.0/utils/mpegconsts.c0000644000175000017500000002665310346407114017713 0ustar glowwormglowworm /* * mpegconsts.c: Video format constants for MPEG and utilities for display * and conversion to format used for yuv4mpeg * * Copyright (C) 2001 Andrew Stevens * Copyright (C) 2001 Matthew Marjanovic * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "mpegconsts.h" #include "yuv4mpeg.h" #include "yuv4mpeg_intern.h" #include "format_codes.h" static y4m_ratio_t mpeg_framerates[] = { Y4M_FPS_UNKNOWN, Y4M_FPS_NTSC_FILM, Y4M_FPS_FILM, Y4M_FPS_PAL, Y4M_FPS_NTSC, Y4M_FPS_30, Y4M_FPS_PAL_FIELD, Y4M_FPS_NTSC_FIELD, Y4M_FPS_60 }; #define MPEG_NUM_RATES (sizeof(mpeg_framerates)/sizeof(mpeg_framerates[0])) static const mpeg_framerate_code_t mpeg_num_framerates = MPEG_NUM_RATES; static const char * framerate_definitions[MPEG_NUM_RATES] = { "illegal", "24000.0/1001.0 (NTSC 3:2 pulldown converted FILM)", "24.0 (NATIVE FILM)", "25.0 (PAL/SECAM VIDEO / converted FILM)", "30000.0/1001.0 (NTSC VIDEO)", "30.0", "50.0 (PAL FIELD RATE)", "60000.0/1001.0 (NTSC FIELD RATE)", "60.0" }; static const char *mpeg1_aspect_ratio_definitions[] = { "illegal", "1:1 (square pixels)", "1:0.6735", "1:0.7031 (16:9 Anamorphic PAL/SECAM for 720x578/352x288 images)", "1:0.7615", "1:0.8055", "1:0.8437 (16:9 Anamorphic NTSC for 720x480/352x240 images)", "1:0.8935", "1:0.9375 (4:3 PAL/SECAM for 720x578/352x288 images)", "1:0.9815", "1:1.0255", "1:1:0695", "1:1.1250 (4:3 NTSC for 720x480/352x240 images)", "1:1.1575", "1:1.2015" }; static const y4m_ratio_t mpeg1_aspect_ratios[] = { Y4M_SAR_UNKNOWN, Y4M_SAR_MPEG1_1, Y4M_SAR_MPEG1_2, Y4M_SAR_MPEG1_3, /* Anamorphic 16:9 PAL */ Y4M_SAR_MPEG1_4, Y4M_SAR_MPEG1_5, Y4M_SAR_MPEG1_6, /* Anamorphic 16:9 NTSC */ Y4M_SAR_MPEG1_7, Y4M_SAR_MPEG1_8, /* PAL/SECAM 4:3 */ Y4M_SAR_MPEG1_9, Y4M_SAR_MPEG1_10, Y4M_SAR_MPEG1_11, Y4M_SAR_MPEG1_12, /* NTSC 4:3 */ Y4M_SAR_MPEG1_13, Y4M_SAR_MPEG1_14, }; static const char *mpeg2_aspect_ratio_definitions[] = { "illegal", "1:1 pixels", "4:3 display", "16:9 display", "2.21:1 display" }; static const y4m_ratio_t mpeg2_aspect_ratios[] = { Y4M_DAR_UNKNOWN, Y4M_DAR_MPEG2_1, Y4M_DAR_MPEG2_2, Y4M_DAR_MPEG2_3, Y4M_DAR_MPEG2_4 }; static const char **aspect_ratio_definitions[2] = { mpeg1_aspect_ratio_definitions, mpeg2_aspect_ratio_definitions }; static const y4m_ratio_t *mpeg_aspect_ratios[2] = { mpeg1_aspect_ratios, mpeg2_aspect_ratios }; static const mpeg_aspect_code_t mpeg_num_aspect_ratios[2] = { sizeof(mpeg1_aspect_ratios)/sizeof(mpeg1_aspect_ratios[0]), sizeof(mpeg2_aspect_ratios)/sizeof(mpeg2_aspect_ratios[0]) }; static const char *mjpegtools_format_code_definitions[MPEG_FORMAT_LAST+1] = { "Generic MPEG1", "Standard VCD", "Stretched VCD", "Generic MPEG2", "Standard SVCD", "Stretched SVCD", "VCD Still", "SVCD Still", "DVD with dummy navigation packets", "Standard DVD", "ATSC 480i", "ATSC 480p", "ATSC 720p", "ATSC 1080i" }; /* * Is code a valid MPEG framerate code? */ int mpeg_valid_framerate_code( mpeg_framerate_code_t code ) { return ((code > 0) && (code < mpeg_num_framerates)) ? 1 : 0; } /* * Convert MPEG frame-rate code to corresponding frame-rate */ y4m_ratio_t mpeg_framerate( mpeg_framerate_code_t code ) { if ((code > 0) && (code < mpeg_num_framerates)) return mpeg_framerates[code]; else return y4m_fps_UNKNOWN; } /* * Look-up MPEG frame rate code for a (exact) frame rate. */ mpeg_framerate_code_t mpeg_framerate_code( y4m_ratio_t framerate ) { mpeg_framerate_code_t i; y4m_ratio_reduce(&framerate); /* start at '1', because 0 is unknown/illegal */ for (i = 1; i < mpeg_num_framerates; ++i) { if (Y4M_RATIO_EQL(framerate, mpeg_framerates[i])) return i; } return 0; } /* small enough to distinguish 1/1000 from 1/1001 */ #define MPEG_FPS_TOLERANCE 0.0001 y4m_ratio_t mpeg_conform_framerate( double fps ) { mpeg_framerate_code_t i; y4m_ratio_t result; /* try to match it to a standard frame rate */ /* (start at '1', because 0 is unknown/illegal) */ for (i = 1; i < mpeg_num_framerates; i++) { double deviation = 1.0 - (Y4M_RATIO_DBL(mpeg_framerates[i]) / fps); if ( (deviation > -MPEG_FPS_TOLERANCE) && (deviation < +MPEG_FPS_TOLERANCE) ) return mpeg_framerates[i]; } /* no luck? just turn it into a ratio (6 decimal place accuracy) */ result.n = (int)((fps * 1000000.0) + 0.5); result.d = 1000000; y4m_ratio_reduce(&result); return result; } /* * Is code a valid MPEG aspect-ratio code? */ int mpeg_valid_aspect_code( int version, mpeg_framerate_code_t c ) { if ((version == 1) || (version == 2)) return ((c > 0) && (c < mpeg_num_aspect_ratios[version-1])) ? 1 : 0; else return 0; } /* * Convert MPEG aspect-ratio code to corresponding aspect-ratio */ y4m_ratio_t mpeg_aspect_ratio( int mpeg_version, mpeg_aspect_code_t code ) { y4m_ratio_t ratio; if ((mpeg_version >= 1) && (mpeg_version <= 2) && (code > 0) && (code < mpeg_num_aspect_ratios[mpeg_version-1])) { ratio = mpeg_aspect_ratios[mpeg_version-1][code]; y4m_ratio_reduce(&ratio); return ratio; } else return y4m_sar_UNKNOWN; } /* * Look-up corresponding MPEG aspect ratio code given an exact aspect ratio. * * WARNING: The semantics of aspect ratio coding *changed* between * MPEG1 and MPEG2. In MPEG1 it is the *pixel* aspect ratio. In * MPEG2 it is the (far more sensible) aspect ratio of the eventual * display. * */ mpeg_aspect_code_t mpeg_frame_aspect_code( int mpeg_version, y4m_ratio_t aspect_ratio ) { mpeg_aspect_code_t i; y4m_ratio_t red_ratio = aspect_ratio; y4m_ratio_reduce( &red_ratio ); if( mpeg_version < 1 || mpeg_version > 2 ) return 0; /* (start at '1', because 0 is unknown/illegal) */ for( i = 1; i < mpeg_num_aspect_ratios[mpeg_version-1]; ++i ) { y4m_ratio_t red_entry = mpeg_aspect_ratios[mpeg_version-1][i]; y4m_ratio_reduce( &red_entry ); if( Y4M_RATIO_EQL( red_entry, red_ratio) ) return i; } return 0; } /* * Guess the correct MPEG aspect ratio code, * given the true sample aspect ratio and frame size of a video stream * (and the MPEG version, 1 or 2). * * Returns 0 if it has no good guess. * */ /* this is big enough to accommodate the difference between 720 and 704 */ #define GUESS_ASPECT_TOLERANCE 0.03 mpeg_aspect_code_t mpeg_guess_mpeg_aspect_code(int mpeg_version, y4m_ratio_t sampleaspect, int frame_width, int frame_height) { if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_UNKNOWN)) { return 0; } switch (mpeg_version) { case 1: if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_SQUARE)) { return 1; } else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_NTSC_CCIR601)) { return 12; } else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_NTSC_16_9)) { return 6; } else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_PAL_CCIR601)) { return 8; } else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_PAL_16_9)) { return 3; } return 0; break; case 2: if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_SQUARE)) { return 1; /* '1' means square *pixels* in MPEG-2; go figure. */ } else { int i; double true_far; /* true frame aspect ratio */ true_far = (double)(sampleaspect.n * frame_width) / (double)(sampleaspect.d * frame_height); /* start at '2'... */ for (i = 2; i < (int)(mpeg_num_aspect_ratios[mpeg_version-1]); i++) { double ratio = true_far / Y4M_RATIO_DBL(mpeg_aspect_ratios[mpeg_version-1][i]); if ( (ratio > (1.0 - GUESS_ASPECT_TOLERANCE)) && (ratio < (1.0 + GUESS_ASPECT_TOLERANCE)) ) return i; } return 0; } break; default: return 0; break; } } /* * Guess the true sample aspect ratio of a video stream, * given the MPEG aspect ratio code and the actual frame size * (and the MPEG version, 1 or 2). * * Returns y4m_sar_UNKNOWN if it has no good guess. * */ y4m_ratio_t mpeg_guess_sample_aspect_ratio(int mpeg_version, mpeg_aspect_code_t code, int frame_width, int frame_height) { switch (mpeg_version) { case 1: /* MPEG-1 codes turn into SAR's, just not quite the right ones. For the common/known values, we provide the ratio used in practice, otherwise say we don't know.*/ switch (code) { case 1: return y4m_sar_SQUARE; break; case 3: return y4m_sar_PAL_16_9; break; case 6: return y4m_sar_NTSC_16_9; break; case 8: return y4m_sar_PAL_CCIR601; break; case 12: return y4m_sar_NTSC_CCIR601; break; default: return y4m_sar_UNKNOWN; break; } break; case 2: /* MPEG-2 codes turn into Display Aspect Ratios, though not exactly the DAR's used in practice. For common/standard frame sizes, we provide the original SAR; otherwise, we say we don't know. */ if (code == 1) { return y4m_sar_SQUARE; /* '1' means square *pixels* in MPEG-2 */ } else if ((code >= 2) && (code <= 4)) { return y4m_guess_sar(frame_width, frame_height, mpeg2_aspect_ratios[code]); } else { return y4m_sar_UNKNOWN; } break; default: return y4m_sar_UNKNOWN; break; } } /* * Look-up MPEG explanatory definition string for frame rate code * */ const char * mpeg_framerate_code_definition( mpeg_framerate_code_t code ) { if( code == 0 || code >= mpeg_num_framerates ) return "UNDEFINED: illegal/reserved frame-rate ratio code"; return framerate_definitions[code]; } /* * Look-up MPEG explanatory definition string aspect ratio code for an * aspect ratio code * */ const char * mpeg_aspect_code_definition( int mpeg_version, mpeg_aspect_code_t code ) { if( mpeg_version < 1 || mpeg_version > 2 ) return "UNDEFINED: illegal MPEG version"; if( code < 1 || code >= mpeg_num_aspect_ratios[mpeg_version-1] ) return "UNDEFINED: illegal aspect ratio code"; return aspect_ratio_definitions[mpeg_version-1][code]; } /* * Look-up explanatory definition of interlace field order code * */ const char * mpeg_interlace_code_definition( int yuv4m_interlace_code ) { const char *def; switch( yuv4m_interlace_code ) { case Y4M_UNKNOWN : def = "unknown"; break; case Y4M_ILACE_NONE : def = "none/progressive"; break; case Y4M_ILACE_TOP_FIRST : def = "top-field-first"; break; case Y4M_ILACE_BOTTOM_FIRST : def = "bottom-field-first"; break; default : def = "UNDEFINED: illegal video interlacing type-code!"; break; } return def; } /* * Look-up explanatory definition of mjepgtools preset format code * */ const char *mpeg_format_code_defintion( int format_code ) { if(format_code >= MPEG_FORMAT_FIRST && format_code <= MPEG_FORMAT_LAST ) return mjpegtools_format_code_definitions[format_code]; else return "UNDEFINED: illegal format code!"; }; /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/utils/mjpeg_logging.h0000644000175000017500000000414010603772216020335 0ustar glowwormglowworm/* $Id: mjpeg_logging.h,v 1.11 2007/04/01 18:06:06 sms00 Exp $ Copyright (C) 2000 Herbert Valerio Riedel This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __MJPEG_LOGGING_H__ #define __MJPEG_LOGGING_H__ #include /* to avoid changing all the places log_level_t is used */ typedef int log_level_t; #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) #define GNUC_PRINTF( format_idx, arg_idx ) \ __attribute__((format (printf, format_idx, arg_idx))) #else /* !__GNUC__ */ #define GNUC_PRINTF( format_idx, arg_idx ) #endif /* !__GNUC__ */ #ifdef __cplusplus extern "C" { #endif void mjpeg_log(log_level_t level, const char format[], ...) GNUC_PRINTF(2, 3); typedef int(*mjpeg_log_filter_t)(log_level_t level); typedef void(*mjpeg_log_handler_t)(log_level_t level, const char message[]); mjpeg_log_handler_t mjpeg_log_set_handler(mjpeg_log_handler_t new_handler); int mjpeg_default_handler_identifier(const char *new_id); int mjpeg_default_handler_verbosity(int verbosity); void mjpeg_debug(const char format[], ...) GNUC_PRINTF(1,2); void mjpeg_info(const char format[], ...) GNUC_PRINTF(1,2); void mjpeg_warn(const char format[], ...) GNUC_PRINTF(1,2); void mjpeg_error(const char format[], ...) GNUC_PRINTF(1,2); void mjpeg_error_exit1(const char format[], ...) GNUC_PRINTF(1,2); log_level_t mjpeg_loglev_t(const char *str); #ifdef __cplusplus } #endif #endif /* __MJPEG_LOGGING_H__ */ mjpegtools-2.1.0/utils/cpu_accel.h0000644000175000017500000000340710535654550017454 0ustar glowwormglowworm/* * cpu_accel.h * Copyright (C) 1999-2000 Aaron Holtzman * * This file was part of mpeg2dec, a free MPEG-2 video stream decoder. * * mpeg2dec is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * mpeg2dec is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _CPU_ACCEL_HH #define _CPU_ACCEL_HH #include #include "mjpeg_types.h" // x86 accelerations #define ACCEL_X86_MMX 0x80000000 #define ACCEL_X86_3DNOW 0x40000000 #define ACCEL_X86_MMXEXT 0x20000000 #define ACCEL_X86_SSE 0x10000000 #ifdef __cplusplus extern "C" { #endif int32_t cpu_accel (void); void *bufalloc( size_t size ); #if !defined(HAVE_POSIX_MEMALIGN) int posix_memalign(void **, size_t, size_t); #endif #if !defined(HAVE_MEMALIGN) void *memalign(size_t, size_t); #endif #if !defined(HAVE_FMAX) double fmax(double, double); #endif #if !defined(HAVE_FMIN) double fmin(double, double); #endif /* take a pointer, and force it to be aligned on a particular boundary */ #define ALIGN_PTR(p,a) ((void *)( (((size_t)(p))+(a)-1)&~((size_t)(a)-1))) extern const char *disable_simd_flags[]; extern int simd_name_ok(char *); extern int disable_simd(char *); #ifdef __cplusplus } #endif #endif mjpegtools-2.1.0/utils/motionsearch.c0000644000175000017500000005633410535654550020233 0ustar glowwormglowworm/* motionsearch.c, block motion estimation for mpeg2enc */ /* (C) 2000/2001 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include "cpu_accel.h" #include "fastintfns.h" #include "motionsearch.h" #include "mjpeg_logging.h" /* * Define prototypes so as to avoid warning errors at compile time */ void sub_mean_reduction(me_result_set *, int, int *); void subsample_image(uint8_t *,int ,uint8_t *,uint8_t *); void variance(uint8_t *,int ,int, unsigned int *,unsigned int *); /* The AltiVec code needs access to symbols during benchmarking * and verification. */ #define STATIC static #ifdef HAVE_ALTIVEC #include "altivec/altivec_motion.h" # if ALTIVEC_TEST_MOTION # undef STATIC # define STATIC /* static */ # endif #endif #if defined(HAVE_ASM_MMX) #include "mmxsse/mmxsse_motion.h" #endif /* * Function pointers for selecting CPU specific implementations * */ int (*pmblocks_sub44_mests)( uint8_t *blk, uint8_t *ref, int ilow, int jlow, int ihigh, int jhigh, int h, int rowstride, int threshold, me_result_s *resvec); void (*pfind_best_one_pel)( me_result_set *sub22set, uint8_t *org, uint8_t *blk, int i0, int j0, int ihigh, int jhigh, int rowstride, int h, me_result_s *res ); int (*pbuild_sub22_mests)( me_result_set *sub44set, me_result_set *sub22set, int i0, int j0, int ihigh, int jhigh, int null_mc_sad, uint8_t *s22org, uint8_t *s22blk, int frowstride, int fh, int reduction ); int (*pbuild_sub44_mests)( me_result_set *sub44set, int ilow, int jlow, int ihigh, int jhigh, int i0, int j0, int null_mc_sad, uint8_t *s44org, uint8_t *s44blk, int qrowstride, int qh, int reduction ); int (*psumsq_sub22)( uint8_t *blk1, uint8_t *blk2, int rowstride, int h); int (*pbsumsq_sub22)( uint8_t *blk1f, uint8_t *blk1b, uint8_t *blk2, int rowstride, int h); void (*pvariance)(uint8_t *mb, int size, int rowstride, uint32_t *p_var, uint32_t *p_mean); int (*psad_sub22) ( uint8_t *blk1, uint8_t *blk2, int frowstride, int fh); int (*psad_sub44) ( uint8_t *blk1, uint8_t *blk2, int qrowstride, int qh); int (*psad_00) ( uint8_t *blk1, uint8_t *blk2, int rowstride, int h, int distlim); int (*psad_01) (uint8_t *blk1, uint8_t *blk2, int rowstride, int h); int (*psad_10) (uint8_t *blk1, uint8_t *blk2, int rowstride, int h); int (*psad_11) (uint8_t *blk1, uint8_t *blk2, int rowstride, int h); int (*psumsq) (uint8_t *blk1, uint8_t *blk2, int rowstride, int hx, int hy, int h); int (*pbsumsq) (uint8_t *pf, uint8_t *pb, uint8_t *p2, int rowstride, int hxf, int hyf, int hxb, int hyb, int h); int (*pbsad) (uint8_t *pf, uint8_t *pb, uint8_t *p2, int rowstride, int hxf, int hyf, int hxb, int hyb, int h); void (*psubsample_image) (uint8_t *image, int rowstride, uint8_t *sub22_image, uint8_t *sub44_image); /* * Round search radius to suit the search algorithm. * Currently radii must be multiples of 8. * */ int round_search_radius( int radius ) { return intmax(8,((radius+4) /8)*8); } /* Take a vector of motion estimations and repeatedly make passes discarding all elements whose sad "weight" is above the current mean weight. */ void sub_mean_reduction( me_result_set *matchset, int times, int *minweight_res) { me_result_s *matches = matchset->mests; int len = matchset->len; int i,j; int weight_sum; int mean_weight; if( len <= 1 ) { *minweight_res = (len==0) ? 100000 : matches[0].weight; return; } for(;;) { weight_sum = 0; for( i = 0; i < len ; ++i ) weight_sum += matches[i].weight; mean_weight = weight_sum / len; if( times <= 0) break; j = 0; for( i =0; i < len; ++i ) { if( matches[i].weight <= mean_weight ) { matches[j] = matches[i]; ++j; } } len = j; --times; } matchset->len = len; *minweight_res = mean_weight; } /* * Build a vector of the top 4*4 sub-sampled motion estimations in * the box (ilow,jlow) to (ihigh,jhigh). * * The algorithm is as follows: * * 1. Matches on an 4*4 pel grid are collected. All those matches * whose that is over a (conservative) threshold (basically 50% more * than moving average of the mean sad of such matches) are discarded. * * 2. Multiple passes are made discarding worse than-average matches. * The number of passes is specified by the user. The default it 2 * (leaving roughly 1/4 of the matches). * * The intial threshold and discard passes are controlled by reduction * [1..4]. The intial SAD threshold is calculated as 6 / reduction of * a reference SAD passed as a parameter. For reduction == 1 one * discard pass is made otherwise two are made. * * The net result is very fast and find good matches if they're to be * found. I.e. the penalty over exhaustive search is pretty low. * * NOTE: The "discard below average" trick depends critically on * having some variation in the matches. The slight penalty imposed * for distant matches (reasonable since the motion vectors have to * be encoded) is *vital* as otherwise pathologically bad performance * results on highly uniform images. * * TODO: We should probably allow the user to eliminate the initial * thinning of 4*4 grid matches if ultimate quality is demanded * (e.g. for low bit-rate applications). * */ STATIC int build_sub44_mests( me_result_set *sub44set, int ilow, int jlow, int ihigh, int jhigh, int i0, int j0, int null_ctl_sad, uint8_t *s44org, uint8_t *s44blk, int qrowstride, int qh, int reduction ) { uint8_t *s44orgblk; me_result_s *sub44_mests = sub44set->mests; int istrt = ilow-i0; int jstrt = jlow-j0; int iend = ihigh-i0; int jend = jhigh-j0; int mean_weight; int threshold; int i,j; int s1; uint8_t *old_s44orgblk; int sub44_num_mests; /* N.b. we may ignore the right hand block of the pair going over the right edge as we have carefully allocated the buffer oversize to ensure no memory faults. The later motion estimation calculations performed on the results of this pass will filter out out-of-range blocks... */ threshold = 6*null_ctl_sad / (4*4*reduction); s44orgblk = s44org+(ilow>>2)+qrowstride*(jlow>>2); /* Exhaustive search on 4*4 sub-sampled data. This is affordable because (a) it is only 16th of the size of the real 1-pel data (b) we ignore those matches with an sad above our threshold. */ sub44_num_mests = 0; /* Invariant: s44orgblk = s44org+(i>>2)+qrowstride*(j>>2) */ s44orgblk = s44org+(ilow>>2)+qrowstride*(jlow>>2); for( j = jstrt; j <= jend; j += 4 ) { old_s44orgblk = s44orgblk; for( i = istrt; i <= iend; i += 4 ) { s1 = ((*psad_sub44)( s44orgblk,s44blk,qrowstride,qh) & 0xffff); if( s1 < threshold ) { threshold = intmin(s1<<2,threshold); sub44_mests[sub44_num_mests].x = i; sub44_mests[sub44_num_mests].y = j; sub44_mests[sub44_num_mests].weight = s1 + (intmax(abs(i-i0), abs(j-j0))<<1); ++sub44_num_mests; } s44orgblk += 1; } s44orgblk = old_s44orgblk + qrowstride; } sub44set->len = sub44_num_mests; sub_mean_reduction( sub44set, 1+(reduction>1), &mean_weight); return sub44set->len; } /* Build a vector of the best 2*2 sub-sampled motion estimations for * the 16*16 macroblock at i0,j0 using a set of 4*4 sub-sampled matches as * starting points. As with with the 4*4 matches We don't collect * them densely as they're just search starting points for 1-pel * search and ones that are 1 out * should still give better than * average matches... * * The resulting candidate motion vectors are thinned by thresholding * and discarding worse than-average matches. * * The intial threshold and number of discard passes are controlled by reduction * [1..4]: the intial SAD threshold is calculated as 6 / reduction of * a reference SAD passed as a parameter and then reduction discard passes * are made. * */ STATIC int build_sub22_mests( me_result_set *sub44set, me_result_set *sub22set, int i0, int j0, int ihigh, int jhigh, int null_ctl_sad, uint8_t *s22org, uint8_t *s22blk, int frowstride, int fh, int reduction) { int i,k,s; int threshold = 6*null_ctl_sad / (2 * 2*reduction); int min_weight; int ilim = ihigh-i0; int jlim = jhigh-j0; int x,y; uint8_t *s22orgblk; sub22set->len = 0; for( k = 0; k < sub44set->len; ++k ) { x = sub44set->mests[k].x; y = sub44set->mests[k].y; s22orgblk = s22org +((y+j0)>>1)*frowstride +((x+i0)>>1); for( i = 0; i < 4; ++i ) { if( x <= ilim && y <= jlim ) { s = (*psad_sub22)( s22orgblk,s22blk,frowstride,fh)+ (intmax(abs(x), abs(y))<<3); if( s < threshold ) { me_result_s *mc = &sub22set->mests[sub22set->len]; mc->x = (int8_t)x; mc->y = (int8_t)y; mc->weight = s; ++(sub22set->len); } } if( i == 1 ) { s22orgblk += frowstride-1; x -= 2; y += 2; } else { s22orgblk += 1; x += 2; } } } sub_mean_reduction( sub22set, reduction, &min_weight ); return sub22set->len; } /* * Search for the best 1-pel match within 1-pel of a good 2*2-pel * match. * * N.b. best_so_far must be initialised by the caller! */ STATIC void find_best_one_pel( me_result_set *sub22set, uint8_t *org, uint8_t *blk, int i0, int j0, int ihigh, int jhigh, int rowstride, int h, me_result_s *best_so_far ) { int i,k; int d; me_result_s minpos = *best_so_far; int dmin = INT_MAX; int ilim = ihigh-i0; int jlim = jhigh-j0; uint8_t *orgblk; int penalty; me_result_s matchrec; for( k = 0; k < sub22set->len; ++k ) { matchrec = sub22set->mests[k]; orgblk = org + (i0+matchrec.x)+rowstride*(j0+matchrec.y); penalty = (abs(matchrec.x) + abs(matchrec.y))<<3; for( i = 0; i < 4; ++i ) { if( matchrec.x <= ilim && matchrec.y <= jlim ) { d = penalty+(*psad_00)(orgblk,blk,rowstride,h, dmin); if (d= distlim) break; p1+= rowstride; p2+= rowstride; } return s; } STATIC int sad_01(uint8_t *blk1,uint8_t *blk2,int rowstride, int h) { uint8_t *p1,*p2; int i,j; int s; register int v; s = 0; p1 = blk1; p2 = blk2; for (j=0; j>1) - p2[i]; s += abs(v); } p1+= rowstride; p2+= rowstride; } return s; } STATIC int sad_10(uint8_t *blk1,uint8_t *blk2, int rowstride, int h) { uint8_t *p1,*p1a,*p2; int i,j; int s; register int v; s = 0; p1 = blk1; p2 = blk2; p1a = p1 + rowstride; for (j=0; j>1) - p2[i]; s += abs(v); } p1 = p1a; p1a+= rowstride; p2+= rowstride; } return s; } STATIC int sad_11(uint8_t *blk1,uint8_t *blk2, int rowstride, int h) { uint8_t *p1,*p1a,*p2; int i,j; int s; register int v; s = 0; p1 = blk1; p2 = blk2; p1a = p1 + rowstride; for (j=0; j>2) - p2[i]; s += abs(v); } p1 = p1a; p1a+= rowstride; p2+= rowstride; } return s; } /* * Compute subsampled images for fast motion compensation search * N.b. rowstride should be *two* line widths for interlace images */ void subsample_image( uint8_t *image, int rowstride, uint8_t *sub22_image, uint8_t *sub44_image) { uint8_t *blk = image; uint8_t *b, *nb; uint8_t *pb; uint8_t *qb; uint8_t *start_s22blk, *start_s44blk; int i; int nextfieldline = rowstride; start_s22blk = sub22_image; start_s44blk = sub44_image; b = blk; nb = (blk+nextfieldline); pb = (uint8_t *) start_s22blk; while( nb < start_s22blk ) { for( i = 0; i < nextfieldline/4; ++i ) /* We're doing 4 pels horizontally at once */ { pb[0] = ((b[0]+b[1])+(nb[0]+nb[1])+2)>>2; pb[1] = ((b[2]+b[3])+(nb[2]+nb[3])+2)>>2; pb += 2; b += 4; nb += 4; } b += nextfieldline; nb = b + nextfieldline; } /* Now create the 4*4 sub-sampled data from the 2*2 N.b. the 2*2 sub-sampled motion data preserves the interlace structure of the original. Albeit half as many lines and pixels... */ nextfieldline = nextfieldline >> 1; qb = start_s44blk; b = start_s22blk; nb = (start_s22blk+nextfieldline); while( nb < start_s44blk ) { for( i = 0; i < nextfieldline/4; ++i ) { qb[0] = ((b[0]+b[1])+(nb[0]+nb[1])+2)>>2; qb[1] = ((b[2]+b[3])+(nb[2]+nb[3])+2)>>2; qb += 2; b += 4; nb += 4; } b += nextfieldline; nb = b + nextfieldline; } } /* * Same as sad_00 except for 2*2 subsampled data so only 8 wide! * */ STATIC int sad_sub22( uint8_t *s22blk1, uint8_t *s22blk2,int frowstride,int fh) { uint8_t *p1 = s22blk1; uint8_t *p2 = s22blk2; int s = 0; int j; for( j = 0; j < fh; ++j ) { register int diff; #define pipestep(o) diff = p1[o]-p2[o]; s += abs(diff) pipestep(0); pipestep(1); pipestep(2); pipestep(3); pipestep(4); pipestep(5); pipestep(6); pipestep(7); p1 += frowstride; p2 += frowstride; #undef pipestep } return s; } /* * Same as sad_00 except for 4*4 sub-sampled data. * * N.b.: currently assumes only 16*16 or 16*8 motion estimation will * be used... I.e. 4*4 or 4*2 sub-sampled blocks will be compared. * * */ STATIC int sad_sub44( uint8_t *s44blk1, uint8_t *s44blk2,int qrowstride,int qh) { register uint8_t *p1 = s44blk1; register uint8_t *p2 = s44blk2; int s = 0; register int diff; /* #define pipestep(o) diff = p1[o]-p2[o]; s += abs(diff) */ #define pipestep(o) diff = p1[o]-p2[o]; s += diff < 0 ? -diff : diff; pipestep(0); pipestep(1); pipestep(2); pipestep(3); if( qh > 1 ) { p1 += qrowstride; p2 += qrowstride; pipestep(0); pipestep(1); pipestep(2); pipestep(3); if( qh > 2 ) { p1 += qrowstride; p2 += qrowstride; pipestep(0); pipestep(1); pipestep(2); pipestep(3); p1 += qrowstride; p2 += qrowstride; pipestep(0); pipestep(1); pipestep(2); pipestep(3); } } return s; } /* * total squared difference between two (8*h) blocks of 2*2 sub-sampled pels * blk1,blk2: addresses of top left pels of both blocks * rowstride: distance (in bytes) of vertically adjacent pels * h: height of block (usually 8 or 16) */ STATIC int sumsq_sub22(uint8_t *blk1, uint8_t *blk2, int rowstride, int h) { uint8_t *p1 = blk1, *p2 = blk2; int i,j,v; int s = 0; for (j=0; j>1) - p2[i]; s+= v*v; } p1f+= rowstride; p1b+= rowstride; p2+= rowstride; } return s; } /* * total squared difference between two (16*h) blocks * including optional half pel interpolation of blk1 (hx,hy) * blk1,blk2: addresses of top left pels of both blocks * rowstride: distance (in bytes) of vertically adjacent pels * hx,hy: flags for horizontal and/or vertical interpolation * h: height of block (usually 8 or 16) */ STATIC int sumsq(blk1,blk2,rowstride,hx,hy,h) uint8_t *blk1,*blk2; int rowstride,hx,hy,h; { uint8_t *p1,*p1a,*p2; int i,j; int s,v; s = 0; p1 = blk1; p2 = blk2; if (!hx && !hy) for (j=0; j>1) - p2[i]; s+= v*v; } p1+= rowstride; p2+= rowstride; } else if (!hx && hy) { p1a = p1 + rowstride; for (j=0; j>1) - p2[i]; s+= v*v; } p1 = p1a; p1a+= rowstride; p2+= rowstride; } } else /* if (hx && hy) */ { p1a = p1 + rowstride; for (j=0; j>2) - p2[i]; s+= v*v; } p1 = p1a; p1a+= rowstride; p2+= rowstride; } } return s; } /* * absolute difference error between a (16*h) block and a bidirectional * prediction * * p2: address of top left pel of block * pf,hxf,hyf: address and half pel flags of forward ref. block * pb,hxb,hyb: address and half pel flags of backward ref. block * h: height of block * rowstride: distance (in bytes) of vertically adjacent pels in p2,pf,pb */ STATIC int bsad(pf,pb,p2,rowstride,hxf,hyf,hxb,hyb,h) uint8_t *pf,*pb,*p2; int rowstride,hxf,hyf,hxb,hyb,h; { uint8_t *pfa,*pfb,*pfc,*pba,*pbb,*pbc; int i,j; int s,v; pfa = pf + hxf; pfb = pf + rowstride*hyf; pfc = pfb + hxf; pba = pb + hxb; pbb = pb + rowstride*hyb; pbc = pbb + hxb; s = 0; for (j=0; j>2) + ((unsigned int)(*pb++ + *pba++ + *pbb++ + *pbc++ + 2)>>2) + 1)>>1) - *p2++; s += abs(v); } p2+= rowstride-16; pf+= rowstride-16; pfa+= rowstride-16; pfb+= rowstride-16; pfc+= rowstride-16; pb+= rowstride-16; pba+= rowstride-16; pbb+= rowstride-16; pbc+= rowstride-16; } return s; } /* * squared error between a (16*h) block and a bidirectional * prediction * * p2: address of top left pel of block * pf,hxf,hyf: address and half pel flags of forward ref. block * pb,hxb,hyb: address and half pel flags of backward ref. block * h: height of block * rowstride: distance (in bytes) of vertically adjacent pels in p2,pf,pb */ STATIC int bsumsq(pf,pb,p2,rowstride,hxf,hyf,hxb,hyb,h) uint8_t *pf,*pb,*p2; int rowstride,hxf,hyf,hxb,hyb,h; { uint8_t *pfa,*pfb,*pfc,*pba,*pbb,*pbc; int i,j; int s,v; pfa = pf + hxf; pfb = pf + rowstride*hyf; pfc = pfb + hxf; pba = pb + hxb; pbb = pb + rowstride*hyb; pbc = pbb + hxb; s = 0; for (j=0; j>2) + ((ui(*pb++) + ui(*pba++) + ui(*pbb++) + ui(*pbc++) + 2)>>2) + 1 )>>1) - ui(*p2++); #undef ui s+=v*v; } p2+= rowstride-16; pf+= rowstride-16; pfa+= rowstride-16; pfb+= rowstride-16; pfc+= rowstride-16; pb+= rowstride-16; pba+= rowstride-16; pbb+= rowstride-16; pbc+= rowstride-16; } return s; } /* * variance of a (size*size) block, multiplied by 256 * p: address of top left pel of block * rowstride: distance (in bytes) of vertically adjacent pels * SIZE is a multiple of 8. */ void variance(uint8_t *p, int size, int rowstride, unsigned int *p_var, unsigned int *p_mean) { int i,j; unsigned int v,s,s2; s = s2 = 0; for (j=0; j 0) { enable_altivec_motion(); } #endif } /* * In some cases it is necessary to not use the SIMD routines even if they * are available. This can be due to a program not being able to use * correctly aligned buffers OR limitations in the SIMD routines. The * yuvdeinterlace program is known to crash on PPC systems due to the sad_00 * function requiring 16 byte alignment which yuvdeinterlace can not guarantee. * * Rather than completely disabling (via the MJPEGTOOLS_SIMD_DISABLE environment * variable) Altivec sad_00 for all programs in a pipeline the code below * can be used to selectively reset specific functions back to the C reference * code specific. */ #define SIMD_RESET(x) \ if (!strcmp(#x, name) && simd_name_ok( name )) \ { \ mjpeg_info(" Use non-SIMD " #x); \ p##x = x; \ } void reset_motion_simd(char *name) { SIMD_RESET(sad_00); SIMD_RESET(sad_01); SIMD_RESET(sad_10); SIMD_RESET(sad_11); SIMD_RESET(sad_sub22); SIMD_RESET(sad_sub44); SIMD_RESET(bsad); SIMD_RESET(variance); SIMD_RESET(sumsq); SIMD_RESET(bsumsq); SIMD_RESET(sumsq_sub22); SIMD_RESET(bsumsq_sub22); SIMD_RESET(find_best_one_pel); SIMD_RESET(build_sub22_mests); SIMD_RESET(build_sub44_mests); SIMD_RESET(subsample_image); } mjpegtools-2.1.0/utils/mjpeg_types.h0000644000175000017500000000201210433135231020036 0ustar glowwormglowworm/* $Id: mjpeg_types.h,v 1.16 2006/05/18 18:19:05 sms00 Exp $ Copyright (C) 2000 Herbert Valerio Riedel This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __MJPEG_TYPES_H__ #define __MJPEG_TYPES_H__ #include /* FreeBSD, others - ssize_t */ #include #include #endif /* __MJPEG_TYPES_H__ */ mjpegtools-2.1.0/utils/format_codes.h0000644000175000017500000000332110346407114020166 0ustar glowwormglowworm/* $Id: format_codes.h,v 1.10 2005/12/09 23:07:56 wackston2 Exp $ Copyright (C) 2001 Andrew Stevens This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __FORMAT_CODES_H__ #define __FORMAT_CODES_H__ #define MPEG_FORMAT_MPEG1 0 #define MPEG_FORMAT_VCD 1 #define MPEG_FORMAT_VCD_NSR 2 #define MPEG_FORMAT_MPEG2 3 #define MPEG_FORMAT_SVCD 4 #define MPEG_FORMAT_SVCD_NSR 5 #define MPEG_FORMAT_VCD_STILL 6 #define MPEG_FORMAT_SVCD_STILL 7 #define MPEG_FORMAT_DVD_NAV 8 #define MPEG_FORMAT_DVD 9 #define MPEG_FORMAT_ATSC480i 10 #define MPEG_FORMAT_ATSC480p 11 #define MPEG_FORMAT_ATSC720p 12 #define MPEG_FORMAT_ATSC1080i 13 #define MPEG_FORMAT_FIRST 0 #define MPEG_FORMAT_LAST MPEG_FORMAT_ATSC1080i #define MPEG_STILLS_FORMAT(x) ((x)==MPEG_FORMAT_VCD_STILL||(x)==MPEG_FORMAT_SVCD_STILL) #define MPEG_ATSC_FORMAT(x) ((x)>=MPEG_FORMAT_ATSC480i && (x)<=MPEG_FORMAT_ATSC1080i) #define MPEG_HDTV_FORMAT(x) MPEG_ATSC_FORMAT(x) #define MPEG_SDTV_FORMAT(x) (!MPEG_HDTV_FORMAT(x)) #endif /* __FORMAT_CODES_H__ */ mjpegtools-2.1.0/utils/yuv4mpeg_intern.h0000644000175000017500000000607707646664704020716 0ustar glowwormglowworm/* * yuv4mpeg_intern.h: Internal constants for "new" YUV4MPEG streams * * Copyright (C) 2001 Andrew Stevens * Copyright (C) 2001 Matthew J. Marjanovic * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __YUV4MPEG_INTERN_H__ #define __YUV4MPEG_INTERN_H__ #define Y4M_MAGIC "YUV4MPEG2" #define Y4M_FRAME_MAGIC "FRAME" #define Y4M_DELIM " " /* single-character(space) separating tagged fields */ #define Y4M_LINE_MAX 256 /* max number of characters in a header line (including the '\n', but not the '\0') */ /* standard framerate ratios */ #define Y4M_FPS_UNKNOWN { 0, 0 } #define Y4M_FPS_NTSC_FILM { 24000, 1001 } #define Y4M_FPS_FILM { 24, 1 } #define Y4M_FPS_PAL { 25, 1 } #define Y4M_FPS_NTSC { 30000, 1001 } #define Y4M_FPS_30 { 30, 1 } #define Y4M_FPS_PAL_FIELD { 50, 1 } #define Y4M_FPS_NTSC_FIELD { 60000, 1001 } #define Y4M_FPS_60 { 60, 1 } /* standard sample/pixel aspect ratios */ #define Y4M_SAR_UNKNOWN { 0, 0 } #define Y4M_SAR_SQUARE { 1, 1 } #define Y4M_SAR_SQR_ANA_16_9 { 4, 3 } #define Y4M_SAR_NTSC_CCIR601 { 10, 11 } #define Y4M_SAR_NTSC_16_9 { 40, 33 } #define Y4M_SAR_NTSC_SVCD_4_3 { 15, 11 } #define Y4M_SAR_NTSC_SVCD_16_9 { 20, 11 } #define Y4M_SAR_PAL_CCIR601 { 59, 54 } #define Y4M_SAR_PAL_16_9 { 118, 81 } #define Y4M_SAR_PAL_SVCD_4_3 { 59, 36 } #define Y4M_SAR_PAL_SVCD_16_9 { 59, 27 } #define Y4M_SAR_MPEG1_1 Y4M_SAR_SQUARE #define Y4M_SAR_MPEG1_2 { 10000, 6735 } #define Y4M_SAR_MPEG1_3 { 10000, 7031 } /* Anamorphic 16:9 PAL */ #define Y4M_SAR_MPEG1_4 { 10000, 7615 } #define Y4M_SAR_MPEG1_5 { 10000, 8055 } #define Y4M_SAR_MPEG1_6 { 10000, 8437 } /* Anamorphic 16:9 NTSC */ #define Y4M_SAR_MPEG1_7 { 10000, 8935 } #define Y4M_SAR_MPEG1_8 { 10000, 9375 } /* PAL/SECAM 4:3 */ #define Y4M_SAR_MPEG1_9 { 10000, 9815 } #define Y4M_SAR_MPEG1_10 { 10000, 10255 } #define Y4M_SAR_MPEG1_11 { 10000, 10695 } #define Y4M_SAR_MPEG1_12 { 10000, 11250 } /* NTSC 4:3 */ #define Y4M_SAR_MPEG1_13 { 10000, 11575 } #define Y4M_SAR_MPEG1_14 { 10000, 12015 } #define Y4M_DAR_UNKNOWN { 0, 0 } #define Y4M_DAR_4_3 { 4, 3 } #define Y4M_DAR_16_9 { 16, 9 } #define Y4M_DAR_221_100 { 221, 100 } #define Y4M_DAR_MPEG2_1 { 1, 1 } #define Y4M_DAR_MPEG2_2 { 4, 3 } #define Y4M_DAR_MPEG2_3 { 16, 9 } #define Y4M_DAR_MPEG2_4 { 221, 100 } #endif /* __YUV4MPEG_INTERN_H__ */ mjpegtools-2.1.0/utils/cpu_accel.c0000644000175000017500000002341411445477341017451 0ustar glowwormglowworm/* * cpu_accel.c * Copyright (C) 1999-2000 Aaron Holtzman * * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. * * mpeg2dec is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * mpeg2dec is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include "cpu_accel.h" #include "mjpeg_logging.h" /* * This WAS a deprecated header but apparently has been resurrected as a * place to put memalign. malloc() itself is in stdlib.h */ #ifdef HAVE_MALLOC_H #include #endif #ifdef HAVE_ALTIVEC extern int altivec_copy_v0(); #endif /* * Don't add "mblocks_sub44_mests" to the list below because it does not * have a C-reference code counterpart (mblocks_sub44_mests only exists as * a SIMD routine). */ const char *disable_simd_flags[] = { "sad_00", "sad_01", "sad_10", "sad_11", "sad_sub22", "sad_sub44", "bsad", "variance", "sumsq", "sumsq_sub22", "bsumsq_sub22", "bsumsq", "build_sub22_mests", "build_sub44_mests", "subsample_image", "find_best_one_pel", "quant_nonintra", "quant_weight_intra", "quant_weight_nonintra", "iquant_intra", "iquant_nonintra", "fdct", "idct", NULL }; static char *parse_next(char **, const char *); #ifdef HAVE_X86CPU /* Some miscelaneous stuff to allow checking whether SSE instructions cause illegal instruction errors. */ static sigjmp_buf sigill_recover; static RETSIGTYPE sigillhandler(int sig ) { siglongjmp( sigill_recover, 1 ); } typedef RETSIGTYPE (*__sig_t)(int); static int testsseill() { int illegal; #if defined(__CYGWIN__) /* SSE causes a crash on CYGWIN, apparently. Perhaps the wrong signal is being caught or something along those line ;-) or maybe SSE itself won't work... */ illegal = 1; #else __sig_t old_handler = signal( SIGILL, sigillhandler); if( sigsetjmp( sigill_recover, 1 ) == 0 ) { asm ( "movups %xmm0, %xmm0" ); illegal = 0; } else illegal = 1; signal( SIGILL, old_handler ); #endif return illegal; } static int x86_accel (void) { long eax, ebx, ecx, edx; int32_t AMD; int32_t caps; /* Slightly weirdified cpuid that preserves the ebx and edi required by gcc for PIC offset table and frame pointer */ #if defined(__LP64__) || defined(_LP64) # define REG_b "rbx" # define REG_S "rsi" #else # define REG_b "ebx" # define REG_S "esi" #endif #define cpuid(op,eax,ebx,ecx,edx) \ asm ( "push %%"REG_b"\n" \ "cpuid\n" \ "mov %%"REG_b", %%"REG_S"\n" \ "pop %%"REG_b"\n" \ : "=a" (eax), \ "=S" (ebx), \ "=c" (ecx), \ "=d" (edx) \ : "a" (op) \ : "cc", "edi") asm ("pushf\n\t" "pop %0\n\t" "mov %0,%1\n\t" "xor $0x200000,%0\n\t" "push %0\n\t" "popf\n\t" "pushf\n\t" "pop %0" : "=a" (eax), "=c" (ecx) : : "cc"); if (eax == ecx) // no cpuid return 0; cpuid (0x00000000, eax, ebx, ecx, edx); if (!eax) // vendor string only return 0; AMD = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65); cpuid (0x00000001, eax, ebx, ecx, edx); if (! (edx & 0x00800000)) // no MMX return 0; caps = ACCEL_X86_MMX; /* If SSE capable CPU has same MMX extensions as AMD and then some. However, to use SSE O.S. must have signalled it use of FXSAVE/FXRSTOR through CR4.OSFXSR and hence FXSR (bit 24) here */ if ((edx & 0x02000000)) caps = ACCEL_X86_MMX | ACCEL_X86_MMXEXT; if( (edx & 0x03000000) == 0x03000000 ) { /* Check whether O.S. has SSE support... has to be done with exception 'cos those Intel morons put the relevant bit in a reg that is only accesible in ring 0... doh! */ if( !testsseill() ) caps |= ACCEL_X86_SSE; } cpuid (0x80000000, eax, ebx, ecx, edx); if (eax < 0x80000001) // no extended capabilities return caps; cpuid (0x80000001, eax, ebx, ecx, edx); if (edx & 0x80000000) caps |= ACCEL_X86_3DNOW; if (AMD && (edx & 0x00400000)) // AMD MMX extensions { caps |= ACCEL_X86_MMXEXT; } return caps; } #endif #ifdef HAVE_ALTIVEC /* AltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder * Copyright (C) 2002 James Klicman * * The altivec_detect() function has been moved here to workaround a bug in a * released version of GCC (3.3.3). When -maltivec and -mabi=altivec are * specified, the bug causes VRSAVE instructions at the beginning and end of * functions which do not use AltiVec. GCC 3.3.3 also lacks support for * '#pragma altivec_vrsave off' which would have been the preferred workaround. * * This AltiVec detection code relies on the operating system to provide an * illegal instruction signal if AltiVec is not present. It is known to work * on Mac OS X and Linux. */ static sigjmp_buf jmpbuf; static void sig_ill(int sig) { siglongjmp(jmpbuf, 1); } int detect_altivec() { volatile int detected = 0; /* volatile (modified after sigsetjmp) */ struct sigaction act, oact; act.sa_handler = sig_ill; sigemptyset(&act.sa_mask); act.sa_flags = 0; if (sigaction(SIGILL, &act, &oact)) { perror("sigaction"); return 0; } if (sigsetjmp(jmpbuf, 1)) goto noAltiVec; /* try to read an AltiVec register */ altivec_copy_v0(); detected = 1; noAltiVec: if (sigaction(SIGILL, &oact, (struct sigaction *)0)) perror("sigaction"); return detected; } #endif int32_t cpu_accel (void) { #ifdef HAVE_X86CPU static int got_accel = 0; static int accel; if (!got_accel) { got_accel = 1; accel = x86_accel (); } return accel; #elif defined(HAVE_ALTIVEC) return detect_altivec(); #else return 0; #endif } /***************************** * * Allocate memory aligned to suit SIMD * ****************************/ #define powerof2(x) ((((x)-1)&(x))==0) #if !defined(HAVE_POSIX_MEMALIGN) int posix_memalign(void **ptr, size_t alignment, size_t size) { void *mem; if (alignment % sizeof (void *) != 0 || !powerof2(alignment) != 0) return(EINVAL); mem = malloc((size + alignment - 1) & ~(alignment - 1)); if (mem != NULL) { *ptr = mem; return(0); } return(ENOMEM); } #endif #if !defined(HAVE_MEMALIGN) void * memalign(size_t alignment, size_t size) { if (alignment % sizeof (void *) || !powerof2(alignment)) { errno = EINVAL; return(NULL); } return(malloc((size + alignment - 1) & ~(alignment - 1))); } #endif /*********************** * Implement fmax() and fmin() for systems which lack them. Not a strictly * conforming implementation - we don't bother checking for NaN which if * mpeg2enc gets means big trouble I suspect ;) ************************/ #if !defined(HAVE_FMAX) double fmax(double x, double y) { if (x > y) return(x); return(y); } #endif #if !defined(HAVE_FMIN) double fmin(double x, double y) { if (x < y) return(x); return(y); } #endif void *bufalloc( size_t size ) { static size_t simd_alignment = 16; static int bufalloc_init = 0; int pgsize; void *buf = NULL; if( !bufalloc_init ) { #ifdef HAVE_X86CPU if( (cpu_accel() & (ACCEL_X86_SSE|ACCEL_X86_3DNOW)) != 0 ) { simd_alignment = 64; bufalloc_init = 1; } #endif } pgsize = sysconf(_SC_PAGESIZE); /* * If posix_memalign fails it could be a broken glibc that caused the error, * so try again with a page aligned memalign request */ if (posix_memalign( &buf, simd_alignment, size)) buf = memalign(pgsize, size); if (buf && ((size_t)buf & (simd_alignment - 1))) { free(buf); buf = memalign(pgsize, size); } if (buf == NULL) mjpeg_error_exit1("malloc of %d bytes failed", (int)size); if ((size_t)buf & (simd_alignment - 1)) mjpeg_error_exit1("could not allocate %d bytes aligned on a %d byte boundary", (int)size, (int)simd_alignment); return buf; } int disable_simd(char *name) { int foundit; char *cp, *simd_env, *dup_backup; if ((cp = getenv("MJPEGTOOLS_SIMD_DISABLE")) == NULL) return(0); /* * Special case for "all" so that all 22 or whatever names don't have to be * explicitly specified. If "all" is seen as the only name in the environment * variable then always return 1. */ if (strcasecmp(cp, "all") == 0) return(1); /* * First check that the routine being tested for disabled status exists in * the list of known functions. */ foundit = simd_name_ok(name); if (foundit == 0) return(0); /* * Next compare the function name passed as input to the comma separated * names in the environment variable. If a match is found then return 1 */ dup_backup = simd_env = strdup(cp); while ((cp = parse_next(&simd_env, ","))) { foundit = 0; if (strcasecmp(cp, name) == 0) { foundit = 1; break; } } free(dup_backup); return(foundit); } int simd_name_ok(char *name) { int foundit = 0; const char **dft; for (dft = disable_simd_flags; *dft; dft++) { if (strcasecmp(name, *dft) == 0) return(1); } return(0); } static char *parse_next(char **sptr, const char *delim) { char *start, *ret; start = ret = *sptr; if ((ret == NULL) || ret == '\0') { return (NULL); } while (*ret != '\0' && strchr(delim, *ret) == NULL) { ret++; } if (*ret == '\0') { *sptr = NULL; } else { *ret = '\0'; ret++; *sptr = ret; } return (start); } mjpegtools-2.1.0/utils/mjpeg_logging.c0000644000175000017500000001235510603772216020337 0ustar glowwormglowworm/* $Id: mjpeg_logging.c,v 1.16 2007/04/01 18:06:06 sms00 Exp $ Copyright (C) 2000 Herbert Valerio Riedel This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include "mjpeg_logging.h" #ifdef HAVE___PROGNAME extern const char *__progname; #endif /* * Put these here and NOT in the exported header file mjpeg_logging.h * * since ALL program use of these should use the API below (mjpeg_warn, * mjpeg_error,etc) these symbols do not need to be exported and possibly * conflict with syslog.h */ #define LOG_DEBUG 1 #define LOG_INFO 2 #define LOG_WARN 3 #define LOG_ERROR 4 static log_level_t mjpeg_log_verbosity = 0; static char *default_handler_id = NULL; static int default_mjpeg_log_filter( log_level_t level ) { int verb_from_env; if( mjpeg_log_verbosity == 0 ) { char *mjpeg_verb_env = getenv("MJPEG_VERBOSITY"); if( mjpeg_verb_env != NULL ) { verb_from_env = LOG_WARN-atoi(mjpeg_verb_env); if( verb_from_env >= LOG_DEBUG && verb_from_env <= LOG_ERROR ) mjpeg_log_verbosity = (log_level_t)verb_from_env; } } return (level < LOG_WARN && level < mjpeg_log_verbosity); } static mjpeg_log_filter_t _filter = default_mjpeg_log_filter; static void default_mjpeg_log_handler(log_level_t level, const char message[]) { const char *ids; if( (*_filter)( level ) ) return; if (default_handler_id != NULL) { ids = default_handler_id; } else { #ifdef HAVE___PROGNAME ids = __progname; #else ids = "???"; #endif } switch(level) { case LOG_ERROR: fprintf(stderr, "**ERROR: [%s] %s\n", ids, message); break; case LOG_DEBUG: fprintf(stderr, "--DEBUG: [%s] %s\n", ids, message); break; case LOG_WARN: fprintf(stderr, "++ WARN: [%s] %s\n", ids, message); break; case LOG_INFO: fprintf(stderr, " INFO: [%s] %s\n", ids, message); break; default: assert(0); } } static mjpeg_log_handler_t _handler = default_mjpeg_log_handler; mjpeg_log_handler_t mjpeg_log_set_handler(mjpeg_log_handler_t new_handler) { mjpeg_log_handler_t old_handler = _handler; _handler = new_handler; return old_handler; } /*************** * Set default log handlers degree of verboseity. * 0 = quiet, 1 = info, 2 = debug *************/ int mjpeg_default_handler_verbosity(int verbosity) { int prev_verb = mjpeg_log_verbosity; mjpeg_log_verbosity = (log_level_t)(LOG_WARN - verbosity); return prev_verb; } /* * Set identifier string used by default handler */ int mjpeg_default_handler_identifier(const char *new_id) { const char *s; if (new_id == NULL) { if (default_handler_id != NULL) free(default_handler_id); default_handler_id = NULL; return 0; } /* find basename of new_id (remove any directory prefix) */ if ((s = strrchr(new_id, '/')) == NULL) s = new_id; else s = s + 1; default_handler_id = strdup(s); return 0; } static void mjpeg_logv(log_level_t level, const char format[], va_list args) { char buf[1024] = { 0, }; /* TODO: Original had a re-entrancy error trap to assist bug finding. To make this work with multi-threaded applications a lock is needed hence delete. */ vsnprintf(buf, sizeof(buf)-1, format, args); _handler(level, buf); } void mjpeg_log(log_level_t level, const char format[], ...) { va_list args; va_start (args, format); mjpeg_logv(level, format, args); va_end (args); } void mjpeg_debug(const char format[], ...) { va_list args; va_start (args, format); mjpeg_logv(LOG_DEBUG, format, args); va_end (args); } void mjpeg_info(const char format[], ...) { va_list args; va_start (args, format); mjpeg_logv(LOG_INFO, format, args); va_end (args); } void mjpeg_warn(const char format[], ...) { va_list args; va_start (args, format); mjpeg_logv(LOG_WARN, format, args); va_end (args); } void mjpeg_error(const char format[], ...) { va_list args; va_start (args, format); mjpeg_logv(LOG_ERROR, format, args); va_end (args); } void mjpeg_error_exit1(const char format[], ...) { va_list args; va_start( args, format ); mjpeg_logv( LOG_ERROR, format, args); va_end(args); exit(EXIT_FAILURE); } log_level_t mjpeg_loglev_t(const char *level) { if (strcasecmp("debug", level) == 0) return(LOG_DEBUG); else if (strcasecmp("info", level) == 0) return(LOG_INFO); else if (strcasecmp("warn", level) == 0) return(LOG_WARN); else if (strcasecmp("error", level) == 0) return(LOG_ERROR); return(0); } mjpegtools-2.1.0/utils/Makefile.in0000644000175000017500000006534512217306407017435 0ustar glowwormglowworm# Makefile.in generated by automake 1.12.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Process this file with Automake to produce Makefile.in VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = utils DIST_COMMON = $(noinst_HEADERS) $(pkginclude_HEADERS) \ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgincludedir)" LTLIBRARIES = $(lib_LTLIBRARIES) libmjpegutils_la_DEPENDENCIES = $(mmxsse_lib) $(altivec_lib) am_libmjpegutils_la_OBJECTS = mjpeg_logging.lo mpegconsts.lo \ mpegtimecode.lo yuv4mpeg.lo yuv4mpeg_ratio.lo motionsearch.lo \ cpu_accel.lo libmjpegutils_la_OBJECTS = $(am_libmjpegutils_la_OBJECTS) libmjpegutils_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libmjpegutils_la_LDFLAGS) $(LDFLAGS) -o $@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libmjpegutils_la_SOURCES) DIST_SOURCES = $(libmjpegutils_la_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) $(pkginclude_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ distdir ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALTIVEC_EXTRA_LIBS = @ALTIVEC_EXTRA_LIBS@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDV_CFLAGS = @LIBDV_CFLAGS@ LIBDV_LIBS = @LIBDV_LIBS@ LIBGETOPT_LIB = @LIBGETOPT_LIB@ LIBM_LIBS = @LIBM_LIBS@ LIBOBJS = @LIBOBJS@ LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ LIBPNG_LIBS = @LIBPNG_LIBS@ LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@ LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ LT_STATIC = @LT_STATIC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROGRAM_NOPIC = @PROGRAM_NOPIC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ SDLgfx_LIBS = @SDLgfx_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ V4LCONF_LIBS = @V4LCONF_LIBS@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @HAVE_ALTIVEC_TRUE@SUBDIRS = altivec @HAVE_ASM_MMX_TRUE@SUBDIRS = mmxsse DIST_SUBDIRS = altivec mmxsse EXTRA_DIST = cpuinfo.c INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/utils lib_LTLIBRARIES = libmjpegutils.la @HAVE_ALTIVEC_TRUE@altivec_lib = $(top_builddir)/utils/altivec/libaltivec.la @HAVE_ASM_MMX_TRUE@mmxsse_lib = $(top_builddir)/utils/mmxsse/libmmxsse.la libmjpegutils_la_LIBADD = $(mmxsse_lib) $(altivec_lib) libmjpegutils_la_LDFLAGS = \ $(LT_STATIC) \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -release $(LT_RELEASE) $(EXTRA_LDFLAGS) libmjpegutils_la_SOURCES = \ mjpeg_logging.c \ mpegconsts.c \ mpegtimecode.c \ yuv4mpeg.c \ yuv4mpeg_ratio.c \ motionsearch.c \ cpu_accel.c noinst_HEADERS = \ cpu_accel.h \ fastintfns.h \ mmx.h \ videodev_mjpeg.h \ yuv4mpeg_intern.h pkginclude_HEADERS = \ format_codes.h \ mjpeg_logging.h \ mjpeg_types.h \ mpegconsts.h \ mpegtimecode.h \ motionsearch.h \ yuv4mpeg.h MAINTAINERCLEANFILES = Makefile.in all: all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu utils/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu utils/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libmjpegutils.la: $(libmjpegutils_la_OBJECTS) $(libmjpegutils_la_DEPENDENCIES) $(EXTRA_libmjpegutils_la_DEPENDENCIES) $(libmjpegutils_la_LINK) -rpath $(libdir) $(libmjpegutils_la_OBJECTS) $(libmjpegutils_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu_accel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mjpeg_logging.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/motionsearch.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpegconsts.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpegtimecode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuv4mpeg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuv4mpeg_ratio.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgincludeHEADERS: $(pkginclude_HEADERS) @$(NORMAL_INSTALL) @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \ done uninstall-pkgincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(RECURSIVE_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done cscopelist-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-recursive clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-pkgincludeHEADERS install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-libLTLIBRARIES uninstall-pkgincludeHEADERS .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) \ cscopelist-recursive ctags-recursive install-am install-strip \ tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool cscopelist \ cscopelist-recursive ctags ctags-recursive distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-man install-pdf install-pdf-am \ install-pkgincludeHEADERS install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ uninstall uninstall-am uninstall-libLTLIBRARIES \ uninstall-pkgincludeHEADERS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mjpegtools-2.1.0/utils/yuv4mpeg.c0000644000175000017500000011555010371737015017310 0ustar glowwormglowworm/* * yuv4mpeg.c: Functions for reading and writing "new" YUV4MPEG streams * * Copyright (C) 2001 Matthew J. Marjanovic * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include #include #include #define INTERNAL_Y4M_LIBCODE_STUFF_QPX #include "yuv4mpeg.h" #include "yuv4mpeg_intern.h" #include "mjpeg_logging.h" static int _y4mparam_allow_unknown_tags = 1; /* default is forgiveness */ static int _y4mparam_feature_level = 0; /* default is ol YUV4MPEG2 */ static void *(*_y4m_alloc)(size_t bytes) = malloc; static void (*_y4m_free)(void *ptr) = free; int y4m_allow_unknown_tags(int yn) { int old = _y4mparam_allow_unknown_tags; if (yn >= 0) _y4mparam_allow_unknown_tags = (yn) ? 1 : 0; return old; } int y4m_accept_extensions(int level) { int old = _y4mparam_feature_level; if (level >= 0) _y4mparam_feature_level = level; return old; } /************************************************************************* * * Convenience functions for fd read/write * * - guaranteed to transfer entire payload (or fail) * - returns: * 0 on complete success * +(# of remaining bytes) on eof (for y4m_read) * -(# of rem. bytes) on error (and ERRNO should be set) * *************************************************************************/ ssize_t y4m_read(int fd, void *buf, size_t len) { ssize_t n; uint8_t *ptr = (uint8_t *)buf; while (len > 0) { n = read(fd, ptr, len); if (n <= 0) { /* return amount left to read */ if (n == 0) return len; /* n == 0 --> eof */ else return -len; /* n < 0 --> error */ } ptr += n; len -= n; } return 0; } ssize_t y4m_write(int fd, const void *buf, size_t len) { ssize_t n; const uint8_t *ptr = (const uint8_t *)buf; while (len > 0) { n = write(fd, ptr, len); if (n <= 0) return -len; /* return amount left to write */ ptr += n; len -= n; } return 0; } /* read len bytes from fd into buf */ ssize_t y4m_read_cb(y4m_cb_reader_t * fd, void *buf, size_t len) { return fd->read(fd->data, buf, len); } /* write len bytes from fd into buf */ ssize_t y4m_write_cb(y4m_cb_writer_t * fd, const void *buf, size_t len) { return fd->write(fd->data, buf, len); } /* Functions to use the callback interface from plain filedescriptors */ /* read len bytes from fd into buf */ ssize_t y4m_read_fd(void * data, void *buf, size_t len) { int * f = (int*)data; return y4m_read(*f, buf, len); } /* write len bytes from fd into buf */ ssize_t y4m_write_fd(void * data, const void *buf, size_t len) { int * f = (int*)data; return y4m_write(*f, buf, len); } static void set_cb_reader_from_fd(y4m_cb_reader_t * ret, int * fd) { ret->read = y4m_read_fd; ret->data = fd; } static void set_cb_writer_from_fd(y4m_cb_writer_t * ret, int * fd) { ret->write = y4m_write_fd; ret->data = fd; } /************************************************************************* * * "Extra tags" handling * *************************************************************************/ static char *y4m_new_xtag(void) { return _y4m_alloc(Y4M_MAX_XTAG_SIZE * sizeof(char)); } void y4m_init_xtag_list(y4m_xtag_list_t *xtags) { int i; xtags->count = 0; for (i = 0; i < Y4M_MAX_XTAGS; i++) { xtags->tags[i] = NULL; } } void y4m_fini_xtag_list(y4m_xtag_list_t *xtags) { int i; for (i = 0; i < Y4M_MAX_XTAGS; i++) { if (xtags->tags[i] != NULL) { _y4m_free(xtags->tags[i]); xtags->tags[i] = NULL; } } xtags->count = 0; } void y4m_copy_xtag_list(y4m_xtag_list_t *dest, const y4m_xtag_list_t *src) { int i; for (i = 0; i < src->count; i++) { if (dest->tags[i] == NULL) dest->tags[i] = y4m_new_xtag(); strncpy(dest->tags[i], src->tags[i], Y4M_MAX_XTAG_SIZE); } dest->count = src->count; } static int y4m_snprint_xtags(char *s, int maxn, const y4m_xtag_list_t *xtags) { int i, room; for (i = 0, room = maxn - 1; i < xtags->count; i++) { int n = snprintf(s, room + 1, " %s", xtags->tags[i]); if ((n < 0) || (n > room)) return Y4M_ERR_HEADER; s += n; room -= n; } s[0] = '\n'; /* finish off header with newline */ s[1] = '\0'; /* ...and end-of-string */ return Y4M_OK; } int y4m_xtag_count(const y4m_xtag_list_t *xtags) { return xtags->count; } const char *y4m_xtag_get(const y4m_xtag_list_t *xtags, int n) { if (n >= xtags->count) return NULL; else return xtags->tags[n]; } int y4m_xtag_add(y4m_xtag_list_t *xtags, const char *tag) { if (xtags->count >= Y4M_MAX_XTAGS) return Y4M_ERR_XXTAGS; if (xtags->tags[xtags->count] == NULL) xtags->tags[xtags->count] = y4m_new_xtag(); strncpy(xtags->tags[xtags->count], tag, Y4M_MAX_XTAG_SIZE); (xtags->count)++; return Y4M_OK; } int y4m_xtag_remove(y4m_xtag_list_t *xtags, int n) { int i; char *q; if ((n < 0) || (n >= xtags->count)) return Y4M_ERR_RANGE; q = xtags->tags[n]; for (i = n; i < (xtags->count - 1); i++) xtags->tags[i] = xtags->tags[i+1]; xtags->tags[i] = q; (xtags->count)--; return Y4M_OK; } int y4m_xtag_clearlist(y4m_xtag_list_t *xtags) { xtags->count = 0; return Y4M_OK; } int y4m_xtag_addlist(y4m_xtag_list_t *dest, const y4m_xtag_list_t *src) { int i, j; if ((dest->count + src->count) > Y4M_MAX_XTAGS) return Y4M_ERR_XXTAGS; for (i = dest->count, j = 0; j < src->count; i++, j++) { if (dest->tags[i] == NULL) dest->tags[i] = y4m_new_xtag(); strncpy(dest->tags[i], src->tags[i], Y4M_MAX_XTAG_SIZE); } dest->count += src->count; return Y4M_OK; } /************************************************************************* * * Creators/destructors for y4m_*_info_t structures * *************************************************************************/ void y4m_init_stream_info(y4m_stream_info_t *info) { if (info == NULL) return; /* init substructures */ y4m_init_xtag_list(&(info->x_tags)); /* set defaults */ y4m_clear_stream_info(info); } void y4m_clear_stream_info(y4m_stream_info_t *info) { if (info == NULL) return; /* clear/initialize info */ info->width = Y4M_UNKNOWN; info->height = Y4M_UNKNOWN; info->interlace = Y4M_UNKNOWN; info->framerate = y4m_fps_UNKNOWN; info->sampleaspect = y4m_sar_UNKNOWN; if (_y4mparam_feature_level < 1) { info->chroma = Y4M_CHROMA_420JPEG; } else { info->chroma = Y4M_UNKNOWN; } y4m_xtag_clearlist(&(info->x_tags)); } void y4m_copy_stream_info(y4m_stream_info_t *dest, const y4m_stream_info_t *src) { if ((dest == NULL) || (src == NULL)) return; /* copy info */ dest->width = src->width; dest->height = src->height; dest->interlace = src->interlace; dest->framerate = src->framerate; dest->sampleaspect = src->sampleaspect; dest->chroma = src->chroma; y4m_copy_xtag_list(&(dest->x_tags), &(src->x_tags)); } // returns 0 if equal, nonzero if different static int y4m_compare_stream_info(const y4m_stream_info_t *s1,const y4m_stream_info_t *s2) { int i,j; if( s1->width != s2->width || s1->height != s2->height || s1->interlace != s2->interlace || s1->framerate.n != s2->framerate.n || s1->framerate.d != s2->framerate.d || s1->sampleaspect.n != s2->sampleaspect.n || s1->sampleaspect.d != s2->sampleaspect.d || s1->chroma != s2->chroma || s1->x_tags.count != s2->x_tags.count ) return 1; // the tags may not be in the same order for( i=0; ix_tags.count; i++ ) { for( j=0; jx_tags.count; j++ ) if( !strncmp(s1->x_tags.tags[i],s2->x_tags.tags[j],Y4M_MAX_XTAG_SIZE) ) goto next; return 1; next:; } return 0; } void y4m_fini_stream_info(y4m_stream_info_t *info) { if (info == NULL) return; y4m_fini_xtag_list(&(info->x_tags)); } void y4m_si_set_width(y4m_stream_info_t *si, int width) { si->width = width; } int y4m_si_get_width(const y4m_stream_info_t *si) { return si->width; } void y4m_si_set_height(y4m_stream_info_t *si, int height) { si->height = height; } int y4m_si_get_height(const y4m_stream_info_t *si) { return si->height; } void y4m_si_set_interlace(y4m_stream_info_t *si, int interlace) { si->interlace = interlace; } int y4m_si_get_interlace(const y4m_stream_info_t *si) { return si->interlace; } void y4m_si_set_framerate(y4m_stream_info_t *si, y4m_ratio_t framerate) { si->framerate = framerate; } y4m_ratio_t y4m_si_get_framerate(const y4m_stream_info_t *si) { return si->framerate; } void y4m_si_set_sampleaspect(y4m_stream_info_t *si, y4m_ratio_t sar) { si->sampleaspect = sar; } y4m_ratio_t y4m_si_get_sampleaspect(const y4m_stream_info_t *si) { return si->sampleaspect; } void y4m_si_set_chroma(y4m_stream_info_t *si, int chroma_mode) { si->chroma = chroma_mode; } int y4m_si_get_chroma(const y4m_stream_info_t *si) { return si->chroma; } int y4m_si_get_plane_count(const y4m_stream_info_t *si) { switch (si->chroma) { case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: case Y4M_CHROMA_444: case Y4M_CHROMA_422: case Y4M_CHROMA_411: return 3; case Y4M_CHROMA_MONO: return 1; case Y4M_CHROMA_444ALPHA: return 4; default: return Y4M_UNKNOWN; } } int y4m_si_get_plane_width(const y4m_stream_info_t *si, int plane) { switch (plane) { case 0: return (si->width); case 1: case 2: switch (si->chroma) { case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: return (si->width) / 2; case Y4M_CHROMA_444: case Y4M_CHROMA_444ALPHA: return (si->width); case Y4M_CHROMA_422: return (si->width) / 2; case Y4M_CHROMA_411: return (si->width) / 4; default: return Y4M_UNKNOWN; } case 3: switch (si->chroma) { case Y4M_CHROMA_444ALPHA: return (si->width); default: return Y4M_UNKNOWN; } default: return Y4M_UNKNOWN; } } int y4m_si_get_plane_height(const y4m_stream_info_t *si, int plane) { switch (plane) { case 0: return (si->height); case 1: case 2: switch (si->chroma) { case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: return (si->height) / 2; case Y4M_CHROMA_444: case Y4M_CHROMA_444ALPHA: case Y4M_CHROMA_422: case Y4M_CHROMA_411: return (si->height); default: return Y4M_UNKNOWN; } case 3: switch (si->chroma) { case Y4M_CHROMA_444ALPHA: return (si->height); default: return Y4M_UNKNOWN; } default: return Y4M_UNKNOWN; } } int y4m_si_get_plane_length(const y4m_stream_info_t *si, int plane) { int w = y4m_si_get_plane_width(si, plane); int h = y4m_si_get_plane_height(si, plane); if ((w != Y4M_UNKNOWN) && (h != Y4M_UNKNOWN)) return (w * h); else return Y4M_UNKNOWN; } int y4m_si_get_framelength(const y4m_stream_info_t *si) { int total = 0; int planes = y4m_si_get_plane_count(si); int p; for (p = 0; p < planes; p++) { int plen = y4m_si_get_plane_length(si, p); if (plen == Y4M_UNKNOWN) return Y4M_UNKNOWN; total += plen; } return total; } y4m_xtag_list_t *y4m_si_xtags(y4m_stream_info_t *si) { return &(si->x_tags); } void y4m_init_frame_info(y4m_frame_info_t *info) { if (info == NULL) return; /* init substructures */ y4m_init_xtag_list(&(info->x_tags)); /* set defaults */ y4m_clear_frame_info(info); } void y4m_clear_frame_info(y4m_frame_info_t *info) { if (info == NULL) return; /* clear/initialize info */ info->spatial = Y4M_UNKNOWN; info->temporal = Y4M_UNKNOWN; info->presentation = Y4M_UNKNOWN; y4m_xtag_clearlist(&(info->x_tags)); } void y4m_copy_frame_info(y4m_frame_info_t *dest, const y4m_frame_info_t *src) { if ((dest == NULL) || (src == NULL)) return; /* copy info */ dest->spatial = src->spatial; dest->temporal = src->temporal; dest->presentation = src->presentation; y4m_copy_xtag_list(&(dest->x_tags), &(src->x_tags)); } void y4m_fini_frame_info(y4m_frame_info_t *info) { if (info == NULL) return; y4m_fini_xtag_list(&(info->x_tags)); } void y4m_fi_set_presentation(y4m_frame_info_t *fi, int pres) { fi->presentation = pres; } int y4m_fi_get_presentation(const y4m_frame_info_t *fi) { return fi->presentation; } void y4m_fi_set_temporal(y4m_frame_info_t *fi, int sampling) { fi->temporal = sampling; } int y4m_fi_get_temporal(const y4m_frame_info_t *fi) { return fi->temporal; } void y4m_fi_set_spatial(y4m_frame_info_t *fi, int sampling) { fi->spatial = sampling; } int y4m_fi_get_spatial(const y4m_frame_info_t *fi) { return fi->spatial; } y4m_xtag_list_t *y4m_fi_xtags(y4m_frame_info_t *fi) { return &(fi->x_tags); } /************************************************************************* * * Tag parsing * *************************************************************************/ int y4m_parse_stream_tags(char *s, y4m_stream_info_t *i) { char *token, *value; char tag; int err; /* parse fields */ for (token = strtok(s, Y4M_DELIM); token != NULL; token = strtok(NULL, Y4M_DELIM)) { if (token[0] == '\0') continue; /* skip empty strings */ tag = token[0]; value = token + 1; switch (tag) { case 'W': /* width */ i->width = atoi(value); if (i->width <= 0) return Y4M_ERR_RANGE; break; case 'H': /* height */ i->height = atoi(value); if (i->height <= 0) return Y4M_ERR_RANGE; break; case 'F': /* frame rate (fps) */ if ((err = y4m_parse_ratio(&(i->framerate), value)) != Y4M_OK) return err; if (i->framerate.n < 0) return Y4M_ERR_RANGE; break; case 'I': /* interlacing */ switch (value[0]) { case 'p': i->interlace = Y4M_ILACE_NONE; break; case 't': i->interlace = Y4M_ILACE_TOP_FIRST; break; case 'b': i->interlace = Y4M_ILACE_BOTTOM_FIRST; break; case 'm': i->interlace = Y4M_ILACE_MIXED; break; case '?': default: i->interlace = Y4M_UNKNOWN; break; } break; case 'A': /* sample (pixel) aspect ratio */ if ((err = y4m_parse_ratio(&(i->sampleaspect), value)) != Y4M_OK) return err; if (i->sampleaspect.n < 0) return Y4M_ERR_RANGE; break; case 'C': i->chroma = y4m_chroma_parse_keyword(value); if (i->chroma == Y4M_UNKNOWN) return Y4M_ERR_HEADER; break; case 'X': /* 'X' meta-tag */ if ((err = y4m_xtag_add(&(i->x_tags), token)) != Y4M_OK) return err; break; default: /* possible error on unknown options */ if (_y4mparam_allow_unknown_tags) { /* unknown tags ok: store in xtag list and warn... */ if ((err = y4m_xtag_add(&(i->x_tags), token)) != Y4M_OK) return err; mjpeg_warn("Unknown stream tag encountered: '%s'", token); } else { /* unknown tags are *not* ok */ return Y4M_ERR_BADTAG; } break; } } /* Without 'C' tag or any other chroma spec, default to 420jpeg */ if (i->chroma == Y4M_UNKNOWN) i->chroma = Y4M_CHROMA_420JPEG; /* Error checking... */ /* - Width and Height are required. */ if ((i->width == Y4M_UNKNOWN) || (i->height == Y4M_UNKNOWN)) return Y4M_ERR_HEADER; /* - Non-420 chroma and mixed interlace require level >= 1 */ if (_y4mparam_feature_level < 1) { if ((i->chroma != Y4M_CHROMA_420JPEG) && (i->chroma != Y4M_CHROMA_420MPEG2) && (i->chroma != Y4M_CHROMA_420PALDV)) return Y4M_ERR_FEATURE; if (i->interlace == Y4M_ILACE_MIXED) return Y4M_ERR_FEATURE; } /* ta da! done. */ return Y4M_OK; } static int y4m_parse_frame_tags(char *s, const y4m_stream_info_t *si, y4m_frame_info_t *fi) { char *token, *value; char tag; int err; /* parse fields */ for (token = strtok(s, Y4M_DELIM); token != NULL; token = strtok(NULL, Y4M_DELIM)) { if (token[0] == '\0') continue; /* skip empty strings */ tag = token[0]; value = token + 1; switch (tag) { case 'I': /* frame 'I' tag requires feature level >= 1 */ if (_y4mparam_feature_level < 1) return Y4M_ERR_FEATURE; if (si->interlace != Y4M_ILACE_MIXED) return Y4M_ERR_BADTAG; switch (value[0]) { case 't': fi->presentation = Y4M_PRESENT_TOP_FIRST; break; case 'T': fi->presentation = Y4M_PRESENT_TOP_FIRST_RPT; break; case 'b': fi->presentation = Y4M_PRESENT_BOTTOM_FIRST; break; case 'B': fi->presentation = Y4M_PRESENT_BOTTOM_FIRST_RPT; break; case '1': fi->presentation = Y4M_PRESENT_PROG_SINGLE; break; case '2': fi->presentation = Y4M_PRESENT_PROG_DOUBLE; break; case '3': fi->presentation = Y4M_PRESENT_PROG_TRIPLE; break; default: return Y4M_ERR_BADTAG; } switch (value[1]) { case 'p': fi->temporal = Y4M_SAMPLING_PROGRESSIVE; break; case 'i': fi->temporal = Y4M_SAMPLING_INTERLACED; break; default: return Y4M_ERR_BADTAG; } switch (value[2]) { case 'p': fi->spatial = Y4M_SAMPLING_PROGRESSIVE; break; case 'i': fi->spatial = Y4M_SAMPLING_INTERLACED; break; case '?': fi->spatial = Y4M_UNKNOWN; break; default: return Y4M_ERR_BADTAG; } break; case 'X': /* 'X' meta-tag */ if ((err = y4m_xtag_add(&(fi->x_tags), token)) != Y4M_OK) return err; break; default: /* possible error on unknown options */ if (_y4mparam_allow_unknown_tags) { /* unknown tags ok: store in xtag list and warn... */ if ((err = y4m_xtag_add(&(fi->x_tags), token)) != Y4M_OK) return err; mjpeg_warn("Unknown frame tag encountered: '%s'", token); } else { /* unknown tags are *not* ok */ return Y4M_ERR_BADTAG; } break; } } /* error-checking and/or non-mixed defaults */ switch (si->interlace) { case Y4M_ILACE_MIXED: /* T and P are required if stream "Im" */ if ((fi->presentation == Y4M_UNKNOWN) || (fi->temporal == Y4M_UNKNOWN)) return Y4M_ERR_HEADER; /* and S is required if stream is also 4:2:0 */ if ( ((si->chroma == Y4M_CHROMA_420JPEG) || (si->chroma == Y4M_CHROMA_420MPEG2) || (si->chroma == Y4M_CHROMA_420PALDV)) && (fi->spatial == Y4M_UNKNOWN) ) return Y4M_ERR_HEADER; break; case Y4M_ILACE_NONE: /* stream "Ip" --> equivalent to frame "I1pp" */ fi->spatial = Y4M_SAMPLING_PROGRESSIVE; fi->temporal = Y4M_SAMPLING_PROGRESSIVE; fi->presentation = Y4M_PRESENT_PROG_SINGLE; break; case Y4M_ILACE_TOP_FIRST: /* stream "It" --> equivalent to frame "Itii" */ fi->spatial = Y4M_SAMPLING_INTERLACED; fi->temporal = Y4M_SAMPLING_INTERLACED; fi->presentation = Y4M_PRESENT_TOP_FIRST; break; case Y4M_ILACE_BOTTOM_FIRST: /* stream "Ib" --> equivalent to frame "Ibii" */ fi->spatial = Y4M_SAMPLING_INTERLACED; fi->temporal = Y4M_SAMPLING_INTERLACED; fi->presentation = Y4M_PRESENT_BOTTOM_FIRST; break; default: /* stream unknown: then, whatever */ break; } /* ta da! done. */ return Y4M_OK; } /************************************************************************* * * Read/Write stream header * *************************************************************************/ static int y4m_read_stream_header_line_cb(y4m_cb_reader_t * fd, y4m_stream_info_t *i,char *line,int n) { int err; /* start with a clean slate */ y4m_clear_stream_info(i); /* read the header line */ for (; n < Y4M_LINE_MAX; n++) { if (y4m_read_cb(fd, line+n, 1)) return Y4M_ERR_SYSTEM; if (line[n] == '\n') { line[n] = '\0'; /* Replace linefeed by end of string */ break; } } /* look for keyword in header */ if (strncmp(line, Y4M_MAGIC, strlen(Y4M_MAGIC))) return Y4M_ERR_MAGIC; if (n >= Y4M_LINE_MAX) return Y4M_ERR_HEADER; if ((err = y4m_parse_stream_tags(line + strlen(Y4M_MAGIC), i)) != Y4M_OK) return err; return Y4M_OK; } static int y4m_reread_stream_header_line_cb(y4m_cb_reader_t *fd,const y4m_stream_info_t *si,char *line,int n) { y4m_stream_info_t i; int err=y4m_read_stream_header_line_cb(fd,&i,line,n); if( err==Y4M_OK && y4m_compare_stream_info(si,&i) ) err=Y4M_ERR_HEADER; y4m_fini_stream_info(&i); return err; } int y4m_read_stream_header_cb(y4m_cb_reader_t *fd, y4m_stream_info_t *i) { char line[Y4M_LINE_MAX]; return y4m_read_stream_header_line_cb(fd,i,line,0); } int y4m_read_stream_header(int fd, y4m_stream_info_t *i) { y4m_cb_reader_t r; set_cb_reader_from_fd(&r, &fd); return y4m_read_stream_header_cb(&r, i); } int y4m_write_stream_header_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *i) { char s[Y4M_LINE_MAX+1]; int n; int err; y4m_ratio_t rate = i->framerate; y4m_ratio_t aspect = i->sampleaspect; const char *chroma_keyword = y4m_chroma_keyword(i->chroma); if ((i->chroma == Y4M_UNKNOWN) || (chroma_keyword == NULL)) return Y4M_ERR_HEADER; if (_y4mparam_feature_level < 1) { if ((i->chroma != Y4M_CHROMA_420JPEG) && (i->chroma != Y4M_CHROMA_420MPEG2) && (i->chroma != Y4M_CHROMA_420PALDV)) return Y4M_ERR_FEATURE; if (i->interlace == Y4M_ILACE_MIXED) return Y4M_ERR_FEATURE; } y4m_ratio_reduce(&rate); y4m_ratio_reduce(&aspect); n = snprintf(s, sizeof(s), "%s W%d H%d F%d:%d I%s A%d:%d C%s", Y4M_MAGIC, i->width, i->height, rate.n, rate.d, (i->interlace == Y4M_ILACE_NONE) ? "p" : (i->interlace == Y4M_ILACE_TOP_FIRST) ? "t" : (i->interlace == Y4M_ILACE_BOTTOM_FIRST) ? "b" : (i->interlace == Y4M_ILACE_MIXED) ? "m" : "?", aspect.n, aspect.d, chroma_keyword ); if ((n < 0) || (n > Y4M_LINE_MAX)) return Y4M_ERR_HEADER; if ((err = y4m_snprint_xtags(s + n, sizeof(s) - n - 1, &(i->x_tags))) != Y4M_OK) return err; /* non-zero on error */ return (y4m_write_cb(fd, s, strlen(s)) ? Y4M_ERR_SYSTEM : Y4M_OK); } int y4m_write_stream_header(int fd, const y4m_stream_info_t *i) { y4m_cb_writer_t w; set_cb_writer_from_fd(&w, &fd); return y4m_write_stream_header_cb(&w, i); } /************************************************************************* * * Read/Write frame header * *************************************************************************/ int y4m_read_frame_header_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi) { char line[Y4M_LINE_MAX]; char *p; int n; ssize_t remain; again: /* start with a clean slate */ y4m_clear_frame_info(fi); /* This is more clever than read_stream_header... Try to read "FRAME\n" all at once, and don't try to parse if nothing else is there... */ remain = y4m_read_cb(fd, line, sizeof(Y4M_FRAME_MAGIC)-1+1); /* -'\0', +'\n' */ if (remain < 0) return Y4M_ERR_SYSTEM; if (remain > 0) { /* A clean EOF should end exactly at a frame-boundary */ if (remain == sizeof(Y4M_FRAME_MAGIC)) return Y4M_ERR_EOF; else return Y4M_ERR_BADEOF; } if (strncmp(line, Y4M_FRAME_MAGIC, sizeof(Y4M_FRAME_MAGIC)-1)) { int err=y4m_reread_stream_header_line_cb(fd,si,line,sizeof(Y4M_FRAME_MAGIC)-1+1); if( err!=Y4M_OK ) return err; goto again; } if (line[sizeof(Y4M_FRAME_MAGIC)-1] == '\n') return Y4M_OK; /* done -- no tags: that was the end-of-line. */ if (line[sizeof(Y4M_FRAME_MAGIC)-1] != Y4M_DELIM[0]) { return Y4M_ERR_MAGIC; /* wasn't a space -- what was it? */ } /* proceed to get the tags... (overwrite the magic) */ for (n = 0, p = line; n < Y4M_LINE_MAX; n++, p++) { if (y4m_read_cb(fd, p, 1)) return Y4M_ERR_SYSTEM; if (*p == '\n') { *p = '\0'; /* Replace linefeed by end of string */ break; } } if (n >= Y4M_LINE_MAX) return Y4M_ERR_HEADER; /* non-zero on error */ return y4m_parse_frame_tags(line, si, fi); } int y4m_read_frame_header(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi) { y4m_cb_reader_t r; set_cb_reader_from_fd(&r, &fd); return y4m_read_frame_header_cb(&r, si, fi); } int y4m_write_frame_header_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *si, const y4m_frame_info_t *fi) { char s[Y4M_LINE_MAX+1]; int n, err; if (si->interlace == Y4M_ILACE_MIXED) { if (_y4mparam_feature_level < 1) return Y4M_ERR_FEATURE; n = snprintf(s, sizeof(s), "%s I%c%c%c", Y4M_FRAME_MAGIC, (fi->presentation == Y4M_PRESENT_TOP_FIRST) ? 't' : (fi->presentation == Y4M_PRESENT_TOP_FIRST_RPT) ? 'T' : (fi->presentation == Y4M_PRESENT_BOTTOM_FIRST) ? 'b' : (fi->presentation == Y4M_PRESENT_BOTTOM_FIRST_RPT) ? 'B' : (fi->presentation == Y4M_PRESENT_PROG_SINGLE) ? '1' : (fi->presentation == Y4M_PRESENT_PROG_DOUBLE) ? '2' : (fi->presentation == Y4M_PRESENT_PROG_TRIPLE) ? '3' : '?', (fi->temporal == Y4M_SAMPLING_PROGRESSIVE) ? 'p' : (fi->temporal == Y4M_SAMPLING_INTERLACED) ? 'i' : '?', (fi->spatial == Y4M_SAMPLING_PROGRESSIVE) ? 'p' : (fi->spatial == Y4M_SAMPLING_INTERLACED) ? 'i' : '?' ); } else { n = snprintf(s, sizeof(s), "%s", Y4M_FRAME_MAGIC); } if ((n < 0) || (n > Y4M_LINE_MAX)) return Y4M_ERR_HEADER; if ((err = y4m_snprint_xtags(s + n, sizeof(s) - n - 1, &(fi->x_tags))) != Y4M_OK) return err; /* non-zero on error */ return (y4m_write_cb(fd, s, strlen(s)) ? Y4M_ERR_SYSTEM : Y4M_OK); } int y4m_write_frame_header(int fd, const y4m_stream_info_t *si, const y4m_frame_info_t *fi) { y4m_cb_writer_t w; set_cb_writer_from_fd(&w, &fd); return y4m_write_frame_header_cb(&w, si, fi); } /************************************************************************* * * Read/Write entire frame * *************************************************************************/ int y4m_read_frame_data_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *frame) { int planes = y4m_si_get_plane_count(si); int p; /* Read each plane */ for (p = 0; p < planes; p++) { int w = y4m_si_get_plane_width(si, p); int h = y4m_si_get_plane_height(si, p); if (y4m_read_cb(fd, frame[p], w*h)) return Y4M_ERR_SYSTEM; } return Y4M_OK; } int y4m_read_frame_data(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *frame) { y4m_cb_reader_t r; set_cb_reader_from_fd(&r, &fd); return y4m_read_frame_data_cb(&r, si, fi, frame); } int y4m_read_frame_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *frame) { int err; /* Read frame header */ if ((err = y4m_read_frame_header_cb(fd, si, fi)) != Y4M_OK) return err; /* Read date */ return y4m_read_frame_data_cb(fd, si, fi, frame); } int y4m_read_frame(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *frame) { y4m_cb_reader_t r; set_cb_reader_from_fd(&r, &fd); return y4m_read_frame_cb(&r, si, fi, frame); } int y4m_write_frame_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *si, const y4m_frame_info_t *fi, uint8_t * const *frame) { int planes = y4m_si_get_plane_count(si); int err, p; /* Write frame header */ if ((err = y4m_write_frame_header_cb(fd, si, fi)) != Y4M_OK) return err; /* Write each plane */ for (p = 0; p < planes; p++) { int w = y4m_si_get_plane_width(si, p); int h = y4m_si_get_plane_height(si, p); if (y4m_write_cb(fd, frame[p], w*h)) return Y4M_ERR_SYSTEM; } return Y4M_OK; } int y4m_write_frame(int fd, const y4m_stream_info_t *si, const y4m_frame_info_t *fi, uint8_t * const *frame) { y4m_cb_writer_t w; set_cb_writer_from_fd(&w, &fd); return y4m_write_frame_cb(&w, si, fi, frame); } /************************************************************************* * * Read/Write entire frame, (de)interleaved (to)from two separate fields * *************************************************************************/ int y4m_read_fields_data_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *upper_field, uint8_t * const *lower_field) { int p; int planes = y4m_si_get_plane_count(si); const int maxrbuf=32*1024; uint8_t *rbuf=_y4m_alloc(maxrbuf); int rbufpos=0,rbuflen=0; /* Read each plane */ for (p = 0; p < planes; p++) { uint8_t *dsttop = upper_field[p]; uint8_t *dstbot = lower_field[p]; int height = y4m_si_get_plane_height(si, p); int width = y4m_si_get_plane_width(si, p); int y; /* alternately read one line into each field */ for (y = 0; y < height; y += 2) { if( width*2 >= maxrbuf ) { if (y4m_read_cb(fd, dsttop, width)) goto y4merr; if (y4m_read_cb(fd, dstbot, width)) goto y4merr; } else { if( rbufpos==rbuflen ) { rbuflen=(height-y)*width; if( rbuflen>maxrbuf ) rbuflen=maxrbuf-maxrbuf%(2*width); if( y4m_read_cb(fd,rbuf,rbuflen) ) goto y4merr; rbufpos=0; } memcpy(dsttop,rbuf+rbufpos,width); rbufpos+=width; memcpy(dstbot,rbuf+rbufpos,width); rbufpos+=width; } dsttop+=width; dstbot+=width; } } _y4m_free(rbuf); return Y4M_OK; y4merr: _y4m_free(rbuf); return Y4M_ERR_SYSTEM; } int y4m_read_fields_data(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *upper_field, uint8_t * const *lower_field) { y4m_cb_reader_t r; set_cb_reader_from_fd(&r, &fd); return y4m_read_fields_data_cb(&r, si, fi, upper_field, lower_field); } int y4m_read_fields_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *upper_field, uint8_t * const *lower_field) { int err; /* Read frame header */ if ((err = y4m_read_frame_header_cb(fd, si, fi)) != Y4M_OK) return err; /* Read data */ return y4m_read_fields_data_cb(fd, si, fi, upper_field, lower_field); } int y4m_read_fields(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *upper_field, uint8_t * const *lower_field) { y4m_cb_reader_t r; set_cb_reader_from_fd(&r, &fd); return y4m_read_fields_cb(&r, si, fi, upper_field, lower_field); } int y4m_write_fields_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *si, const y4m_frame_info_t *fi, uint8_t * const *upper_field, uint8_t * const *lower_field) { int p, err; int planes = y4m_si_get_plane_count(si); int numwbuf=0; const int maxwbuf=32*1024; uint8_t *wbuf; /* Write frame header */ if ((err = y4m_write_frame_header_cb(fd, si, fi)) != Y4M_OK) return err; /* Write each plane */ wbuf=_y4m_alloc(maxwbuf); for (p = 0; p < planes; p++) { uint8_t *srctop = upper_field[p]; uint8_t *srcbot = lower_field[p]; int height = y4m_si_get_plane_height(si, p); int width = y4m_si_get_plane_width(si, p); int y; /* alternately write one line from each field */ for (y = 0; y < height; y += 2) { if( width*2 >= maxwbuf ) { if (y4m_write_cb(fd, srctop, width)) goto y4merr; if (y4m_write_cb(fd, srcbot, width)) goto y4merr; } else { if (numwbuf + 2 * width > maxwbuf) { if(y4m_write_cb(fd, wbuf, numwbuf)) goto y4merr; numwbuf=0; } memcpy(wbuf+numwbuf,srctop,width); numwbuf += width; memcpy(wbuf+numwbuf,srcbot,width); numwbuf += width; } srctop += width; srcbot += width; } } if( numwbuf ) if( y4m_write_cb(fd, wbuf, numwbuf) ) goto y4merr; _y4m_free(wbuf); return Y4M_OK; y4merr: _y4m_free(wbuf); return Y4M_ERR_SYSTEM; } int y4m_write_fields(int fd, const y4m_stream_info_t *si, const y4m_frame_info_t *fi, uint8_t * const *upper_field, uint8_t * const *lower_field) { y4m_cb_writer_t w; set_cb_writer_from_fd(&w, &fd); return y4m_write_fields_cb(&w, si, fi, upper_field, lower_field); } /************************************************************************* * * Handy logging of stream info * *************************************************************************/ void y4m_log_stream_info(log_level_t level, const char *prefix, const y4m_stream_info_t *i) { char s[256]; snprintf(s, sizeof(s), " frame size: "); if (i->width == Y4M_UNKNOWN) snprintf(s+strlen(s), sizeof(s)-strlen(s), "(?)x"); else snprintf(s+strlen(s), sizeof(s)-strlen(s), "%dx", i->width); if (i->height == Y4M_UNKNOWN) snprintf(s+strlen(s), sizeof(s)-strlen(s), "(?) pixels "); else snprintf(s+strlen(s), sizeof(s)-strlen(s), "%d pixels ", i->height); { int framelength = y4m_si_get_framelength(i); if (framelength == Y4M_UNKNOWN) snprintf(s+strlen(s), sizeof(s)-strlen(s), "(? bytes)"); else snprintf(s+strlen(s), sizeof(s)-strlen(s), "(%d bytes)", framelength); mjpeg_log(level, "%s%s", prefix, s); } { const char *desc = y4m_chroma_description(i->chroma); if (desc == NULL) desc = "unknown!"; mjpeg_log(level, "%s chroma: %s", prefix, desc); } if ((i->framerate.n == 0) && (i->framerate.d == 0)) mjpeg_log(level, "%s frame rate: ??? fps", prefix); else mjpeg_log(level, "%s frame rate: %d/%d fps (~%f)", prefix, i->framerate.n, i->framerate.d, (double) i->framerate.n / (double) i->framerate.d); mjpeg_log(level, "%s interlace: %s", prefix, (i->interlace == Y4M_ILACE_NONE) ? "none/progressive" : (i->interlace == Y4M_ILACE_TOP_FIRST) ? "top-field-first" : (i->interlace == Y4M_ILACE_BOTTOM_FIRST) ? "bottom-field-first" : (i->interlace == Y4M_ILACE_MIXED) ? "mixed-mode" : "anyone's guess"); if ((i->sampleaspect.n == 0) && (i->sampleaspect.d == 0)) mjpeg_log(level, "%ssample aspect ratio: ?:?", prefix); else mjpeg_log(level, "%ssample aspect ratio: %d:%d", prefix, i->sampleaspect.n, i->sampleaspect.d); } /************************************************************************* * * Convert error code to string * *************************************************************************/ const char *y4m_strerr(int err) { switch (err) { case Y4M_OK: return "no error"; case Y4M_ERR_RANGE: return "parameter out of range"; case Y4M_ERR_SYSTEM: return "system error (failed read/write)"; case Y4M_ERR_HEADER: return "bad stream or frame header"; case Y4M_ERR_BADTAG: return "unknown header tag"; case Y4M_ERR_MAGIC: return "bad header magic"; case Y4M_ERR_XXTAGS: return "too many xtags"; case Y4M_ERR_EOF: return "end-of-file"; case Y4M_ERR_BADEOF: return "stream ended unexpectedly (EOF)"; case Y4M_ERR_FEATURE: return "stream requires unsupported features"; default: return "unknown error code"; } } /************************************************************************* * * Chroma subsampling stuff * *************************************************************************/ y4m_ratio_t y4m_chroma_ss_x_ratio(int chroma_mode) { y4m_ratio_t r; switch (chroma_mode) { case Y4M_CHROMA_444ALPHA: case Y4M_CHROMA_444: case Y4M_CHROMA_MONO: r.n = 1; r.d = 1; break; case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: case Y4M_CHROMA_422: r.n = 1; r.d = 2; break; case Y4M_CHROMA_411: r.n = 1; r.d = 4; break; default: r.n = 0; r.d = 0; } return r; } y4m_ratio_t y4m_chroma_ss_y_ratio(int chroma_mode) { y4m_ratio_t r; switch (chroma_mode) { case Y4M_CHROMA_444ALPHA: case Y4M_CHROMA_444: case Y4M_CHROMA_MONO: case Y4M_CHROMA_422: case Y4M_CHROMA_411: r.n = 1; r.d = 1; break; case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: r.n = 1; r.d = 2; break; default: r.n = 0; r.d = 0; } return r; } #if 0 /* unfinished work here */ y4m_ratio_t y4m_chroma_ss_x_offset(int chroma_mode, int field, int plane) { y4m_ratio_t r; switch (chroma_mode) { case Y4M_CHROMA_444ALPHA: case Y4M_CHROMA_444: case Y4M_CHROMA_MONO: case Y4M_CHROMA_422: case Y4M_CHROMA_411: r.n = 0; r.d = 1; break; case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: r.n = 1; r.d = 2; break; default: r.n = 0; r.d = 0; } return r; } y4m_ratio_t y4m_chroma_ss_y_offset(int chroma_mode, int field, int plane); { y4m_ratio_t r; switch (chroma_mode) { case Y4M_CHROMA_444ALPHA: case Y4M_CHROMA_444: case Y4M_CHROMA_MONO: case Y4M_CHROMA_422: case Y4M_CHROMA_411: r.n = 0; r.d = 1; break; case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: r.n = 1; r.d = 2; break; default: r.n = 0; r.d = 0; } return r; } #endif int y4m_chroma_parse_keyword(const char *s) { if (!strcasecmp("420jpeg", s)) return Y4M_CHROMA_420JPEG; else if (!strcasecmp("420mpeg2", s)) return Y4M_CHROMA_420MPEG2; else if (!strcasecmp("420paldv", s)) return Y4M_CHROMA_420PALDV; else if (!strcasecmp("444", s)) return Y4M_CHROMA_444; else if (!strcasecmp("422", s)) return Y4M_CHROMA_422; else if (!strcasecmp("411", s)) return Y4M_CHROMA_411; else if (!strcasecmp("mono", s)) return Y4M_CHROMA_MONO; else if (!strcasecmp("444alpha", s)) return Y4M_CHROMA_444ALPHA; else return Y4M_UNKNOWN; } const char *y4m_chroma_keyword(int chroma_mode) { switch (chroma_mode) { case Y4M_CHROMA_420JPEG: return "420jpeg"; case Y4M_CHROMA_420MPEG2: return "420mpeg2"; case Y4M_CHROMA_420PALDV: return "420paldv"; case Y4M_CHROMA_444: return "444"; case Y4M_CHROMA_422: return "422"; case Y4M_CHROMA_411: return "411"; case Y4M_CHROMA_MONO: return "mono"; case Y4M_CHROMA_444ALPHA: return "444alpha"; default: return NULL; } } const char *y4m_chroma_description(int chroma_mode) { switch (chroma_mode) { case Y4M_CHROMA_420JPEG: return "4:2:0 JPEG/MPEG-1 (interstitial)"; case Y4M_CHROMA_420MPEG2: return "4:2:0 MPEG-2 (horiz. cositing)"; case Y4M_CHROMA_420PALDV: return "4:2:0 PAL-DV (altern. siting)"; case Y4M_CHROMA_444: return "4:4:4 (no subsampling)"; case Y4M_CHROMA_422: return "4:2:2 (horiz. cositing)"; case Y4M_CHROMA_411: return "4:1:1 (horiz. cositing)"; case Y4M_CHROMA_MONO: return "luma plane only"; case Y4M_CHROMA_444ALPHA: return "4:4:4 with alpha channel"; default: return NULL; } } mjpegtools-2.1.0/utils/mmx.h0000644000175000017500000003040710314351424016324 0ustar glowwormglowworm/* * mmx.h * Copyright (C) 1997-1999 H. Dietz and R. Fisher * * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. * * mpeg2dec is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * mpeg2dec is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define ATTR_ALIGN(align) __attribute__ ((__aligned__ (align))) /* * The type of an value that fits in an MMX register (note that long * long constant values MUST be suffixed by LL and unsigned long long * values by ULL, lest they be truncated by the compiler) */ typedef union { int64_t q; /* Quadword (64-bit) value */ uint64_t uq; /* Unsigned Quadword */ int32_t d[2]; /* 2 Doubleword (32-bit) values */ uint32_t ud[2]; /* 2 Unsigned Doubleword */ int16_t w[4]; /* 4 Word (16-bit) values */ uint16_t uw[4]; /* 4 Unsigned Word */ int8_t b[8]; /* 8 Byte (8-bit) values */ uint8_t ub[8]; /* 8 Unsigned Byte */ float s[2]; /* Single-precision (32-bit) value */ } ATTR_ALIGN(8) mmx_t; /* On an 8-byte (64-bit) boundary */ #define mmx_si2r(op,imm,reg) \ __asm__ __volatile__ (#op " %0, %%" #reg \ : /* nothing */ \ : "J" (imm) ) #define mmx_m2r(op,mem,reg) \ __asm__ __volatile__ (#op " %0, %%" #reg \ : /* nothing */ \ : "m" (mem)) #define mmx_r2m(op,reg,mem) \ __asm__ __volatile__ (#op " %%" #reg ", %0" \ : "=m" (mem) \ : /* nothing */ ) #define mmx_g2r(op,mem,reg) \ __asm__ __volatile__ (#op " %0, %%" #reg \ : /* nothing */ \ : "rm" (mem)) #define mmx_r2g(op,reg,mem) \ __asm__ __volatile__ (#op " %%" #reg ", %0" \ : "=rm" (mem) \ : /* nothing */ ) #define mmx_r2r(op,regs,regd) \ __asm__ __volatile__ (#op " %" #regs ", %" #regd) #define emms() __asm__ __volatile__ ("emms") #define femms() __asm__ __volatile__ ("femms") #define movd_m2r(var,reg) mmx_m2r (movd, var, reg) #define movd_r2m(reg,var) mmx_r2m (movd, reg, var) #define movd_g2r(var,reg) mmx_g2r (movd, var, reg) #define movd_r2g(reg,var) mmx_r2g (movd, reg, var) #define movd_r2r(regs,regd) mmx_r2r (movd, regs, regd) #define movq_m2r(var,reg) mmx_m2r (movq, var, reg) #define movq_r2m(reg,var) mmx_r2m (movq, reg, var) #define movq_r2r(regs,regd) mmx_r2r (movq, regs, regd) #define packssdw_m2r(var,reg) mmx_m2r (packssdw, var, reg) #define packssdw_r2r(regs,regd) mmx_r2r (packssdw, regs, regd) #define packsswb_m2r(var,reg) mmx_m2r (packsswb, var, reg) #define packsswb_r2r(regs,regd) mmx_r2r (packsswb, regs, regd) #define packuswb_m2r(var,reg) mmx_m2r (packuswb, var, reg) #define packuswb_r2r(regs,regd) mmx_r2r (packuswb, regs, regd) #define paddb_m2r(var,reg) mmx_m2r (paddb, var, reg) #define paddb_r2r(regs,regd) mmx_r2r (paddb, regs, regd) #define paddd_m2r(var,reg) mmx_m2r (paddd, var, reg) #define paddd_r2r(regs,regd) mmx_r2r (paddd, regs, regd) #define paddw_m2r(var,reg) mmx_m2r (paddw, var, reg) #define paddw_r2r(regs,regd) mmx_r2r (paddw, regs, regd) #define paddsb_m2r(var,reg) mmx_m2r (paddsb, var, reg) #define paddsb_r2r(regs,regd) mmx_r2r (paddsb, regs, regd) #define paddsw_m2r(var,reg) mmx_m2r (paddsw, var, reg) #define paddsw_r2r(regs,regd) mmx_r2r (paddsw, regs, regd) #define paddusb_m2r(var,reg) mmx_m2r (paddusb, var, reg) #define paddusb_r2r(regs,regd) mmx_r2r (paddusb, regs, regd) #define paddusw_m2r(var,reg) mmx_m2r (paddusw, var, reg) #define paddusw_r2r(regs,regd) mmx_r2r (paddusw, regs, regd) #define pand_m2r(var,reg) mmx_m2r (pand, var, reg) #define pand_r2r(regs,regd) mmx_r2r (pand, regs, regd) #define pandn_m2r(var,reg) mmx_m2r (pandn, var, reg) #define pandn_r2r(regs,regd) mmx_r2r (pandn, regs, regd) #define pcmpeqb_m2r(var,reg) mmx_m2r (pcmpeqb, var, reg) #define pcmpeqb_r2r(regs,regd) mmx_r2r (pcmpeqb, regs, regd) #define pcmpeqd_m2r(var,reg) mmx_m2r (pcmpeqd, var, reg) #define pcmpeqd_r2r(regs,regd) mmx_r2r (pcmpeqd, regs, regd) #define pcmpeqw_m2r(var,reg) mmx_m2r (pcmpeqw, var, reg) #define pcmpeqw_r2r(regs,regd) mmx_r2r (pcmpeqw, regs, regd) #define pcmpgtb_m2r(var,reg) mmx_m2r (pcmpgtb, var, reg) #define pcmpgtb_r2r(regs,regd) mmx_r2r (pcmpgtb, regs, regd) #define pcmpgtd_m2r(var,reg) mmx_m2r (pcmpgtd, var, reg) #define pcmpgtd_r2r(regs,regd) mmx_r2r (pcmpgtd, regs, regd) #define pcmpgtw_m2r(var,reg) mmx_m2r (pcmpgtw, var, reg) #define pcmpgtw_r2r(regs,regd) mmx_r2r (pcmpgtw, regs, regd) #define pmaddwd_m2r(var,reg) mmx_m2r (pmaddwd, var, reg) #define pmaddwd_r2r(regs,regd) mmx_r2r (pmaddwd, regs, regd) #define pmulhw_m2r(var,reg) mmx_m2r (pmulhw, var, reg) #define pmulhw_r2r(regs,regd) mmx_r2r (pmulhw, regs, regd) #define pmullw_m2r(var,reg) mmx_m2r (pmullw, var, reg) #define pmullw_r2r(regs,regd) mmx_r2r (pmullw, regs, regd) #define por_m2r(var,reg) mmx_m2r (por, var, reg) #define por_r2r(regs,regd) mmx_r2r (por, regs, regd) #define pslld_i2r(imm,reg) mmx_si2r (pslld, imm, reg) #define pslld_m2r(var,reg) mmx_m2r (pslld, var, reg) #define pslld_r2r(regs,regd) mmx_r2r (pslld, regs, regd) #define psllq_i2r(imm,reg) mmx_si2r (psllq, imm, reg) #define psllq_m2r(var,reg) mmx_m2r (psllq, var, reg) #define psllq_r2r(regs,regd) mmx_r2r (psllq, regs, regd) #define psllw_i2r(imm,reg) mmx_si2r (psllw, imm, reg) #define psllw_m2r(var,reg) mmx_m2r (psllw, var, reg) #define psllw_r2r(regs,regd) mmx_r2r (psllw, regs, regd) #define psrad_i2r(imm,reg) mmx_si2r (psrad, imm, reg) #define psrad_m2r(var,reg) mmx_m2r (psrad, var, reg) #define psrad_r2r(regs,regd) mmx_r2r (psrad, regs, regd) #define psraw_i2r(imm,reg) mmx_si2r (psraw, imm, reg) #define psraw_m2r(var,reg) mmx_m2r (psraw, var, reg) #define psraw_r2r(regs,regd) mmx_r2r (psraw, regs, regd) #define psrld_i2r(imm,reg) mmx_si2r (psrld, imm, reg) #define psrld_m2r(var,reg) mmx_m2r (psrld, var, reg) #define psrld_r2r(regs,regd) mmx_r2r (psrld, regs, regd) #define psrlq_i2r(imm,reg) mmx_si2r (psrlq, imm, reg) #define psrlq_m2r(var,reg) mmx_m2r (psrlq, var, reg) #define psrlq_r2r(regs,regd) mmx_r2r (psrlq, regs, regd) #define psrlw_i2r(imm,reg) mmx_si2r (psrlw, imm, reg) #define psrlw_m2r(var,reg) mmx_m2r (psrlw, var, reg) #define psrlw_r2r(regs,regd) mmx_r2r (psrlw, regs, regd) #define psubb_m2r(var,reg) mmx_m2r (psubb, var, reg) #define psubb_r2r(regs,regd) mmx_r2r (psubb, regs, regd) #define psubd_m2r(var,reg) mmx_m2r (psubd, var, reg) #define psubd_r2r(regs,regd) mmx_r2r (psubd, regs, regd) #define psubw_m2r(var,reg) mmx_m2r (psubw, var, reg) #define psubw_r2r(regs,regd) mmx_r2r (psubw, regs, regd) #define psubsb_m2r(var,reg) mmx_m2r (psubsb, var, reg) #define psubsb_r2r(regs,regd) mmx_r2r (psubsb, regs, regd) #define psubsw_m2r(var,reg) mmx_m2r (psubsw, var, reg) #define psubsw_r2r(regs,regd) mmx_r2r (psubsw, regs, regd) #define psubusb_m2r(var,reg) mmx_m2r (psubusb, var, reg) #define psubusb_r2r(regs,regd) mmx_r2r (psubusb, regs, regd) #define psubusw_m2r(var,reg) mmx_m2r (psubusw, var, reg) #define psubusw_r2r(regs,regd) mmx_r2r (psubusw, regs, regd) #define punpckhbw_m2r(var,reg) mmx_m2r (punpckhbw, var, reg) #define punpckhbw_r2r(regs,regd) mmx_r2r (punpckhbw, regs, regd) #define punpckhdq_m2r(var,reg) mmx_m2r (punpckhdq, var, reg) #define punpckhdq_r2r(regs,regd) mmx_r2r (punpckhdq, regs, regd) #define punpckhwd_m2r(var,reg) mmx_m2r (punpckhwd, var, reg) #define punpckhwd_r2r(regs,regd) mmx_r2r (punpckhwd, regs, regd) #define punpcklbw_m2r(var,reg) mmx_m2r (punpcklbw, var, reg) #define punpcklbw_r2r(regs,regd) mmx_r2r (punpcklbw, regs, regd) #define punpckldq_m2r(var,reg) mmx_m2r (punpckldq, var, reg) #define punpckldq_r2r(regs,regd) mmx_r2r (punpckldq, regs, regd) #define punpcklwd_m2r(var,reg) mmx_m2r (punpcklwd, var, reg) #define punpcklwd_r2r(regs,regd) mmx_r2r (punpcklwd, regs, regd) #define pxor_m2r(var, reg) mmx_m2r (pxor, var, reg) #define pxor_r2r(regs, regd) mmx_r2r (pxor, regs, regd) /* AMD MMX extensions - also available in intel SSE */ #define mmx_m2ri(op,mem,reg,imm) \ __asm__ __volatile__ (#op " %1, %0, %%" #reg \ : /* nothing */ \ : "m" (mem), "i" (imm)) #define mmx_r2ri(op,regs,regd,imm) \ __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \ : /* nothing */ \ : "i" (imm) ) #define mmx_fetch(mem,hint) \ __asm__ __volatile__ ("prefetch" #hint " %0" \ : /* nothing */ \ : "m" (mem)) /* 3DNow goodies */ #define pfmul_m2r(var,reg) mmx_m2r( pfmul, var, reg ) #define pfmul_r2r(regs,regd) mmx_r2r( pfmul, regs, regd ) #define pfadd_m2r(var,reg) mmx_m2r( pfadd, var, reg ) #define pfadd_r2r(regs,regd) mmx_r2r( pfadd, regs, regd ) #define pf2id_r2r(regs,regd) mmx_r2r( pf2id, regs, regd ) #define pi2fd_r2r(regs,regd) mmx_r2r( pi2fd, regs, regd ) /* SSE goodies */ #define addps_m2r( var, regd) mmx_m2r( addps, var, regd ) #define addps_r2r( regs, regd) mmx_r2r( addps, regs, regd ) #define subps_r2r( regs, regd) mmx_r2r( subps, regs, regd ) #define minps_r2r( regs, regd) mmx_r2r( minps, regs, regd ) #define maxps_r2r( regs, regd) mmx_r2r( maxps, regs, regd ) #define mulps_r2r( regs, regd) mmx_r2r( mulps, regs, regd ) #define mulps_m2r( var, regd) mmx_m2r( mulps, var, regd ) #define movups_r2r(reg1, reg2) mmx_r2r( movups, reg1, reg2 ) #define movups_m2r(var, reg) mmx_m2r( movups, var, reg ) #define movaps_m2r(var, reg) mmx_m2r( movaps, var, reg ) #define movaps_r2r(reg1, reg2) mmx_r2r( movaps, reg1, reg2 ) #define movlps_m2r(var, reg) mmx_m2r( movlps, var, reg ) #define movlps_r2m(reg, var) mmx_r2m( movlps, reg, var ) #define movlhps_m2r(var, reg) mmx_m2r( movlhps, var, reg ) #define movlhps_r2r(reg1, reg2) mmx_r2r( movlhps, reg1, reg2 ) #define movhlps_r2r(reg1, reg2) mmx_r2r( movhlps, reg1, reg2 ) #define movups_r2m(reg, var) mmx_r2m( movups, reg, var ) #define movaps_r2m(reg, var) mmx_r2m( movaps, reg, var ) #define movss_r2m(reg, var) mmx_r2m( movss, reg, var ) #define cvttps2pi_r2r(regs,regd) mmx_r2r( cvttps2pi, regs, regd ) #define cvtps2pi_r2r(regs,regd) mmx_r2r( cvtps2pi, regs, regd ) #define cvtpi2ps_r2r(regs,regd) mmx_r2r( cvtpi2ps, regs, regd ) #define shufps_r2ri(regs, regd, imm) mmx_r2ri( shufps, regs, regd, imm ) #define unpcklps_r2r(reg1, reg2) mmx_r2r( unpcklps, reg1, reg2 ) #define unpckhps_r2r(reg1, reg2) mmx_r2r( unpckhps, reg1, reg2 ) #define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg) #define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var) #define pavgb_m2r(var,reg) mmx_m2r (pavgb, var, reg) #define pavgb_r2r(regs,regd) mmx_r2r (pavgb, regs, regd) #define pavgw_m2r(var,reg) mmx_m2r (pavgw, var, reg) #define pavgw_r2r(regs,regd) mmx_r2r (pavgw, regs, regd) #define pextrw_r2r(mmreg,reg,imm) mmx_r2ri (pextrw, mmreg, reg, imm) #define pinsrw_r2r(reg,mmreg,imm) mmx_r2ri (pinsrw, reg, mmreg, imm) #define pmaxsw_m2r(var,reg) mmx_m2r (pmaxsw, var, reg) #define pmaxsw_r2r(regs,regd) mmx_r2r (pmaxsw, regs, regd) #define pmaxub_m2r(var,reg) mmx_m2r (pmaxub, var, reg) #define pmaxub_r2r(regs,regd) mmx_r2r (pmaxub, regs, regd) #define pminsw_m2r(var,reg) mmx_m2r (pminsw, var, reg) #define pminsw_r2r(regs,regd) mmx_r2r (pminsw, regs, regd) #define pminub_m2r(var,reg) mmx_m2r (pminub, var, reg) #define pminub_r2r(regs,regd) mmx_r2r (pminub, regs, regd) #define pmovmskb(mmreg,reg) \ __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg) #define pmulhuw_m2r(var,reg) mmx_m2r (pmulhuw, var, reg) #define pmulhuw_r2r(regs,regd) mmx_r2r (pmulhuw, regs, regd) #define prefetcht0(mem) mmx_fetch (mem, t0) #define prefetcht1(mem) mmx_fetch (mem, t1) #define prefetcht2(mem) mmx_fetch (mem, t2) #define prefetchnta(mem) mmx_fetch (mem, nta) #define psadbw_m2r(var,reg) mmx_m2r (psadbw, var, reg) #define psadbw_r2r(regs,regd) mmx_r2r (psadbw, regs, regd) #define pshufw_m2ri(var,reg,imm) mmx_m2ri( pshufw, var, reg, imm) #define pshufw_r2ri(regs,regd,imm) mmx_r2ri( pshufw, regs, regd, imm) #define sfence() __asm__ __volatile__ ("sfence\n\t") mjpegtools-2.1.0/utils/cpuinfo.c0000644000175000017500000002437611114425001017161 0ustar glowwormglowworm/* small utility to extract CPU information Used by configure to set CPU optimization levels on some operating systems where /proc/cpuinfo is non-existent or unreliable. */ #include #include #include #include #include #if defined(__MINGW32__) && (__MINGW32_MAJOR_VERSION <= 3) && (__MINGW32_MINOR_VERSION < 10) #include void gettimeofday(struct timeval* t,void* timezone) { struct timeb timebuffer; ftime( &timebuffer ); t->tv_sec=timebuffer.time; t->tv_usec=1000*timebuffer.millitm; } #endif #ifdef __MINGW32__ #define MISSING_USLEEP #include #define sleep(t) Sleep(1000*t); #endif #ifdef __BEOS__ #define usleep(t) snooze(t) #endif #ifdef M_UNIX typedef long long int64_t; #define MISSING_USLEEP #else #include #endif #define CPUID_FEATURE_DEF(bit, desc, description) \ { bit, desc } typedef struct cpuid_regs { unsigned int eax; unsigned int ebx; unsigned int ecx; unsigned int edx; } cpuid_regs_t; static cpuid_regs_t cpuid(int func) { cpuid_regs_t regs; #define CPUID ".byte 0x0f, 0xa2; " #ifdef __x86_64__ asm("mov %%rbx, %%rsi\n\t" #else asm("mov %%ebx, %%esi\n\t" #endif CPUID"\n\t" #ifdef __x86_64__ "xchg %%rsi, %%rbx\n\t" #else "xchg %%esi, %%ebx\n\t" #endif : "=a" (regs.eax), "=S" (regs.ebx), "=c" (regs.ecx), "=d" (regs.edx) : "0" (func)); return regs; } static int64_t rdtsc(void) { uint64_t i; #define RDTSC ".byte 0x0f, 0x31; " asm volatile (RDTSC : "=A"(i) : ); return i; } static const char* brandname(int i) { const static char* brandmap[] = { NULL, "Intel(R) Celeron(R) processor", "Intel(R) Pentium(R) III processor", "Intel(R) Pentium(R) III Xeon(tm) processor", "Intel(R) Pentium(R) III processor", NULL, "Mobile Intel(R) Pentium(R) III processor-M", "Mobile Intel(R) Celeron(R) processor" }; if (i >= sizeof(brandmap)) return NULL; else return brandmap[i]; } static void store32(char *d, unsigned int v) { d[0] = v & 0xff; d[1] = (v >> 8) & 0xff; d[2] = (v >> 16) & 0xff; d[3] = (v >> 24) & 0xff; } int main(int argc, char **argv) { cpuid_regs_t regs, regs_ext; char idstr[13]; unsigned max_cpuid; unsigned max_ext_cpuid; unsigned int amd_flags; unsigned int amd_flags2; const char *model_name = NULL; int i; char processor_name[49]; regs = cpuid(0); max_cpuid = regs.eax; /* printf("%d CPUID function codes\n", max_cpuid+1); */ store32(idstr+0, regs.ebx); store32(idstr+4, regs.edx); store32(idstr+8, regs.ecx); idstr[12] = 0; printf("vendor_id\t: %s\n", idstr); regs_ext = cpuid((1<<31) + 0); max_ext_cpuid = regs_ext.eax; if (max_ext_cpuid >= (1<<31) + 1) { regs_ext = cpuid((1<<31) + 1); amd_flags = regs_ext.edx; amd_flags2 = regs_ext.ecx; if (max_ext_cpuid >= (1<<31) + 4) { for (i = 2; i <= 4; i++) { regs_ext = cpuid((1<<31) + i); store32(processor_name + (i-2)*16, regs_ext.eax); store32(processor_name + (i-2)*16 + 4, regs_ext.ebx); store32(processor_name + (i-2)*16 + 8, regs_ext.ecx); store32(processor_name + (i-2)*16 + 12, regs_ext.edx); } processor_name[48] = 0; model_name = processor_name; while (*model_name == ' ') { model_name++; } } } else { amd_flags = 0; amd_flags2 = 0; } if (max_cpuid >= 1) { static struct { int bit; char *desc; } cap[] = { CPUID_FEATURE_DEF(0, "fpu", "Floating-point unit on-chip"), CPUID_FEATURE_DEF(1, "vme", "Virtual Mode Enhancements"), CPUID_FEATURE_DEF(2, "de", "Debugging Extension"), CPUID_FEATURE_DEF(3, "pse", "Page Size Extension"), CPUID_FEATURE_DEF(4, "tsc", "Time Stamp Counter"), CPUID_FEATURE_DEF(5, "msr", "Pentium Processor MSR"), CPUID_FEATURE_DEF(6, "pae", "Physical Address Extension"), CPUID_FEATURE_DEF(7, "mce", "Machine Check Exception"), CPUID_FEATURE_DEF(8, "cx8", "CMPXCHG8B Instruction Supported"), CPUID_FEATURE_DEF(9, "apic", "On-chip APIC Hardware Enabled"), CPUID_FEATURE_DEF(11, "sep", "SYSENTER and SYSEXIT"), CPUID_FEATURE_DEF(12, "mtrr", "Memory Type Range Registers"), CPUID_FEATURE_DEF(13, "pge", "PTE Global Bit"), CPUID_FEATURE_DEF(14, "mca", "Machine Check Architecture"), CPUID_FEATURE_DEF(15, "cmov", "Conditional Move/Compare Instruction"), CPUID_FEATURE_DEF(16, "pat", "Page Attribute Table"), CPUID_FEATURE_DEF(17, "pse36", "Page Size Extension 36-bit"), CPUID_FEATURE_DEF(18, "pn", "Processor Serial Number"), CPUID_FEATURE_DEF(19, "clflush", "CFLUSH instruction"), CPUID_FEATURE_DEF(21, "dts", "Debug Store"), CPUID_FEATURE_DEF(22, "acpi", "Thermal Monitor and Clock Ctrl"), CPUID_FEATURE_DEF(23, "mmx", "MMX Technology"), CPUID_FEATURE_DEF(24, "fxsr", "FXSAVE/FXRSTOR"), CPUID_FEATURE_DEF(25, "sse", "SSE Extensions"), CPUID_FEATURE_DEF(26, "sse2", "SSE2 Extensions"), CPUID_FEATURE_DEF(27, "ss", "Self Snoop"), CPUID_FEATURE_DEF(28, "ht", "Multi-threading"), CPUID_FEATURE_DEF(29, "tm", "Therm. Monitor"), CPUID_FEATURE_DEF(30, "ia64", "IA-64 Processor"), CPUID_FEATURE_DEF(31, "pbe", "Pend. Brk. EN."), { -1 } }; static struct { int bit; char *desc; } cap2[] = { CPUID_FEATURE_DEF(0, "pni", "SSE3 Extensions"), CPUID_FEATURE_DEF(3, "monitor", "MONITOR/MWAIT"), CPUID_FEATURE_DEF(4, "ds_cpl", "CPL Qualified Debug Store"), CPUID_FEATURE_DEF(5, "vmx", "Virtual Machine Extensions"), CPUID_FEATURE_DEF(6, "smx", "Safer Mode Extensions"), CPUID_FEATURE_DEF(7, "est", "Enhanced Intel SpeedStep Technology"), CPUID_FEATURE_DEF(8, "tm2", "Thermal Monitor 2"), CPUID_FEATURE_DEF(9, "ssse3", "Supplemental SSE3"), CPUID_FEATURE_DEF(10, "cid", "L1 Context ID"), CPUID_FEATURE_DEF(13, "cx16", "CMPXCHG16B Available"), CPUID_FEATURE_DEF(14, "xtpr", "xTPR Disable"), CPUID_FEATURE_DEF(15, "pdcm", "Perf/Debug Capability MSR"), CPUID_FEATURE_DEF(18, "dca", "Direct Cache Access"), CPUID_FEATURE_DEF(19, "sse41", "SSE4.1 Extensions"), CPUID_FEATURE_DEF(20, "sse42", "SSE4.2 Extensions"), CPUID_FEATURE_DEF(23, "popcnt", "Pop Count Instruction"), { -1 } }; static struct { int bit; char *desc; } cap_amd[] = { CPUID_FEATURE_DEF(11, "syscall", "SYSCALL and SYSRET"), CPUID_FEATURE_DEF(19, "mp", "MP Capable"), CPUID_FEATURE_DEF(20, "nx", "No-Execute Page Protection"), CPUID_FEATURE_DEF(22, "mmxext", "MMX Technology (AMD Extensions)"), CPUID_FEATURE_DEF(25, "fxsr_opt", "Fast FXSAVE/FXRSTOR"), CPUID_FEATURE_DEF(26, "pdpe1gb", "PDP Entry for 1GiB Page"), CPUID_FEATURE_DEF(27, "rdtscp", "RDTSCP Instruction"), CPUID_FEATURE_DEF(29, "lm", "Long Mode Capable"), CPUID_FEATURE_DEF(30, "3dnowext", "3DNow! Extensions"), CPUID_FEATURE_DEF(31, "3dnow", "3DNow!"), { -1 } }; static struct { int bit; char *desc; } cap_amd2[] = { CPUID_FEATURE_DEF(0, "lahf_lm", "LAHF/SAHF Supported in 64-bit Mode"), CPUID_FEATURE_DEF(1, "cmp_legacy", "Chip Multi-Core"), CPUID_FEATURE_DEF(2, "svm", "Secure Virtual Machine"), CPUID_FEATURE_DEF(3, "extapic", "Extended APIC Space"), CPUID_FEATURE_DEF(4, "cr8legacy", "CR8 Available in Legacy Mode"), CPUID_FEATURE_DEF(5, "abm", "Advanced Bit Manipulation"), CPUID_FEATURE_DEF(6, "sse4a", "SSE4A Extensions"), CPUID_FEATURE_DEF(7, "misalignsse", "Misaligned SSE Mode"), CPUID_FEATURE_DEF(8, "3dnowprefetch", "3DNow! Prefetch/PrefetchW"), CPUID_FEATURE_DEF(9, "osvw", "OS Visible Workaround"), CPUID_FEATURE_DEF(10, "ibs", "Instruction Based Sampling"), { -1 } }; unsigned int family, model, stepping; regs = cpuid(1); family = (regs.eax >> 8) & 0xf; model = (regs.eax >> 4) & 0xf; stepping = regs.eax & 0xf; if (family == 0xf) family += (regs.eax >> 20) & 0xff; if (family == 0xf || family == 6) model += ((regs.eax >> 16) & 0xf) << 4; printf("cpu family\t: %d\n" "model\t\t: %d\n" "stepping\t: %d\n" , family, model, stepping); if (strstr(idstr, "Intel") && !model_name) { if (family == 6 && model == 0xb && stepping == 1) model_name = "Intel (R) Celeron (R) processor"; else model_name = brandname(regs.ebx & 0xf); } printf("flags\t\t:"); for (i = 0; cap[i].bit >= 0; i++) { if (regs.edx & (1 << cap[i].bit)) { printf(" %s", cap[i].desc); } } for (i = 0; cap2[i].bit >= 0; i++) { if (regs.ecx & (1 << cap2[i].bit)) { printf(" %s", cap2[i].desc); } } /* k6_mtrr is supported by some AMD K6-2/K6-III CPUs but it is not indicated by a CPUID feature bit, so we have to check the family, model and stepping instead. */ if (strstr(idstr, "AMD") && family == 5 && (model >= 9 || model == 8 && stepping >= 8)) printf(" %s", "k6_mtrr"); /* similar for cyrix_arr. */ if (strstr(idstr, "Cyrix") && (family == 5 && model < 4 || family == 6)) printf(" %s", "cyrix_arr"); /* as well as centaur_mcr. */ if (strstr(idstr, "Centaur") && family == 5) printf(" %s", "centaur_mcr"); for (i = 0; cap_amd[i].bit >= 0; i++) { if (amd_flags & (1 << cap_amd[i].bit)) { printf(" %s", cap_amd[i].desc); } } for (i = 0; cap_amd2[i].bit >= 0; i++) { if (amd_flags2 & (1 << cap_amd2[i].bit)) { printf(" %s", cap_amd2[i].desc); } } printf("\n"); if (regs.edx & (1 << 4)) { int64_t tsc_start, tsc_end; struct timeval tv_start, tv_end; int usec_delay; tsc_start = rdtsc(); gettimeofday(&tv_start, NULL); #ifdef MISSING_USLEEP sleep(1); #else usleep(100000); #endif tsc_end = rdtsc(); gettimeofday(&tv_end, NULL); usec_delay = 1000000 * (tv_end.tv_sec - tv_start.tv_sec) + (tv_end.tv_usec - tv_start.tv_usec); printf("cpu MHz\t\t: %.3f\n", (double)(tsc_end-tsc_start) / usec_delay); } } printf("model name\t: "); if (model_name) printf("%s\n", model_name); else printf("Unknown %s CPU\n", idstr); } mjpegtools-2.1.0/utils/motionsearch.h0000644000175000017500000001047010622255563020225 0ustar glowwormglowworm/* (C) 2000/2001 Andrew Stevens */ /* This software is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #ifndef __MOTIONSEARCH_H__ #define __MOTIONSEARCH_H__ #include struct me_result { uint16_t weight; int8_t x; int8_t y; }; typedef struct me_result me_result_s; #define MAX_MATCHES (256*256/4) typedef struct _me_result_vec { int len; me_result_s mests[MAX_MATCHES]; } me_result_set; /* * Function pointers for selecting CPU specific implementations * Top-level motion estimation entry points. */ /* * Use given set of 2*2 sub-sampled motion estimates generated using * pbuild_sub22_mests to generate a best 1-pel motion estimate. */ extern void (*pfind_best_one_pel)(me_result_set *sub22set, uint8_t *org, uint8_t *blk, int i0, int j0, int ihigh, int jhigh, int rowstride, int h, me_result_s *res); /* * Use given set of 4*4 sub-sampled motion estimates generated using * pbuild_sub44_mests to generate a set of best 2*2 sub-sampled motion estimates */ extern int (*pbuild_sub22_mests)(me_result_set *sub44set, me_result_set *sub22set, int i0, int j0, int ihigh, int jhigh, int null_mc_sad, uint8_t *s22org, uint8_t *s22blk, int frowstride, int fh, int reduction); /* * Generate a set the best 4*4 sub-sampled motion estimates * from the specifed rectangle of candidates in s44org with respect * to the reference block s44blk */ extern int (*pbuild_sub44_mests)(me_result_set *sub44set, int ilow, int jlow, int ihigh, int jhigh, int i0, int j0, int null_mc_sad, uint8_t *s44org, uint8_t *s44blk, int qrowstride, int qh, int reduction); /* * Lower level difference comparison routines * * Naming convention: for block difference metric functions * sad - Sum Absolute difference * sumsq - Sum of squares * sub44 - 4*4 Subsampled macroblocks (i.e. 4x4 subsampled pels) * sub22 2*2 submsapled macroblocks (i.e. 8x8 subsampled pels) * Ordinary macroblocks (i.e. 16x16 pels) * "b" prefix: Difference of bi-directionally interpolated block * (i.e. mean of two blocks) * _xy suffix: Difference with half-pel sub-sampling offset. * (i.e. _00 is just ordinary no sub-sampling) * mests - Motion estimate results relative motion vector with sad. */ extern int (*psumsq_sub22)(uint8_t *blk1, uint8_t *blk2, int rowstride, int h); extern int (*pbsumsq_sub22)(uint8_t *blk1f, uint8_t *blk1b, uint8_t *blk2, int rowstride, int h); extern void (*pvariance)(uint8_t *mb, int size, int rowstride, uint32_t *p_variance, uint32_t *p_mean); extern int (*psad_sub22)(uint8_t *blk1, uint8_t *blk2, int frowstride, int fh); extern int (*psad_sub44)(uint8_t *blk1, uint8_t *blk2, int qrowstride, int qh); extern int (*psad_00)(uint8_t *blk1, uint8_t *blk2, int rowstride, int h, int distlim); extern int (*psad_01)(uint8_t *blk1, uint8_t *blk2, int rowstride, int h); extern int (*psad_10)(uint8_t *blk1, uint8_t *blk2, int rowstride, int h); extern int (*psad_11)(uint8_t *blk1, uint8_t *blk2, int rowstride, int h); extern int (*psumsq)(uint8_t *blk1, uint8_t *blk2, int rowstride, int hx, int hy, int h); extern int (*pbsumsq) (uint8_t *pf, uint8_t *pb, uint8_t *p2, int rowstride, int hxf, int hyf, int hxb, int hyb, int h); extern int (*pbsad) (uint8_t *pf, uint8_t *pb, uint8_t *p2, int rowstride, int hxf, int hyf, int hxb, int hyb, int h); extern void (*psubsample_image) (uint8_t *image, int rowstride, uint8_t *sub22_image, uint8_t *sub44_image); #ifdef __cplusplus extern "C" { #endif void init_motion_search(void), reset_motion_simd(char *); int round_search_radius( int radius ); #ifdef __cplusplus } #endif #endif /* __MOTIONSEARCH_H__ */ mjpegtools-2.1.0/utils/mpegtimecode.c0000644000175000017500000000743507342745335020204 0ustar glowwormglowworm/* * Copyright (C) 2001 Kawamata/Hitoshi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include "mpegtimecode.h" /************************************************************** * // NTSC DROP FRAME TIMECODE / 29.97fps (SMTPE) * // hh:mm:ss:ff * // hh: 0.. * // mm: 0..59 * // ss: 0..59 * // ff: 0..29 # ss != 0 || mm % 10 == 0 * // 2..29 # ss == 0 && mm % 10 != 0 * // * // 00:00:00:00 00:00:00:01 00:00:00:02 ... 00:00:00:29 * // 00:00:01:00 00:00:01:01 00:00:01:02 ... 00:00:01:29 * // : * // 00:00:59:00 00:00:59:01 00:00:59:02 ... 00:00:59:29 * // 00:01:00:02 ... 00:01:00:29 * // 00:01:01:00 00:01:01:01 00:01:01:02 ... 00:01:00:29 * // : * // 00:01:59:00 00:01:59:01 00:01:59:02 ... 00:01:59:29 * // 00:02:00:02 ... 00:02:00:29 * // 00:02:01:00 00:02:01:01 00:02:01:02 ... 00:02:00:29 * // : * // : * // 00:09:59:00 00:09:59:01 00:09:59:02 ... 00:09:59:29 * // 00:10:00:00 00:10:00:01 00:10:00:02 ... 00:10:00:29 * // 00:10:01:00 00:10:01:01 00:10:01:02 ... 00:10:01:29 * // : * // 00:10:59:00 00:10:59:01 00:10:59:02 ... 00:10:59:29 * // 00:11:00:02 ... 00:11:00:29 * // 00:11:01:00 00:11:01:01 00:11:01:02 ... 00:11:00:29 * // : * // : * // DROP FRAME / 59.94fps (no any standard) * // DROP FRAME / 23.976fps (no any standard) ***************************************************************/ int dropframetimecode = -1; /* mpeg_timecode() return -tc->f on first frame in the minute, tc->f on other. */ int mpeg_timecode(MPEG_timecode_t *tc, int f, int fpscode, double fps) { static const int ifpss[] = { 0, 24, 24, 25, 30, 30, 50, 60, 60, }; int h, m, s; if (dropframetimecode < 0) { char *env = getenv("MJPEG_DROP_FRAME_TIME_CODE"); dropframetimecode = (env && *env != '0' && *env != 'n' && *env != 'N'); } if (dropframetimecode && 0 < fpscode && fpscode + 1 < sizeof ifpss / sizeof ifpss[0] && ifpss[fpscode] == ifpss[fpscode + 1]) { int topinmin = 0, k = (30*4) / ifpss[fpscode]; f *= k; /* frame# when 119.88fps */ h = (f / ((10*60*30-18)*4)); /* # of 10min. */ f %= ((10*60*30-18)*4); /* frame# in 10min. */ f -= (2*4); /* frame# in 10min. - (2*4) */ m = (f / ((60*30-2)*4)); /* min. in 10min. */ topinmin = ((f - k) / ((60*30-2)*4) < m); m += (h % 6 * 10); /* min. */ h /= 6; /* hour */ f %= ((60*30-2)*4); /* frame# in min. - (2*4)*/ f += (2*4); /* frame# in min. */ s = f / (30*4); /* sec. */ f %= (30*4); /* frame# in sec. */ f /= k; /* frame# in sec. on original fps */ tc->f = f; if (topinmin) f = -f; } else { int ifps = ((0 < fpscode && fpscode < sizeof ifpss / sizeof ifpss[0])? ifpss[fpscode]: (int)(fps + .5)); s = f / ifps; f %= ifps; m = s / 60; s %= 60; h = m / 60; m %= 60; tc->f = f; } tc->s = s; tc->m = m; tc->h = h; return f; } mjpegtools-2.1.0/utils/yuv4mpeg_ratio.c0000644000175000017500000001164707646664704020527 0ustar glowwormglowworm/* * yuv4mpeg_ratio.c: Functions for dealing with y4m_ratio_t datatype. * * Copyright (C) 2001 Matthew J. Marjanovic * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include "yuv4mpeg.h" #include "yuv4mpeg_intern.h" /* useful list of standard framerates */ const y4m_ratio_t y4m_fps_UNKNOWN = Y4M_FPS_UNKNOWN; const y4m_ratio_t y4m_fps_NTSC_FILM = Y4M_FPS_NTSC_FILM; const y4m_ratio_t y4m_fps_FILM = Y4M_FPS_FILM; const y4m_ratio_t y4m_fps_PAL = Y4M_FPS_PAL; const y4m_ratio_t y4m_fps_NTSC = Y4M_FPS_NTSC; const y4m_ratio_t y4m_fps_30 = Y4M_FPS_30; const y4m_ratio_t y4m_fps_PAL_FIELD = Y4M_FPS_PAL_FIELD; const y4m_ratio_t y4m_fps_NTSC_FIELD = Y4M_FPS_NTSC_FIELD; const y4m_ratio_t y4m_fps_60 = Y4M_FPS_60; /* useful list of standard sample aspect ratios */ const y4m_ratio_t y4m_sar_UNKNOWN = Y4M_SAR_UNKNOWN; const y4m_ratio_t y4m_sar_SQUARE = Y4M_SAR_SQUARE; const y4m_ratio_t y4m_sar_SQR_ANA_16_9 = Y4M_SAR_SQR_ANA_16_9; const y4m_ratio_t y4m_sar_NTSC_CCIR601 = Y4M_SAR_NTSC_CCIR601; const y4m_ratio_t y4m_sar_NTSC_16_9 = Y4M_SAR_NTSC_16_9; const y4m_ratio_t y4m_sar_NTSC_SVCD_4_3 = Y4M_SAR_NTSC_SVCD_4_3; const y4m_ratio_t y4m_sar_NTSC_SVCD_16_9 = Y4M_SAR_NTSC_SVCD_16_9; const y4m_ratio_t y4m_sar_PAL_CCIR601 = Y4M_SAR_PAL_CCIR601; const y4m_ratio_t y4m_sar_PAL_16_9 = Y4M_SAR_PAL_16_9; const y4m_ratio_t y4m_sar_PAL_SVCD_4_3 = Y4M_SAR_PAL_SVCD_4_3; const y4m_ratio_t y4m_sar_PAL_SVCD_16_9 = Y4M_SAR_PAL_SVCD_16_9; /* useful list of standard display aspect ratios */ const y4m_ratio_t y4m_dar_UNKNOWN = Y4M_DAR_UNKNOWN; const y4m_ratio_t y4m_dar_4_3 = Y4M_DAR_4_3; const y4m_ratio_t y4m_dar_16_9 = Y4M_DAR_16_9; const y4m_ratio_t y4m_dar_221_100 = Y4M_DAR_221_100; /* * Euler's algorithm for greatest common divisor */ static int gcd(int a, int b) { a = (a >= 0) ? a : -a; b = (b >= 0) ? b : -b; while (b > 0) { int x = b; b = a % b; a = x; } return a; } /************************************************************************* * * Remove common factors from a ratio * *************************************************************************/ void y4m_ratio_reduce(y4m_ratio_t *r) { int d; if ((r->n == 0) && (r->d == 0)) return; /* "unknown" */ d = gcd(r->n, r->d); r->n /= d; r->d /= d; } /************************************************************************* * * Parse "nnn:ddd" into a ratio * * returns: Y4M_OK - success * Y4M_ERR_RANGE - range error * *************************************************************************/ int y4m_parse_ratio(y4m_ratio_t *r, const char *s) { char *t = strchr(s, ':'); if (t == NULL) return Y4M_ERR_RANGE; r->n = atoi(s); r->d = atoi(t+1); if (r->d < 0) return Y4M_ERR_RANGE; /* 0:0 == unknown, so that is ok, otherwise zero denominator is bad */ if ((r->d == 0) && (r->n != 0)) return Y4M_ERR_RANGE; y4m_ratio_reduce(r); return Y4M_OK; } /************************************************************************* * * Guess the true SAR (sample aspect ratio) from a list of commonly * encountered values, given the "suggested" display aspect ratio, and * the true frame width and height. * * Returns y4m_sar_UNKNOWN if no match is found. * *************************************************************************/ /* this is big enough to accommodate the difference between 720 and 704 */ #define GUESS_ASPECT_TOLERANCE 0.03 y4m_ratio_t y4m_guess_sar(int width, int height, y4m_ratio_t dar) { int i; double implicit_sar = (double)(dar.n * height) / (double)(dar.d * width); const y4m_ratio_t *sarray[] = { &y4m_sar_SQUARE, &y4m_sar_NTSC_CCIR601, &y4m_sar_NTSC_16_9, &y4m_sar_NTSC_SVCD_4_3, &y4m_sar_NTSC_SVCD_16_9, &y4m_sar_PAL_CCIR601, &y4m_sar_PAL_16_9, &y4m_sar_PAL_SVCD_4_3, &y4m_sar_PAL_SVCD_16_9, &y4m_sar_UNKNOWN }; for (i = 0; !(Y4M_RATIO_EQL(*(sarray[i]),y4m_sar_UNKNOWN)); i++) { double ratio = implicit_sar / Y4M_RATIO_DBL(*(sarray[i])); if ( (ratio > (1.0 - GUESS_ASPECT_TOLERANCE)) && (ratio < (1.0 + GUESS_ASPECT_TOLERANCE)) ) return *(sarray[i]); } return y4m_sar_UNKNOWN; } mjpegtools-2.1.0/utils/mpegtimecode.h0000644000175000017500000000224607342745363020205 0ustar glowwormglowworm/* -*- mode:C -*- */ /* * Copyright (C) 2001 Kawamata/Hitoshi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __MPEGTIMECODE_H__ #define __MPEGTIMECODE_H__ #ifdef __cplusplus extern "C" { #endif typedef struct { char h, m, s, f; } MPEG_timecode_t; extern int dropframetimecode; extern int mpeg_timecode(MPEG_timecode_t *tc, int f, int fpscode, double fps); /* mpeg_timecode() return -tc->f on first frame in the minute, tc->f on other. */ #ifdef __cplusplus } #endif #endif mjpegtools-2.1.0/utils/fastintfns.h0000644000175000017500000000051110205274474017703 0ustar glowwormglowworm/* fast int primitives. min,max,rnddiv2 * * WARNING: Assumes 2's complement arithmetic. */ static inline int intmax( register int x, register int y ) { return x < y ? y : x; } static inline int intmin( register int x, register int y ) { return x < y ? x : y; } static inline int rnddiv2( int x ) { return (x+(x>0))>>1; } mjpegtools-2.1.0/INSTALL0000644000175000017500000003660512217306406015255 0ustar glowwormglowwormInstallation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2012 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX `make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as `configure' are involved. Use GNU `make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf limitation. Until the limitation is lifted, you can use this workaround: CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. mjpegtools-2.1.0/AUTHORS0000644000175000017500000000120712176714635015275 0ustar glowwormglowwormmjpegtools authors: =================== Rainer Johanni Gernot Ziegler Andrew Stevens Bernhard Praschinger Ronald Bultje Xavier Biquard Matthew Marjanovic pHilipp Zabel Kawamata/Hitoshi Stefan Fendt Scott Moser Shawn Sulma Mike Bernson James Klicman mjpegtools-2.1.0/config.sub0000755000175000017500000010527412217306406016206 0ustar glowwormglowworm#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 Free Software Foundation, Inc. timestamp='2012-04-18' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted GNU ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 \ | ns16k | ns32k \ | open8 \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze) basic_machine=microblaze-xilinx ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i386-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: mjpegtools-2.1.0/aenc/0000755000175000017500000000000012217306500015113 5ustar glowwormglowwormmjpegtools-2.1.0/aenc/encode.c0000644000175000017500000014760410314356557016545 0ustar glowwormglowworm/********************************************************************** Copyright (c) 1991 MPEG/audio software simulation group, All Rights Reserved encode.c **********************************************************************/ /********************************************************************** * MPEG/audio coding/decoding software, work in progress * * NOT for public distribution until verified and approved by the * * MPEG/audio committee. For further information, please contact * * Davis Pan, 508-493-2241, e-mail: pan@3d.enet.dec.com * * * * VERSION 3.9t * * changes made since last update: * * date programmers comment * * 3/01/91 Douglas Wong, start of version 1.1 records * * Davis Pan * * 3/06/91 Douglas Wong rename: setup.h to endef.h * * efilter to enfilter * * ewindow to enwindow * * integrated "quantizer", "scalefactor",* * and "transmission" files * * update routine "window_subband" * * 3/31/91 Bill Aspromonte replaced read_filter by * * create_an_filter * * 5/10/91 W. Joseph Carter Ported to Macintosh and Unix. * * Incorporated Jean-Georges Fritsch's * * "bitstream.c" package. * * Incorporated Bill Aspromonte's * * filterbank coefficient matrix * * calculation routines and added * * roundoff to coincide with specs. * * Modified to strictly adhere to * * encoded bitstream specs, including * * "Berlin changes". * * Modified PCM sound file handling to * * process all incoming samples and fill * * out last encoded frame with zeros * * (silence) if needed. * * Located and fixed numerous software * * bugs and table data errors. * * 19jun91 dpwe (Aware) moved "alloc_*" reader to common.c * * Globals sblimit, alloc replaced by new* * struct 'frame_params' passed as arg. * * Added JOINT STEREO coding, layers I,II* * Affects: *_bit_allocation, * * subband_quantization, encode_bit_alloc* * sample_encoding * * 6/10/91 Earle Jennings modified II_subband_quantization to * * resolve type cast problem for MS_DOS * * 6/11/91 Earle Jennings modified to avoid overflow on MS_DOS * * in routine filter_subband * * 7/10/91 Earle Jennings port to MsDos from MacIntosh version * * 8/ 8/91 Jens Spille Change for MS-C6.00 * *10/ 1/91 S.I. Sudharsanan, Ported to IBM AIX platform. * * Don H. Lee, * * Peter W. Farrett * *10/ 3/91 Don H. Lee implemented CRC-16 error protection * * newly introduced function encode_CRC * *11/ 8/91 Kathy Wang Documentation of code * * All variablenames are referred to * * with surrounding pound (#) signs * * 2/11/92 W. Joseph Carter Ported new code to Macintosh. Most * * important fixes involved changing * * 16-bit ints to long or unsigned in * * bit alloc routines for quant of 65535 * * and passing proper function args. * * Removed "Other Joint Stereo" option * * and made bitrate be total channel * * bitrate, irrespective of the mode. * * Fixed many small bugs & reorganized. * * 6/16/92 Shaun Astarabadi Changed I_scale_factor_calc() and * * II_scale_factor_calc() to use scale * * factor 0 thru 62 only and not to * * encode index 63 into the bit stream. * * 7/27/92 Mike Li (re-)Port to MS-DOS * * 9/22/92 jddevine@aware.com Fixed _scale_factor_calc() defs * * 3/31/93 Giogio Dimino changed II_a_bit_allocation() from: * * if( ad > ...) to if(ad >= ...) * * 8/05/93 TEST changed I_a_bit_allocation() from: * * if( ad > ...) to if(ad >= ...) * **********************************************************************/ #include "config.h" #include #include #include "common.h" #include "encoder.h" extern int freq_in; extern int freq_out; extern int chans_in; extern int chans_out; extern int audio_bits; extern int32_t audio_bytes; extern int raw_in; static unsigned long nseconds = 0; static int num_out = -1; static int buff_pos; static int big_endian; static unsigned char *in_buff; static short *buf1, *buf2, *out_buff; static double freq_quot; static void read_and_resample(void) { int n, nbps, num_in, is; double s, fs; /* Read 1 second of audio from stdin */ nbps = chans_in*audio_bits/8; /* Bytes per sample in */ if(num_out<0) { /* Initialize, read first sample to the end of the buffer */ n = fread(in_buff+freq_in*nbps,1,nbps,stdin); if(n!=nbps) { mjpeg_error_exit1("Error reading wave data"); } } /* Copy last sample in input buffer to front, read exactly 1 second */ memcpy(in_buff,in_buff+freq_in*nbps,nbps); n = fread(in_buff+nbps,1,freq_in*nbps,stdin); num_in = n/nbps + 1; /* Step 1: Make little endian shorts from input */ if(audio_bits==8) { for(n=0;n> 1; } if(chans_in==1 && chans_out==2) { for(n=0;nnum_out) n = num_out-buff_pos; memcpy(abuff,out_buff+buff_pos,n*sizeof(short)); abuff += n; buff_pos += n; num -= n; } return 1; } /*=======================================================================\ | | | This segment contains all the core routines of the encoder, | | except for the psychoacoustic models. | | | | The user can select either one of the two psychoacoustic | | models. Model I is a simple tonal and noise masking threshold | | generator, and Model II is a more sophisticated cochlear masking | | threshold generator. Model I is recommended for lower complexity | | applications whereas Model II gives better subjective quality at low | | bit rates. | | | | Layers I and II of mono, stereo, and joint stereo modes are supported.| | Routines associated with a given layer are prefixed by "I_" for layer | | 1 and "II_" for layer 2. | \=======================================================================*/ /************************************************************************ * * get_audio() * * PURPOSE: reads a frame of audio data from a file to the buffer, * aligns the data for future processing, and separates the * left and right channels * * SEMANTICS: * Calls read_samples() to read a frame of audio data from filepointer * #musicin# to #insampl[]#. The data is shifted to make sure the data * is centered for the 1024pt window to be used by the psychoacoustic model, * and to compensate for the 256 sample delay from the filter bank. For * stereo, the channels are also demultiplexed into #buffer[0][]# and * #buffer[1][]# * ************************************************************************/ unsigned long get_audio(musicin, buffer, num_samples, stereo, lay) FILE *musicin; short buffer[2][1152]; unsigned long num_samples; int stereo, lay; { int j, res; short insamp[2304]; if (lay == 1){ if(stereo == 2){ /* layer 1, stereo */ res = get_samples(insamp, 384*2, stereo); for(j=0;j<448;j++) { if(j<64) { buffer[0][j] = buffer[0][j+384]; buffer[1][j] = buffer[1][j+384]; } else { buffer[0][j] = insamp[2*j-128]; buffer[1][j] = insamp[2*j-127]; } } } else { /* layer 1, mono */ res = get_samples(insamp, 384, stereo); for(j=0;j<448;j++){ if(j<64) { buffer[0][j] = buffer[0][j+384]; buffer[1][j] = 0; } else { buffer[0][j] = insamp[j-64]; buffer[1][j] = 0; } } } } else { if(stereo == 2){ /* layer 2 (or 3), stereo */ res = get_samples(insamp, 1152*2, stereo); for(j=0;j<1152;j++) { buffer[0][j] = insamp[2*j]; buffer[1][j] = insamp[2*j+1]; } } else { /* layer 2 (or 3), mono */ res = get_samples(insamp, 1152, stereo); for(j=0;j<1152;j++){ buffer[0][j] = insamp[j]; buffer[1][j] = 0; } } } return res; } /************************************************************************ * * window_subband() * * PURPOSE: Overlapping window on PCM samples * * SEMANTICS: * 32 16-bit pcm samples are scaled to fractional 2's complement and * concatenated to the end of the window buffer #x#. The updated window * buffer #x# is then windowed by the analysis window #c# to produce the * windowed sample #z# * ************************************************************************/ void window_subband(buffer, z, k) short **buffer; double z[HAN_SIZE]; int k; { typedef double XX[2][HAN_SIZE]; static XX *x; int i, j; static int off[2] = {0,0}; static char init = 0; static double *c; if (!init) { c = (double *) mem_alloc(sizeof(double) * HAN_SIZE, "window"); read_ana_window(c); x = (XX *) mem_alloc(sizeof(XX),"x"); for (i=0;i<2;i++) for (j=0;j= 0) modf(filter[i][k]+0.5, &filter[i][k]); else modf(filter[i][k]-0.5, &filter[i][k]); filter[i][k] *= 1e-9; } } /************************************************************************ * * filter_subband() * * PURPOSE: Calculates the analysis filter bank coefficients * * SEMANTICS: * The windowed samples #z# is filtered by the digital filter matrix #m# * to produce the subband samples #s#. This done by first selectively * picking out values from the windowed samples, and then multiplying * them by the filter matrix, producing 32 subband samples. * ************************************************************************/ void filter_subband(z,s) double z[HAN_SIZE], s[SBLIMIT]; { double y[64]; int i,j; static char init = 0; typedef double MM[SBLIMIT][64]; static MM *m; if (!init) { m = (MM *) mem_alloc(sizeof(MM), "filter"); create_ana_filter(*m); init = 1; } for (i=0;i<64;i++) for (j=0, y[i] = 0;j<8;j++) y[i] += z[i+64*j]; for (i=0;iheader; putbits(bs,0xfff,12); /* syncword 12 bits */ put1bit(bs,info->version); /* ID 1 bit */ putbits(bs,4-info->lay,2); /* layer 2 bits */ put1bit(bs,!info->error_protection); /* bit set => no err prot */ putbits(bs,info->bitrate_index,4); putbits(bs,info->sampling_frequency,2); put1bit(bs,info->padding); put1bit(bs,info->extension); /* private_bit */ putbits(bs,info->mode,2); putbits(bs,info->mode_ext,2); put1bit(bs,info->copyright); put1bit(bs,info->original); putbits(bs,info->emphasis,2); } /************************************************************************ * * mod() * * PURPOSE: Returns the absolute value of its argument * ************************************************************************/ double mod(a) double a; { return (a > 0) ? a : -a; } /************************************************************************ * * I_combine_LR (Layer I) * II_combine_LR (Layer II) * * PURPOSE:Combines left and right channels into a mono channel * * SEMANTICS: The average of left and right subband samples is put into * #joint_sample# * * Layer I and II differ in frame length and # subbands used * ************************************************************************/ void I_combine_LR(sb_sample, joint_sample) double sb_sample[2][3][SCALE_BLOCK][SBLIMIT]; double joint_sample[3][SCALE_BLOCK][SBLIMIT]; { /* make a filtered mono for joint stereo */ int sb, smp; for(sb = 0; sb s[i]) s[i] = mod(sb_sample[k][0][j][i]); for (i=0;i=0;j--) /* $A 6/16/92 */ if (s[i] <= multiple[j]) { scalar[k][0][i] = j; break; } } } /******************************** Layer II ******************************/ void II_scale_factor_calc(sb_sample,scalar,stereo,sblimit) double sb_sample[][3][SCALE_BLOCK][SBLIMIT]; unsigned int scalar[][3][SBLIMIT]; int stereo,sblimit; { int i,j, k,t; double s[SBLIMIT]; for (k=0;k s[i]) s[i] = mod(sb_sample[k][t][j][i]); for (i=0;i=0;j--) /* $A 6/16/92 */ if (s[i] <= multiple[j]) { scalar[k][t][i] = j; break; } for (i=sblimit;istereo; int sblimit = fr_ps->sblimit; for (k=0;k scalar[k][j][i]) max = scalar[k][j][i]; for (i=sblimit;istereo; for (k=0;kstereo; int sblimit = fr_ps->sblimit; int dscf[2]; int class[2],i,j,k; static int pattern[5][5] = {{0x123, 0x122, 0x122, 0x133, 0x123}, {0x113, 0x111, 0x111, 0x444, 0x113}, {0x111, 0x111, 0x111, 0x333, 0x113}, {0x222, 0x222, 0x222, 0x333, 0x123}, {0x123, 0x122, 0x122, 0x133, 0x123}}; for (k=0;k -3 && dscf[j] <0) class[j] = 1; else if (dscf[j] == 0) class[j] = 2; else if (dscf[j] > 0 && dscf[j] < 3) class[j] = 3; else class[j] = 4; } switch (pattern[class[0]][class[1]]) { case 0x123 : scfsi[k][i] = 0; break; case 0x122 : scfsi[k][i] = 3; scalar[k][2][i] = scalar[k][1][i]; break; case 0x133 : scfsi[k][i] = 3; scalar[k][1][i] = scalar[k][2][i]; break; case 0x113 : scfsi[k][i] = 1; scalar[k][1][i] = scalar[k][0][i]; break; case 0x111 : scfsi[k][i] = 2; scalar[k][1][i] = scalar[k][2][i] = scalar[k][0][i]; break; case 0x222 : scfsi[k][i] = 2; scalar[k][0][i] = scalar[k][2][i] = scalar[k][1][i]; break; case 0x333 : scfsi[k][i] = 2; scalar[k][0][i] = scalar[k][1][i] = scalar[k][2][i]; break; case 0x444 : scfsi[k][i] = 2; if (scalar[k][0][i] > scalar[k][2][i]) scalar[k][0][i] = scalar[k][2][i]; scalar[k][1][i] = scalar[k][2][i] = scalar[k][0][i]; } } } /************************************************************************ * * I_encode_scale (Layer I) * II_encode_scale (Layer II) * * PURPOSE:The encoded scalar factor information is arranged and * queued into the output fifo to be transmitted. * * For Layer II, the three scale factors associated with * a given subband and channel are transmitted in accordance * with the scfsi, which is transmitted first. * ************************************************************************/ void I_encode_scale(scalar, bit_alloc, fr_ps, bs) unsigned int scalar[2][3][SBLIMIT]; unsigned int bit_alloc[2][SBLIMIT]; frame_params *fr_ps; Bit_stream_struc *bs; { int stereo = fr_ps->stereo; int i,j; for (i=0;istereo; int sblimit = fr_ps->sblimit; int i,j,k; for (i=0;istereo; int jsbound = fr_ps->jsbound; int req_bits = 0; /* initial b_anc (header) allocation bits */ req_bits = 32 + 4 * ( (jsbound * stereo) + (SBLIMIT-jsbound) ); for(i=0; i= NOISY_MIN_MNR) break; /* we found enough bits */ if(stereo == 2 && i >= jsbound) /* check other JS channel */ for(;k<14; ++k) if( (-perm_smr[1-j][i] + snr[k]) >= NOISY_MIN_MNR) break; if(k>0) req_bits += (k+1)*SCALE_BLOCK + 6*((i>=jsbound)?stereo:1); } return req_bits; } /***************************** Layer II ********************************/ int II_bits_for_nonoise(perm_smr, scfsi, fr_ps) double perm_smr[2][SBLIMIT]; unsigned int scfsi[2][SBLIMIT]; frame_params *fr_ps; { int sb,ch,ba; int stereo = fr_ps->stereo; int sblimit = fr_ps->sblimit; int jsbound = fr_ps->jsbound; al_table *alloc = fr_ps->alloc; int req_bits = 0, bbal = 0, berr = 0, banc = 32; int maxAlloc, sel_bits, sc_bits, smp_bits; static int sfsPerScfsi[] = { 3,2,1,2 }; /* lookup # sfs per scfsi */ /* added 92-08-11 shn */ if (fr_ps->header->error_protection) berr=16; else berr=0; for (sb=0; sb0)?1:0)]) >= NOISY_MIN_MNR) break; /* we found enough bits */ if(stereo == 2 && sb >= jsbound) /* check other JS channel */ for(;ba0)?1:0)]) >= NOISY_MIN_MNR) break; if(ba>0) { smp_bits = SCALE_BLOCK * ((*alloc)[sb][ba].group * (*alloc)[sb][ba].bits); /* scale factor bits required for subband */ sel_bits = 2; sc_bits = 6 * sfsPerScfsi[scfsi[ch][sb]]; if(stereo == 2 && sb >= jsbound) { /* each new js sb has L+R scfsis */ sel_bits += 2; sc_bits += 6 * sfsPerScfsi[scfsi[1-ch][sb]]; } req_bits += smp_bits+sel_bits+sc_bits; } } return req_bits; } /************************************************************************ * * I_main_bit_allocation (Layer I) * II_main_bit_allocation (Layer II) * * PURPOSE:For joint stereo mode, determines which of the 4 joint * stereo modes is needed. Then calls *_a_bit_allocation(), which * allocates bits for each of the subbands until there are no more bits * left, or the MNR is at the noise/no_noise threshold. * * SEMANTICS: * * For joint stereo mode, joint stereo is changed to stereo if * there are enough bits to encode stereo at or better than the * no-noise threshold (NOISY_MIN_MNR). Otherwise, the system * iteratively allocates less bits by using joint stereo until one * of the following occurs: * - there are no more noisy subbands (MNR >= NOISY_MIN_MNR) * - mode_ext has been reduced to 0, which means that all but the * lowest 4 subbands have been converted from stereo to joint * stereo, and no more subbands may be converted * * This function calls *_bits_for_nonoise() and *_a_bit_allocation(). * ************************************************************************/ void I_main_bit_allocation(perm_smr, bit_alloc, adb, fr_ps) double perm_smr[2][SBLIMIT]; unsigned int bit_alloc[2][SBLIMIT]; int *adb; frame_params *fr_ps; { int noisy_sbs; int mode, mode_ext, lay, i; int rq_db; static int init = 0; if(init == 0) { /* rearrange snr for layer I */ snr[2] = snr[3]; for (i=3;i<16;i++) snr[i] = snr[i+2]; init = 1; } if((mode = fr_ps->actual_mode) == MPG_MD_JOINT_STEREO) { fr_ps->header->mode = MPG_MD_STEREO; fr_ps->header->mode_ext = 0; fr_ps->jsbound = fr_ps->sblimit; if((rq_db = I_bits_for_nonoise(perm_smr, fr_ps)) > *adb) { fr_ps->header->mode = MPG_MD_JOINT_STEREO; mode_ext = 4; /* 3 is least severe reduction */ lay = fr_ps->header->lay; do { --mode_ext; fr_ps->jsbound = js_bound(lay, mode_ext); rq_db = I_bits_for_nonoise(perm_smr, fr_ps); } while( (rq_db > *adb) && (mode_ext > 0)); fr_ps->header->mode_ext = mode_ext; } /* well we either eliminated noisy sbs or mode_ext == 0 */ } noisy_sbs = I_a_bit_allocation(perm_smr, bit_alloc, adb, fr_ps); } /***************************** Layer II ********************************/ void II_main_bit_allocation(perm_smr, scfsi, bit_alloc, adb, fr_ps) double perm_smr[2][SBLIMIT]; unsigned int scfsi[2][SBLIMIT]; unsigned int bit_alloc[2][SBLIMIT]; int *adb; frame_params *fr_ps; { int noisy_sbs; int mode, mode_ext, lay; int rq_db; if((mode = fr_ps->actual_mode) == MPG_MD_JOINT_STEREO) { fr_ps->header->mode = MPG_MD_STEREO; fr_ps->header->mode_ext = 0; fr_ps->jsbound = fr_ps->sblimit; if((rq_db=II_bits_for_nonoise(perm_smr, scfsi, fr_ps)) > *adb) { fr_ps->header->mode = MPG_MD_JOINT_STEREO; mode_ext = 4; /* 3 is least severe reduction */ lay = fr_ps->header->lay; do { --mode_ext; fr_ps->jsbound = js_bound(lay, mode_ext); rq_db = II_bits_for_nonoise(perm_smr, scfsi, fr_ps); } while( (rq_db > *adb) && (mode_ext > 0)); fr_ps->header->mode_ext = mode_ext; } /* well we either eliminated noisy sbs or mode_ext == 0 */ } noisy_sbs = II_a_bit_allocation(perm_smr, scfsi, bit_alloc, adb, fr_ps); } /************************************************************************ * * I_a_bit_allocation (Layer I) * II_a_bit_allocation (Layer II) * * PURPOSE:Adds bits to the subbands with the lowest mask-to-noise * ratios, until the maximum number of bits for the subband has * been allocated. * * SEMANTICS: * 1. Find the subband and channel with the smallest MNR (#min_sb#, * and #min_ch#) * 2. Calculate the increase in bits needed if we increase the bit * allocation to the next higher level * 3. If there are enough bits available for increasing the resolution * in #min_sb#, #min_ch#, and the subband has not yet reached its * maximum allocation, update the bit allocation, MNR, and bits * available accordingly * 4. Repeat until there are no more bits left, or no more available * subbands. (A subband is still available until the maximum * number of bits for the subband has been allocated, or there * aren't enough bits to go to the next higher resolution in the * subband.) * ************************************************************************/ int I_a_bit_allocation(perm_smr, bit_alloc, adb, fr_ps) /* return noisy sbs */ double perm_smr[2][SBLIMIT]; unsigned int bit_alloc[2][SBLIMIT]; int *adb; frame_params *fr_ps; { int i, k, smpl_bits, scale_bits, min_sb, min_ch, oth_ch; int bspl, bscf, ad, noisy_sbs, bbal ; double mnr[2][SBLIMIT], small; char used[2][SBLIMIT]; int stereo = fr_ps->stereo; int jsbound = fr_ps->jsbound; static char init= 0; static int banc=32, berr=0; if (!init) { init = 1; if (fr_ps->header->error_protection) berr = 16; /* added 92-08-11 shn */ } bbal = 4 * ( (jsbound * stereo) + (SBLIMIT-jsbound) ); *adb -= bbal + berr + banc; ad= *adb; for (i=0;i mnr[k][i]) { small = mnr[k][i]; min_sb = i; min_ch = k; } if(min_sb > -1) { /* there was something to find */ /* first step of bit allocation is biggest */ if (used[min_ch][min_sb]) { smpl_bits = SCALE_BLOCK; scale_bits = 0; } else { smpl_bits = 24; scale_bits = 6; } if(min_sb >= jsbound) scale_bits *= stereo; /* check to see enough bits were available for */ /* increasing resolution in the minimum band */ if (ad >= bspl + bscf + scale_bits + smpl_bits) { bspl += smpl_bits; /* bit for subband sample */ bscf += scale_bits; /* bit for scale factor */ bit_alloc[min_ch][min_sb]++; used[min_ch][min_sb] = 1; /* subband has bits */ mnr[min_ch][min_sb] = -perm_smr[min_ch][min_sb] + snr[bit_alloc[min_ch][min_sb]]; /* Check if subband has been fully allocated max bits */ if (bit_alloc[min_ch][min_sb] == 14 ) used[min_ch][min_sb] = 2; } else /* no room to improve this band */ used[min_ch][min_sb] = 2; /* for allocation anymore */ if(stereo == 2 && min_sb >= jsbound) { oth_ch = 1-min_ch; /* joint-st : fix other ch */ bit_alloc[oth_ch][min_sb] = bit_alloc[min_ch][min_sb]; used[oth_ch][min_sb] = used[min_ch][min_sb]; mnr[oth_ch][min_sb] = -perm_smr[oth_ch][min_sb] + snr[bit_alloc[oth_ch][min_sb]]; } } } while(min_sb>-1); /* i.e. still some sub-bands to find */ /* Calculate the number of bits left, add on to pointed var */ ad -= bspl+bscf; *adb = ad; /* see how many channels are noisy */ noisy_sbs = 0; small = mnr[0][0]; for(k=0; k mnr[k][i]) small = mnr[k][i]; } } return noisy_sbs; } /***************************** Layer II ********************************/ int II_a_bit_allocation(perm_smr, scfsi, bit_alloc, adb, fr_ps) double perm_smr[2][SBLIMIT]; unsigned int scfsi[2][SBLIMIT]; unsigned int bit_alloc[2][SBLIMIT]; int *adb; frame_params *fr_ps; { int i, min_ch, min_sb, oth_ch, k, increment, scale, seli, ba; int bspl, bscf, bsel, ad, noisy_sbs, bbal=0; double mnr[2][SBLIMIT], small; char used[2][SBLIMIT]; int stereo = fr_ps->stereo; int sblimit = fr_ps->sblimit; int jsbound = fr_ps->jsbound; al_table *alloc = fr_ps->alloc; static char init= 0; static int banc=32, berr=0; static int sfsPerScfsi[] = { 3,2,1,2 }; /* lookup # sfs per scfsi */ if (!init) { init = 1; if (fr_ps->header->error_protection) berr=16; /* added 92-08-11 shn */ } for (i=0; i mnr[k][i]) { small = mnr[k][i]; min_sb = i; min_ch = k; } if(min_sb > -1) { /* there was something to find */ /* find increase in bit allocation in subband [min] */ increment = SCALE_BLOCK * ((*alloc)[min_sb][bit_alloc[min_ch][min_sb]+1].group * (*alloc)[min_sb][bit_alloc[min_ch][min_sb]+1].bits); if (used[min_ch][min_sb]) increment -= SCALE_BLOCK * ((*alloc)[min_sb][bit_alloc[min_ch][min_sb]].group* (*alloc)[min_sb][bit_alloc[min_ch][min_sb]].bits); /* scale factor bits required for subband [min] */ oth_ch = 1 - min_ch; /* above js bound, need both chans */ if (used[min_ch][min_sb]) scale = seli = 0; else { /* this channel had no bits or scfs before */ seli = 2; scale = 6 * sfsPerScfsi[scfsi[min_ch][min_sb]]; if(stereo == 2 && min_sb >= jsbound) { /* each new js sb has L+R scfsis */ seli += 2; scale += 6 * sfsPerScfsi[scfsi[oth_ch][min_sb]]; } } /* check to see enough bits were available for */ /* increasing resolution in the minimum band */ if (ad >= bspl + bscf + bsel + seli + scale + increment) { ba = ++bit_alloc[min_ch][min_sb]; /* next up alloc */ bspl += increment; /* bits for subband sample */ bscf += scale; /* bits for scale factor */ bsel += seli; /* bits for scfsi code */ used[min_ch][min_sb] = 1; /* subband has bits */ mnr[min_ch][min_sb] = -perm_smr[min_ch][min_sb] + snr[(*alloc)[min_sb][ba].quant+1]; /* Check if subband has been fully allocated max bits */ if (ba >= (1<<(*alloc)[min_sb][0].bits)-1) used[min_ch][min_sb] = 2; } else used[min_ch][min_sb] = 2; /* can't increase this alloc */ if(min_sb >= jsbound && stereo == 2) { /* above jsbound, alloc applies L+R */ ba = bit_alloc[oth_ch][min_sb] = bit_alloc[min_ch][min_sb]; used[oth_ch][min_sb] = used[min_ch][min_sb]; mnr[oth_ch][min_sb] = -perm_smr[oth_ch][min_sb] + snr[(*alloc)[min_sb][ba].quant+1]; } } } while(min_sb > -1); /* until could find no channel */ /* Calculate the number of bits left */ ad -= bspl+bscf+bsel; *adb = ad; for (i=sblimit;i mnr[k][i]) small = mnr[k][i]; if(mnr[k][i] < NOISY_MIN_MNR) ++noisy_sbs; /* noise is not masked */ } } return noisy_sbs; } /************************************************************************ * * I_subband_quantization (Layer I) * II_subband_quantization (Layer II) * * PURPOSE:Quantizes subband samples to appropriate number of bits * * SEMANTICS: Subband samples are divided by their scalefactors, which * makes the quantization more efficient. The scaled samples are * quantized by the function a*x+b, where a and b are functions of * the number of quantization levels. The result is then truncated * to the appropriate number of bits and the MSB is inverted. * * Note that for fractional 2's complement, inverting the MSB for a * negative number x is equivalent to adding 1 to it. * ************************************************************************/ static double a[17] = { 0.750000000, 0.625000000, 0.875000000, 0.562500000, 0.937500000, 0.968750000, 0.984375000, 0.992187500, 0.996093750, 0.998046875, 0.999023438, 0.999511719, 0.999755859, 0.999877930, 0.999938965, 0.999969482, 0.999984741 }; static double b[17] = { -0.250000000, -0.375000000, -0.125000000, -0.437500000, -0.062500000, -0.031250000, -0.015625000, -0.007812500, -0.003906250, -0.001953125, -0.000976563, -0.000488281, -0.000244141, -0.000122070, -0.000061035, -0.000030518, -0.000015259 }; void I_subband_quantization(scalar, sb_samples, j_scale, j_samps, bit_alloc, sbband, fr_ps) unsigned int scalar[2][3][SBLIMIT]; double sb_samples[2][3][SCALE_BLOCK][SBLIMIT]; unsigned int j_scale[3][SBLIMIT]; double j_samps[3][SCALE_BLOCK][SBLIMIT]; /* L+R for j-stereo if necess */ unsigned int bit_alloc[2][SBLIMIT]; unsigned int sbband[2][3][SCALE_BLOCK][SBLIMIT]; frame_params *fr_ps; { int i, j, k, n, sig; int stereo = fr_ps->stereo; int jsbound = fr_ps->jsbound; double d; static char init = 0; if (!init) { init = 1; /* rearrange quantization coef to correspond to layer I table */ a[1] = a[2]; b[1] = b[2]; for (i=2;i<15;i++) { a[i] = a[i+2]; b[i] = b[i+2]; } } for (j=0;j=jsbound) /* use the joint data passed in */ d = j_samps[0][j][i] / multiple[j_scale[0][i]]; else d = sb_samples[k][0][j][i] / multiple[scalar[k][0][i]]; /* scale and quantize floating point sample */ n = bit_alloc[k][i]; d = d * a[n-1] + b[n-1]; /* extract MSB N-1 bits from the floating point sample */ if (d >= 0) sig = 1; else { sig = 0; d += 1.0; } sbband[k][0][j][i] = (unsigned int) (d * (double) (1L<stereo; int sblimit = fr_ps->sblimit; int jsbound = fr_ps->jsbound; unsigned int stps; double d; al_table *alloc = fr_ps->alloc; for (s=0;s<3;s++) for (j=0;j=jsbound) /* use j-stereo samples */ d = j_samps[s][j][i] / multiple[j_scale[s][i]]; else d = sb_samples[k][s][j][i] / multiple[scalar[k][s][i]]; if (mod(d) > 1.0) mjpeg_info("Not scaled properly %d %d %d %d",k,s,j,i); qnt = (*alloc)[i][bit_alloc[k][i]].quant; d = d * a[qnt] + b[qnt]; /* extract MSB N-1 bits from the floating point sample */ if (d >= 0) sig = 1; else { sig = 0; d += 1.0; } n = 0; stps = (*alloc)[i][bit_alloc[k][i]].steps; while ((1L<stereo; int jsbound = fr_ps->jsbound; for (i=0;istereo; int sblimit = fr_ps->sblimit; int jsbound = fr_ps->jsbound; al_table *alloc = fr_ps->alloc; for (i=0;istereo; int jsbound = fr_ps->jsbound; for(j=0;jstereo; int sblimit = fr_ps->sblimit; int jsbound = fr_ps->jsbound; al_table *alloc = fr_ps->alloc; for (s=0;s<3;s++) for (j=0;j #include #include #include "common.h" /* * Global Variable Definitions */ const char *mode_names[4] = { "stereo", "j-stereo", "dual-ch", "single-ch" }; const char *layer_names[3] = { "I", "II", "III" }; double s_freq[4] = {44.1, 48, 32, 0}; int bitrate[3][15] = { {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448}, {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384}, {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320} }; double multiple[64] = { 2.00000000000000, 1.58740105196820, 1.25992104989487, 1.00000000000000, 0.79370052598410, 0.62996052494744, 0.50000000000000, 0.39685026299205, 0.31498026247372, 0.25000000000000, 0.19842513149602, 0.15749013123686, 0.12500000000000, 0.09921256574801, 0.07874506561843, 0.06250000000000, 0.04960628287401, 0.03937253280921, 0.03125000000000, 0.02480314143700, 0.01968626640461, 0.01562500000000, 0.01240157071850, 0.00984313320230, 0.00781250000000, 0.00620078535925, 0.00492156660115, 0.00390625000000, 0.00310039267963, 0.00246078330058, 0.00195312500000, 0.00155019633981, 0.00123039165029, 0.00097656250000, 0.00077509816991, 0.00061519582514, 0.00048828125000, 0.00038754908495, 0.00030759791257, 0.00024414062500, 0.00019377454248, 0.00015379895629, 0.00012207031250, 0.00009688727124, 0.00007689947814, 0.00006103515625, 0.00004844363562, 0.00003844973907, 0.00003051757813, 0.00002422181781, 0.00001922486954, 0.00001525878906, 0.00001211090890, 0.00000961243477, 0.00000762939453, 0.00000605545445, 0.00000480621738, 0.00000381469727, 0.00000302772723, 0.00000240310869, 0.00000190734863, 0.00000151386361, 0.00000120155435, 1E-20 }; /* * Using the decoded info the appropriate possible quantization per * subband table is loaded */ int pick_table(fr_ps) /* choose table, load if necess, return # sb's */ frame_params *fr_ps; { int table, lay, ws, bsp, br_per_ch, sfrq; int sblim = fr_ps->sblimit; /* return current value if no load */ lay = fr_ps->header->lay - 1; bsp = fr_ps->header->bitrate_index; br_per_ch = bitrate[lay][bsp] / fr_ps->stereo; ws = fr_ps->header->sampling_frequency; sfrq = s_freq[ws]; /* decision rules refer to per-channel bitrates (kbits/sec/chan) */ if ((sfrq == 48 && br_per_ch >= 56) || (br_per_ch >= 56 && br_per_ch <= 80)) table = 0; else if (sfrq != 48 && br_per_ch >= 96) table = 1; else if (sfrq != 32 && br_per_ch <= 48) table = 2; else table = 3; if (fr_ps->tab_num != table) { if (fr_ps->tab_num >= 0) mem_free((void **)&(fr_ps->alloc)); fr_ps->alloc = (al_table *) mem_alloc(sizeof(al_table), "alloc"); sblim = read_bit_alloc(fr_ps->tab_num = table, fr_ps->alloc); } return sblim; } int js_bound(lay, m_ext) int lay, m_ext; { static int jsb_table[3][4] = { { 4, 8, 12, 16 }, { 4, 8, 12, 16}, { 0, 4, 8, 16} }; /* lay+m_e -> jsbound */ if(lay<1 || lay >3 || m_ext<0 || m_ext>3) { mjpeg_error_exit1("js_bound bad layer/modext (%d/%d)", lay, m_ext); } return(jsb_table[lay-1][m_ext]); } void hdr_to_frps(fr_ps) /* interpret data in hdr str to fields in fr_ps */ frame_params *fr_ps; { layer *hdr = fr_ps->header; /* (or pass in as arg?) */ fr_ps->actual_mode = hdr->mode; fr_ps->stereo = (hdr->mode == MPG_MD_MONO) ? 1 : 2; if (hdr->lay == 2) fr_ps->sblimit = pick_table(fr_ps); else fr_ps->sblimit = SBLIMIT; if(hdr->mode == MPG_MD_JOINT_STEREO) fr_ps->jsbound = js_bound(hdr->lay, hdr->mode_ext); else fr_ps->jsbound = fr_ps->sblimit; /* alloc, tab_num set in pick_table */ } #ifdef WRITE_DEBUG_INFO void WriteHdr(fr_ps s) frame_params *fr_ps; FILE *s; { layer *info = fr_ps->header; fprintf(s, "HDR: s=FFF, id=%X, l=%X, ep=%X, br=%X, sf=%X, pd=%X, ", info->version, info->lay, !info->error_protection, info->bitrate_index, info->sampling_frequency, info->padding); fprintf(s, "pr=%X, m=%X, js=%X, c=%X, o=%X, e=%X\n", info->extension, info->mode, info->mode_ext, info->copyright, info->original, info->emphasis); fprintf(s, "layer=%s, tot bitrate=%d, sfrq=%.1f, mode=%s, ", layer_names[info->lay-1], bitrate[info->lay-1][info->bitrate_index], s_freq[info->sampling_frequency], mode_names[info->mode]); fprintf(s, "sblim=%d, jsbd=%d, ch=%d\n", fr_ps->sblimit, fr_ps->jsbound, fr_ps->stereo); fflush(s); } void WriteBitAlloc(bit_alloc, f_p, s) unsigned int bit_alloc[2][SBLIMIT]; frame_params *f_p; FILE *s; { int i,j; int st = f_p->stereo; int sbl = f_p->sblimit; int jsb = f_p->jsbound; fprintf(s, "BITA "); for(i=0; istereo; int sblimit = fr_ps->sblimit; int lay = fr_ps->header->lay; int i,j,k; if(lay == 2) { fprintf(s, "SFSI "); for (i=0;istereo; int sblimit = fr_ps->sblimit; fprintf(s, "SMPL "); for (i=0;ibuf_size-2-bs->buf_byte_idx; register unsigned long n=1; register int index=0; char val[2]; while ((i>=0) && (!bs->eob)) { if (bs->format == BINARY) n = fread(&bs->buf[i--], sizeof(unsigned char), 1, bs->pt); else { while((index < 2) && n) { n = fread(&val[index], sizeof(char), 1, bs->pt); switch (val[index]) { case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: index++; break; default: break; } } if (val[0] <= 0x39) bs->buf[i] = (val[0] - 0x30) << 4; else bs->buf[i] = (val[0] - 0x37) << 4; if (val[1] <= 0x39) bs->buf[i--] |= (val[1] - 0x30); else bs->buf[i--] |= (val[1] - 0x37); index = 0; } if (!n) { bs->eob= i+1; } } } /* empty the buffer to the output device when the buffer becomes full */ void empty_buffer(bs, minimum) Bit_stream_struc *bs; /* bit stream structure */ int minimum; /* end of the buffer to empty */ { register int i; #if BS_FORMAT == BINARY for (i=bs->buf_size-1;i>=minimum;i--) fwrite(&bs->buf[i], sizeof(unsigned char), 1, bs->pt); #else for (i=bs->buf_size-1;i>=minimum;i--) { char val[2]; val[0] = he[((bs->buf[i] >> 4) & 0x0F)]; val[1] = he[(bs->buf[i] & 0x0F)]; fwrite(val, sizeof(char), 2, bs->pt); } #endif for (i=minimum-1; i>=0; i--) bs->buf[bs->buf_size - minimum + i] = bs->buf[i]; bs->buf_byte_idx = bs->buf_size -1 - minimum; bs->buf_bit_idx = 8; } /* open the device to write the bit stream into it */ void open_bit_stream_w(bs, bs_filenam, size) Bit_stream_struc *bs; /* bit stream structure */ char *bs_filenam; /* name of the bit stream file */ int size; /* size of the buffer */ { if ( strcmp(bs_filenam, "-" ) == 0 ) { bs->pt = stdout; } else if ((bs->pt = fopen(bs_filenam, "wb")) == NULL) { fprintf(stderr,"Could not create \"%s\".\n", bs_filenam); exit(1); } alloc_buffer(bs, size); bs->buf_byte_idx = size-1; bs->buf_bit_idx=8; bs->totbit=0; bs->mode = WRITE_MODE; bs->eob = FALSE; bs->eobs = FALSE; } /* open the device to read the bit stream from it */ void open_bit_stream_r(bs, bs_filenam, size) Bit_stream_struc *bs; /* bit stream structure */ char *bs_filenam; /* name of the bit stream file */ int size; /* size of the buffer */ { register unsigned long n; register unsigned char flag = 1; unsigned char val; if ((bs->pt = fopen(bs_filenam, "rb")) == NULL) { printf("Could not find \"%s\".\n", bs_filenam); exit(1); } do { n = fread(&val, sizeof(unsigned char), 1, bs->pt); switch (val) { case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0xa: /* \n */ case 0xd: /* cr */ case 0x1a: /* sub */ break; default: /* detection of an binary character */ flag--; break; } } while (flag & n); if (flag) { printf ("the bit stream file %s is an ASCII file\n", bs_filenam); bs->format = ASCII; } else { bs->format = BINARY; printf ("the bit stream file %s is a BINARY file\n", bs_filenam); } fclose(bs->pt); if ((bs->pt = fopen(bs_filenam, "rb")) == NULL) { printf("Could not find \"%s\".\n", bs_filenam); exit(1); } alloc_buffer(bs, size); bs->buf_byte_idx=0; bs->buf_bit_idx=0; bs->totbit=0; bs->mode = READ_MODE; bs->eob = FALSE; bs->eobs = FALSE; } /*close the device containing the bit stream after a read process*/ void close_bit_stream_r(bs) Bit_stream_struc *bs; /* bit stream structure */ { fclose(bs->pt); desalloc_buffer(bs); } /*close the device containing the bit stream after a write process*/ void close_bit_stream_w(bs) Bit_stream_struc *bs; /* bit stream structure */ { putbits(bs, 0, 7); empty_buffer(bs, bs->buf_byte_idx + 1); fclose(bs->pt); desalloc_buffer(bs); } /*open and initialize the buffer; */ void alloc_buffer(bs, size) Bit_stream_struc *bs; /* bit stream structure */ int size; { bs->buf = (unsigned char *) mem_alloc(size*sizeof(unsigned char), "buffer"); bs->buf_size = size; } /*empty and close the buffer */ void desalloc_buffer(bs) Bit_stream_struc *bs; /* bit stream structure */ { free(bs->buf); } int putmask[9]={0x0, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff}; int clearmask[9]={0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x0}; void back_track_buffer(bs, N) /* goes back N bits in the buffer */ Bit_stream_struc *bs; /* bit stream structure */ int N; { int tmp = N - (N/8)*8; register int i; bs->totbit -= N; for (i=bs->buf_byte_idx;i< bs->buf_byte_idx+N/8-1;i++) bs->buf[i] = 0; bs->buf_byte_idx += N/8; if ( (tmp + bs->buf_bit_idx) <= 8) { bs->buf_bit_idx += tmp; } else { bs->buf_byte_idx ++; bs->buf_bit_idx += (tmp - 8); } bs->buf[bs->buf_byte_idx] &= clearmask[bs->buf_bit_idx]; } int mask[8]={0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80}; /*read 1 bit from the bit stream */ unsigned int get1bit(bs) Bit_stream_struc *bs; /* bit stream structure */ { unsigned int bit; register int i; bs->totbit++; if (!bs->buf_bit_idx) { bs->buf_bit_idx = 8; bs->buf_byte_idx--; if ((bs->buf_byte_idx < MINIMUM) || (bs->buf_byte_idx < bs->eob)) { if (bs->eob) bs->eobs = TRUE; else { for (i=bs->buf_byte_idx; i>=0;i--) bs->buf[bs->buf_size-1-bs->buf_byte_idx+i] = bs->buf[i]; refill_buffer(bs); bs->buf_byte_idx = bs->buf_size-1; } } } bit = bs->buf[bs->buf_byte_idx]&mask[bs->buf_bit_idx-1]; bit = bit >> (bs->buf_bit_idx-1); bs->buf_bit_idx--; return(bit); } /*write 1 bit from the bit stream */ void put1bit(bs, bit) Bit_stream_struc *bs; /* bit stream structure */ int bit; /* bit to write into the buffer */ { bs->totbit++; bs->buf[bs->buf_byte_idx] |= (bit&0x1) << (bs->buf_bit_idx-1); bs->buf_bit_idx--; if (!bs->buf_bit_idx) { bs->buf_bit_idx = 8; bs->buf_byte_idx--; if (bs->buf_byte_idx < 0) empty_buffer(bs, MINIMUM); bs->buf[bs->buf_byte_idx] = 0; } } /*look ahead for the next N bits from the bit stream */ unsigned long look_ahead(bs, N) Bit_stream_struc *bs; /* bit stream structure */ int N; /* number of bits to read from the bit stream */ { unsigned long val=0; register int j = N; register int k, tmp; register int bit_idx = bs->buf_bit_idx; register int byte_idx = bs->buf_byte_idx; if (N > MAX_LENGTH) printf("Cannot read or write more than %d bits at a time.\n", MAX_LENGTH); while (j > 0) { if (!bit_idx) { bit_idx = 8; byte_idx--; } k = MIN (j, bit_idx); tmp = bs->buf[byte_idx]&putmask[bit_idx]; tmp = tmp >> (bit_idx-k); val |= tmp << (j-k); bit_idx -= k; j -= k; } return(val); } /*read N bit from the bit stream */ unsigned long getbits(bs, N) Bit_stream_struc *bs; /* bit stream structure */ int N; /* number of bits to read from the bit stream */ { unsigned long val=0; register int i; register int j = N; register int k, tmp; if (N > MAX_LENGTH) printf("Cannot read or write more than %d bits at a time.\n", MAX_LENGTH); bs->totbit += N; while (j > 0) { if (!bs->buf_bit_idx) { bs->buf_bit_idx = 8; bs->buf_byte_idx--; if ((bs->buf_byte_idx < MINIMUM) || (bs->buf_byte_idx < bs->eob)) { if (bs->eob) bs->eobs = TRUE; else { for (i=bs->buf_byte_idx; i>=0;i--) bs->buf[bs->buf_size-1-bs->buf_byte_idx+i] = bs->buf[i]; refill_buffer(bs); bs->buf_byte_idx = bs->buf_size-1; } } } k = MIN (j, bs->buf_bit_idx); tmp = bs->buf[bs->buf_byte_idx]&putmask[bs->buf_bit_idx]; tmp = tmp >> (bs->buf_bit_idx-k); val |= tmp << (j-k); bs->buf_bit_idx -= k; j -= k; } return(val); } /*write N bits into the bit stream */ void putbits(bs, val, N) Bit_stream_struc *bs; /* bit stream structure */ unsigned int val; /* val to write into the buffer */ int N; /* number of bits of val */ { register int j = N; register int k, tmp; if (N > MAX_LENGTH) printf("Cannot read or write more than %d bits at a time.\n", MAX_LENGTH); bs->totbit += N; while (j > 0) { k = MIN(j, bs->buf_bit_idx); tmp = val >> (j-k); bs->buf[bs->buf_byte_idx] |= (tmp&putmask[k]) << (bs->buf_bit_idx-k); bs->buf_bit_idx -= k; if (!bs->buf_bit_idx) { bs->buf_bit_idx = 8; bs->buf_byte_idx--; if (bs->buf_byte_idx < 0) empty_buffer(bs, MINIMUM); bs->buf[bs->buf_byte_idx] = 0; } j -= k; } } /*write N bits byte aligned into the bit stream */ void byte_ali_putbits(bs, val, N) Bit_stream_struc *bs; /* bit stream structure */ unsigned int val; /* val to write into the buffer */ int N; /* number of bits of val */ { unsigned long aligning; if (N > MAX_LENGTH) printf("Cannot read or write more than %d bits at a time.\n", MAX_LENGTH); aligning = sstell(bs)%8; if (aligning) putbits(bs, (unsigned int)0, (int)(8-aligning)); putbits(bs, val, N); } /*read the next bute aligned N bits from the bit stream */ unsigned long byte_ali_getbits(bs, N) Bit_stream_struc *bs; /* bit stream structure */ int N; /* number of bits of val */ { unsigned long aligning; if (N > MAX_LENGTH) printf("Cannot read or write more than %d bits at a time.\n", MAX_LENGTH); aligning = sstell(bs)%8; if (aligning) getbits(bs, (int)(8-aligning)); return(getbits(bs, N)); } /*return the current bit stream length (in bits)*/ unsigned long sstell(bs) Bit_stream_struc *bs; /* bit stream structure */ { return(bs->totbit); } /*return the status of the bit stream*/ /* returns 1 if end of bit stream was reached */ /* returns 0 if end of bit stream was not reached */ int end_bs(bs) Bit_stream_struc *bs; /* bit stream structure */ { return(bs->eobs); } /*this function seeks for a byte aligned sync word in the bit stream and places the bit stream pointer right after the sync. This function returns 1 if the sync was found otherwise it returns 0 */ int seek_sync(bs, sync, N) Bit_stream_struc *bs; /* bit stream structure */ long sync; /* sync word maximum 32 bits */ int N; /* sync word length */ { unsigned long aligning; unsigned long val; long maxi = (int)pow(2.0, (FLOAT)N) - 1; aligning = sstell(bs)%ALIGNING; if (aligning) getbits(bs, (int)(ALIGNING-aligning)); val = getbits(bs, N); while (((val&maxi) != sync) && (!end_bs(bs))) { val <<= ALIGNING; val |= getbits(bs, ALIGNING); } if (end_bs(bs)) return(0); else return(1); } /* * CRC error protection package */ void I_CRC_calc(fr_ps, bit_alloc, crc) frame_params *fr_ps; unsigned int bit_alloc[2][SBLIMIT]; unsigned int *crc; { int i, k; layer *info = fr_ps->header; int stereo = fr_ps->stereo; int jsbound = fr_ps->jsbound; *crc = 0xffff; /* changed from '0' 92-08-11 shn */ update_CRC(info->bitrate_index, 4, crc); update_CRC(info->sampling_frequency, 2, crc); update_CRC(info->padding, 1, crc); update_CRC(info->extension, 1, crc); update_CRC(info->mode, 2, crc); update_CRC(info->mode_ext, 2, crc); update_CRC(info->copyright, 1, crc); update_CRC(info->original, 1, crc); update_CRC(info->emphasis, 2, crc); for (i=0;iheader; int stereo = fr_ps->stereo; int sblimit = fr_ps->sblimit; int jsbound = fr_ps->jsbound; al_table *alloc = fr_ps->alloc; *crc = 0xffff; /* changed from '0' 92-08-11 shn */ update_CRC(info->bitrate_index, 4, crc); update_CRC(info->sampling_frequency, 2, crc); update_CRC(info->padding, 1, crc); update_CRC(info->extension, 1, crc); update_CRC(info->mode, 2, crc); update_CRC(info->mode_ext, 2, crc); update_CRC(info->copyright, 1, crc); update_CRC(info->original, 1, crc); update_CRC(info->emphasis, 2, crc); for (i=0;i>= 1)){ carry = *crc & 0x8000; *crc <<= 1; if (!carry ^ !(data & masking)) *crc ^= CRC16_POLYNOMIAL; } *crc &= 0xffff; } mjpegtools-2.1.0/aenc/table_cb.h0000644000175000017500000000110607133030460017015 0ustar glowwormglowwormstatic int cb_len[6] = { 25, 26, 24, 27, 27, 25 }; static int cb_tab[6][27] = { {1,2,3,5,6,8,9,11,13,15,17,20,23,27,32,37,45,52,62,74,88,108,132,180,232,0,0}, {1,2,3,4,5,6,7,9,10,12,14,16,19,21,25,29,35,41,50,58,68,82,100,124,164,216,0}, {1,3,5,7,9,11,13,15,18,21,24,27,32,37,44,52,62,74,88,104,124,148,184,240,0,0,0}, {1,2,3,5,7,10,13,16,19,22,26,30,35,40,46,54,64,76,90,104,124,148,176,216,264,360,464}, {1,2,3,5,7,9,12,14,17,20,24,27,32,37,42,50,58,70,82,100,116,136,164,200,248,328,432}, {1,3,6,10,13,17,21,25,30,35,41,47,54,64,74,88,104,124,148,176,208,248,296,368,480,0,0}}; mjpegtools-2.1.0/aenc/Makefile.am0000644000175000017500000000106210254331121017142 0ustar glowwormglowworm# Process this file with automake to produce Makefile.in MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I $(top_srcdir) -I $(top_srcdir)/utils bin_PROGRAMS = mp2enc mp2enc_SOURCES = \ common.c \ encode.c \ fft.c \ musicin.c \ psy.c \ tables.c \ tonal.c \ wav_io.c noinst_HEADERS = \ common.h \ encoder.h \ table_absthr.h \ table_alloc.h \ table_cb.h \ table_enwindow.h \ table_th.h \ wav_io.h mp2enc_LDADD = $(top_builddir)/utils/libmjpegutils.la $(LIBM_LIBS) if HAVE_ALTIVEC mp2enc_LDADD += $(top_builddir)/mpeg2enc/libmpeg2encpp.la endif mjpegtools-2.1.0/aenc/wav_io.c0000644000175000017500000000726307543667642016602 0ustar glowwormglowworm/* wav_io: Utilities for dealing with WAV files This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "mjpeg_logging.h" #include "wav_io.h" /* wav_read_header: Read and analyze the header of a WAV file. The file must be positioned at start before the call The file is positioned at the start of the audio data after the call. This program is written so that it can be used on big and little endian machines and that it can be used on a pipe (no seeks) returns 0 on success, -1 on error */ static int hdr_len = 0; static uint32_t getulong(uint8_t *data) { /* Interprets data as a little endian number */ return (data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24)); } static int32_t find_tag(FILE *fd, const char *tag) { uint8_t data[8]; uint32_t m; int n; /* scan input stream for specified tag and return its length */ /* returns -1 in case of error */ while(1) { n = fread(data,1,8,fd); if(n!=8) goto error; hdr_len += 8; m = getulong(data+4); if(!strncasecmp((char*)data,tag,4)) return m; for(n=0;n>16) & 0xffff; *rate = getulong(data+4); /* nSamplesPerSec */ m = getulong(data+8); /* nAvgBytesPerSec */ m = getulong(data+12); /* nBlockAlign + wBitsPerSample */ *bits = (m>>16) & 0xffff; /* skip over remaining bytes in format (if any) */ for(n=16;nmode and info->mode_ext * * updates for AIFF format files * * 3/10/93 Kevin Peterson In parse_args, only set non default * * bit rate if specified in arg list. * * Use return value from aiff_read_hdrs * * to fseek to start of sound data * * 7/26/93 Davis Pan fixed bug in printing info->mode_ext * * value for joint stereo condition * * 8/27/93 Seymour Shlien, Fixes in Unix and MSDOS ports, * * Daniel Lauzon, and * * Bill Truerniet * * 2004/7/29 Steven Schultz Cleanup and fix the pathname limit * * once and for all. * * 2004/8/22 Steven Schultz Make the code agree with the manpage * * The manpage says that -V _forces_ VCD * * compatible mode. Also, the VCD 2.0 * * specification permits 128, 192 and * * 384 kbit/sec rates for stereo (or dual* * mono) and 64,96 or 192 kbit/sec for * * mono mode. Since VCD2.0 came out in * * 1995 I think it's time to update this * * program ;) * * Make the default sampling rate 48000 * * if -V is NOT used - this will avoid * * problems with folks encoding for DVDs.* **********************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "common.h" #include "encoder.h" #include "wav_io.h" /* Global variable definitions for "musicin.c" */ FILE *musicin; Bit_stream_struc bs; int verbose = 1; char *programName; /* Global variables */ int freq_in=0; int freq_out=48000; int chans_in=0; int chans_out=0; int audio_bits=0; int32_t audio_bytes=0; int raw_in=0; static void Usage(char *str) { printf("Usage: %s [params] < input.wav\n",str); printf(" where possible params are:\n"); printf( " -v num Level of verbosity. 0 = quiet, 1 = normal 2 = verbose/debug\n"); printf(" -b num Bitrate in KBit/sec (default: 224 KBit/s)\n"); printf(" -l num Layer number 1 or 2 (default: 2)\n"); printf(" -o name Outputfile name (REQUIRED)\n"); printf(" -r num Force output sampling rate to be num Hz (default: 48000)\n"); printf(" num must be one of 32000, 44100, 48000\n"); printf(" -s Force stereo output (default)\n"); printf(" -m Force mono output\n"); printf(" -R rate,chans,bits Input are raw samples without a wav header. rate is the\n"); printf(" samplerate of the input, chans is the number of channels,\n"); printf(" bits are the bits per sample (can be 8 or 16). All 3 numbers\n"); printf(" MUST be given\n"); printf(" -e Use CRC error protection\n"); printf(" -V Force VCD sampling rate (-r 44100) and perform bitrate/channel validity checks\n"); printf(" -? Print this lot out\n"); exit(0); } static void get_params(argc, argv,fr_ps,psy,num_samples,encoded_file_name) int argc; char** argv; frame_params *fr_ps; int *psy; unsigned long *num_samples; char **encoded_file_name; { char * pos, *end; layer *info = fr_ps->header; int brt=224; char *outfilename = 0; int stereo = 1; int mono = 0; int video_cd = 0; int j, n; int audio_format; /* RJ: We set most params to fixed defaults: */ info->lay = 2; info->emphasis = 0; info->extension = 0; info->error_protection = 0; info->copyright = 0; info->original = 0; info->mode_ext = 0; *psy = 2; *num_samples = MAX_U_32_NUM; /* Unlimited */ while( (n=getopt(argc,argv,"b:o:l:r:R:smeVv:")) != EOF) { switch(n) { case 'b': brt = atoi(optarg); break; case 'o': outfilename = optarg; break; case 'r': freq_out = atoi(optarg); if (freq_out!=32000 && freq_out!=44100 && freq_out!=48000) mjpeg_error_exit1("-r requires one of 32000 44100 48000!"); break; case 'R': pos = optarg; /* Frequency */ freq_in = strtol(pos, &end, 10); if(pos == end) mjpeg_error_exit1("-R requires rate,chans,bits!"); pos = end; if(*pos != ',') mjpeg_error_exit1("-R requires rate,chans,bits!"); pos++; /* Channels */ chans_in = strtol(pos, &end, 10); if(pos == end) mjpeg_error_exit1("-R requires rate,chans,bits!"); pos = end; if(*pos != ',') mjpeg_error_exit1("-R requires rate,chans,bits!"); pos++; /* Bits */ audio_bits = strtol(pos, &end, 10); if(pos == end) mjpeg_error_exit1("-R requires rate,chans,bits!"); raw_in = 1; break; case 'l': info->lay = atoi(optarg); if (info->lay!=2 && info->lay!=1) mjpeg_error_exit1("-l requires 1 or 2!"); break; case 's': stereo = 1; mono = 0; chans_out = 2; break; case 'm': mono = 1; stereo = 0; chans_out = 1; break; case 'e': info->error_protection = 1; break; case 'V': video_cd = 1; break; case 'v': verbose = atoi(optarg); if( verbose < 0 || verbose > 2 ) Usage(argv[0]); break; case '?': Usage(argv[0]); } } (void)mjpeg_default_handler_verbosity(verbose); if(argc!=optind) Usage(argv[0]); if(outfilename==0) { mjpeg_error("Output file name (-o option) is required!"); Usage(argv[0]); } *encoded_file_name = strdup(outfilename); if (*encoded_file_name == NULL) mjpeg_error_exit1("can not malloc %d bytes", strlen(outfilename)); /* Read the WAV file header, make sanity checks */ if(!raw_in) { if(wav_read_header(stdin,&freq_in,&chans_in,&audio_bits, &audio_format,&audio_bytes)) mjpeg_error_exit1("failure reading WAV file"); mjpeg_info("Opened WAV file, freq = %d Hz, channels = %d, bits = %d", freq_in, chans_in, audio_bits); mjpeg_info("format = 0x%x, audio length = %d bytes",audio_format,audio_bytes); if(audio_format!=1) mjpeg_error_exit1("WAV file is not in PCM format"); } else { mjpeg_info("Raw PCM input, freq = %d Hz, channels = %d, bits = %d", freq_in, chans_in, audio_bits); } if(audio_bits!=8 && audio_bits!=16) mjpeg_error_exit1("audio samples must have 8 or 16 bits"); if(chans_in!=1 && chans_in!=2) mjpeg_error_exit1("can only handle files with 1 or 2 channels"); if(chans_out==0) chans_out = chans_in; if(chans_out==1) info->mode = MPG_MD_MONO; else info->mode = MPG_MD_STEREO; if(video_cd && info->lay != 2 ) mjpeg_error_exit1("Option -V requires layer II!"); if (video_cd) { freq_out=44100; if (chans_out == 2) { switch (brt) { case 128: case 192: case 224: case 384: break; default: mjpeg_error_exit1("-b %d not valid with stereo. Bitrate must be 128, 192, 224 or 384", brt); } } else if (chans_out == 1) { switch (brt) { case 64: case 96: case 192: break; default: mjpeg_error_exit1("-b %d not valid with mono. Bitrate must be 64, 96 or 192", brt); } } } if(freq_out==0) freq_out = freq_in; switch (freq_out) { case 48000 : info->sampling_frequency = 1; break; case 44100 : info->sampling_frequency = 0; break; case 32000 : info->sampling_frequency = 2; break; default: mjpeg_error_exit1("Frequency must be one of 32000 44100 48000" " unless -r is used!"); } *num_samples = audio_bytes/(audio_bits/8); if (brt==0) { if (info->lay==2) brt = (info->mode == MPG_MD_MONO) ? 112 : 224; else brt = (info->mode == MPG_MD_MONO) ? 192 : 384; } for(j=0;j<15;j++) if (bitrate[info->lay-1][j] == brt) break; if (j==15) mjpeg_error_exit1("Bitrate of %d KBit/s not allowed!",brt); info->bitrate_index = j; if(info->lay==2 && brt>192 && info->mode==MPG_MD_MONO) mjpeg_error_exit1("Bitrate of %d KBit/s not allowed for MONO",brt); open_bit_stream_w(&bs, *encoded_file_name, BUFFER_SIZE); } /* * print_config * * PURPOSE: Prints the encoding parameters used */ void print_config(fr_ps, psy, num_samples, outPath) frame_params *fr_ps; int *psy; unsigned long *num_samples; char *outPath; { layer *info = fr_ps->header; mjpeg_debug("Encoding configuration:"); if(info->mode != MPG_MD_JOINT_STEREO) mjpeg_debug("Layer=%s mode=%s extn=%d psy model=%d", layer_names[info->lay-1], mode_names[info->mode], info->mode_ext, *psy); else mjpeg_debug("Layer=%s mode=%s extn=data dependant psy model=%d", layer_names[info->lay-1], mode_names[info->mode], *psy); mjpeg_debug("samp frq=%.1f kHz total bitrate=%d kbps", s_freq[info->sampling_frequency], bitrate[info->lay-1][info->bitrate_index]); mjpeg_debug("de-emph=%d c/right=%d orig=%d errprot=%d", info->emphasis, info->copyright, info->original, info->error_protection); mjpeg_debug("output file: '%s'", outPath); } /* * main * * PURPOSE: MPEG I Encoder supporting layers 1 and 2, and * psychoacoustic models 1 (MUSICAM) and 2 (AT&T) * * SEMANTICS: One overlapping frame of audio of up to 2 channels are * processed at a time in the following order: * (associated routines are in parentheses) * * 1. Filter sliding window of data to get 32 subband * samples per channel. * (window_subband,filter_subband) * * 2. If joint stereo mode, combine left and right channels * for subbands above #jsbound#. * (*_combine_LR) * * 3. Calculate scalefactors for the frame, and if layer 2, * also calculate scalefactor select information. * (*_scale_factor_calc) * * 4. Calculate psychoacoustic masking levels using selected * psychoacoustic model. * (*_Psycho_One, psycho_anal) * * 5. Perform iterative bit allocation for subbands with low * mask_to_noise ratios using masking levels from step 4. * (*_main_bit_allocation) * * 6. If error protection flag is active, add redundancy for * error protection. * (*_CRC_calc) * * 7. Pack bit allocation, scalefactors, and scalefactor select * information (layer 2) onto bitstream. * (*_encode_bit_alloc,*_encode_scale,II_transmission_pattern) * * 8. Quantize subbands and pack them into bitstream * (*_subband_quantization, *_sample_encoding) */ int main(argc, argv) int argc; char **argv; { typedef double SBS[2][3][SCALE_BLOCK][SBLIMIT]; SBS *sb_sample; typedef double JSBS[3][SCALE_BLOCK][SBLIMIT]; JSBS *j_sample; typedef double IN[2][HAN_SIZE]; IN *win_que; typedef unsigned int SUB[2][3][SCALE_BLOCK][SBLIMIT]; SUB *subband; frame_params fr_ps; layer info; char *encoded_file_name; short **win_buf; static short buffer[2][1152]; static unsigned int bit_alloc[2][SBLIMIT], scfsi[2][SBLIMIT]; static unsigned int scalar[2][3][SBLIMIT], j_scale[3][SBLIMIT]; static double ltmin[2][SBLIMIT], lgmin[2][SBLIMIT], max_sc[2][SBLIMIT]; FLOAT snr32[32]; short sam[2][1056]; int whole_SpF, extra_slot = 0; double avg_slots_per_frame, frac_SpF, slot_lag; int model, stereo, error_protection; static unsigned int crc; int i, j, k, adb; unsigned long bitsPerSlot, samplesPerFrame, frameNum = 0; unsigned long frameBits, sentBits = 0; unsigned long num_samples; /* Most large variables are declared dynamically to ensure compatibility with smaller machines */ sb_sample = (SBS *) mem_alloc(sizeof(SBS), "sb_sample"); j_sample = (JSBS *) mem_alloc(sizeof(JSBS), "j_sample"); win_que = (IN *) mem_alloc(sizeof(IN), "Win_que"); subband = (SUB *) mem_alloc(sizeof(SUB),"subband"); win_buf = (short **) mem_alloc(sizeof(short *)*2, "win_buf"); /* clear buffers */ memset((char *) buffer, 0, sizeof(buffer)); memset((char *) bit_alloc, 0, sizeof(bit_alloc)); memset((char *) scalar, 0, sizeof(scalar)); memset((char *) j_scale, 0, sizeof(j_scale)); memset((char *) scfsi, 0, sizeof(scfsi)); memset((char *) ltmin, 0, sizeof(ltmin)); memset((char *) lgmin, 0, sizeof(lgmin)); memset((char *) max_sc, 0, sizeof(max_sc)); memset((char *) snr32, 0, sizeof(snr32)); memset((char *) sam, 0, sizeof(sam)); fr_ps.header = &info; fr_ps.tab_num = -1; /* no table loaded */ fr_ps.alloc = NULL; info.version = MPEG_AUDIO_ID; programName = argv[0]; get_params(argc, argv, &fr_ps, &model, &num_samples, &encoded_file_name); print_config(&fr_ps, &model, &num_samples, encoded_file_name); hdr_to_frps(&fr_ps); stereo = fr_ps.stereo; error_protection = info.error_protection; if (info.lay == 1) { bitsPerSlot = 32; samplesPerFrame = 384; } else { bitsPerSlot = 8; samplesPerFrame = 1152; } /* Figure average number of 'slots' per frame. */ /* Bitrate means TOTAL for both channels, not per side. */ avg_slots_per_frame = ((double)samplesPerFrame / s_freq[info.sampling_frequency]) * ((double)bitrate[info.lay-1][info.bitrate_index] / (double)bitsPerSlot); whole_SpF = (int) avg_slots_per_frame; frac_SpF = avg_slots_per_frame - (double)whole_SpF; slot_lag = -frac_SpF; mjpeg_info("SpF=%d, frac SpF=%.3f, bitrate=%d kbps, sfreq=%.1f kHz", whole_SpF, frac_SpF, bitrate[info.lay-1][info.bitrate_index], s_freq[info.sampling_frequency]); if (frac_SpF != 0) mjpeg_info("Fractional number of slots, padding required"); else info.padding = 0; while (get_audio(musicin, buffer, num_samples, stereo, info.lay) != 0) { frameNum++; win_buf[0] = &buffer[0][0]; win_buf[1] = &buffer[1][0]; if (frac_SpF != 0) { if (slot_lag > (frac_SpF-1.0) ) { slot_lag -= frac_SpF; extra_slot = 0; info.padding = 0; } else { extra_slot = 1; info.padding = 1; slot_lag += (1-frac_SpF); } } adb = (whole_SpF+extra_slot) * bitsPerSlot; switch (info.lay) { /***************************** Layer I **********************************/ case 1 : for (j=0;j> 1; w_r[L] = cos(PI/le1); w_i[L] = -sin(PI/le1); } for(i=0;i>j) & 1; l |= (k<<(9-j)); } init = 1; } memcpy( (char *) x_r, (char *) sample, sizeof(double) * FFT_SIZE); for(L=0;L> 1; u_r = 1; u_i = 0; for(j=0;j>4] = max, i+=16) /* calculate the */ for(j=0, max = DBMIN;j<16;j++) /* maximum spectral */ max = (max>power[i+j].x) ? max : power[i+j].x; /* component in each */ } /* subband from bound */ /* 4-16 */ #else void II_pick_max(power, spike) double spike[SBLIMIT]; mask power[HAN_SIZE]; { double sum; int i,j; for(i=0;i>4] = 10.0*log10(sum), i+=16) /* calculate the */ for(j=0, sum = pow(10.0,0.1*DBMIN);j<16;j++) /* sum of spectral */ sum += pow(10.0,0.1*power[i+j].x); /* component in each */ } /* subband from bound */ /* 4-16 */ #endif /* * This function labels the tonal component in the power spectrum. */ void II_tonal_label(power, tone) /* this function extracts (tonal) */ mask power[HAN_SIZE]; /* sinusoidals from the spectrum */ int *tone; { int i,j, last = LAST, first, run, last_but_one = LAST; /* dpwe */ double max; *tone = LAST; for(i=2;ipower[i-1].x && power[i].x>=power[i+1].x){ power[i].type = TONE; power[i].next = LAST; if(last != LAST) power[last].next = i; else first = *tone = i; last = i; } } last = LAST; first = *tone; *tone = LAST; while(first != LAST){ /* the conditions for the tonal */ if(first<3 || first>500) run = 0;/* otherwise k+/-j will be out of bounds */ else if(first<63) run = 2; /* components in layer II, which */ else if(first<127) run = 3; /* are the boundaries for calc. */ else if(first<255) run = 6; /* the tonal components */ else run = 12; max = power[first].x - 7; /* after calculation of tonal */ for(j=2;j<=run;j++) /* components, set to local max */ if(max < power[first-j].x || max < power[first+j].x){ power[first].type = FALSE; break; } if(power[first].type == TONE){ /* extract tonal components */ int help=first; if(*tone==LAST) *tone = first; while((power[help].next!=LAST)&&(power[help].next-first)<=run) help=power[help].next; help=power[help].next; power[first].next=help; if((first-last)<=run){ if(last_but_one != LAST) power[last_but_one].next=first; } if(first>1 && first<500){ /* calculate the sum of the */ double tmp; /* powers of the components */ tmp = add_db(power[first-1].x, power[first+1].x); power[first].x = add_db(power[first].x, tmp); } for(j=1;j<=run;j++){ power[first-j].x = power[first+j].x = DBMIN; power[first-j].next = power[first+j].next = STOP; power[first-j].type = power[first+j].type = FALSE; } last_but_one=last; last = first; first = power[first].next; } else { int ll; if(last == LAST); /* *tone = power[first].next; dpwe */ else power[last].next = power[first].next; ll = first; first = power[first].next; power[ll].next = STOP; } } } /* * This function groups all the remaining non-tonal * spectral lines into critical band where they are replaced by * one single line. */ void noise_label(power, noise, ltg) g_thres *ltg; mask *power; int *noise; { int i,j, centre, last = LAST; double index, weight, sum; /* calculate the remaining spectral */ for(i=0;i= ltg[power[i].map].hear){ if(sum >= ltg[power[i].map].hear) sum = add_db(power[j].x,sum); else sum = power[centre].x; } } #endif if(last == LAST) *noise = centre; else { power[centre].next = LAST; power[last].next = centre; } power[centre].x = sum; power[centre].type = NOISE; last = centre; } } /* * This function reduces the number of noise and tonal * component for further threshold analysis. */ void subsampling(power, ltg, tone, noise) mask power[HAN_SIZE]; g_thres *ltg; int *tone, *noise; { int i, old; i = *tone; old = STOP; /* calculate tonal components for */ while(i!=LAST){ /* reduction of spectral lines */ if(power[i].x < ltg[power[i].map].hear){ power[i].type = FALSE; power[i].x = DBMIN; if(old == STOP) *tone = power[i].next; else power[old].next = power[i].next; } else old = i; i = power[i].next; } i = *noise; old = STOP; /* calculate non-tonal components for */ while(i!=LAST){ /* reduction of spectral lines */ if(power[i].x < ltg[power[i].map].hear){ power[i].type = FALSE; power[i].x = DBMIN; if(old == STOP) *noise = power[i].next; else power[old].next = power[i].next; } else old = i; i = power[i].next; } i = *tone; old = STOP; while(i != LAST){ /* if more than one */ if(power[i].next == LAST)break; /* tonal component */ if(ltg[power[power[i].next].map].bark - /* is less than .5 */ ltg[power[i].map].bark < 0.5) { /* bark, take the */ if(power[power[i].next].x > power[i].x ){/* maximum */ if(old == STOP) *tone = power[i].next; else power[old].next = power[i].next; power[i].type = FALSE; power[i].x = DBMIN; i = power[i].next; } else { power[power[i].next].type = FALSE; power[power[i].next].x = DBMIN; power[i].next = power[power[i].next].next; old = i; } } else { old = i; i = power[i].next; } } } /* * This function calculates the individual threshold and * sum with the quiet threshold to find the global threshold. */ void threshold(power, ltg, tone, noise, bit_rate) mask power[HAN_SIZE]; g_thres *ltg; int *tone, *noise, bit_rate; { int k, t; double dz, tmps, vf; vf = 0.0; /* Suppress compiler warning */ for(k=1;k= -3.0 && /*threshold (LTG)*/ ltg[k].bark-ltg[power[t].map].bark <8.0){ dz = ltg[k].bark-ltg[power[t].map].bark; /* distance of bark value*/ tmps = -1.525-0.275*ltg[power[t].map].bark - 4.5 + power[t].x; /* masking function for lower & upper slopes */ if(-3<=dz && dz<-1) vf = 17*(dz+1)-(0.4*power[t].x +6); else if(-1<=dz && dz<0) vf = (0.4 *power[t].x + 6) * dz; else if(0<=dz && dz<1) vf = (-17*dz); else if(1<=dz && dz<8) vf = -(dz-1) * (17-0.15 *power[t].x) - 17; tmps += vf; ltg[k].x = add_db(ltg[k].x, tmps); } t = power[t].next; } t = *noise; /* calculate individual masking threshold */ while(t != LAST){ /* for non-tonal components to find LTG */ if(ltg[k].bark-ltg[power[t].map].bark >= -3.0 && ltg[k].bark-ltg[power[t].map].bark <8.0){ dz = ltg[k].bark-ltg[power[t].map].bark; /* distance of bark value */ tmps = -1.525-0.175*ltg[power[t].map].bark -0.5 + power[t].x; /* masking function for lower & upper slopes */ if(-3<=dz && dz<-1) vf = 17*(dz+1)-(0.4*power[t].x +6); else if(-1<=dz && dz<0) vf = (0.4 *power[t].x + 6) * dz; else if(0<=dz && dz<1) vf = (-17*dz); else if(1<=dz && dz<8) vf = -(dz-1) * (17-0.15 *power[t].x) - 17; tmps += vf; ltg[k].x = add_db(ltg[k].x, tmps); } t = power[t].next; } if(bit_rate<96)ltg[k].x = add_db(ltg[k].hear, ltg[k].x); else ltg[k].x = add_db(ltg[k].hear-12.0, ltg[k].x); } } /* * This function finds the minimum masking threshold and * return the value to the encoder. */ void II_minimum_mask(ltg,ltmin,sblimit) g_thres *ltg; double ltmin[SBLIMIT]; int sblimit; { double min; int i,j; j=1; for(i=0;i=sub_size-1) /* check subband limit, and */ ltmin[i] = ltg[sub_size-1].hear; /* calculate the minimum masking */ else { /* level of LTMIN for each subband*/ min = ltg[j].x; while(ltg[j].line>>4 == i && j < sub_size){ if(min>ltg[j].x) min = ltg[j].x; j++; } ltmin[i] = min; } } /* * This procedure is called in musicin to pick out the * smaller of the scalefactor or threshold. */ void II_smr(ltmin, spike, scale, sblimit) double spike[SBLIMIT], scale[SBLIMIT], ltmin[SBLIMIT]; int sblimit; { int i; double max; for(i=0;imax) max = spike[i]; /* for the maximum scale */ max -= ltmin[i]; /* factors */ ltmin[i] = max; } } /* * This procedure calls all the necessary functions to * complete the psychoacoustic analysis. */ void II_Psycho_One(buffer, scale, ltmin, fr_ps) short buffer[2][1152]; double scale[2][SBLIMIT], ltmin[2][SBLIMIT]; frame_params *fr_ps; { layer *info = fr_ps->header; int stereo = fr_ps->stereo; int sblimit = fr_ps->sblimit; int k,i, tone=0, noise=0; static char init = 0; static int off[2] = {256,256}; static double *sample; static DSBL *spike; static D1408 *fft_buf; static mask_ptr power; static g_ptr ltg; /* call functions for critical boundaries, freq. */ if(!init){ /* bands, bark values, and mapping */ fft_buf = (D1408 *) mem_alloc((long) sizeof(D1408) * 2, "fft_buf"); power = (mask_ptr ) mem_alloc(sizeof(mask) * HAN_SIZE, "power"); sample = (double *) mem_alloc(sizeof(DFFT), "sample"); spike = (DSBL *) mem_alloc(sizeof(D2SBL), "spike"); read_cbound(info->lay,info->sampling_frequency); read_freq_band(<g,info->lay,info->sampling_frequency); make_map(power,ltg); init = 1; } for(k=0;klay-1][info->bitrate_index]/stereo); /*to-mask ratio*/ II_minimum_mask(ltg, <min[k][0], sblimit); II_smr(<min[k][0], &spike[k][0], &scale[k][0], sblimit); } } /* * This module implements the psychoacoustic model I for the * MPEG encoder layer I. It uses simplified tonal and noise masking * threshold analysis to generate SMR for the encoder bit allocation * routine. */ /* * Fast Fourier transform of the input samples. */ void I_f_f_t(sample, power) /* this function calculates */ double sample[FFT_SIZE/2]; /* an FFT analysis for the */ mask power[HAN_SIZE/2]; /* freq. domain */ { int i,j,k,L,l=0; int ip, le, le1; double t_r, t_i, u_r, u_i; static int M, MM1, init = 0, N; static double *x_r, *x_i, *energy; static int *rev; static double *w_r, *w_i; if(!init){ rev = (int *) mem_alloc(sizeof(IFFT2), "rev"); w_r = (double *) mem_alloc(sizeof(D9), "w_r"); w_i = (double *) mem_alloc(sizeof(D9), "w_i"); x_r = (double *) mem_alloc(sizeof(DFFT2), "x_r"); x_i = (double *) mem_alloc(sizeof(DFFT2), "x_i"); energy = (double *) mem_alloc(sizeof(DFFT2), "energy"); M = 9; MM1 = 8; N = FFT_SIZE/2; for(L=0;L> 1; w_r[L] = cos(PI/le1); w_i[L] = -sin(PI/le1); } for(i=0;i>j) & 1; l |= (k<<(8-j)); } init = 1; } memcpy( (char *) x_r, (char *) sample, sizeof(double) * FFT_SIZE/2); for(L=0;L> 1; u_r = 1; u_i = 0; for(j=0;j>3] = max, i+=8) for(j=0, max = DBMIN;j<8;j++) max = (max>power[i+j].x) ? max : power[i+j].x; } #else void I_pick_max(power, spike) double spike[SBLIMIT]; mask power[HAN_SIZE]; { double sum; int i,j; for(i=0;i>3] = 10.0*log10(sum), i+=8) /* calculate the */ for(j=0, sum = pow(10.0,0.1*DBMIN);j<8;j++) /* sum of spectral */ sum += pow(10.0,0.1*power[i+j].x); /* component in each */ } /* subband from bound */ #endif /* * This function labels the tonal component in the power spectrum. */ void I_tonal_label(power, tone) /* this function extracts */ mask power[HAN_SIZE/2]; /* (tonal) sinusoidals from */ int *tone; /* the spectrum */ { int i,j, last = LAST, first, run; double max; int last_but_one= LAST; *tone = LAST; for(i=2;ipower[i-1].x && power[i].x>=power[i+1].x){ power[i].type = TONE; power[i].next = LAST; if(last != LAST) power[last].next = i; else first = *tone = i; last = i; } } last = LAST; first = *tone; *tone = LAST; while(first != LAST){ /* conditions for the tonal */ if(first<3 || first>250) run = 0; /* otherwise k+/-j will be out of bounds*/ else if(first<63) run = 2; /* components in layer I, which */ else if(first<127) run = 3; /* are the boundaries for calc. */ else run = 6; /* the tonal components */ max = power[first].x - 7; for(j=2;j<=run;j++) /* after calc. of tonal components, set to loc.*/ if(max < power[first-j].x || max < power[first+j].x){ /* max */ power[first].type = FALSE; break; } if(power[first].type == TONE){ /* extract tonal components */ int help=first; if(*tone == LAST) *tone = first; while((power[help].next!=LAST)&&(power[help].next-first)<=run) help=power[help].next; help=power[help].next; power[first].next=help; if((first-last)<=run){ if(last_but_one != LAST) power[last_but_one].next=first; } if(first>1 && first<255){ /* calculate the sum of the */ double tmp; /* powers of the components */ tmp = add_db(power[first-1].x, power[first+1].x); power[first].x = add_db(power[first].x, tmp); } for(j=1;j<=run;j++){ power[first-j].x = power[first+j].x = DBMIN; power[first-j].next = power[first+j].next = STOP; /*dpwe: 2nd was .x*/ power[first-j].type = power[first+j].type = FALSE; } last_but_one=last; last = first; first = power[first].next; } else { int ll; if(last == LAST) ; /* *tone = power[first].next; dpwe */ else power[last].next = power[first].next; ll = first; first = power[first].next; power[ll].next = STOP; } } } /* * This function finds the minimum masking threshold and * return the value to the encoder. */ void I_minimum_mask(ltg,ltmin) g_thres *ltg; double ltmin[SBLIMIT]; { double min; int i,j; j=1; for(i=0;i=sub_size-1) /* check subband limit, and */ ltmin[i] = ltg[sub_size-1].hear; /* calculate the minimum masking */ else { /* level of LTMIN for each subband*/ min = ltg[j].x; while(ltg[j].line>>3 == i && j < sub_size){ if (min>ltg[j].x) min = ltg[j].x; j++; } ltmin[i] = min; } } /* * This procedure is called in musicin to pick out the * smaller of the scalefactor or threshold. * */ void I_smr(ltmin, spike, scale) double spike[SBLIMIT], scale[SBLIMIT], ltmin[SBLIMIT]; { int i; double max; for(i=0;imax) max = spike[i]; /* for the scalefactor */ max -= ltmin[i]; ltmin[i] = max; } } /* * This procedure calls all the necessary functions to * complete the psychoacoustic analysis. */ void I_Psycho_One(buffer, scale, ltmin, fr_ps) short buffer[2][1152]; double scale[2][SBLIMIT], ltmin[2][SBLIMIT]; frame_params *fr_ps; { int stereo = fr_ps->stereo; the_layer info = fr_ps->header; int k,i, tone=0, noise=0; static char init = 0; static int off[2] = {256,256}; static double *sample; static DSBL *spike; static D640 *fft_buf; static mask_ptr power; static g_ptr ltg; /* call functions for critical boundaries, freq. */ if(!init){ /* bands, bark values, and mapping */ fft_buf = (D640 *) mem_alloc(sizeof(D640) * 2, "fft_buf"); power = (mask_ptr ) mem_alloc(sizeof(mask) * HAN_SIZE/2, "power"); sample = (double *) mem_alloc(sizeof(DFFT2), "sample"); spike = (DSBL *) mem_alloc(sizeof(D2SBL), "spike"); read_cbound(info->lay,info->sampling_frequency); read_freq_band(<g,info->lay,info->sampling_frequency); make_map(power,ltg); init = 1; } for(k=0;klay-1][info->bitrate_index]/stereo); I_minimum_mask(ltg, <min[k][0]); I_smr(<min[k][0], &spike[k][0], &scale[k][0]); } } mjpegtools-2.1.0/aenc/fft.c0000644000175000017500000003550507771103762016064 0ustar glowwormglowworm/* ** FFT and FHT routines ** Copyright 1988, 1993; Ron Mayer ** ** fht(fz,n); ** Does a hartley transform of "n" points in the array "fz". ** ** NOTE: This routine uses at least 2 patented algorithms, and may be ** under the restrictions of a bunch of different organizations. ** Although I wrote it completely myself; it is kind of a derivative ** of a routine I once authored and released under the GPL, so it ** may fall under the free software foundation's restrictions; ** it was worked on as a Stanford Univ project, so they claim ** some rights to it; it was further optimized at work here, so ** I think this company claims parts of it. The patents are ** held by R. Bracewell (the FHT algorithm) and O. Buneman (the ** trig generator), both at Stanford Univ. ** If it were up to me, I'd say go do whatever you want with it; ** but it would be polite to give credit to the following people ** if you use this anywhere: ** Euler - probable inventor of the fourier transform. ** Gauss - probable inventor of the FFT. ** Hartley - probable inventor of the hartley transform. ** Buneman - for a really cool trig generator ** Mayer(me) - for authoring this particular version and ** including all the optimizations in one package. ** Thanks, ** Ron Mayer; mayer@acuson.com ** */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #define FLOAT float #define SQRT2 1.4142135623730951454746218587388284504414 void fft(FLOAT *x_real, FLOAT *x_imag, FLOAT *energy, FLOAT *phi, int N); void fft2(FLOAT *x_real, FLOAT *energy, int N); static FLOAT costab[20]= { .00000000000000000000000000000000000000000000000000, .70710678118654752440084436210484903928483593768847, .92387953251128675612818318939678828682241662586364, .98078528040323044912618223613423903697393373089333, .99518472667219688624483695310947992157547486872985, .99879545620517239271477160475910069444320361470461, .99969881869620422011576564966617219685006108125772, .99992470183914454092164649119638322435060646880221, .99998117528260114265699043772856771617391725094433, .99999529380957617151158012570011989955298763362218, .99999882345170190992902571017152601904826792288976, .99999970586288221916022821773876567711626389934930, .99999992646571785114473148070738785694820115568892, .99999998161642929380834691540290971450507605124278, .99999999540410731289097193313960614895889430318945, .99999999885102682756267330779455410840053741619428 }; static FLOAT sintab[20]= { 1.0000000000000000000000000000000000000000000000000, .70710678118654752440084436210484903928483593768846, .38268343236508977172845998403039886676134456248561, .19509032201612826784828486847702224092769161775195, .09801714032956060199419556388864184586113667316749, .04906767432741801425495497694268265831474536302574, .02454122852291228803173452945928292506546611923944, .01227153828571992607940826195100321214037231959176, .00613588464915447535964023459037258091705788631738, .00306795676296597627014536549091984251894461021344, .00153398018628476561230369715026407907995486457522, .00076699031874270452693856835794857664314091945205, .00038349518757139558907246168118138126339502603495, .00019174759731070330743990956198900093346887403385, .00009587379909597734587051721097647635118706561284, .00004793689960306688454900399049465887274686668768 }; /* This is a simplified version for n an even power of 2 */ /* MFC: In the case of LayerII encoding, n==1024 always. */ static void fht(FLOAT *fz) { int i,k,k1,k2,k3,k4,kx; FLOAT *fi,*fn,*gi; FLOAT t_c,t_s; FLOAT a; static const struct { unsigned short k1, k2; } k1k2tab[8*62] = { {0x020,0x010},{0x040,0x008},{0x050,0x028},{0x060,0x018},{0x068,0x058},{0x070,0x038},{0x080,0x004},{0x088,0x044}, {0x090,0x024},{0x098,0x064},{0x0a0,0x014},{0x0a4,0x094},{0x0a8,0x054},{0x0b0,0x034},{0x0b8,0x074},{0x0c0,0x00c}, {0x0c4,0x08c},{0x0c8,0x04c},{0x0d0,0x02c},{0x0d4,0x0ac},{0x0d8,0x06c},{0x0e0,0x01c},{0x0e4,0x09c},{0x0e8,0x05c}, {0x0ec,0x0dc},{0x0f0,0x03c},{0x0f4,0x0bc},{0x0f8,0x07c},{0x100,0x002},{0x104,0x082},{0x108,0x042},{0x10c,0x0c2}, {0x110,0x022},{0x114,0x0a2},{0x118,0x062},{0x11c,0x0e2},{0x120,0x012},{0x122,0x112},{0x124,0x092},{0x128,0x052}, {0x12c,0x0d2},{0x130,0x032},{0x134,0x0b2},{0x138,0x072},{0x13c,0x0f2},{0x140,0x00a},{0x142,0x10a},{0x144,0x08a}, {0x148,0x04a},{0x14c,0x0ca},{0x150,0x02a},{0x152,0x12a},{0x154,0x0aa},{0x158,0x06a},{0x15c,0x0ea},{0x160,0x01a}, {0x162,0x11a},{0x164,0x09a},{0x168,0x05a},{0x16a,0x15a},{0x16c,0x0da},{0x170,0x03a},{0x172,0x13a},{0x174,0x0ba}, {0x178,0x07a},{0x17c,0x0fa},{0x180,0x006},{0x182,0x106},{0x184,0x086},{0x188,0x046},{0x18a,0x146},{0x18c,0x0c6}, {0x190,0x026},{0x192,0x126},{0x194,0x0a6},{0x198,0x066},{0x19a,0x166},{0x19c,0x0e6},{0x1a0,0x016},{0x1a2,0x116}, {0x1a4,0x096},{0x1a6,0x196},{0x1a8,0x056},{0x1aa,0x156},{0x1ac,0x0d6},{0x1b0,0x036},{0x1b2,0x136},{0x1b4,0x0b6}, {0x1b8,0x076},{0x1ba,0x176},{0x1bc,0x0f6},{0x1c0,0x00e},{0x1c2,0x10e},{0x1c4,0x08e},{0x1c6,0x18e},{0x1c8,0x04e}, {0x1ca,0x14e},{0x1cc,0x0ce},{0x1d0,0x02e},{0x1d2,0x12e},{0x1d4,0x0ae},{0x1d6,0x1ae},{0x1d8,0x06e},{0x1da,0x16e}, {0x1dc,0x0ee},{0x1e0,0x01e},{0x1e2,0x11e},{0x1e4,0x09e},{0x1e6,0x19e},{0x1e8,0x05e},{0x1ea,0x15e},{0x1ec,0x0de}, {0x1ee,0x1de},{0x1f0,0x03e},{0x1f2,0x13e},{0x1f4,0x0be},{0x1f6,0x1be},{0x1f8,0x07e},{0x1fa,0x17e},{0x1fc,0x0fe}, {0x200,0x001},{0x202,0x101},{0x204,0x081},{0x206,0x181},{0x208,0x041},{0x20a,0x141},{0x20c,0x0c1},{0x20e,0x1c1}, {0x210,0x021},{0x212,0x121},{0x214,0x0a1},{0x216,0x1a1},{0x218,0x061},{0x21a,0x161},{0x21c,0x0e1},{0x21e,0x1e1}, {0x220,0x011},{0x221,0x211},{0x222,0x111},{0x224,0x091},{0x226,0x191},{0x228,0x051},{0x22a,0x151},{0x22c,0x0d1}, {0x22e,0x1d1},{0x230,0x031},{0x232,0x131},{0x234,0x0b1},{0x236,0x1b1},{0x238,0x071},{0x23a,0x171},{0x23c,0x0f1}, {0x23e,0x1f1},{0x240,0x009},{0x241,0x209},{0x242,0x109},{0x244,0x089},{0x246,0x189},{0x248,0x049},{0x24a,0x149}, {0x24c,0x0c9},{0x24e,0x1c9},{0x250,0x029},{0x251,0x229},{0x252,0x129},{0x254,0x0a9},{0x256,0x1a9},{0x258,0x069}, {0x25a,0x169},{0x25c,0x0e9},{0x25e,0x1e9},{0x260,0x019},{0x261,0x219},{0x262,0x119},{0x264,0x099},{0x266,0x199}, {0x268,0x059},{0x269,0x259},{0x26a,0x159},{0x26c,0x0d9},{0x26e,0x1d9},{0x270,0x039},{0x271,0x239},{0x272,0x139}, {0x274,0x0b9},{0x276,0x1b9},{0x278,0x079},{0x27a,0x179},{0x27c,0x0f9},{0x27e,0x1f9},{0x280,0x005},{0x281,0x205}, {0x282,0x105},{0x284,0x085},{0x286,0x185},{0x288,0x045},{0x289,0x245},{0x28a,0x145},{0x28c,0x0c5},{0x28e,0x1c5}, {0x290,0x025},{0x291,0x225},{0x292,0x125},{0x294,0x0a5},{0x296,0x1a5},{0x298,0x065},{0x299,0x265},{0x29a,0x165}, {0x29c,0x0e5},{0x29e,0x1e5},{0x2a0,0x015},{0x2a1,0x215},{0x2a2,0x115},{0x2a4,0x095},{0x2a5,0x295},{0x2a6,0x195}, {0x2a8,0x055},{0x2a9,0x255},{0x2aa,0x155},{0x2ac,0x0d5},{0x2ae,0x1d5},{0x2b0,0x035},{0x2b1,0x235},{0x2b2,0x135}, {0x2b4,0x0b5},{0x2b6,0x1b5},{0x2b8,0x075},{0x2b9,0x275},{0x2ba,0x175},{0x2bc,0x0f5},{0x2be,0x1f5},{0x2c0,0x00d}, {0x2c1,0x20d},{0x2c2,0x10d},{0x2c4,0x08d},{0x2c5,0x28d},{0x2c6,0x18d},{0x2c8,0x04d},{0x2c9,0x24d},{0x2ca,0x14d}, {0x2cc,0x0cd},{0x2ce,0x1cd},{0x2d0,0x02d},{0x2d1,0x22d},{0x2d2,0x12d},{0x2d4,0x0ad},{0x2d5,0x2ad},{0x2d6,0x1ad}, {0x2d8,0x06d},{0x2d9,0x26d},{0x2da,0x16d},{0x2dc,0x0ed},{0x2de,0x1ed},{0x2e0,0x01d},{0x2e1,0x21d},{0x2e2,0x11d}, {0x2e4,0x09d},{0x2e5,0x29d},{0x2e6,0x19d},{0x2e8,0x05d},{0x2e9,0x25d},{0x2ea,0x15d},{0x2ec,0x0dd},{0x2ed,0x2dd}, {0x2ee,0x1dd},{0x2f0,0x03d},{0x2f1,0x23d},{0x2f2,0x13d},{0x2f4,0x0bd},{0x2f5,0x2bd},{0x2f6,0x1bd},{0x2f8,0x07d}, {0x2f9,0x27d},{0x2fa,0x17d},{0x2fc,0x0fd},{0x2fe,0x1fd},{0x300,0x003},{0x301,0x203},{0x302,0x103},{0x304,0x083}, {0x305,0x283},{0x306,0x183},{0x308,0x043},{0x309,0x243},{0x30a,0x143},{0x30c,0x0c3},{0x30d,0x2c3},{0x30e,0x1c3}, {0x310,0x023},{0x311,0x223},{0x312,0x123},{0x314,0x0a3},{0x315,0x2a3},{0x316,0x1a3},{0x318,0x063},{0x319,0x263}, {0x31a,0x163},{0x31c,0x0e3},{0x31d,0x2e3},{0x31e,0x1e3},{0x320,0x013},{0x321,0x213},{0x322,0x113},{0x323,0x313}, {0x324,0x093},{0x325,0x293},{0x326,0x193},{0x328,0x053},{0x329,0x253},{0x32a,0x153},{0x32c,0x0d3},{0x32d,0x2d3}, {0x32e,0x1d3},{0x330,0x033},{0x331,0x233},{0x332,0x133},{0x334,0x0b3},{0x335,0x2b3},{0x336,0x1b3},{0x338,0x073}, {0x339,0x273},{0x33a,0x173},{0x33c,0x0f3},{0x33d,0x2f3},{0x33e,0x1f3},{0x340,0x00b},{0x341,0x20b},{0x342,0x10b}, {0x343,0x30b},{0x344,0x08b},{0x345,0x28b},{0x346,0x18b},{0x348,0x04b},{0x349,0x24b},{0x34a,0x14b},{0x34c,0x0cb}, {0x34d,0x2cb},{0x34e,0x1cb},{0x350,0x02b},{0x351,0x22b},{0x352,0x12b},{0x353,0x32b},{0x354,0x0ab},{0x355,0x2ab}, {0x356,0x1ab},{0x358,0x06b},{0x359,0x26b},{0x35a,0x16b},{0x35c,0x0eb},{0x35d,0x2eb},{0x35e,0x1eb},{0x360,0x01b}, {0x361,0x21b},{0x362,0x11b},{0x363,0x31b},{0x364,0x09b},{0x365,0x29b},{0x366,0x19b},{0x368,0x05b},{0x369,0x25b}, {0x36a,0x15b},{0x36b,0x35b},{0x36c,0x0db},{0x36d,0x2db},{0x36e,0x1db},{0x370,0x03b},{0x371,0x23b},{0x372,0x13b}, {0x373,0x33b},{0x374,0x0bb},{0x375,0x2bb},{0x376,0x1bb},{0x378,0x07b},{0x379,0x27b},{0x37a,0x17b},{0x37c,0x0fb}, {0x37d,0x2fb},{0x37e,0x1fb},{0x380,0x007},{0x381,0x207},{0x382,0x107},{0x383,0x307},{0x384,0x087},{0x385,0x287}, {0x386,0x187},{0x388,0x047},{0x389,0x247},{0x38a,0x147},{0x38b,0x347},{0x38c,0x0c7},{0x38d,0x2c7},{0x38e,0x1c7}, {0x390,0x027},{0x391,0x227},{0x392,0x127},{0x393,0x327},{0x394,0x0a7},{0x395,0x2a7},{0x396,0x1a7},{0x398,0x067}, {0x399,0x267},{0x39a,0x167},{0x39b,0x367},{0x39c,0x0e7},{0x39d,0x2e7},{0x39e,0x1e7},{0x3a0,0x017},{0x3a1,0x217}, {0x3a2,0x117},{0x3a3,0x317},{0x3a4,0x097},{0x3a5,0x297},{0x3a6,0x197},{0x3a7,0x397},{0x3a8,0x057},{0x3a9,0x257}, {0x3aa,0x157},{0x3ab,0x357},{0x3ac,0x0d7},{0x3ad,0x2d7},{0x3ae,0x1d7},{0x3b0,0x037},{0x3b1,0x237},{0x3b2,0x137}, {0x3b3,0x337},{0x3b4,0x0b7},{0x3b5,0x2b7},{0x3b6,0x1b7},{0x3b8,0x077},{0x3b9,0x277},{0x3ba,0x177},{0x3bb,0x377}, {0x3bc,0x0f7},{0x3bd,0x2f7},{0x3be,0x1f7},{0x3c0,0x00f},{0x3c1,0x20f},{0x3c2,0x10f},{0x3c3,0x30f},{0x3c4,0x08f}, {0x3c5,0x28f},{0x3c6,0x18f},{0x3c7,0x38f},{0x3c8,0x04f},{0x3c9,0x24f},{0x3ca,0x14f},{0x3cb,0x34f},{0x3cc,0x0cf}, {0x3cd,0x2cf},{0x3ce,0x1cf},{0x3d0,0x02f},{0x3d1,0x22f},{0x3d2,0x12f},{0x3d3,0x32f},{0x3d4,0x0af},{0x3d5,0x2af}, {0x3d6,0x1af},{0x3d7,0x3af},{0x3d8,0x06f},{0x3d9,0x26f},{0x3da,0x16f},{0x3db,0x36f},{0x3dc,0x0ef},{0x3dd,0x2ef}, {0x3de,0x1ef},{0x3e0,0x01f},{0x3e1,0x21f},{0x3e2,0x11f},{0x3e3,0x31f},{0x3e4,0x09f},{0x3e5,0x29f},{0x3e6,0x19f}, {0x3e7,0x39f},{0x3e8,0x05f},{0x3e9,0x25f},{0x3ea,0x15f},{0x3eb,0x35f},{0x3ec,0x0df},{0x3ed,0x2df},{0x3ee,0x1df}, {0x3ef,0x3df},{0x3f0,0x03f},{0x3f1,0x23f},{0x3f2,0x13f},{0x3f3,0x33f},{0x3f4,0x0bf},{0x3f5,0x2bf},{0x3f6,0x1bf}, {0x3f7,0x3bf},{0x3f8,0x07f},{0x3f9,0x27f},{0x3fa,0x17f},{0x3fb,0x37f},{0x3fc,0x0ff},{0x3fd,0x2ff},{0x3fe,0x1ff} }; { int i; for (i = 0; i < sizeof k1k2tab / sizeof k1k2tab[0]; ++i) { k1 = k1k2tab[i].k1; k2 = k1k2tab[i].k2; a = fz[k1]; fz[k1] = fz[k2]; fz[k2] = a; } } for (fi=fz,fn=fz+1024;fi> 1; fi = fz; gi = fi + kx; fn = fz + 1024; do { FLOAT g0,f0,f1,g1,f2,g2,f3,g3; f1 = fi[0 ] - fi[k1]; f0 = fi[0 ] + fi[k1]; f3 = fi[k2] - fi[k3]; f2 = fi[k2] + fi[k3]; fi[k2] = f0 - f2; fi[0 ] = f0 + f2; fi[k3] = f1 - f3; fi[k1] = f1 + f3; g1 = gi[0 ] - gi[k1]; g0 = gi[0 ] + gi[k1]; g3 = SQRT2 * gi[k3]; g2 = SQRT2 * gi[k2]; gi[k2] = g0 - g2; gi[0 ] = g0 + g2; gi[k3] = g1 - g3; gi[k1] = g1 + g3; gi += k4; fi += k4; } while (fi/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = mp2enc$(EXEEXT) @HAVE_ALTIVEC_TRUE@am__append_1 = $(top_builddir)/mpeg2enc/libmpeg2encpp.la subdir = aenc DIST_COMMON = README $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_mp2enc_OBJECTS = common.$(OBJEXT) encode.$(OBJEXT) fft.$(OBJEXT) \ musicin.$(OBJEXT) psy.$(OBJEXT) tables.$(OBJEXT) \ tonal.$(OBJEXT) wav_io.$(OBJEXT) mp2enc_OBJECTS = $(am_mp2enc_OBJECTS) am__DEPENDENCIES_1 = mp2enc_DEPENDENCIES = $(top_builddir)/utils/libmjpegutils.la \ $(am__DEPENDENCIES_1) $(am__append_1) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(mp2enc_SOURCES) DIST_SOURCES = $(mp2enc_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALTIVEC_EXTRA_LIBS = @ALTIVEC_EXTRA_LIBS@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDV_CFLAGS = @LIBDV_CFLAGS@ LIBDV_LIBS = @LIBDV_LIBS@ LIBGETOPT_LIB = @LIBGETOPT_LIB@ LIBM_LIBS = @LIBM_LIBS@ LIBOBJS = @LIBOBJS@ LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ LIBPNG_LIBS = @LIBPNG_LIBS@ LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@ LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ LT_STATIC = @LT_STATIC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROGRAM_NOPIC = @PROGRAM_NOPIC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ SDLgfx_LIBS = @SDLgfx_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ V4LCONF_LIBS = @V4LCONF_LIBS@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I $(top_srcdir) -I $(top_srcdir)/utils mp2enc_SOURCES = \ common.c \ encode.c \ fft.c \ musicin.c \ psy.c \ tables.c \ tonal.c \ wav_io.c noinst_HEADERS = \ common.h \ encoder.h \ table_absthr.h \ table_alloc.h \ table_cb.h \ table_enwindow.h \ table_th.h \ wav_io.h mp2enc_LDADD = $(top_builddir)/utils/libmjpegutils.la $(LIBM_LIBS) \ $(am__append_1) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu aenc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu aenc/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list mp2enc$(EXEEXT): $(mp2enc_OBJECTS) $(mp2enc_DEPENDENCIES) $(EXTRA_mp2enc_DEPENDENCIES) @rm -f mp2enc$(EXEEXT) $(LINK) $(mp2enc_OBJECTS) $(mp2enc_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encode.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fft.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/musicin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tables.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tonal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wav_io.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool cscopelist ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mjpegtools-2.1.0/aenc/table_th.h0000644000175000017500000003576207133030460017063 0ustar glowwormglowwormstatic int th_len[6] = { 107, 103, 103, 131, 127, 133 }; static struct { int count; int line; float bark; float hear; } th_tab[6][132] = { { {1,1,0.850,25.87}, {2,2,1.694,14.85}, {3,3,2.525,10.72}, {4,4,3.337,8.50}, {5,5,4.124,7.10}, {6,6,4.882,6.11}, {7,7,5.608,5.37}, {8,8,6.301,4.79}, {9,9,6.959,4.32}, {10,10,7.581,3.92}, {11,11,8.169,3.57}, {12,12,8.723,3.25}, {13,13,9.244,2.95}, {14,14,9.734,2.67}, {15,15,10.195,2.39}, {16,16,10.629,2.11}, {17,17,11.037,1.83}, {18,18,11.421,1.53}, {19,19,11.783,1.23}, {20,20,12.125,0.90}, {21,21,12.448,0.56}, {22,22,12.753,0.21}, {23,23,13.042,-0.17}, {24,24,13.317,-0.56}, {25,25,13.578,-0.96}, {26,26,13.826,-1.38}, {27,27,14.062,-1.79}, {28,28,14.288,-2.21}, {29,29,14.504,-2.63}, {30,30,14.711,-3.03}, {31,31,14.909,-3.41}, {32,32,15.100,-3.77}, {33,33,15.284,-4.09}, {34,34,15.460,-4.37}, {35,35,15.631,-4.60}, {36,36,15.796,-4.78}, {37,37,15.955,-4.91}, {38,38,16.110,-4.97}, {39,39,16.260,-4.98}, {40,40,16.406,-4.92}, {41,41,16.547,-4.81}, {42,42,16.685,-4.65}, {43,43,16.820,-4.43}, {44,44,16.951,-4.17}, {45,45,17.079,-3.87}, {46,46,17.205,-3.54}, {47,47,17.327,-3.19}, {48,48,17.447,-2.82}, {49,50,17.680,-2.06}, {50,52,17.905,-1.32}, {51,54,18.121,-0.64}, {52,56,18.331,-0.04}, {53,58,18.534,0.47}, {54,60,18.731,0.89}, {55,62,18.922,1.23}, {56,64,19.108,1.51}, {57,66,19.289,1.74}, {58,68,19.464,1.93}, {59,70,19.635,2.11}, {60,72,19.801,2.28}, {61,74,19.963,2.46}, {62,76,20.120,2.63}, {63,78,20.273,2.82}, {64,80,20.421,3.03}, {65,82,20.565,3.25}, {66,84,20.705,3.49}, {67,86,20.840,3.74}, {68,88,20.972,4.02}, {69,90,21.099,4.32}, {70,92,21.222,4.64}, {71,94,21.342,4.98}, {72,96,21.457,5.35}, {73,100,21.677,6.15}, {74,104,21.882,7.07}, {75,108,22.074,8.10}, {76,112,22.253,9.25}, {77,116,22.420,10.54}, {78,120,22.576,11.97}, {79,124,22.721,13.56}, {80,128,22.857,15.31}, {81,132,22.984,17.23}, {82,136,23.102,19.34}, {83,140,23.213,21.64}, {84,144,23.317,24.15}, {85,148,23.415,26.88}, {86,152,23.506,29.84}, {87,156,23.592,33.05}, {88,160,23.673,36.52}, {89,164,23.749,40.25}, {90,168,23.821,44.27}, {91,172,23.888,48.59}, {92,176,23.952,53.22}, {93,180,24.013,58.18}, {94,184,24.070,63.49}, {95,188,24.125,68.00}, {96,192,24.176,68.00}, {97,196,24.225,68.00}, {98,200,24.271,68.00}, {99,204,24.316,68.00}, {100,208,24.358,68.00}, {101,212,24.398,68.00}, {102,216,24.436,68.00}, {103,220,24.473,68.00}, {104,224,24.508,68.00}, {105,228,24.542,68.00}, {106,232,24.574,68.00}, }, { {1,1,0.925,24.17}, {2,2,1.842,13.87}, {3,3,2.742,10.01}, {4,4,3.618,7.94}, {5,5,4.463,6.62}, {6,6,5.272,5.70}, {7,7,6.041,5.00}, {8,8,6.770,4.45}, {9,9,7.457,4.00}, {10,10,8.103,3.61}, {11,11,8.708,3.26}, {12,12,9.275,2.93}, {13,13,9.805,2.63}, {14,14,10.301,2.32}, {15,15,10.765,2.02}, {16,16,11.199,1.71}, {17,17,11.606,1.38}, {18,18,11.988,1.04}, {19,19,12.347,0.67}, {20,20,12.684,0.29}, {21,21,13.002,-0.11}, {22,22,13.302,-0.54}, {23,23,13.586,-0.97}, {24,24,13.855,-1.43}, {25,25,14.111,-1.88}, {26,26,14.354,-2.34}, {27,27,14.585,-2.79}, {28,28,14.807,-3.22}, {29,29,15.018,-3.62}, {30,30,15.221,-3.98}, {31,31,15.415,-4.30}, {32,32,15.602,-4.57}, {33,33,15.783,-4.77}, {34,34,15.956,-4.91}, {35,35,16.124,-4.98}, {36,36,16.287,-4.97}, {37,37,16.445,-4.90}, {38,38,16.598,-4.76}, {39,39,16.746,-4.55}, {40,40,16.891,-4.29}, {41,41,17.032,-3.99}, {42,42,17.169,-3.64}, {43,43,17.303,-3.26}, {44,44,17.434,-2.86}, {45,45,17.563,-2.45}, {46,46,17.688,-2.04}, {47,47,17.811,-1.63}, {48,48,17.932,-1.24}, {49,50,18.166,-0.51}, {50,52,18.392,0.12}, {51,54,18.611,0.64}, {52,56,18.823,1.06}, {53,58,19.028,1.39}, {54,60,19.226,1.66}, {55,62,19.419,1.88}, {56,64,19.606,2.08}, {57,66,19.788,2.27}, {58,68,19.964,2.46}, {59,70,20.135,2.65}, {60,72,20.300,2.86}, {61,74,20.461,3.09}, {62,76,20.616,3.33}, {63,78,20.766,3.60}, {64,80,20.912,3.89}, {65,82,21.052,4.20}, {66,84,21.188,4.54}, {67,86,21.318,4.91}, {68,88,21.445,5.31}, {69,90,21.567,5.73}, {70,92,21.684,6.18}, {71,94,21.797,6.67}, {72,96,21.906,7.19}, {73,100,22.113,8.33}, {74,104,22.304,9.63}, {75,108,22.482,11.08}, {76,112,22.646,12.71}, {77,116,22.799,14.53}, {78,120,22.941,16.54}, {79,124,23.072,18.77}, {80,128,23.195,21.23}, {81,132,23.309,23.94}, {82,136,23.415,26.90}, {83,140,23.515,30.14}, {84,144,23.607,33.67}, {85,148,23.694,37.51}, {86,152,23.775,41.67}, {87,156,23.852,46.17}, {88,160,23.923,51.04}, {89,164,23.991,56.29}, {90,168,24.054,61.94}, {91,172,24.114,68.00}, {92,176,24.171,68.00}, {93,180,24.224,68.00}, {94,184,24.275,68.00}, {95,188,24.322,68.00}, {96,192,24.368,68.00}, {97,196,24.411,68.00}, {98,200,24.452,68.00}, {99,204,24.491,68.00}, {100,208,24.528,68.00}, {101,212,24.564,68.00}, {102,216,24.597,68.00}, }, { {1,1,0.925,24.17}, {2,2,1.842,13.87}, {3,3,2.742,10.01}, {4,4,3.618,7.94}, {5,5,4.463,6.62}, {6,6,5.272,5.70}, {7,7,6.041,5.00}, {8,8,6.770,4.45}, {9,9,7.457,4.00}, {10,10,8.103,3.61}, {11,11,8.708,3.26}, {12,12,9.275,2.93}, {13,13,9.805,2.63}, {14,14,10.301,2.32}, {15,15,10.765,2.02}, {16,16,11.199,1.71}, {17,17,11.606,1.38}, {18,18,11.988,1.04}, {19,19,12.347,0.67}, {20,20,12.684,0.29}, {21,21,13.002,-0.11}, {22,22,13.302,-0.54}, {23,23,13.586,-0.97}, {24,24,13.855,-1.43}, {25,25,14.111,-1.88}, {26,26,14.354,-2.34}, {27,27,14.585,-2.79}, {28,28,14.807,-3.22}, {29,29,15.018,-3.62}, {30,30,15.221,-3.98}, {31,31,15.415,-4.30}, {32,32,15.602,-4.57}, {33,33,15.783,-4.77}, {34,34,15.956,-4.91}, {35,35,16.124,-4.98}, {36,36,16.287,-4.97}, {37,37,16.445,-4.90}, {38,38,16.598,-4.76}, {39,39,16.746,-4.55}, {40,40,16.891,-4.29}, {41,41,17.032,-3.99}, {42,42,17.169,-3.64}, {43,43,17.303,-3.26}, {44,44,17.434,-2.86}, {45,45,17.563,-2.45}, {46,46,17.688,-2.04}, {47,47,17.811,-1.63}, {48,48,17.932,-1.24}, {49,50,18.166,-0.51}, {50,52,18.392,0.12}, {51,54,18.611,0.64}, {52,56,18.823,1.06}, {53,58,19.028,1.39}, {54,60,19.226,1.66}, {55,62,19.419,1.88}, {56,64,19.606,2.08}, {57,66,19.788,2.27}, {58,68,19.964,2.46}, {59,70,20.135,2.65}, {60,72,20.300,2.86}, {61,74,20.461,3.09}, {62,76,20.616,3.33}, {63,78,20.766,3.60}, {64,80,20.912,3.89}, {65,82,21.052,4.20}, {66,84,21.188,4.54}, {67,86,21.318,4.91}, {68,88,21.445,5.31}, {69,90,21.567,5.73}, {70,92,21.684,6.18}, {71,94,21.797,6.67}, {72,96,21.906,7.19}, {73,100,22.113,8.33}, {74,104,22.304,9.63}, {75,108,22.482,11.08}, {76,112,22.646,12.71}, {77,116,22.799,14.53}, {78,120,22.941,16.54}, {79,124,23.072,18.77}, {80,128,23.195,21.23}, {81,132,23.309,23.94}, {82,136,23.415,26.90}, {83,140,23.515,30.14}, {84,144,23.607,33.67}, {85,148,23.694,37.51}, {86,152,23.775,41.67}, {87,156,23.852,46.17}, {88,160,23.923,51.04}, {89,164,23.991,56.29}, {90,168,24.054,61.94}, {91,172,24.114,68.00}, {92,176,24.171,68.00}, {93,180,24.224,68.00}, {94,184,24.275,68.00}, {95,188,24.322,68.00}, {96,192,24.368,68.00}, {97,196,24.411,68.00}, {98,200,24.452,68.00}, {99,204,24.491,68.00}, {100,208,24.528,68.00}, {101,212,24.564,68.00}, {102,216,24.597,68.00}, }, { {1,1,0.425,45.05}, {2,2,0.850,25.87}, {3,3,1.273,18.70}, {4,4,1.694,14.85}, {5,5,2.112,12.41}, {6,6,2.525,10.72}, {7,7,2.934,9.47}, {8,8,3.337,8.50}, {9,9,3.733,7.73}, {10,10,4.124,7.10}, {11,11,4.507,6.56}, {12,12,4.882,6.11}, {13,13,5.249,5.72}, {14,14,5.608,5.37}, {15,15,5.959,5.07}, {16,16,6.301,4.79}, {17,17,6.634,4.55}, {18,18,6.959,4.32}, {19,19,7.274,4.11}, {20,20,7.581,3.92}, {21,21,7.879,3.74}, {22,22,8.169,3.57}, {23,23,8.450,3.40}, {24,24,8.723,3.25}, {25,25,8.987,3.10}, {26,26,9.244,2.95}, {27,27,9.493,2.81}, {28,28,9.734,2.67}, {29,29,9.968,2.53}, {30,30,10.195,2.39}, {31,31,10.416,2.25}, {32,32,10.629,2.11}, {33,33,10.836,1.97}, {34,34,11.037,1.83}, {35,35,11.232,1.68}, {36,36,11.421,1.53}, {37,37,11.605,1.38}, {38,38,11.783,1.23}, {39,39,11.957,1.07}, {40,40,12.125,0.90}, {41,41,12.289,0.74}, {42,42,12.448,0.56}, {43,43,12.603,0.39}, {44,44,12.753,0.21}, {45,45,12.900,0.02}, {46,46,13.042,-0.17}, {47,47,13.181,-0.36}, {48,48,13.317,-0.56}, {49,50,13.577,-0.96}, {50,52,13.826,-1.38}, {51,54,14.062,-1.79}, {52,56,14.288,-2.21}, {53,58,14.504,-2.63}, {54,60,14.711,-3.03}, {55,62,14.909,-3.41}, {56,64,15.100,-3.77}, {57,66,15.284,-4.09}, {58,68,15.460,-4.37}, {59,70,15.631,-4.60}, {60,72,15.796,-4.78}, {61,74,15.955,-4.91}, {62,76,16.110,-4.97}, {63,78,16.260,-4.98}, {64,80,16.406,-4.92}, {65,82,16.547,-4.81}, {66,84,16.685,-4.65}, {67,86,16.820,-4.43}, {68,88,16.951,-4.17}, {69,90,17.079,-3.87}, {70,92,17.205,-3.54}, {71,94,17.327,-3.19}, {72,96,17.447,-2.82}, {73,100,17.680,-2.06}, {74,104,17.905,-1.32}, {75,108,18.121,-0.64}, {76,112,18.331,-0.04}, {77,116,18.534,0.47}, {78,120,18.731,0.89}, {79,124,18.922,1.23}, {80,128,19.108,1.51}, {81,132,19.289,1.74}, {82,136,19.464,1.93}, {83,140,19.635,2.11}, {84,144,19.801,2.28}, {85,148,19.963,2.46}, {86,152,20.120,2.63}, {87,156,20.273,2.82}, {88,160,20.421,3.03}, {89,164,20.565,3.25}, {90,168,20.705,3.49}, {91,172,20.840,3.74}, {92,176,20.972,4.02}, {93,180,21.099,4.32}, {94,184,21.222,4.64}, {95,188,21.342,4.98}, {96,192,21.457,5.35}, {97,200,21.677,6.15}, {98,208,21.882,7.07}, {99,216,22.074,8.10}, {100,224,22.253,9.25}, {101,232,22.420,10.54}, {102,240,22.576,11.97}, {103,248,22.721,13.56}, {104,256,22.857,15.31}, {105,264,22.984,17.23}, {106,272,23.102,19.34}, {107,280,23.213,21.64}, {108,288,23.317,24.15}, {109,296,23.415,26.88}, {110,304,23.506,29.84}, {111,312,23.592,33.05}, {112,320,23.673,36.52}, {113,328,23.749,40.25}, {114,336,23.821,44.27}, {115,344,23.888,48.59}, {116,352,23.952,53.22}, {117,360,24.013,58.18}, {118,368,24.070,63.49}, {119,376,24.125,68.00}, {120,384,24.176,68.00}, {121,392,24.225,68.00}, {122,400,24.271,68.00}, {123,408,24.316,68.00}, {124,416,24.358,68.00}, {125,424,24.398,68.00}, {126,432,24.436,68.00}, {127,440,24.473,68.00}, {128,448,24.508,68.00}, {129,456,24.542,68.00}, {130,464,24.574,68.00}, }, { {1,1,0.463,42.10}, {2,2,0.925,24.17}, {3,3,1.385,17.47}, {4,4,1.842,13.87}, {5,5,2.295,11.60}, {6,6,2.742,10.01}, {7,7,3.184,8.84}, {8,8,3.618,7.94}, {9,9,4.045,7.22}, {10,10,4.463,6.62}, {11,11,4.872,6.12}, {12,12,5.272,5.70}, {13,13,5.661,5.33}, {14,14,6.041,5.00}, {15,15,6.411,4.71}, {16,16,6.770,4.45}, {17,17,7.119,4.21}, {18,18,7.457,4.00}, {19,19,7.785,3.79}, {20,20,8.103,3.61}, {21,21,8.410,3.43}, {22,22,8.708,3.26}, {23,23,8.996,3.09}, {24,24,9.275,2.93}, {25,25,9.544,2.78}, {26,26,9.805,2.63}, {27,27,10.057,2.47}, {28,28,10.301,2.32}, {29,29,10.537,2.17}, {30,30,10.765,2.02}, {31,31,10.986,1.86}, {32,32,11.199,1.71}, {33,33,11.406,1.55}, {34,34,11.606,1.38}, {35,35,11.800,1.21}, {36,36,11.988,1.04}, {37,37,12.170,0.86}, {38,38,12.347,0.67}, {39,39,12.518,0.49}, {40,40,12.684,0.29}, {41,41,12.845,0.09}, {42,42,13.002,-0.11}, {43,43,13.154,-0.32}, {44,44,13.302,-0.54}, {45,45,13.446,-0.75}, {46,46,13.586,-0.97}, {47,47,13.723,-1.20}, {48,48,13.855,-1.43}, {49,50,14.111,-1.88}, {50,52,14.354,-2.34}, {51,54,14.585,-2.79}, {52,56,14.807,-3.22}, {53,58,15.018,-3.62}, {54,60,15.221,-3.98}, {55,62,15.415,-4.30}, {56,64,15.602,-4.57}, {57,66,15.783,-4.77}, {58,68,15.956,-4.91}, {59,70,16.124,-4.98}, {60,72,16.287,-4.97}, {61,74,16.445,-4.90}, {62,76,16.598,-4.76}, {63,78,16.746,-4.55}, {64,80,16.891,-4.29}, {65,82,17.032,-3.99}, {66,84,17.169,-3.64}, {67,86,17.303,-3.26}, {68,88,17.434,-2.86}, {69,90,17.563,-2.45}, {70,92,17.688,-2.04}, {71,94,17.811,-1.63}, {72,96,17.932,-1.24}, {73,100,18.166,-0.51}, {74,104,18.392,0.12}, {75,108,18.611,0.64}, {76,112,18.823,1.06}, {77,116,19.028,1.39}, {78,120,19.226,1.66}, {79,124,19.419,1.88}, {80,128,19.606,2.08}, {81,132,19.788,2.27}, {82,136,19.964,2.46}, {83,140,20.135,2.65}, {84,144,20.300,2.86}, {85,148,20.461,3.09}, {86,152,20.616,3.33}, {87,156,20.766,3.60}, {88,160,20.912,3.89}, {89,164,21.052,4.20}, {90,168,21.188,4.54}, {91,172,21.318,4.91}, {92,176,21.445,5.31}, {93,180,21.567,5.73}, {94,184,21.684,6.18}, {95,188,21.797,6.67}, {96,192,21.906,7.19}, {97,200,22.113,8.33}, {98,208,22.304,9.63}, {99,216,22.482,11.08}, {100,224,22.646,12.71}, {101,232,22.799,14.53}, {102,240,22.941,16.54}, {103,248,23.072,18.77}, {104,256,23.195,21.23}, {105,264,23.309,23.94}, {106,272,23.415,26.90}, {107,280,23.515,30.14}, {108,288,23.607,33.67}, {109,296,23.694,37.51}, {110,304,23.775,41.67}, {111,312,23.852,46.17}, {112,320,23.923,51.04}, {113,328,23.991,56.29}, {114,336,24.054,61.94}, {115,344,24.114,68.00}, {116,352,24.171,68.00}, {117,360,24.224,68.00}, {118,368,24.275,68.00}, {119,376,24.322,68.00}, {120,384,24.368,68.00}, {121,392,24.411,68.00}, {122,400,24.452,68.00}, {123,408,24.491,68.00}, {124,416,24.528,68.00}, {125,424,24.564,68.00}, {126,432,24.597,68.00}, }, { {1,1,0.309,58.23}, {2,2,0.617,33.44}, {3,3,0.925,24.17}, {4,4,1.232,19.20}, {5,5,1.538,16.05}, {6,6,1.842,13.87}, {7,7,2.145,12.26}, {8,8,2.445,11.01}, {9,9,2.742,10.01}, {10,10,3.037,9.20}, {11,11,3.329,8.52}, {12,12,3.618,7.94}, {13,13,3.903,7.44}, {14,14,4.185,7.00}, {15,15,4.463,6.62}, {16,16,4.736,6.28}, {17,17,5.006,5.97}, {18,18,5.272,5.70}, {19,19,5.533,5.44}, {20,20,5.789,5.21}, {21,21,6.041,5.00}, {22,22,6.289,4.80}, {23,23,6.532,4.62}, {24,24,6.770,4.45}, {25,25,7.004,4.29}, {26,26,7.233,4.14}, {27,27,7.457,4.00}, {28,28,7.677,3.86}, {29,29,7.892,3.73}, {30,30,8.103,3.61}, {31,31,8.309,3.49}, {32,32,8.511,3.37}, {33,33,8.708,3.26}, {34,34,8.901,3.15}, {35,35,9.090,3.04}, {36,36,9.275,2.93}, {37,37,9.456,2.83}, {38,38,9.632,2.73}, {39,39,9.805,2.63}, {40,40,9.974,2.53}, {41,41,10.139,2.42}, {42,42,10.301,2.32}, {43,43,10.459,2.22}, {44,44,10.614,2.12}, {45,45,10.765,2.02}, {46,46,10.913,1.92}, {47,47,11.058,1.81}, {48,48,11.199,1.71}, {49,50,11.474,1.49}, {50,52,11.736,1.27}, {51,54,11.988,1.04}, {52,56,12.230,0.80}, {53,58,12.461,0.55}, {54,60,12.684,0.29}, {55,62,12.898,0.02}, {56,64,13.104,-0.25}, {57,66,13.302,-0.54}, {58,68,13.493,-0.83}, {59,70,13.678,-1.12}, {60,72,13.855,-1.43}, {61,74,14.027,-1.73}, {62,76,14.193,-2.04}, {63,78,14.354,-2.34}, {64,80,14.509,-2.64}, {65,82,14.660,-2.93}, {66,84,14.807,-3.22}, {67,86,14.949,-3.49}, {68,88,15.087,-3.74}, {69,90,15.221,-3.98}, {70,92,15.351,-4.20}, {71,94,15.478,-4.40}, {72,96,15.602,-4.57}, {73,100,15.841,-4.82}, {74,104,16.069,-4.96}, {75,108,16.287,-4.97}, {76,112,16.496,-4.86}, {77,116,16.697,-4.63}, {78,120,16.891,-4.29}, {79,124,17.078,-3.87}, {80,128,17.259,-3.39}, {81,132,17.434,-2.86}, {82,136,17.605,-2.31}, {83,140,17.770,-1.77}, {84,144,17.932,-1.24}, {85,148,18.089,-0.74}, {86,152,18.242,-0.29}, {87,156,18.392,0.12}, {88,160,18.539,0.48}, {89,164,18.682,0.79}, {90,168,18.823,1.06}, {91,172,18.960,1.29}, {92,176,19.095,1.49}, {93,180,19.226,1.66}, {94,184,19.356,1.81}, {95,188,19.482,1.95}, {96,192,19.606,2.08}, {97,200,19.847,2.33}, {98,208,20.079,2.59}, {99,216,20.300,2.86}, {100,224,20.513,3.17}, {101,232,20.717,3.51}, {102,240,20.912,3.89}, {103,248,21.098,4.31}, {104,256,21.275,4.79}, {105,264,21.445,5.31}, {106,272,21.606,5.88}, {107,280,21.760,6.50}, {108,288,21.906,7.19}, {109,296,22.046,7.93}, {110,304,22.178,8.75}, {111,312,22.304,9.63}, {112,320,22.424,10.58}, {113,328,22.538,11.60}, {114,336,22.646,12.71}, {115,344,22.749,13.90}, {116,352,22.847,15.18}, {117,352,22.941,16.54}, {118,368,23.030,18.01}, {119,376,23.114,19.57}, {120,384,23.195,21.23}, {121,382,23.272,23.01}, {122,400,23.345,24.90}, {123,408,23.415,26.90}, {124,416,23.482,29.03}, {125,424,23.546,31.28}, {126,432,23.607,33.67}, {127,440,23.666,36.19}, {128,448,23.722,38.86}, {129,456,23.775,41.67}, {130,464,23.827,44.63}, {131,472,23.876,47.76}, {132,480,23.923,51.04}, } }; mjpegtools-2.1.0/aenc/psy.c0000644000175000017500000003463310320537714016111 0ustar glowwormglowworm/* * Copyright (c) 1991 MPEG/audio software simulation group, All Rights Reserved * * psy.c * * MPEG/audio coding/decoding software, work in progress * NOT for public distribution until verified and approved by the * MPEG/audio committee. For further information, please contact * Davis Pan, 508-493-2241, e-mail: pan@3d.enet.dec.com * * VERSION 3.9 * changes made since last update: * date programmers comment * 2/25/91 Davis Pan start of version 1.0 records * 5/10/91 W. Joseph Carter Ported to Macintosh and Unix. * 7/10/91 Earle Jennings Ported to MsDos. * replace of floats with FLOAT * 2/11/92 W. Joseph Carter Fixed mem_alloc() arg for "absthr". * 7/24/92 M. Iwadare HANN window coefficients modified. * 7/27/92 Masahiro Iwadare Bug fix, FFT modification for Layer 3 * 7/27/92 Masahiro Iwadare Bug fix, "new", "old", and "oldest" * updates * 8/07/92 Mike Coleman Bug fix, read_absthr() * 10/4/2005 Steven Schultz Speedup by avoiding the malloc/free simulation * of automatic variables. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "common.h" #include "encoder.h" void psycho_anal(buffer,savebuf,chn,lay,snr32,sfreq) short int *buffer; short int savebuf[1056]; int chn, lay; FLOAT snr32[32]; double sfreq; /* to match prototype : float args are always double */ { unsigned int i, j, k; FLOAT r_prime, phi_prime; FLOAT freq_mult, bval_lo, minthres, sum_energy; double tb, temp1, temp2, temp3; /* The static variables "r", "phi_sav", "new", "old" and "oldest" have */ /* to be remembered for the unpredictability measure. For "r" and */ /* "phi_sav", the first index from the left is the channel select and */ /* the second index is the "age" of the data. */ static int new = 0, old = 1, oldest = 0; static int init = 0, flush, sync_flush, syncsize, sfreq_idx; /* The following static variables are constants. */ static double nmt = 5.5; static FLOAT crit_band[27] = {0, 100, 200, 300, 400, 510, 630, 770, 920, 1080, 1270,1480,1720,2000,2320, 2700, 3150, 3700, 4400,5300,6400,7700,9500,12000, 15500,25000,30000}; static FLOAT bmax[27] = {20.0, 20.0, 20.0, 20.0, 20.0, 17.0, 15.0, 10.0, 7.0, 4.4, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 3.5, 3.5, 3.5}; /* * The following pointer variables point to large areas of memory * dynamically allocated by the mem_alloc() function. Dynamic memory * allocation is used in order to avoid stack frame or data area * overflow errors that otherwise would have occurred at compile time * on the Macintosh computer. That may have been true in 1992 but in 2005? */ static FLOAT *grouped_c, *grouped_e, *nb, *cb, *ecb, *bc; static FLOAT *wsamp_r, *wsamp_i, *phi, *energy; static FLOAT *c, *fthr; static F32 *snrtmp; static int *numlines; static int *partition; static FLOAT *cbval, *rnorm; static FLOAT *window; static FLOAT *absthr; static double *tmn; static FCB *s; static FHBLK *lthr; static F2HBLK *r, *phi_sav; if (init==0) { /* * These dynamic memory allocations simulate "automatic" variables * placed on the stack. The overhead of allocating and freeing the memory * can be obviated by making all (not just some) of the pointers static and * using the 'init' flag. */ grouped_c = (FLOAT *) mem_alloc(sizeof(FCB), "grouped_c"); grouped_e = (FLOAT *) mem_alloc(sizeof(FCB), "grouped_e"); nb = (FLOAT *) mem_alloc(sizeof(FCB), "nb"); cb = (FLOAT *) mem_alloc(sizeof(FCB), "cb"); ecb = (FLOAT *) mem_alloc(sizeof(FCB), "ecb"); bc = (FLOAT *) mem_alloc(sizeof(FCB), "bc"); wsamp_r = (FLOAT *) mem_alloc(sizeof(FBLK), "wsamp_r"); wsamp_i = (FLOAT *) mem_alloc(sizeof(FBLK), "wsamp_i"); phi = (FLOAT *) mem_alloc(sizeof(FBLK), "phi"); energy = (FLOAT *) mem_alloc(sizeof(FBLK), "energy"); c = (FLOAT *) mem_alloc(sizeof(FHBLK), "c"); fthr = (FLOAT *) mem_alloc(sizeof(FHBLK), "fthr"); snrtmp = (F32 *) mem_alloc(sizeof(F2_32), "snrtmp"); /* These dynamic memory allocations simulate "static" variables placed */ /* in the data space. Each mem_alloc() call here occurs only once at */ /* initialization time. The mem_free() function must not be called. */ numlines = (int *) mem_alloc(sizeof(ICB), "numlines"); partition = (int *) mem_alloc(sizeof(IHBLK), "partition"); cbval = (FLOAT *) mem_alloc(sizeof(FCB), "cbval"); rnorm = (FLOAT *) mem_alloc(sizeof(FCB), "rnorm"); window = (FLOAT *) mem_alloc(sizeof(FBLK), "window"); absthr = (FLOAT *) mem_alloc(sizeof(FHBLK), "absthr"); tmn = (double *) mem_alloc(sizeof(DCB), "tmn"); s = (FCB *) mem_alloc(sizeof(FCBCB), "s"); lthr = (FHBLK *) mem_alloc(sizeof(F2HBLK), "lthr"); r = (F2HBLK *) mem_alloc(sizeof(F22HBLK), "r"); phi_sav = (F2HBLK *) mem_alloc(sizeof(F22HBLK), "phi_sav"); i = sfreq + 0.5; switch(i) { case 32000: sfreq_idx = 0; break; case 44100: sfreq_idx = 1; break; case 48000: sfreq_idx = 2; break; default: mjpeg_error_exit1("invalid sampling frequency: %d Hz",i); } read_absthr(absthr, sfreq_idx); if(lay==1){ flush = 384; syncsize = 1024; sync_flush = 576; } else { flush = 384*3.0/2.0; syncsize = 1056; sync_flush = syncsize - flush; } /* calculate HANN window coefficients */ /* for(i=0;icrit_band[j])j++; fthr[i]=j-1+(temp1-crit_band[j-1])/(crit_band[j]-crit_band[j-1]); } partition[0] = 0; /* temp2 is the counter of the number of frequency lines in each partition */ temp2 = 1; cbval[0]=fthr[0]; bval_lo=fthr[0]; for(i=1;i0.33){ partition[i]=partition[i-1]+1; cbval[partition[i-1]] = cbval[partition[i-1]]/temp2; cbval[partition[i]] = fthr[i]; bval_lo = fthr[i]; numlines[partition[i-1]] = temp2; temp2 = 1; } else { partition[i]=partition[i-1]; cbval[partition[i]] += fthr[i]; temp2++; } } numlines[partition[i-1]] = temp2; cbval[partition[i-1]] = cbval[partition[i-1]]/temp2; /* * Now compute the spreading function, s[j][i], the value of the spread- * ing function, centered at band j, for band i, store for later use */ for(j=0;j=0.5 && temp1<=2.5){ temp2 = temp1 - 0.5; temp2 = 8.0 * (temp2*temp2 - 2.0 * temp2); } else temp2 = 0; temp1 += 0.474; temp3 = 15.811389+7.5*temp1-17.5*sqrt((double) (1.0+temp1*temp1)); if(temp3 <= -100) s[i][j] = 0; else { temp3 = (temp2 + temp3)*LN_TO_LOG10; s[i][j] = exp(temp3); } } } /* Calculate Tone Masking Noise values */ for(j=0;j24.5) ? temp1 : 24.5; /* Calculate normalization factors for the net spreading functions */ rnorm[j] = 0; for(i=0;i.5)cb[j]=0.5; tb = -0.434294482*log((double) cb[j])-0.301029996; bc[j] = tmn[j]*tb + nmt*(1.0-tb); k = cbval[j] + 0.5; bc[j] = (bc[j] > bmax[k]) ? bc[j] : bmax[k]; bc[j] = exp((double) -bc[j]*LN_TO_LOG10); } /* * Calculate the permissible noise energy level in each of the frequency * partitions. Include absolute threshold and pre-echo controls * this whole section can be accomplished by a table lookup */ for(j=0;jabsthr[j])?temp1:absthr[j]; /* * do not use pre-echo control for layer 2 because it may do bad things to the * MUSICAM bit allocation algorithm */ if(lay==1){ fthr[j] = (temp1 < lthr[chn][j]) ? temp1 : lthr[chn][j]; temp2 = temp1 * 0.00316; fthr[j] = (temp2 > fthr[j]) ? temp2 : fthr[j]; } else fthr[j] = temp1; lthr[chn][j] = LXMIN*temp1; } /* * Translate the 512 threshold values to the 32 filter bands of the coder * */ for(j=0;j<193;j += 16){ minthres = 60802371420160.0; sum_energy = 0.0; for(k=0;k<17;k++){ if(minthres>fthr[j+k])minthres = fthr[j+k]; sum_energy += energy[j+k]; } snrtmp[i][j/16] = sum_energy/(minthres * 17.0); snrtmp[i][j/16] = 4.342944819 * log((double)snrtmp[i][j/16]); } for(j=208;j<(HBLKSIZE-1);j += 16){ minthres = 0.0; sum_energy = 0.0; for(k=0;k<17;k++){ minthres += fthr[j+k]; sum_energy += energy[j+k]; } snrtmp[i][j/16] = sum_energy/minthres; snrtmp[i][j/16] = 4.342944819 * log((double)snrtmp[i][j/16]); } /* * End of Psychoacuostic calculation loop * */ } for(i=0; i<32; i++){ if(lay==2) snr32[i]=(snrtmp[0][i]>snrtmp[1][i])?snrtmp[0][i]:snrtmp[1][i]; else snr32[i]=snrtmp[0][i]; } break; case 3: mjpeg_error_exit1("layer 3 is not currently supported"); break; default: mjpeg_error_exit1("invalid MPEG/audio coding layer: %d",lay); } } mjpegtools-2.1.0/aenc/table_enwindow.h0000644000175000017500000001524507133030460020274 0ustar glowwormglowwormstatic double enwindow_tab[512] = { 0.000000000,-0.000000477,-0.000000477,-0.000000477, -0.000000477,-0.000000477,-0.000000477,-0.000000954, -0.000000954,-0.000000954,-0.000000954,-0.000001431, -0.000001431,-0.000001907,-0.000001907,-0.000002384, -0.000002384,-0.000002861,-0.000003338,-0.000003338, -0.000003815,-0.000004292,-0.000004768,-0.000005245, -0.000006199,-0.000006676,-0.000007629,-0.000008106, -0.000009060,-0.000010014,-0.000011444,-0.000012398, -0.000013828,-0.000014782,-0.000016689,-0.000018120, -0.000019550,-0.000021458,-0.000023365,-0.000025272, -0.000027657,-0.000030041,-0.000032425,-0.000034809, -0.000037670,-0.000040531,-0.000043392,-0.000046253, -0.000049591,-0.000052929,-0.000055790,-0.000059605, -0.000062943,-0.000066280,-0.000070095,-0.000073433, -0.000076771,-0.000080585,-0.000083923,-0.000087261, -0.000090599,-0.000093460,-0.000096321,-0.000099182, 0.000101566, 0.000103951, 0.000105858, 0.000107288, 0.000108242, 0.000108719, 0.000108719, 0.000108242, 0.000106812, 0.000105381, 0.000102520, 0.000099182, 0.000095367, 0.000090122, 0.000084400, 0.000077724, 0.000069618, 0.000060558, 0.000050545, 0.000039577, 0.000027180, 0.000013828,-0.000000954,-0.000017166, -0.000034332,-0.000052929,-0.000072956,-0.000093937, -0.000116348,-0.000140190,-0.000165462,-0.000191212, -0.000218868,-0.000247478,-0.000277042,-0.000307560, -0.000339031,-0.000371456,-0.000404358,-0.000438213, -0.000472546,-0.000507355,-0.000542164,-0.000576973, -0.000611782,-0.000646591,-0.000680923,-0.000714302, -0.000747204,-0.000779152,-0.000809669,-0.000838757, -0.000866413,-0.000891685,-0.000915051,-0.000935555, -0.000954151,-0.000968933,-0.000980854,-0.000989437, -0.000994205,-0.000995159,-0.000991821,-0.000983715, 0.000971317, 0.000953674, 0.000930786, 0.000902653, 0.000868797, 0.000829220, 0.000783920, 0.000731945, 0.000674248, 0.000610352, 0.000539303, 0.000462532, 0.000378609, 0.000288486, 0.000191689, 0.000088215, -0.000021458,-0.000137329,-0.000259876,-0.000388145, -0.000522137,-0.000661850,-0.000806808,-0.000956535, -0.001111031,-0.001269817,-0.001432419,-0.001597881, -0.001766682,-0.001937389,-0.002110004,-0.002283096, -0.002457142,-0.002630711,-0.002803326,-0.002974033, -0.003141880,-0.003306866,-0.003467083,-0.003622532, -0.003771782,-0.003914356,-0.004048824,-0.004174709, -0.004290581,-0.004395962,-0.004489899,-0.004570484, -0.004638195,-0.004691124,-0.004728317,-0.004748821, -0.004752159,-0.004737377,-0.004703045,-0.004649162, -0.004573822,-0.004477024,-0.004357815,-0.004215240, -0.004049301,-0.003858566,-0.003643036,-0.003401756, 0.003134727, 0.002841473, 0.002521515, 0.002174854, 0.001800537, 0.001399517, 0.000971317, 0.000515938, 0.000033379,-0.000475883,-0.001011848,-0.001573563, -0.002161503,-0.002774239,-0.003411293,-0.004072189, -0.004756451,-0.005462170,-0.006189346,-0.006937027, -0.007703304,-0.008487225,-0.009287834,-0.010103703, -0.010933399,-0.011775017,-0.012627602,-0.013489246, -0.014358521,-0.015233517,-0.016112804,-0.016994476, -0.017876148,-0.018756866,-0.019634247,-0.020506859, -0.021372318,-0.022228718,-0.023074150,-0.023907185, -0.024725437,-0.025527000,-0.026310921,-0.027073860, -0.027815342,-0.028532982,-0.029224873,-0.029890060, -0.030526638,-0.031132698,-0.031706810,-0.032248020, -0.032754898,-0.033225536,-0.033659935,-0.034055710, -0.034412861,-0.034730434,-0.035007000,-0.035242081, -0.035435200,-0.035586357,-0.035694122,-0.035758972, 0.035780907, 0.035758972, 0.035694122, 0.035586357, 0.035435200, 0.035242081, 0.035007000, 0.034730434, 0.034412861, 0.034055710, 0.033659935, 0.033225536, 0.032754898, 0.032248020, 0.031706810, 0.031132698, 0.030526638, 0.029890060, 0.029224873, 0.028532982, 0.027815342, 0.027073860, 0.026310921, 0.025527000, 0.024725437, 0.023907185, 0.023074150, 0.022228718, 0.021372318, 0.020506859, 0.019634247, 0.018756866, 0.017876148, 0.016994476, 0.016112804, 0.015233517, 0.014358521, 0.013489246, 0.012627602, 0.011775017, 0.010933399, 0.010103703, 0.009287834, 0.008487225, 0.007703304, 0.006937027, 0.006189346, 0.005462170, 0.004756451, 0.004072189, 0.003411293, 0.002774239, 0.002161503, 0.001573563, 0.001011848, 0.000475883, -0.000033379,-0.000515938,-0.000971317,-0.001399517, -0.001800537,-0.002174854,-0.002521515,-0.002841473, 0.003134727, 0.003401756, 0.003643036, 0.003858566, 0.004049301, 0.004215240, 0.004357815, 0.004477024, 0.004573822, 0.004649162, 0.004703045, 0.004737377, 0.004752159, 0.004748821, 0.004728317, 0.004691124, 0.004638195, 0.004570484, 0.004489899, 0.004395962, 0.004290581, 0.004174709, 0.004048824, 0.003914356, 0.003771782, 0.003622532, 0.003467083, 0.003306866, 0.003141880, 0.002974033, 0.002803326, 0.002630711, 0.002457142, 0.002283096, 0.002110004, 0.001937389, 0.001766682, 0.001597881, 0.001432419, 0.001269817, 0.001111031, 0.000956535, 0.000806808, 0.000661850, 0.000522137, 0.000388145, 0.000259876, 0.000137329, 0.000021458,-0.000088215,-0.000191689,-0.000288486, -0.000378609,-0.000462532,-0.000539303,-0.000610352, -0.000674248,-0.000731945,-0.000783920,-0.000829220, -0.000868797,-0.000902653,-0.000930786,-0.000953674, 0.000971317, 0.000983715, 0.000991821, 0.000995159, 0.000994205, 0.000989437, 0.000980854, 0.000968933, 0.000954151, 0.000935555, 0.000915051, 0.000891685, 0.000866413, 0.000838757, 0.000809669, 0.000779152, 0.000747204, 0.000714302, 0.000680923, 0.000646591, 0.000611782, 0.000576973, 0.000542164, 0.000507355, 0.000472546, 0.000438213, 0.000404358, 0.000371456, 0.000339031, 0.000307560, 0.000277042, 0.000247478, 0.000218868, 0.000191212, 0.000165462, 0.000140190, 0.000116348, 0.000093937, 0.000072956, 0.000052929, 0.000034332, 0.000017166, 0.000000954,-0.000013828, -0.000027180,-0.000039577,-0.000050545,-0.000060558, -0.000069618,-0.000077724,-0.000084400,-0.000090122, -0.000095367,-0.000099182,-0.000102520,-0.000105381, -0.000106812,-0.000108242,-0.000108719,-0.000108719, -0.000108242,-0.000107288,-0.000105858,-0.000103951, 0.000101566, 0.000099182, 0.000096321, 0.000093460, 0.000090599, 0.000087261, 0.000083923, 0.000080585, 0.000076771, 0.000073433, 0.000070095, 0.000066280, 0.000062943, 0.000059605, 0.000055790, 0.000052929, 0.000049591, 0.000046253, 0.000043392, 0.000040531, 0.000037670, 0.000034809, 0.000032425, 0.000030041, 0.000027657, 0.000025272, 0.000023365, 0.000021458, 0.000019550, 0.000018120, 0.000016689, 0.000014782, 0.000013828, 0.000012398, 0.000011444, 0.000010014, 0.000009060, 0.000008106, 0.000007629, 0.000006676, 0.000006199, 0.000005245, 0.000004768, 0.000004292, 0.000003815, 0.000003338, 0.000003338, 0.000002861, 0.000002384, 0.000002384, 0.000001907, 0.000001907, 0.000001431, 0.000001431, 0.000000954, 0.000000954, 0.000000954, 0.000000954, 0.000000477, 0.000000477, 0.000000477, 0.000000477, 0.000000477, 0.000000477}; mjpegtools-2.1.0/aenc/encoder.h0000644000175000017500000002727610227604770016732 0ustar glowwormglowworm/********************************************************************** Copyright (c) 1991 MPEG/audio software simulation group, All Rights Reserved encoder.h **********************************************************************/ /********************************************************************** * MPEG/audio coding/decoding software, work in progress * * NOT for public distribution until verified and approved by the * * MPEG/audio committee. For further information, please contact * * Davis Pan, 508-493-2241, e-mail: pan@gauss.enet.dec.com * * * * VERSION 3.5 * * changes made since last update: * * date programmers comment * * 2/25/91 Doulas Wong, start of version 1.0 records * * Davis Pan * * 5/10/91 W. Joseph Carter Reorganized & renamed all ".h" files * * into "common.h" and "encoder.h". * * Ported to Macintosh and Unix. * * Added function prototypes for more * * rigorous type checking. * * 27jun91 dpwe (Aware) moved "alloc_*" types, pros to common * * Use ifdef PROTO_ARGS for prototypes * * prototypes reflect frame_params struct* * 7/10/91 Earle Jennings Conversion of all floats to FLOAT * * 10/3/91 Don H. Lee implemented CRC-16 error protection * * Additions and revisions are marked * * with "dhl" for clarity * * 2/11/92 W. Joseph Carter Ported new code to Macintosh. Most * * important fixes involved changing * * 16-bit ints to long or unsigned in * * bit alloc routines for quant of 65535 * * and passing proper function args. * * Removed "Other Joint Stereo" option * * and made bitrate be total channel * * bitrate, irrespective of the mode. * * Fixed many small bugs & reorganized. * * Modified some function prototypes. * * 7/27/92 Masahiro Iwadare FFT modifications for Layer 3 * * 8/3/92 Mike Li removed declaration _stklen for DOS. * * 9/22/92 jddevine@aware.com Fix protos for _scale_factor_calc() * * 2004/7/29 Steven Schultz Cleanup and modernize * **********************************************************************/ /*********************************************************************** * * Encoder Definitions * ***********************************************************************/ /* General Definitions */ /* Default Input Arguments (for command line control) */ #define DFLT_LAY 2 /* default encoding layer is II */ #define DFLT_MOD 's' /* default mode is stereo */ #define DFLT_PSY 2 /* default psych model is 2 */ #define DFLT_SFQ 44.1 /* default input sampling rate is 44.1 kHz */ #define DFLT_BRT 128 /* default total output bitrate is 384 kbps */ #define DFLT_EMP 'n' /* default de-emphasis is none */ #define DFLT_EXT ".mpg" /* default output file extension */ #define FILETYPE_ENCODE 'TEXT' #define CREATOR_ENCODE 'MpgD' /* This is the smallest MNR a subband can have before it is counted as 'noisy' by the logic which chooses the number of JS subbands */ #define NOISY_MIN_MNR 0.0 /* Psychacoustic Model 1 Definitions */ #define CB_FRACTION 0.33 #define MAX_SNR 1000 #define NOISE 10 #define TONE 20 #define DBMIN -200.0 #define LAST -1 #define STOP -100 #define POWERNORM 90.3090 /* = 20 * log10(32768) to normalize */ /* max output power to 96 dB per spec */ /* Psychoacoustic Model 2 Definitions */ #define LOGBLKSIZE 10 #define BLKSIZE 1024 #define HBLKSIZE 513 #define CBANDS 63 #define LXMIN 32.0 /*********************************************************************** * * Encoder Type Definitions * ***********************************************************************/ /* Psychoacoustic Model 1 Type Definitions */ typedef int IFFT2[FFT_SIZE/2]; typedef int IFFT[FFT_SIZE]; typedef double D9[9]; typedef double D10[10]; typedef double D640[640]; typedef double D1408[1408]; typedef double DFFT2[FFT_SIZE/2]; typedef double DFFT[FFT_SIZE]; typedef double DSBL[SBLIMIT]; typedef double D2SBL[2][SBLIMIT]; typedef struct { int line; double bark, hear, x; } g_thres, *g_ptr; typedef struct { double x; int type, next, map; } mask, *mask_ptr; /* Psychoacoustic Model 2 Type Definitions */ typedef int ICB[CBANDS]; typedef int IHBLK[HBLKSIZE]; typedef FLOAT F32[32]; typedef FLOAT F2_32[2][32]; typedef FLOAT FCB[CBANDS]; typedef FLOAT FCBCB[CBANDS][CBANDS]; typedef FLOAT FBLK[BLKSIZE]; typedef FLOAT FHBLK[HBLKSIZE]; typedef FLOAT F2HBLK[2][HBLKSIZE]; typedef FLOAT F22HBLK[2][2][HBLKSIZE]; typedef double DCB[CBANDS]; /*********************************************************************** * * Encoder Function Prototype Declarations * ***********************************************************************/ /* The following functions are in the file "musicin.c" */ extern void print_config(frame_params*, int*, unsigned long*, char *); /* The following functions are in the file "encode.c" */ extern unsigned long read_samples(FILE*, short[2304], unsigned long, unsigned long); extern unsigned long get_audio(FILE*, short[2][1152], unsigned long, int, int); extern void read_ana_window(double[HAN_SIZE]); extern void window_subband(short**, double[HAN_SIZE], int); extern void create_ana_filter(double[SBLIMIT][64]); extern void filter_subband(double[HAN_SIZE], double[SBLIMIT]); extern void encode_info(frame_params*, Bit_stream_struc*); extern double mod(double); extern void I_combine_LR(double[2][3][SCALE_BLOCK][SBLIMIT], double[3][SCALE_BLOCK][SBLIMIT]); extern void II_combine_LR(double[2][3][SCALE_BLOCK][SBLIMIT], double[3][SCALE_BLOCK][SBLIMIT], int); extern void I_scale_factor_calc(double[][3][SCALE_BLOCK][SBLIMIT], unsigned int[][3][SBLIMIT], int); extern void II_scale_factor_calc(double[][3][SCALE_BLOCK][SBLIMIT], unsigned int[][3][SBLIMIT], int, int); extern void pick_scale(unsigned int[2][3][SBLIMIT], frame_params*, double[2][SBLIMIT]); extern void put_scale(unsigned int[2][3][SBLIMIT], frame_params*, double[2][SBLIMIT]); extern void II_transmission_pattern(unsigned int[2][3][SBLIMIT], unsigned int[2][SBLIMIT], frame_params*); extern void II_encode_scale(unsigned int[2][SBLIMIT], unsigned int[2][SBLIMIT], unsigned int[2][3][SBLIMIT], frame_params*, Bit_stream_struc*); extern void I_encode_scale(unsigned int[2][3][SBLIMIT], unsigned int[2][SBLIMIT], frame_params*, Bit_stream_struc*); extern int II_bits_for_nonoise(double[2][SBLIMIT], unsigned int[2][SBLIMIT], frame_params*); extern void II_main_bit_allocation(double[2][SBLIMIT], unsigned int[2][SBLIMIT], unsigned int[2][SBLIMIT], int*, frame_params*); extern int II_a_bit_allocation(double[2][SBLIMIT], unsigned int[2][SBLIMIT], unsigned int[2][SBLIMIT], int*, frame_params*); extern int I_bits_for_nonoise(double[2][SBLIMIT], frame_params*); extern void I_main_bit_allocation(double[2][SBLIMIT], unsigned int[2][SBLIMIT], int*, frame_params*); extern int I_a_bit_allocation(double[2][SBLIMIT], unsigned int[2][SBLIMIT], int*, frame_params*); extern void I_subband_quantization(unsigned int[2][3][SBLIMIT], double[2][3][SCALE_BLOCK][SBLIMIT], unsigned int[3][SBLIMIT], double[3][SCALE_BLOCK][SBLIMIT], unsigned int[2][SBLIMIT], unsigned int[2][3][SCALE_BLOCK][SBLIMIT], frame_params*); extern void II_subband_quantization(unsigned int[2][3][SBLIMIT], double[2][3][SCALE_BLOCK][SBLIMIT], unsigned int[3][SBLIMIT], double[3][SCALE_BLOCK][SBLIMIT], unsigned int[2][SBLIMIT], unsigned int[2][3][SCALE_BLOCK][SBLIMIT], frame_params*); extern void II_encode_bit_alloc(unsigned int[2][SBLIMIT], frame_params*, Bit_stream_struc*); extern void I_encode_bit_alloc(unsigned int[2][SBLIMIT], frame_params*, Bit_stream_struc*); extern void I_sample_encoding(unsigned int[2][3][SCALE_BLOCK][SBLIMIT], unsigned int[2][SBLIMIT], frame_params*, Bit_stream_struc*); extern void II_sample_encoding(unsigned int[2][3][SCALE_BLOCK][SBLIMIT], unsigned int[2][SBLIMIT], frame_params*, Bit_stream_struc*); extern void encode_CRC(unsigned int, Bit_stream_struc*); /* The following functions are in the file "tonal.c" */ extern void read_cbound(int, int); extern void read_freq_band(g_ptr*, int, int); extern void make_map(mask[HAN_SIZE], g_thres*); extern double add_db(double, double); extern void II_f_f_t(double[FFT_SIZE], mask[HAN_SIZE]); extern void II_hann_win(double[FFT_SIZE]); extern void II_pick_max(mask[HAN_SIZE], double[SBLIMIT]); extern void II_tonal_label(mask[HAN_SIZE], int*); extern void noise_label(mask*, int*, g_thres*); extern void subsampling(mask[HAN_SIZE], g_thres*, int*, int*); extern void threshold(mask[HAN_SIZE], g_thres*, int*, int*, int); extern void II_minimum_mask(g_thres*, double[SBLIMIT], int); extern void II_smr(double[SBLIMIT], double[SBLIMIT], double[SBLIMIT], int); extern void II_Psycho_One(short[2][1152], double[2][SBLIMIT], double[2][SBLIMIT], frame_params*); extern void I_f_f_t(double[FFT_SIZE/2], mask[HAN_SIZE/2]); extern void I_hann_win(double[FFT_SIZE/2]); extern void I_pick_max(mask[HAN_SIZE/2], double[SBLIMIT]); extern void I_tonal_label(mask[HAN_SIZE/2], int*); extern void I_minimum_mask(g_thres*, double[SBLIMIT]); extern void I_smr(double[SBLIMIT], double[SBLIMIT], double[SBLIMIT]); extern void I_Psycho_One(short[2][1152], double[2][SBLIMIT], double[2][SBLIMIT], frame_params*); /* The following functions are in the file "psy.c" */ extern void psycho_anal(short int*, short int[1056], int, int, FLOAT[32], double); void fft(FLOAT *x_real, FLOAT *x_imag, FLOAT *energy, FLOAT *phi, int N); /* The following functions are in the file "wav_io.c" */ extern int wav_read_header(FILE *fd, int *rate, int *chans, int *bits, int *format, int32_t *bytes); mjpegtools-2.1.0/aenc/wav_io.h0000644000175000017500000000154407447203035016564 0ustar glowwormglowworm/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef WAV_IO_H #define WAV_IO_H int wav_read_header(FILE *fd, int *rate, int *chans, int *bits, int *format, int32_t *bytes); #endif mjpegtools-2.1.0/aenc/tables.c0000644000175000017500000000525210102343771016537 0ustar glowwormglowworm#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "common.h" #include "encoder.h" /*********************************************************************** * * Read one of the data files ("alloc_*") specifying the bit allocation/ * quatization parameters for each subband in layer II encoding * **********************************************************************/ #include "table_alloc.h" int read_bit_alloc(table, alloc) /* read in table, return # subbands */ int table; al_table *alloc; { int i, j, n; if( table>3 || table<0 ) table = 0; for(n=0;n #include #include #include #include #include "mjpeg_logging.h" #define FLOAT float #define FALSE 0 #define TRUE 1 #define MAX_U_32_NUM 0xFFFFFFFF #define PI 3.14159265358979 #define PI4 PI/4 #define PI64 PI/64 #define LN_TO_LOG10 0.2302585093 #define MPEG_AUDIO_ID 1 #define MONO 1 #define STEREO 2 #define BITS_IN_A_BYTE 8 #define SBLIMIT 32 #define FFT_SIZE 1024 #define HAN_SIZE 512 #define SCALE_BLOCK 12 #define SCALE_RANGE 64 #define SCALE 32768 #define CRC16_POLYNOMIAL 0x8005 /* MPEG Header Definitions - Mode Values */ #define MPG_MD_STEREO 0 #define MPG_MD_JOINT_STEREO 1 #define MPG_MD_DUAL_CHANNEL 2 #define MPG_MD_MONO 3 /* "bit_stream.h" Definitions */ #define MINIMUM 4 /* Minimum size of the buffer in bytes */ #define MAX_LENGTH 32 /* Maximum length of word written or read from bit stream */ #define READ_MODE 0 #define WRITE_MODE 1 #define ALIGNING 8 #define BINARY 0 #define ASCII 1 #define BS_FORMAT BINARY /* BINARY or ASCII = 2x bytes */ #define BUFFER_SIZE 4096 #define MIN(A, B) ((A) < (B) ? (A) : (B)) #define MAX(A, B) ((A) > (B) ? (A) : (B)) /*********************************************************************** * * Global Type Definitions * ***********************************************************************/ /* Structure for Reading Layer II Allocation Tables from File */ typedef struct { unsigned int steps; unsigned int bits; unsigned int group; unsigned int quant; } sb_alloc, *alloc_ptr; typedef sb_alloc al_table[SBLIMIT][16]; /* Header Information Structure */ typedef struct { int version; int lay; int error_protection; int bitrate_index; int sampling_frequency; int padding; int extension; int mode; int mode_ext; int copyright; int original; int emphasis; } layer, *the_layer; /* Parent Structure Interpreting some Frame Parameters in Header */ typedef struct { layer *header; /* raw header information */ int actual_mode; /* when writing IS, may forget if 0 chs */ al_table *alloc; /* bit allocation table read in */ int tab_num; /* number of table as loaded */ int stereo; /* 1 for mono, 2 for stereo */ int jsbound; /* first band of joint stereo coding */ int sblimit; /* total number of sub bands */ int in_freq; /* Freq. input in Hz */ int down_freq; /* Freq. to downsample input to for encoding in Hz */ } frame_params; /* "bit_stream.h" Type Definitions */ typedef struct bit_stream_struc { FILE *pt; /* pointer to bit stream device */ unsigned char *buf; /* bit stream buffer */ int buf_size; /* size of buffer (in number of bytes) */ long totbit; /* bit counter of bit stream */ int buf_byte_idx; /* pointer to top byte in buffer */ int buf_bit_idx; /* pointer to top bit of top byte in buffer */ int mode; /* bit stream open in read or write mode */ int eob; /* end of buffer index */ int eobs; /* end of bit stream flag */ char format; /* format of file in rd mode (BINARY/ASCII) */ } Bit_stream_struc; /*********************************************************************** * * Global Variable External Declarations * ***********************************************************************/ extern const char *mode_names[4]; extern const char *layer_names[3]; extern double s_freq[4]; extern int bitrate[3][15]; extern double multiple[64]; extern int verbose; /*********************************************************************** * * Global Function Prototype Declarations * ***********************************************************************/ /* The following functions are in the file "common.c" */ extern FILE *OpenTableFile(char*); extern int read_bit_alloc(int, al_table*); extern int pick_table(frame_params*); extern int js_bound(int, int); extern void hdr_to_frps(frame_params*); extern void WriteHdr(frame_params*, FILE*); extern void WriteBitAlloc(unsigned int[2][SBLIMIT], frame_params*, FILE*); extern void WriteScale(unsigned int[2][SBLIMIT], unsigned int[2][SBLIMIT], unsigned int[2][3][SBLIMIT], frame_params*, FILE*); extern void WriteSamples(int, unsigned int [SBLIMIT], unsigned int[SBLIMIT], frame_params*, FILE*); extern int NumericQ(char*); extern int BitrateIndex(int, int); extern int SmpFrqIndex(long); extern void *mem_alloc(unsigned long, const char*); extern void mem_free(void**); extern void refill_buffer(Bit_stream_struc*); extern void empty_buffer(Bit_stream_struc*, int); extern void open_bit_stream_w(Bit_stream_struc*, char*, int); extern void open_bit_stream_r(Bit_stream_struc*, char*, int); extern void close_bit_stream_r(Bit_stream_struc*); extern void close_bit_stream_w(Bit_stream_struc*); extern void alloc_buffer(Bit_stream_struc*, int); extern void desalloc_buffer(Bit_stream_struc*); extern void back_track_buffer(Bit_stream_struc*, int); extern unsigned int get1bit(Bit_stream_struc*); extern void put1bit(Bit_stream_struc*, int); extern unsigned long look_ahead(Bit_stream_struc*, int); extern unsigned long getbits(Bit_stream_struc*, int); extern void putbits(Bit_stream_struc*, unsigned int, int); extern void byte_ali_putbits(Bit_stream_struc*, unsigned int, int); extern unsigned long byte_ali_getbits(Bit_stream_struc*, int); extern unsigned long sstell(Bit_stream_struc*); extern int end_bs(Bit_stream_struc*); extern int seek_sync(Bit_stream_struc*, long, int); extern void I_CRC_calc(frame_params*, unsigned int[2][SBLIMIT], unsigned int*); extern void II_CRC_calc(frame_params*, unsigned int[2][SBLIMIT], unsigned int[2][SBLIMIT], unsigned int*); extern void update_CRC(unsigned int, unsigned int, unsigned int*); extern void read_absthr(FLOAT*, int); mjpegtools-2.1.0/HINTS0000644000175000017500000001600107755317461015036 0ustar glowwormglowworm(0) If you're just starting run, don't walk to the HOWTO. There's a text copy mjpeg_howto.txt where you found this file. Its online at http://sourceforge.net/docman/?group_id=5776. If you're interested in the source-code and what's buried there read the README's. There's a lot of useful info buried in there... There are specialist README's for mpeg2enc and mplex in the corresponding sub-directories as well as the general README in the top directory. The scripts directory contains shell scripts that provide a convenient interface for common tasks. E.g. lav file (editlist, avi, quicktime) -> MPEG for disk storage, VCD or SVCD. (1) VCD and SVCDs. VCD's have very specific requirements as to the format of the multiplexed systems stream. For VCD these are actually at least "bendings" of the original MPEG standard and are far from optimal as far as maximising possible quality for software decoding goes. The simplest way to generate VCD and SVCD streams that can be burnt to CD and played using DVD players etc is to use the lav2mpeg script with the "-V" and "-S" flags. If you want to play around a couple of hints. To build a VCD you absolutely *must* used the VCD format option for mplex "-f 1". This turns on a lot of weird stuff that otherwise has no place in a respectable multiplexer! Obviously, to play on all players your original MPEG video must be the standard 1151Kbps and audio must be 224Kbps MPEG-1 layer 2 (as produced by the "-v" flag of mp2enc. The systems streams generated by "-f 1" have been tested and succesfully burned onto CD using vcdimager and vcdburn. An SVCD video stream is variable bit-rate MPEG-2 with a maximum rate of around 2500Kbps and a video buffer size of 230KB. Currently I recommend encoding -m 2 -F 3 or (for progressive material like PAL films) -m 2 -F 0. -F 1 and -F 2 will work but are currently handicapped by rather dumb code to choose the type of motion compensation. I have some suspicions that the rate control code and multiplexer needs adjusting for field sequences (-m 2 -F 1 and -F 2) also. To generate a legal S VCD program stream with mplex use the "-f 3" flag. (2) For transcoding existing MPEG-2 streams from digital TV cards or DVD a still lower data-rate than for broadcast will give good results. Standard VCD 1152 Kbps typically works just fine for MPEG1. The difference is in the Signal/Noise ratio of the original. The noise in the analog stuff makes it much harder to compress. You will also need to manually adjust the audio delay offset relative to video when multiplexing. Very often around 150ms delay seems to do the trick. (3) If you want to play MPEG1 on hardware decoders don't build variable bit-rate video streams. If you intend to use software players variable bit-rate is a much more efficient way of encoding and guarantees decent quality. All in all a *much* better bet. The code for the "-S" (SVCD) flags in the lav2mpeg script shows an example for typical usage. Buffer sizes. For hardware players experimentation is the order of the day. My DXR2 seems to use a nice big > 100K buffer for VCD as well as DVD streams and be happy to read MPEG-1 streams *much* faster than the official VCD 170K/sec. 300K seems fine. Generally, you'll probably need a buffer size of around 1/4 data-rate to avoid buffer underflows (signalled as "TO"'s by mplex). (4) If you want to play MPEG-1 stuff on hardware decoders stick to 44.1 224Kbps Stereo layer-2 audio. The 100Kbps or so maximum you'll gain using MP3 aren't going to make a visible difference to video anyway. (5) If you want to reduce bit-rate without annoying artefacts when compressing broadcast material you should try the noise filters. (6) Storing MPEG's. If you record the data as XA mode 2 tracks you can fit appreciably more on a CD (at the expense of error correction/detection). You can use vcdimager to do this and readvcd to extract the resulting files. (6) For MPEG-1 encoding a typical (45 minute running time) show or 90 odd minute movie from an analog broadcast I have found a constant bit-rate of around 1800 to be ideal. The resulting files are around 700M for 45 minutes which fits nicely as a raw XA MODE2 data track on a CD-R. (I use cdrdao to write such CD's and a hacked version of vcdread - soon to be included to extract them). Update: I've now got a digital cable provider. Digital TV sources (even when captured via an analog interface) give *much* better results. There doesn't seem much point going above 1400 or 1500Kbps. Often even VCD 1152 works fine. It depends a bit on the quality of the original. However, IMHO the VCD rate is silly 'cos it means every movie still needs two CD's but the second is mostly empty. Might as well crank the rate (and quality) up until you come in at just under 2 CD's. For pure digital sources (DTV or DVD streams and similar) VCD 1152 works fine. Extrapolating this suggests using 2500bps for MPEG-2 SVCD from broadcast sources with 2000bps or less o.k. for pure digital. (7) Speed. On modern 400Mhz+ CPU's there is *no point* running with a motion compensation setting less than 16. The speed gains aren't huge as other parts of the encoder take a significant fraction of the time. It is much better to leave the radius at 16 and push -4 and -2 to 4. See README. (8) Variable bit-rate. Remember to tell mplex you're encoding VBR as well as mpeg2enc (see the example scripts). It *could* auto-detect but I haven't got around to that yet. You should tell mplex a video buffer size at least as large as the one you specified to "mpeg2enc". Sensible numbers for MPEG-1 might be a ceiling bit-rate of 2800Kbps, a quality ceiling (quantisation floor) of 6 and a buffer size of 400K. (9) Big files. Under typical linux 2.2 systems files are limited to 2G bytes. This is rarely a problem for MPEG-1 video files but it could bite. If your video threatens to exceed 2G you'll need to do it in seperate chunks (for now). 10) Interoperability. Quicktime files capturing using lavrec can be editted using Broadcast2000. mjpeg AVI files captured using the streamer tool from the xawtv package can be editted and compressed and played back using software. Hardware playback is not possible for such files due to limitations in the Zoran hardware currently supported. MPEG files produced using the tools are know to play back correctly on: dxr2 (hardware decoder card) mtv ztheater xine oms dvdview MS Media player versino 6 (anyone like to test version 7?). Obviously, there are some limitations. MPEG-1 players won't play MPEG-2! 11) Optimising encoding. Encoder performance is slightly enhanced if you allow it to dynamically size the output streams groups-of-pictures to reflect scene changes. This is done by setting a maximum GOP (-G flag) size larger than the minimum (-g flag). The default value for both is 12. For VCD's sensible values might be a minimum of 9 and a maximum of 15. For SVCD 9 and 18 would be good values. Andrew mjpegtools-2.1.0/depcomp0000755000175000017500000005055212217306411015572 0ustar glowwormglowworm#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2012-03-27.16; # UTC # Copyright (C) 1999-2012 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # A tabulation character. tab=' ' # A newline character. nl=' ' if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' "$nl" < "$tmpdepfile" | ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependent.h'. # Do two passes, one to just change these to # '$object: dependent.h' and one to simply 'dependent.h:'. sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'. # However on # $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\': # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... # tcc 0.9.26 (FIXME still under development at the moment of writing) # will emit a similar output, but also prepend the continuation lines # with horizontal tabulation characters. "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form 'foo.o: dependent.h', # or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'. # Do two passes, one to just change these to # '$object: dependent.h' and one to simply 'dependent.h:'. sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \ < "$tmpdepfile" > "$depfile" sed ' s/[ '"$tab"'][ '"$tab"']*/ /g s/^ *// s/ *\\*$// s/^[^:]*: *// /^$/d /:$/d s/$/ :/ ' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then # With Tru64 cc, shared objects can also be used to make a # static library. This mechanism is used in libtool 1.4 series to # handle both shared and static libraries in a single compilation. # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. # # With libtool 1.5 this exception was removed, and libtool now # generates 2 separate objects for the 2 libraries. These two # compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 tmpdepfile2=$dir$base.o.d # libtool 1.5 tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.o.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d tmpdepfile4=$dir$base.d "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test "$stat" = 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' "$nl" < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: mjpegtools-2.1.0/mjpegtools.spec0000644000175000017500000001164212217306441017254 0ustar glowwormglowworm%define name mjpegtools %define version 2.1.0 %define release 1 %define infoentry "* mjpeg-howto: (mjpeg-howto). How to use the mjpeg tools" %define infofile mjpeg-howto.info %define __os_install_post %{nil} Name: %name Version: %version Release: %release Summary: Tools for recording, editing, playing back and mpeg-encoding video under linux License: GPL Url: http://mjpeg.sourceforge.net/ Group: Video Source0: http://prdownloads.sourceforge.net/mjpeg/mjpegtools-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-buildroot-%{version}-%{release} Requires: xorg-x11 SDL Requires: libpng libjpeg Requires: glib2 gtk2 Requires: libquicktime Requires: libdv BuildRequires: autoconf automake BuildRequires: xorg-x11-devel SDL-devel BuildRequires: libpng-devel libjpeg-devel BuildRequires: glib2-devel gtk2-devel BuildRequires: gcc-c++ BuildRequires: libquicktime-devel BuildRequires: libdv-devel Prefix: %{_prefix} %description The MJPEG-tools are a basic set of utilities for recording, editing, playing back and encoding (to mpeg) video under linux. Recording can be done with zoran-based MJPEG-boards (LML33, Iomega Buz, Pinnacle DC10(+), Marvel G200/G400), these can also playback video using the hardware. With the rest of the tools, this video can be edited and encoded into mpeg1/2. With tools from you can create mor formats. %prep %setup -q -n %{name}-%{version} mkdir usr %build tmp_prefix="`pwd`/usr" mkdir -p $tmp_prefix/{include,lib,bin,share} CFLAGS="${CFLAGS:-%optflags}" ; export CFLAGS CXXFLAGS="${CXXFLAGS:-%optflags}" ; export CXXFLAGS ./configure --prefix=%{_prefix} make %install [ -n "${RPM_BUILD_ROOT}" -a "${RPM_BUILD_ROOT}" != / ] \ && rm -rf ${RPM_BUILD_ROOT}/ make prefix=${RPM_BUILD_ROOT}%{prefix} INSTALL_INFO= install %post /sbin/install-info \ --entry=%{infoentry} \ --info-dir=%{_prefix}/share/info \ %{_prefix}/share/info/%{infofile} /sbin/ldconfig %postun /sbin/install-info \ --remove \ --info-dir=%{_prefix}/share/info \ %{_prefix}/share/info/%{infofile} %clean [ -n "${RPM_BUILD_ROOT}" -a "${RPM_BUILD_ROOT}" != / ] \ && rm -rf ${RPM_BUILD_ROOT}/ %files %defattr(-,root,root) %doc AUTHORS BUGS CHANGES COPYING HINTS PLANS README TODO README.* %{_bindir}/lav* %{_bindir}/yuv* %{_bindir}/jpeg2yuv %{_bindir}/y4m* %{_bindir}/ppm* %{_bindir}/glav %{_bindir}/ypipe %{_bindir}/mp* %{_bindir}/*toy4m %{_bindir}/png2yuv %{_bindir}/anytovcd.sh %{_bindir}/mjpeg_simd_helper %{_bindir}/*.flt %{_libdir}/*.so.* %{_prefix}/share/man/man1/* %{_prefix}/share/man/man5/* %{_prefix}/share/info/ %package devel Summary: Development headers and libraries for the mjpegtools Group: Development/Libraries %description devel This package contains static libraries and C system header files needed to compile applications that use part of the libraries of the mjpegtools package. %files devel %{_includedir}/mjpegtools/*.h %{_includedir}/mjpegtools/mpeg2enc/*.hh %{_includedir}/mjpegtools/mpeg2enc/*.h %{_includedir}/mjpegtools/mplex/*.hpp %{_libdir}/pkgconfig/*.pc %{_libdir}/*.a %exclude %{_libdir}/*.la %{_libdir}/*.so %changelog * Sat Sep 21 2013 Bernhard Praschinger This some more change for the release made * Sat Nov 17 2012 Bernhard Praschinger This release has no major change, but a lot of bugfixes. A lot of patches and fixes are included. There are no major changes, but some small enhancements. Steven Schultz added y4mscaler to the CVS and included it to the build process * Sat May 21 2011 Bernhard Praschinger This is it, after more than 10 years on Sourcefogre we named this release 2.0.0. For further changes and fixes please take a look at the Changelog. * Tue Dec 02 2008 Bernhard Praschinger No we have everything together to release a new RC4 That will be very close to the next relase. There are much changes for new CPU's * Fri Jun 02 2006 Steven Schultz jpeg-mmx is not supported, it crashes on IA32 systems, will not build on X86_64 or PPC systems and even when it did work didn't provide much of a speedup (jpeg decoding is a small portion of the overall encoding process). * Fri Dec 19 2003 Ronald Bultje - add everything for mpeg2enc/mplex libs (dev headers and so on) * Sat Aug 23 2003 Ronald Bultje - Remove quicktime4linux hacks, add libquicktime depdency - Remove avifile leftovers * Wed May 20 2002 Thomas Vander Stichele - Added BuildRequires and Requires * Tue Feb 12 2002 Geoffrey T. Dairiki - Fix spec file to build in one directory, etc... * Thu Dec 06 2001 Ronald Bultje - separated mjpegtools and mjpegtools-devel - added changes by Marcel Pol for cleaner RPM build * Wed Jun 06 2001 Ronald Bultje - 1.4.0-final release, including precompiled binaries (deb/rpm) mjpegtools-2.1.0/PLANS0000644000175000017500000000253510107241053015007 0ustar glowwormglowworm(Gernot Ziegler speaking) These are some of my new ideas, I don't know if I am going to realize them - ever: .) Plugins for GIMP .) Blender output plugin -> 22 kHz, 11kHz reading functions ... -> multiplexing functions .) "Normal" read/write support (position in the file, and then start writing over there (needs a new internal writing position info)) .) (frozen because of assumed low demand) Read/write support with a special feature: If the new written frame is smaller than the old one, preserve the old filestructure, and mark the rest of the unused old filespace as "junk", which can be reused the next time -> allows a new kind of clipping in without having to render a new movie all the time . Long, in the far distant future: Program a Virtual File system with these features mjpeg: .) Real support for interlaced playback .) Hardware YUV-RGB-conversion ? .) jpeg compression (Andrew Stevens speaking) .) Proper integration of the output patches into the ac3dec and mpeg2dec code-bases. Construction of a title extraction tool for reading DVD's (based on dxr2 code-base)? .) Support for SSE instructions on Pentium-III. .) Scene change detection and dynamic GOP structure adjustment. .) Support for parallel encoding on multi-CPU machines. .) Optimisation of DCT/iDCT to avoid unnecessary transpositions? mjpegtools-2.1.0/configure.ac0000644000175000017500000005274012217263512016510 0ustar glowwormglowwormdnl Process this file with autoconf to produce a configure script. AC_INIT([mjpegtools],[2.1.0],[mjpeg-developer@lists.sourceforge.net]) AC_PREREQ(2.57) AC_CONFIG_SRCDIR([lavtools/lav_io.c]) MJPEG_MAJOR_VERSION=2 MJPEG_MINOR_VERSION=1 MJPEG_MICRO_VERSION=0 MJPEG_VERSION=$MJPEG_MAJOR_VERSION.$MJPEG_MINOR_VERSION.$MJPEG_MICRO_VERSION AC_CONFIG_HEADERS([config.h]) AC_CANONICAL_HOST AM_INIT_AUTOMAKE([1.7]) AM_MAINTAINER_MODE # libtool versioning LT_RELEASE=$MJPEG_MAJOR_VERSION.$MJPEG_MINOR_VERSION LT_CURRENT=$MJPEG_MICRO_VERSION LT_REVISION=$MJPEG_MICRO_VERSION LT_AGE=$MJPEG_MICRO_VERSION AC_SUBST(LT_RELEASE) AC_SUBST(LT_CURRENT) AC_SUBST(LT_REVISION) AC_SUBST(LT_AGE) AC_SUBST(LT_STATIC) dnl ********************************************************************** dnl Options AC_ARG_ENABLE(compile-warnings, AC_HELP_STRING([--enable-compile-warnings], [Turn on compiler warnings.])) AC_ARG_ENABLE(warnings_as_errors, AC_HELP_STRING([--enable-warnings_as_errors], [Compiler warnings are errors.])) AC_ARG_ENABLE(static-build, AC_HELP_STRING([--enable-static-build], [Force static linkage instead of shared libraries (useful for profiling etc).])) AC_ARG_ENABLE(simd-accel, AC_HELP_STRING([--enable-simd-accel], [use SIMD multimedia instructions (MMX, AltiVec, etc.) if possible])) AC_ARG_WITH(extra-cflags, AC_HELP_STRING([--with-extra-cflags=flags], [Options to be added to CFLAGS (optional)])) AC_ARG_WITH(libquicktime, AC_HELP_STRING([--without-libquicktime], [Do not use libquicktime.]), [], [with_libquicktime=yes]) AC_ARG_WITH(libdv, AC_HELP_STRING([--without-libdv], [Do not use libdv.]), [], [with_libdv=yes]) AC_ARG_WITH(libpng, AC_HELP_STRING([--without-libpng], [Do not use libpng.]), [], [with_libpng=yes]) AC_ARG_WITH(dga, AC_HELP_STRING([--without-dga], [Do not use dga.]), [], [with_dga=yes]) AC_ARG_WITH(gtk, AC_HELP_STRING([--without-gtk], [Do not use gtk.]), [], [with_gtk=yes]) AC_ARG_WITH(libsdl, AC_HELP_STRING([--without-libsdl], [Do not use libsdl.]), [], [with_libsdl=yes]) AC_ARG_WITH(sdlgfx, AC_HELP_STRING([--without-sdlgfx], [Do not use sdlgfx.]), [], [with_sdlgfx=yes]) AC_GNU_SOURCE dnl Initialize libtool AC_PROG_LIBTOOL dnl Checks for programs. AC_PROG_AWK AC_PROG_CC # automake 1.9 could use AM_PROG_STDC but 1.10 became picky and needs CC_C_0 AM_PROG_CC_C_O # AM_PROG_CC_STDC AC_PROG_CXX AC_PROG_INSTALL AC_PROG_LN_S AC_C_BIGENDIAN AC_C_CONST AC_C_INLINE AC_SYS_LARGEFILE dnl configure AS and ASFLAGS... AM_PROG_AS if test x"$with_extra_cflags" != "x"; then CFLAGS="$CFLAGS $with_extra_cflags" CXXFLAGS="$CXXFLAGS $with_extra_cflags" CCASFLAGS="$CCASFLAGS $with_extra_cflags" fi AC_CHECK_HEADERS([stdint.h inttypes.h sys/types.h getopt.h malloc.h sys/soundcard.h]) #maddog: check for math lib, and add it to LIBS (needed for fmax, lround...) #maddog: (How does this interact with cpml stuff below???????) AC_CHECK_LIB([m],[sin]) AC_CHECK_FUNCS([posix_memalign memalign fmax fmin lround]) AC_CHECK_FUNC(getopt_long, [AC_DEFINE(HAVE_GETOPT_LONG, 1, [long getopt support])], [ # FreeBSD and BSD/OS have a gnugetopt library for this: AC_CHECK_LIB([gnugetopt], [getopt_long], [AC_DEFINE(HAVE_GETOPT_LONG, 1, [long getopt support]) LIBGETOPT_LIB="-lgnugetopt"]) ]) AC_SUBST(LIBGETOPT_LIB) AC_TYPE_SIGNAL AC_MSG_NOTICE([The host is $host $host_cpu $host_vendor $host_os .]) dnl test for alpha architecture, and Compaq Math Library (cpml) -- much faster dnl than GNU libm on this arch. LIBM_LIBS="-lm " AC_SUBST(LIBM_LIBS) AC_MSG_CHECKING([for alpha architecture]) case $host in alpha*-*-linux-*) AC_MSG_RESULT([yes]) AC_CHECK_LIB(cpml, asin, [ LIBM_LIBS="-lcpml" have_cpml=true ],,) ;; *) AC_MSG_RESULT([no]) ;; esac dnl ********************************************************************* dnl Some host-specific tweaks: dnl o OS-X/Darwin needs "-no-cpp-precomp" to avoid compile errors. dnl o (e.g) Cygwin shared libs cannot have undefined symbols, libtool only dnl builds them if really given flag to force this (see ltmain.sh) dnl This also requires inter-library dependency to be indicated in _LIBADD; dnl (probably good libtool practice in any case) to have all symbols satisfied dnl o Linux handles with or without this flag, but at least on OS-X/Darwin dnl altivec (utils) can cause circular library dependency (with mpeg2enc), dnl so better limit this flag dnl ********************************************************************* case $host in *-apple-darwin*) CFLAGS="$CFLAGS -no-cpp-precomp" ;; *-unknown-netbsdelf2.*) LIBS="-lossaudio" ;; *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) EXTRA_LDFLAGS="-no-undefined" ;; esac AC_SUBST(EXTRA_LDFLAGS) dnl ********************************************************************* dnl Test whether we're linux or not. If so, define HAVE_V4L and build the dnl video4linux/hardware dependent tools. Else, undefine HAVE_V4L have_video4linux=false AC_ARG_WITH([v4l], AC_HELP_STRING([--without-v4l], [Disable v4l1 API])) AS_IF([test "x$with_v4l" != "xno"], [ case $host in *-*-linux*) AC_CHECK_HEADER(linux/videodev.h, [have_video4linux=true AC_DEFINE(HAVE_V4L, 1, [Building for Linux - using the video4linux API])], []) ;; esac]) AS_IF([test "x$have_video4linux" != "xtrue" && test "x$with_v4l" != "xno"], [have_video4linux=false AC_MSG_WARN([videodev.h not found - please install the linux kernel headers programms needing v4l disabled])]) AM_CONDITIONAL(HAVE_V4L, test x$have_video4linux = xtrue) dnl ********************************************************************* dnl Figure out how to build with POSIX threads. dnl (Creates PTHREAD_LIBS, PTHREAD_CFLAGS, PTHREAD_CC, dnl and defines HAVE_PTHREAD.) dnl ********************************************************************* ACX_PTHREAD dnl maddog: The following matches the original pthread-checking behavior dnl in this script, i.e. "If a CFLAG is necessary, use it for dnl *everything*." Hopefully, any CFLAGs will eventually go away. dnl The other option is to stick PTHREAD_CFLAGS/CC in Makefile.am.... CFLAGS="$CFLAGS $PTHREAD_CFLAGS" CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS" CC="$PTHREAD_CC" oldLIBS="$LIBS" LIBS="$LIBS $PTHREAD_LIBS" AC_CHECK_FUNC(pthread_attr_getstacksize, [AC_DEFINE(HAVE_PTHREADSTACKSIZE, 1, [pthread stack sizes accesible])]) LIBS="$oldLIBS" AC_CHECK_LIB(jpeg, jpeg_start_compress, [ JPEG_LIBS="-ljpeg" JPEG_CFLAGS="" have_libjpeg=true ],,) if test x$have_libjpeg != "xtrue"; then AC_MSG_ERROR([JPEG 6b library missing - Go to http://www.ijg.org/]) fi AC_SUBST(JPEG_LIBS) AC_SUBST(JPEG_CFLAGS) PKG_PROG_PKG_CONFIG have_libquicktime=false if test x$with_libquicktime != xno ; then PKG_CHECK_MODULES(LIBQUICKTIME, [libquicktime > 0.9.7], [have_libquicktime=true AC_DEFINE(HAVE_LIBQUICKTIME, 1, [libquicktime > 0.9.7 present])], [have_libquicktime=false]) fi AM_CONDITIONAL(HAVE_LIBQUICKTIME, test x$have_libquicktime = xtrue) dnl ********************************************************************* dnl Check for PNG library dnl (creates LIBPNG_CFLAGS, LIBPNG_LIBS) dnl ********************************************************************* have_libpng=false if test x$with_libpng != xno ; then PKG_CHECK_MODULES(LIBPNG, [libpng], [have_libpng=true], [have_libpng=false]) if test x$have_libpng = xfalse ; then PKG_CHECK_MODULES(LIBPNG, [libpng12], [have_libpng=true], [have_libpng=false]) fi fi AM_CONDITIONAL(HAVE_LIBPNG, test x$have_libpng = xtrue) dnl ********************************************************************* dnl Check for libdv dnl (creates LIBDV_CFLAGS, LIBDV_LIBS; defines HAVE_LIBDV) dnl ********************************************************************* have_libdv=false if test x$with_libdv != xno ; then PKG_CHECK_MODULES(LIBDV, [libdv >= 0.9], [have_libdv=true AC_DEFINE(HAVE_LIBDV, 1, [libdv is present])], [have_libdv=false]) fi dnl ********************************************************************* dnl Look for X Window System. dnl (creates X_CFLAGS, X_PRE_LIBS, X_EXTRA_LIBS, X_LIBS; dnl defines X_DISPLAY_MISSING if no X) dnl ********************************************************************* AC_PATH_XTRA dnl ******************************************************************** dnl Check to see if __progname is provided by the system dnl ******************************************************************** AC_CACHE_CHECK([for __progname], [mjt_cv_extern___progname], [AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[extern char *__progname; puts(__progname);]])], [mjt_cv_extern___progname=yes], [mjt_cv_extern___progname=no])]) if test x$mjt_cv_extern___progname = xyes ; then AC_DEFINE(HAVE___PROGNAME, 1, [Is __progname defined by system?]) fi dnl ******************************************************************** dnl Check for DGA (for v4l-conf) dnl ******************************************************************** have_dga=false if test x$with_dga != xno ; then AC_SUBST(V4LCONF_LIBS) AC_CHECK_LIB(Xxf86dga, XF86DGAQueryExtension, V4LCONF_LIBS="$X_LIBS -lXxf86dga" have_dga="true" AC_DEFINE(HAVE_LIBXXF86DGA,1, [libxf86dga is present]), have_dga="false", $X_LIBS $X_PRE_LIBS -lXext $X_EXTRA_LIBS) fi AM_CONDITIONAL(HAVE_LIBXXF86DGA, test x$have_dga = xtrue) dnl ******************************************************************** dnl Check for Gtk+/glib (for glav). 2.4.0 or greater required (should dnl not be a problem on recent distributions). dnl (defines GTK_CFLAGS and GTK_LIBS) dnl ******************************************************************** have_gtk=false if test x$with_gtk != xno ; then PKG_CHECK_MODULES(GTK, [gtk+-2.0 >= 2.4.0], have_gtk="true", have_gtk="false") fi AM_CONDITIONAL(HAVE_GTK, test x$have_gtk = xtrue) dnl ******************************************************************** dnl Check for the SDL library (for software playback) dnl (defines SDL_CFLAGS and SDL_LIBS) dnl ******************************************************************** have_sdl=false if test x$with_libsdl != xno ; then PKG_CHECK_MODULES(SDL, [sdl > 1.1.3], [have_sdl=true AC_DEFINE(HAVE_SDL, 1, [libsdl > 1.1.3 present])], [have_sdl=false]) fi AM_CONDITIONAL(HAVE_SDL, test x$have_sdl = xtrue) dnl ******************************************************************** dnl Check for SDL_gfx which is used by y4mhist to display a graphical dnl histogram. dnl ******************************************************************** have_sdlgfx=false if test x$with_sdlgfx != xno ; then AC_SUBST(SDLgfx_LIBS) if test x$have_sdl = xtrue; then OLD_LIBS="$LIBS" LIBS="$LIBS -lSDL -lSDL_gfx" AC_CHECK_LIB(SDL_gfx, vlineColor, [SDLgfx_LIBS="-lSDL_gfx" AC_DEFINE(HAVE_SDLgfx, 1, [SDL_gfx library present]) have_sdlgfx=true ],[have_sdlgfx=false]) LIBS="$OLD_LIBS" fi fi AM_CONDITIONAL(HAVE_SDLgfx, test x$have_sdlgfx = xtrue) dnl ******************************************************************** dnl Test for MMX support if an IA32 platform. If on a PPC then look for dnl Altivec support. For the IA32 platform see if gcc understands inline dnl MMX instructions. dnl dnl TODO: host = non intel, target = intel do the checks also? dnl Remember we are checking that the toolchain can generate the dnl code, not whether the host can execute the code, thats done dnl at run time with the exception of the SSE code. have_asm_mmx=false have_x86cpu=false have_altivec=false AC_MSG_CHECKING([Architecture]) case $host_cpu in i[[3-7]]86) AC_MSG_RESULT(IA32) AC_DEFINE(HAVE_X86CPU,1, [Compiling for x86 architecture CPU]) have_x86cpu=true PROGRAM_NOPIC="-fno-PIC" ;; x86_64*) AC_MSG_RESULT(x86_64) AC_DEFINE(HAVE_X86CPU,1, [Compiling for x86-64 architecture CPU]) have_x86cpu=true have_x86_64cpu=true PROGRAM_NOPIC="-fno-PIC" ;; powerpc | powerpc64) AC_MSG_RESULT(PowerPC) AC_DEFINE(HAVE_PPCCPU,1, [Compiling for PowerPC CPU]) have_ppccpu=true PROGRAM_NOPIC="" ;; *) AC_MSG_RESULT(unknown) PROGRAM_NOPIC="" ;; esac dnl Apple's darwin works on multiple hosts now, so add a catchall override dnl after processing normal hosts case $host in *-apple-darwin*) PROGRAM_NOPIC="-mdynamic-no-pic" # dynamic-no-pic is an Apple gcc option ;; esac dnl This flag is used for PROGRAMS not SHARED LIBRARIES. PIC code is required dnl for shared libraries but is slower than non-pic code. Compute bound dnl programs such as yuvdenoise and y4mspatialfilter can use this flag by dnl simply adding programname_CFLAGS=@PROGRAM_NOPIC@ to the Makefile.am AC_SUBST(PROGRAM_NOPIC) if test "$enable_simd_accel" != "false" -a "$enable_simd_accel" != "no" then if test x$have_x86cpu = xtrue then AC_MSG_CHECKING([if C compiler accepts inline MMX assembly]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[__asm__ __volatile__("emms":::"memory");]])], [have_asm_mmx=true], [have_asm_mmx=false]) if test $have_asm_mmx = true; then AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) fi if test $have_asm_mmx = true; then AC_DEFINE(HAVE_ASM_MMX,1,[Inline MMX assembly accepted by C compiler]) fi fi if test x$have_ppccpu = xtrue then AC_MSG_CHECKING([compiler support for AltiVec]) cat > conftest.c < #endif int main() { union { vector signed int v; signed int i; } vi; vi.v = vec_splat_s32(1); return vi.i; } EOF ALTIVEC_CFLAGS="" if $CC -o conftest conftest.c >/dev/null 2>&1; then have_altivec=true elif $CC $CFLAGS -faltivec -maltivec -o conftest conftest.c >/dev/null 2>&1; then # Mac OS X style with -maltivec have_altivec=true ALTIVEC_CFLAGS="-faltivec -maltivec" elif $CC $CFLAGS -faltivec -o conftest conftest.c >/dev/null 2>&1; then # Mac OS X style without -maltivec have_altivec=true ALTIVEC_CFLAGS="-faltivec" elif $CC $CFLAGS -fvec -o conftest conftest.c >/dev/null 2>&1; then # Motorola style have_altivec=true ALTIVEC_CFLAGS="-fvec" elif $CC $CFLAGS -DHAVE_ALTIVEC_H=1 -maltivec -mabi=altivec -o conftest conftest.c >/dev/null 2>&1; then # gcc 3.1 style have_altivec=true ALTIVEC_CFLAGS="-DHAVE_ALTIVEC_H=1 -maltivec -mabi=altivec" fi rm -f conftest*; if test x$have_altivec = xtrue then CFLAGS="$CFLAGS ${ALTIVEC_CFLAGS}" CXXFLAGS="$CXXFLAGS ${ALTIVEC_CFLAGS}" AC_MSG_RESULT(yes) AC_DEFINE(HAVE_ALTIVEC,1, [Inline PPC Altivec primitives available]) else AC_MSG_RESULT(no) fi fi fi dnl ********************************************************************* dnl For x86 and ppc machines check which code model we should use. This is dnl done with the helper script cpuinfo.sh because the logic to do the job dnl correctly is complex and lengthy (about as long as the entire configure.ac dnl file). if test x$have_x86cpu = xtrue -o x$have_ppccpu = xtrue; then if test x$host_alias != x; then dnl This is to allow cross compiling AC_MSG_CHECKING(sub-architecture settings) if test x$have_x86cpu = xtrue; then host_mod_cpu=`echo $host_cpu | tr _ -` ARCHFLAGS="-march=$host_mod_cpu -mcpu=$host_mod_cpu" fi else if test ! -r $srcdir/cpuinfo.sh; then AC_MSG_ERROR([cpuinfo.sh script not found - do a cvs update]) fi AC_MSG_CHECKING(sub-architecture settings) chmod +x $srcdir/cpuinfo.sh if test x$have_x86cpu = xtrue; then ARCHFLAGS=`$srcdir/cpuinfo.sh x86` elif test x$have_ppccpu = xtrue; then ARCHFLAGS=`$srcdir/cpuinfo.sh ppc` fi fi AC_MSG_RESULT($ARCHFLAGS) fi dnl ********************************************************************** dnl Handle forcing static linkage in key places if test "x$enable_static_build" = "xyes" ; then echo "Forcing static linkage..." LT_STATIC=-all-static else echo enable_static_build="\'${enable_static_build}\'" fi dnl ********************************************************************** dnl All the conditional stuff for the Makefiles AM_CONDITIONAL(HAVE_ASM_MMX, test x$have_asm_mmx = xtrue) AM_CONDITIONAL(HAVE_X86CPU, test x$have_x86cpu = xtrue) AM_CONDITIONAL(HAVE_PPCCPU, test x$have_ppccpu = xtrue) AM_CONDITIONAL(HAVE_ALTIVEC, test x$have_altivec = xtrue) # This is a redhat ppc hack - OSX (which also uses gcc4) does NOT have any # of the problems with undefined symbols, etc caused by a misplaced reference # to an encoder routine (next_larger_quant) in the utils/altivec routines. ALTIVEC_EXTRA_LIBS= if test x$have_altivec = xtrue; then ALTIVEC_EXTRA_LIBS=-lmpeg2encpp fi AC_SUBST(ALTIVEC_EXTRA_LIBS) have_v4l_or_sdl=false if test x$have_video4linux = xtrue; then have_v4l_or_sdl=true else if test x$have_sdl = xtrue; then have_v4l_or_sdl=true fi fi AM_CONDITIONAL(HAVE_V4L_OR_SDL, test x$have_v4l_or_sdl = xtrue) dnl ********************************************************************* dnl Check for what warnings we want gcc to use and adjust the CFLAGS dnl as needed. This only works for GCC. dnl We do this last as it can screw up library detection etc... CFLAGS="$ARCHFLAGS $CFLAGS" CXXFLAGS="$ARCHFLAGS $CXXFLAGS" if test "x${GCC}" != "xyes" ; then enable_compile_warnings=no fi AC_MSG_CHECKING(what warning flags to pass to the C compiler) warnCFLAGS= warnCXXFLAGS= if test "x$enable_compile_warnings" != "xno" ; then if test "x$GCC" = "xyes" ; then case "$CFLAGS" in *-Wall*) ;; *) warnCFLAGS="-Wall -Wunused" ;; esac if test "x$enable_compile_warnings" = "xyes" ; then warnCFLAGS="$warnCFLAGS -Wmissing-prototypes -Wmissing-declarations -Wpointer-arith -Wcast-align -Wwrite-strings -Wcast-qual" warnCXXFLAGS="$warnCXXFLAGS -Wmissing-prototypes -Wpointer-arith -Wcast-align -Wwrite-strings -Wcast-qual" fi if test "x$enable_warnings_as_errors" = "xyes" ; then warnCFLAGS="$warnCFLAGS -Werror" warnCXXFLAGS="$warnCXXFLAGS -Werror" fi fi fi AC_MSG_RESULT($warnCFLAGS) AC_MSG_RESULT($warnCXXFLAGS) if test "x$cflags_set" != "xyes" ; then CFLAGS="$CFLAGS $warnCFLAGS" CXXFLAGS="$CXXFLAGS $warnCXXFLAGS" cflags_set=yes fi AC_ARG_ENABLE(assert, AC_HELP_STRING([--disable-assert], [Disable assertions (compile with NDEBUG).]), [ case "$enableval" in yes|no) : ;; *) AC_MSG_ERROR(bad value for --enable-assert) ;; esac ], [ enable_assert=yes ]) if test x"$enable_assert" = x"no"; then NDEBUG=1; fi AC_DEFINE(MJPEGTOOLS,1, [Building mjpegtools]) case x"$NDEBUG" in x"1") AC_DEFINE(NDEBUG,1, [Optimised no DEBUG build, assertions disabled]) ;; esac dnl ********************************************************************** dnl Output a Makefile or two and the lib/header descriptor script dnl ********************************************************************** AC_CONFIG_FILES([ Makefile debian/Makefile debian/control docs/Makefile lavtools/Makefile yuvcorrect/Makefile yuvdenoise/Makefile yuvdeinterlace/Makefile yuvscaler/Makefile y4munsharp/Makefile y4mutils/Makefile yuvfilters/Makefile mpeg2enc/Makefile aenc/Makefile mplex/Makefile scripts/Makefile utils/Makefile utils/altivec/Makefile utils/mmxsse/Makefile y4mdenoise/Makefile y4mscaler/Makefile mjpegtools.pc mjpegtools.spec ]) AC_OUTPUT dnl ************************************************************************ dnl Summarize the config for the user. dnl ************************************************************************ AC_MSG_NOTICE([]) AC_MSG_NOTICE([ MJPEG tools ${VERSION} build configuration :]) AC_MSG_NOTICE([]) if test "$have_x86cpu" = "true" ; then AC_MSG_NOTICE([ - X86 Optimizations:]) AC_MSG_NOTICE([ - MMX/3DNow!/SSE enabled : ${have_asm_mmx}]) fi if test "$have_ppccpu" = "true" ; then AC_MSG_NOTICE([ - PowerPC Optimizations:]) AC_MSG_NOTICE([ - AltiVec enabled : ${have_altivec}]) fi if test x"$ARCHFLAGS" != x; then AC_MSG_NOTICE([ - arch/cpu compiler flags : ${ARCHFLAGS}]) fi if test x"$with_extra_cflags" != "x"; then AC_MSG_NOTICE([ - extra_cflags added to CFLAGS: ${with_extra_cflags}]) fi AC_MSG_NOTICE([ - video4linux recording/playback: ${have_video4linux}]) AC_MSG_NOTICE([ - software MJPEG playback : ${have_sdl}]) AC_MSG_NOTICE([ - Quicktime playback/recording : ${have_libquicktime}]) AC_MSG_NOTICE([ - PNG input support : ${have_libpng}]) AC_MSG_NOTICE([ - AVI MJPEG playback/recording : true (always)]) AC_MSG_NOTICE([ - libDV (digital video) support : ${have_libdv} ]) AC_MSG_NOTICE([ - Gtk+ support for glav : ${have_gtk}]) AC_MSG_NOTICE([]) mjpegtools-2.1.0/README0000644000175000017500000001441012216631543015074 0ustar glowwormglowwormDocumentation Files =================== INSTALL - How to install this package lavtools: Linux Audio and Video TOOLS for Motion JPEG and MPEG ============================================================== Programs for MJPEG recording and playback and simple cut-and-paste editting and MPEG compression of audio and video under Linux. N.b. Only the "lav" programs have been written whooly from scratch. The rest are from diverse open source originals, modified to work with the lav tools edit lists and AVI and quicktime files. Some (especially the MPEG tools) have had also more major perfomance and functionality enhancements. * The lavtools, xlav and utils directories The latest and greatest versions of Rainer Johanni's original lavtools. Plus some extra goodies to link them to the MPEG compression tools. - "lavrec" is a program to record AVI and Quicktime MJPEG files with the Iomega BUZ etc including sound recording from the soundcard. - "lavplay" plays back AVI and Quicktime MJPEG files or "xlav" produced edit files with the Iomega BUZ etc (including sound). - "xlav" in the directory xlav is a GUI for lavplay which permits fast forward/reverse, single frame stepping and simple non-destructive editing. Instead of writing new AVI or Quicktime files xlav creates an "edit list" file with pointers to the relevant bits of the original files. The lav tools and MPEG encoding tools can all work directly with these files as well as Quicktime and AVI files. Since these files have simple plain-text format they can easily be manually editted or use for other tools. - "lavtrans" (in directory utils) converts a mixture of AVI files, Quicktime files or Edit Lists into a single AVI or Quicktime file into single images or into WAV files. - "lavaddwav" (in directory utils) lets you add another soundtrack (a WAV file) to an AVI/Quicktime file - "lavvideo" is a small test application for the video overlay capabilities of your V4L hardware device. - "lav2yuv" decodes AVI and Quicktime MJPEG and edit lists video and outputs it to standard out the simple raw YUV video format expected by the MPEG compressor "mpeg2enc" (see below). - "lav2wav" decodes AVI and Quicktime MJPEG and edit lists video and outputs it to standard out the WAV format expected by the MPEG layer 2 audio compressor "mp2enc" (see below. If you output to a pipe it simply sticks a maxium length in the header. Most programs processing streams will work fine with this, ending cleanly when they reach the actual end. - "lav2dfilter". A median filter for noise reduction. Useful when MPEG encoding TV material. - "v4l-conf" is used in X to set up your video framebuffer address - "yuv2lav", "ypipe" and "transist.flt" for (first decode an mjpeg input file into raw yuv data (lav2yuv)) putting the data of more than one yuv stream together (ypipe), making a transition between the two input streams (transist.flt) and for making an mjpeg file out of the resulting yuv data (yuv2lav). Read README.transist for more info on how to use this. * The scripts directory Turning a video stream captured as MJPEG AVI's or Quicktime files using a capture card into MPEG or transcoding a MPEG-2 file involves several steps and multiple programs. This directory contains several useful shell scripts that automagically do the right thing for common encoding tasks. They're also intended as examples of typical uses. * The mpeg2enc directory - "mpeg2enc" for encoding the output of lav2yuv or suitable output plugins in mpeg2dec to MPEG-1/2 video streams. See the README for further details. In the current beta release MPEG-2 is untested and variable bit-rate probably won't work. HOWEVER: speed and quality for MPEG-1 are really rather good. Encoding 352x288 PAL at 18 fps on a 700Mhz Duron or 11ps on a 450Mhz P-III. * The aenc directory - Contains the source files for "mp2enc" the MPEG-1 layer 2 audio compressor. It is not particularly good as encoders go, but is included for simplicity and completeness. It also has the virtue that for transcoding applications (e.g. AC3 to mp2) it can do sampling rate conversions. You need this to compress audio. In general, however, you'd be better off with the faster and more capable "toolame" encoder. For transcoding applications the good old stand-by "sox" will convert sampling rates very nicely (albeit it'll print a few warnings about incorrect headers if you use it in a pipeline). You may wish to try using your favourite MPEG 1 layer 3 "MP3" encoder for better quality results. However, make sure you use constant bit-rate and turn of any extensions to the format. I have no idea how many players actually cope with layer 3. Drop andrew.stevens@nexgo.de an email if you get it to work! * The mplex directory Contains for the source files the "mplex" multiplexer. This multiplexes (interleaves) MPEG-1/2 video and audio streams into a combined "system stream" that can be played back smoothly. This is *not* quite as trivial a task as it might seem (see the original authors paper on the subject - copy is in the documentation). Note that the program has been pretty heavily modified since then. MPEG-2 multiplexing is implemented but is currently untested. DVD VOB multiplexing (AC3 audio in addition to MPEG) is not implemented. See the README's of the various programs for further details of authorship, usage, and implementation/compilation details. Attention: lavplay is mainly intended to play back files created by lavrec and should also be able to play back MJPEG AVI files created from the Iomega BUZ under Win98 or the xawtv capture tool under linux. The vast majority of AVI/Quicktime files will not be played by lavplay!!! (see http://dix.euro.ru for such codecs) The reason is that lavplay only handles AVI that use an MJPG codec, all other files don't use that codec and can therefore not be played back by the BUZ. * Contact You reach us by email. If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG-tools is: mjpeg-users@lists.sourceforge.net Although little bits have been done by everyone the main work was roughly as follows: lav* : Rainer Johanni and Gernot Ziegler mpeg2enc mplex : Andrew.Stevens@nexgo.de libmjpeg: Gernot Ziegler mjpegtools-2.1.0/acinclude.m40000644000175000017500000011046310105456513016407 0ustar glowwormglowworm dnl ************************************************************************* dnl ************************************************************************* dnl ACX_PTHREAD dnl v1.10 (last modified: 2004-06-16) dnl Steven G. Johnson dnl retrieved from dnl http://www.gnu.org/software/ac-archive/htmldoc/acx_pthread.html dnl ************************************************************************* dnl ************************************************************************* AC_DEFUN([ACX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_SAVE AC_LANG_C acx_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) AC_MSG_RESULT($acx_pthread_ok) if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthread or # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -*) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" ;; pthread-config) AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) if test x"$acx_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [acx_pthread_ok=yes]) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" AC_MSG_RESULT($acx_pthread_ok) if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: threads are created detached by default # and the JOINABLE attribute has a nonstandard name (UNDETACHED). AC_MSG_CHECKING([for joinable pthread attribute]) AC_TRY_LINK([#include ], [int attr=PTHREAD_CREATE_JOINABLE;], ok=PTHREAD_CREATE_JOINABLE, ok=unknown) if test x"$ok" = xunknown; then AC_TRY_LINK([#include ], [int attr=PTHREAD_CREATE_UNDETACHED;], ok=PTHREAD_CREATE_UNDETACHED, ok=unknown) fi if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok, [Define to the necessary symbol if this constant uses a non-standard name on your system.]) fi AC_MSG_RESULT(${ok}) if test x"$ok" = xunknown; then AC_MSG_WARN([we do not know how to create joinable pthreads]) fi AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; esac AC_MSG_RESULT(${flag}) if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with cc_r AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC}) else PTHREAD_CC="$CC" fi AC_SUBST(PTHREAD_LIBS) AC_SUBST(PTHREAD_CFLAGS) AC_SUBST(PTHREAD_CC) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) : else acx_pthread_ok=no $2 fi AC_LANG_RESTORE ])dnl ACX_PTHREAD dnl ************************************************************************* dnl ************************************************************************* dnl AC_PATH_LIB dnl 1.3 (last modified: 2003-11-04) dnl Roger Leigh dnl retrieved from dnl http://www.gnu.org/software/ac-archive/htmldoc/ac_path_lib.html dnl ************************************************************************* dnl ************************************************************************* ## Table of Contents: ## 1. The main macro ## 2. Core macros ## 3. Integrity checks ## 4. Error reporting ## 5. Feature macros ## ------------------ ## ## 1. The main macro. ## ## ------------------ ## # AC_PATH_LIB(LIBRARY, MINIMUM-VERSION, HEADER, CONFIG-SCRIPT, # MODULES, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) # ----------------------------------------------------------- # Check for the presence of libLIBRARY, with a minumum version # MINIMUM-VERSION. # # If needed, use the libconfig script CONFIG-SCRIPT. If the script # needs extra modules specifying, pass them as MODULES. # # Run ACTION-IF-FOUND if the library is present and all tests pass, or # ACTION-IF-NOT-FOUND if it is not present or any tests fail. AC_DEFUN([AC_PATH_LIB],[# check for presence of lib$1 dnl We're going to need uppercase, lowercase and user-friendly dnl versions of the string `LIBRARY', and long and cache variants. m4_pushdef([UP], m4_translit([$1], [a-z], [A-Z]))dnl m4_pushdef([DOWN], m4_translit([$1], [A-Z], [a-z]))dnl m4_pushdef([LDOWN], ac_path_lib_[]DOWN)dnl m4_pushdef([CACHE], ac_cv_path_lib_[]DOWN)dnl m4_pushdef([ERRORLOG], error.[]DOWN[]test)dnl _AC_PATH_LIB_INIT([$1], [$3], [$4]) _AC_PATH_LIB_CHECK([$1], [$2], [$5]) _AC_PATH_LIB_CHECK_TESTS([$2]) _AC_PATH_LIB_ERROR_DUMP _AC_PATH_LIB_FINI([$6], [$7]) dnl Pop the macros we defined earlier. m4_popdef([UP])dnl m4_popdef([DOWN])dnl m4_popdef([LDOWN])dnl m4_popdef([CACHE])dnl m4_popdef([ERRORLOG])dnl ])# AC_PATH_LIB ## --------------- ## ## 2. Core macros. ## ## --------------- ## # _AC_PATH_LIB_INIT(LIBRARY, HEADER, CONFIG-SCRIPT) # ----------------------------------------- # Initialisation of defaults and options. # Remove error log from previous runs. AC_DEFUN([_AC_PATH_LIB_INIT], [_AC_PATH_LIB_DEFAULTS([$1], [$2], [$3]) _AC_PATH_LIB_OPTIONS rm -f ERRORLOG # Save variables in case check fails. ac_save_[]UP[]_CFLAGS="$UP[]_CFLAGS" ac_save_[]UP[]_LIBS="$UP[]_LIBS" ac_save_[]UP[]_VERSION="$UP[]_VERSION" ]) # _AC_PATH_LIB_DEFAULTS(LIBRARY, HEADER, CONFIG-SCRIPT) # ----------------------------------------------------- # Set up default behaviour. AC_DEFUN([_AC_PATH_LIB_DEFAULTS], [dnl Set up pkgconfig as default config script. m4_ifdef([AC_PATH_LIB_USEPKGCONFIG],, [AC_PATH_LIB_PKGCONFIG]) dnl Set default header and config script names. LDOWN[]_header="m4_default([$2], [$1/$1.h])" LDOWN[]_config="m4_default([$3], [$1-config])" ifdef([_AC_PATH_LIB_VERSION_PREFIX],, [m4_define([_AC_PATH_LIB_VERSION_PREFIX], DOWN[_]) ]) ifdef([_AC_PATH_LIB_VERSION_MAJOR],, [m4_define([_AC_PATH_LIB_VERSION_MAJOR], [major]) ]) ifdef([_AC_PATH_LIB_VERSION_MINOR],, [m4_define([_AC_PATH_LIB_VERSION_MINOR], [minor]) ]) ifdef([_AC_PATH_LIB_VERSION_MICRO],, [m4_define([_AC_PATH_LIB_VERSION_MICRO], [micro]) ]) ifdef([_AC_PATH_LIB_VERSION_SUFFIX],, [m4_define([_AC_PATH_LIB_VERSION_SUFFIX], [_version]) ]) ifdef([_AC_PATH_LIB_DEFVERSION_PREFIX],, [m4_define([_AC_PATH_LIB_DEFVERSION_PREFIX], UP[_]) ]) ifdef([_AC_PATH_LIB_DEFVERSION_MAJOR],, [m4_define([_AC_PATH_LIB_DEFVERSION_MAJOR], [MAJOR]) ]) ifdef([_AC_PATH_LIB_DEFVERSION_MINOR],, [m4_define([_AC_PATH_LIB_DEFVERSION_MINOR], [MINOR]) ]) ifdef([_AC_PATH_LIB_DEFVERSION_MICRO],, [m4_define([_AC_PATH_LIB_DEFVERSION_MICRO], [MICRO]) ]) ifdef([_AC_PATH_LIB_DEFVERSION_SUFFIX],, [m4_define([_AC_PATH_LIB_DEFVERSION_SUFFIX], [_VERSION]) ]) ])# _AC_PATH_LIB_DEFAULTS # _AC_PATH_LIB_OPTIONS # -------------------- # configure options. AC_DEFUN([_AC_PATH_LIB_OPTIONS], [m4_if(AC_PATH_LIB_USEPKGCONFIG, [true], , [AC_ARG_WITH(DOWN-prefix, AC_HELP_STRING([--with-DOWN-prefix=PFX], [prefix where UP is installed (optional)]), [LDOWN[]_config_prefix="$withval"], [LDOWN[]_config_prefix=""])dnl AC_ARG_WITH(DOWN-exec-prefix, AC_HELP_STRING([--with-DOWN-exec-prefix=PFX], [exec-prefix where UP is installed (optional)]), [LDOWN[]_config_exec_prefix="$withval"], [LDOWN[]_config_exec_prefix=""])dnl ]) AC_ARG_ENABLE(DOWN[]test, AC_HELP_STRING([--disable-DOWN[]test], [do not try to compile and run a test UP program]), [LDOWN[]_test_enabled="no"], [LDOWN[]_test_enabled="yes"])dnl ])# _AC_PATH_LIB_OPTIONS # _AC_PATH_LIB_CHECK(LIBRARY, MINIMUM-VERSION, MODULES) # ----------------------------------------------------- # Obtain library CFLAGS, LIBS and VERSION information. Cache results, # but set avoidcache to no if config program is not available. Break # up available and minumum version into major, minor and micro version # numbers. AC_DEFUN([_AC_PATH_LIB_CHECK], [ # Set up LIBRARY-config script parameters m4_if([$3], , , [LDOWN[]_config_args="$LDOWN[]_config_args $3"]) LDOWN[]_min_version=`echo "$2" | sed -e 's/ -nocheck//'` m4_if([$2], , ,[if test "$LDOWN[]_min_version" = "$2" ; then LDOWN[]_version_test_enabled="yes" fi]) m4_if(AC_PATH_LIB_USEPKGCONFIG, [true], [LDOWN[]_config_args="$1 $LDOWN[]_config_args" ], [ if test x$LDOWN[]_config_exec_prefix != x ; then LDOWN[]_config_args="$LDOWN[]_config_args --exec-prefix=$LDOWN[]_config_exec_prefix" fi if test x$LDOWN[]_config_prefix != x ; then LDOWN[]_config_args="$LDOWN[]_config_args --prefix=$LDOWN[]_config_prefix" fi ]) dnl set --version for libconfig or --modversion for pkgconfig m4_if(AC_PATH_LIB_USEPKGCONFIG, [true], [AC_PATH_PROG(PKG_CONFIG, pkg-config, no) if test x$PKG_CONFIG != xno ; then if pkg-config --atleast-pkgconfig-version 0.7 ; then : else AC_PATH_LIB_ERROR([A new enough version of pkg-config was not found:]) AC_PATH_LIB_ERROR([version 0.7 or better required.]) AC_PATH_LIB_ERROR([See http://pkgconfig.sourceforge.net]) PKG_CONFIG=no fi fi UP[]_CONFIG="$PKG_CONFIG" LDOWN[]_config="pkg-config" m4_pushdef([LIBCONFIG_CFLAGS], [--cflags]) m4_pushdef([LIBCONFIG_LIBS], [--libs]) m4_pushdef([LIBCONFIG_VERSION], [--modversion]) ], [AC_PATH_PROG(UP[]_CONFIG, $LDOWN[]_config, no) m4_pushdef([LIBCONFIG_CFLAGS], [--cflags]) m4_pushdef([LIBCONFIG_LIBS], [--libs]) m4_pushdef([LIBCONFIG_VERSION], [--version]) if test x$UP[]_CONFIG = xno ; then AC_PATH_LIB_ERROR([The $LDOWN[]_config script installed by UP could not be found.]) AC_PATH_LIB_ERROR([If UP was installed in PREFIX, make sure PREFIX/bin is in]) AC_PATH_LIB_ERROR([your path, or set the UP[]_CONFIG environment variable to the]) AC_PATH_LIB_ERROR([full path to $LDOWN[]_config.]) fi ]) if test x$UP[]_CONFIG = xno ; then LDOWN[]_present_avoidcache="no" else LDOWN[]_present_avoidcache="yes" AC_CACHE_CHECK([for UP CFLAGS], [CACHE[]_cflags], [CACHE[]_cflags=`$UP[]_CONFIG $LDOWN[]_config_args LIBCONFIG_CFLAGS`]) AC_CACHE_CHECK([for UP LIBS], [CACHE[]_libs], [CACHE[]_libs=`$UP[]_CONFIG $LDOWN[]_config_args LIBCONFIG_LIBS`]) AC_CACHE_CHECK([for UP VERSION], [CACHE[]_version], [CACHE[]_version=`$UP[]_CONFIG $LDOWN[]_config_args LIBCONFIG_VERSION`]) UP[]_CFLAGS="$CACHE[]_cflags" UP[]_LIBS="$CACHE[]_libs" UP[]_VERSION="$CACHE[]_version" LDOWN[]_config_major_version=`echo "$CACHE[]_version" | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` LDOWN[]_config_minor_version=`echo "$CACHE[]_version" | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` LDOWN[]_config_micro_version=`echo "$CACHE[]_version" | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` LDOWN[]_min_major_version=`echo "$LDOWN[]_min_version" | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` LDOWN[]_min_minor_version=`echo "$LDOWN[]_min_version" | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` LDOWN[]_min_micro_version=`echo "$LDOWN[]_min_version" | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` fi m4_popdef([LIBCONFIG_CFLAGS])dnl m4_popdef([LIBCONFIG_LIBS])dnl m4_popdef([LIBCONFIG_VERSION])dnl ])# _AC_PATH_LIB_CHECK # _AC_PATH_LIB_FINI(ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) # ------------------------------------------------------- # Finish: report errors and define/substitute variables. Run any # user-supplied code for success or failure. Restore defaults. AC_DEFUN([_AC_PATH_LIB_FINI], [dnl define variables and run extra code UP[]_CFLAGS="$CACHE[]_cflags" UP[]_LIBS="$CACHE[]_libs" UP[]_VERSION="$CACHE[]_version" AC_SUBST(UP[]_CFLAGS)dnl AC_SUBST(UP[]_LIBS)dnl AC_SUBST(UP[]_VERSION)dnl # Run code which depends upon the test result. if test x$CACHE[]_present = xyes ; then m4_if([$1], , :, [$1]) else # Restore saved variables if test fails UP[]_CFLAGS="$ac_save_[]UP[]_CFLAGS" UP[]_LIBS="$ac_save_[]UP[]_LIBS" UP[]_VERSION="$ac_save_[]UP[]_VERSION" m4_if([$2], , :, [$2]) fi dnl Restore defaults AC_PATH_LIB_CHECK_REGISTER_DEFAULTS AC_PATH_LIB_PKGCONFIG ])# _AC_PATH_LIB_FINI ## -------------------- ## ## 3. Integrity checks. ## ## -------------------- ## # _AC_PATH_LIB_CHECK_TESTS(MINIMUM-VERSION) # ----------------------------------------- # Now check if the installed UP is sufficiently new. (Also sanity # checks the results of DOWN-config to some extent AC_DEFUN([_AC_PATH_LIB_CHECK_TESTS], [AC_CACHE_CHECK([for UP - m4_if([$1], , [any version], [version >= $LDOWN[]_min_version])], [CACHE[]_present], [CACHE[]_present="$LDOWN[]_present_avoidcache" if test x$CACHE[]_present = xyes -a x$LDOWN[]_test_enabled = xyes -a \ x$LDOWN[]_version_test_enabled = xyes ; then m4_default([_AC_PATH_LIB_CHECK_TEST_COMPILE], [_AC_PATH_LIB_CHECK_TEST_COMPILE], [_AC_PATH_LIB_CHECK_TEST_COMPILE_DEFAULT]) else m4_default([_AC_PATH_LIB_CHECK_VERSION], [_AC_PATH_LIB_CHECK_VERSION], [_AC_PATH_LIB_CHECK_VERSION_DEFAULT]) # If the user allowed it, try linking with the library if test x$LDOWN[]_test_enabled = xyes ; then _AC_PATH_LIB_CHECK_LINK(, [ CACHE[]_present="no" if test x$LDOWN[]_version_test_error = xyes ; then AC_PATH_LIB_ERROR fi AC_PATH_LIB_ERROR([The test program failed to compile or link. See the file]) AC_PATH_LIB_ERROR([config.log for the exact error that occured. This usually]) AC_PATH_LIB_ERROR([means UP was not installed, was incorrectly installed]) AC_PATH_LIB_ERROR([or that you have moved UP since it was installed. In]) AC_PATH_LIB_ERROR([the latter case, you may want to edit the $LDOWN[]_config]) AC_PATH_LIB_ERROR([script: $UP[]_CONFIG]) ]) fi fi]) dnl end tests ])# _AC_PATH_LIB_CHECK_TESTS # _AC_PATH_LIB_CHECK_TEST_COMPILE_DEFAULT # --------------------------------------- # Check if the installed UP is sufficiently new. (Also sanity checks # the results of DOWN-config to some extent. The test program must # compile, link and run sucessfully AC_DEFUN([_AC_PATH_LIB_CHECK_TEST_COMPILE], [m4_pushdef([RUNLOG], run.[]DOWN[]test)dnl m4_pushdef([MAJOR], _AC_PATH_LIB_VERSION_PREFIX[]_AC_PATH_LIB_VERSION_MAJOR[]_AC_PATH_LIB_VERSION_SUFFIX)dnl m4_pushdef([MINOR], _AC_PATH_LIB_VERSION_PREFIX[]_AC_PATH_LIB_VERSION_MINOR[]_AC_PATH_LIB_VERSION_SUFFIX)dnl m4_pushdef([MICRO], _AC_PATH_LIB_VERSION_PREFIX[]_AC_PATH_LIB_VERSION_MICRO[]_AC_PATH_LIB_VERSION_SUFFIX)dnl m4_pushdef([DEFMAJOR], _AC_PATH_LIB_DEFVERSION_PREFIX[]_AC_PATH_LIB_DEFVERSION_MAJOR[]_AC_PATH_LIB_DEFVERSION_SUFFIX)dnl m4_pushdef([DEFMINOR], _AC_PATH_LIB_DEFVERSION_PREFIX[]_AC_PATH_LIB_DEFVERSION_MINOR[]_AC_PATH_LIB_DEFVERSION_SUFFIX)dnl m4_pushdef([DEFMICRO], _AC_PATH_LIB_DEFVERSION_PREFIX[]_AC_PATH_LIB_DEFVERSION_MICRO[]_AC_PATH_LIB_DEFVERSION_SUFFIX)dnl ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $UP[]_CFLAGS" LIBS="$UP[]_LIBS $LIBS" rm -f RUNLOG AC_TRY_RUN([ #include <$]LDOWN[_header> #include #include /* * XXX FIXME Francesco: * This is a pigsty patch for undefined strdup (defined in string.h). * Maybe we should look for strdup() or wrapping it using functions * like malloc && strcpy(). */ #include int main () { int major, minor, micro; char *tmp_version; FILE *errorlog; if ((errorlog = fopen("]ERRORLOG[", "w")) == NULL) { exit(1); } system ("touch ]RUNLOG["); /* HP/UX 9 (%@#!) writes to sscanf strings */ tmp_version = strdup("$]LDOWN[_min_version"); if (!tmp_version) { exit(1); } if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { fprintf(errorlog, "*** %s: bad version string\n", "$]LDOWN[_min_version"); exit(1); } if ((]MAJOR[ != $]LDOWN[_config_major_version) || (]MINOR[ != $]LDOWN[_config_minor_version) || (]MICRO[ != $]LDOWN[_config_micro_version)) { fprintf(errorlog, "*** '$]UP[_CONFIG ]LIBCONFIG_VERSION[' returned %d.%d.%d, but \n", \ $]LDOWN[_config_major_version, $]LDOWN[_config_minor_version, \ $]LDOWN[_config_micro_version); fprintf(errorlog, "*** ]UP[ (%d.%d.%d) was found!\n", \ ]MAJOR[, ]MINOR[, ]MICRO[); fprintf(errorlog, "***\n"); fprintf(errorlog, "*** If $]LDOWN[_config was correct, then it is best to remove\n"); fprintf(errorlog, "*** the old version of ]UP[. You may also be able to\n"); fprintf(errorlog, "*** fix the error by modifying your LD_LIBRARY_PATH enviroment\n"); fprintf(errorlog, "*** variable, or by editing /etc/ld.so.conf. Make sure you have\n"); fprintf(errorlog, "*** run ldconfig if that is required on your system.\n"); fprintf(errorlog, "*** If $]LDOWN[_config was wrong, set the environment\n"); fprintf(errorlog, "*** variable ]UP[_CONFIG to point to the correct copy of\n"); fprintf(errorlog, "*** $]LDOWN[_config, and remove the file config.cache\n"); fprintf(errorlog, "*** before re-running configure.\n"); } #if defined (]DEFMAJOR[) && defined (]DEFMINOR[) && defined (]DEFMICRO[) else if ((]MAJOR[ != ]DEFMAJOR[) || (]MINOR[ != ]DEFMINOR[) || (]MICRO[ != ]DEFMICRO[)) { fprintf(errorlog, "*** ]UP[ header files (version %d.%d.%d) do not match\n", ]DEFMAJOR[, ]DEFMINOR[, ]DEFMICRO[); fprintf(errorlog, "*** library (version %d.%d.%d)\n", ]MAJOR[, ]MINOR[, ]MICRO[); } #endif /* defined (]DEFMAJOR[) ... */ else { if ((]MAJOR[ > major) || ((]MAJOR[ == major) && (]MINOR[ > minor)) || ((]MAJOR[ == major) && (]MINOR[ == minor) && (]MICRO[ >= micro))) { return 0; } else { fprintf(errorlog, "*** An old version of ]UP[ (%d.%d.%d) was found.\n", ]MAJOR[, ]MINOR[, ]MICRO[); fprintf(errorlog, "*** You need a version of ]UP[ newer than %d.%d.%d.\n", major, minor, micro); /*fprintf(errorlog, "*** The latest version of ]UP[ is always available from ftp://ftp.my.site\n");*/ fprintf(errorlog, "***\n"); fprintf(errorlog, "*** If you have already installed a sufficiently new version, this\n"); fprintf(errorlog, "*** error probably means that the wrong copy of the $]LDOWN[_config\n"); fprintf(errorlog, "*** shell script is being found. The easiest way to fix this is to\n"); fprintf(errorlog, "*** remove the old version of ]UP[, but you can also set the\n"); fprintf(errorlog, "*** ]UP[_CONFIG environment variable to point to the correct\n"); fprintf(errorlog, "*** copy of $]LDOWN[_config. (In this case, you will have to\n"); fprintf(errorlog, "*** modify your LD_LIBRARY_PATH environment variable, or edit\n"); fprintf(errorlog, "*** /etc/ld.so.conf so that the correct libraries are found at\n"); fprintf(errorlog, "*** run-time.)\n"); } } return 1; } ],, [CACHE[]_present="no"], [AC_PATH_LIB_ERROR([cross compiling; assumed OK.])]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" if test -f RUNLOG ; then : elif test x$LDOWN[]_version_test_enabled = xyes ; then AC_PATH_LIB_ERROR([Could not run UP test program, checking why...]) AC_PATH_LIB_ERROR _AC_PATH_LIB_CHECK_LINK(dnl [AC_PATH_LIB_ERROR([The test program compiled, but did not run. This usually]) AC_PATH_LIB_ERROR([means that the run-time linker is not finding UP or]) AC_PATH_LIB_ERROR([finding the wrong version of UP. If it is not finding]) AC_PATH_LIB_ERROR([UP, you will need to set your LD_LIBRARY_PATH environment]) AC_PATH_LIB_ERROR([variable, or edit /etc/ld.so.conf to point to the installed]) AC_PATH_LIB_ERROR([location. Also, make sure you have run ldconfig if that is]) AC_PATH_LIB_ERROR([required on your system.]) AC_PATH_LIB_ERROR AC_PATH_LIB_ERROR([If you have an old version installed, it is best to remove]) AC_PATH_LIB_ERROR([it, although you may also be able to get things to work by]) AC_PATH_LIB_ERROR([modifying LD_LIBRARY_PATH]) ], [AC_PATH_LIB_ERROR([The test program failed to compile or link. See the file]) AC_PATH_LIB_ERROR([config.log for the exact error that occured. This usually]) AC_PATH_LIB_ERROR([means UP was incorrectly installed or that you have]) AC_PATH_LIB_ERROR([moved UP since it was installed. In the latter case,]) AC_PATH_LIB_ERROR([you may want to edit the $LDOWN[]_config script:]) AC_PATH_LIB_ERROR([$UP[]_CONFIG]) ]) fi rm -f RUNLOG m4_popdef([RUNLOG])dnl m4_popdef([MAJOR])dnl m4_popdef([MINOR])dnl m4_popdef([MICRO])dnl m4_popdef([DEFMAJOR])dnl m4_popdef([DEFMINOR])dnl m4_popdef([DEFMICRO])dnl ])# _AC_PATH_LIB_CHECK_TEST_COMPILE_DEFAULT # _AC_PATH_LIB_CHECK_VERSION_DEFAULT # ---------------------------------- # Check that the library version (config) is greater than or equal to # the requested (minimum) version. AC_DEFUN([_AC_PATH_LIB_CHECK_VERSION], [m4_if([$2], , , [if test x$LDOWN[]_present_avoidcache = xyes ; then if test \ "$LDOWN[]_config_major_version" -lt "$LDOWN[]_min_major_version" -o \ "$LDOWN[]_config_major_version" -eq "$LDOWN[]_min_major_version" -a \ "$LDOWN[]_config_minor_version" -lt "$LDOWN[]_min_minor_version" -o \ "$LDOWN[]_config_major_version" -eq "$LDOWN[]_min_major_version" -a \ "$LDOWN[]_config_minor_version" -eq "$LDOWN[]_min_minor_version" -a \ "$LDOWN[]_config_micro_version" -lt "$LDOWN[]_min_micro_version" ; then CACHE[]_present="no" LDOWN[]_version_test_error="yes" AC_PATH_LIB_ERROR([$UP[]_CONFIG --version' returned $LDOWN[]_config_major_version.$LDOWN[]_config_minor_version.$LDOWN[]_config_micro_version, but]) AC_PATH_LIB_ERROR([UP (>= $LDOWN[]_min_version) was needed.]) AC_PATH_LIB_ERROR AC_PATH_LIB_ERROR([If $]LDOWN[_config was wrong, set the environment]) AC_PATH_LIB_ERROR([variable ]UP[_CONFIG to point to the correct copy of]) AC_PATH_LIB_ERROR([$]LDOWN[_config, and remove the file config.cache]) AC_PATH_LIB_ERROR([before re-running configure.]) else CACHE[]_present="yes" fi fi]) ])# _AC_PATH_LIB_CHECK_VERSION_DEFAULT # _AC_PATH_LIB_CHECK_LINK_DEFAULT(SUCCESS, FAIL) # ---------------------------------------------- # Check if the library will link successfully. If specified, run # SUCCESS or FAIL on success or failure AC_DEFUN([_AC_PATH_LIB_CHECK_LINK], [ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $UP[]_CFLAGS" LIBS="$LIBS $UP[]_LIBS" AC_TRY_LINK([ #include ], , [m4_if([$1], , :, [$1])], [m4_if([$2], , :, [$2])]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" ])# _AC_PATH_LIB_CHECK_LINK_DEFAULT ## ------------------- ## ## 4. Error reporting. ## ## ------------------- ## # AC_PATH_LIB_ERROR(MESSAGE) # -------------------------- # Print an error message, MESSAGE, to the error log. AC_DEFUN([AC_PATH_LIB_ERROR], [echo '*** m4_if([$1], , , [$1])' >>ERRORLOG]) # _AC_PATH_LIB_ERROR_DUMP # ----------------------- # Print the error log (after main AC_CACHE_CHECK completes). AC_DEFUN([_AC_PATH_LIB_ERROR_DUMP], [if test -f ERRORLOG ; then cat ERRORLOG rm -f ERRORLOG fi]) ## ------------------ ## ## 5. Feature macros. ## ## ------------------ ## # AC_PATH_LIB_PKGCONFIG # --------------------- # Enable pkgconfig support in libconfig script (default). AC_DEFUN([AC_PATH_LIB_PKGCONFIG], [m4_define([AC_PATH_LIB_USEPKGCONFIG], [true]) ])dnl # AC_PATH_LIB_LIBCONFIG # --------------------- # Disable pkgconfig support in libconfig script. AC_DEFUN([AC_PATH_LIB_LIBCONFIG], [m4_define([AC_PATH_LIB_USEPKGCONFIG], [false]) ])dnl # AC_PATH_LIB_REGISTER (MACRO, REPLACEMENT) # ----------------------------------------- # Register a macro to replace the default checks. Use the REPLACEMENT # macro for the check macro MACRO. # # Possible MACROs are: # _AC_PATH_LIB_CHECK_COMPILE and # _AC_PATH_LIB_CHECK_VERSION # You should make sure that replacement macros use the same arguments # (if any), and do error logging in the same manner and behave in the # same way as the original. # Non-default header names may be specified, as well as version # variable names in the library itself (needed for # _AC_PATH_LIB_CHECK_COMPILE): # _AC_PATH_LIB_HEADER # _AC_PATH_LIB_VERSION_PREFIX (default library_) # _AC_PATH_LIB_VERSION_MAJOR (default major) # _AC_PATH_LIB_VERSION_MINOR (default minor) # _AC_PATH_LIB_VERSION_MICRO (default micro) # _AC_PATH_LIB_VERSION_SUFFIX (default _version) # _AC_PATH_LIB_DEFVERSION_PREFIX (default LIBRARY_) # _AC_PATH_LIB_DEFVERSION_MAJOR (default MAJOR) # _AC_PATH_LIB_DEFVERSION_MINOR (default MINOR) # _AC_PATH_LIB_DEFVERSION_MICRO (default MICRO) # _AC_PATH_LIB_DEFVERSION_SUFFIX (default _VERSION) # For example, library_major_version. AC_DEFUN([AC_PATH_LIB_REGISTER], [m4_define([$1], [$2])]) # AC_PATH_LIB_CHECK_REGISTER_DEFAULTS # ----------------------------------- # Restore the default check macros. AC_DEFUN([AC_PATH_LIB_CHECK_REGISTER_DEFAULTS], [_AC_PATH_LIB_CHECK_REGISTER_DEFAULTS([_AC_PATH_LIB_CHECK_COMPILE], [_AC_PATH_LIB_CHECK_VERSION], [_AC_PATH_LIB_HEADER], [_AC_PATH_LIB_VERSION_PREFIX], [_AC_PATH_LIB_VERSION_MAJOR], [_AC_PATH_LIB_VERSION_MINOR], [_AC_PATH_LIB_VERSION_MICRO], [_AC_PATH_LIB_VERSION_SUFFIX], [_AC_PATH_LIB_DEFVERSION_PREFIX], [_AC_PATH_LIB_DEFVERSION_MAJOR], [_AC_PATH_LIB_DEFVERSION_MINOR], [_AC_PATH_LIB_DEFVERSION_MICRO], [_AC_PATH_LIB_DEFVERSION_SUFFIX]) ])# AC_PATH_LIB_CHECK_REGISTER_DEFAULTS # _AC_PATH_LIB_CHECK_REGISTER_DEFAULTS(MACROs ...) # ------------------------------------------------ # Undefine MACROs. AC_DEFUN([AC_PATH_LIB_CHECK_REGISTER_DEFAULTS], [m4_if([$1], , , [m4_ifdef([$1], [m4_undefine([$1])]) AC_PATH_LIB_CHECK_REGISTER_DEFAULTS(m4_shift($@)) ]) ]) dnl ************************************************************************* dnl AX_CONFIG_PREFIXED_HEADER and AX_PREFIXED_DEFINE dnl dnl @synopsis AX_CONFIG_PREFIXED_HEADER(OUTPUT, PREFIX, INPUT) dnl @synopsis AX_PREFIXED_DEFINE(PREFIX, SYMBOL) dnl dnl This pair of macros is used to create an installable version of a dnl configure-generated config file (such as the usual 'config.h', which dnl itself should never be installed by a package). dnl dnl The classic example is the creation of a "mypkg-config.h" file dnl which will be installed along with mypkg's other header files. dnl Your configure.ac should contain: dnl dnl AC_CONFIG_HEADERS([config.h]) dnl ... dnl AX_CONFIG_PREFIXED_HEADER([mypkg-config.h], [MYPKG], [config.h]) dnl dnl This declares that 'mypkg-config.h' will be generated at the end of dnl config.status from 'config.h' by prefixing the desired symbols with dnl "MYPKG_". To schedule symbols for inclusion in 'mypkg-config.h', dnl you would add the following to configure.ac: dnl dnl AX_PREFIXED_DEFINE([MYPKG], [HAVE_FEATURE_Q]) dnl ... dnl AX_PREFIXED_DEFINE([MYPKG], [HAVE_ALLOCA_H]) dnl ... dnl AX_PREFIXED_DEFINE([MYPKG], [SPECIAL_PRINTING_STRING]) dnl etc. dnl dnl Each instance of AX_PREFIXED_DEFINE() should correspond to an instance dnl of the usual AC_DEFINE(); the AX_PREFIXED_DEFINE() merely declares that dnl the DEFINE'd symbol should be prefixed with "MYPKG_" and added to the dnl 'mypkg-config.h' output file. dnl dnl AX_CONFIG_PREFIXED_HEADER will only transfer over "#define SYMBOL ..." dnl and "/* #undef SYMBOL ... */" declarations. It will also attempt to dnl transfer an immediately preceding (no intervening blank lines) C-style dnl comment block. dnl dnl The mutual ordering of AC_CONFIG_PREFIXED_HEADER, AC_CONFIG_HEADERS, dnl AX_PREFIXED_DEFINE, and AC_DEFINE is unimportant. All the real work dnl is done at AC_OUTPUT and during execution of config.status. dnl dnl @version v1.0 (last modified: 2004-08-08) dnl @author Matthew Marjanovic dnl dnl ************************************************************************* AC_DEFUN([AX_CONFIG_PREFIXED_HEADER],[dnl AC_CONFIG_COMMANDS([$1],[dnl AS_VAR_PUSHDEF([_OUT],[ax_config_prefixed_OUT])dnl AS_VAR_PUSHDEF([_PFX],[ax_config_prefixed_PFX])dnl AS_VAR_PUSHDEF([_INP],[ax_config_prefixed_INP])dnl AS_VAR_PUSHDEF([_DFN],[ax_config_prefixed_DFN])dnl AS_VAR_PUSHDEF([_TMP],[ax_config_prefixed_TMP])dnl AS_VAR_PUSHDEF([_SCRIPT],[ax_config_prefixed_SCRIPT])dnl _OUT="$1" _PFX=AS_TR_CPP([$2]) _INP=`echo "$3" | sed -e 's/ *//'` _DFN=AS_TR_CPP([_$_OUT]) _TMP="$tmp/$_OUT" _SCRIPT="$tmp/${_OUT}.sed" if test -z "$_PFX" ; then AC_MSG_ERROR([missing prefix in [$0]]) else if test ! -f "$_INP" ; then if test -f "$srcdir/$_INP" ; then _INP="$srcdir/$_INP" fi fi AC_MSG_NOTICE([creating $_OUT (prefix $_PFX for $_INP)]) if test ! -f $_INP ; then AC_MSG_ERROR([input file $_INP does not exist]) else # Create the transformation script cat <<_EOF >$_SCRIPT @%:@ look for requested keywords and prefix them m4_ifdef([_AX_PREFIXED_DEFINE_VARS($2)], [AC_FOREACH([AC_Var], m4_defn([_AX_PREFIXED_DEFINE_VARS($2)]), [s/@%:@\\( *\\)\\(def[]ine\\|undef\\) *\\(AC_Var\\)\\(.*\\)/@%:@\\1\\2 ${_PFX}_\\3 \\4/ ])])dnl @%:@ successful? then go print tPrint @%:@ else, try to collect a comment \\,/\\*, bCommentBegin @%:@ else, clear comment if a blank li[]ne is encountered / */ h d @%:@ Comments: collect lines in hold buffer until end marker found. :CommentBegin \\,\\*/, bCommentEnd N; bCommentBegin :CommentEnd h; d @%:@ append pattern/nl to hold buffer, remove any blank, print, clear hold. :Print s/\\(.*\\)/\\1\\n/ H; x; s/^\\n//; p s/.*//; x; d _EOF # Run _INP through _SCRIPT to create _TMP cat <<_EOF >$_TMP /* $_OUT This is an architecture-specific fi[]le which was generated automatically by configure. Do not edit it manually. */ @%:@ifndef $_DFN @%:@def[]ine $_DFN _EOF sed -nf $_SCRIPT $_INP >>$_TMP cat <<_EOF >>$_TMP @%:@endif /* $_DFN */ _EOF # Check if new output is different from existing... # ...move to destination if so. if cmp -s $_OUT $_TMP 2>/dev/null; then AC_MSG_NOTICE([$_OUT is unchanged]) else ac_dir=`AS_DIRNAME(["$_OUT"])` AS_MKDIR_P(["$ac_dir"]) rm -f "$_OUT" mv "$_TMP" "$_OUT" fi fi fi AS_VAR_POPDEF([_SCRIPT])dnl AS_VAR_POPDEF([_TMP])dnl AS_VAR_POPDEF([_DFN])dnl AS_VAR_POPDEF([_INP])dnl AS_VAR_POPDEF([_PFX])dnl AS_VAR_POPDEF([_OUT])dnl ],[PACKAGE_TARNAME="$PACKAGE_TARNAME"])])# AX_CONFIG_PREFIXED_HEADER AC_DEFUN([AX_PREFIXED_DEFINE], [m4_append_uniq([_AX_PREFIXED_DEFINE_VARS($1)], [$2], [ ])dnl ])# AX_PREFIXED_DEFINE mjpegtools-2.1.0/README.AltiVec0000644000175000017500000000325707765251612016441 0ustar glowwormglowwormAltiVec optimized library for MJPEG tools MPEG-1/2 Video Encoder ----------------------------------------------------------------------------- Copyright (C) 2002 James Klicman Performance statistics for these optimizations are available at http://klicman.org/altivec/. Platform specific comments: Linux: AltiVec enabled compilers are now widely distributed. However, the AltiVec support in the GNU GCC 3.1, 3.2 and even the latest 3.3.1 release all have known bugs which cause invalid code or compile failures. It is likely that release GCC 3.3.2 will be a functional compiler for this AltiVec code. Until then, gcc 2.96.4 with the Motorola AltiVec patches works just fine and may even provide better AltiVec instruction scheduling. There are AltiVec enabled GCC compilers maintained by Kaoru Fukui at ftp://ppc.linux.or.jp/pub/users/fukui/. You will also need a recent binutils package. I've verified that binutils-2.12.90.0.7 works. It is also the recommended version for GCC 3.1. There may also be suitable binutils packages at Kaoru's FTP site. Mac OS X: If you have the developer tools, you're all set. General comments: Additional performance can be gained by setting the -mcpu option. For GCC 2.95.* use -mcpu=750, for GCC 3.1 and higher try -mcpu=7400 or -mcpu=7450. This option can be added during configuration by setting the CFLAGS environment variable. Since the encoder (mpeg2enc) and multiplexor (mplex) are now written in C++ the CXXFLAGS environment variable should also be set. For example: env CFLAGS="-O2 -mcpu=750" CXXFLAGS="-O2 -mcpu=750" ./configure mjpegtools-2.1.0/mjpegtools.spec.in0000644000175000017500000001164512217306351017664 0ustar glowwormglowworm%define name @PACKAGE@ %define version @VERSION@ %define release 1 %define infoentry "* mjpeg-howto: (mjpeg-howto). How to use the mjpeg tools" %define infofile mjpeg-howto.info %define __os_install_post %{nil} Name: %name Version: %version Release: %release Summary: Tools for recording, editing, playing back and mpeg-encoding video under linux License: GPL Url: http://mjpeg.sourceforge.net/ Group: Video Source0: http://prdownloads.sourceforge.net/mjpeg/mjpegtools-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-buildroot-%{version}-%{release} Requires: xorg-x11 SDL Requires: libpng libjpeg Requires: glib2 gtk2 Requires: libquicktime Requires: libdv BuildRequires: autoconf automake BuildRequires: xorg-x11-devel SDL-devel BuildRequires: libpng-devel libjpeg-devel BuildRequires: glib2-devel gtk2-devel BuildRequires: gcc-c++ BuildRequires: libquicktime-devel BuildRequires: libdv-devel Prefix: %{_prefix} %description The MJPEG-tools are a basic set of utilities for recording, editing, playing back and encoding (to mpeg) video under linux. Recording can be done with zoran-based MJPEG-boards (LML33, Iomega Buz, Pinnacle DC10(+), Marvel G200/G400), these can also playback video using the hardware. With the rest of the tools, this video can be edited and encoded into mpeg1/2. With tools from you can create mor formats. %prep %setup -q -n %{name}-%{version} mkdir usr %build tmp_prefix="`pwd`/usr" mkdir -p $tmp_prefix/{include,lib,bin,share} CFLAGS="${CFLAGS:-%optflags}" ; export CFLAGS CXXFLAGS="${CXXFLAGS:-%optflags}" ; export CXXFLAGS ./configure --prefix=%{_prefix} make %install [ -n "${RPM_BUILD_ROOT}" -a "${RPM_BUILD_ROOT}" != / ] \ && rm -rf ${RPM_BUILD_ROOT}/ make prefix=${RPM_BUILD_ROOT}%{prefix} INSTALL_INFO= install %post /sbin/install-info \ --entry=%{infoentry} \ --info-dir=%{_prefix}/share/info \ %{_prefix}/share/info/%{infofile} /sbin/ldconfig %postun /sbin/install-info \ --remove \ --info-dir=%{_prefix}/share/info \ %{_prefix}/share/info/%{infofile} %clean [ -n "${RPM_BUILD_ROOT}" -a "${RPM_BUILD_ROOT}" != / ] \ && rm -rf ${RPM_BUILD_ROOT}/ %files %defattr(-,root,root) %doc AUTHORS BUGS CHANGES COPYING HINTS PLANS README TODO README.* %{_bindir}/lav* %{_bindir}/yuv* %{_bindir}/jpeg2yuv %{_bindir}/y4m* %{_bindir}/ppm* %{_bindir}/glav %{_bindir}/ypipe %{_bindir}/mp* %{_bindir}/*toy4m %{_bindir}/png2yuv %{_bindir}/anytovcd.sh %{_bindir}/mjpeg_simd_helper %{_bindir}/*.flt %{_libdir}/*.so.* %{_prefix}/share/man/man1/* %{_prefix}/share/man/man5/* %{_prefix}/share/info/ %package devel Summary: Development headers and libraries for the mjpegtools Group: Development/Libraries %description devel This package contains static libraries and C system header files needed to compile applications that use part of the libraries of the mjpegtools package. %files devel %{_includedir}/mjpegtools/*.h %{_includedir}/mjpegtools/mpeg2enc/*.hh %{_includedir}/mjpegtools/mpeg2enc/*.h %{_includedir}/mjpegtools/mplex/*.hpp %{_libdir}/pkgconfig/*.pc %{_libdir}/*.a %exclude %{_libdir}/*.la %{_libdir}/*.so %changelog * Sat Sep 21 2013 Bernhard Praschinger This some more change for the release made * Sat Nov 17 2012 Bernhard Praschinger This release has no major change, but a lot of bugfixes. A lot of patches and fixes are included. There are no major changes, but some small enhancements. Steven Schultz added y4mscaler to the CVS and included it to the build process * Sat May 21 2011 Bernhard Praschinger This is it, after more than 10 years on Sourcefogre we named this release 2.0.0. For further changes and fixes please take a look at the Changelog. * Tue Dec 02 2008 Bernhard Praschinger No we have everything together to release a new RC4 That will be very close to the next relase. There are much changes for new CPU's * Fri Jun 02 2006 Steven Schultz jpeg-mmx is not supported, it crashes on IA32 systems, will not build on X86_64 or PPC systems and even when it did work didn't provide much of a speedup (jpeg decoding is a small portion of the overall encoding process). * Fri Dec 19 2003 Ronald Bultje - add everything for mpeg2enc/mplex libs (dev headers and so on) * Sat Aug 23 2003 Ronald Bultje - Remove quicktime4linux hacks, add libquicktime depdency - Remove avifile leftovers * Wed May 20 2002 Thomas Vander Stichele - Added BuildRequires and Requires * Tue Feb 12 2002 Geoffrey T. Dairiki - Fix spec file to build in one directory, etc... * Thu Dec 06 2001 Ronald Bultje - separated mjpegtools and mjpegtools-devel - added changes by Marcel Pol for cleaner RPM build * Wed Jun 06 2001 Ronald Bultje - 1.4.0-final release, including precompiled binaries (deb/rpm) mjpegtools-2.1.0/Makefile.in0000644000175000017500000007323612217306406016272 0ustar glowwormglowworm# Makefile.in generated by automake 1.12.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Process with automake to produce Makefile.in # NOTE: utils and mpeg2enc MUST be built first so that libmjpegutils AND # libmpeg2encpp exist. Then in the following Makefile.am files if # HAVE_ALTIVEC is defined libmpeg2encpp will be added to the list of # libraries dependencies. All this because utils/altivec/libaltivec.la # contains routines which which should have gone into the encoder # library libmpeg2encpp. Sigh. Feel free to do it differently if you # can come up with a better method. VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = . DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(srcdir)/mjpegtools.pc.in $(srcdir)/mjpegtools.spec.in \ $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \ TODO compile config.guess config.sub depcomp install-sh \ ltmain.sh missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = mjpegtools.pc mjpegtools.spec CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(pkgconfigdir)" DATA = $(pkgconfig_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ cscope distdir dist dist-all distcheck ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ ALTIVEC_EXTRA_LIBS = @ALTIVEC_EXTRA_LIBS@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDV_CFLAGS = @LIBDV_CFLAGS@ LIBDV_LIBS = @LIBDV_LIBS@ LIBGETOPT_LIB = @LIBGETOPT_LIB@ LIBM_LIBS = @LIBM_LIBS@ LIBOBJS = @LIBOBJS@ LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ LIBPNG_LIBS = @LIBPNG_LIBS@ LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@ LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ LT_STATIC = @LT_STATIC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROGRAM_NOPIC = @PROGRAM_NOPIC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ SDLgfx_LIBS = @SDLgfx_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ V4LCONF_LIBS = @V4LCONF_LIBS@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = \ utils \ mpeg2enc \ lavtools \ aenc \ mplex \ scripts \ docs \ yuvcorrect \ yuvscaler \ yuvdenoise \ yuvfilters \ yuvdeinterlace \ y4mdenoise \ y4mscaler \ y4munsharp \ y4mutils \ debian # # Add any non autoconf'd files here, extra readmes and other misc # info to be copied into the dist # EXTRA_DIST = \ BUGS \ CHANGES \ HINTS \ PLANS \ README.AltiVec \ README.DV \ README.avilib \ README.glav \ README.lavpipe \ README.transist \ INSTALL \ INSTALL.real \ TODO \ cpuinfo.sh \ mjpeg_howto.txt \ mjpegtools.spec \ mjpegtools.spec.in \ mjpegtools.pc \ mjpegtools.pc.in \ autogen.sh pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = mjpegtools.pc DISTCLEANFILES = \ mjpegtools-config.h \ mjpegtools.pc \ confdefs.h \ config.cache \ config.status \ config.log MAINTAINERCLEANFILES = \ compile \ depcomp \ install-sh \ missing \ mkinstalldirs \ Makefile.in \ aclocal.m4 \ config.guess \ config.h.in \ config.sub \ configure \ ltmain.sh \ stamp-h.in all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @if test ! -f $@; then rm -f stamp-h1; else :; fi @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 mjpegtools.pc: $(top_builddir)/config.status $(srcdir)/mjpegtools.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ mjpegtools.spec: $(top_builddir)/config.status $(srcdir)/mjpegtools.spec.in cd $(top_builddir) && $(SHELL) ./config.status $@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ done uninstall-pkgconfigDATA: @$(NORMAL_UNINSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(RECURSIVE_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done cscopelist-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist-recursive cscopelist cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir); chmod a+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(DATA) config.h installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(pkgconfigdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr \ distclean-libtool distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-pkgconfigDATA install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-pkgconfigDATA .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \ cscopelist-recursive ctags-recursive install-am install-strip \ tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am am--refresh check check-am clean clean-cscope \ clean-generic clean-libtool cscope cscopelist \ cscopelist-recursive ctags ctags-recursive dist dist-all \ dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ dist-xz \ dist-zip distcheck distclean distclean-generic distclean-hdr \ distclean-libtool distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-pkgconfigDATA install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ uninstall uninstall-am uninstall-pkgconfigDATA rpm: Makefile $(MAKE) dist rpmbuild -ta --clean $(PACKAGE)-$(VERSION).tar.gz deb: Makefile dist -chmod -R +w $(PACKAGE)-$(VERSION) rm -rf $(PACKAGE)-$(VERSION) tar xzf $(PACKAGE)-$(VERSION).tar.gz cd $(PACKAGE)-$(VERSION); dpkg-buildpackage -rfakeroot # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mjpegtools-2.1.0/y4mdenoise/0000755000175000017500000000000012217306501016266 5ustar glowwormglowwormmjpegtools-2.1.0/y4mdenoise/SkipList.hh0000644000175000017500000015601011206302455020355 0ustar glowwormglowworm#ifndef __SKIPLIST_H__ #define __SKIPLIST_H__ // This file (C) 2004-2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. /* A skip list is a sorted data structure with probabilistic balancing that performs the same functions as balanced-binary-tree sorts of data structures, but skip lists have lots of unusual avenues for optimizations not available to binary trees. */ #include "config.h" #include #include #include #include "mjpeg_types.h" #include "Status_t.h" #include "Allocator.hh" // Define this to compile in code to double-check and debug the skip // list. #ifndef NDEBUG // #define DEBUG_SKIPLIST #endif // NDEBUG // The skip list. Parameterized by the class of the sorting key, the // class of the contained value, the method for extracting the key from // the value, the method for comparing keys, the number of forward pointers // in the header, and the type of allocator to use for skip-list nodes. template > class SkipList { private: // The type of a node in the skip list. struct Node { VALUE m_oValue; // The data held by this node. #ifdef DEBUG_SKIPLIST int32_t m_nLevel; #endif // DEBUG_SKIPLIST // The number of forward pointers in this node. Node *m_pBackward; // The node before this one. Node *m_apForward[1]; // The nodes after this one, at all the levels we exist. }; SkipList (const SkipList &a_rOther); const SkipList &operator = (const SkipList &a_rOther); // Disallow copying and assignment. enum { HEADERCHUNK = HC }; // The number of forward pointers in the header. // Will give good sorting for up to e^HC items. public: typedef ALLOC Allocator_t; // The type of node allocator to use. static Allocator_t sm_oNodeAllocator; // The default node allocator. // A structure that contains all of our initialization parameters. struct InitParams { public: uint32_t m_nRandSeed; // The skip list's random number seed. bool m_bAllocateInternalNodesFromAllocator; // True if the skip list's internal nodes (i.e. the header // and search-fingers) should be allocated from the allocator. // False if they should be allocated from system memory. // // Since these nodes live for the lifetime of the skip-list, // allocating them from the allocator prevents the allocator // from being able to purge itself. InitParams() : m_nRandSeed (rand()), m_bAllocateInternalNodesFromAllocator (false) {} // Default constructor. // Gets the random seed from the system. InitParams (uint32_t a_nRandSeed, bool a_bAllocateInternalNodesFromAllocator) : m_nRandSeed (a_nRandSeed), m_bAllocateInternalNodesFromAllocator (a_bAllocateInternalNodesFromAllocator) {} // Initializing constructor. }; SkipList (const PRED &a_rPred = PRED(), Allocator_t &a_rAlloc = sm_oNodeAllocator); // Default constructor. Must be followed by Init(). SkipList (Status_t &a_reStatus, bool a_bAllowDuplicates, const InitParams &a_rInitParams, const PRED &a_rPred = PRED(), Allocator_t &a_rAlloc = sm_oNodeAllocator); // Constructor. Specify whether or not duplicates are allowed, // and provide a random number seed. void Init (Status_t &a_reStatus, bool a_bAllowDuplicates, const InitParams &a_rInitParams); // Construction method. Specify whether or not duplicates are // allowed, and provide a random number seed. virtual ~SkipList (void); // Destructor. #ifdef DEBUG_SKIPLIST void Invariant (void) const; // Thoroughly analyze the skip list for structural integrity. void SetDebug (bool a_bDebug); // Set whether to run the skip-list invariant before and after // methods. #endif // DEBUG_SKIPLIST // // Iterator classes. // class Iterator; class ConstIterator; friend class ConstIterator; class ConstIterator { protected: friend class SkipList; // Let SkipList access m_pNode. Node *m_pNode; // The node we represent. public: ConstIterator() { m_pNode = NULL; } ConstIterator (Node *a_pNode) : m_pNode (a_pNode) {} ConstIterator (const Iterator &a_rOther) : m_pNode (a_rOther.m_pNode) {} const VALUE &operator*() const {return m_pNode->m_oValue; } ConstIterator& operator++() { m_pNode = m_pNode->m_apForward[0]; return *this; } ConstIterator operator++(int) { ConstIterator oTmp = *this; ++*this; return oTmp; } ConstIterator& operator--() { m_pNode = m_pNode->m_pBackward; return *this; } ConstIterator operator--(int) { ConstIterator oTmp = *this; --*this; return oTmp; } bool operator== (const ConstIterator &a_rOther) const { return (m_pNode == a_rOther.m_pNode) ? true : false; } bool operator!= (const ConstIterator &a_rOther) const { return (m_pNode != a_rOther.m_pNode) ? true : false; } }; friend class Iterator; class Iterator : public ConstIterator { private: typedef ConstIterator BaseClass; // Keep track of who our base class is. public: Iterator() : ConstIterator() {} Iterator (Node *a_pNode) : ConstIterator (a_pNode) {} VALUE &operator*() {return BaseClass::m_pNode->m_oValue; } Iterator& operator++() { BaseClass::m_pNode = BaseClass::m_pNode->m_apForward[0]; return *this; } Iterator operator++(int) { Iterator oTmp = *this; ++*this; return oTmp; } Iterator& operator--() { BaseClass::m_pNode = BaseClass::m_pNode->m_pBackward; return *this; } Iterator operator--(int) { Iterator oTmp = *this; --*this; return oTmp; } bool operator== (const ConstIterator &a_rOther) const { return (((BaseClass&)(*this)) == a_rOther); } bool operator!= (const ConstIterator &a_rOther) const { return (((BaseClass&)(*this)) != a_rOther); } }; // // Skip list methods. // Iterator Begin (void) { return Iterator (m_pHeader->m_apForward[0]); } // Return an iterator to the beginning of the list. ConstIterator Begin (void) const { return ConstIterator (m_pHeader->m_apForward[0]); } // Return an iterator to the beginning of the list. Iterator End (void) { return Iterator (m_pHeader); } // Return an iterator to the end of the list. ConstIterator End (void) const { return ConstIterator (m_pHeader); } // Return an iterator to the end of the list. uint32_t Size (void) const { return m_nItems; } // Return the number of items in the list. // (May be called on a default-constructed object, making it // possible for default-constructed subclasses/owners to destroy // themselves safely.) bool Empty (void) const { return (m_nItems == 0) ? true : false; } // Return whether the list is empty. // A structure used to return the result of an insertion. struct InsertResult { Iterator m_itPosition; // Where the item was inserted, or where the duplicate was // found. bool m_bInserted; // true if the item was inserted into the list. }; InsertResult Insert (Status_t &a_reStatus, const VALUE &a_rValue); // Insert an item into the list. Iterator Insert (Status_t &a_reStatus, Iterator a_oPosition, const VALUE &a_rValue); // Insert an item into the list, at this exact location, if it's // safe. Returns where it was really inserted. void Insert (Status_t &a_reStatus, ConstIterator a_oFirst, ConstIterator a_oLast); // Insert a range of items from another skip-list. Iterator Erase (Iterator a_oHere); // Erase the item here. Return the item following the one // removed. Iterator Erase (Iterator a_oFirst, Iterator a_oLast); // Erase a range of items in this list. Return the item // following the last one removed. void Clear (void); // Empty the list. void Purge (void) { } // Purge all internally-allocated memory. // Not implemented for SkipList -- this is only here to preserve // interface compatibility with Vector<>. InsertResult Move (SkipList &a_rOther, Iterator a_oHere); // Remove an item from another skip list and insert it into // ourselves. // Just like an Erase() followed by an Insert(), except that // there's no possibility of the operation failing. void Move (SkipList &a_rOther, Iterator a_oFirst, Iterator a_oLast); // Remove a range of items from another skip-list and insert // them into ourselves. // Just like an Erase() followed by an Insert(), except that // there's no possibility of the operation failing. void Move (SkipList &a_rOther); // Move all items from the other skip-list to ourself. // The current skip-list must be empty. bool CanMove (const SkipList &a_rOther) const; // Returns true if the two skip lists can move items between // each other. void Assign (Status_t &a_reStatus, const SkipList &a_rOther); // Assign the contents of the other skip list to ourselves. Iterator Find (const KEY &a_rKey); // Find the given item in the list. Returns End() if not found. ConstIterator Find (const KEY &a_rKey) const; // Find the given item in the list. Returns End() if not found. Iterator LowerBound (const KEY &a_rKey); // Return the position of the first item that's >= the key. ConstIterator LowerBound (const KEY &a_rKey) const; // Return the position of the first item that's >= the key. Iterator UpperBound (const KEY &a_rKey); // Return the position of the first item that's > the key. ConstIterator UpperBound (const KEY &a_rKey) const; // Return the position of the first item that's > the key. size_t GetSizeOfLargestNode (void) const; // Return the size of the largest possible skip-list node. // // (Not generally useful...needed by VariableSizeAllocator, // to make sure all free-space blocks can become part of an // in-place skip-list.) private: Allocator_t &m_rNodeAllocator; // Where we get memory to allocate nodes. bool m_bAllowDuplicates; // true if we allow duplicate elements. int16_t m_nHeaderLevel; // How many valid pointers m_pHeader[] is holding. Node *m_pHeader; // The beginning of the list. Node *m_pSearchFinger, *m_pSearchFinger2; // Used to speed up searches, by caching the results of // previous searches. uint32_t m_nItems; // The number of items in this list. uint32_t m_nRandSeed; // The random-number seed. bool m_bAllocateInternalNodesFromAllocator; // True if the skip list's internal nodes (i.e. the header // and search-fingers) should be allocated from the allocator. // False if they should be allocated from system memory. // // Since these nodes live for the lifetime of the skip-list, // allocating them from the allocator prevents the allocator // from being able to purge itself. KEYFN m_oKeyFn; // How we extract a key from a value. PRED m_oPred; // How we compare keys to each other. void SearchLower (const KEY &a_rKey, Node *a_pTraverse) const; // Search for an item greater than or equal to a_rKey. bool SearchExact (Node *a_pKey, Node *a_pTraverse) const; // Search for this exact item. Returns true if it's found. void SearchUpper (const KEY &a_rKey, Node *a_pTraverse) const; // Search for an item greater than a_rKey. void SearchEnd (Node *a_pTraverse) const; // Point to the end of the list. void InsertNode (Node *a_pNewNode, int16_t a_nNewLevel, Node *a_pTraverse); // Insert a new node into the skip list. Assume a_pTraverse is // set up. Node *RemoveNode (Node *a_pToRemove, Node *a_pTraverse, int16_t *a_pLevel = NULL); // Remove the given node from the skip list. Assume a_pTraverse // is set up. // Returns the node that got removed, and optionally backpatches // its level. Node *GetNewNode (int16_t a_nForwardPointers); // Allocate a new node with the given number of forward // pointers. Returns NULL if something goes wrong. Node *GetNewNodeOfRandomLevel (int16_t &a_rnLevel); // Allocate a new node with a random number of forward pointers. // Returns NULL if something goes wrong; otherwise, a_rnLevel // gets backpatched with the number of levels. void DeleteNode (int16_t a_nForwardPointers, Node *a_pToDelete); // Delete a node. void DeallocateNode (int16_t a_nForwardPointers, Node *a_pToDelete); // Deallocate a node's storage. int16_t Rand (void); // Get another random number. #ifdef DEBUG_SKIPLIST bool m_bDebug; #endif // DEBUG_SKIPLIST // true if the invariant should be checked. }; // The default node allocator. Allocates 64K at a time. template typename SkipList::Allocator_t SkipList::sm_oNodeAllocator (65536); // Default constructor. Must be followed by Init(). template SkipList::SkipList (const PRED &a_rPred, Allocator_t &a_rAlloc) : m_rNodeAllocator (a_rAlloc), m_oPred (a_rPred) { // Set up some defaults. m_bAllowDuplicates = false; m_nHeaderLevel = 0; m_pHeader = NULL; m_pSearchFinger = NULL; m_pSearchFinger2 = NULL; m_nItems = 0; m_nRandSeed = 0; m_bAllocateInternalNodesFromAllocator = false; #ifdef DEBUG_SKIPLIST m_bDebug = false; // Make sure we're intact. Invariant(); #endif // DEBUG_SKIPLIST } // Constructor. Specify whether or not duplicates are allowed, and // provide a random number seed. template SkipList::SkipList (Status_t &a_reStatus, bool a_bAllowDuplicates, const InitParams &a_rInitParams, const PRED &a_rPred, Allocator_t &a_rAlloc) : m_rNodeAllocator (a_rAlloc), m_oPred (a_rPred) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Set up some defaults. m_bAllowDuplicates = false; m_nHeaderLevel = 0; m_pHeader = NULL; m_pSearchFinger = NULL; m_pSearchFinger2 = NULL; m_nItems = 0; m_nRandSeed = 0; m_bAllocateInternalNodesFromAllocator = false; #ifdef DEBUG_SKIPLIST m_bDebug = false; #endif // DEBUG_SKIPLIST // Init() does all the work. Init (a_reStatus, a_bAllowDuplicates, a_rInitParams); } // Construction method. Specify whether or not duplicates are allowed, // and provide a random number seed. template void SkipList::Init (Status_t &a_reStatus, bool a_bAllowDuplicates, const InitParams &a_rInitParams) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure we haven't been initialized already. assert (m_pHeader == NULL); // Fill in the blanks. m_bAllowDuplicates = a_bAllowDuplicates; m_nHeaderLevel = 0; m_nItems = 0; m_nRandSeed = a_rInitParams.m_nRandSeed; m_bAllocateInternalNodesFromAllocator = a_rInitParams.m_bAllocateInternalNodesFromAllocator; // Allocate our necessary nodes. if (m_bAllocateInternalNodesFromAllocator) { m_pHeader = GetNewNode (HEADERCHUNK); m_pSearchFinger = GetNewNode (HEADERCHUNK); m_pSearchFinger2 = GetNewNode (HEADERCHUNK); } else { // Do this from system memory, instead of the supplied allocator. // Otherwise, these "permanent" allocations won't allow the // allocator to purge itself during the lifetime of this skip-list. size_t nHeaderBytes = (size_t)(&(((Node *)0x80000000) ->m_apForward[HEADERCHUNK])) - 0x80000000; m_pHeader = (Node *) malloc (nHeaderBytes); m_pSearchFinger = (Node *) malloc (nHeaderBytes); m_pSearchFinger2 = (Node *) malloc (nHeaderBytes); } if (m_pHeader == NULL || m_pSearchFinger == NULL || m_pSearchFinger2 == NULL) { if (m_bAllocateInternalNodesFromAllocator) { if (m_pSearchFinger2 != NULL) DeallocateNode (HEADERCHUNK, m_pSearchFinger2); if (m_pSearchFinger != NULL) DeallocateNode (HEADERCHUNK, m_pSearchFinger); if (m_pHeader != NULL) DeallocateNode (HEADERCHUNK, m_pHeader); } else { free (m_pSearchFinger2); free (m_pSearchFinger); free (m_pHeader); } m_pHeader = NULL; m_pSearchFinger = NULL; m_pSearchFinger2 = NULL; a_reStatus = g_kOutOfMemory; return; } // Set up our nodes. // // The way we work, incrementing End() gets you Begin(), and // decrementing Begin() gets you End(). We implement that by using // our header node as a NULL-like sentinel node. #ifdef DEBUG_SKIPLIST m_pHeader->m_nLevel = HEADERCHUNK; m_pSearchFinger->m_nLevel = HEADERCHUNK; m_pSearchFinger2->m_nLevel = HEADERCHUNK; #endif // DEBUG_SKIPLIST new ((void *)(&(m_pHeader->m_oValue))) VALUE; new ((void *)(&(m_pSearchFinger->m_oValue))) VALUE; new ((void *)(&(m_pSearchFinger2->m_oValue))) VALUE; m_pHeader->m_pBackward = m_pHeader; m_pSearchFinger->m_pBackward = m_pHeader; m_pSearchFinger2->m_pBackward = m_pHeader; for (int16_t nI = 0; nI < HEADERCHUNK; nI++) { m_pHeader->m_apForward[nI] = m_pHeader; m_pSearchFinger->m_apForward[nI] = m_pHeader; m_pSearchFinger2->m_apForward[nI] = m_pHeader; } // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST } // Destructor. template SkipList::~SkipList (void) { // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // If we have anything to delete, delete it. if (m_pHeader != NULL) { // Delete everything in the list. Erase (Begin(), End()); // Free up our extra nodes. m_pSearchFinger2->m_oValue.~VALUE(); m_pSearchFinger->m_oValue.~VALUE(); m_pHeader->m_oValue.~VALUE(); if (m_bAllocateInternalNodesFromAllocator) { DeallocateNode (HEADERCHUNK, m_pSearchFinger2); DeallocateNode (HEADERCHUNK, m_pSearchFinger); DeallocateNode (HEADERCHUNK, m_pHeader); } else { free (m_pSearchFinger2); free (m_pSearchFinger); free (m_pHeader); } } } #ifdef DEBUG_SKIPLIST // Set whether to run the skip-list invariant before and after methods. template void SkipList::SetDebug (bool a_bDebug) { // Easy enough. m_bDebug = a_bDebug; } #endif // DEBUG_SKIPLIST // Insert an item into the list. template typename SkipList::InsertResult SkipList::Insert (Status_t &a_reStatus, const VALUE &a_rValue) { Node *pNewNode; // The new node being inserted. int16_t nNewLevel; // The level of the new node. InsertResult oInsertResult; // The result of the insertion. // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure we have been initialized properly. assert (m_pHeader != NULL); // Find where to put this key. (Put equal keys at the upper bound.) SearchUpper (m_oKeyFn (a_rValue), m_pSearchFinger); // Insert this node if there's no duplicate already in here. if (m_bAllowDuplicates || (pNewNode = m_pSearchFinger->m_apForward[0], pNewNode == m_pHeader || m_oPred (m_oKeyFn (pNewNode->m_oValue), m_oKeyFn (a_rValue)))) { // Generate a node of random level. pNewNode = GetNewNodeOfRandomLevel (nNewLevel); if (pNewNode == NULL) { // We couldn't allocate space. a_reStatus = g_kOutOfMemory; oInsertResult.m_itPosition = End(); oInsertResult.m_bInserted = false; return oInsertResult; } // Install the value. new ((void *)(&(pNewNode->m_oValue))) VALUE (a_rValue); // Put it into the skip list here. InsertNode (pNewNode, nNewLevel, m_pSearchFinger); // Let them know where we put it, and that we did insert it. oInsertResult.m_itPosition = Iterator (pNewNode); oInsertResult.m_bInserted = true; } else { // We didn't insert it. Show them the equal item. oInsertResult.m_itPosition = Iterator (pNewNode); oInsertResult.m_bInserted = false; } // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Let them know what happened. return oInsertResult; } // Insert an item into the list, at this exact location, if it's safe. // Returns where it was really inserted. template typename SkipList::Iterator SkipList::Insert (Status_t &a_reStatus, Iterator a_oPosition, const VALUE &a_rValue) { const KEY &rKey = m_oKeyFn (a_rValue); // The key of what they're inserting. Node *pNewNode; // The node we're inserting. int16_t nNewLevel; // The level it's at. Iterator oHere; // Where it gets inserted. // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure we have been initialized properly. assert (m_pHeader != NULL); // According to STL semantics, the insertion point must immediately // follow a_oPosition. To fit more naturally with skip-list // semantics, the insertion point needs to precede a_oPosition. if (a_oPosition != End()) ++a_oPosition; // The new item has to fit where this iterator points, and we must // be able to find this iterator's node in the list. Iterator oBefore = a_oPosition; --oBefore; if ((a_oPosition.m_pNode != m_pHeader && m_oPred (m_oKeyFn (a_oPosition.m_pNode->m_oValue), rKey)) || (oBefore.m_pNode != m_pHeader && m_oPred (rKey, m_oKeyFn (oBefore.m_pNode->m_oValue))) || !SearchExact (a_oPosition.m_pNode, m_pSearchFinger)) { // Don't use their iterator. oHere = Insert (a_reStatus, a_rValue).m_itPosition; } // Insert this node if we always insert, or if there's no duplicate // already. else if (m_bAllowDuplicates || (pNewNode = m_pSearchFinger->m_apForward[0]->m_apForward[0], pNewNode == m_pHeader || m_oPred (rKey, m_oKeyFn (pNewNode->m_oValue)))) { // Generate a node of random level. pNewNode = GetNewNodeOfRandomLevel (nNewLevel); if (pNewNode == NULL) { // We couldn't allocate space. a_reStatus = g_kOutOfMemory; oHere = End(); } else { // Install the value. new ((void *)(&(pNewNode->m_oValue))) VALUE (a_rValue); // Put it into the skip list here. InsertNode (pNewNode, nNewLevel, m_pSearchFinger); // Let them know where we put it. oHere = Iterator (pNewNode); } } // We didn't insert it. Show them the equal item. else oHere = Iterator (pNewNode); // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Let our caller know what happened. return oHere; } // Insert a range of items from another skip-list. template void SkipList::Insert (Status_t &a_reStatus, ConstIterator a_oFirst, ConstIterator a_oLast) { ConstIterator oHere; // The next item to insert. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure we have been initialized properly. assert (m_pHeader != NULL); // Try to insert every item they gave us. for (oHere = a_oFirst; oHere != a_oLast; oHere++) { Insert (a_reStatus, *oHere); if (a_reStatus != g_kNoError) { // BUG: this is messy. If we can't insert the entire range, // we shouldn't insert any of it. Fix this by preallocating // all necessary nodes. return; } } } // Erase the item here. Return the item following the one removed. template typename SkipList::Iterator SkipList::Erase (Iterator a_oHere) { Node *pToRemove; int16_t nLevel; // The node being deleted, and its level. // Make sure we have been initialized properly. assert (m_pHeader != NULL); // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Don't let them erase End(). if (a_oHere.m_pNode == m_pHeader) return Begin(); // If this iterator does not point to a current node, leave. // (This check also sets up the search finger for RemoveNode().) if (!SearchExact (a_oHere.m_pNode, m_pSearchFinger)) return Begin(); // Erase it. pToRemove = RemoveNode (m_pSearchFinger->m_apForward[0] ->m_apForward[0], m_pSearchFinger, &nLevel); DeleteNode (nLevel, pToRemove); // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Return an iterator that points past the deleted node. return Iterator (m_pSearchFinger->m_apForward[0]->m_apForward[0]); } // Erase a range of items in this list. Return the item following the // last one removed. template typename SkipList::Iterator SkipList::Erase (Iterator a_oFirst, Iterator a_oLast) { int16_t nI; // Used to loop through things. Node *pNode, *pToRemove; // Nodes we're examining and deleting. int16_t nLevel; // The level of each removed node. // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Make sure we have been initialized properly. assert (m_pHeader != NULL); // Make sure these iterators are in the right order. assert (a_oFirst == Begin() || a_oLast == End() || !m_oPred (m_oKeyFn (a_oLast.m_pNode->m_oValue), m_oKeyFn (a_oFirst.m_pNode->m_oValue))); // If the first item to be removed is the end of the list, then // nothing needs to be done. if (a_oFirst == End()) return End(); // A skip-list's range-delete doesn't involve a rebalancing for // every node deleted, like a tree structure's range-delete would. // Here, we just generate search fingers for each end of the // range, and fix the forward/backward pointers in one shot. // We still have to loop through the deleted range in order to // delete the nodes, but that's nowhere near the cost of a // rebalance per node. Spiffy, huh? // First, search for the beginning of the range to delete. // Abort if we can't find it. if (!SearchExact (a_oFirst.m_pNode, m_pSearchFinger)) return End(); // Use that as a base for the second search. for (nI = 0; nI < m_nHeaderLevel; nI++) m_pSearchFinger2->m_apForward[nI] = m_pSearchFinger->m_apForward[nI]; // Now search for the end of the range to delete. // Abort if we can't find it. if (!SearchExact (a_oLast.m_pNode, m_pSearchFinger2)) return End(); // Loop through the removed nodes, destroy the values inside, // and deallocate the nodes. pNode = a_oFirst.m_pNode; while (pNode != a_oLast.m_pNode) { // Get the node to destroy. pToRemove = pNode; pNode = pNode->m_apForward[0]; // Destroy it. pToRemove = RemoveNode (pToRemove, m_pSearchFinger, &nLevel); DeleteNode (nLevel, pToRemove); } // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Return the end of the removed range. return a_oLast; } // Empty the list. template void SkipList::Clear (void) { // Make sure we have been initialized properly. assert (m_pHeader != NULL); // Easy enough. Erase (Begin(), End()); // Since there are no nodes left, it's OK to "fix the dice" at // zero again. m_nHeaderLevel = 0; } // Remove an item from another skip list and insert it into ourselves. // Just like an Erase() followed by an Insert(), except that there's no // possibility of the operation failing. template typename SkipList::InsertResult SkipList::Move (SkipList &a_rOther, Iterator a_oHere) { Node *pNode; // The node we're moving. int16_t nLevel; // The level of the node we're moving. InsertResult oInsertResult; // The result of the insertion. // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Make sure we have been initialized properly. assert (m_pHeader != NULL); // Make sure the skip-lists can move items between themselves. assert (CanMove (a_rOther)); // Don't let them move End(). assert (a_oHere.m_pNode != a_rOther.m_pHeader); // Get a reference to the key of the value being moved. const KEY &rKey = m_oKeyFn (a_oHere.m_pNode->m_oValue); // Find where to put this key. (Put equal keys at the upper bound.) SearchUpper (rKey, m_pSearchFinger); // Move this node if there's no duplicate already in here. if (m_bAllowDuplicates || (pNode = m_pSearchFinger->m_apForward[0], pNode == m_pHeader || m_oPred (m_oKeyFn (pNode->m_oValue), rKey))) { bool bFound; // true if this node was found in the other skip list. // Make sure the other list is intact. #ifdef DEBUG_SKIPLIST a_rOther.Invariant(); #endif // DEBUG_SKIPLIST // Find this node in the other skip list. bFound = a_rOther.SearchExact (a_oHere.m_pNode, a_rOther.m_pSearchFinger); // Make sure this iterator points to a current node. assert (bFound); // Remove it from that skip list. pNode = a_rOther.RemoveNode (a_oHere.m_pNode, a_rOther.m_pSearchFinger, &nLevel); // If the node we're about to add is a higher level than any // node we've seen so far, keep track of the new maximum. if (m_nHeaderLevel < nLevel) m_nHeaderLevel = nLevel; // Put it into the skip list here. InsertNode (pNode, nLevel, m_pSearchFinger); // Let them know where we put it, and that we did insert it. oInsertResult.m_itPosition = Iterator (pNode); oInsertResult.m_bInserted = true; } else { // We didn't insert it. Show them the equal item. oInsertResult.m_itPosition = Iterator (pNode); oInsertResult.m_bInserted = false; } // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Let them know what happened. return oInsertResult; } // Remove a range of items from another skip-list and insert them // into ourselves. // Just like an Erase() followed by an Insert(), except that there's no // possibility of the operation failing. template void SkipList::Move (SkipList &a_rOther, Iterator a_oFirst, Iterator a_oLast) { Iterator oHere, oNext; // The item we're moving. // Make sure we have been initialized properly. assert (m_pHeader != NULL); // Loop through all the items, move each one. oHere = a_oFirst; while (oHere != a_oLast) { // Keep track of the next item to move. oNext = oHere; oNext++; // Move this item. Move (a_rOther, oHere); // Loop back and move the next one. oHere = oNext; } } // Move all items from the other skip-list to ourself. template void SkipList::Move (SkipList &a_rOther) { Node *p; // Used to swap structures. // Make sure we're all intact. #ifdef DEBUG_SKIPLIST Invariant(); a_rOther.Invariant(); #endif // DEBUG_SKIPLIST // Make sure the skip-lists can move items between themselves. assert (CanMove (a_rOther)); // Make sure we're empty. assert (m_nItems == 0); // Swap the header & search fingers. p = m_pHeader; m_pHeader = a_rOther.m_pHeader; a_rOther.m_pHeader = p; p = m_pSearchFinger; m_pSearchFinger = a_rOther.m_pSearchFinger; a_rOther.m_pSearchFinger = p; p = m_pSearchFinger2; m_pSearchFinger2 = a_rOther.m_pSearchFinger2; a_rOther.m_pSearchFinger2 = p; // Use their header level, if it's bigger than ours. if (m_nHeaderLevel < a_rOther.m_nHeaderLevel) m_nHeaderLevel = a_rOther.m_nHeaderLevel; a_rOther.m_nHeaderLevel = 0; // Now we have all their items. m_nItems = a_rOther.m_nItems; a_rOther.m_nItems = 0; // Make sure we're all intact. #ifdef DEBUG_SKIPLIST Invariant(); a_rOther.Invariant(); #endif // DEBUG_SKIPLIST } // Returns true if the two skip lists can move items between // each other. template bool SkipList::CanMove (const SkipList &a_rOther) const { // They can if they have the same allocator. return (&m_rNodeAllocator == &a_rOther.m_rNodeAllocator); } // Assign the contents of the other skip list to ourselves. template void SkipList::Assign (Status_t &a_reStatus, const SkipList &a_rOther) { Node *pBegin, *pEnd; // Where we're looking in the other list. Node *pHere; // Where we're looking in our list. // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure we have been initialized properly. assert (m_pHeader != NULL); // Get the range of items from the other list. pBegin = a_rOther.Begin().m_pNode; pEnd = a_rOther.End().m_pNode; // First, if we have more nodes than they do, erase enough of ours // so that we have the same amount. if (Size() > a_rOther.Size()) { // Calculate the number of nodes to delete. int32_t nToDelete = Size() - a_rOther.Size(); // Move forward that many items. Iterator oToDelete = Begin(); while (--nToDelete >= 0) oToDelete++; // Delete those items. Erase (Begin(), oToDelete); } // Start modifying our items here. pHere = Begin().m_pNode; // Next, insert as many items as we can, using the nodes already // allocated in the list. while (pHere != m_pHeader && pBegin != pEnd) { // Store the new item over the old one. pHere->m_oValue = pBegin->m_oValue; // Move forward. pHere = pHere->m_apForward[0]; pBegin = pBegin->m_apForward[0]; } // If we ran out of nodes, insert the rest in the normal way. if (pBegin != pEnd) Insert (a_reStatus, ConstIterator (pBegin), ConstIterator (pEnd)); // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST } // Find the given item in the list. Returns End() if not found. template typename SkipList::Iterator SkipList::Find (const KEY &a_rKey) { Iterator oHere; // What we found. // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Make sure we have been initialized properly. assert (m_pHeader != NULL); // Look for the item. oHere = LowerBound (a_rKey); // LowerBound() returns the first item >= the key. So if this item // is greater than what they were asking for, that means we didn't // find it. if (oHere == End() || m_oPred (a_rKey, m_oKeyFn (oHere.m_pNode->m_oValue))) return End(); else return oHere; } // Find the given item in the list. Returns End() if not found. template typename SkipList::ConstIterator SkipList::Find (const KEY &a_rKey) const { ConstIterator oHere; // What we found. // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Make sure we have been initialized properly. assert (m_pHeader != NULL); // Look for the item. oHere = LowerBound (a_rKey); // LowerBound() returns the first item >= the key. So if this item // is greater than what they were asking for, that means we didn't // find it. if (oHere == End() || m_oPred (a_rKey, m_oKeyFn (oHere.m_pNode->m_oValue))) return End(); else return oHere; } // Return the position of the first item that's >= the key. template typename SkipList::Iterator SkipList::LowerBound (const KEY &a_rKey) { // Make sure we have been initialized properly. assert (m_pHeader != NULL); // Search for the first item >= the key. SearchLower (a_rKey, m_pSearchFinger); // Return what we found. return Iterator (m_pSearchFinger->m_apForward[0]->m_apForward[0]); } // Return the position of the first item that's >= the key. template typename SkipList::ConstIterator SkipList::LowerBound (const KEY &a_rKey) const { // Make sure we have been initialized properly. assert (m_pHeader != NULL); // Search for the first item >= the key. SearchLower (a_rKey, m_pSearchFinger); // Return what we found. return ConstIterator (m_pSearchFinger->m_apForward[0] ->m_apForward[0]); } // Return the position of the first item that's > the key. template typename SkipList::Iterator SkipList::UpperBound (const KEY &a_rKey) { // Make sure we have been initialized properly. assert (m_pHeader != NULL); // Search for the first item > the key. SearchUpper (a_rKey, m_pSearchFinger); // Return what we found. return Iterator (m_pSearchFinger->m_apForward[0]->m_apForward[0]); } // Return the position of the first item that's > the key. template typename SkipList::ConstIterator SkipList::UpperBound (const KEY &a_rKey) const { // Make sure we have been initialized properly. assert (m_pHeader != NULL); // Search for the first item > the key. SearchUpper (a_rKey, m_pSearchFinger); // Return what we found. return ConstIterator (m_pSearchFinger->m_apForward[0] ->m_apForward[0]); } // Return the size of the largest possible skip-list node. template size_t SkipList::GetSizeOfLargestNode (void) const { // Easy enough. return (size_t)(&(((Node *)0x80000000)->m_apForward[HEADERCHUNK])) - 0x80000000; } // Search for an item greater than or equal to a_rKey. template void SkipList::SearchLower (const KEY &a_rKey, Node *a_pTraverse) const { Node *pCurrentNode; // Where we're searching. int16_t nCurrentLevel; // The level we've searched so far. Node *pLastFinger; // A node that we know is < the key. Node *pAlreadyChecked; // A node that we know is >= the key. // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Make sure we have been initialized properly. assert (m_pHeader != NULL); // See how much of the previous search we can reuse. pCurrentNode = m_pHeader; pLastFinger = m_pHeader; pAlreadyChecked = m_pHeader; nCurrentLevel = m_nHeaderLevel; while (--nCurrentLevel >= 0) { Node *pCurrentFinger; // What's at this level. // See what's at this level. pCurrentFinger = a_pTraverse->m_apForward[nCurrentLevel]; // If this is what we found before, OR if there's nothing here, // OR we haven't gone past what we're trying to find, then // there's a chance we can reuse the search at this level. if (pCurrentFinger == pLastFinger || pCurrentFinger == m_pHeader || m_oPred (m_oKeyFn (pCurrentFinger->m_oValue), a_rKey)) { // Look at the item past the current search finger. Node *pNextFinger = pCurrentFinger->m_apForward[nCurrentLevel]; // If there's nothing here, OR what's here is >= what we're // looking for, then we can reuse all of this level's // search. if (pNextFinger == m_pHeader || pNextFinger == pAlreadyChecked || !m_oPred (m_oKeyFn (pNextFinger->m_oValue), a_rKey)) { // We can reuse all of this level's search. pCurrentNode = pCurrentFinger; pLastFinger = pCurrentFinger; pAlreadyChecked = pNextFinger; } else { // We can reuse this level's search, but we have to // start looking here. pCurrentNode = pCurrentFinger; nCurrentLevel++; break; } } else { // We can't reuse this level. Redo it. nCurrentLevel++; break; } } // Now search for the item in the list. while (--nCurrentLevel >= 0) { Node *pNextNode; while (pNextNode = pCurrentNode->m_apForward[nCurrentLevel], pNextNode != pAlreadyChecked && pNextNode != m_pHeader && m_oPred (m_oKeyFn (pNextNode->m_oValue), a_rKey)) { pCurrentNode = pNextNode; } pAlreadyChecked = pCurrentNode->m_apForward[nCurrentLevel]; a_pTraverse->m_apForward[nCurrentLevel] = pCurrentNode; } // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST } // Search for this exact item. Returns true if it's found. template bool SkipList::SearchExact (Node *a_pKey, Node *a_pTraverse) const { Node *pFound; // What we found. int16_t nI; // Used to iterate through levels. // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Make sure we have been initialized properly. assert (m_pHeader != NULL); // If they passed us End(), just search to the end and succeed. if (a_pKey == m_pHeader) { SearchEnd (a_pTraverse); return true; } // Find the lower bound. SearchLower (m_oKeyFn (a_pKey->m_oValue), a_pTraverse); // Run through the equal range, look for this exact item. for (pFound = a_pTraverse->m_apForward[0]->m_apForward[0]; pFound != m_pHeader && pFound != a_pKey; pFound = pFound->m_apForward[0]) { // Advance the search finger. for (nI = 0; nI < m_nHeaderLevel && a_pTraverse->m_apForward[nI]->m_apForward[nI] == pFound; nI++) { a_pTraverse->m_apForward[nI] = pFound; } } // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Let them know if we succeeded. return (pFound == a_pKey); } // Search for an item greater than a_rKey. template void SkipList::SearchUpper (const KEY &a_rKey, Node *a_pTraverse) const { Node *pCurrentNode; // Where we're searching. int16_t nCurrentLevel; // The level we've searched so far. Node *pLastFinger; // A node that we know is <= the key. Node *pAlreadyChecked; // A node that we know is > the key. // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Make sure we have been initialized properly. assert (m_pHeader != NULL); // See how much of the previous search we can reuse. pCurrentNode = m_pHeader; pLastFinger = m_pHeader; pAlreadyChecked = m_pHeader; nCurrentLevel = m_nHeaderLevel; while (--nCurrentLevel >= 0) { Node *pCurrentFinger; // What's at this level. // See what's at this level. pCurrentFinger = a_pTraverse->m_apForward[nCurrentLevel]; // If this is what we found before, OR if there's nothing here, // OR we haven't gone past what we're trying to find, then // there's a chance we can reuse the search at this level. if (pCurrentFinger == pLastFinger || pCurrentFinger == m_pHeader || !m_oPred (a_rKey, m_oKeyFn (pCurrentFinger->m_oValue))) { // Look at the item past the current search finger. Node *pNextFinger = pCurrentFinger->m_apForward[nCurrentLevel]; // If there's nothing here, OR what's here is > what we're // looking for, then we can reuse all of this level's // search. if (pNextFinger == m_pHeader || pNextFinger == pAlreadyChecked || m_oPred (a_rKey, m_oKeyFn (pNextFinger->m_oValue))) { // We can reuse all of this level's search. pCurrentNode = pCurrentFinger; pLastFinger = pCurrentFinger; pAlreadyChecked = pNextFinger; } else { // We can reuse this level's search, but we have to // start looking here. pCurrentNode = pCurrentFinger; nCurrentLevel++; break; } } else { // We can't reuse this level. Redo it. nCurrentLevel++; break; } } // Now search for the item in the list. while (--nCurrentLevel >= 0) { Node *pNextNode; while (pNextNode = pCurrentNode->m_apForward[nCurrentLevel], pNextNode != pAlreadyChecked && pNextNode != m_pHeader && !m_oPred (a_rKey, m_oKeyFn (pNextNode->m_oValue))) { pCurrentNode = pNextNode; } pAlreadyChecked = pCurrentNode->m_apForward[nCurrentLevel]; a_pTraverse->m_apForward[nCurrentLevel] = pCurrentNode; } // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST } // Point to the end of the list. template void SkipList::SearchEnd (Node *a_pTraverse) const { // Make sure we have been initialized properly. assert (m_pHeader != NULL); // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Point every level of the traverse array to the last node before // the end. Node *pLastNode = a_pTraverse->m_apForward[m_nHeaderLevel - 1]; int16_t nCurrentLevel = m_nHeaderLevel; while (--nCurrentLevel >= 0) { Node *pNextNode; while (pNextNode = pLastNode->m_apForward[nCurrentLevel], pNextNode != m_pHeader) { pLastNode = pNextNode; } a_pTraverse->m_apForward[nCurrentLevel] = pLastNode; } // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST } // Insert a new node into the skip list. Assume a_pTraverse is // set up. template void SkipList::InsertNode (Node *a_pNewNode, int16_t a_nNewLevel, Node *a_pTraverse) { // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Set up the backward link of the new node. a_pNewNode->m_pBackward = a_pTraverse->m_apForward[0]; // Modify all levels of pointers. while (--a_nNewLevel >= 0) { // Insert ourselves where the traverse array points. a_pNewNode->m_apForward[a_nNewLevel] = a_pTraverse->m_apForward[a_nNewLevel] ->m_apForward[a_nNewLevel]; a_pTraverse->m_apForward[a_nNewLevel]->m_apForward[a_nNewLevel] = a_pNewNode; // Point the traverse array at the new node. a_pTraverse->m_apForward[a_nNewLevel] = a_pNewNode; } // Set up the backward link of the node after the new one. a_pNewNode->m_apForward[0]->m_pBackward = a_pNewNode; // That's one more node in the list. m_nItems++; // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST } // Remove the given node from the skip list. Assume a_pTraverse is // set up. // Returns the node that got removed, and optionally backpatches its // level. template typename SkipList::Node * SkipList::RemoveNode (Node *a_pToRemove, Node *a_pTraverse, int16_t *a_pLevel) { int16_t nI; // Used to loop through skip-list levels. Node *pCurrentNode; // A node that's pointing to the node we're removing. // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Make sure this traversal array is set up to remove this node. assert (a_pTraverse->m_apForward[0]->m_apForward[0] == a_pToRemove); // Remove this node from all levels where it appears. for (nI = 0; nI < m_nHeaderLevel && (pCurrentNode = a_pTraverse->m_apForward[nI], pCurrentNode->m_apForward[nI] == a_pToRemove); nI++) { pCurrentNode->m_apForward[nI] = a_pToRemove->m_apForward[nI]; } // Make sure the node had as many levels as we expected. #ifdef DEBUG_SKIPLIST assert (nI == a_pToRemove->m_nLevel); #endif // DEBUG_SKIPLIST // Remove this node from the back-links. a_pTraverse->m_apForward[0]->m_apForward[0]->m_pBackward = a_pTraverse->m_apForward[0]; // That's one less item in the list. m_nItems--; // Give them the level of this node, if they asked for it. if (a_pLevel != NULL) *a_pLevel = nI; // Make sure we're intact. #ifdef DEBUG_SKIPLIST Invariant(); #endif // DEBUG_SKIPLIST // Return the node we removed. return a_pToRemove; } // Allocate a new node with the given number of forward pointers. // Returns NULL if something goes wrong. template typename SkipList::Node * SkipList::GetNewNode (int16_t a_nForwardPointers) { size_t nBytes; // The number of bytes this node needs. Node *pNode; // The node we allocate. // Calculate the number of bytes it takes to represent a node with // this many forward pointers. nBytes = (size_t)(&(((Node *)0x80000000) ->m_apForward[a_nForwardPointers])) - 0x80000000; // Allocate space. pNode = (Node *) m_rNodeAllocator.Allocate (a_nForwardPointers - 1, nBytes); if (pNode == NULL) return NULL; // Set the number of forward pointers. #ifdef DEBUG_SKIPLIST pNode->m_nLevel = a_nForwardPointers; #endif // DEBUG_SKIPLIST // Return what we allocated. return pNode; } // Allocate a new node with a random number of forward pointers. // Returns NULL if something goes wrong; otherwise, a_rnLevel gets // backpatched with the number of levels. template typename SkipList::Node * SkipList::GetNewNodeOfRandomLevel (int16_t &a_rnLevel) { // Fix the dice (as described in the skip-list paper). int16_t nHighestLevel = (m_nHeaderLevel == HEADERCHUNK) ? HEADERCHUNK : (m_nHeaderLevel + 1); // Now generate a random level for the node. (12055 / 32768 equals // our skip list's p, which is 1/e.) int16_t nNewLevel = 1; while (nNewLevel < nHighestLevel && Rand() < 12055) nNewLevel++; // Keep track of the new maximum. if (nNewLevel == nHighestLevel) m_nHeaderLevel = nHighestLevel; // Allocate a node of this size. a_rnLevel = nNewLevel; return GetNewNode (nNewLevel); } // Delete a node. template void SkipList::DeleteNode (int16_t a_nForwardPointers, Node *a_pToDelete) { // Make sure they gave us a node to delete. assert (a_pToDelete != NULL); // Delete the value we contain. a_pToDelete->m_oValue.~VALUE(); // Deallocate the node's storage. DeallocateNode (a_nForwardPointers, a_pToDelete); } // Deallocate a node's storage. template void SkipList::DeallocateNode (int16_t a_nForwardPointers, Node *a_pToDelete) { // Make sure they gave us a node to deallocate. assert (a_pToDelete != NULL); // Calculate the number of bytes it takes to represent a node with // this many forward pointers. size_t nBytes = (size_t)(&(((Node *)0x80000000) ->m_apForward[a_nForwardPointers])) - 0x80000000; // Return the memory to our node allocator. m_rNodeAllocator.Deallocate (a_nForwardPointers - 1, nBytes, (void *)a_pToDelete); } // Get another random number. template int16_t SkipList::Rand (void) { // I'd use the normal rand() but it's WAAAY too slow. // Feel free to adjust this routine all you want. m_nRandSeed = m_nRandSeed * 42989 + 17891; return int16_t (m_nRandSeed & 32767); } #ifdef DEBUG_SKIPLIST template void SkipList::Invariant (void) const { int32_t nI; // Used to loop through things. Node *pSearchFinger; // Used to verify the integrity of the forward pointers. Node *pCurrentNode; // The node whose integrity we are presently verifying. Node *pPreviousNode; // The node before the current one. uint32_t nItems; // The number of items we found. // Only check the invariant if they requested we do. if (!m_bDebug) return; // If the skip list is not fully initialized, we have less to check. if (m_pHeader == NULL) { assert (m_nHeaderLevel == 0); assert (m_pSearchFinger == NULL); assert (m_pSearchFinger2 == NULL); assert (m_nItems == 0); return; } // Make sure the skip list level isn't bigger than the compiled-in // maximum. assert (m_nHeaderLevel <= HEADERCHUNK); // Calculate the number of bytes it takes to represent a node with // this many forward pointers. size_t nBytes = (size_t)(&(((Node *)0x80000000) ->m_apForward[HEADERCHUNK])) - 0x80000000; // We're going to run through the skip list and make sure all the // forward pointers are correct. For that, we need a temporary // search finger to keep track of the traversal. pSearchFinger = (Node *) alloca (nBytes); pSearchFinger->m_nLevel = 0; pSearchFinger->m_pBackward = NULL; for (nI = 0; nI < HEADERCHUNK; nI++) pSearchFinger->m_apForward[nI] = m_pHeader; // The backward link for the header node points to the last item in // the list. So find the last item in the list. pPreviousNode = m_pHeader; while (pPreviousNode->m_apForward[0] != m_pHeader) pPreviousNode = pPreviousNode->m_apForward[0]; // Run through the skip list, make sure the forward pointers and // backward pointers are intact. pCurrentNode = m_pHeader; nItems = 0; for (;;) { int32_t nLevel; // The level of the current node. // At least one forward pointer of the temporary search finger // points to the current node. The number of forward pointers // that point to the current node, must be equal to its assigned // level. So start by calculating what level this node must be. nLevel = 0; while (nLevel < HEADERCHUNK && pSearchFinger->m_apForward[nLevel] == pCurrentNode) nLevel++; // Make sure the node has that many forward pointers. assert (pCurrentNode->m_nLevel == nLevel); // Make sure the backward pointer is intact. assert (pCurrentNode->m_pBackward == pPreviousNode); // Make sure that the nodes are in proper sorted order. if (pPreviousNode != m_pHeader && pCurrentNode != m_pHeader) { if (m_bAllowDuplicates) { // The current item has to be >= the previous item. assert (!m_oPred (m_oKeyFn (pCurrentNode->m_oValue), m_oKeyFn (pPreviousNode->m_oValue))); } else { // The current item has to be > the previous item. assert (m_oPred (m_oKeyFn (pPreviousNode->m_oValue), m_oKeyFn (pCurrentNode->m_oValue))); } } // If we're at the end of the list, stop. if (pCurrentNode->m_apForward[0] == m_pHeader) break; // That's one more item we found. (We put this here in order to // avoid counting the header node as an item.) nItems++; // Move forward. pPreviousNode = pCurrentNode; pCurrentNode = pCurrentNode->m_apForward[0]; for (nI = 0; nI < nLevel; nI++) pSearchFinger->m_apForward[nI] = pSearchFinger->m_apForward[nI]->m_apForward[nI]; } // Make sure the list has the expected number of items. assert (m_nItems == nItems); } #endif // DEBUG_SKIPLIST #endif // __SKIPLIST_H__ mjpegtools-2.1.0/y4mdenoise/newdenoise.cc0000644000175000017500000021543511175116204020750 0ustar glowwormglowworm// This file (C) 2004-2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "mjpeg_types.h" #include "mjpeg_logging.h" #include "yuv4mpeg.h" #include #include "newdenoise.hh" #include "MotionSearcher.hh" // Pixel types we use. typedef Pixel PixelY; typedef Pixel PixelCbCr; // Reference-pixel types we use. typedef ReferencePixel ReferencePixelY; typedef ReferencePixel ReferencePixelCbCr; // Reference-frame types we use. typedef ReferenceFrame ReferenceFrameY; typedef ReferenceFrame ReferenceFrameCbCr; // The denoisers. (We have to make these classes, in order to keep gdb // from crashing. I didn't even know one could crash gdb. ;-) #if 0 typedef MotionSearcher MotionSearcherY; typedef MotionSearcher MotionSearcherCbCr; #else class MotionSearcherY : public MotionSearcher {}; class MotionSearcherCbCr : public MotionSearcher {}; #endif MotionSearcherY g_oMotionSearcherY; MotionSearcherCbCr g_oMotionSearcherCbCr; // Whether the denoisers should be used. bool g_bMotionSearcherY; bool g_bMotionSearcherCbCr; // Pixel buffers, used to translate provided input into the form the // denoiser needs. int g_nPixelsY, g_nWidthY, g_nHeightY; MotionSearcherY::Pixel_t *g_pPixelsY; int g_nPixelsCbCr, g_nWidthCbCr, g_nHeightCbCr; MotionSearcherCbCr::Pixel_t *g_pPixelsCbCr; // Internal methods to output a frame. static void output_frame (const MotionSearcherY::ReferenceFrame_t *a_pFrameY, const MotionSearcherCbCr::ReferenceFrame_t *a_pFrameCbCr, uint8_t *a_pOutputY, uint8_t *a_pOutputCb, uint8_t *a_pOutputCr); static void output_field (int a_nMask, const MotionSearcherY::ReferenceFrame_t *a_pFrameY, const MotionSearcherCbCr::ReferenceFrame_t *a_pFrameCbCr, uint8_t *a_pOutputY, uint8_t *a_pOutputCb, uint8_t *a_pOutputCr); // A class wrapper for mutexes. class ThreadMutex { public: ThreadMutex(); // Default constructor. ~ThreadMutex(); // Destructor. void Lock (void); // Lock the mutex. void Unlock (void); // Unlock the mutex. operator pthread_mutex_t * (void) { return &m_oMutex; } operator const pthread_mutex_t * (void) const { return &m_oMutex; } // Accessor. private: pthread_mutex_t m_oMutex; // The wrapped mutex. #ifndef NDEBUG public: bool m_bLocked; // true if the mutex is locked. #endif // NDEBUG }; // A class to communicate conditions between threads. class ThreadCondition { public: ThreadCondition (ThreadMutex &a_rMutex); // Default constructor. ~ThreadCondition(); // Destructor. void Signal (void); // Signal the condition. // The mutex must be locked to call this. void Wait (void); // Wait for the condition to be signaled. // The mutex must be locked to call this. private: ThreadMutex &m_rMutex; // Provides mutual exclusion for the condition. pthread_cond_t m_oCondition; // The way the condition gets signaled if another thread is // waiting for it. Protected by the mutex. #ifndef NDEBUG bool m_bSignaled; // Whether or not a condition has been signaled. #endif // NDEBUG }; // A basic input/output-oriented thread. class BasicThread { public: BasicThread(); // Default constructor. virtual ~BasicThread(); // Destructor. void ForceShutdown (void); // Force the thread to terminate. protected: virtual int Work (void) = 0; // Do some work. // Must be implemented by the subclass. void Initialize (void); // Start the thread. // Called by the subclass' Initialize() method. void Lock (void); // Lock the mutex that guards the conditions. void Unlock (void); // Unlock the mutex that guards the conditions. #ifndef NDEBUG bool IsLocked (void) const; // True if the mutex is locked. #endif // !NDEBUG void SignalInput (void); // Signal that input has been provided to the thread. void WaitForInput (void); // Wait for input to be provided. void SignalOutput (void); // Signal that output has been provided to the thread. void WaitForOutput (void); // Wait for output to be provided. void Shutdown (void); // Stop the thread. pthread_t m_oThreadInfo; // OS-level thread state. private: ThreadMutex m_oMutex; // A mutex to guard general shared access to the thread's // data, as well as the following conditions. ThreadCondition m_oInputCondition, m_oOutputCondition; // Conditions to signal input-ready and output-ready. static void *WorkLoop (void *a_pThread); // The thread function stub. Calls the virtual WorkLoop(). public: void WorkLoopExit (void); // Clean up after WorkLoop() exits. // To be called only by the static WorkLoop(). protected: bool m_bWaitingForInput, m_bWaitingForOutput; // true if we're waiting for input/output (i.e. if they need // to be signaled). bool m_bWorkLoop; // true if WorkLoop() should continue running, false if it // should exit. virtual void WorkLoop (void); // The thread function. Loop, calling Work(), until told to // stop. int m_nWorkRetval; // The value returned by Work(). }; // A class to run denoisers in a separate thread. class DenoiserThread : public BasicThread { private: typedef BasicThread BaseClass; // Keep track of who our base class is. public: DenoiserThread(); // Default constructor. virtual ~DenoiserThread(); // Destructor. // Prototypes for methods that subclasses must implement. //void Initialize (subclass parameters); // Initialize. Set up all private thread data and start the // worker thread. //void AddFrame (subclass parameters); // Add a frame to the denoiser. //void WaitForAddFrame (subclass parameters); // Wait for the frame to be added & output possibly generated. //void Shutdown (subclass parameters); // Shut down the worker thread. protected: virtual void WorkLoop (void); // The thread function. Loop, calling Work(), until told to // stop. void AddFrame (void); // Add a frame to the denoiser. // Te be called by the subclass' AddFrame(). void WaitForAddFrame (void); // Wait for the frame to be added & output possibly generated. // Te be called by the subclass' WaitForAddFrame(). private: enum { m_kWaitingForFrame, m_kGivenFrame, m_kFinishedFrame }; int m_eWorkStatus; // Where we are in the process of denoising. }; // A class to run the intensity denoiser in a separate thread. class DenoiserThreadY : public DenoiserThread { private: typedef DenoiserThread BaseClass; // Keep track of who our base class is. public: DenoiserThreadY(); // Default constructor. virtual ~DenoiserThreadY(); // Destructor. void Initialize (void); // Initialize. Set up all private thread data and start the // worker thread. void AddFrame (const uint8_t *a_pInputY, uint8_t *a_pOutputY); // Add a frame to the denoiser. int WaitForAddFrame (void); // Get the next denoised frame, if any. // Returns the result of Work(). protected: virtual int Work (void); // Denoise the current frame. private: const uint8_t *m_pInputY; uint8_t *m_pOutputY; // Input/output buffers. }; // A class to run the color denoiser in a separate thread. class DenoiserThreadCbCr : public DenoiserThread { private: typedef DenoiserThread BaseClass; // Keep track of who our base class is. public: DenoiserThreadCbCr(); // Default constructor. virtual ~DenoiserThreadCbCr(); // Destructor. void Initialize (void); // Initialize. Set up all private thread data and start the // worker thread. void AddFrame (const uint8_t *a_pInputCb, const uint8_t *a_pInputCr, uint8_t *a_pOutputCb, uint8_t *a_pOutputCr); // Add a frame to the denoiser. int WaitForAddFrame (void); // Get the next denoised frame, if any. // Returns the result of Work(). protected: virtual int Work (void); // Denoise the current frame. private: const uint8_t *m_pInputCb; const uint8_t *m_pInputCr; uint8_t *m_pOutputCb; uint8_t *m_pOutputCr; // Input/output buffers. }; // A class to read/write raw-video in a separate thread. class ReadWriteThread : public BasicThread { private: typedef BasicThread BaseClass; // Keep track of who our base class is. public: ReadWriteThread(); // Default constructor. virtual ~ReadWriteThread(); // Destructor. void Initialize (int a_nFD, const y4m_stream_info_t *a_pStreamInfo, y4m_frame_info_t *a_pFrameInfo, int a_nWidthY, int a_nHeightY, int a_nWidthCbCr, int a_nHeightCbCr); // Start the thread. protected: int m_nFD; // The file descriptor from which to read/write raw video. const y4m_stream_info_t *m_pStreamInfo; // Information on the raw video stream. y4m_frame_info_t *m_pFrameInfo; // Information on the current frame in the raw video stream. struct Frame { uint8_t *planes[3]; Frame *next; }; // The type of a frame. Frame *m_apFrames; // Space for frames being read from input. enum { m_kNumFrames = 4 }; // The number of frames to allocate. Frame *m_pValidFramesHead, *m_pValidFramesTail, *m_pCurrentFrame, *m_pFreeFramesHead; // A list of frames containing data, the current frame, and // a list of free frames. Frame *GetFirstValidFrame (void); // Remove the first valid frame from the list and return it. void AddFrameToValidList (Frame *a_pFrame); // Add the given frame to the end of the valid-frame list. Frame *GetFreeFrame (void); // Remove a frame from the free-frames list and return it. void AddFrameToFreeList (Frame *a_pFrame); // Add the given frame to the free-frames list. void MoveValidFrameToCurrent (void); // Remove the first valid frame, and make it the current frame. void MoveCurrentFrameToValidList (void); // Move the current frame to the end of the valid-frame list. void MoveFreeFrameToCurrent (void); // Remove a frame from the free list, and make it the current // frame. void MoveCurrentFrameToFreeList (void); // Move the current frame to the free-frame list. }; // A class to read raw-video in a separate thread. class DenoiserThreadRead : public ReadWriteThread { private: typedef ReadWriteThread BaseClass; // Keep track of who our base class is. public: DenoiserThreadRead(); // Default constructor. virtual ~DenoiserThreadRead(); // Destructor. int ReadFrame (uint8_t **a_apPlanes); // Read a frame from input. a_apPlanes[] gets backpatched // with pointers to valid frame data, and they are valid until // the next call to ReadFrame(). // Returns Y4M_OK if it succeeds, Y4M_ERR_EOF at the end of // the stream. (Returns other errors too.) protected: virtual int Work (void); // Read frames from the raw-video stream. }; // A class to write raw-video in a separate thread. class DenoiserThreadWrite : public ReadWriteThread { private: typedef ReadWriteThread BaseClass; // Keep track of who our base class is. public: DenoiserThreadWrite(); // Default constructor. virtual ~DenoiserThreadWrite(); // Destructor. int GetSpaceToWriteFrame (uint8_t **a_apPlanes); // Get space for a frame to write to output. a_apPlanes[] gets // backpatched with pointers to valid frame data. // Returns Y4M_OK if it succeeds, something else if it fails. void WriteFrame (void); // Write a frame to output. The a_apPlanes[] previously set up // by GetSpaceToWriteFrame() must be filled with video data by // the client. protected: virtual void WorkLoop (void); // The thread function. Loop, calling Work(), until told to // stop. // Differs from BasicThread's implementation because it waits until // all pending frames are written before it stops. virtual int Work (void); // Write frames to the raw-video stream. }; // Threads for denoising intensity & color. DenoiserThreadY g_oDenoiserThreadY; DenoiserThreadCbCr g_oDenoiserThreadCbCr; // Threads for reading and writing raw video. DenoiserThreadRead g_oDenoiserThreadRead; DenoiserThreadWrite g_oDenoiserThreadWrite; // Initialize the denoising system. int newdenoise_init (int a_nFrames, int a_nWidthY, int a_nHeightY, int a_nWidthCbCr, int a_nHeightCbCr, int a_nInputFD, int a_nOutputFD, const y4m_stream_info_t *a_pStreamInfo, y4m_frame_info_t *a_pFrameInfo) { Status_t eStatus; // An error that may occur. int nInterlace; // A factor to apply to frames/frame-height because of // interlacing. // No errors yet. eStatus = g_kNoError; // Save the width and height. g_nWidthY = a_nWidthY; g_nHeightY = a_nHeightY; g_nWidthCbCr = a_nWidthCbCr; g_nHeightCbCr = a_nHeightCbCr; // If the video is interlaced, that means the denoiser will see // twice as many frames, half their original height. nInterlace = (denoiser.interlaced) ? 2 : 1; // If input/output should be handled in separate threads, set that // up. if (denoiser.threads & 1) { g_oDenoiserThreadRead.Initialize (a_nInputFD, a_pStreamInfo, a_pFrameInfo, a_nWidthY, a_nHeightY, a_nWidthCbCr, a_nHeightCbCr); g_oDenoiserThreadWrite.Initialize (a_nOutputFD, a_pStreamInfo, a_pFrameInfo, a_nWidthY, a_nHeightY, a_nWidthCbCr, a_nHeightCbCr); } // If intensity should be denoised, set it up. if (a_nWidthY != 0 && a_nHeightY != 0) { g_bMotionSearcherY = true; g_nPixelsY = (a_nWidthY * a_nHeightY) / nInterlace; g_pPixelsY = new MotionSearcherY::Pixel_t [g_nPixelsY]; if (g_pPixelsY == NULL) return -1; g_oMotionSearcherY.Init (eStatus, nInterlace * a_nFrames, a_nWidthY, a_nHeightY / nInterlace, denoiser.radiusY, denoiser.radiusY, denoiser.zThresholdY, denoiser.thresholdY, denoiser.matchCountThrottle, denoiser.matchSizeThrottle); if (eStatus != g_kNoError) { delete[] g_pPixelsY; return -1; } } else g_bMotionSearcherY = false; // If color should be denoised, set it up. if (a_nWidthCbCr != 0 && a_nHeightCbCr != 0) { g_bMotionSearcherCbCr = true; g_nPixelsCbCr = (a_nWidthCbCr * a_nHeightCbCr) / nInterlace; g_pPixelsCbCr = new MotionSearcherCbCr::Pixel_t [g_nPixelsCbCr]; if (g_pPixelsCbCr == NULL) { delete[] g_pPixelsY; return -1; } g_oMotionSearcherCbCr.Init (eStatus, nInterlace * a_nFrames, a_nWidthCbCr, a_nHeightCbCr / nInterlace, denoiser.radiusCbCr / denoiser.frame.ss_h, denoiser.radiusCbCr / denoiser.frame.ss_v, denoiser.zThresholdCbCr, denoiser.thresholdCbCr, denoiser.matchCountThrottle, denoiser.matchSizeThrottle); if (eStatus != g_kNoError) { delete[] g_pPixelsCbCr; delete[] g_pPixelsY; return -1; } // If color should be denoised in a separate thread, set that // up. if (denoiser.threads & 2) g_oDenoiserThreadCbCr.Initialize(); } else g_bMotionSearcherCbCr = false; // Initialization was successful. return 0; } // Shut down the denoising system. int newdenoise_shutdown (void) { // If color was denoised in a separate thread, shut that down. if (g_bMotionSearcherCbCr && (denoiser.threads & 2)) g_oDenoiserThreadCbCr.ForceShutdown(); // If reading/writing is being done in separate threads, shut // them down. if (denoiser.threads & 1) { g_oDenoiserThreadRead.ForceShutdown(); g_oDenoiserThreadWrite.ForceShutdown(); } // No errors. return 0; } /* Read another frame. Usable only in multi-threaded situations. */ int newdenoise_read_frame (uint8_t **a_apPlanes) { // Make sure the read/write threads are being used. assert (denoiser.threads & 1); // Easy enough. return g_oDenoiserThreadRead.ReadFrame (a_apPlanes); } /* Get space to write another frame. Usable only in multi-threaded situations. */ int newdenoise_get_write_frame (uint8_t **a_apPlanes) { // Make sure the read/write threads are being used. assert (denoiser.threads & 1); // Easy enough. return g_oDenoiserThreadWrite.GetSpaceToWriteFrame (a_apPlanes); } /* Write another frame. Usable only in multi-threaded situations. */ int newdenoise_write_frame (void) { // Make sure the read/write threads are being used. assert (denoiser.threads & 1); // Easy enough. g_oDenoiserThreadWrite.WriteFrame(); return Y4M_OK; } // (This routine isn't used any more, but I think it should be kept around // as a reference.) int newdenoise_frame0 (const uint8_t *a_pInputY, const uint8_t *a_pInputCb, const uint8_t *a_pInputCr, uint8_t *a_pOutputY, uint8_t *a_pOutputCb, uint8_t *a_pOutputCr) { Status_t eStatus; // An error that may occur. const MotionSearcherY::ReferenceFrame_t *pFrameY; const MotionSearcherCbCr::ReferenceFrame_t *pFrameCbCr; // Denoised frame data, ready for output. int i; // Used to loop through pixels. // No errors yet. eStatus = g_kNoError; // No output frames have been received yet. pFrameY = NULL; pFrameCbCr = NULL; // If it's time to purge, do so. { extern int frame; if (frame % denoiser.frames == 0) { g_oMotionSearcherY.Purge(); g_oMotionSearcherCbCr.Purge(); } } // If the end of input has been reached, then return the next // remaining denoised frame, if available. if ((g_bMotionSearcherY && a_pInputY == NULL) || (g_bMotionSearcherCbCr && a_pInputCr == NULL)) { // Get any remaining frame. if (g_bMotionSearcherY) pFrameY = g_oMotionSearcherY.GetRemainingFrames(); if (g_bMotionSearcherCbCr) pFrameCbCr = g_oMotionSearcherCbCr.GetRemainingFrames(); // Output it. output_frame (pFrameY, pFrameCbCr, a_pOutputY, a_pOutputCb, a_pOutputCr); } // Otherwise, if there is more input, feed the frame into the // denoiser & possibly get a frame back. else { // Get any frame that's ready for output. if (g_bMotionSearcherY) pFrameY = g_oMotionSearcherY.GetFrameReadyForOutput(); if (g_bMotionSearcherCbCr) pFrameCbCr = g_oMotionSearcherCbCr.GetFrameReadyForOutput(); // Output it. output_frame (pFrameY, pFrameCbCr, a_pOutputY, a_pOutputCb, a_pOutputCr); // Pass the input frame to the denoiser. if (g_bMotionSearcherY) { // Convert the input frame into the format needed by the // denoiser. (This step is a big waste of time & cache. // I wish there was another way.) for (i = 0; i < g_nPixelsY; ++i) g_pPixelsY[i] = PixelY (a_pInputY + i); // Pass the frame to the denoiser. g_oMotionSearcherY.AddFrame (eStatus, g_pPixelsY); if (eStatus != g_kNoError) return -1; } if (g_bMotionSearcherCbCr) { PixelCbCr::Num_t aCbCr[2]; // Convert the input frame into the format needed by the // denoiser. (This step is a big waste of time & cache. // I wish there was another way.) for (i = 0; i < g_nPixelsCbCr; ++i) { aCbCr[0] = a_pInputCb[i]; aCbCr[1] = a_pInputCr[i]; g_pPixelsCbCr[i] = PixelCbCr (aCbCr); } // Pass the frame to the denoiser. g_oMotionSearcherCbCr.AddFrame (eStatus, g_pPixelsCbCr); if (eStatus != g_kNoError) return -1; } } // If we're denoising both color & intensity, make sure we // either got two reference frames or none at all. assert (!g_bMotionSearcherY || !g_bMotionSearcherCbCr || (pFrameY == NULL && pFrameCbCr == NULL) || (pFrameY != NULL && pFrameCbCr != NULL)); // Return whether there was an output frame this time. return ((g_bMotionSearcherY && pFrameY != NULL) || (g_bMotionSearcherCbCr && pFrameCbCr != NULL)) ? 0 : 1; } int newdenoise_frame_intensity (const uint8_t *a_pInputY, uint8_t *a_pOutputY) { Status_t eStatus; // An error that may occur. const MotionSearcherY::ReferenceFrame_t *pFrameY; // Denoised frame data, ready for output. int i; // Used to loop through pixels. // Make sure intensity is being denoised. assert (g_bMotionSearcherY); // No errors yet. eStatus = g_kNoError; // No output frames have been received yet. pFrameY = NULL; // If it's time to purge, do so. { extern int frame; if (frame % denoiser.frames == 0) g_oMotionSearcherY.Purge(); } // If the end of input has been reached, then return the next // remaining denoised frame, if available. if (a_pInputY == NULL) { // Get any remaining frame. pFrameY = g_oMotionSearcherY.GetRemainingFrames(); // Output it. output_frame (pFrameY, NULL, a_pOutputY, NULL, NULL); } // Otherwise, if there is more input, feed the frame into the // denoiser & possibly get a frame back. else { // Get any frame that's ready for output. pFrameY = g_oMotionSearcherY.GetFrameReadyForOutput(); // Output it. output_frame (pFrameY, NULL, a_pOutputY, NULL, NULL); // Convert the input frame into the format needed by the // denoiser. (This step is a big waste of time & cache. // I wish there was another way.) for (i = 0; i < g_nPixelsY; ++i) g_pPixelsY[i] = PixelY (a_pInputY + i); // Pass the frame to the denoiser. g_oMotionSearcherY.AddFrame (eStatus, g_pPixelsY); if (eStatus != g_kNoError) return -1; } // Return whether there was an output frame this time. return (pFrameY != NULL) ? 0 : 1; } int newdenoise_frame_color (const uint8_t *a_pInputCb, const uint8_t *a_pInputCr, uint8_t *a_pOutputCb, uint8_t *a_pOutputCr) { Status_t eStatus; // An error that may occur. const MotionSearcherCbCr::ReferenceFrame_t *pFrameCbCr; // Denoised frame data, ready for output. int i; // Used to loop through pixels. // Make sure color is being denoised. assert (g_bMotionSearcherCbCr); // No errors yet. eStatus = g_kNoError; // No output frames have been received yet. pFrameCbCr = NULL; // If it's time to purge, do so. { extern int frame; if (frame % denoiser.frames == 0) g_oMotionSearcherCbCr.Purge(); } // If the end of input has been reached, then return the next // remaining denoised frame, if available. if (a_pInputCr == NULL) { // Get any remaining frame. pFrameCbCr = g_oMotionSearcherCbCr.GetRemainingFrames(); // Output it. output_frame (NULL, pFrameCbCr, NULL, a_pOutputCb, a_pOutputCr); } // Otherwise, if there is more input, feed the frame into the // denoiser & possibly get a frame back. else { // Get any frame that's ready for output. pFrameCbCr = g_oMotionSearcherCbCr.GetFrameReadyForOutput(); // Output it. output_frame (NULL, pFrameCbCr, NULL, a_pOutputCb, a_pOutputCr); // Pass the input frame to the denoiser. { PixelCbCr::Num_t aCbCr[2]; // Convert the input frame into the format needed by the // denoiser. (This step is a big waste of time & cache. // I wish there was another way.) for (i = 0; i < g_nPixelsCbCr; ++i) { aCbCr[0] = a_pInputCb[i]; aCbCr[1] = a_pInputCr[i]; g_pPixelsCbCr[i] = PixelCbCr (aCbCr); } // Pass the frame to the denoiser. g_oMotionSearcherCbCr.AddFrame (eStatus, g_pPixelsCbCr); if (eStatus != g_kNoError) return -1; } } // Return whether there was an output frame this time. return (pFrameCbCr != NULL) ? 0 : 1; } int newdenoise_frame (const uint8_t *a_pInputY, const uint8_t *a_pInputCb, const uint8_t *a_pInputCr, uint8_t *a_pOutputY, uint8_t *a_pOutputCb, uint8_t *a_pOutputCr) { int bY, bCbCr; // Make the compiler shut up. bY = bCbCr = 0; // Denoise intensity & color. (Do intensity in the current // thread.) if (g_bMotionSearcherCbCr && (denoiser.threads & 2)) g_oDenoiserThreadCbCr.AddFrame (a_pInputCb, a_pInputCr, a_pOutputCb, a_pOutputCr); if (g_bMotionSearcherY) bY = newdenoise_frame_intensity (a_pInputY, a_pOutputY); if (g_bMotionSearcherCbCr && !(denoiser.threads & 2)) bCbCr = newdenoise_frame_color (a_pInputCb, a_pInputCr, a_pOutputCb, a_pOutputCr); if (g_bMotionSearcherCbCr && (denoiser.threads & 2)) bCbCr = g_oDenoiserThreadCbCr.WaitForAddFrame(); // If we're denoising both color & intensity, make sure we // either got two reference frames or none at all. (This is // a sanity check, to make sure there are as many intensity // frames as color frames.) assert (!g_bMotionSearcherY || !g_bMotionSearcherCbCr || (bY != 0 && bCbCr != 0) || (bY == 0 && bCbCr == 0)); // Return 0 if there are no errors. return (bY) ? bY : bCbCr; } static void output_frame (const MotionSearcherY::ReferenceFrame_t *a_pFrameY, const MotionSearcherCbCr::ReferenceFrame_t *a_pFrameCbCr, uint8_t *a_pOutputY, uint8_t *a_pOutputCb, uint8_t *a_pOutputCr) { int i; // Used to loop through pixels. // Convert any denoised intensity frame into the format expected // by our caller. if (a_pFrameY != NULL) { ReferencePixelY *pY; // The pixel, as it's being converted to the output format. // Make sure our caller gave us somewhere to write output. assert (a_pOutputY != NULL); // Loop through all the pixels, convert them to the output // format. for (i = 0; i < g_nPixelsY; ++i) { pY = a_pFrameY->GetPixel (i); assert (pY != NULL); const PixelY &rY = pY->GetValue(); a_pOutputY[i] = rY[0]; } } if (a_pFrameCbCr != NULL) { ReferencePixelCbCr *pCbCr; // The pixel, as it's being converted to the output format. // Make sure our caller gave us somewhere to write output. assert (a_pOutputCb != NULL && a_pOutputCr != NULL); // Loop through all the pixels, convert them to the output // format. for (i = 0; i < g_nPixelsCbCr; ++i) { pCbCr = a_pFrameCbCr->GetPixel (i); assert (pCbCr != NULL); const PixelCbCr &rCbCr = pCbCr->GetValue(); a_pOutputCb[i] = rCbCr[0]; a_pOutputCr[i] = rCbCr[1]; } } } // (This routine isn't used any more, but I think it should be kept around // as a reference.) int newdenoise_interlaced_frame0 (const uint8_t *a_pInputY, const uint8_t *a_pInputCb, const uint8_t *a_pInputCr, uint8_t *a_pOutputY, uint8_t *a_pOutputCb, uint8_t *a_pOutputCr) { Status_t eStatus; // An error that may occur. const MotionSearcherY::ReferenceFrame_t *pFrameY; const MotionSearcherCbCr::ReferenceFrame_t *pFrameCbCr; // Denoised frame data, ready for output. int i, x, y; // Used to loop through pixels. int nMask; // Used to switch between top-field interlacing and bottom-field // interlacing. // No errors yet. eStatus = g_kNoError; // No output frames have been received yet. pFrameY = NULL; pFrameCbCr = NULL; // If it's time to purge, do so. { extern int frame; if (frame % denoiser.frames == 0) { g_oMotionSearcherY.Purge(); g_oMotionSearcherCbCr.Purge(); } } // Set up for the type of interlacing. nMask = (denoiser.interlaced == 2) ? 1 : 0; // If the end of input has been reached, then return the next // remaining denoised frame, if available. if ((g_bMotionSearcherY && a_pInputY == NULL) || (g_bMotionSearcherCbCr && a_pInputCr == NULL)) { // Get 1/2 any remaining frame. if (g_bMotionSearcherY) pFrameY = g_oMotionSearcherY.GetRemainingFrames(); if (g_bMotionSearcherCbCr) pFrameCbCr = g_oMotionSearcherCbCr.GetRemainingFrames(); // Output it. output_field (nMask ^ 0, pFrameY, pFrameCbCr, a_pOutputY, a_pOutputCb, a_pOutputCr); // Get 1/2 any remaining frame. if (g_bMotionSearcherY) pFrameY = g_oMotionSearcherY.GetRemainingFrames(); if (g_bMotionSearcherCbCr) pFrameCbCr = g_oMotionSearcherCbCr.GetRemainingFrames(); // Output it. output_field (nMask ^ 1, pFrameY, pFrameCbCr, a_pOutputY, a_pOutputCb, a_pOutputCr); } // Otherwise, if there is more input, feed the frame into the // denoiser & possibly get a frame back. else { // Get 1/2 any frame that's ready for output. if (g_bMotionSearcherY) pFrameY = g_oMotionSearcherY.GetFrameReadyForOutput(); if (g_bMotionSearcherCbCr) pFrameCbCr = g_oMotionSearcherCbCr.GetFrameReadyForOutput(); // Output it. output_field (nMask ^ 0, pFrameY, pFrameCbCr, a_pOutputY, a_pOutputCb, a_pOutputCr); // Pass the input frame to the denoiser. if (g_bMotionSearcherY) { // Convert the input frame into the format needed by the // denoiser. for (i = 0, y = (nMask ^ 0); y < g_nHeightY; y += 2) for (x = 0; x < g_nWidthY; ++x, ++i) g_pPixelsY[i] = PixelY (a_pInputY + (y * g_nWidthY + x)); assert (i == g_nPixelsY); // Pass the frame to the denoiser. g_oMotionSearcherY.AddFrame (eStatus, g_pPixelsY); if (eStatus != g_kNoError) return -1; } if (g_bMotionSearcherCbCr) { PixelCbCr::Num_t aCbCr[2]; // Convert the input frame into the format needed by the // denoiser. for (i = 0, y = (nMask ^ 0); y < g_nHeightCbCr; y += 2) { for (x = 0; x < g_nWidthCbCr; ++x, ++i) { aCbCr[0] = a_pInputCb[y * g_nWidthCbCr + x]; aCbCr[1] = a_pInputCr[y * g_nWidthCbCr + x]; g_pPixelsCbCr[i] = PixelCbCr (aCbCr); } } assert (i == g_nPixelsCbCr); // Pass the frame to the denoiser. g_oMotionSearcherCbCr.AddFrame (eStatus, g_pPixelsCbCr); if (eStatus != g_kNoError) return -1; } // Get 1/2 any frame that's ready for output. if (g_bMotionSearcherY) pFrameY = g_oMotionSearcherY.GetFrameReadyForOutput(); if (g_bMotionSearcherCbCr) pFrameCbCr = g_oMotionSearcherCbCr.GetFrameReadyForOutput(); // Output it. output_field (nMask ^ 1, pFrameY, pFrameCbCr, a_pOutputY, a_pOutputCb, a_pOutputCr); // Pass the input frame to the denoiser. if (g_bMotionSearcherY) { // Convert the input frame into the format needed by the // denoiser. for (i = 0, y = (nMask ^ 1); y < g_nHeightY; y += 2) for (x = 0; x < g_nWidthY; ++x, ++i) g_pPixelsY[i] = PixelY (a_pInputY + (y * g_nWidthY + x)); assert (i == g_nPixelsY); // Pass the frame to the denoiser. g_oMotionSearcherY.AddFrame (eStatus, g_pPixelsY); if (eStatus != g_kNoError) return -1; } if (g_bMotionSearcherCbCr) { PixelCbCr::Num_t aCbCr[2]; // Convert the input frame into the format needed by the // denoiser. for (i = 0, y = (nMask ^ 1); y < g_nHeightCbCr; y += 2) { for (x = 0; x < g_nWidthCbCr; ++x, ++i) { aCbCr[0] = a_pInputCb[y * g_nWidthCbCr + x]; aCbCr[1] = a_pInputCr[y * g_nWidthCbCr + x]; g_pPixelsCbCr[i] = PixelCbCr (aCbCr); } } assert (i == g_nPixelsCbCr); // Pass the frame to the denoiser. g_oMotionSearcherCbCr.AddFrame (eStatus, g_pPixelsCbCr); if (eStatus != g_kNoError) return -1; } } // If we're denoising both color & intensity, make sure we // either got two reference frames or none at all. assert (!g_bMotionSearcherY || !g_bMotionSearcherCbCr || (pFrameY == NULL && pFrameCbCr == NULL) || (pFrameY != NULL && pFrameCbCr != NULL)); // Return whether there was an output frame this time. return ((g_bMotionSearcherY && pFrameY != NULL) || (g_bMotionSearcherCbCr && pFrameCbCr != NULL)) ? 0 : 1; } int newdenoise_interlaced_frame_intensity (const uint8_t *a_pInputY, uint8_t *a_pOutputY) { Status_t eStatus; // An error that may occur. const MotionSearcherY::ReferenceFrame_t *pFrameY; // Denoised frame data, ready for output. int i, x, y; // Used to loop through pixels. int nMask; // Used to switch between top-field interlacing and bottom-field // interlacing. // Make sure intensity is being denoised. assert (g_bMotionSearcherY); // No errors yet. eStatus = g_kNoError; // No output frames have been received yet. pFrameY = NULL; // If it's time to purge, do so. { extern int frame; if (frame % denoiser.frames == 0) g_oMotionSearcherY.Purge(); } // Set up for the type of interlacing. nMask = (denoiser.interlaced == 2) ? 1 : 0; // If the end of input has been reached, then return the next // remaining denoised frame, if available. if (a_pInputY == NULL) { // Get 1/2 any remaining frame. pFrameY = g_oMotionSearcherY.GetRemainingFrames(); // Output it. output_field (nMask ^ 0, pFrameY, NULL, a_pOutputY, NULL, NULL); // Get 1/2 any remaining frame. pFrameY = g_oMotionSearcherY.GetRemainingFrames(); // Output it. output_field (nMask ^ 1, pFrameY, NULL, a_pOutputY, NULL, NULL); } // Otherwise, if there is more input, feed the frame into the // denoiser & possibly get a frame back. else { // Get 1/2 any frame that's ready for output. pFrameY = g_oMotionSearcherY.GetFrameReadyForOutput(); // Output it. output_field (nMask ^ 0, pFrameY, NULL, a_pOutputY, NULL, NULL); // Convert the input frame into the format needed by the // denoiser. for (i = 0, y = (nMask ^ 0); y < g_nHeightY; y += 2) for (x = 0; x < g_nWidthY; ++x, ++i) g_pPixelsY[i] = PixelY (a_pInputY + (y * g_nWidthY + x)); assert (i == g_nPixelsY); // Pass the frame to the denoiser. g_oMotionSearcherY.AddFrame (eStatus, g_pPixelsY); if (eStatus != g_kNoError) return -1; // Get 1/2 any frame that's ready for output. pFrameY = g_oMotionSearcherY.GetFrameReadyForOutput(); // Output it. output_field (nMask ^ 1, pFrameY, NULL, a_pOutputY, NULL, NULL); // Convert the input frame into the format needed by the // denoiser. for (i = 0, y = (nMask ^ 1); y < g_nHeightY; y += 2) for (x = 0; x < g_nWidthY; ++x, ++i) g_pPixelsY[i] = PixelY (a_pInputY + (y * g_nWidthY + x)); assert (i == g_nPixelsY); // Pass the frame to the denoiser. g_oMotionSearcherY.AddFrame (eStatus, g_pPixelsY); if (eStatus != g_kNoError) return -1; } // Return whether there was an output frame this time. return (pFrameY != NULL) ? 0 : 1; } int newdenoise_interlaced_frame_color (const uint8_t *a_pInputCb, const uint8_t *a_pInputCr, uint8_t *a_pOutputCb, uint8_t *a_pOutputCr) { Status_t eStatus; // An error that may occur. const MotionSearcherCbCr::ReferenceFrame_t *pFrameCbCr; // Denoised frame data, ready for output. int i, x, y; // Used to loop through pixels. int nMask; // Used to switch between top-field interlacing and bottom-field // interlacing. // Make sure color is being denoised. assert (g_bMotionSearcherCbCr); // No errors yet. eStatus = g_kNoError; // No output frames have been received yet. pFrameCbCr = NULL; // If it's time to purge, do so. { extern int frame; if (frame % denoiser.frames == 0) g_oMotionSearcherCbCr.Purge(); } // Set up for the type of interlacing. nMask = (denoiser.interlaced == 2) ? 1 : 0; // If the end of input has been reached, then return the next // remaining denoised frame, if available. if (a_pInputCr == NULL) { // Get 1/2 any remaining frame. pFrameCbCr = g_oMotionSearcherCbCr.GetRemainingFrames(); // Output it. output_field (nMask ^ 0, NULL, pFrameCbCr, NULL, a_pOutputCb, a_pOutputCr); // Get 1/2 any remaining frame. pFrameCbCr = g_oMotionSearcherCbCr.GetRemainingFrames(); // Output it. output_field (nMask ^ 1, NULL, pFrameCbCr, NULL, a_pOutputCb, a_pOutputCr); } // Otherwise, if there is more input, feed the frame into the // denoiser & possibly get a frame back. else { // Get 1/2 any frame that's ready for output. pFrameCbCr = g_oMotionSearcherCbCr.GetFrameReadyForOutput(); // Output it. output_field (nMask ^ 0, NULL, pFrameCbCr, NULL, a_pOutputCb, a_pOutputCr); // Pass the input frame to the denoiser. { PixelCbCr::Num_t aCbCr[2]; // Convert the input frame into the format needed by the // denoiser. for (i = 0, y = (nMask ^ 0); y < g_nHeightCbCr; y += 2) { for (x = 0; x < g_nWidthCbCr; ++x, ++i) { aCbCr[0] = a_pInputCb[y * g_nWidthCbCr + x]; aCbCr[1] = a_pInputCr[y * g_nWidthCbCr + x]; g_pPixelsCbCr[i] = PixelCbCr (aCbCr); } } assert (i == g_nPixelsCbCr); // Pass the frame to the denoiser. g_oMotionSearcherCbCr.AddFrame (eStatus, g_pPixelsCbCr); if (eStatus != g_kNoError) return -1; } // Get 1/2 any frame that's ready for output. pFrameCbCr = g_oMotionSearcherCbCr.GetFrameReadyForOutput(); // Output it. output_field (nMask ^ 1, NULL, pFrameCbCr, NULL, a_pOutputCb, a_pOutputCr); // Pass the input frame to the denoiser. { PixelCbCr::Num_t aCbCr[2]; // Convert the input frame into the format needed by the // denoiser. for (i = 0, y = (nMask ^ 1); y < g_nHeightCbCr; y += 2) { for (x = 0; x < g_nWidthCbCr; ++x, ++i) { aCbCr[0] = a_pInputCb[y * g_nWidthCbCr + x]; aCbCr[1] = a_pInputCr[y * g_nWidthCbCr + x]; g_pPixelsCbCr[i] = PixelCbCr (aCbCr); } } assert (i == g_nPixelsCbCr); // Pass the frame to the denoiser. g_oMotionSearcherCbCr.AddFrame (eStatus, g_pPixelsCbCr); if (eStatus != g_kNoError) return -1; } } // Return whether there was an output frame this time. return (pFrameCbCr != NULL) ? 0 : 1; } int newdenoise_interlaced_frame (const uint8_t *a_pInputY, const uint8_t *a_pInputCb, const uint8_t *a_pInputCr, uint8_t *a_pOutputY, uint8_t *a_pOutputCb, uint8_t *a_pOutputCr) { int bY, bCbCr; // Make the compiler shut up. bY = bCbCr = 0; // Denoise intensity & color. (Intensity is denoised in the // current thread.) if (g_bMotionSearcherCbCr && (denoiser.threads & 2)) g_oDenoiserThreadCbCr.AddFrame (a_pInputCb, a_pInputCr, a_pOutputCb, a_pOutputCr); if (g_bMotionSearcherY) bY = newdenoise_interlaced_frame_intensity (a_pInputY, a_pOutputY); if (g_bMotionSearcherCbCr && !(denoiser.threads & 2)) bCbCr = newdenoise_interlaced_frame_color (a_pInputCb, a_pInputCr, a_pOutputCb, a_pOutputCr); if (g_bMotionSearcherCbCr && (denoiser.threads & 2)) bCbCr = g_oDenoiserThreadCbCr.WaitForAddFrame(); // If we're denoising both color & intensity, make sure we // either got two reference frames or none at all. assert (!g_bMotionSearcherY || !g_bMotionSearcherCbCr || (bY != 0 && bCbCr != 0) || (bY == 0 && bCbCr == 0)); // Return 0 if there are no errors. return (bY) ? bY : bCbCr; } static void output_field (int a_nMask, const MotionSearcherY::ReferenceFrame_t *a_pFrameY, const MotionSearcherCbCr::ReferenceFrame_t *a_pFrameCbCr, uint8_t *a_pOutputY, uint8_t *a_pOutputCb, uint8_t *a_pOutputCr) { int i, x, y; // Used to loop through pixels. // Convert any denoised intensity frame into the format expected // by our caller. if (a_pFrameY != NULL) { ReferencePixelY *pY; // The pixel, as it's being converted to the output format. // Make sure our caller gave us somewhere to write output. assert (a_pOutputY != NULL); // Loop through all the pixels, convert them to the output // format. for (i = 0, y = a_nMask; y < g_nHeightY; y += 2) { for (x = 0; x < g_nWidthY; ++x, ++i) { pY = a_pFrameY->GetPixel (i); assert (pY != NULL); const PixelY &rY = pY->GetValue(); a_pOutputY[y * g_nWidthY + x] = rY[0]; } } } if (a_pFrameCbCr != NULL) { ReferencePixelCbCr *pCbCr; // The pixel, as it's being converted to the output format. // Make sure our caller gave us somewhere to write output. assert (a_pOutputCb != NULL && a_pOutputCr != NULL); // Loop through all the pixels, convert them to the output // format. for (i = 0, y = a_nMask; y < g_nHeightCbCr; y += 2) { for (x = 0; x < g_nWidthCbCr; ++x, ++i) { pCbCr = a_pFrameCbCr->GetPixel (i); assert (pCbCr != NULL); const PixelCbCr &rCbCr = pCbCr->GetValue(); a_pOutputCb[y * g_nWidthCbCr + x] = rCbCr[0]; a_pOutputCr[y * g_nWidthCbCr + x] = rCbCr[1]; } } } } // Pixel methods. // Turn an integer tolerance value into what's appropriate for // the pixel type. template <> int32_t PixelY::MakeTolerance (uint8_t a_tnTolerance) { // For a one-dimensional pixel, just use the given number. return int32_t (a_tnTolerance); } // Turn an integer tolerance value into what's appropriate for // the pixel type. template <> int32_t PixelCbCr::MakeTolerance (uint8_t a_tnTolerance) { // For a two-dimensional pixel, use the square of the given number. return int32_t (a_tnTolerance) * int32_t (a_tnTolerance); } // Return true if the two pixels are within the specified tolerance. template <> bool PixelY::IsWithinTolerance (const PixelY &a_rOther, int32_t a_tnTolerance) const { // Check to see if the absolute value of the difference between // the two pixels is within our tolerance value. return AbsoluteValue (int32_t (m_atnVal[0]) - int32_t (a_rOther.m_atnVal[0])) <= a_tnTolerance; } // Return true if the two pixels are within the specified tolerance. template <> bool PixelY::IsWithinTolerance (const PixelY &a_rOther, int32_t a_tnTolerance, int32_t &a_rtnSAD) const { // Check to see if the absolute value of the difference between // the two pixels is within our tolerance value. a_rtnSAD = AbsoluteValue (int32_t (m_atnVal[0]) - int32_t (a_rOther.m_atnVal[0])); return a_rtnSAD <= a_tnTolerance; } // Return true if the two pixels are within the specified tolerance. template <> bool PixelCbCr::IsWithinTolerance (const PixelCbCr &a_rOther, int32_t a_tnTolerance) const { // Calculate the vector difference between the two pixels. int32_t tnX = int32_t (m_atnVal[0]) - int32_t (a_rOther.m_atnVal[0]); int32_t tnY = int32_t (m_atnVal[1]) - int32_t (a_rOther.m_atnVal[1]); // Check to see if the length of the vector difference is within // our tolerance value. (Technically, we check the squares of // the values, but that's just as valid & much faster than // calculating a square root.) return tnX * tnX + tnY * tnY <= a_tnTolerance; } // Return true if the two pixels are within the specified tolerance. template <> bool PixelCbCr::IsWithinTolerance (const PixelCbCr &a_rOther, int32_t a_tnTolerance, int32_t &a_rtnSAD) const { // Calculate the vector difference between the two pixels. int32_t tnX = int32_t (m_atnVal[0]) - int32_t (a_rOther.m_atnVal[0]); int32_t tnY = int32_t (m_atnVal[1]) - int32_t (a_rOther.m_atnVal[1]); // Calculate the sample-array-difference. a_rtnSAD = tnX * tnX + tnY * tnY; // Check to see if the length of the vector difference is within // our tolerance value. (Technically, we check the squares of // the values, but that's just as valid & much faster than // calculating a square root.) return a_rtnSAD <= a_tnTolerance; } // The ThreadMutex class. // Default constructor. ThreadMutex::ThreadMutex() { int nErr; // An error that may occur. pthread_mutexattr_t sMutexAttr; // Attributes for the mutex. #ifndef NDEBUG // Not locked upon creation. m_bLocked = false; #endif // NDEBUG // Initialize the mutex. nErr = pthread_mutexattr_init (&sMutexAttr); if (nErr != 0) mjpeg_error_exit1 ("pthread_mutexattr_init() failed: %s", strerror (nErr)); nErr = pthread_mutex_init (&m_oMutex, &sMutexAttr); if (nErr != 0) mjpeg_error_exit1 ("pthread_mutex_init() failed: %s", strerror (nErr)); nErr = pthread_mutexattr_destroy (&sMutexAttr); if (nErr != 0) mjpeg_error_exit1 ("pthread_mutexattr_destroy() failed: %s", strerror (nErr)); } // Destructor. ThreadMutex::~ThreadMutex() { int nErr; // An error that may occur. // Make sure it's not locked. assert (!m_bLocked); // Destroy the mutex. nErr = pthread_mutex_destroy (&m_oMutex); if (nErr != 0) mjpeg_error_exit1 ("pthread_mutex_destroy() failed: %s", strerror (nErr)); } // Lock the mutex. void ThreadMutex::Lock (void) { int nErr; // An error that may occur. // Note that the mutex could either be locked or unlocked when this // method is called. If it's locked, we'll have to wait our turn. // Get exclusive access. nErr = pthread_mutex_lock (&m_oMutex); if (nErr != 0) mjpeg_error_exit1 ("pthread_mutex_lock() failed: %s", strerror (nErr)); #ifndef NDEBUG // Make sure it wasn't locked already. assert (!m_bLocked); // Now it's locked. m_bLocked = true; #endif // NDEBUG } // Unlock the mutex void ThreadMutex::Unlock (void) { int nErr; // An error that may occur. // Make sure it's locked. assert (m_bLocked); #ifndef NDEBUG // Now it's unlocked. m_bLocked = false; #endif // NDEBUG // Release exclusive access. nErr = pthread_mutex_unlock (&m_oMutex); if (nErr != 0) mjpeg_error_exit1 ("pthread_mutex_unlock() failed: %s", strerror (nErr)); } // The ThreadCondition class. // Default constructor. ThreadCondition::ThreadCondition (ThreadMutex &a_rMutex) : m_rMutex (a_rMutex) { int nErr; // An error that may occur. pthread_condattr_t sCondAttr; // Attributes for the condition. // Initialize the condition. nErr = pthread_condattr_init (&sCondAttr); if (nErr != 0) mjpeg_error_exit1 ("pthread_condattr_init() failed: %s", strerror (nErr)); nErr = pthread_cond_init (&m_oCondition, &sCondAttr); if (nErr != 0) mjpeg_error_exit1 ("pthread_cond_init() failed: %s", strerror (nErr)); nErr = pthread_condattr_destroy (&sCondAttr); if (nErr != 0) mjpeg_error_exit1 ("pthread_condattr_destroy() failed: %s", strerror (nErr)); #ifndef NDEBUG // No signal yet. m_bSignaled = false; #endif // NDEBUG } // Destructor. ThreadCondition::~ThreadCondition() { int nErr; // An error that may occur. // Destroy the condition. nErr = pthread_cond_destroy (&m_oCondition); if (nErr != 0) mjpeg_error_exit1 ("pthread_cond_destroy() failed: %s", strerror (nErr)); } // Signal the condition. void ThreadCondition::Signal (void) { int nErr; // An error that may occur. // Make sure our mutex is locked. assert (m_rMutex.m_bLocked); #ifndef NDEBUG // Make sure we haven't been signaled already. assert (!m_bSignaled); // Remember we've been signaled. m_bSignaled = true; #endif // NDEBUG // Signal the condition. nErr = pthread_cond_signal (&m_oCondition); if (nErr != 0) mjpeg_error_exit1 ("pthread_cond_signal() failed: %s", strerror (nErr)); } // Wait for the condition to be signaled. void ThreadCondition::Wait (void) { int nErr; // An error that may occur. // Make sure our mutex is locked. assert (m_rMutex.m_bLocked); // Make sure a condition hasn't been signaled. (We have to wait // for it first, in order for signaling to mean anything.) assert (!m_bSignaled); #ifndef NDEBUG // Waiting on the condition will unlock the mutex. m_rMutex.m_bLocked = false; #endif // NDEBUG // Wait for the condition to be signaled. nErr = pthread_cond_wait (&m_oCondition, m_rMutex); if (nErr != 0) mjpeg_error_exit1 ("pthread_cond_wait() failed: %s", strerror (nErr)); // Make sure the condition was signaled properly. assert (m_bSignaled); // Make sure the mutex thinks it's still unlocked. // (It's actually locked...the mutex was re-acquired // when the wait succeeded.) assert (!m_rMutex.m_bLocked); #ifndef NDEBUG // Remember that the mutex is actually locked. m_rMutex.m_bLocked = true; // The signal has been delivered. m_bSignaled = false; #endif // NDEBUG } // The BasicThread class. // Default constructor. BasicThread::BasicThread() : m_oInputCondition (m_oMutex), m_oOutputCondition (m_oMutex) { // No waiting yet. m_bWaitingForInput = m_bWaitingForOutput = false; // No work yet. m_bWorkLoop = false; // No return value yet. m_nWorkRetval = Y4M_OK; // Nothing additional to do. m_oInputCondition and // m_oOutputCondition are already constructed, and m_oThreadInfo is // initialized by pthread_create(), called in Initialize(). } // Destructor. BasicThread::~BasicThread() { // Nothing additional to do. m_oInputCondition and // m_oOutputCondition are destroyed by default, and m_oThreadInfo // apparently does not need to be destroyed. } // Force the thread to terminate. void BasicThread::ForceShutdown (void) { // Get exclusive access. Lock(); // Shut down the thread. (No need to unlock; Shutdown() will do that.) Shutdown(); } // Start the thread. void BasicThread::Initialize (void) { int nErr; // An error that may occur. pthread_attr_t sThreadAttributes; // Where we set up thread attributes. // Set up to work. m_bWorkLoop = true; // Set up the initial, default set of thread attributes. nErr = pthread_attr_init (&sThreadAttributes); if (nErr != 0) mjpeg_error_exit1 ("pthread_attr_init() failed: %s", strerror (nErr)); // Inherit scheduling parameters from the main thread. nErr = pthread_attr_setinheritsched (&sThreadAttributes, PTHREAD_INHERIT_SCHED); if (nErr != 0) mjpeg_error_exit1 ("pthread_attr_setinheritsched() failed: %s", strerror (nErr)); // Create the thread. nErr = pthread_create (&m_oThreadInfo, &sThreadAttributes, WorkLoop, (void *)this); if (nErr != 0) mjpeg_error_exit1 ("pthread_create() failed: %s", strerror (nErr)); } // Lock the mutex that guards the conditions. void BasicThread::Lock (void) { // Easy enough. m_oMutex.Lock(); } // Unlock the mutex that guards the conditions. void BasicThread::Unlock (void) { // Easy enough. m_oMutex.Unlock(); } #ifndef NDEBUG // Returns true if the mutex is locked. bool BasicThread::IsLocked (void) const { // Easy enough. return m_oMutex.m_bLocked; } #endif // !NDEBUG // Signal that input has been provided to the thread. void BasicThread::SignalInput (void) { // Make sure the mutex is locked. assert (IsLocked()); // Easy enough. m_oInputCondition.Signal(); // We're no longer waiting for output. m_bWaitingForInput = false; } // Wait for input to be provided. // Called by the subclass' Work() method. void BasicThread::WaitForInput (void) { // Make sure the mutex is locked. assert (IsLocked()); // Make sure we're not already waiting for input. assert (!m_bWaitingForInput); // Easy enough. m_bWaitingForInput = true; m_oInputCondition.Wait(); assert (!m_bWaitingForInput); } // Signal that output has been provided to the thread. // Called by the subclass' Work() method. void BasicThread::SignalOutput (void) { // Make sure the mutex is locked. assert (IsLocked()); // Easy enough. m_oOutputCondition.Signal(); // We're no longer waiting for output. m_bWaitingForOutput = false; } // Wait for output to be provided. void BasicThread::WaitForOutput (void) { // Make sure the mutex is locked. assert (IsLocked()); // Make sure we're not already waiting for output. assert (!m_bWaitingForOutput); // Easy enough. m_bWaitingForOutput = true; m_oOutputCondition.Wait(); assert (!m_bWaitingForOutput); } // Stop the thread. void BasicThread::Shutdown (void) { // Make sure we have exclusive access. assert (IsLocked()); // Tell the thread to stop looping. m_bWorkLoop = false; // If anyone is waiting, stop them. They should notice // that m_bWorkLoop is now false (or that m_nWorkRetval // is not Y4M_OK) and gracefully exit. if (m_bWaitingForInput) SignalInput(); if (m_bWaitingForOutput) SignalOutput(); // Release exclusive access. Unlock(); // Wait for the loop to stop. int nErr = pthread_join (m_oThreadInfo, NULL); if (nErr != 0) mjpeg_error_exit1 ("pthread_join() failed: %s", strerror (nErr)); } // The thread function. void * BasicThread::WorkLoop (void *a_pThread) { // Make sure they gave us a thread object. assert (a_pThread != NULL); // Call the real work loop. (static_cast(a_pThread))->WorkLoop(); // Clean up after WorkLoop() exits. (static_cast(a_pThread))->WorkLoopExit(); // Mandatory return value. return NULL; } // Clean up after WorkLoop() exits. // To be called only by the static WorkLoop(). void BasicThread::WorkLoopExit (void) { // If the work loop stopped due of an error, clean up. // This is similar to Shutdown(), but without the pthread_join(). if (m_nWorkRetval != Y4M_OK) { // Get exclusive access. Lock(); // Tell the thread to stop looping. m_bWorkLoop = false; // If anyone is waiting, stop them. They should notice // that m_bWorkLoop is now false (or that m_nWorkRetval // is not Y4M_OK) and gracefully exit. if (m_bWaitingForInput) SignalInput(); if (m_bWaitingForOutput) SignalOutput(); // Release exclusive access. Unlock(); } } // The thread function. Loop, calling Work(), until told to stop. void BasicThread::WorkLoop (void) { // Loop and do work until told to quit. while (m_bWorkLoop) { // Do work. m_nWorkRetval = Work(); // If it returned non-OK, stop. if (m_nWorkRetval != Y4M_OK) break; } } // The DenoiserThread class. // Default constructor. DenoiserThread::DenoiserThread() { // No work done yet. m_eWorkStatus = m_kWaitingForFrame; } // Destructor. DenoiserThread::~DenoiserThread() { // Nothing additional to do. } // The thread function. Loop, calling Work(), until told to stop. void DenoiserThread::WorkLoop (void) { // Loop and do work until told to quit. while (m_bWorkLoop) { // Wait for an input frame. Lock(); if (m_eWorkStatus != m_kGivenFrame) WaitForInput(); bool bWorkLoop = m_bWorkLoop; Unlock(); // If there's no more work to do, stop. if (!bWorkLoop) break; // Do work. assert (m_eWorkStatus == m_kGivenFrame); m_nWorkRetval = Work(); // Signal that there's output. Lock(); m_eWorkStatus = m_kFinishedFrame; if (m_bWaitingForOutput) SignalOutput(); Unlock(); } } // Add a frame to the denoiser. void DenoiserThread::AddFrame (void) { // Make sure we have exclusive access. assert (IsLocked()); // Make sure they're waiting for a frame. assert (m_eWorkStatus == m_kWaitingForFrame); // Now they've been given a frame. m_eWorkStatus = m_kGivenFrame; // Signal the availability of input. if (m_bWaitingForInput) SignalInput(); } // Get the next denoised frame, if any. void DenoiserThread::WaitForAddFrame (void) { // Make sure we have exclusive access. assert (IsLocked()); // Make sure that we know we're working. assert (m_eWorkStatus != m_kWaitingForFrame); // Wait for the current frame to finish denoising. if (m_eWorkStatus != m_kFinishedFrame) WaitForOutput(); assert (m_eWorkStatus == m_kFinishedFrame); // Now we're waiting for another frame. m_eWorkStatus = m_kWaitingForFrame; } // The DenoiserThreadY class. // Default constructor. DenoiserThreadY::DenoiserThreadY() { // No input/output buffers yet. m_pInputY = NULL; m_pOutputY = NULL; } // Destructor. DenoiserThreadY::~DenoiserThreadY() { // Nothing to do. } // Initialize. Set up all private thread data and start the // worker thread. void DenoiserThreadY::Initialize (void) { // Let the base class initialize itself. BaseClass::Initialize(); } // Add a frame to the denoiser. void DenoiserThreadY::AddFrame (const uint8_t *a_pInputY, uint8_t *a_pOutputY) { // Make sure they gave us a new frame to denoise. assert (a_pInputY != NULL && a_pOutputY != NULL); // Get exclusive access. Lock(); // Make sure there's not a current frame already. assert (m_pInputY == NULL && m_pOutputY == NULL); // Store the parameters. m_pInputY = a_pInputY; m_pOutputY = a_pOutputY; // Signal the availability of input. BaseClass::AddFrame(); // Release exclusive access. Unlock(); } // Get the next denoised frame, if any. int DenoiserThreadY::WaitForAddFrame (void) { // Get exclusive access. Lock(); // Make sure we're denoising a frame. assert (m_pInputY != NULL && m_pOutputY != NULL); // Wait for the current frame to finish denoising. BaseClass::WaitForAddFrame(); // We're done denoising this frame. m_pInputY = NULL; m_pOutputY = NULL; // Release exclusive access. Unlock(); // Let our caller know if there's another frame. return m_nWorkRetval; } // Denoise the current frame. int DenoiserThreadY::Work (void) { // Make sure we're denoising a frame. assert (m_pInputY != NULL && m_pOutputY != NULL); // Denoise the current frame. return ((denoiser.interlaced != 0) ? newdenoise_interlaced_frame_intensity : newdenoise_frame_intensity) (m_pInputY, m_pOutputY); } // The DenoiserThreadCbCr class. // Default constructor. DenoiserThreadCbCr::DenoiserThreadCbCr() { // No input/output buffers yet. m_pInputCb = NULL; m_pInputCr = NULL; m_pOutputCb = NULL; m_pOutputCr = NULL; } // Destructor. DenoiserThreadCbCr::~DenoiserThreadCbCr() { // Nothing to do. } // Initialize. Set up all private thread data and start the // worker thread. void DenoiserThreadCbCr::Initialize (void) { // Let the base class initialize itself. BaseClass::Initialize(); } // Add a frame to the denoiser. void DenoiserThreadCbCr::AddFrame (const uint8_t *a_pInputCb, const uint8_t *a_pInputCr, uint8_t *a_pOutputCb, uint8_t *a_pOutputCr) { // Make sure they gave us a frame to denoise. (Actually, // a null input frame means that the end of input has // been reached, which is OK, but there always needs to // be space for an output frame.) assert ((a_pInputCb == NULL && a_pInputCr == NULL) || (a_pInputCb != NULL && a_pInputCr != NULL)); assert (a_pOutputCb != NULL && a_pOutputCr != NULL); // Get exclusive access. Lock(); // Make sure there isn't already a current frame. assert (m_pInputCb == NULL && m_pInputCr == NULL && m_pOutputCb == NULL && m_pOutputCr == NULL); // Store the parameters. m_pInputCb = a_pInputCb; m_pInputCr = a_pInputCr; m_pOutputCb = a_pOutputCb; m_pOutputCr = a_pOutputCr; // Signal the availability of input. BaseClass::AddFrame(); // Release exclusive access. Unlock(); } // Get the next denoised frame, if any. int DenoiserThreadCbCr::WaitForAddFrame (void) { // Get exclusive access. Lock(); // Make sure there's a current frame. (Actually, // a null input frame means that the end of input has // been reached, which is OK, but there always needs to // be space for an output frame.) assert ((m_pInputCb == NULL && m_pInputCr == NULL) || (m_pInputCb != NULL && m_pInputCr != NULL)); assert (m_pOutputCb != NULL && m_pOutputCr != NULL); // Wait for the frame to finish denoising. BaseClass::WaitForAddFrame(); // We're done denoising this frame. m_pInputCb = NULL; m_pInputCr = NULL; m_pOutputCb = NULL; m_pOutputCr = NULL; // Release exclusive access. Unlock(); // Let our caller know if there's a new frame. return m_nWorkRetval; } // Denoise the current frame. int DenoiserThreadCbCr::Work (void) { // Make sure there's a current frame. (Actually, // a null input frame means that the end of input has // been reached, which is OK, but there always needs to // be space for an output frame.) assert ((m_pInputCb == NULL && m_pInputCr == NULL) || (m_pInputCb != NULL && m_pInputCr != NULL)); assert (m_pOutputCb != NULL && m_pOutputCr != NULL); // Denoise the current frame. return ((denoiser.interlaced != 0) ? newdenoise_interlaced_frame_color : newdenoise_frame_color) (m_pInputCb, m_pInputCr, m_pOutputCb, m_pOutputCr); } // The ReadWriteThread class. // Default constructor. ReadWriteThread::ReadWriteThread() { // No input stream yet. m_nFD = -1; m_pStreamInfo = NULL; m_pFrameInfo = NULL; // No space for frames yet. m_apFrames = NULL; m_pValidFramesHead = m_pValidFramesTail = m_pCurrentFrame = m_pFreeFramesHead = NULL; } // Destructor. ReadWriteThread::~ReadWriteThread() { // Free up all the frames. if (m_apFrames != NULL) { for (int i = 0; i < m_kNumFrames; ++i) { delete[] m_apFrames[i].planes[0]; delete[] m_apFrames[i].planes[1]; delete[] m_apFrames[i].planes[2]; } delete[] m_apFrames; } } // Initialize. Set up all private thread data and start the // worker thread. void ReadWriteThread::Initialize (int a_nFD, const y4m_stream_info_t *a_pStreamInfo, y4m_frame_info_t *a_pFrameInfo, int a_nWidthY, int a_nHeightY, int a_nWidthCbCr, int a_nHeightCbCr) { int i, nSizeY, nSizeCbCr; // Make sure we got stream/frame info. assert (a_pStreamInfo != NULL); assert (a_pFrameInfo != NULL); // Fill in the blanks. m_nFD = a_nFD; m_pStreamInfo = a_pStreamInfo; m_pFrameInfo = a_pFrameInfo; // Allocate space for frames. m_apFrames = new Frame[m_kNumFrames]; nSizeY = a_nWidthY * a_nHeightY; assert (nSizeY > 0); nSizeCbCr = a_nWidthCbCr * a_nHeightCbCr; for (i = 0; i < m_kNumFrames; ++i) { // Allocate space for each frame. Don't allocate space for // color unless we're denoising color. m_apFrames[i].planes[0] = new uint8_t[nSizeY]; if (nSizeCbCr > 0) { m_apFrames[i].planes[1] = new uint8_t[nSizeCbCr]; m_apFrames[i].planes[2] = new uint8_t[nSizeCbCr]; } else { // Space must be allocated anyway, since the incoming // frames have color information that needs to be read // in (even though it's not used). m_apFrames[i].planes[1] = new uint8_t[denoiser.frame.Cw * denoiser.frame.Ch]; m_apFrames[i].planes[2] = new uint8_t[denoiser.frame.Cw * denoiser.frame.Ch]; } // Put each new frame into the free list. m_apFrames[i].next = m_pFreeFramesHead; m_pFreeFramesHead = &(m_apFrames[i]); } // Let the base class initialize. The thread will start. BaseClass::Initialize(); } // Remove the first valid frame from the list and return it. ReadWriteThread::Frame * ReadWriteThread::GetFirstValidFrame (void) { Frame *pFrame; // The frame we get. // Make sure we have exclusive access. assert (IsLocked()); // Make sure there's a valid frame. assert (m_pValidFramesHead != NULL); // Make the first valid frame the current frame. pFrame = m_pValidFramesHead; // Remove that frame from the valid-frame list. m_pValidFramesHead = m_pValidFramesHead->next; if (m_pValidFramesHead == NULL) m_pValidFramesTail = NULL; // Return the next valid frame. return pFrame; } // Add the given frame to the end of the valid-frame list. void ReadWriteThread::AddFrameToValidList (Frame *a_pFrame) { // Make sure we have exclusive access. assert (IsLocked()); // Make sure they gave us a frame to add. assert (a_pFrame != NULL); // This will be at the end of the list. a_pFrame->next = NULL; // If the valid-frame list is empty, set it up. if (m_pValidFramesHead == NULL) { m_pValidFramesHead = m_pValidFramesTail = a_pFrame; } // Otherwise, append this frame to the end of the list. else { assert (m_pValidFramesTail->next == NULL); m_pValidFramesTail->next = a_pFrame; m_pValidFramesTail = m_pValidFramesTail->next; } } // Remove a frame from the free-frames list and return it. ReadWriteThread::Frame * ReadWriteThread::GetFreeFrame (void) { Frame *pFrame; // The frame we get. // Make sure we have exclusive access. assert (IsLocked()); // Make sure there's a free frame. assert (m_pFreeFramesHead != NULL); // Make the first free frame the current frame. pFrame = m_pFreeFramesHead; // Remove that frame from the free-frames list. m_pFreeFramesHead = m_pFreeFramesHead->next; // Return the free frame. return pFrame; } // Add the given frame to the free-frames list. void ReadWriteThread::AddFrameToFreeList (Frame *a_pFrame) { // Make sure we have exclusive access. assert (IsLocked()); // Make sure they gave us a frame. assert (a_pFrame != NULL); // Add this frame to the list. a_pFrame->next = m_pFreeFramesHead; m_pFreeFramesHead = a_pFrame; } // Remove the first valid frame, and make it the current frame. void ReadWriteThread::MoveValidFrameToCurrent (void) { // Make sure we have exclusive access. assert (IsLocked()); // Make sure there's a valid frame. assert (m_pValidFramesHead != NULL); // Make sure there's no current frame. assert (m_pCurrentFrame == NULL); // Make the first valid frame the current frame. m_pCurrentFrame = GetFirstValidFrame(); } // Move the current frame to the end of the valid-frame list. void ReadWriteThread::MoveCurrentFrameToValidList (void) { // Make sure we have exclusive access. assert (IsLocked()); // Make sure there's a current frame. assert (m_pCurrentFrame != NULL); // Add the frame to the end of the valid-frame list. AddFrameToValidList (m_pCurrentFrame); // Now there's no current frame. m_pCurrentFrame = NULL; } // Remove a frame from the free list, and make it the current frame. void ReadWriteThread::MoveFreeFrameToCurrent (void) { // Make sure we have exclusive access. assert (IsLocked()); // Make sure there's a free frame. assert (m_pFreeFramesHead != NULL); // Make sure there's no current frame. assert (m_pCurrentFrame == NULL); // Make the first free frame the current frame. m_pCurrentFrame = GetFreeFrame(); } // Move the current frame to the free-frame list. void ReadWriteThread::MoveCurrentFrameToFreeList (void) { // Make sure we have exclusive access. assert (IsLocked()); // Make sure there's a current frame. assert (m_pCurrentFrame != NULL); // Add this frame to the list. AddFrameToFreeList (m_pCurrentFrame); // Now there's no current frame. m_pCurrentFrame = NULL; } // The DenoiserThreadRead class. // Default constructor. DenoiserThreadRead::DenoiserThreadRead() { // Nothing additional to do. } // Destructor. DenoiserThreadRead::~DenoiserThreadRead() { // Nothing additional to do. } // Read a frame from input. a_apPlanes[] gets backpatched // with pointers to valid frame data, and they are valid until // the next call to ReadFrame(). // Returns Y4M_OK if it succeeds, Y4M_ERR_EOF at the end of // the stream. (Returns other errors too.) int DenoiserThreadRead::ReadFrame (uint8_t **a_apPlanes) { // Get exclusive access. Lock(); // Any previous current frame can be reused now. if (m_pCurrentFrame != NULL) { // Now recycle the previous current frame. MoveCurrentFrameToFreeList(); // If there were no free frames before, then signal that input // can continue. if (m_bWaitingForInput) SignalInput(); } // If there are no valid frames, and the thread is still reading // frames, then wait for some valid output. if (m_pValidFramesHead == NULL && m_bWorkLoop) WaitForOutput(); // Make the next valid frame the current frame. If there are no // valid frames at this point, then we're at the end of the stream. if (m_pValidFramesHead != NULL) MoveValidFrameToCurrent(); // Remember the current frame. (It could conceivably get changed // once we release exclusive access. The code, as presently written, // doesn't do that, but I like to plan for random future extensions.) Frame *pCurrentFrame = m_pCurrentFrame; // Release exclusive access. Unlock(); // Backpatch the frame info. if (pCurrentFrame != NULL) { a_apPlanes[0] = pCurrentFrame->planes[0]; a_apPlanes[1] = pCurrentFrame->planes[1]; a_apPlanes[2] = pCurrentFrame->planes[2]; return Y4M_OK; } // Make sure we got an error at the end of stream (hopefully // Y4M_ERR_EOF). assert (m_nWorkRetval != Y4M_OK); // Return whatever error we got at the end of the stream. return m_nWorkRetval; } // Read frames from the raw-video stream. int DenoiserThreadRead::Work (void) { int nErr; // An error that may occur. Frame *pFrame; // Space for reading a frame into memory. // No errors yet. nErr = Y4M_OK; // No frame yet. pFrame = NULL; // Get exclusive access. Lock(); // Are there no free buffers? if (m_pFreeFramesHead == NULL) { // If we've been asked to quit, do so. if (!m_bWorkLoop) nErr = Y4M_ERR_EOF; // Otherwise, wait for space to read in frames. else WaitForInput(); } // If there is still no space to read in frames, we're done. if (nErr == Y4M_OK && m_pFreeFramesHead == NULL) nErr = Y4M_ERR_EOF; // Otherwise, get a free buffer. if (nErr == Y4M_OK) pFrame = GetFreeFrame(); // Release exclusive access. Unlock(); // If there's space to read in another frame, do so. if (nErr == Y4M_OK && pFrame != NULL) { // Read the next frame into the buffer. nErr = y4m_read_frame (m_nFD, m_pStreamInfo, m_pFrameInfo, pFrame->planes); // Get exclusive access. Lock(); // Did we successfully read a frame? if (nErr == Y4M_OK) { // Yes. Put the frame into the valid-frames list. AddFrameToValidList (pFrame); // If there are no other valid frames, then signal // that there's some output now. if (m_bWaitingForOutput) SignalOutput(); } else { // No. Put the frame back into the free-frames list. AddFrameToFreeList (pFrame); } // Release exclusive access. Unlock(); } // Return whether we successfully read a frame. return nErr; } // The DenoiserThreadWrite class. // Default constructor. DenoiserThreadWrite::DenoiserThreadWrite() { // Nothing additional to do. } // Destructor. DenoiserThreadWrite::~DenoiserThreadWrite() { // Nothing additional to do. } // Get space for a frame to write to output. a_apPlanes[] gets // backpatched with pointers to valid frame data. // Returns Y4M_OK if it succeeds, something else if it fails. int DenoiserThreadWrite::GetSpaceToWriteFrame (uint8_t **a_apPlanes) { // Get exclusive access. Lock(); // Make sure there's no current frame. assert (m_pCurrentFrame == NULL); // If there are no free frames, and the thread is still writing // frames, then wait for it to free up a frame. if (m_pFreeFramesHead == NULL && m_bWorkLoop) WaitForInput(); // Make a free frame the current frame. if (m_pFreeFramesHead != NULL) MoveFreeFrameToCurrent(); // Remember the current frame. (It could conceivably get changed // once we release exclusive access. The code, as presently written, // doesn't do that, but I like to plan for random future extensions.) Frame *pCurrentFrame = m_pCurrentFrame; // Release exclusive access. Unlock(); // Backpatch the frame info, for all the info we're denoising. if (pCurrentFrame != NULL) { a_apPlanes[0] = pCurrentFrame->planes[0]; a_apPlanes[1] = pCurrentFrame->planes[1]; a_apPlanes[2] = pCurrentFrame->planes[2]; return Y4M_OK; } // Make sure we got an error at the end of stream (hopefully // Y4M_ERR_EOF). assert (m_nWorkRetval != Y4M_OK); // Return whatever error we got at the end of the stream. return m_nWorkRetval; } // Write a frame to output. The a_apPlanes[] previously set up by // GetSpaceToWriteFrame() must be filled with video data by the client. void DenoiserThreadWrite::WriteFrame (void) { // Get exclusive access. Lock(); // Make sure there's a current frame. assert (m_pCurrentFrame != NULL); // Move it to the end of the valid-frames list. MoveCurrentFrameToValidList(); // If that's the only valid frame, then signal that we're ready // for output again. if (m_bWaitingForOutput) SignalOutput(); // Release exclusive access. Unlock(); } // The thread function. Loop, calling Work(), until told to stop. // Differs from BasicThread's implementation because it waits until // all frames are written before it stops. void DenoiserThreadWrite::WorkLoop (void) { // Loop and do work until told to quit. for (;;) { // Determine if we should continue looping. // This requires exclusive access because of the test // for remaining frames to write. bool bContinue; Lock(); bContinue = (m_bWorkLoop || m_pValidFramesHead != NULL); Unlock(); if (!bContinue) break; // Do work. m_nWorkRetval = Work(); // If it returned non-OK, stop. if (m_nWorkRetval != Y4M_OK) break; } } // Write frames to the raw-video stream. int DenoiserThreadWrite::Work (void) { int nErr; // An error that may occur. Frame *pFrame; // A frame that gets written out. // No errors yet. nErr = Y4M_OK; // No frame yet. pFrame = NULL; // Get exclusive access. Lock(); // Are there no frames to write out? if (m_pValidFramesHead == NULL) { // If we've been asked to quit, do so. if (!m_bWorkLoop) nErr = Y4M_ERR_EOF; // Otherwise, wait for some frames to write out. else WaitForOutput(); } // If there are still no frames to write out, we're done. if (nErr == Y4M_OK && m_pValidFramesHead == NULL) nErr = Y4M_ERR_EOF; // Otherwise, fetch a frame to write to output. if (nErr == Y4M_OK) pFrame = GetFirstValidFrame(); // Release exclusive access. Unlock(); // If there's a frame to write to output, do so. if (nErr == Y4M_OK && pFrame != NULL) { // Write the frame to output. nErr = y4m_write_frame (m_nFD, m_pStreamInfo, m_pFrameInfo, pFrame->planes); // Whether or not that succeeds, put the frame into the // free-frames list. Lock(); AddFrameToFreeList (pFrame); if (m_bWaitingForInput) SignalInput(); Unlock(); } // Let our caller know what happened. return nErr; } mjpegtools-2.1.0/y4mdenoise/Status_t.h0000644000175000017500000000066611173460062020260 0ustar glowwormglowworm#ifndef __STATUS_T_H__ #define __STATUS_T_H__ // This file (C) 2004-2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. // The result of an operation. enum Status_t { g_kNoError, // No error (i.e. success) g_kInternalError, // Unspecified internal error. g_kOutOfMemory, // Free store exhausted. }; #endif // __STATUS_T_H__ mjpegtools-2.1.0/y4mdenoise/SearchWindow.hh0000644000175000017500000020655411206112210021205 0ustar glowwormglowworm#ifndef __SEARCH_WINDOW_H__ #define __SEARCH_WINDOW_H__ // This file (C) 2004-2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. #include "config.h" #include #include #include "mjpeg_types.h" #include "TemplateLib.hh" #include "Limits.hh" #include "Allocator.hh" #include "ReferenceFrame.hh" // Define this to sort pixel-groups only when asked. //#define OPTIONALLY_SORT_PIXEL_GROUPS // Define this to calculate and return the sum-of-absolute-differences // associated with each found match. //#define CALCULATE_SAD // The generic search-window class. It's parameterized by the size of // elements in the pixels, the dimension of the pixels, the numeric // type to use in tolerance calculations, the numeric type to use for // pixel indices, a numeric type big enough to hold the product of the // largest expected frame width/height, the width/height of pixel groups // to operate on, a numeric type big enough to hold // pixel-dimension * pixel-group-width * pixel-group-height bits and // serve as an array index, and the types of pixels, reference pixels, // and reference frames to operate on. // When constructed, it's configured with the width/height of frames, // the search radius (in the X and Y directions), and the error // tolerance. // // The search-window works on groups of pixels. It allows the client // to iterate through a frame and look for pixel-groups within the // search radius that match a given pixel-group (within the error // tolerance). template , class REFERENCEPIXEL = ReferencePixel, class REFERENCEFRAME = ReferenceFrame > class SearchWindow { public: typedef PIXEL Pixel_t; // Our pixel type. typedef REFERENCEPIXEL ReferencePixel_t; // Our reference pixel type. typedef REFERENCEFRAME ReferenceFrame_t; // Our reference frame type. typedef PIXEL_NUM PixelValue_t; // The numeric type to use in pixel values, in each dimension // of our pixels. typedef PIXEL_TOL Tolerance_t; // The numeric type to use in tolerance calculations. SearchWindow(); // Default constructor. virtual ~SearchWindow(); // Destructor. void Init (Status_t &a_reStatus, PIXELINDEX a_tnWidth, PIXELINDEX a_tnHeight, PIXELINDEX a_tnSearchRadiusX, PIXELINDEX a_tnSearchRadiusY, PixelValue_t a_nTolerance); // Initializer. Provide the dimensions of the frames, the // search radius, and the error tolerance. void PurgePixelSorter (void); // Purge the pixel sorter. // Should be called every once in a while (e.g. every 10 // frames). Otherwise, it may use way too much memory and // starts hitting virtual memory & otherwise performs badly. // A pixel group. class PixelGroup { public: Pixel_t m_atPixels[PGH][PGW]; // The pixels we represent. PIXELINDEX m_tnX, m_tnY; // The index of the upper-left pixel in this pixel-group. PixelGroup(); // Constructor. ~PixelGroup(); // Destructor. bool IsWithinTolerance (const PixelGroup &a_rOther, Tolerance_t a_tnTolerance #ifdef CALCULATE_SAD , Tolerance_t &a_rtnSAD #endif // CALCULATE_SAD ) const; // Returns true if the two pixels groups are equal, within // the given tolerance, and backpatches the sum-of-absolute- // differences in a_rtnSAD. a_tnTolerance must have been // generated by Pixel_t::MakeTolerance(). }; void StartFrame (ReferenceFrame_t *a_pReferenceFrame); // Begin searching through a frame. // Provide the frame to search through. void PrepareForSearch (Status_t &a_reStatus, bool a_bSortPixels); // Prepare for searching, i.e. find all search-window cells // within the search radius of the current pixel-group that // aren't initialized, and do so. // If a_bSortPixels is true, then additionally find all // search-window cells within the search radius of the current // pixel-group that aren't in the pixel-sorter already, and put // them there. // This must be called before StartSearch()/FoundNextMatch() if // any of the Move*() methods have been called. #ifdef OPTIONALLY_SORT_PIXEL_GROUPS const SearchWindowCell &GetCell (PIXELINDEX a_tnY, PIXELINDEX a_tnX) const; // Return the cell at this index. #endif // OPTIONALLY_SORT_PIXEL_GROUPS template void Prune (const REGION &a_rAppliedRegion, PIXELINDEX a_tnOffsetX, PIXELINDEX a_tnOffsetY); // Prune the search-window, i.e. find all pixel-groups that now // contain used reference-pixels, and remove them from the // window and from the pixel-sorter. void MoveRight (void); // Move the window one pixel to the right, removing all pixel // groups on the left edge of the window. void MoveLeft (void); // Move the window one pixel to the left, removing all pixel // groups on the right edge of the window. void MoveDown (void); // Move the window down one line, removing all pixel groups on // the top edge of the window. void FinishFrame (void); // Remove all search-window pixel groups from the pixel sorter, // leaving it empty & ready for another frame. // A class to keep track of our progress during a search inside the // pixel sorter. class PixelSorterIterator; void StartSearch (PixelSorterIterator &a_rIterator, const PixelGroup &a_rSearch); // Begin a search through the pixel sorter for the given pixel // group. const PixelGroup *FoundNextMatch (PixelSorterIterator &a_rIterator #ifdef CALCULATE_SAD , Tolerance_t &a_rtnSAD #endif // CALCULATE_SAD ) const; // If there is another pixel group that matches the one being // searched for, returns the matched pixel group, and // backpatches the sum-of-absolute-differences. // If the search is over, returns NULL. #ifndef NDEBUG static uint32_t GetPixelSorterNodeCount (void); #endif // NDEBUG // Return the number of allocated pixel-sorters. private: PIXELINDEX m_tnWidth; PIXELINDEX m_tnHeight; // The dimensions of each reference frame. PIXELINDEX m_tnSearchRadiusX, m_tnSearchRadiusY; // The search radius, i.e. how far from the current pixel // group we look when searching for possible moved instances of // the group. Tolerance_t m_tnTolerance, m_tnTwiceTolerance; // The error tolerance, i.e. the largest difference we're // willing to tolerate between pixels before considering them // to be different. Also, twice the tolerance. ReferenceFrame_t *m_pReferenceFrame; // The reference frame, against which the new frame is // compared. PIXELINDEX m_tnX, m_tnY; // The index of the current pixel group. Actually the index // of the top-left pixel in the current pixel group. This // gets moved in a zigzag pattern, back and forth across the // frame and then down, until the end of the frame is reached. // A pixel group within the search radius of the current // pixel group. Lists of these are attached to pixel-sorter // nodes (defined below). class PixelSorterBranchNode; class SearchWindowCell : public PixelGroup, public DoublyLinkedList { public: PixelSorterBranchNode *m_pSorter; // The branch of the pixel-sorter where this cell was // placed, the last time it was in the pixel-sorter. enum { m_knNotDone = 0, m_knDoneEnough = 1, m_knDone = 2 }; int8_t m_eDoneSorting; // m_knDone if m_pSorter is the lowest node in the tree // where this cell could be placed, m_knNotDone if it's // possible for this cell to descend further into the tree, // m_knDoneEnough if it's possible but not happening. SearchWindowCell(); // Default constructor. ~SearchWindowCell(); // Destructor. }; SearchWindowCell **m_ppSearchWindow; SearchWindowCell *m_pSearchWindowStorage; // The search window. It contains all the cells needed to // analyze the image. // m_ppSearchWindow consists of pointers to various areas within // m_pSearchWindowStorage; this is done solely to keep the code // for accessing cells simpler & easier to understand (i.e. the // code might be slightly more optimal otherwise). PIXELINDEX m_tnSearchWindowPixelLeft, m_tnSearchWindowPixelRight, m_tnSearchWindowPixelTop, m_tnSearchWindowPixelBottom; // The extent of the search window that contains valid values // in the pixel-groups. Generally (m_tnX - m_tnSearchRadiusX) // to (m_tnX + m_tnSearchRadiusX), and (m_tnY - m_tnSearchRadiusY) // to (m_tnY + m_tnSearchRadiusY), but it gets clipped by the // frame boundaries, and, if a run of current pixel-groups // contain resolved pixels, will lag until the current // pixel-group contains all unresolved pixels. PIXELINDEX m_tnSearchWindowSortLeft, m_tnSearchWindowSortRight, m_tnSearchWindowSortTop, m_tnSearchWindowSortBottom; // The extent of the search window that's been put into the // pixel sorter. Generally (m_tnX - m_tnSearchRadiusX) to // (m_tnX + m_tnSearchRadiusX), and (m_tnY - m_tnSearchRadiusY) // to (m_tnY + m_tnSearchRadiusY), but it gets clipped by the // frame boundaries, and, if a run of current pixel-groups // contain resolved pixels, will lag until the current // pixel-group contains all unresolved pixels. // A branch node in the pixel-sorter tree. One node partitions // search-window cells (i.e. pixel groups within the search radius) // into several subtrees, and contains a list of cells that can't be // pushed further down the tree. Used to locate matches for the // current pixel group in quasi-logarithmic time. class PixelSorterBranchNode { private: void *operator new (size_t); void operator delete (void *) {} void *operator new[] (size_t); void operator delete[] (void *); // Disallow allocation from system memory. public: SearchWindowCell m_oSplitValue; // A cell that contains the split values for each dimension // of each pixel of the groups being partitioned. The // contained forward/backward pointers are used to form a // list of all reference-frame pixel groups (within the // search radius) connected to this node. PixelGroup m_oRangeMin, m_oRangeMax; // The minimum/maximum values for pixels at this level of // the pixel-sorter tree. // Used to re-evaluate cells that enum { m_knBranches = 1 << (PGH * PGW * DIM) }; // The number of branches from each node. There's two for // each possible combination of pixel & dimension. PixelSorterBranchNode *m_apBranches[m_knBranches]; // This node's child branches. // // The bit-mask for the branch that represents a particular // pixel-group/pixel-dimension (x,y,dim) is calculated by // the formula "1 << (y * (PGW * DIM) + x * DIM + dim)". // // If the searched-for pixel is greater than its counterpart // in the pixel-sorter node, its corresponding bit-mask is // added to a running total. When done, that total is the // index of the branch to descend down. If the searched-for // pixel is equal to its counterpart (within the tolerance), // the search stops at this level. It only takes one dimension // of one pixel to be like this to stop the descent. // // This way, a search for matches only has to follow one // series of branches all the way to the bottom of the tree // (i.e. there's no need for a queue of branches to try), // and there's no need for an incoming pixel group to end up // in more than one branch, no matter what the tolerance. PixelSorterBranchNode(); // Default constructor. ~PixelSorterBranchNode(); // Destructor. static SORTERBITMASK GetBitMask (PIXELINDEX a_tnY, PIXELINDEX a_tnX, int a_nDimension); // Calculate the bitmask to represent the given pixel // dimension at the given coordinates within the pixel // group. bool ShouldCellStayHere (const SearchWindowCell &a_rCell, Tolerance_t a_tnTolerance, SORTERBITMASK &a_rtnChildIndex, PixelGroup &a_rMin, PixelGroup &a_rMax) const; // If the given cell should stay at this level of the tree // (i.e. because one of its pixel values is within the // tolerance value of its corresponding split point), then // return true. Otherwise, calculate the index of the // child branch that should take this cell, and modify // a_rMin and a_rMax (which start as the min/max pixel // values for the current branch node) to be the min/max // for the child branch node. (If this function returns // true, a_rMin and a_rMax are undefined.) bool DoesPixelGroupStopHere (const PixelGroup *a_pPixelGroup, Tolerance_t a_tnTwiceTolerance, SORTERBITMASK &a_rtnChildIndex, bool &a_rbMatchAtThisLevel) const; // If the given pixel group straddles this level of the tree // (i.e. because one of its pixel values is within the // tolerance value of its corresponding split point), then // return true. // Otherwise, calculate the index of the child branch that // should take this cell, and return false. // In either case, determine whether any search-window cells // that had to stop at this level of the tree could possibly // intersect the given pixel-group. void SplitValues (const PixelGroup &a_rMin, const PixelGroup &a_rMax); // Set our split values to the midpoint between the given // minimum & maximum. // Count the number of pixel-sorter objects in existence. #ifndef NDEBUG private: static uint32_t sm_ulInstances; public: static uint32_t GetInstances (void) { return sm_ulInstances; } #endif // NDEBUG }; typedef Allocator<1> PSBN_Allocator_t; PSBN_Allocator_t m_oPSBNAllocator; PixelSorterBranchNode m_oPixelSorter; // The pixel sorter, i.e. the root of a tree of pixel-sorter // branch nodes that partitions all unresolved pixel-groups // within the search radius. SearchWindowCell m_oPixelSorterMin, m_oPixelSorterMax; // The minimum/maximum values for pixels. Used to help // PixelSorter_Add() generate pixel values for new branch nodes. PixelGroup m_oRangeMin, m_oRangeMax; // The minimum/maximum values for pixels at the current level // of the pixel-sorter tree. Used to generate values for new // branch nodes. // (These were local variables in PixelSorter_Add(), but the // construction & destruction cost actually showed up in the // profile! So they were moved here.) PixelSorterBranchNode *PixelSorter_Add (Status_t &a_reStatus, SearchWindowCell *a_pCell, PixelSorterBranchNode *a_pLastSorter, int8_t &a_reDoneSorting); // Add this search-window cell to the pixel-sorter, creating // new branch nodes as needed. If this cell has been in the // pixel-sorter before, a_pLastSorter is where it was; this // avoids duplicated work. // Returns the pixel-sorter node where this cell is now // attached, and a_reDoneSorting is backpatched with whether the // cell could have descended further down the tree, but didn't. void PixelSorter_Remove (SearchWindowCell *a_pCell); // Remove this search-window cell from the pixel-sorter. // Does not remove branch nodes; it's assumed that created // branch nodes will most likely become useful again at some // later time. void DeletePixelSorterBranchNode (PixelSorterBranchNode *a_pNode); // Delete a pixel-sorter-branch-node. public: // A class to keep track of our progress during a search inside the // pixel sorter. (This has to be public, in order to allow clients // to create one, but the definition is hidden down here because the // details of it aren't public.) class PixelSorterIterator { public: const PixelGroup *m_pSearch; // The pixel group being searched for. const PixelSorterBranchNode *m_pBranch; // The branch being examined. // Initialized to &m_oPixelSorter. // If NULL, means the search is over. const SearchWindowCell *m_pCell; // The last cell examined. // If equal to m_pBranch->m_oSplitValue, means that the // branch hasn't been examined yet. SORTERBITMASK m_tnChildIndex; // The index of the branch node child that the search // descends down next. bool m_bPixelGroupStopsHere; // true if we don't have to descend further down the tree. bool m_bMatchesAtThisLevel; // true if it's possible for the current pixel-group to // match pixel-groups that had to stop at this level in the // tree. }; }; // Default constructor. template SearchWindow::SearchWindow() : m_oPSBNAllocator (262144) { // No frames yet. m_tnWidth = m_tnHeight = PIXELINDEX (0); // No information on the sort of search to do yet. m_tnSearchRadiusX = m_tnSearchRadiusY = PIXELINDEX (0); m_tnTolerance = m_tnTwiceTolerance = PIXEL_TOL (0); // No active search yet. m_tnX = m_tnY = PIXELINDEX (0); m_pReferenceFrame = NULL; // No search window yet. m_ppSearchWindow = NULL; m_pSearchWindowStorage = NULL; m_tnSearchWindowPixelLeft = m_tnSearchWindowPixelRight = m_tnSearchWindowPixelTop = m_tnSearchWindowPixelBottom = m_tnSearchWindowSortLeft = m_tnSearchWindowSortRight = m_tnSearchWindowSortTop = m_tnSearchWindowSortBottom = PIXELINDEX (0); } // Destructor. template SearchWindow::~SearchWindow() { // Destroy the search window. delete[] m_ppSearchWindow; delete[] m_pSearchWindowStorage; // Purge the pixel-sorter. (The PixelSorterBranchNode destructor // doesn't have access to the allocator, so the pixel-sorter tree must // be explicitly destroyed here.) PurgePixelSorter(); } // Initializer. template void SearchWindow::Init (Status_t &a_reStatus, PIXELINDEX a_tnWidth, PIXELINDEX a_tnHeight, PIXELINDEX a_tnSearchRadiusX, PIXELINDEX a_tnSearchRadiusY, PixelValue_t a_tnTolerance) { int i; // Used to loop through things. FRAMESIZE tnPixels; // The number of pixels in each frame. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure the sorter bit-mask type is big enough to hold // pixel-sorter branch-node child indices. (Note that this is // technically a compile-time assertion.) assert (sizeof (SORTERBITMASK) * g_knBitsPerByte > PGH * PGW * DIM); // Make sure the width & height are reasonable. assert (a_tnWidth > PIXELINDEX (0)); assert (a_tnHeight > PIXELINDEX (0)); // Make sure the search radius is reasonable. assert (a_tnSearchRadiusX > PIXELINDEX (0) && a_tnSearchRadiusY > PIXELINDEX (0) && a_tnSearchRadiusX <= a_tnWidth && a_tnSearchRadiusY <= a_tnHeight); // Make sure the tolerance is reasonable. (A zero tolerance can // be used for lossless motion detection.) assert (a_tnTolerance >= 0); // Calculate the number of pixels in each frame. tnPixels = FRAMESIZE (a_tnWidth) * FRAMESIZE (a_tnHeight); // Allocate enough cells for our search window. m_pSearchWindowStorage = new SearchWindowCell [FRAMESIZE (a_tnHeight - PGH + 1) * FRAMESIZE (a_tnWidth - PGW + 1)]; if (m_pSearchWindowStorage == NULL) { a_reStatus = g_kOutOfMemory; return; } // Allocate enough space for our line-based index into the // search window storage. m_ppSearchWindow = new SearchWindowCell * [a_tnHeight - PGH + 1]; if (m_ppSearchWindow == NULL) { a_reStatus = g_kOutOfMemory; return; } // Generate pointers to the beginning of each line in the search // window. SearchWindowCell *pNextLine = m_pSearchWindowStorage; for (i = 0; i < (a_tnHeight - PGH + 1); ++i) { m_ppSearchWindow[i] = pNextLine; pNextLine += (a_tnWidth - PGW + 1); } // Initialize the root of the pixel-sorter tree to split the // available range in half. Also generate search-window cells // that represent the minimum/maximum values for pixels. { PIXELINDEX x, y; // Used to loop through pixels. PixelValue_t atnMin[DIM], atnHalf[DIM], atnMax[DIM]; // What we initialize each pixel to. // Generate a pixel value that represents half the available // range in each dimension, plus the minimums & maximums. for (i = 0; i < DIM; i++) { atnMin[i] = Limits::Min; atnHalf[i] = (Limits::Min + Limits::Max) / PixelValue_t (2); atnMax[i] = Limits::Max; } // Loop through all pixels in the root of the pixel-sorter tree, // initialize them to half the maximum value. Set up our // search-window minimum/maximum too. for (y = 0; y < PGH; ++y) { for (x = 0; x < PGW; ++x) { m_oPixelSorterMin.m_atPixels[y][x] = Pixel_t (atnMin); m_oPixelSorter.m_oSplitValue.m_atPixels[y][x] = Pixel_t (atnHalf); m_oPixelSorterMax.m_atPixels[y][x] = Pixel_t (atnMax); } } } // Finally, store our parameters. m_tnWidth = a_tnWidth; m_tnHeight = a_tnHeight; m_tnSearchRadiusX = a_tnSearchRadiusX; m_tnSearchRadiusY = a_tnSearchRadiusY; m_tnTolerance = Pixel_t::MakeTolerance (a_tnTolerance); m_tnTwiceTolerance = Pixel_t::MakeTolerance (Tolerance_t (2) * a_tnTolerance); } // Purge the pixel sorter. template void SearchWindow::PurgePixelSorter (void) { // Clear out the pixel-sorter. for (SORTERBITMASK i = 0; i < m_oPixelSorter.m_knBranches; ++i) { if (m_oPixelSorter.m_apBranches[i] != NULL) { DeletePixelSorterBranchNode (m_oPixelSorter.m_apBranches[i]); m_oPixelSorter.m_apBranches[i] = NULL; } } // Make sure there are no more allocated pixel-sorter-branch-nodes. assert (m_oPSBNAllocator.GetNumAllocated() == 0); } // Delete a pixel-sorter-branch-node. template void SearchWindow ::DeletePixelSorterBranchNode (PixelSorterBranchNode *a_pNode) { // Delete all the branches recursively. for (SORTERBITMASK i = 0; i < a_pNode->m_knBranches; ++i) { if (a_pNode->m_apBranches[i] != NULL) { DeletePixelSorterBranchNode (a_pNode->m_apBranches[i]); a_pNode->m_apBranches[i] = NULL; } } // Delete the given node. a_pNode->~PixelSorterBranchNode(); m_oPSBNAllocator.Deallocate (0, sizeof (PixelSorterBranchNode), a_pNode); } // Default constructor. template SearchWindow ::PixelGroup::PixelGroup() { // No location yet. m_tnX = m_tnY = PIXELINDEX (0); } // Destructor. template SearchWindow ::PixelGroup::~PixelGroup() { // Nothing to do. } // Returns true if the two pixels groups are equal, within // the given tolerance. template bool SearchWindow ::PixelGroup::IsWithinTolerance (const PixelGroup &a_rOther, Tolerance_t a_tnTolerance #ifdef CALCULATE_SAD , Tolerance_t &a_rtnSAD #endif // CALCULATE_SAD ) const { PIXELINDEX tnX, tnY; // Used to loop through pixels. // Compare the two pixel groups, pixel by pixel. #ifdef CALCULATE_SAD a_rtnSAD = 0; #endif // CALCULATE_SAD for (tnY = 0; tnY < PGH; ++tnY) { for (tnX = 0; tnX < PGW; ++tnX) { #ifdef CALCULATE_SAD Tolerance_t tnSAD; #endif // CALCULATE_SAD // The sum-of-absolute-differences between these two // pixels. // Get the two pixels of interest. const Pixel_t &rThisPixel = m_atPixels[tnY][tnX]; const Pixel_t &rOtherPixel = a_rOther.m_atPixels[tnY][tnX]; // If this pixel value is not within the tolerance of // the corresponding pixel in the other group, exit now. if (!rThisPixel.IsWithinTolerance (rOtherPixel, a_tnTolerance #ifdef CALCULATE_SAD , tnSAD #endif // CALCULATE_SAD )) { return false; } // Sum up the sum-of-absolute-differences. #ifdef CALCULATE_SAD a_rtnSAD += tnSAD; #endif // CALCULATE_SAD } } // The pixel groups are equal, within the given tolerance. return true; } // Default constructor. template SearchWindow ::SearchWindowCell::SearchWindowCell() { // We haven't been put into the pixel-sorter yet. m_pSorter = NULL; m_eDoneSorting = m_knNotDone; } // Destructor. template SearchWindow ::SearchWindowCell::~SearchWindowCell() { // Nothing to do. } // Begin searching through a frame. // Provide the frame to search through. template void SearchWindow::StartFrame (ReferenceFrame_t *a_pReferenceFrame) { // Make sure they gave us a frame. assert (a_pReferenceFrame != NULL); // Make sure we didn't already have a frame. assert (m_pReferenceFrame == NULL); // Remember the frame we're operating on this pass. m_pReferenceFrame = a_pReferenceFrame; // We'll be checking the upper-left corner first. m_tnX = m_tnY = PIXELINDEX (0); } // Prepare for searching, i.e. find all search-window cells within the // search radius of the current pixel-group that aren't in the // pixel-sorter already, and put them there. template void SearchWindow::PrepareForSearch (Status_t &a_reStatus, bool a_bSortPixels) { PIXELINDEX tnSearchWindowPixelLeft, tnSearchWindowPixelRight, tnSearchWindowPixelTop, tnSearchWindowPixelBottom; // What the search window should look like when we're done. PIXELINDEX tnX, tnY; // Used to loop through pixel groups. PIXELINDEX tnSearchLeft, tnSearchRight, tnSearchTop, tnSearchBottom; // The part of the search window that we actually loop through. SearchWindowCell *pCell; // The search-window cell corresponding to the pixel group being // manipulated. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // (If we're not doing the expanding-regions variant, make sure // they always want to add search-window cells to the pixel-sorter.) #ifndef OPTIONALLY_SORT_PIXEL_GROUPS assert (a_bSortPixels); #endif // OPTIONALLY_SORT_PIXEL_GROUPS // Make sure we have a new frame & reference frame to work with. assert (m_pReferenceFrame != NULL); // The search window starts in a radius around the index of the // current pixel group. tnSearchWindowPixelLeft = m_tnX - m_tnSearchRadiusX; tnSearchWindowPixelRight = m_tnX + m_tnSearchRadiusX + PIXELINDEX (1); tnSearchWindowPixelTop = m_tnY - m_tnSearchRadiusY; tnSearchWindowPixelBottom = m_tnY + m_tnSearchRadiusY + PIXELINDEX (1); // Then it gets clipped by the frame boundaries. tnSearchWindowPixelLeft = Max (tnSearchWindowPixelLeft, PIXELINDEX (0)); tnSearchWindowPixelRight = Min (tnSearchWindowPixelRight, PIXELINDEX (m_tnWidth - PGW + 1)); tnSearchWindowPixelTop = Max (tnSearchWindowPixelTop, PIXELINDEX (0)); tnSearchWindowPixelBottom = Min (tnSearchWindowPixelBottom, PIXELINDEX (m_tnHeight - PGH + 1)); // If we only have to loop through part of the search window, do // so, to save time. tnSearchLeft = tnSearchWindowPixelLeft; tnSearchRight = tnSearchWindowPixelRight; tnSearchTop = tnSearchWindowPixelTop; tnSearchBottom = tnSearchWindowPixelBottom; if (tnSearchWindowPixelLeft == m_tnSearchWindowPixelLeft && tnSearchWindowPixelRight == m_tnSearchWindowPixelRight) { // We only have to do the bottom line. assert (tnSearchWindowPixelTop == m_tnSearchWindowPixelTop); tnSearchTop = m_tnSearchWindowPixelBottom; } else if (tnSearchWindowPixelTop == m_tnSearchWindowPixelTop && tnSearchWindowPixelBottom == m_tnSearchWindowPixelBottom) { if (tnSearchWindowPixelLeft == m_tnSearchWindowPixelLeft) { // We only have to do the right side. tnSearchLeft = m_tnSearchWindowPixelRight; } else if (tnSearchWindowPixelRight == m_tnSearchWindowPixelRight) { // We only have to do the left side. tnSearchRight = m_tnSearchWindowPixelLeft; } } // Loop through the active portion of the search window, find all // pixel-groups that contain only unresolved pixels, and put those // cells into the pixel-sorter. Skip the already-active part of the // search-window, if any. for (tnY = tnSearchTop; tnY < tnSearchBottom; ++tnY) { PIXELINDEX tnPixelX, tnPixelY; // Used to loop through pixels in the pixel-group. for (tnX = tnSearchLeft; tnX < tnSearchRight; ++tnX) { // Skip any part of the search-window that's already active. if (tnY >= m_tnSearchWindowPixelTop && tnY < m_tnSearchWindowPixelBottom && tnX >= m_tnSearchWindowPixelLeft && tnX < m_tnSearchWindowPixelRight) { // (Skip the rest of the line.) assert (tnX == m_tnSearchWindowPixelLeft); tnX = m_tnSearchWindowPixelRight - PIXELINDEX (1); goto nextXPixel; } // Get the cell that we'll be setting up. pCell = &(m_ppSearchWindow[tnY][tnX]); // If this cell was invalidated previously, skip it. if (pCell->m_eDoneSorting != SearchWindowCell::m_knNotDone && pCell->m_pSorter == NULL) { assert (pCell->m_pForward == NULL); assert (pCell->m_pBackward == NULL); goto nextXPixel; } // If this cell was set up previously, skip it. if (pCell->m_pForward != NULL) { assert (pCell->m_pBackward != NULL); goto sortCell; } // Now set up the pixels. for (tnPixelY = 0; tnPixelY < PGH; ++tnPixelY) { for (tnPixelX = 0; tnPixelX < PGW; ++tnPixelX) { ReferencePixel_t *pPixel; // The current reference pixel. // Get the current reference pixel. pPixel = m_pReferenceFrame->GetPixel (tnX + tnPixelX, tnY + tnPixelY); // Set up the corresponding pixel in the current // search-window cell. pCell->m_atPixels[tnPixelY][tnPixelX] = pPixel->GetValue(); } } // Set up the cell's location. pCell->m_tnX = tnX; pCell->m_tnY = tnY; // Remember that this cell's pixels are set up (by putting // the cell into a circular list with itself). pCell->m_pForward = pCell->m_pBackward = pCell; sortCell:; // Put this cell into the pixel-sorter, if it's not // there already. #ifndef OPTIONALLY_SORT_PIXEL_GROUPS if (pCell->m_pForward == pCell) { // (Sanity check: the backward pointer should be // circular too.) assert (pCell->m_pBackward == pCell); // Take it out of the list it's in with itself. pCell->Remove(); // Put it into the pixel-sorter. pCell->m_pSorter = PixelSorter_Add (a_reStatus, pCell, pCell->m_pSorter, pCell->m_eDoneSorting); if (a_reStatus != g_kNoError) return; } #endif // OPTIONALLY_SORT_PIXEL_GROUPS nextXPixel:; } } // The search-window now looks like this. m_tnSearchWindowPixelLeft = tnSearchWindowPixelLeft; m_tnSearchWindowPixelRight = tnSearchWindowPixelRight; m_tnSearchWindowPixelTop = tnSearchWindowPixelTop; m_tnSearchWindowPixelBottom = tnSearchWindowPixelBottom; #ifndef OPTIONALLY_SORT_PIXEL_GROUPS // The search-window now looks like this. m_tnSearchWindowSortLeft = tnSearchWindowPixelLeft; m_tnSearchWindowSortRight = tnSearchWindowPixelRight; m_tnSearchWindowSortTop = tnSearchWindowPixelTop; m_tnSearchWindowSortBottom = tnSearchWindowPixelBottom; #else // OPTIONALLY_SORT_PIXEL_GROUPS // Put pixel-groups into the pixel-sorter, if so asked. if (a_bSortPixels) { PIXELINDEX tnSearchWindowSortLeft, tnSearchWindowSortRight, tnSearchWindowSortTop, tnSearchWindowSortBottom; // What the search window should look like when we're done. // The search window starts in a radius around the index of the // current pixel group. tnSearchWindowSortLeft = m_tnX - m_tnSearchRadiusX; tnSearchWindowSortRight = m_tnX + m_tnSearchRadiusX + PIXELINDEX (1); tnSearchWindowSortTop = m_tnY - m_tnSearchRadiusY; tnSearchWindowSortBottom = m_tnY + m_tnSearchRadiusY + PIXELINDEX (1); // Then it gets clipped by the frame boundaries. tnSearchWindowSortLeft = Max (tnSearchWindowSortLeft, PIXELINDEX (0)); tnSearchWindowSortRight = Min (tnSearchWindowSortRight, PIXELINDEX (m_tnWidth - PGW + 1)); tnSearchWindowSortTop = Max (tnSearchWindowSortTop, PIXELINDEX (0)); tnSearchWindowSortBottom = Min (tnSearchWindowSortBottom, PIXELINDEX (m_tnHeight - PGH + 1)); // If we only have to loop through part of the search window, do // so, to save time. tnSearchLeft = tnSearchWindowSortLeft; tnSearchRight = tnSearchWindowSortRight; tnSearchTop = tnSearchWindowSortTop; tnSearchBottom = tnSearchWindowSortBottom; if (tnSearchWindowSortLeft == m_tnSearchWindowSortLeft && tnSearchWindowSortRight == m_tnSearchWindowSortRight) { // We only have to do the bottom line. assert (tnSearchWindowSortTop == m_tnSearchWindowSortTop); tnSearchTop = m_tnSearchWindowSortBottom; } else if (tnSearchWindowSortTop == m_tnSearchWindowSortTop && tnSearchWindowSortBottom == m_tnSearchWindowSortBottom) { if (tnSearchWindowSortLeft == m_tnSearchWindowSortLeft) { // We only have to do the right side. tnSearchLeft = m_tnSearchWindowSortRight; } else if (tnSearchWindowSortRight == m_tnSearchWindowSortRight) { // We only have to do the left side. tnSearchRight = m_tnSearchWindowSortLeft; } } // Loop through the active portion of the search window, find // all pixel-groups that contain only unresolved pixels, and // put those cells into the pixel-sorter. Skip the // already-active part of the search-window, if any. for (tnY = tnSearchTop; tnY < tnSearchBottom; ++tnY) { for (tnX = tnSearchLeft; tnX < tnSearchRight; ++tnX) { // Skip any part of the search-window that's already // active. if (tnY >= m_tnSearchWindowSortTop && tnY < m_tnSearchWindowSortBottom && tnX >= m_tnSearchWindowSortLeft && tnX < m_tnSearchWindowSortRight) { // (Skip the rest of the line.) assert (tnX == m_tnSearchWindowSortLeft); tnX = m_tnSearchWindowSortRight - PIXELINDEX (1); continue; } // Get the cell that we'll be setting up. pCell = &(m_ppSearchWindow[tnY][tnX]); // Put this cell into the pixel-sorter, if it's not // there already. if (pCell->m_pForward == pCell) { // (Sanity check: the backward pointer should be // circular too.) assert (pCell->m_pBackward == pCell); // Take it out of the list it's in with itself. pCell->Remove(); // Put it into the pixel-sorter. pCell->m_pSorter = PixelSorter_Add (a_reStatus, pCell, pCell->m_pSorter, pCell->m_eDoneSorting); if (a_reStatus != g_kNoError) return; } } } // The search-window now looks like this. m_tnSearchWindowSortLeft = tnSearchWindowSortLeft; m_tnSearchWindowSortRight = tnSearchWindowSortRight; m_tnSearchWindowSortTop = tnSearchWindowSortTop; m_tnSearchWindowSortBottom = tnSearchWindowSortBottom; } #endif // OPTIONALLY_SORT_PIXEL_GROUPS } #ifdef OPTIONALLY_SORT_PIXEL_GROUPS // Return the cell at this index. template template const SearchWindow::SearchWindowCell & SearchWindow:: GetCell (PIXELINDEX a_tnY, PIXELINDEX a_tnX) const { // Make sure the indices are within range. assert (a_tnX >= 0 && a_tnX < m_tnWidth - PGW + 1 && a_tnY >= 0 && a_tnY < m_tnHeight - PGH + 1); // Easy enough. return m_ppSearchWindow[a_tnY][a_tnX]; } #endif // OPTIONALLY_SORT_PIXEL_GROUPS // Prune the search-window, i.e. find all pixel-groups that now // contain used reference-pixels, and remove them from the window // and from the pixel-sorter. template template void SearchWindow::Prune (const REGION &a_rAppliedRegion, PIXELINDEX a_tnOffsetX, PIXELINDEX a_tnOffsetY) { typename REGION::ConstIterator itExtent; // Used to loop through applied-region extents. PIXELINDEX tnX, tnY; // Used to loop through search-window cells. // Make sure we have a new frame & reference frame to work with. assert (m_pReferenceFrame != NULL); // Loop through all the extents in the newly-applied region, find // all corresponding search-window cells, and invalidate them. for (itExtent = a_rAppliedRegion.Begin(); itExtent != a_rAppliedRegion.End(); ++itExtent) { PIXELINDEX tnTop, tnBottom, tnLeft, tnRight; // The range of search-window cells invalidated by the // current applied-region extent. // Get the current extent. const typename REGION::Extent &rExtent = *itExtent; // Determine the range of search-window cells invalidated by // this extent. tnTop = rExtent.m_tnY - PGH + PIXELINDEX (1) + a_tnOffsetY; tnBottom = rExtent.m_tnY + PIXELINDEX (1) + a_tnOffsetY; tnLeft = rExtent.m_tnXStart - PGW + PIXELINDEX (1) + a_tnOffsetX; tnRight = rExtent.m_tnXEnd + a_tnOffsetX; // Clip the range of search-window cells to the boundaries of // the frame. if (tnTop < 0) tnTop = 0; if (tnBottom > m_tnHeight - PGH + PIXELINDEX (1)) tnBottom = m_tnHeight - PGH + PIXELINDEX (1); if (tnLeft < 0) tnLeft = 0; if (tnRight > m_tnWidth - PGW + PIXELINDEX (1)) tnRight = m_tnWidth - PGW + PIXELINDEX (1); // Loop through the search-window cells intersected by the // current extent, and invalidate them. for (tnY = tnTop; tnY < tnBottom; ++tnY) { for (tnX = tnLeft; tnX < tnRight; ++tnX) { SearchWindowCell *pCell; // The search-window cell corresponding to the pixel // group being manipulated. // Get the cell. pCell = &(m_ppSearchWindow[tnY][tnX]); // If the cell is in use, remove it from service. if (pCell->m_pForward != NULL) { // (Sanity check.) assert (pCell->m_pBackward != NULL); // Remove this cell from the pixel-sorter, if it's // in there. if (pCell->m_pForward != pCell) PixelSorter_Remove (pCell); // Invalidate this cell. assert (pCell->m_pForward == pCell); pCell->Remove(); } // Mark it as invalid, so that it won't be used again // for the rest of the frame. pCell->m_eDoneSorting = SearchWindowCell::m_knDone; pCell->m_pSorter = NULL; } } } } // Move the window one pixel to the right, removing all pixel // groups on the left side of the window. template void SearchWindow::MoveRight (void) { PIXELINDEX tnY; // Used to loop through pixel groups. SearchWindowCell *pCell; // The search-window cell corresponding to the pixel group being // removed from the search-window. // If the leftmost edge of the search-window isn't at the edge of // the active area, then there's nothing to invalidate on that side, // and we can stop now. if (m_tnX - m_tnSearchRadiusX != m_tnSearchWindowPixelLeft) { ++m_tnX; return; } // If the search-window is zero width (i.e. invalid anyway), we can // stop now. if (m_tnSearchWindowPixelLeft == m_tnSearchWindowPixelRight) { ++m_tnX; return; } // Make sure that the extent of pixels in the pixel-sorter is // consistent with the extent of initialized pixel-groups. assert (m_tnSearchWindowSortLeft == m_tnSearchWindowSortRight || m_tnSearchWindowPixelLeft <= m_tnSearchWindowSortLeft); // Loop through the left edge of the window, remove all active // search-window cells. for (tnY = m_tnSearchWindowPixelTop; tnY < m_tnSearchWindowPixelBottom; ++tnY) { // Get the cell that we may be removing. pCell = &(m_ppSearchWindow[tnY][m_tnSearchWindowPixelLeft]); // If the cell is in the pixel sorter, remove it. if (pCell->m_pForward != NULL && pCell->m_pForward != pCell) { PixelSorter_Remove (pCell); } } // The search-window now loses its left edge. if (m_tnSearchWindowSortLeft != m_tnSearchWindowSortRight && m_tnSearchWindowSortLeft == m_tnSearchWindowPixelLeft) ++m_tnSearchWindowSortLeft; ++m_tnSearchWindowPixelLeft; // And we're one pixel-group to the right. ++m_tnX; } // Move the window one pixel to the left, removing all pixel // groups on the right side of the window. template void SearchWindow::MoveLeft (void) { PIXELINDEX tnY; // Used to loop through pixel groups. SearchWindowCell *pCell; // The search-window cell corresponding to the pixel group being // removed from the search-window. // If the rightmost edge of the search-window isn't at the edge of // the active area, then there's nothing to invalidate on that side, // and we can stop now. if (m_tnX + m_tnSearchRadiusX + PIXELINDEX (1) != m_tnSearchWindowPixelRight) { --m_tnX; return; } // If the search-window is zero width (i.e. invalid anyway), we can // stop now. if (m_tnSearchWindowPixelLeft == m_tnSearchWindowPixelRight) { --m_tnX; return; } // Make sure that the extent of pixels in the pixel-sorter is // consistent with the extent of initialized pixel-groups. assert (m_tnSearchWindowSortRight == m_tnSearchWindowSortLeft || m_tnSearchWindowPixelRight >= m_tnSearchWindowSortRight); // The search-window loses its right edge. if (m_tnSearchWindowSortRight != m_tnSearchWindowSortLeft && m_tnSearchWindowSortRight == m_tnSearchWindowPixelRight) --m_tnSearchWindowSortRight; --m_tnSearchWindowPixelRight; // Loop through the right edge of the window, remove all active // search-window cells. for (tnY = m_tnSearchWindowPixelTop; tnY < m_tnSearchWindowPixelBottom; ++tnY) { // Get the cell that we may be removing. pCell = &(m_ppSearchWindow[tnY][m_tnX + m_tnSearchRadiusX]); // If the cell is in the pixel sorter, remove it. if (pCell->m_pForward != NULL && pCell->m_pForward != pCell) { PixelSorter_Remove (pCell); } } // And we're one pixel-group to the left. --m_tnX; } // Move the window down one line, removing all pixel groups on // the top of the window. template void SearchWindow::MoveDown (void) { PIXELINDEX tnX; // Used to loop through pixel groups. SearchWindowCell *pCell; // The search-window cell corresponding to the pixel group being // removed from the search-window. // If the topmost edge of the search-window isn't at the edge of the // active area, we can stop now. if (m_tnY - m_tnSearchRadiusY != m_tnSearchWindowPixelTop) { ++m_tnY; return; } // If the search-window is zero height, we can stop now. if (m_tnSearchWindowPixelTop == m_tnSearchWindowPixelBottom) { ++m_tnY; return; } // Make sure that the extent of pixels in the pixel-sorter is // consistent with the extent of initialized pixel-groups. assert (m_tnSearchWindowSortTop == m_tnSearchWindowSortBottom || m_tnSearchWindowPixelTop == m_tnSearchWindowSortTop); // Loop through the top edge of the window, remove all active // search-window cells. for (tnX = m_tnSearchWindowPixelLeft; tnX < m_tnSearchWindowPixelRight; ++tnX) { // Get the cell that we may be removing. pCell = &(m_ppSearchWindow[m_tnSearchWindowPixelTop][tnX]); // If the cell is in the pixel sorter, remove it. if (pCell->m_pForward != NULL && pCell->m_pForward != pCell) { PixelSorter_Remove (pCell); } } // The search-window loses its top edge. if (m_tnSearchWindowSortTop != m_tnSearchWindowSortBottom) ++m_tnSearchWindowSortTop; ++m_tnSearchWindowPixelTop; // And we're one pixel-group lower. ++m_tnY; } // Remove all search-window pixel groups from the pixel sorter, // leaving it empty & ready for another frame. template void SearchWindow::FinishFrame (void) { PIXELINDEX tnX, tnY; // Used to loop through pixel groups. // Loop through the search-window, invalidate all cells. for (tnY = 0; tnY < m_tnHeight - PGH + 1; ++tnY) { for (tnX = 0; tnX < m_tnWidth - PGW + 1; ++tnX) { SearchWindowCell *pCell; // The search-window cell corresponding to the pixel // group being removed from the search-window. // Get the cell that we may be removing. pCell = &(m_ppSearchWindow[tnY][tnX]); // If the cell's pixels are valid, or if it's in the pixel // sorter, invalidate it. if (pCell->m_pForward != NULL) { // (Sanity check.) assert (pCell->m_pBackward != NULL); // If this cell is in the pixel-sorter, remove it. if (pCell->m_pForward != pCell) PixelSorter_Remove (pCell); // Invalidate this cell. assert (pCell->m_pForward == pCell); pCell->Remove(); } // Re-sort it in the next frame. pCell->m_pSorter = NULL; pCell->m_eDoneSorting = SearchWindowCell::m_knNotDone; } } // The search-window is now empty. m_tnSearchWindowPixelLeft = m_tnSearchWindowPixelRight = m_tnSearchWindowPixelTop = m_tnSearchWindowPixelBottom = m_tnSearchWindowSortLeft = m_tnSearchWindowSortRight = m_tnSearchWindowSortTop = m_tnSearchWindowSortBottom = PIXELINDEX (0); // We're done with this frame. Expect our caller to give us a new // one. m_pReferenceFrame = NULL; } // Default constructor. template SearchWindow ::PixelSorterBranchNode::PixelSorterBranchNode() { // One more instance. #ifndef NDEBUG ++sm_ulInstances; #endif // NDEBUG // The attached search-window-cells form a circular list. So // start the circle. m_oSplitValue.m_pForward = m_oSplitValue.m_pBackward = &m_oSplitValue; // No branches yet. for (int i = 0; i < m_knBranches; ++i) m_apBranches[i] = NULL; } // Destructor. template SearchWindow ::PixelSorterBranchNode::~PixelSorterBranchNode() { // Make sure we're the only one in our circular list (i.e. that // no search-window cells are still attached to us). assert (m_oSplitValue.m_pForward == &m_oSplitValue); // Make sure the tree has already been destroyed. // (We don't have a reference to our own allocator.) #ifndef NDEBUG for (int i = 0; i < m_knBranches; ++i) assert (m_apBranches[i] == NULL); #endif // NDEBUG // Finish off the circular list. m_oSplitValue.Remove(); // One less instance. #ifndef NDEBUG --sm_ulInstances; #endif // NDEBUG } // Calculate the bitmask to represent the given pixel // dimension at the given coordinates within the pixel // group. template SORTERBITMASK SearchWindow ::PixelSorterBranchNode::GetBitMask (PIXELINDEX a_tnY, PIXELINDEX a_tnX, int a_nDimension) { // Make sure the pixel index/dimension are within limits. assert (a_tnY >= 0 && a_tnY < PGH); assert (a_tnX >= 0 && a_tnX < PGW); assert (a_nDimension >= 0 && a_nDimension < DIM); // Easy enough. return SORTERBITMASK (1) << ((a_tnY * (PGW * DIM) + a_tnX * DIM + a_nDimension)); } // Determine whether this cell should stay at this level of the tree, // or calculate the details of the child branch where it should go. template bool SearchWindow ::PixelSorterBranchNode::ShouldCellStayHere (const SearchWindowCell &a_rCell, Tolerance_t a_tnTolerance, SORTERBITMASK &a_rtnChildIndex, PixelGroup &a_rMin, PixelGroup &a_rMax) const { PIXELINDEX tnX, tnY; int i; // Used to loop through pixels & pixel dimensions. // Compare the cell's pixel values to our split values, and // determine which child branch it should be moved to, or if it // should stay at this level. a_rtnChildIndex = 0; for (tnY = 0; tnY < PGH; ++tnY) { for (tnX = 0; tnX < PGW; ++tnX) { // Get the two pixels of interest. const Pixel_t &rCellPixel = a_rCell.m_atPixels[tnY][tnX]; const Pixel_t &rSplitPixel = m_oSplitValue.m_atPixels[tnY][tnX]; // If this pixel value is within the tolerance of // the split-point's corresponding pixel, then this // cell has to stay at this level of the tree. if (DIM == 1 && rCellPixel.IsWithinTolerance (rSplitPixel, a_tnTolerance)) { return true; } // Determine the effect each dimension has on the // bitmask that we use to determine the index of the // child branch that this cell should descend into. // Also calculate the min/max for this branch. for (i = 0; i < DIM; ++i) { // If this is a multi-dimensional pixel, we have to // make sure that none of its axes are within the // tolerance either. if (DIM > 1) { // Make copies of the two pixels. Pixel_t oCellPixel = rCellPixel; Pixel_t oSplitPixel = rSplitPixel; // Collapse all dimensions but the current one. for (int j = 0; j < DIM; ++j) if (j != i) oCellPixel[j] = oSplitPixel[j]; // If this axis, all by itself, is within the // tolerance, stop here. if (oCellPixel.IsWithinTolerance (oSplitPixel, a_tnTolerance)) { return true; } } if (rCellPixel[i] > rSplitPixel[i]) { a_rtnChildIndex |= GetBitMask (tnY, tnX, i); a_rMin.m_atPixels[tnY][tnX][i] = rSplitPixel[i]; } else { a_rMax.m_atPixels[tnY][tnX][i] = rSplitPixel[i]; } } } } // The cell can move into a child branch. return false; } // If the given pixel group straddles this level of the tree // (i.e. because one of its pixel values equals its // corresponding split point), then return true. // Otherwise, calculate the index of the child branch that // should take this cell, and return false. // In either case, determine whether any search-window cells // that had to stop at this level of the tree could possibly // intersect the given pixel-group. template bool SearchWindow ::PixelSorterBranchNode::DoesPixelGroupStopHere (const PixelGroup *a_pPixelGroup, Tolerance_t a_tnTwiceTolerance, SORTERBITMASK &a_rtnChildIndex, bool &a_rbMatchAtThisLevel) const { PIXELINDEX tnX, tnY; int i; // Used to loop through pixels & pixel dimensions. bool bPixelGroupStopsHere; // True if one of the pixel-group's pixels exactly matches // its corresponding split-point. // Make sure they gave us a pixel-group. assert (a_pPixelGroup != NULL); // Compare the group's pixel values to our split values, and // determine which child branch it should descend, or if it // should stop at this level. a_rtnChildIndex = 0; bPixelGroupStopsHere = false; a_rbMatchAtThisLevel = false; for (tnY = 0; tnY < PGH; ++tnY) { for (tnX = 0; tnX < PGW; ++tnX) { // Get the two pixels of interest. const Pixel_t &rGroupPixel = a_pPixelGroup->m_atPixels[tnY][tnX]; const Pixel_t &rSplitPixel = m_oSplitValue.m_atPixels[tnY][tnX]; // Determine the effect each dimension has on the // bitmask that we use to determine the index of the // child branch that this cell should descend into. // (If the pixel value is right on a branch's split value, // then all pixels that would match it have been found at // this level.) for (i = 0; i < DIM; i++) { if (rGroupPixel[i] == rSplitPixel[i]) bPixelGroupStopsHere = true; if (rGroupPixel[i] > rSplitPixel[i]) a_rtnChildIndex |= GetBitMask (tnY, tnX, i); // If the current pixel is within twice the tolerance // of the split-point, then some of the search-window // cells that had to stop at this point in the tree may // match the current pixel-group. (And once we figure // that out, we don't have to check any other pixels for // this property.) if (!a_rbMatchAtThisLevel) { // Make copies of the two pixels. Pixel_t oGroupPixel = rGroupPixel; Pixel_t oSplitPixel = rSplitPixel; // Collapse all dimensions but the current one. for (int j = 0; j < DIM; ++j) if (j != i) oGroupPixel[j] = oSplitPixel[j]; // If this axis, all by itself, is within twice the // tolerance, then we can no longer rule out matches // at this level. if (oGroupPixel.IsWithinTolerance (oSplitPixel, a_tnTwiceTolerance)) { a_rbMatchAtThisLevel = true; } } } } } // Return whether the pixel group can descend into a child branch. return bPixelGroupStopsHere; } // Set our split values to the midpoint between the given // minimum & maximum. template void SearchWindow ::PixelSorterBranchNode::SplitValues (const PixelGroup &a_rMin, const PixelGroup &a_rMax) { PIXELINDEX tnX, tnY; int nDim; // Used to iterate through pixel-groups. // Loop through all the pixels & their dimensions, calculate each // split value. for (tnY = 0; tnY < PGH; ++tnY) for (tnX = 0; tnX < PGW; ++tnX) for (nDim = 0; nDim < DIM; ++nDim) m_oSplitValue.m_atPixels[tnY][tnX][nDim] = PIXEL_NUM ((PIXEL_TOL (a_rMin.m_atPixels[tnY][tnX][nDim]) + PIXEL_TOL (a_rMax.m_atPixels[tnY][tnX][nDim])) / PIXEL_TOL (2)); } #ifndef NDEBUG template uint32_t SearchWindow ::PixelSorterBranchNode::sm_ulInstances; template uint32_t SearchWindow ::GetPixelSorterNodeCount (void) { return PixelSorterBranchNode::GetInstances(); } #endif // NDEBUG // Add this search-window cell to the pixel-sorter, creating // new branch nodes as needed. template typename SearchWindow::PixelSorterBranchNode * SearchWindow::PixelSorter_Add (Status_t &a_reStatus, SearchWindowCell *a_pCell, PixelSorterBranchNode *a_pLastSorter, int8_t &a_reDoneSorting) { PixelSorterBranchNode *pCurrentBranch; // Where we are in the pixel-sorter tree. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure they gave us a cell to add. assert (a_pCell != NULL); // Make sure the cell is within the search radius. assert (AbsoluteValue (a_pCell->m_tnX - m_tnX) <= m_tnSearchRadiusX); assert (AbsoluteValue (a_pCell->m_tnY - m_tnY) <= m_tnSearchRadiusY); // If we know where the cell should go, just put it there and exit. if (a_pLastSorter != NULL && a_reDoneSorting == SearchWindowCell::m_knDone) { a_pLastSorter->m_oSplitValue.InsertAfter (&(a_pLastSorter->m_oSplitValue), a_pCell); return a_pLastSorter; } // Initialize our traversal's minimum/maximum to the full range. // This will get modified as we move down the tree. if (a_pLastSorter == NULL) { m_oRangeMin = m_oPixelSorterMin; m_oRangeMax = m_oPixelSorterMax; pCurrentBranch = &m_oPixelSorter; } else { m_oRangeMin = a_pLastSorter->m_oRangeMin; m_oRangeMax = a_pLastSorter->m_oRangeMax; pCurrentBranch = a_pLastSorter; } // Traverse the tree, figure out where the new search-window cell // should be put. Create new branch nodes as needed. for (;;) { SORTERBITMASK tnChildIndex; // The index of the child branch node that should take the // newly-added cell. // If the cell must stay at this level of the tree, then put // the cell at this level & exit. if (pCurrentBranch->ShouldCellStayHere (*a_pCell, m_tnTolerance, tnChildIndex, m_oRangeMin, m_oRangeMax)) { // Hook this cell up to the branch's cell list. pCurrentBranch->m_oSplitValue.InsertAfter (&(pCurrentBranch->m_oSplitValue), a_pCell); // We're done. a_reDoneSorting = SearchWindowCell::m_knDone; return pCurrentBranch; } // The cell should descend into a child branch. If that child // exists, then descend. if (pCurrentBranch->m_apBranches[tnChildIndex] != NULL) { pCurrentBranch = pCurrentBranch->m_apBranches[tnChildIndex]; continue; } // Try to create the child branch that the cell should go into. pCurrentBranch->m_apBranches[tnChildIndex] = (PixelSorterBranchNode *) m_oPSBNAllocator.Allocate (0, sizeof (PixelSorterBranchNode)); if (pCurrentBranch->m_apBranches[tnChildIndex] == NULL) { // We ran out of memory. Just put the cell here. pCurrentBranch->m_oSplitValue.InsertAfter (&(pCurrentBranch->m_oSplitValue), a_pCell); a_reDoneSorting = SearchWindowCell::m_knDoneEnough; return pCurrentBranch; } ::new ((void *)pCurrentBranch->m_apBranches[tnChildIndex]) PixelSorterBranchNode; pCurrentBranch = pCurrentBranch->m_apBranches[tnChildIndex]; // Set its split value to the midpoint between the min/max for // this child. pCurrentBranch->SplitValues (m_oRangeMin, m_oRangeMax); // Put the cell here. pCurrentBranch->m_oSplitValue.InsertAfter (&(pCurrentBranch->m_oSplitValue), a_pCell); // If new branch nodes are created below us, we could go deeper // into the tree, but that won't happen until this cell gets // re-inserted. pCurrentBranch->m_oRangeMin = m_oRangeMin; pCurrentBranch->m_oRangeMax = m_oRangeMax; a_reDoneSorting = SearchWindowCell::m_knDoneEnough; return pCurrentBranch; } } // Remove this search-window cell from the pixel-sorter. template void SearchWindow::PixelSorter_Remove (SearchWindowCell *a_pCell) { // Make sure they gave us a cell to remove. assert (a_pCell != NULL); // Make sure the cell is in the pixel-sorter. assert (a_pCell->m_pForward != NULL && a_pCell->m_pForward != a_pCell); // Remove the cell from the pixel-sorter. a_pCell->Remove(); // Put it back into a list with itself. (This marks the cell as // having been initialized, saving us from having to do that work // again.) a_pCell->m_pForward = a_pCell->m_pBackward = a_pCell; } // Begin a search through the pixel sorter for the given pixel group. template void SearchWindow::StartSearch (PixelSorterIterator &a_rIterator, const PixelGroup &a_rSearch) { // Remember what cell we're searching for. a_rIterator.m_pSearch = &a_rSearch; // Start searching at the top of the tree. a_rIterator.m_pBranch = &m_oPixelSorter; // Remember to search this branch's cells. a_rIterator.m_pCell = &(a_rIterator.m_pBranch->m_oSplitValue); // Initialize these to safe values. a_rIterator.m_tnChildIndex = 0; a_rIterator.m_bPixelGroupStopsHere = false; a_rIterator.m_bMatchesAtThisLevel = false; } // If there is another pixel group that matches the one being // searched for, returns true and backpatches information on the // matched pixel group. If the search is over, returns false. template const typename SearchWindow::PixelGroup * SearchWindow::FoundNextMatch (PixelSorterIterator &a_rIterator #ifdef CALCULATE_SAD , Tolerance_t &a_rtnSAD #endif // CALCULATE_SAD ) const { // Make sure they didn't try to search past the end. assert (a_rIterator.m_pBranch != NULL); // Loop until we find a match or reach the bottom of the tree. for (;;) { // See if we should descend the tree, and whether this // pixel-group could possibly match any search-window cells that // had to stay at this level of the tree. // This only has to be calculated once per branch-node. if (a_rIterator.m_pCell == &(a_rIterator.m_pBranch->m_oSplitValue)) a_rIterator.m_bPixelGroupStopsHere = a_rIterator.m_pBranch ->DoesPixelGroupStopHere (a_rIterator.m_pSearch, m_tnTwiceTolerance, a_rIterator.m_tnChildIndex, a_rIterator.m_bMatchesAtThisLevel); // Move past the last match we found. (This also works if the // branch was just entered, i.e. we're pointing at the branch // node's split values.) a_rIterator.m_pCell = a_rIterator.m_pCell->m_pForward; // Loop through the cells attached to this branch, look for // matches, return if we find one. while (a_rIterator.m_pCell != &(a_rIterator.m_pBranch->m_oSplitValue)) { // If there are not supposed to be any matches at this // level of the search-tree, and the current search-window // cell is stuck at this level, then make sure there's no // match. #ifndef NDEBUG if (!a_rIterator.m_bMatchesAtThisLevel && a_rIterator.m_pCell->m_eDoneSorting == SearchWindowCell::m_knDone) { #ifdef CALCULATE_SAD assert (!a_rIterator.m_pCell->IsWithinTolerance (*(a_rIterator.m_pSearch), m_tnTolerance, a_rtnSAD)); #else // CALCULATE_SAD assert (!a_rIterator.m_pCell->IsWithinTolerance (*(a_rIterator.m_pSearch), m_tnTolerance)); #endif // CALCULATE_SAD } #endif // NDEBUG // If the two pixel groups match, return the match. if ((a_rIterator.m_bMatchesAtThisLevel || a_rIterator.m_pCell->m_eDoneSorting != SearchWindowCell::m_knDone) && a_rIterator.m_pCell->IsWithinTolerance (*(a_rIterator.m_pSearch), m_tnTolerance #ifdef CALCULATE_SAD , a_rtnSAD #endif // CALCULATE_SAD )) return a_rIterator.m_pCell; // Move to the next cell to match against. a_rIterator.m_pCell = a_rIterator.m_pCell->m_pForward; } // We're done examining the cells in this node. See if we // should descend the tree. if (a_rIterator.m_bPixelGroupStopsHere) { // The search stops here. a_rIterator.m_pBranch = NULL; return NULL; } // Descend the tree. a_rIterator.m_pBranch = a_rIterator.m_pBranch ->m_apBranches[a_rIterator.m_tnChildIndex]; if (a_rIterator.m_pBranch == NULL) return NULL; a_rIterator.m_pCell = &(a_rIterator.m_pBranch->m_oSplitValue); } } #endif // __SEARCH_WINDOW_H__ mjpegtools-2.1.0/y4mdenoise/Allocator.hh0000644000175000017500000001517611255220017020537 0ustar glowwormglowworm#ifndef __ALLOCATOR_H__ #define __ALLOCATOR_H__ // This file (C) 2004-2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. #include "config.h" #include "mjpeg_types.h" #include "Limits.hh" // An allocator for small classes. It gets large chunks from the // standard memory allocator & divides it up. It's able to handle // several different object sizes at once. template class Allocator { public: Allocator (size_t a_nChunkSize); // Constructor. Specify the number of bytes to allocate at a // time from the standard memory allocator. ~Allocator(); // Destructor. void *Allocate (size_t a_nSize, size_t a_nBytes); // Allocate memory for another object. // Use the given size-bucket, which must be for the given number // of bytes. // Returns NULL if memory is exhausted. void Deallocate (size_t a_nSize, size_t a_nBytes, void *a_pMemory); // Deallocate previously-allocated memory. uint32_t GetNumAllocated (void) const { return m_ulAllocated; } // Get the number of allocated blocks. private: // One chunk of memory. class Chunk { public: Chunk *m_pNext; // The next allocated chunk. char *m_aSpace; // The memory to divide up. }; size_t m_nChunkSize; // The size of allocated chunks. Set by the constructor. Chunk *m_pChunks; // A linked-list of all the allocated chunks. char *m_pFreeChunk; // The next piece of unallocated memory in the // most-recently-allocated chunk. void *m_apFree[SIZES]; // Linked lists of freed pieces of memory, for all the sizes we // manage. uint32_t m_ulAllocated; // The number of live allocations, i.e. those that haven't been // deleted yet. #ifndef NDEBUG size_t m_aiSizes[SIZES]; #endif // NDEBUG // The size of the pieces of memory in each bucket. // Used to make sure they always ask for the same memory size // in each bucket. void Purge (void); // Free up all chunks. // Only safe if there are no live allocations. }; // Constructor. Specify the number of bytes to allocate at a // time from the standard memory allocator. template Allocator::Allocator (size_t a_nChunkSize) : m_pChunks (NULL), m_pFreeChunk (NULL) { // Round our chunk size up to the nearest pointer size. m_nChunkSize = ((a_nChunkSize + sizeof (Chunk *) - 1) / sizeof (Chunk *)) * sizeof (Chunk *); // All our buckets are empty. for (size_t i = 0; i < SIZES; ++i) { m_apFree[i] = NULL; // (We don't know the memory-size of each bucket yet.) #ifndef NDEBUG m_aiSizes[i] = Limits::Max; #endif // NDEBUG } // No allocations yet. m_ulAllocated = 0UL; } // Destructor. template Allocator::~Allocator() { // If all allocated objects were deallocated, go ahead and free // up our memory. (If there are any allocated objects left, then // generally, that means this is a global allocator, and since C++ // doesn't guarantee order of destruction for global objects, we // have no guarantee our clients have been destroyed, and so it // isn't safe to delete our memory.) if (m_ulAllocated == 0UL) Purge(); } // Allocate memory for another object. // Use the given size-bucket, which must be for the given number // of bytes. // Returns NULL if memory is exhausted. template void * Allocator::Allocate (size_t a_nSize, size_t a_nBytes) { void *pAlloc; // The memory we allocate. // Make sure they gave us a valid size. assert (a_nSize >= 0 && a_nSize < SIZES); // Make sure they gave us a valid number of bytes. assert (a_nBytes >= 0); // Round the number of bytes up to the nearest pointer size. a_nBytes = ((a_nBytes + sizeof (Chunk *) - 1) / sizeof (Chunk *)) * sizeof (Chunk *); // Make sure the requested size fits within our chunk size. assert (a_nBytes <= m_nChunkSize - sizeof (Chunk *)); // If we don't know the size of this bucket, we do now. #ifndef NDEBUG if (m_aiSizes[a_nSize] == Limits::Max) m_aiSizes[a_nSize] = a_nBytes; #endif // NDEBUG // Make sure they ask for the same number of bytes each time. assert (m_aiSizes[a_nSize] == a_nBytes); // If there's a free piece of memory of this size, return it. if (m_apFree[a_nSize] != NULL) { // Remember the allocated memory. pAlloc = m_apFree[a_nSize]; // Remove it from our list. m_apFree[a_nSize] = *(void **)m_apFree[a_nSize]; // That's one more allocation. ++m_ulAllocated; // Return the allocated memory. return pAlloc; } // If there's enough unallocated space in the current chunk, // use it. if (m_pFreeChunk != NULL && size_t (m_pFreeChunk - ((char *)m_pChunks)) <= m_nChunkSize - a_nBytes) { // Remember the allocated memory. pAlloc = (void *) m_pFreeChunk; // Move past this new allocated memory. m_pFreeChunk += a_nBytes; // That's one more allocation. ++m_ulAllocated; // Return the allocated memory. return pAlloc; } // We'll have to create a new chunk in order to satisfy this // allocation request. // First, find a place for the rest of this chunk. // // (Not currently possible, unless we make m_aiSizes[] a non-debug // thing.) // Add a new chunk to our list. { // Allocate a new chunk. Chunk *pNewChunk = (Chunk *) malloc (m_nChunkSize); if (pNewChunk == NULL) return NULL; // Hook it into our list. pNewChunk->m_pNext = m_pChunks; m_pChunks = pNewChunk; } // The unallocated portion of the new chunk is here. m_pFreeChunk = m_pChunks->m_aSpace + a_nBytes; // That's one more allocation. ++m_ulAllocated; // Return the allocated memory. return (void *) (&(m_pChunks->m_aSpace)); } // Deallocate previously-allocated memory. template void Allocator::Deallocate (size_t a_nSize, size_t /* a_nBytes */, void *a_pMemory) { // Make sure they gave us a valid size. assert (a_nSize >= 0 && a_nSize < SIZES); // Put this memory into the given bucket. *(void **)a_pMemory = m_apFree[a_nSize]; m_apFree[a_nSize] = a_pMemory; // That's one less allocation. --m_ulAllocated; // If all memory is unallocated, free up our chunks & start over. if (m_ulAllocated == 0UL) Purge(); } // Free up all chunks. template void Allocator::Purge (void) { // Make sure there are no live allocations assert (m_ulAllocated == 0UL); // Empty the free-space list. for (size_t i = 0; i < SIZES; ++i) m_apFree[i] = NULL; m_pFreeChunk = NULL; // Free all allocated chunks. while (m_pChunks != NULL) { // Remember the next chunk. Chunk *pNextChunk = m_pChunks->m_pNext; // Free this chunk. free (m_pChunks); // Move to the next chunk. m_pChunks = pNextChunk; } } #endif // __ALLOCATOR_H__ mjpegtools-2.1.0/y4mdenoise/Makefile.am0000644000175000017500000000162211736012513020325 0ustar glowwormglowworm# Makefile for y4mdenoise MAINTAINERCLEANFILES = Makefile.in EXTRA_DIST = implementation.html AM_CFLAGS = -DNDEBUG -finline-functions @PROGRAM_NOPIC@ AM_CXXFLAGS = -DNDEBUG -finline-functions @PROGRAM_NOPIC@ INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/utils LIBMJPEGUTILS = $(top_builddir)/utils/libmjpegutils.la if HAVE_ALTIVEC LIBMJPEGUTILS += $(top_builddir)/mpeg2enc/libmpeg2encpp.la endif bin_PROGRAMS = y4mdenoise noinst_HEADERS = \ Allocator.hh \ BitmapRegion2D.hh \ DoublyLinkedList.hh \ Limits.hh \ MotionSearcher.hh \ newdenoise.hh \ PlacementAllocator.hh\ ReferenceFrame.hh \ Region2D.hh \ SearchBorder.hh \ SearchWindow.hh \ Set.hh \ SetRegion2D.hh \ SkipList.hh \ Status_t.h \ TemplateLib.hh \ VariableSizeAllocator.hh \ Vector.hh noinst_PROGRAMS = regiontest regiontest_SOURCES = regiontest.cc y4mdenoise_SOURCES = main.c newdenoise.cc y4mdenoise_LDADD = $(LIBMJPEGUTILS) mjpegtools-2.1.0/y4mdenoise/regiontest.cc0000644000175000017500000001113211173460062020761 0ustar glowwormglowworm#include "config.h" #include #include #include "SetRegion2D.hh" // This file (C) 2004-2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. // The type of region we're testing. typedef SetRegion2D Region; struct Extent { int16_t m_nY; int16_t m_nXStart; int16_t m_nXEnd; }; void PrintRegion (const Region &a_rRegion) { Region::ConstIterator itHere; // Used to loop through the region. // Print the region header. printf ("( "); // Print each extent. for (itHere = a_rRegion.Begin(); itHere != a_rRegion.End(); itHere++) { // Print the extent. printf ("[%d,%d-%d] ", (*itHere).m_tnY, (*itHere).m_tnXStart, (*itHere).m_tnXEnd); } // Print the region trailer. printf (")"); } int main (void) { Status_t eStatus; // An error that may occur. Region oSrcRegion, oTestRegion; // Regions being exercised. // No errors yet. eStatus = g_kNoError; // Initialize our regions. oSrcRegion.Init (eStatus); if (eStatus != g_kNoError) { printf ("oSrcRegion.Init() failed\n"); return 1; } oTestRegion.Init (eStatus); if (eStatus != g_kNoError) { printf ("oTestRegion.Init() failed\n"); return 1; } // Set up an example region. oSrcRegion.Union (eStatus, (int16_t)1, (int16_t)1, (int16_t)4); if (eStatus != g_kNoError) { printf ("oSrcRegion.Union() failed\n"); return 1; } oSrcRegion.Union (eStatus, (int16_t)1, (int16_t)5, (int16_t)7); if (eStatus != g_kNoError) { printf ("oSrcRegion.Union() failed\n"); return 1; } oSrcRegion.Union (eStatus, (int16_t)1, (int16_t)10, (int16_t)20); if (eStatus != g_kNoError) { printf ("oSrcRegion.Union() failed\n"); return 1; } printf ("Original region: "); PrintRegion (oSrcRegion); printf ("\n"); // Now test various additions. { Extent aExtents[] = { {1, 4, 5}, {1, 15, 16}, {1, 6, 10}, {1, 8, 9}, {1, 6, 9}, {1, 9, 21}, {1, 9, 18}, {1, 10, 15}, {1, 25, 30} }; // Extents to test. unsigned int i; // Used to loop through extents to test. // Test each extent in the list. for (i = 0; i < sizeof (aExtents) / sizeof (aExtents[0]); i++) { oTestRegion.Assign (eStatus, oSrcRegion); if (eStatus != g_kNoError) { printf ("oTestRegion.Assign() failed\n"); return 1; } oTestRegion.Union (eStatus, aExtents[i].m_nY, aExtents[i].m_nXStart, aExtents[i].m_nXEnd); if (eStatus != g_kNoError) { printf ("oTestRegion.Union() failed\n"); return 1; } printf ("After adding [%d,%d-%d]: ", aExtents[i].m_nY, aExtents[i].m_nXStart, aExtents[i].m_nXEnd); PrintRegion (oTestRegion); printf ("\n"); } } // Now test various subtractions. { Extent aExtents[] = { {1, 0, 2}, {1, 1, 2}, {1, 3, 5}, {1, 3, 6}, {1, 4, 6}, {1, 3, 12}, {1, 0, 12}, {1, 22, 25}, {1, 15, 17}, {1, 5, 7} }; // Extents to test. unsigned int i; // Used to loop through extents to test. // Test each extent in the list. for (i = 0; i < sizeof (aExtents) / sizeof (aExtents[0]); i++) { oTestRegion.Assign (eStatus, oSrcRegion); if (eStatus != g_kNoError) { printf ("oTestRegion.Assign() failed\n"); return 1; } oTestRegion.Subtract (eStatus, aExtents[i].m_nY, aExtents[i].m_nXStart, aExtents[i].m_nXEnd); if (eStatus != g_kNoError) { printf ("oTestRegion.Subtract() failed\n"); return 1; } printf ("After subtracting [%d,%d-%d]: ", aExtents[i].m_nY, aExtents[i].m_nXStart, aExtents[i].m_nXEnd); PrintRegion (oTestRegion); printf ("\n"); } } /* Before Subtract: ( [0,24-26] [1,24-26] ) Subtract from it: ( [0,10-12] [0,24-26] [1,10-12] [1,24-26] ) Result: ( [0,12-24] [1,12-24] ) */ oSrcRegion.Clear(); oTestRegion.Clear(); oSrcRegion.Union (eStatus, 0, 24, 26); if (eStatus != g_kNoError) { printf ("oSrcRegion.Union() failed\n"); return 1; } oSrcRegion.Union (eStatus, 1, 24, 26); if (eStatus != g_kNoError) { printf ("oSrcRegion.Union() failed\n"); return 1; } oTestRegion.Union (eStatus, 0, 10, 12); if (eStatus != g_kNoError) { printf ("oTestRegion.Union() failed\n"); return 1; } oTestRegion.Union (eStatus, 0, 24, 26); if (eStatus != g_kNoError) { printf ("oTestRegion.Union() failed\n"); return 1; } oTestRegion.Union (eStatus, 1, 10, 12); if (eStatus != g_kNoError) { printf ("oTestRegion.Union() failed\n"); return 1; } oTestRegion.Union (eStatus, 1, 24, 26); if (eStatus != g_kNoError) { printf ("oTestRegion.Union() failed\n"); return 1; } oSrcRegion.Subtract (eStatus, oTestRegion); if (eStatus != g_kNoError) { printf ("oSrc.Subtract (oTestRegion) failed\n"); return 1; } // All done. return 0; } mjpegtools-2.1.0/y4mdenoise/ReferenceFrame.hh0000644000175000017500000004241411173460062021470 0ustar glowwormglowworm#ifndef __REFERENCE_FRAME_H__ #define __REFERENCE_FRAME_H__ // This file (C) 2004-2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. #include "config.h" #include #include "mjpeg_types.h" #include "Status_t.h" #include "TemplateLib.hh" // Definitions for pixels, reference pixels, pixel allocators, and // reference frames. // A generic pixel. // Provide the numeric type used to store pixel values, the dimension of // the pixel type, and the numeric type to use in tolerance // calculations. template class Pixel { public: typedef NUM Num_t; // The numeric type used to store pixel values. Pixel() {} // Default constructor. Pixel (const NUM a_atnVal[DIM]); // Initializing constructor. Pixel (const Pixel &a_rOther); // Copy constructor. NUM &operator[] (int a_nDim) { return m_atnVal[a_nDim]; } NUM operator[] (int a_nDim) const { return m_atnVal[a_nDim]; } // Get the value of this pixel. static TOL MakeTolerance (NUM a_tnTolerance); // Turn an integer tolerance value into what's appropriate for // the pixel type. bool IsWithinTolerance (const Pixel &a_rOther, TOL a_tnTolerance) const; // Return true if the two pixels are within the specified // tolerance. // a_tnTolerance must have been previously retrieved from // MakeTolerance(). bool IsWithinTolerance (const Pixel &a_rOther, TOL a_tnTolerance, TOL &a_rtnSAD) const; // Return true if the two pixels are within the specified // tolerance, and backpatch the sample-array-difference. // a_tnTolerance must have been previously retrieved from // MakeTolerance(). private: NUM m_atnVal[DIM]; // The pixel value. }; // A reference pixel. Used to accumulate values across several frames // for any pixel deemed, via motion detection, to actually be the same // pixel. // Provide the numeric type for accumulated pixels (and tolerance // calculations), the numeric type for pixels, the dimension of the // pixel, and the class used to implement pixels. template > class ReferencePixel { public: typedef PIXEL Pixel_t; // Our pixel type. typedef ACCUM_NUM Tolerance_t; // Our tolerance value type. ReferencePixel(); // Default constructor. ~ReferencePixel(); // Destructor. void Reset (void); // Reset ourselves, so that we may refer to a new pixel. void AddSample (const PIXEL &a_rPixel); // Incorporate another sample. const PIXEL &GetValue (void); // Return this pixel's value. void AddFrameReference (void) { ++m_nFrameReferences; } // Add another reference from a frame. void RemoveFrameReference (void) { --m_nFrameReferences; } // Remove an existing reference from a frame. // (Once all references are removed, the pixel is implicitly // unallocated.) int16_t GetFrameReferences (void) const { return m_nFrameReferences; } // Return the number of frames that refer to this pixel. private: ACCUM_NUM m_atSum[DIM]; // The sum of the values of all pixels we've incorporated. ACCUM_NUM m_tCount; // The number of pixels we've incorporated. int16_t m_nFrameReferences; // The number of reference-frames that make use of this pixel. // A value of 0 means the pixel is not in use & therefore can // be allocated. PIXEL m_oPixel; // The value of this pixel, i.e. m_nSumY / m_nYCount. // Calculated on demand. }; // A class to allocate reference pixels. // Parameterized by the type of reference pixel, and a numeric type that // can hold the largest number of reference pixels to be allocated (i.e. // big enough to hold the product of the frame's width & height). template class PixelAllocator { public: PixelAllocator(); // Default constructor. ~PixelAllocator(); // Destructor. void Initialize (Status_t &a_reStatus, FRAMESIZE a_tnCount); // Initialize the pool to contain the given number of pixels. // This must be greater than or equal to the number of pixels // that can ever be in use at one time. REFERENCEPIXEL *Allocate (void); // Allocate another pixel. // (Note that not having a free pixel to allocate indicates // that the a_nCount parameter to Initialize() needed to be // bigger.) private: FRAMESIZE m_tnCount; // The number of reference pixels in our pool. FRAMESIZE m_tnNext; // The index of the next pixel to try to allocate. // A pixel is considered unallocated if it has a zero // reference count. REFERENCEPIXEL *m_pPixels; // The pool of pixels. }; // A reference frame. Points to reference pixels, which may be shared // across several reference frames, depending on what motion-detection // determines about the pixel's lifetime. Parameterized by the type of // reference pixels to use, the numeric type to use for pixel indices, // and a numeric type big enough to hold the product of the largest // expected width & height. template class ReferenceFrame { public: ReferenceFrame (Status_t &a_reStatus, PIXELINDEX a_tnWidth, PIXELINDEX a_tnHeight); // Initializing constructor. REFERENCEPIXEL *GetPixel (PIXELINDEX a_tnX, PIXELINDEX a_tnY) const; // Get the pixel at this index (which may be NULL). REFERENCEPIXEL *GetPixel (FRAMESIZE a_tnI) const; // Get the pixel at this offset (which may be NULL). void SetPixel (PIXELINDEX a_tnX, PIXELINDEX a_tnY, REFERENCEPIXEL *a_pPixel); // Set the pixel at this index. a_pPixel may be NULL. void SetPixel (FRAMESIZE a_tnI, REFERENCEPIXEL *a_pPixel); // Set the pixel at this offset. a_pPixel may be NULL. void Reset (void); // Reset the frame, i.e. set all the pixels to NULL. private: PIXELINDEX m_tnWidth, m_tnHeight; // The dimensions of the frame. REFERENCEPIXEL **m_ppPixels; // The reference pixels that make up this frame. // The contained pointers may be NULL, to mark pixels that still // need to be resolved. }; // Initializing constructor. template Pixel::Pixel (const NUM a_atnVal[DIM]) { // Store the values. for (int i = 0; i < DIM; ++i) m_atnVal[i] = a_atnVal[i]; } // Copy constructor. template Pixel::Pixel (const Pixel &a_rOther) { // Copy the values. for (int i = 0; i < DIM; ++i) m_atnVal[i] = a_rOther.m_atnVal[i]; } // Turn an integer tolerance value into what's appropriate for // the pixel type. template TOL Pixel::MakeTolerance (NUM a_tnTolerance) { // The default is to just use the given number. return TOL (a_tnTolerance); } #if 0 // This is what I mean, but C++ templates can't do this. // Turn an integer tolerance value into what's appropriate for // the pixel type. template TOL Pixel::MakeTolerance (NUM a_tnTolerance) { // For a one-dimensional pixel, just use the given number. return TOL (a_tnTolerance); } #endif #if 0 // This is what I mean, but C++ templates can't do this. // Turn an integer tolerance value into what's appropriate for // the pixel type. template TOL Pixel::MakeTolerance (NUM a_tnTolerance) { // For a two-dimensional pixel, use the square of the given number. return TOL (a_tnTolerance) * TOL (a_tnTolerance); } #endif #if 0 // This is what I mean, but C++ templates can't do this. // Return true if the two pixels are within the specified tolerance. template bool Pixel::IsWithinTolerance (const Pixel &a_rOther, TOL a_tnTolerance) const { // Check to see if the absolute value of the difference between // the two pixels is within our tolerance value. return AbsoluteValue (TOL (m_atnVal[0]) - TOL (a_rOther.m_atnVal[0])) <= a_tnTolerance; } #endif #if 0 // This is what I mean, but C++ templates can't do this. // Return true if the two pixels are within the specified tolerance. template bool Pixel::IsWithinTolerance (const Pixel &a_rOther, TOL a_tnTolerance) const { // Calculate the vector difference between the two pixels. TOL tnX = TOL (m_atnVal[0]) - TOL (a_rOther.m_atnVal[0]); TOL tnY = TOL (m_atnVal[1]) - TOL (a_rOther.m_atnVal[1]); // Check to see if the length of the vector difference is within // our tolerance value. (Technically, we check the squares of // the values, but that's just as valid & much faster than // calculating a square root.) return tnX * tnX + tnY * tnY <= a_tnTolerance; } #endif // Default constructor. template ReferencePixel::ReferencePixel() { // Reset the pixel value. Reset(); // No references from frames yet. m_nFrameReferences = 0; } // Destructor. template ReferencePixel::~ReferencePixel() { // Make sure no frames refer to us. assert (m_nFrameReferences == 0); } // Reset ourselves, so that we may refer to a new pixel. template void ReferencePixel::Reset (void) { // Reset the accumulated sum, and get rid of any existing pixel value. for (int i = 0; i < DIM; i++) { m_atSum[i] = ACCUM_NUM (0); m_oPixel[i] = PIXEL_NUM (0); } m_tCount = ACCUM_NUM (0); } // Incorporate another sample. template void ReferencePixel::AddSample (const PIXEL &a_rPixel) { // Make sure this pixel is in use. assert (m_nFrameReferences > 0); // If the number of samples is getting close to causing overflow // problems, deal with it by losing a little resolution. // (These divides should turn into bit-shifts with integer types, // and therefore not be a performance issue.) if (m_tCount >= 10 /* HACK (Limits::Max / ACCUM_NUM (2)) */) { for (int i = 0; i < DIM; i++) m_atSum[i] /= ACCUM_NUM (2); m_tCount /= ACCUM_NUM (2); } // Add the value to our accumulated sum. for (int i = 0; i < DIM; i++) m_atSum[i] += a_rPixel[i]; ++m_tCount; // Recalculate the pixel value. { static float afDivisors[] = { 0.0f, 1.0f, 1.0f / 2.0f, 1.0f / 3.0f, 1.0f / 4.0f, 1.0f / 5.0f, 1.0f / 6.0f, 1.0f / 7.0f, 1.0f / 8.0f, 1.0f / 9.0f, 1.0f / 10.0f }; // HACK: try to speed this up. // Calculate the pixel's value. if (m_tCount <= 10) { for (int i = 0; i < DIM; i++) m_oPixel[i] = PIXEL_NUM ((float (m_atSum[i]) * afDivisors[m_tCount]) + 0.5f); } else { for (int i = 0; i < DIM; i++) m_oPixel[i] = PIXEL_NUM ((float (m_atSum[i]) / float (m_tCount)) + 0.5f); } } } // Return the pixel's value. template const PIXEL & ReferencePixel::GetValue (void) { // Easy enough. return m_oPixel; } // Default constructor. template PixelAllocator::PixelAllocator() { // No pixels yet. m_tnCount = m_tnNext = 0; m_pPixels = NULL; } // Destructor. template PixelAllocator::~PixelAllocator() { // Free up the pixel pool. (The pixels themselves will verify that // there are no more references to them.) delete[] m_pPixels; } // Initialize the pool to contain the given number of pixels. template void PixelAllocator::Initialize (Status_t &a_reStatus, FRAMESIZE a_tnCount) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure we haven't been initialized already. assert (m_pPixels == NULL); // Try to allocate a pool of the given number of pixels. m_pPixels = new REFERENCEPIXEL[a_tnCount]; if (m_pPixels == NULL) { a_reStatus = g_kOutOfMemory; return; } // Remember that we allocated this many pixels. m_tnCount = a_tnCount; // Allocate the first pixel first. m_tnNext = 0; } // Allocate another pixel. template REFERENCEPIXEL * PixelAllocator::Allocate (void) { FRAMESIZE tnOrigNext; // The original value of the index of the next pixel to // allocate. Used to detect when we've run through all of // them. REFERENCEPIXEL *pPixel; // The pixel we allocate. // Loop through the pixel pool, find an unallocated one, return it // to them. tnOrigNext = m_tnNext; for (;;) { // Get the next pixel. pPixel = m_pPixels + m_tnNext; //m_tnNext = (m_tnNext + 1) % m_tnCount; ++m_tnNext; // (faster...no divide) assert (m_tnNext <= m_tnCount); if (m_tnNext == m_tnCount) m_tnNext = 0; // If this pixel is unallocated, reset it & return it. if (pPixel->GetFrameReferences() == 0) { pPixel->Reset(); return pPixel; } // Make sure we haven't run out of pixels. (Returning NULL // may cause a segmentation fault in our client, but that's // slightly better than an infinite loop.) if (m_tnNext == tnOrigNext) { assert (false); return NULL; } } } // Initializing constructor. template ReferenceFrame::ReferenceFrame (Status_t &a_reStatus, PIXELINDEX a_tnWidth, PIXELINDEX a_tnHeight) { FRAMESIZE tnPixels; // The total number of pixels referred to by this frame. FRAMESIZE i; // Used to loop through pixel references. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure the height and width are sane. assert (a_tnWidth > 0); assert (a_tnHeight > 0); // Allocate space for the frame's pixels. tnPixels = FRAMESIZE (a_tnWidth) * FRAMESIZE (a_tnHeight); m_ppPixels = new REFERENCEPIXEL * [tnPixels]; if (m_ppPixels == NULL) { a_reStatus = g_kOutOfMemory; return; } // Remember our dimensions. m_tnWidth = a_tnWidth; m_tnHeight = a_tnHeight; // Initially, no pixels are referred to by the frame. for (i = 0; i < tnPixels; i++) m_ppPixels[i] = NULL; } // Get the pixel at this index (which may be NULL). template REFERENCEPIXEL * ReferenceFrame::GetPixel (PIXELINDEX a_tnX, PIXELINDEX a_tnY) const { // Make sure the indices are within limits. assert (a_tnX >= PIXELINDEX (0) && a_tnX < m_tnWidth); assert (a_tnY >= PIXELINDEX (0) && a_tnY < m_tnHeight); // Easy enough. return m_ppPixels[FRAMESIZE (a_tnY) * FRAMESIZE (m_tnWidth) + FRAMESIZE (a_tnX)]; } // Get the pixel at this offset (which may be NULL). template REFERENCEPIXEL * ReferenceFrame::GetPixel (FRAMESIZE a_tnI) const { // Make sure the offset is within limits. assert (a_tnI >= FRAMESIZE (0) && a_tnI < FRAMESIZE (m_tnWidth) * FRAMESIZE (m_tnHeight)); // Easy enough. return m_ppPixels[a_tnI]; } // Set the pixel at this index. a_pPixel may be NULL. template void ReferenceFrame::SetPixel (PIXELINDEX a_tnX, PIXELINDEX a_tnY, REFERENCEPIXEL *a_pPixel) { // Make sure the indices are within limits. assert (a_tnX >= PIXELINDEX (0) && a_tnX < m_tnWidth); assert (a_tnY >= PIXELINDEX (0) && a_tnY < m_tnHeight); // Get the pixel of interest. REFERENCEPIXEL *&rpPixel = m_ppPixels[FRAMESIZE (a_tnY) * FRAMESIZE (m_tnWidth) + FRAMESIZE (a_tnX)]; // If there's a pixel here already, remove our reference to it. if (rpPixel != NULL) rpPixel->RemoveFrameReference(); // Store the new pixel here. rpPixel = a_pPixel; // If they stored a valid pixel, add our reference to it. if (rpPixel != NULL) rpPixel->AddFrameReference(); } // Set the pixel at this offset. a_pPixel may be NULL. template void ReferenceFrame::SetPixel (FRAMESIZE a_tnI, REFERENCEPIXEL *a_pPixel) { // Make sure the offset is within limits. assert (a_tnI >= FRAMESIZE (0) && a_tnI < FRAMESIZE (m_tnWidth) * FRAMESIZE (m_tnHeight)); // Get the pixel of interest. REFERENCEPIXEL *&rpPixel = m_ppPixels[a_tnI]; // If there's a pixel here already, remove our reference to it. if (rpPixel != NULL) rpPixel->RemoveFrameReference(); // Store the new pixel here. rpPixel = a_pPixel; // If they stored a valid pixel, add our reference to it. if (rpPixel != NULL) rpPixel->AddFrameReference(); } // Reset the frame (i.e. set all the pixels to NULL). template void ReferenceFrame::Reset (void) { FRAMESIZE tnPixels; // The total number of pixels referred to by this frame. FRAMESIZE i; // Used to loop through pixels. // Loop through all pixels, set them to NULL. tnPixels = FRAMESIZE (m_tnWidth) * FRAMESIZE (m_tnHeight); for (i = 0; i < tnPixels; ++i) { // If there's a pixel here already, remove our reference to it, // then remove the pixel. if (m_ppPixels[i] != NULL) { m_ppPixels[i]->RemoveFrameReference(); m_ppPixels[i] = NULL; } } } #endif // __REFERENCE_FRAME_H__ mjpegtools-2.1.0/y4mdenoise/SetRegion2D.hh0000644000175000017500000015303311206112210020666 0ustar glowwormglowworm#ifndef __SETREGION2D_H__ #define __SETREGION2D_H__ // This file (C) 2004-2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. // SetRegion2D tracks a 2-dimensional region of arbitrary points. // It's implemented by a sorted set of Extents. This is pretty fast // overall, and is very space efficient, even with sparse regions. #include "Region2D.hh" #include "Set.hh" // Define this to compile in code to double-check and debug the region. #ifndef DEBUG_REGION2D // #define DEBUG_SETREGION2D #endif // DEBUG_REGION2D // The 2-dimensional region class. Parameterized by the numeric type // to use for point indices, and the numeric type to use to count the // contained number of points. template ::Extent,typename Region2D::Extent,Ident::Extent,typename Region2D::Extent>,Less::Extent> > > class SetRegion2D : public Region2D { private: typedef Region2D BaseClass; // Keep track of who our base class is. public: typedef typename BaseClass::Extent Extent; // (Wouldn't we automatically have access to Extent because // we're a subclass of Region2D<>? Why is this needed?) typedef Set,SETIMP> Extents; // The container type that stores our extents. typedef typename Extents::InitParams InitParams; // The structure for our container's initialization parameters. private: Extents m_setExtents; // The extents that make up the region. public: typedef typename Extents::Allocator Allocator; // The type of allocator to use to allocate region extents. explicit SetRegion2D (Allocator &a_rAlloc = Extents::Imp::sm_oNodeAllocator); // Default constructor. Must be followed by Init(). SetRegion2D (Status_t &a_reStatus, const InitParams &a_rInitParams = InitParams(), Allocator &a_rAlloc = Extents::Imp::sm_oNodeAllocator); // Initializing constructor. Creates an empty region. SetRegion2D (Status_t &a_reStatus, const SetRegion2D &a_rOther); // Copy constructor. void Init (Status_t &a_reStatus, const InitParams &a_rInitParams = InitParams()); // Initializer. Must be called on default-constructed regions. void Assign (Status_t &a_reStatus, const SetRegion2D &a_rOther); // Make the current region a copy of the other region. virtual ~SetRegion2D(); // Destructor. #ifdef DEBUG_SETREGION2D void SetDebug (bool a_bDebug); // Set whether to run the region invariant before and after // methods. void Invariant (void) const; // Thoroughly analyze the region for structural integrity. #endif // DEBUG_SETREGION2D inline SIZE NumberOfPoints (void) const; // Return the total number of points contained by the region. void Clear (void); // Clear the region, emptying it of all extents. void Purge (void); // Purge all internally-allocated memory. void Union (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd); // Add the given horizontal extent to the region. Note that // a_tnXEnd is technically one past the end of the extent. void Merge (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd); // Merge this extent into the current region. // The new extent can't intersect any of the region's existing // extents (including being horizontally contiguous). void Merge (SetRegion2D &a_rOther); // Merge the other region into ourselves, emptying the other // region. Like Union(), but doesn't allocate any new memory. // Also, the other region can't intersect any of the region's // existing extents (including being horizontally contiguous), // and both regions must use the same allocator. void Move (SetRegion2D &a_rOther); // Move the contents of the other region into the current // region. // The current region must be empty. bool CanMove (const SetRegion2D &a_rOther) const; // Returns true if the other region's contents can be moved // into the current region. bool CanMove (const Region2D &a_rOther) const { return false; } void Move (Region2D &a_rOther) { assert (false); } // (We can move between SetRegion2D<>s, but not any arbitrary // Region2D<> subclass.) void Intersection (Status_t &a_reStatus, const SetRegion2D &a_rOther); // Make the current region represent the intersection between // itself and the other given region. void Subtract (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd); // Subtract the given horizontal extent from the region. Note // that a_tnXEnd is technically one past the end of the extent. void Subtract (Status_t &a_reStatus, const SetRegion2D &a_rOther); // Subtract the other region from the current region, i.e. // remove from the current region any extents that exist in the // other region. void SubtractWithOffset (Status_t &a_reStatus, const SetRegion2D &a_rOther, INDEX a_tnXOffset, INDEX a_tnYOffset); // Subtract the other region from the current region, but offset // the other region by the given amounts. void Offset (INDEX a_tnXOffset, INDEX a_tnYOffset); // Move all extents by the given offset. typedef typename Extents::ConstIterator ConstIterator; ConstIterator Begin (void) const { return m_setExtents.Begin(); } ConstIterator End (void) const { return m_setExtents.End(); } // Allow our client to iterate through the extents & get their // values. bool DoesContainPoint (INDEX a_tnY, INDEX a_tnX); // Returns true if the region contains the given point. bool DoesContainPoint (INDEX a_tnY, INDEX a_tnX, ConstIterator &a_ritHere); // Returns true if the region contains the given point. // Backpatches the extent that contains the point, or the // extent before where it should be. ConstIterator LowerBound (INDEX a_tnY, INDEX a_tnX) const { Extent oExtent (a_tnY, a_tnX, a_tnX); return m_setExtents.LowerBound (oExtent); } // Return the position of the first extent whose beginning // is >= the given point. ConstIterator UpperBound (INDEX a_tnY, INDEX a_tnX) const { Extent oExtent (a_tnY, a_tnX, a_tnX); return m_setExtents.UpperBound (oExtent); } // Return the position of the first extent whose beginning // is > the given extent. // A structure that implements flood-fills using SetRegion2D<> to // do the work. class FloodFillControl; template void FloodFill (Status_t &a_reStatus, CONTROL &a_rControl, bool a_bVerify, bool a_bExpand); // Flood-fill the current region. // If a_bVerify is true, all existing region points are re-tested. // If a_bExpand is true, all points bordering the current region // are tested for inclusion. template void MakeBorder (Status_t &a_reStatus, const REGION &a_rOther); // Make the current region represent the border of the other // region, i.e. every pixel that's adjacent to a pixel that's // in the region, but isn't already in the region. void UnionSurroundingExtents (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd); // Add all extents surrounding the given extent. // Used by FloodFill() and MakeBorder(). private: SIZE m_tnPoints; // The total number of points contained by the region. void Subtract (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd, const SetRegion2D &a_rOther, typename Extents::ConstIterator &a_ritHere); // Subtract the given horizontal extent from the region. Note // that a_tnXEnd is technically one past the end of the extent. // a_ritHere is a reference to the iterator that this extent // came from in a_rOther, or a_rOther.m_setExtents.End() if // there is no such iterator. If there are no extents that // intersect the given extent, ritHere is backpatched with the // location of the first extent in a_rOther to intersect it. // This allows region subtractions to skip past irrelevant // areas. void SubtractWithOffset (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd, INDEX a_tnXOffset, INDEX a_tnYOffset, const SetRegion2D &a_rOther, typename Extents::ConstIterator &a_ritHere); // Subtract the given horizontal extent from the region, with // the given offset. #ifdef DEBUG_SETREGION2D bool m_bDebug; #endif // DEBUG_SETREGION2D // true if the invariant should be checked. #ifndef NDEBUG // Count the number of region objects in existence. private: static uint32_t sm_ulInstances; public: static uint32_t GetInstances (void) { return sm_ulInstances; } #endif // NDEBUG }; // The flood-fill-control class. template class SetRegion2D::FloodFillControl { private: typedef SetRegion2D Region_t; // Keep track of our region class. public: // (Although these fields are public, they should be considered // opaque to the client.) Region_t m_oToDo; // Extents that still need to be be tested. Region_t m_oAlreadyDone; // Extents that have been tested. Region_t m_oNextToDo; // Extents contiguous with those that have just been added // to the flood-filled area. typedef typename Region_t::ConstIterator ConstIterator; typedef typename Region_t::Extent Extent; // The iterator/extent type for running through the above // regions. typedef typename Region_t::Allocator Allocator; // The allocator type for region extents. public: explicit FloodFillControl (Allocator &a_rAllocator = Region_t::Extents::Imp::sm_oNodeAllocator); // Default constructor. Must be followed by a call to Init(). FloodFillControl (Status_t &a_reStatus, Allocator &a_rAllocator = Region_t::Extents::Imp::sm_oNodeAllocator); // Initializing constructor. void Init (Status_t &a_reStatus); // Initializer. Must be called on default-constructed objects. // (May not be valid to call on subclasses, depending on // whether more parameters are needed for its Init().) void Purge (void); // Purge all internally-allocated memory. // Methods to be redefined by clients implementing specific // flood-fills. bool ShouldUseExtent (Extent &a_rExtent) { return true; } // Return true if the flood-fill should examine the given // extent. Clients should redefine this to define their own // criteria for when extents should be used, and to modify the // extent as needed (e.g. to clip the extent to a bounding box). bool IsPointInRegion (INDEX a_tnX, INDEX a_tnY) { return false; } // Returns true if the given point should be included in the // flood-fill. Clients must redefine this to explain their // flood-fill criteria. }; // Default constructor. Must be followed by Init(). template SetRegion2D::SetRegion2D (Allocator &a_rAlloc) : m_setExtents (Less(), a_rAlloc) { // One more instance. #ifndef NDEBUG ++sm_ulInstances; #endif // NDEBUG // No points yet. m_tnPoints = 0; // Check the invariant by default; they'll have to specifically // request not to. #ifdef DEBUG_SETREGION2D m_bDebug = true; #endif // DEBUG_SETREGION2D } // Initializing constructor. Creates an empty region. template SetRegion2D::SetRegion2D (Status_t &a_reStatus, const InitParams &a_rInitParams, Allocator &a_rAlloc) : m_setExtents (a_reStatus, false, a_rInitParams, Less(), a_rAlloc) { // One more instance. #ifndef NDEBUG ++sm_ulInstances; #endif // NDEBUG // No points yet. m_tnPoints = 0; // Check the invariant by default; they'll have to specifically // request not to. #ifdef DEBUG_SETREGION2D m_bDebug = true; #endif // DEBUG_SETREGION2D } // Copy constructor. template SetRegion2D::SetRegion2D (Status_t &a_reStatus, const SetRegion2D &a_rOther) : m_setExtents (a_reStatus, false, Less(), a_rOther.m_setExtents.m_oImp.m_rNodeAllocator) { // One more instance. #ifndef NDEBUG ++sm_ulInstances; #endif // NDEBUG // No points yet. m_tnPoints = 0; // Check the invariant by default; they'll have to specifically // request not to. #ifdef DEBUG_SETREGION2D m_bDebug = true; #endif // DEBUG_SETREGION2D // If the construction of m_setExtents failed, bail. if (a_reStatus != g_kNoError) return; // Copy all the extents. m_setExtents.Insert (a_reStatus, a_rOther.m_setExtents.Begin(), a_rOther.m_setExtents.End()); if (a_reStatus != g_kNoError) return; // Now we have as many points as the copied region. m_tnPoints = a_rOther.m_tnPoints; // Make sure we're intact. #ifdef DEBUG_SETREGION2D Invariant(); #endif // DEBUG_SETREGION2D } // Initializer. Must be called on default-constructed regions. template void SetRegion2D::Init (Status_t &a_reStatus, const InitParams &a_rInitParams) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Initialize our set of extents. m_setExtents.Init (a_reStatus, false, a_rInitParams); if (a_reStatus != g_kNoError) return; } // Make the current region a copy of the other region. template void SetRegion2D::Assign (Status_t &a_reStatus, const SetRegion2D &a_rOther) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure both regions are intact. #ifdef DEBUG_SETREGION2D Invariant(); a_rOther.Invariant(); #endif // DEBUG_SETREGION2D // Assign the other region's extents to ourselves. m_setExtents.Assign (a_reStatus, a_rOther.m_setExtents); if (a_reStatus != g_kNoError) return; // Now we have as many points as they do. m_tnPoints = a_rOther.m_tnPoints; // Make sure we're intact. #ifdef DEBUG_SETREGION2D Invariant(); #endif // DEBUG_SETREGION2D } // Destructor. template SetRegion2D::~SetRegion2D() { // One less instance. #ifndef NDEBUG --sm_ulInstances; #endif // NDEBUG } #ifdef DEBUG_SETREGION2D // Set whether to run the region invariant before and after // methods. template void SetRegion2D::SetDebug (bool a_bDebug) { // Easy enough. m_bDebug = a_bDebug; // Have the set of extents check itself too, to make sure we didn't // do anything to break it. #ifdef DEBUG_SKIPLIST m_setExtents.SetDebug (a_bDebug); #endif // DEBUG_SKIPLIST } // Thoroughly analyze the region for structural integrity. template void SetRegion2D::Invariant (void) const { SIZE tnPoints; // Our total of the number of points in the region. typename Extents::ConstIterator itHere, itNext; // Used to run through the extents. // Only check the invariant if they requested we do. if (!m_bDebug) return; // Make sure the contained set is intact. (That will verify that // the extents are sorted properly, so we don't have to do that // here.) #ifdef DEBUG_SKIPLIST m_setExtents.Invariant(); #endif // DEBUG_SKIPLIST // Run through the extents, make sure that they're not contiguous // with each other, and count up the number of contained points. tnPoints = 0; for (itHere = m_setExtents.Begin(); itHere != m_setExtents.End(); itHere = itNext) { // Find the next extent. itNext = itHere; ++itNext; // Make sure that the extents aren't horizontally contiguous. // (Horizontally contiguous extents should have been merged // together.) assert (itNext == m_setExtents.End() || (*itHere).m_tnY != (*itNext).m_tnY || (*itHere).m_tnXEnd < (*itNext).m_tnXStart); // Add the number of points in this extent to our total. tnPoints += (*itHere).m_tnXEnd - (*itHere).m_tnXStart; } // Make sure the point total is accurate. assert (m_tnPoints == tnPoints); } #endif // DEBUG_SETREGION2D // Return the total number of points contained by the region. template inline SIZE SetRegion2D::NumberOfPoints (void) const { // Easy enough. return m_tnPoints; } // Clear the region, emptying it of all extents. template void SetRegion2D::Clear (void) { // Easy enough. m_setExtents.Clear(); m_tnPoints = 0; } // Purge all internally-allocated memory. template void SetRegion2D::Purge (void) { // Make sure the region is empty. assert (m_tnPoints == 0); // Easy enough. m_setExtents.Purge(); } // Add the given horizontal extent to the region. template void SetRegion2D::Union (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd) { Extent oKey; // An extent being searched for. Extent oInserted; // The extent being added, modified to account for the extents // already present in the region. typename Extents::Iterator itStart, itEnd; // The range of existing extents that gets removed because of // the addition of the new extent. typename Extents::Iterator itHere; // An extent being examined and/or modified. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure they gave us a non-empty extent. assert (a_tnXStart < a_tnXEnd); // Make sure we're intact. #ifdef DEBUG_SETREGION2D Invariant(); #endif // DEBUG_SETREGION2D // The extent we'll be inserting starts as the extent they asked // to add. That may get modified based on the nature of the extents // already present in the region. oInserted.m_tnY = a_tnY; oInserted.m_tnXStart = a_tnXStart; oInserted.m_tnXEnd = a_tnXEnd; // Find the first extent that may get removed because of this new // extent. // (That's the one before the first existing extent // that's > (y, x-start).) oKey.m_tnY = a_tnY; oKey.m_tnXStart = a_tnXStart; itStart = m_setExtents.UpperBound (oKey); --itStart; // Does the found extent intersect the new extent? if (itStart != m_setExtents.End() && (*itStart).m_tnY == a_tnY && (*itStart).m_tnXEnd >= a_tnXStart) { // The found extent intersects with the new extent. // If the found extent contains the new extent, exit now; // the region already contains the new extent, and no // modifications are necessary. if ((*itStart).m_tnXEnd >= a_tnXEnd) return; // The found extent will be removed, and the inserted extent // will start in the same location (which we know is less than // or equal to the inserted extent's current start, thanks to // the search we did earlier). oInserted.m_tnXStart = (*itStart).m_tnXStart; // If the next extent in the region doesn't intersect the one // being added, we can modify this extent & be done, without // having to do a 2nd upper-bound search. itEnd = itStart; ++itEnd; if (itEnd == m_setExtents.End() || (*itEnd).m_tnY != (*itStart).m_tnY || (*itEnd).m_tnXStart > a_tnXEnd) { // We can modify this one extent & be done. Keep the // largest end. if (oInserted.m_tnXEnd < (*itStart).m_tnXEnd) oInserted.m_tnXEnd = (*itStart).m_tnXEnd; // Adjust the number of points we contain. m_tnPoints += (oInserted.m_tnXEnd - oInserted.m_tnXStart) - ((*itStart).m_tnXEnd - (*itStart).m_tnXStart); // Modify the extent. *itStart = oInserted; // Make sure we're intact. #ifdef DEBUG_SETREGION2D Invariant(); #endif // DEBUG_SETREGION2D // We're done. return; } } else { // The found extent doesn't intersect with the new extent. // Therefore, it won't get modified or removed by the addition // of the new extent. Move past it. ++itStart; } // Find the last extent that may get removed because of this new // extent. Start by searching for the first existing extent // that's > (y, x-end), then move back one.) oKey.m_tnY = a_tnY; oKey.m_tnXStart = a_tnXEnd; itEnd = m_setExtents.UpperBound (oKey); --itEnd; // Does the found extent intersect the new extent? if (itEnd != m_setExtents.End() && (*itEnd).m_tnY == a_tnY && (*itEnd).m_tnXStart <= a_tnXEnd) { // Yes. That extent will get replaced, and its endpoint may be // used by the inserted extent. if (oInserted.m_tnXEnd < (*itEnd).m_tnXEnd) oInserted.m_tnXEnd = (*itEnd).m_tnXEnd; } // In either case, move ahead again, to get back to the end of the // range we'll be removing. ++itEnd; // We now have the actual extent to be inserted, and the range of // existing extents to be removed. // Run through the extents to be removed, count the number of points // they represent, and subtract that from our separately-maintained // total number of points in the region. for (itHere = itStart; itHere != itEnd; ++itHere) m_tnPoints -= (*itHere).m_tnXEnd - (*itHere).m_tnXStart; // If the range to be replaced has at least one existing item, then // move the start of the range forward by one, and overwrite the // old start with the extent to be inserted, i.e. avoid a memory // allocation if at all possible. if (itStart != itEnd) { // Keep track of the location of the extent to be overwritten. itHere = itStart; // Move past the extent that'll be overwritten. ++itStart; // Remove all extents that were found to conflict with the one // being inserted. m_setExtents.Erase (itStart, itEnd); // Store the new extent. *itHere = oInserted; } // Otherwise, no extents are being removed, and we just insert the // new extent. else { #ifndef NDEBUG typename Extents::InsertResult oInsertResult = #endif // NDEBUG m_setExtents.Insert (a_reStatus, oInserted); if (a_reStatus != g_kNoError) return; assert (oInsertResult.m_bInserted); } // The region now contains this many more points. m_tnPoints += oInserted.m_tnXEnd - oInserted.m_tnXStart; // Make sure we're intact. #ifdef DEBUG_SETREGION2D Invariant(); #endif // DEBUG_SETREGION2D } // Merge this extent into the current region. // The new extent can't intersect the region in any way. template void SetRegion2D::Merge (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd) { Extent oExtent; // The new extent being added. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Generate the new extent. oExtent.m_tnY = a_tnY; oExtent.m_tnXStart = a_tnXStart; oExtent.m_tnXEnd = a_tnXEnd; // We will contain this many more points. m_tnPoints += a_tnXEnd - a_tnXStart; // Add this extent to the current region. #ifndef NDEBUG typename Extents::InsertResult oInsertResult = #endif // NDEBUG m_setExtents.Insert (a_reStatus, oExtent); if (a_reStatus != g_kNoError) return; assert (oInsertResult.m_bInserted); // Make sure the new extent is not contiguous with the extent // in front of & behind it. #ifndef NDEBUG { typename Extents::Iterator itNew, itOther; // Get the location of the newly moved extent. itNew = oInsertResult.m_itPosition; // Make sure it's not contiguous with the extent before it. itOther = itNew; --itOther; assert (itOther == m_setExtents.End() || (*itOther).m_tnY != (*itNew).m_tnY || (*itOther).m_tnXEnd < (*itNew).m_tnXStart); // Make sure it's not contiguous with the extent after it. itOther = itNew; ++itOther; assert (itOther == m_setExtents.End() || (*itNew).m_tnY != (*itOther).m_tnY || (*itNew).m_tnXEnd < (*itOther).m_tnXStart); } #endif // NDEBUG } // Merge the other region into ourselves, emptying the other region. template void SetRegion2D::Merge (SetRegion2D &a_rOther) { // Make sure we can move extents between regions. assert (CanMove (a_rOther)); // If the current region is empty, just move all the other region's // extents over at once. if (m_tnPoints == 0) { Move (a_rOther); } else { typename Extents::Iterator itHere, itNext; // Where we are in the other region's extents. // Run through the extents in the other region, move them to the // current region, and make sure the new extent isn't contiguous // with any of our existing extents. for (itHere = a_rOther.m_setExtents.Begin(); itHere != a_rOther.m_setExtents.End(); itHere = itNext) { // Get the location of the next extent. (We have to do this // because, after we call Move(), itHere isn't valid any // more.) itNext = itHere; ++itNext; // We will contain this many more points. m_tnPoints += (*itHere).m_tnXEnd - (*itHere).m_tnXStart; // Move this extent to the current region. #ifndef NDEBUG typename Extents::InsertResult oInsertResult = #endif // NDEBUG m_setExtents.Move (a_rOther.m_setExtents, itHere); assert (oInsertResult.m_bInserted); // Make sure the new extent is not contiguous with the // extent in front of & behind it. #ifndef NDEBUG { typename Extents::Iterator itNew, itOther; // Get the location of the newly moved extent. itNew = oInsertResult.m_itPosition; // Make sure it's not contiguous with the extent before // it. itOther = itNew; --itOther; assert (itOther == m_setExtents.End() || (*itOther).m_tnY != (*itNew).m_tnY || (*itOther).m_tnXEnd < (*itNew).m_tnXStart); // Make sure it's not contiguous with the extent after // it. itOther = itNew; ++itOther; assert (itOther == m_setExtents.End() || (*itNew).m_tnY != (*itOther).m_tnY || (*itNew).m_tnXEnd < (*itOther).m_tnXStart); } #endif // NDEBUG } } // Now the other region is empty. a_rOther.m_tnPoints = 0; } // Move the contents of the other region into the current region. // The current region must be empty. template void SetRegion2D::Move (SetRegion2D &a_rOther) { // Make sure we're allowed to do this. assert (CanMove (a_rOther)); // Make sure the current region is empty. assert (m_tnPoints == 0); // Move the extents. m_setExtents.Move (a_rOther.m_setExtents); // Now we have all their points. m_tnPoints = a_rOther.m_tnPoints; a_rOther.m_tnPoints = 0; } // Returns true if the other region's contents can be moved // into the current region. template bool SetRegion2D::CanMove (const SetRegion2D &a_rOther) const { // Return whether our extents can be moved. return m_setExtents.CanMove (a_rOther.m_setExtents); } // Make the current region represent the intersection between // itself and the other given region. template void SetRegion2D::Intersection (Status_t &a_reStatus, const SetRegion2D &a_rOther) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Not implemented yet. assert (false); a_reStatus = g_kInternalError; } // Subtract the given horizontal extent from the region. template void SetRegion2D::Subtract (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd, const SetRegion2D &a_rOther, typename Extents::ConstIterator &a_ritHere) { Extent oKey; // Used to search through the existing extents. typename Extents::Iterator itStart, itEnd; // The range of existing extents that gets removed because of // the subtraction of the new extent. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure they gave us a non-empty extent. assert (a_tnXStart < a_tnXEnd); // Make sure we're intact. #ifdef DEBUG_SETREGION2D Invariant(); #endif // DEBUG_SETREGION2D // Find the first extent that may get removed or modified by this // subtraction. (That's the first existing extent // that's >= (y, x-start).) oKey.m_tnY = a_tnY; oKey.m_tnXStart = a_tnXStart; itStart = m_setExtents.LowerBound (oKey); // Figure out if no existing extents intersect with the beginning // of the extent we're trying to subtract. if (itStart == m_setExtents.End() || (*itStart).m_tnY != a_tnY || (*itStart).m_tnXStart > a_tnXStart) { // The found extent is past any extent that the beginning would // intersect with. Move back one. --itStart; // See if this extent intersects the beginning of the range // we're trying to subtract. if (itStart == m_setExtents.End() || (*itStart).m_tnY != a_tnY || (*itStart).m_tnXEnd <= a_tnXStart) { // Move forward again. If that extent is on a different // line, or it starts after the removed range ends, then // leave: there's nothing to subtract. ++itStart; if (itStart == m_setExtents.End() || (*itStart).m_tnY != a_tnY || (*itStart).m_tnXStart >= a_tnXEnd) { // There's nothing to subtract. Find the first extent // in a_rOther that may intersect with one of our // extents. if (a_ritHere != a_rOther.m_setExtents.End() && itStart != m_setExtents.End()) { a_ritHere = a_rOther.m_setExtents.UpperBound (*itStart); --a_ritHere; } return; } } } // We found the first extent that may intersect with the range we're // trying to subtract. // Sanity check: make sure the found extent is on the same line as // the range we're trying to subtract. assert (itStart != m_setExtents.End() && (*itStart).m_tnY == a_tnY); // We have 4 cases: that extent has its beginning chopped off, // its end chopped off, gets removed completely, or gets broken in // half. if ((*itStart).m_tnXStart >= a_tnXStart) { if ((*itStart).m_tnXEnd > a_tnXEnd) { // The found extent gets its beginning cut off, and then // we're done. m_tnPoints -= a_tnXEnd - (*itStart).m_tnXStart; (*itStart).m_tnXStart = a_tnXEnd; return; } else { // The found extent gets removed completely. // Fall through to deal with the end of the range being // subtracted. } } else { if ((*itStart).m_tnXEnd > a_tnXEnd) { // The found extent gets broken in half. Extent oInserted; // The second half of the broken extent. // Prepare to break the extent in half, by generating the // second half of the extent. oInserted.m_tnY = a_tnY; oInserted.m_tnXStart = a_tnXEnd; oInserted.m_tnXEnd = (*itStart).m_tnXEnd; // Modify the found extent so that it becomes the first // half of the broken extent. This is safe because it // doesn't affect the consistency of the region. (*itStart).m_tnXEnd = a_tnXStart; // Insert the second half of the broken extent. { #ifndef NDEBUG typename Extents::InsertResult oInsertResult = #endif // NDEBUG m_setExtents.Insert (a_reStatus, oInserted); if (a_reStatus != g_kNoError) return; assert (oInsertResult.m_bInserted); } // We removed this many points. m_tnPoints -= a_tnXEnd - a_tnXStart; // We're done. return; } else { // The found extent gets its end cut off. // Remember the end of the found extent. INDEX nOldEnd = (*itStart).m_tnXEnd; // Cut off the end of the found extent. m_tnPoints -= (*itStart).m_tnXEnd - a_tnXStart; (*itStart).m_tnXEnd = a_tnXStart; // If the extent being subtracted ends at the same place // as this found extent, then we're done. if (nOldEnd == a_tnXEnd) return; // Move forward. ++itStart; // If the next extent starts after the end of this subtraction, // we're done. // (This seemed like a good idea, but actualy seems to make it // run slightly slower in practice! Argh.) #if 0 assert (itStart == m_setExtents.End() || (*itStart).m_tnY >= a_tnY); if (itStart == m_setExtents.End() || (*itStart).m_tnY > a_tnY || ( /* (*itStart).m_tnY == a_tnY && */ (*itStart).m_tnXStart > a_tnXEnd)) return; #endif // Fall through to deal with the end of the range being // subtracted. } } // Find the last extent that may get removed or modified by this // subtraction. (That's the first existing extent // that's >= (y, x-end).) oKey.m_tnY = a_tnY; oKey.m_tnXStart = a_tnXEnd; itEnd = m_setExtents.LowerBound (oKey); // If that put us past any extent we'll have to remove, we can just // skip to the end, where the range we located will be removed. // Otherwise, we have to figure out the implications of the end of // the subtracted range. if (itEnd == m_setExtents.End() || (*itEnd).m_tnY != a_tnY || (*itEnd).m_tnXStart > a_tnXEnd) { // Move back one. --itEnd; // If that didn't put us out of the range of existing extents // that are getting removed, we have 2 cases: either the entire // extent is getting removed, or its beginning is getting // chopped off. if (itEnd != m_setExtents.End() && (*itEnd).m_tnY == a_tnY) { // How much of this extent is getting removed? if ((*itEnd).m_tnXEnd <= a_tnXEnd) { // The entire extent is getting removed. Move forward // again. ++itEnd; } else { // The found extent's beginning is getting chopped off. // (The search above ensures that this extent starts // before the end of the range being removed, but we // check our sanity anyway.) assert ((*itEnd).m_tnXStart < a_tnXEnd); m_tnPoints -= a_tnXEnd - (*itEnd).m_tnXStart; (*itEnd).m_tnXStart = a_tnXEnd; } } } // Loop through the range of extents to remove, subtract their // contribution to our point total. for (typename Extents::Iterator itHere = itStart; itHere != itEnd; itHere++) { m_tnPoints -= (*itHere).m_tnXEnd - (*itHere).m_tnXStart; } // Remove any range of extents found. m_setExtents.Erase (itStart, itEnd); // Make sure we're intact. #ifdef DEBUG_SETREGION2D Invariant(); #endif // DEBUG_SETREGION2D } // Subtract the given horizontal extent from the region, with the given // offset. template void SetRegion2D::SubtractWithOffset (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd, INDEX a_tnXOffset, INDEX a_tnYOffset, const SetRegion2D &a_rOther, typename Extents::ConstIterator &a_ritHere) { Extent oKey; // Used to search through the existing extents. typename Extents::Iterator itStart, itEnd; // The range of existing extents that gets removed because of // the subtraction of the new extent. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure they gave us a non-empty extent. assert (a_tnXStart < a_tnXEnd); // Make sure we're intact. #ifdef DEBUG_SETREGION2D Invariant(); #endif // DEBUG_SETREGION2D // Find the first extent that may get removed or modified by this // subtraction. (That's the first existing extent // that's >= (y, x-start).) oKey.m_tnY = a_tnY + a_tnYOffset; oKey.m_tnXStart = a_tnXStart + a_tnXOffset; itStart = m_setExtents.LowerBound (oKey); // Figure out if no existing extents intersect with the beginning // of the extent we're trying to subtract. if (itStart == m_setExtents.End() || (*itStart).m_tnY != a_tnY + a_tnYOffset || (*itStart).m_tnXStart > a_tnXStart + a_tnXOffset) { // The found extent is past any extent that the beginning would // intersect with. Move back one. --itStart; // See if this extent intersects the beginning of the range // we're trying to subtract. if (itStart == m_setExtents.End() || (*itStart).m_tnY != a_tnY + a_tnYOffset || (*itStart).m_tnXEnd <= a_tnXStart + a_tnXOffset) { // Move forward again. If that extent is on a different // line, or it starts after the removed range ends, then // leave: there's nothing to subtract. ++itStart; if (itStart == m_setExtents.End() || (*itStart).m_tnY != a_tnY + a_tnYOffset || (*itStart).m_tnXStart >= a_tnXEnd + a_tnXOffset) { // There's nothing to subtract. Find the first extent // in a_rOther that may intersect with one of our // extents. if (a_ritHere != a_rOther.m_setExtents.End() && itStart != m_setExtents.End()) { oKey.m_tnY = (*itStart).m_tnY - a_tnYOffset; oKey.m_tnXStart = (*itStart).m_tnXStart - a_tnXOffset; a_ritHere = a_rOther.m_setExtents.UpperBound (oKey); --a_ritHere; } return; } } } // We found the first extent that may intersect with the range we're // trying to subtract. // Sanity check: make sure the found extent is on the same line as // the range we're trying to subtract. assert (itStart != m_setExtents.End() && (*itStart).m_tnY == a_tnY + a_tnYOffset); // We have 4 cases: that extent has its beginning chopped off, // its end chopped off, gets removed completely, or gets broken in // half. if ((*itStart).m_tnXStart >= a_tnXStart + a_tnXOffset) { if ((*itStart).m_tnXEnd > a_tnXEnd + a_tnXOffset) { // The found extent gets its beginning cut off, and then // we're done. m_tnPoints -= (a_tnXEnd + a_tnXOffset) - (*itStart).m_tnXStart; (*itStart).m_tnXStart = a_tnXEnd + a_tnXOffset; return; } else { // The found extent gets removed completely. // Fall through to deal with the end of the range being // subtracted. } } else { if ((*itStart).m_tnXEnd > a_tnXEnd + a_tnXOffset) { // The found extent gets broken in half. Extent oInserted; // The second half of the broken extent. // Prepare to break the extent in half, by generating the // second half of the extent. oInserted.m_tnY = a_tnY + a_tnYOffset; oInserted.m_tnXStart = a_tnXEnd + a_tnXOffset; oInserted.m_tnXEnd = (*itStart).m_tnXEnd; // Modify the found extent so that it becomes the first // half of the broken extent. This is safe because it // doesn't affect the consistency of the region. (*itStart).m_tnXEnd = a_tnXStart + a_tnXOffset; // Insert the second half of the broken extent. { #ifndef NDEBUG typename Extents::InsertResult oInsertResult = #endif // NDEBUG m_setExtents.Insert (a_reStatus, oInserted); if (a_reStatus != g_kNoError) return; assert (oInsertResult.m_bInserted); } // We removed this many points. m_tnPoints -= a_tnXEnd - a_tnXStart; // We're done. return; } else { // The found extent gets its end cut off. // Remember the end of the found extent. INDEX nOldEnd = (*itStart).m_tnXEnd + a_tnXOffset; // Cut off the end of the found extent. m_tnPoints -= (*itStart).m_tnXEnd - (a_tnXStart + a_tnXOffset); (*itStart).m_tnXEnd = a_tnXStart + a_tnXOffset; // If the extent being subtracted ends at the same place // as this found extent, then we're done. if (nOldEnd == a_tnXEnd + a_tnXOffset) return; // Move forward, and fall through to deal with the end of // the range being subtracted. ++itStart; } } // Find the last extent that may get removed or modified by this // subtraction. (That's the first existing extent // that's >= (y, x-end).) oKey.m_tnY = a_tnY + a_tnYOffset; oKey.m_tnXStart = a_tnXEnd + a_tnXOffset; itEnd = m_setExtents.LowerBound (oKey); // If that put us past any extent we'll have to remove, we can just // skip to the end, where the range we located will be removed. // Otherwise, we have to figure out the implications of the end of // the subtracted range. if (itEnd == m_setExtents.End() || (*itEnd).m_tnY != a_tnY + a_tnYOffset || (*itEnd).m_tnXStart > a_tnXEnd + a_tnXOffset) { // Move back one. --itEnd; // If that didn't put us out of the range of existing extents // that are getting removed, we have 2 cases: either the entire // extent is getting removed, or its beginning is getting // chopped off. if (itEnd != m_setExtents.End() && (*itEnd).m_tnY == a_tnY + a_tnYOffset) { // How much of this extent is getting removed? if ((*itEnd).m_tnXEnd <= a_tnXEnd + a_tnXOffset) { // The entire extent is getting removed. Move forward // again. ++itEnd; } else { // The found extent's beginning is getting chopped off. // (The search above ensures that this extent starts // before the end of the range being removed, but we // check our sanity anyway.) assert ((*itEnd).m_tnXStart < a_tnXEnd + a_tnXOffset); m_tnPoints -= (a_tnXEnd + a_tnXOffset) - (*itEnd).m_tnXStart; (*itEnd).m_tnXStart = a_tnXEnd + a_tnXOffset; } } } // Loop through the range of extents to remove, subtract their // contribution to our point total. for (typename Extents::Iterator itHere = itStart; itHere != itEnd; itHere++) { m_tnPoints -= (*itHere).m_tnXEnd - (*itHere).m_tnXStart; } // Remove any range of extents found. m_setExtents.Erase (itStart, itEnd); // Make sure we're intact. #ifdef DEBUG_SETREGION2D Invariant(); #endif // DEBUG_SETREGION2D } // Subtract the given horizontal extent from the region. template void SetRegion2D::Subtract (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd) { // Defer to our private helper function. ConstIterator itUnused = m_setExtents.End(); Subtract (a_reStatus, a_tnY, a_tnXStart, a_tnXEnd, *this, itUnused); } // Subtract the other region from the current region, i.e. // remove from the current region any areas that exist in the // other region. template void SetRegion2D::Subtract (Status_t &a_reStatus, const SetRegion2D &a_rOther) { typename Extents::ConstIterator itHere, itNext; // Where we are in the other region's extents. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Run through the extents in the other region, subtract them from // the current region. for (itHere = a_rOther.m_setExtents.Begin(); itHere != a_rOther.m_setExtents.End(); itHere = itNext) { // Subtract this extent from the current region. itNext = itHere; Subtract (a_reStatus, (*itHere).m_tnY, (*itHere).m_tnXStart, (*itHere).m_tnXEnd, a_rOther, itNext); if (a_reStatus != g_kNoError) return; // If this region is now empty, leave. if (m_setExtents.Size() == 0) return; // If there was no intersection, then itNext has the location of // the first extent in a_rOther that intersects one of our // extents. Otherwise, move forward. if (itHere == itNext) ++itNext; } } // Subtract the other region from the current region, but offset // the other region by the given amounts. template void SetRegion2D::SubtractWithOffset (Status_t &a_reStatus, const SetRegion2D &a_rOther, INDEX a_tnXOffset, INDEX a_tnYOffset) { typename Extents::ConstIterator itHere, itNext; // Where we are in the other region's extents. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Run through the extents in the other region, subtract them from // the current region. for (itHere = a_rOther.m_setExtents.Begin(); itHere != a_rOther.m_setExtents.End(); itHere = itNext) { // Subtract this extent from the current region. itNext = itHere; SubtractWithOffset (a_reStatus, (*itHere).m_tnY, (*itHere).m_tnXStart, (*itHere).m_tnXEnd, a_tnXOffset, a_tnYOffset, a_rOther, itNext); if (a_reStatus != g_kNoError) return; // If this region is now empty, leave. if (m_setExtents.Size() == 0) return; // If there was no intersection, then itNext has the location of // the first extent in a_rOther that intersects one of our // extents. Otherwise, move forward. if (itHere == itNext) ++itNext; } } // Move all extents by the given offset. template void SetRegion2D::Offset (INDEX a_tnXOffset, INDEX a_tnYOffset) { typename Extents::Iterator itHere; // Where we're offsetting an extent. // Run through all the extents, offset them. (NOTE: during this // operation, the skip-list's sorting is broken, but we don't // leave it broken. for (itHere = m_setExtents.Begin(); itHere != m_setExtents.End(); ++itHere) { Extent &rExtent = *itHere; rExtent.m_tnY += a_tnYOffset; rExtent.m_tnXStart += a_tnXOffset; rExtent.m_tnXEnd += a_tnXOffset; } } // Returns true if the region contains the given point. template bool SetRegion2D::DoesContainPoint (INDEX a_tnY, INDEX a_tnX) { Extent oKey; ConstIterator itKey; // Used to search for the extent that would contain this point. // Find the extent that would contain this point. oKey.m_tnY = a_tnY; oKey.m_tnXStart = a_tnX; itKey = m_setExtents.UpperBound (oKey); --itKey; // Return whether it does. if (itKey != m_setExtents.End() && (*itKey).m_tnY == a_tnY && a_tnX >= (*itKey).m_tnXStart && a_tnX < (*itKey).m_tnXEnd) return true; else return false; } // Returns true if the region contains the given point. template bool SetRegion2D::DoesContainPoint (INDEX a_tnY, INDEX a_tnX, ConstIterator &a_ritHere) { Extent oKey; ConstIterator itKey; // Used to search for the extent that would contain this point. // Find the extent that would contain this point. oKey.m_tnY = a_tnY; oKey.m_tnXStart = a_tnX; itKey = m_setExtents.UpperBound (oKey); --itKey; // Pass it back to our caller. a_ritHere = itKey; // Return whether it does. if (itKey != m_setExtents.End() && (*itKey).m_tnY == a_tnY && a_tnX >= (*itKey).m_tnXStart && a_tnX < (*itKey).m_tnXEnd) return true; else return false; } // Flood-fill the current region. template template void SetRegion2D::FloodFill (Status_t &a_reStatus, CONTROL &a_rControl, bool a_bVerify, bool a_bExpand) { typename CONTROL::ConstIterator itExtent; // An extent we're examining. Extent oFoundExtent; // An extent we found to be part of the region. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make the compiler shut up. oFoundExtent.m_tnXStart = oFoundExtent.m_tnXEnd = 0; // How we set up depends on whether we're to verify all existing // region extents. if (a_bVerify) { // The to-do-list becomes the current region, and we empty // out the current region too. a_rControl.m_oAlreadyDone.Clear(); if (a_rControl.m_oToDo.CanMove (*this)) { // Grab the extents right out of the current region. a_rControl.m_oToDo.Clear(); a_rControl.m_oToDo.Move (*this); } else { // Copy the extents from the current region, then empty it. a_rControl.m_oToDo.Assign (a_reStatus, *this); if (a_reStatus != g_kNoError) return; Clear(); } } else { // The already-done list starts with the region, i.e. every // extent already known to be in the region can avoid getting // tested. a_rControl.m_oAlreadyDone.Assign (a_reStatus, *this); if (a_reStatus != g_kNoError) return; // Start the to-do list with a border around all the extents in // the region. a_rControl.m_oToDo.MakeBorder (a_reStatus, *this); if (a_reStatus != g_kNoError) return; } // Now pull each extent out of the to-do list. Determine which // sub-extents are part of the region. Add those found extents // to the region. Then add all extent surrounding the found extents // to the to-do-next list. itExtent = a_rControl.m_oToDo.Begin(); while (itExtent != a_rControl.m_oToDo.End()) { bool bStartedExtent; // true if we've started finding an extent. INDEX tnX; // Where we're looking for extents. // Get the extent, converting the type if necessary. Extent oExtent; oExtent.m_tnY = (*itExtent).m_tnY; oExtent.m_tnXStart = (*itExtent).m_tnXStart; oExtent.m_tnXEnd = (*itExtent).m_tnXEnd; // We're about to check this extent. Put it in the // already-checked list now. a_rControl.m_oAlreadyDone.Union (a_reStatus, oExtent.m_tnY, oExtent.m_tnXStart, oExtent.m_tnXEnd); if (a_reStatus != g_kNoError) return; // If this extent shouldn't be considered, skip it. if (!a_rControl.ShouldUseExtent (oExtent)) goto nextExtent; // Make sure our client left us with a valid extent. assert (oExtent.m_tnXStart < oExtent.m_tnXEnd); // Run through the pixels described by this extent, see if // they can be added to the region, and remember where to // search next. oFoundExtent.m_tnY = oExtent.m_tnY; bStartedExtent = false; for (tnX = oExtent.m_tnXStart; tnX <= oExtent.m_tnXEnd; ++tnX) { // Is this point in the region? if (tnX < oExtent.m_tnXEnd && a_rControl.IsPointInRegion (tnX, oExtent.m_tnY)) { // This point is in the region. Start a new extent // if we didn't have one already, and add the point // to it. if (!bStartedExtent) { oFoundExtent.m_tnXStart = tnX; bStartedExtent = true; } oFoundExtent.m_tnXEnd = tnX + 1; } // This point is not in the region. Any extent we're // building is done. else if (bStartedExtent) { // Add this extent to the region. Union (a_reStatus, oFoundExtent.m_tnY, oFoundExtent.m_tnXStart, oFoundExtent.m_tnXEnd); if (a_reStatus != g_kNoError) return; // Now add all surrounding extents to the to-do-next list. if (a_bExpand) { a_rControl.m_oNextToDo.UnionSurroundingExtents (a_reStatus, oFoundExtent.m_tnY, oFoundExtent.m_tnXStart, oFoundExtent.m_tnXEnd); if (a_reStatus != g_kNoError) return; } // Look for another extent. bStartedExtent = false; } } nextExtent: // Move to the next extent. ++itExtent; // If the to-do list needs to be replenished, do so. if (itExtent == a_rControl.m_oToDo.End()) { // Replenish the to-do list. a_rControl.m_oNextToDo.Subtract (a_reStatus, a_rControl.m_oAlreadyDone); if (a_reStatus != g_kNoError) return; a_rControl.m_oToDo.Clear(); a_rControl.m_oToDo.Move (a_rControl.m_oNextToDo); // Start over at the beginning. itExtent = a_rControl.m_oToDo.Begin(); } } } // Make the current region represent the border of the other // region, i.e. every pixel that borders the region but isn't // already in the region. template template void SetRegion2D::MakeBorder (Status_t &a_reStatus, const REGION &a_rOther) { typename REGION::ConstIterator itExtent; // Used to loop through the other region's extents. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Start with an empty region. Clear(); // For every extent in the other region, add every surrounding // extent. That creates a region that looks like the other region, // but also contains the border we're after. for (itExtent = a_rOther.Begin(); itExtent != a_rOther.End(); ++itExtent) { UnionSurroundingExtents (a_reStatus, (*itExtent).m_tnY, (*itExtent).m_tnXStart, (*itExtent).m_tnXEnd); if (a_reStatus != g_kNoError) return; } // Finally, subtract the other region. That punches a hole in us, // and creates the border region we're after. Subtract (a_reStatus, a_rOther); if (a_reStatus != g_kNoError) return; } // Add all extents surrounding the given extent. Used by FloodFill(). template void SetRegion2D::UnionSurroundingExtents (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Add the extent above this one. Union (a_reStatus, a_tnY - 1, a_tnXStart, a_tnXEnd); if (a_reStatus != g_kNoError) return; // Add the extent in the middle. Union (a_reStatus, a_tnY, a_tnXStart - 1, a_tnXEnd + 1); if (a_reStatus != g_kNoError) return; // Add the extent below this one. Union (a_reStatus, a_tnY + 1, a_tnXStart, a_tnXEnd); if (a_reStatus != g_kNoError) return; } #ifndef NDEBUG template uint32_t SetRegion2D::sm_ulInstances; #endif // NDEBUG // Default constructor. Must be followed by a call to Init(). template SetRegion2D::FloodFillControl::FloodFillControl (Allocator &a_rAllocator) : m_oToDo (a_rAllocator), m_oAlreadyDone (a_rAllocator), m_oNextToDo (a_rAllocator) { // Nothing to do. } // Initializing constructor. template SetRegion2D::FloodFillControl::FloodFillControl (Status_t &a_reStatus, Allocator &a_rAllocator) : m_oToDo (a_rAllocator), m_oAlreadyDone (a_rAllocator), m_oNextToDo (a_rAllocator) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Initialize ourselves. Init (a_reStatus); if (a_reStatus != g_kNoError) return; } // Initializer. Must be called on default-constructed objects. template void SetRegion2D::FloodFillControl::Init (Status_t &a_reStatus) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Initialize our helper regions. m_oToDo.Init (a_reStatus); if (a_reStatus != g_kNoError) return; m_oAlreadyDone.Init (a_reStatus); if (a_reStatus != g_kNoError) return; m_oNextToDo.Init (a_reStatus); if (a_reStatus != g_kNoError) return; } // Purge all internally-allocated memory. template void SetRegion2D::FloodFillControl::Purge (void) { // Get rid of the contents of our internal regions. // (These aren't cleared at the end of FloodFill() because we'd // rather reuse existing region-extent allocations, since that // involves less allocator thrashing and region-extent insertions.) m_oToDo.Clear(); m_oAlreadyDone.Clear(); m_oNextToDo.Clear(); // Now purge internally-allocated memory. m_oToDo.Purge(); m_oAlreadyDone.Purge(); m_oNextToDo.Purge(); } #endif // __SETREGION2D_H__ mjpegtools-2.1.0/y4mdenoise/implementation.html0000644000175000017500000005317411173460062022216 0ustar glowwormglowworm Design and implementation of the new denoiser

Design and implementation of the new denoiser

In theory, the design of the denoiser is pretty simple; getting it to perform was the hard part.

It maintains a list of the last several frames, called reference frames. Each reference frame is composed of reference pixels, which accumulate the values of several pixels. Every time a pixel in one frame is proven to be a moved instance of a pixel in another frame, the reference-pixel incorporates its value, and produces an average value for the pixel. The oldest reference frame, therefore, gets a pretty good idea of the real value of every pixel, but of course output is delayed by the number of reference frames.

It compares every pixel in the current frame with all pixels in the previous frame, within a given search-radius, and any pixels that are equal within the given error tolerance are assumed to be the same pixel. It builds contiguous regions of matched pixels, with the motion vector that's common to the region.

If there are too many matches for a particular area of the image, or if the largest contiguous match in the area is too large, it's applied to the image right then, and then searching continues. Applying a region means to flood-fill the region (to make it the largest size possible, and to flesh out its borders to pixel accuracy), then hooking up the corresponding reference-frame pixels to the new frame at their new location, and incorporating the values of all the new pixels into the corresponding reference pixels. Doing this before the end of searching the frame means the affected areas don't have to be part of the search any more, helping to reduce the amount of work needed to search the rest of the frame.

At the end of the frame, matches are applied to the new frame, from the largest to the smallest, discounting any areas that have already been resolved. Any new-frame pixels not resolved by now are considered to be new information, and a new reference-pixel is generated for each one.

The search is not actually done one pixel at a time; it's done in terms of pixel groups. An entire pixel-group has to match for any match to be found, but all possible pixel-groups are tested (i.e. all possible overlaps are checked). Using pixel-groups helps to establish a minimum standard for what may be considered a match, in order to avoid finding lots of really small (and really useless) matches. The flood-fill still extends the matches out to pixel accuracy, so the only details that can't be found by motion-detection are the ones smaller than a pixel-group, which is not a bad sacrifice for performance's sake.


Table of contents:

Overview

main.c parses command-line options and the YUV stream header. newdenoise.cc converts between YUV format and the denoiser's internal format, and calls the denoiser. MotionSearcher.hh is the denoiser's top-level file. SearchWindow.hh and SearchBorder.hh are two high-level pieces of the denoiser that were broken out into their own classes, for use in other contexts. ReferenceFrame.hh contains the definitions for pixels, reference pixels, and reference frames. Region2D.hh is the base class for 2-dimensional region classes; SetRegion2D.hh implements a region using a Set of horizontal extents, and BitmapRegion2D.hh uses an array of integers to implement a bitmap. Set.hh is much like the STL "set" class, except that it's based on SkipList.hh. Allocator.hh, DoublyLinkedList.hh, Limits.hh, Status_t.h, and TemplateLib.hh contain other basic definitions, most of which should be standardly available; I'm just not sure they're standardly available on all supported platforms.

The denoiser classes are highly templated and highly reconfigurable; newdenoise.cc uses them in a way suited to YUV420P video. Intensity pixels are one 8-bit unsigned integer, color pixels are two 8-bit unsigned integers, intensity pixel-groups are 4x2, color pixel-groups are 2x2, intensity is denoised separately from color, and the search-radius used for color is proportional to the relative size of the intensity and color planes (and may, in effect, be rectangular).

Implementation

newdenoise.cc gives a good top-level view of how to use the denoiser for YUV420P video. Although the top-level class of the denoiser is MotionSearcher, a small army of classes is responsible for implementing all the necessary pieces.

SkipList, Set

SkipList is a highly optimized version of the famous probabilistically-balanced logarithmic-complexity sorted list structure. Skip lists are well-described in other documents. Note that this skip-list uses the "fix the dice" and "search finger" extensions described in the literature, and its p value is 1/e, which maximizes speed & causes nodes to have an average of 1.71 forward pointers. (A tree node would have to have 2 pointers, one for left and one for right, so a skip-list is more space-efficient than a tree structure also.)

One big advantage of skip-lists over tree structures, given the way the denoiser uses them, is that iterator forward/backward operations are small-constant complexity; they're implemented by a single pointer dereference. The typical tree-structure iterator forward/backward is logarithmic. Iterator forward/backward is used constantly throughout the denoiser.

Set is much like STL's set class, except that it's based on SkipList.

Region2D, SetRegion2D, BitmapRegion2D

SetRegion2D was the first region class written for the denoiser; later, Region2D and SetRegion2D were split into two classes, and BitmapRegion2D was made a subclass of Region2D. It was not a perfect separation, and Region2D remains a sketch of what I'd like to see, rather than a completed product. I could solve its problem using virtual methods, but that would prevent a lot of function-inlining from happening, and for performance reasons I don't want to do that.

SetRegion2D uses Set to implement regions as a set of horizontal extents, i.e. as y/x-start/x-end triplets. Quite a bit of work went into writing efficient union/subtraction methods.

BitmapRegion2D uses an array of integers, treated like a bit field, to implement regions. It's faster to use them in some cases, though they're a lot less memory-efficient than SetRegion2D, and have to be created with a maximum size.

Pixel, ReferencePixel, ReferenceFrame

The Pixel class is templated with a numeric type for storing pixel values, the number of dimensions in the pixel's value, and a numeric type to use when doing tolerance calculations. The rule of thumb is, the tolerance type should be able to hold the value of two pixel-value types multiplied together.

For YUV420P video, a Y pixel is Pixel<uint_8,1,int32_t> and a color (i.e. CbCr) pixel is Pixel<uint8_t,2,int32_t>.

The Pixel class contains methods to get and set the value of pixels, and to compare two pixels within a given tolerance. It also contains methods to generate tolerance values from integers, in case the pixel type has special rules. (For instance, the tolerance value for a color pixel is the square of its integer counterpart, since CbCr color is 2-dimensional.)

The ReferencePixel is templated much like the Pixel class. It holds a sum of pixel values, and the number of pixel values summed so far. It also counts the number of reference-frames that point to it. It's intended to represent a single pixel that's found to exist over several frames, and to produce an average value for the pixel, so as to smooth away errors.

The ReferenceFrame is a rectangular array of ReferencePixels, representing each frame and the parts of the image that it has in common with other frames.

MotionSearcher, SearchWindow, SearchBorder

OK, so much for the easy part.

MotionSearcher maintains a circular list of ReferenceFrames. To make space for a new frame, the oldest frame is returned to the client.

AddFrame() is responsible for processing new frames. It does so in several stages. First, it looks for pixels that haven't moved, i.e. new pixels whose corresponding reference-pixels are within the error tolerance. That resolves most of the average frame.

Next, it detects moved areas, i.e. parts of the new frame that match parts of the previous frame except that they've moved.

It could iterate through the frame in any order, but to keep the implementation of SearchWindow and SearchBorder simple and efficient, it iterates through the frame in a zigzag pattern, i.e. starting at the upper-left corner, it moves right to the edge, then down a line, then left to the edge, then down a line, and so on to the end of the frame.

The search-window consists of the reference-frame's pixels, partitioned into search-window cells. Each cell contains a pixel-group (i.e. a rectangular array of pixels, containing the minimum pixel pattern that can be searched for). The pixel-groups in each cell overlap other cells; although the motion-search is done in terms of pixel-groups, it still looks at all all possible combinations of pixels that could form a pixel-group.

The pixel-sorter is a tree structure that partitions pixel-groups (actually, search-window cells, which contain a pixel-group). The total number of dimensions of a pixel-group is the number of pixels in the group, times the dimension of a pixel. For the YUV420 implementation, 4x2 pixel-groups are used for intensity pixels, which consist of 1 dimension, for a total of 8, and 2x2 pixel groups are used for color pixels, which consist of 2 dimensions, again for a total of 8. Partitioning n dimensions requires 2n branches per tree node; in this example, that's 256. (So if the pixel-sorter tree is well-balanced, then descending to a child branch cuts out all but 1/256 of the remaining pixel-groups, which is supposed to make searching for matching pixel-groups very efficient.) Search-window cells are inserted into the pixel-sorter tree, and descend into child branches based on their value. But if any of the pixel-group's pixel dimension values are within the error tolerance of the split-point for that dimension in the current pixel-sorter branch node, then that pixel-group won't fit neatly into any of the children nodes, and thus the search-window cell has to stay at that level of the tree. (Alternately, a copy of it could be placed in multiple children, but this design opts not to do that.) Each pixel-sorter branch node maintains a doubly-linked list of search-window cells that are attached to it. As an optimization, once a search-window cell is inserted into the pixel-sorter, that result is used for the rest of the frame, as the search-window cell is added to and removed from the pixel-sorter, depending on whether that search-window cell is within the search radius of the current new-frame pixel-group.

To look for matches between the current pixel-group from the new frame, and all pixel-groups from the previous frame within the search radius, one just matches the current pixel-group to every search-window cell attached to the pixel-sorter branch nodes, and descend the tree according to the new pixel-group's values. (One optimization is possible here: If the search-window cell was forced to stop at that level of the pixel-sorter because one of its pixel values was within the tolerance of the split value of that pixel-sorter branch node, and none of the current pixel-group's pixel values are within twice the tolerance of the split value of that pixel-sorter branch node, then we can save time and avoid the comparison, for no search-window cell that had to stop at that level could possibly intersect the new pixel-group. This especially helps in the presence of low error thresholds.)

As matches are found, the search-border builds contiguous regions of matches that all have the same motion-vector. (The "border" is the border between the searched area and the not-yet-searched area.) It's designed to move through the regions of matches in a zigzag pattern, and constantly maintain a list of all regions that would be contiguous with the current new-frame pixel-group. When a match is found, all such regions with the same motion-vector are now contiguous, once the current pixel-group's area is added.

The search-border is implemented by sets of startpoints/endpoints. Every horizontal extent (that could potentially intersect a new-frame pixel-group) of every region under construction along the border is represented in the set of startpoints/endpoints. The search-border also has two arrays of set iterators, one for startpoints, one for endpoints. As the search zig-zags across the new frame, these two arrays of iterators keep track of all regions that will be contiguous with the current new-frame pixel-group, and all regions that are no longer contiguous with the current new-frame pixel-group; by doing this, it's very efficient to maintain the set of border regions that would be contiguous with the current new-frame pixel-group.

The general idea is to analyze the entire frame like this, then run through the found regions from largest to smallest, and apply them to the new frame. This can be a lot of data, too much in fact. To limit the search to a reasonable complexity, two throttles exist -- one on the number of matches in the area of the current pixel-group, and one on the size of the the largest match in the area of the current pixel-group. If there are too many regions in the area, or if the biggest region in the area is too large, then the best region found so far is chosen, all other regions in the area are thrown away, and that best region is applied to the new frame right then. This will eliminate pixel-groups from consideration in the search-window and pixel-sorter, which will save time in the search. This will also resolve new-frame pixels; only pixel-groups that contain nothing but unresolved pixels can be searched for in the pixel-sorter, which also saves time in the remainder of the search. Only after the entire frame is analyzed are regions applied from largest to smallest.

Before a match is applied to the new frame, it's flood-filled in order to resolve its entire extent. Searching is done in terms of pixel-groups, so it won't be able to find any detail that's smaller than a pixel-group. Also, the region may not have been completed, if it was chosen because a throttle value was exceeded, so its full extent is not known. Plus, parts of that match may have already been resolved. The flood-fill takes care of all of these situations.

Any pixels not found by the above searches are declared to be new information, and new reference-pixels are allocated for all such new-frame pixels.

The whole point of this design is to use as many high-level-design features as possible to reduce the amount of work necessary to perform the job. It attempts to accomplish this with a heavy reliance on data structures over more mathematical algorithms, a drive to locate sub-linear/sub-quadratic algorithms for common tasks (e.g. the pixel-sorter tree, which reduced quadratic to logarithmic, and the iterator arrays in the search-border, which reduced logarithmic to small-constant), and to use data structure design to understand the problem in ways that directly lead to efficient implementations.

Version 1

The above discussion describes the intent of the first version of the denoiser (which I'm calling version 0). However, the very last high-level change I made to it, right before releasing it under GPL, was defective! In effect, the match-count throttle was always 1, and the best match was applied every pixel-group! It was intended to be a performance increase, and it was, but obviously it broke the code...except that this bugged change also vastly increased the quality! There is every reason in the world to believe that such a bug should have broken the denoiser's quality, except that it didn't. What a stroke of luck!

I decided to take the implications of this accidental discovery to the next logical level. Before, I wouldn't have believed that the best match could be found without amassing a large list of possibilities from several pixel-group searches. Now, each match found is flood-filled, and the first one to exceed the match-size throttle is applied to the image right then and there, and all other possibilities aren't considered. So there is no big list of regions to try at the end.

This version performed better than the bugged version, which is surprising enough, but the quality was vastly improved too.

Parallel processing was added at this time too. Color can be denoised in a thread separate from intensity denoising, and reading/writing frames can be moved into separate threads too.

Version 2

If match-size-throttling is in use (which is usually is), now it picks the largest such match, instead of the first match that's larger than the throttle size. This led to a pretty serious increase in quality!

Parallel processing was modified so that the reader/writer threads can be used independently of the denoiser threads. This may not be very useful, but there was no good reason to prevent it.

Future Extensions

The motion-detector is highly parallel, and a better multi-threaded version should be written. So far, color and intensity can be analyzed separately. But a thread could conceivably denoise one half of the remaining area of an image plane. The pixel-sorter would have to become its own class for this to work, since there'd now be more than one per search-window, and the search-window would have to keep pixel-sorters from colliding with each other (i.e. the areas being searched by each can't overlap). Also, depending on how efficient the thread-synchronization methods are, the pixel-sorter could feed results to the flood-filling stage. Perhaps both approaches can be taken. Anything that allows the denoiser to fill up processors is probably worth trying.

The motion-detector should probably be able to find matches in more than one previous frame. I'd probably want to avoid later-frame matches that occur in earlier frames, for efficiency's sake.

The search-border should allow the insertion of new regions. It would need a method, implemented somewhat like AddNewMatch(), to generate a startpoint/endpoint for every horizontal extent in the region that intersected the border area. This could be used to make a ChooseBestActiveRegion() that eliminated flood-filled areas from the other regions on the border and then put those regions back into the border. I don't know if this would speed things up, though.

I think the search-border can be used to implement removal of transient phenomena, e.g. film lint/scratches, LaserDisc rot, analog-broadcast static, etc. After the new frame has had motion detection run on it, look at the 2nd-to-oldest frame, and build contiguous regions of pixels that have the same reference count. (Film lint/scratches will be limited to 1 reference count; I think LaserDisc rot can extend over several frames.) If a region has the right shape and the expected contents for a known sort of artifact, it's declared to be an instance of that artifact, and a blend involving the next/previous frame is used to generate the values of pixels affected by the artifact. We'll probably want to take the result of motion-detection into account too.

I think the search-window could replace the radius-search in yuvmedianfilter. It could even do motion-detection for mpeg2enc.

Copyright (C) 2004-2009 by Steven Boswell. All rights reserved, and all that stuff.
Released to the public under the GNU General Public License v2. See the file COPYING for more information. mjpegtools-2.1.0/y4mdenoise/TemplateLib.hh0000644000175000017500000000406611173460062021022 0ustar glowwormglowworm#ifndef __TEMPLATELIB_H__ #define __TEMPLATELIB_H__ // This file (C) 2004-2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. // Basic template definitions. enum { g_knBitsPerByte = 8 }; // The number of bits per byte. (I doubt this'll ever change, // but just in case, we make a constant for it.) // Calcluate the size of an array of items. #define ARRAYSIZE(CLASS,COUNT) ((size_t)(&(((CLASS*)0)[COUNT]))) // A template function class that declares two classes are the same. template class Ident { public: const SECOND &operator() (const FIRST &a_rOther) const { return a_rOther; } }; // A generic pair. template class Pair { public: Pair() : m_oFirst (FIRST()), m_oSecond (SECOND()) {} Pair (const FIRST &a_oFirst, const SECOND &a_oSecond) : m_oFirst (a_oFirst), m_oSecond (a_oSecond) {} template Pair (const Pair &a_rOther) : m_oFirst (a_rOther.m_oFirst), m_oSecond (a_rOther.m_oSecond) {} FIRST m_oFirst; SECOND m_oSecond; }; // A template function that returns the first item (i.e. in a Pair). template class Select1st { public: const FIRST &operator() (const PAIR &a_rOther) const { return a_rOther.m_oFirst; } }; // A standard less-than comparison object. template class Less { public: bool operator() (const TYPE &a_rLeft, const TYPE &a_rRight) const { return a_rLeft < a_rRight; } }; // A general absolute-value function. template TYPE AbsoluteValue (const TYPE &a_rValue) { return (a_rValue < TYPE (0)) ? (-a_rValue) : a_rValue; } // A general minimum-value function. template TYPE Min (const TYPE &a_rLeft, const TYPE &a_rRight) { return (a_rLeft < a_rRight) ? a_rLeft : a_rRight; } // A general maximum-value function. template TYPE Max (const TYPE &a_rLeft, const TYPE &a_rRight) { return (a_rLeft > a_rRight) ? a_rLeft : a_rRight; } #endif // __TEMPLATELIB_H__ mjpegtools-2.1.0/y4mdenoise/BitmapRegion2D.hh0000644000175000017500000013107711212017415021363 0ustar glowwormglowworm#ifndef __BITMAPREGION2D_H__ #define __BITMAPREGION2D_H__ // This file (C) 2004-2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. // BitmapRegion2D tracks a 2-dimensional region of arbitrary points, // implemented with a bitmap. #include #include #include #include "Region2D.hh" // Define this to compile in code to double-check and debug the region. #ifndef NDEBUG // #define DEBUG_BITMAPREGION2D #endif // NDEBUG // Define this to enable the more specific method to subtract one // bitmap-region from another. // Disabled because, given how the code currently uses it, it's slightly // slower (adding maybe 1% to the runtime). //#define DIRECT_BITMAPREGION_SUBTRACT // Part of BitmapRegion2D<> breaks gcc 2.95. An earlier arrangement of // the code also broke gcc 3.3, but that seems to be in remission now. #if defined(__GNUC__) && defined(__GNUC_MINOR__) #if __GNUC__ == 2 && __GNUC_MINOR__ < 96 #define GCC_295_WORKAROUND #endif #endif // The 2-dimensional region class. Parameterized by the numeric type // to use for point indices, and the numeric type to use to count the // contained number of points. template class BitmapRegion2D : public Region2D { private: typedef Region2D BaseClass; // Keep track of who our base class is. public: typedef typename BaseClass::Extent Extent; // (Wouldn't we automatically have access to Extent because // we're a subclass of Region2D<>? Why is this needed?) BitmapRegion2D(); // Default constructor. Must be followed by Init(). BitmapRegion2D (Status_t &a_reStatus, INDEX a_tnWidth, INDEX a_tnHeight); // Initializing constructor. Creates an empty region with the // given extent. BitmapRegion2D (Status_t &a_reStatus, const BitmapRegion2D &a_rOther); // Copy constructor. void Init (Status_t &a_reStatus, INDEX a_tnWidth, INDEX a_tnHeight); // Initializer. Must be called on default-constructed regions. template void Assign (Status_t &a_reStatus, const OTHER &a_rOther); // Make the current region a copy of the other region. void Assign (Status_t &a_reStatus, const BitmapRegion2D &a_rOther); // Make the current region a copy of the other region. virtual ~BitmapRegion2D(); // Destructor. SIZE NumberOfPoints (void) const; // Return the total number of points contained by the region. void Clear (void); // Clear the region, emptying it of all extents. void Union (INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd); // Add the given horizontal extent to the region. Note that // a_tnXEnd is technically one past the end of the extent. void Union (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd); // Add the given horizontal extent to the region. Note that // a_tnXEnd is technically one past the end of the extent. // (This version is for interface compatibility with the // set-based region.) void Union (Status_t &a_reStatus, const BitmapRegion2D &a_rOther); // Make the current region represent the union between itself // and the other given region. void Merge (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd); // Merge this extent into the current region. // The new extent can't intersect the region in any way. void Merge (BitmapRegion2D &a_rOther); // Merge the other region into ourselves, emptying the other // region. Like Union(), but doesn't allocate any new memory. // Also, the other region can't intersect us in any way, and // both regions must use the same allocator. void Move (BitmapRegion2D &a_rOther); // Move the contents of the other region into the current // region. bool CanMove (const BitmapRegion2D &a_rOther) const; // Returns true if the other region's contents can be moved // into the current region. bool CanMove (const Region2D &a_rOther) const { return false; } void Move (Region2D &a_rOther) { assert (false); } // (We can move between BitmapRegion2D<>s, but not any arbitrary // Region2D<> subclass.) void Intersection (Status_t &a_reStatus, const BitmapRegion2D &a_rOther); // Make the current region represent the intersection between // itself and the other given region. void Subtract (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd); // Subtract the given horizontal extent from the region. Note // that a_tnXEnd is technically one past the end of the extent. template void Subtract (Status_t &a_reStatus, const OTHER &a_rOther); // Subtract the other region from the current region, i.e. // remove from the current region any areas that exist in the // other region. #ifdef DIRECT_BITMAPREGION_SUBTRACT void Subtract (Status_t &a_reStatus, const BitmapRegion2D &a_rOther); #endif // DIRECT_BITMAPREGION_SUBTRACT // Subtract the other region from the current region, i.e. // remove from the current region any areas that exist in the // other region. bool DoesContainPoint (INDEX a_tnY, INDEX a_tnX) const; // Returns true if the region contains the given point. void SetPoint (INDEX a_tnY, INDEX a_tnX); // Add the given point to the region. // (Basically a one-point Union().) // A structure that implements flood-fills using BitmapRegion2D<> to // do the work. (The definition of this class follows the // definition of Region<>.) class FloodFillControl; template void FloodFill (Status_t &a_reStatus, CONTROL &a_rControl, bool a_bVerify, bool a_bExpand); // Flood-fill the current region. // If a_bVerify is true, all existing region points are re-tested. // If a_bExpand is true, all points bordering the current region // are tested for inclusion. template void MakeBorder (Status_t &a_reStatus, const OTHER &a_rOther); // Make the current region represent the border of the other // region, i.e. every pixel that's adjacent to a pixel that's // in the region, but isn't already in the region. // An iterator for the bitmap-oriented region. class ConstIterator { protected: friend class BitmapRegion2D; // Let the region implement our operations. const BitmapRegion2D *m_pThis; // The region that we're iterating through. Extent m_oExtent; // The extent we currently represent. public: ConstIterator() { m_pThis = NULL; } ConstIterator (const ConstIterator &a_rOther) : m_pThis (a_rOther.m_pThis), m_oExtent (a_rOther.m_oExtent) {} const Extent &operator*() const { return m_oExtent; } ConstIterator& operator++(); ConstIterator operator++(int) { ConstIterator oTmp = *this; ++*this; return oTmp; } ConstIterator& operator--(); ConstIterator operator--(int) { ConstIterator oTmp = *this; --*this; return oTmp; } bool operator== (const ConstIterator &a_rOther) const { return (m_pThis == a_rOther.m_pThis && m_oExtent == a_rOther.m_oExtent) ? true : false; } bool operator!= (const ConstIterator &a_rOther) const { return (m_pThis != a_rOther.m_pThis || m_oExtent != a_rOther.m_oExtent) ? true : false; } }; ConstIterator Begin (void) const; ConstIterator End (void) const; // Allow our client to iterate through the extents & get their // values. void UnionSurroundingExtents (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd); // Add all extents surrounding the given extent. // Used by FloodFill() and MakeBorder(). void IteratorForward (ConstIterator &a_ritHere) const; // Move one of our iterators forward. void IteratorBackward (ConstIterator &a_ritHere) const; // Move one of our iterators backward. static int FindFirstSetBit (unsigned int a_nWord, int a_nSkip); static int FindFirstClearBit (unsigned int a_nWord, int a_nSkip); static int FindLastSetBit (unsigned int a_nWord, int a_nSkip); static int FindLastClearBit (unsigned int a_nWord, int a_nSkip); // Find the index of the first/last set/clear bit, skipping // the first/last a_nSkip bits. // Used to implement iterator increment/decrement. private: INDEX m_tnWidth, m_tnHeight; // The extent of the bitmap. unsigned int *m_pnPoints; // The bitmap representing the region. SIZE m_tnBitmapInts; // The number of integers in our bitmap. INDEX m_tnXMin, m_tnXMax, m_tnYMin, m_tnYMax; // The portion of the bitmap that may contain extents. // Used to speed up IteratorForward(). static int8_t m_anSetBitsPerByte[256]; // The number of set bits in every possible byte value. static bool m_bSetBitsPerByte; // Whether the set-bits-per-byte table has been set up. #ifndef NDEBUG // Count the number of region objects in existence. private: static uint32_t sm_ulInstances; public: static uint32_t GetInstances (void) { return sm_ulInstances; } #endif // NDEBUG }; // A structure that implements flood-fills using BitmapRegion2D<> to // do the work. template class BitmapRegion2D::FloodFillControl #ifndef GCC_295_WORKAROUND : public Region2D::template FloodFillControl > #endif // ! GCC_295_WORKAROUND { private: typedef Region2D BaseRegion; typedef BitmapRegion2D OurRegion; typedef typename BaseRegion::template FloodFillControl BaseClass; // Keep track of who our base class is. public: #ifdef GCC_295_WORKAROUND // (Although these fields are public, they should be considered // opaque to the client.) BitmapRegion2D m_oToDo; // Extents that still need to be be tested. BitmapRegion2D m_oAlreadyDone; // Extents that have been tested. BitmapRegion2D m_oNextToDo; // Extents contiguous with those that have just been added // to the flood-filled area. typedef typename BitmapRegion2D::ConstIterator ConstIterator; typedef typename BitmapRegion2D::Extent Extent; // The iterator/extent type for running through the above // regions. #endif // GCC_295_WORKAROUND FloodFillControl(); // Default constructor. Must be followed by a call to Init(). FloodFillControl (Status_t &a_reStatus, INDEX a_tnWidth, INDEX a_tnHeight); // Initializing constructor. void Init (Status_t &a_reStatus, INDEX a_tnWidth, INDEX a_tnHeight); // Initializer. Must be called on default-constructed objects. }; // Default constructor. Must be followed by Init(). template BitmapRegion2D::BitmapRegion2D() { // One more instance. #ifndef NDEBUG ++sm_ulInstances; #endif // NDEBUG // No bitmap yet. m_tnWidth = m_tnHeight = INDEX (0); m_tnXMin = m_tnXMax = m_tnYMin = m_tnYMax = INDEX (0); m_pnPoints = NULL; m_tnBitmapInts = SIZE (0); } // Initializing constructor. Creates an empty region. template BitmapRegion2D::BitmapRegion2D (Status_t &a_reStatus, INDEX a_tnWidth, INDEX a_tnHeight) { // One more instance. #ifndef NDEBUG ++sm_ulInstances; #endif // NDEBUG // No bitmap yet. m_tnWidth = m_tnHeight = INDEX (0); m_tnXMin = m_tnXMax = m_tnYMin = m_tnYMax = INDEX (0); m_pnPoints = NULL; m_tnBitmapInts = SIZE (0); // Save the width & height. m_tnWidth = a_tnWidth; m_tnHeight = a_tnHeight; m_tnXMin = a_tnWidth; m_tnXMax = INDEX (0); m_tnYMin = a_tnHeight; m_tnYMax = INDEX (0); // Allocate the bitmap. m_tnBitmapInts = (SIZE (m_tnWidth) * SIZE (m_tnHeight)) / (g_knBitsPerByte * sizeof (unsigned int)) + 1; m_pnPoints = new unsigned int[m_tnBitmapInts]; if (m_pnPoints == NULL) { a_reStatus = g_kOutOfMemory; return; } // No points yet. for (SIZE i = 0; i < m_tnBitmapInts; ++i) m_pnPoints[i] = 0U; } // Copy constructor. template BitmapRegion2D::BitmapRegion2D (Status_t &a_reStatus, const BitmapRegion2D &a_rOther) { // One more instance. #ifndef NDEBUG ++sm_ulInstances; #endif // NDEBUG // No bitmap yet. m_tnWidth = m_tnHeight = INDEX (0); m_pnPoints = NULL; m_tnBitmapInts = SIZE (0); // Copy the width, height, and active area. m_tnWidth = a_rOther.m_tnWidth; m_tnHeight = a_rOther.m_tnHeight; m_tnXMin = a_rOther.m_tnXMin; m_tnXMax = a_rOther.m_tnXMax; m_tnYMin = a_rOther.m_tnYMin; m_tnYMax = a_rOther.m_tnYMax; // Allocate the bitmap. m_tnBitmapInts = (SIZE (m_tnWidth) * SIZE (m_tnHeight)) / (g_knBitsPerByte * sizeof (unsigned int)) + 1; m_pnPoints = new unsigned int[m_tnBitmapInts]; if (m_pnPoints == NULL) { a_reStatus = g_kOutOfMemory; return; } // Copy the bitmap. memcpy (m_pnPoints, a_rOther.m_pnPoints, m_tnBitmapInts * sizeof (unsigned int)); } // Initializer. Must be called on default-constructed regions. template void BitmapRegion2D::Init (Status_t &a_reStatus, INDEX a_tnWidth, INDEX a_tnHeight) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Save the width & height. m_tnWidth = a_tnWidth; m_tnHeight = a_tnHeight; m_tnXMin = a_tnWidth; m_tnXMax = INDEX (0); m_tnYMin = a_tnHeight; m_tnYMax = INDEX (0); // Allocate the bitmap. m_tnBitmapInts = (SIZE (m_tnWidth) * SIZE (m_tnHeight)) / (g_knBitsPerByte * sizeof (unsigned int)) + 1; m_pnPoints = new unsigned int[m_tnBitmapInts]; if (m_pnPoints == NULL) { a_reStatus = g_kOutOfMemory; return; } // No points yet. for (SIZE i = 0; i < m_tnBitmapInts; ++i) m_pnPoints[i] = 0U; } // Make the current region a copy of the other region. template template void BitmapRegion2D::Assign (Status_t &a_reStatus, const OTHER &a_rOther) { typename OTHER::ConstIterator itExtent; // Used to loop through extents to copy. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Clear our contents, in preparation for being assigned. Clear(); // Loop through the other region's extents, clip them to the current // region's boundaries, and add them to the current region. for (itExtent = a_rOther.Begin(); itExtent != a_rOther.End(); ++itExtent) { // Get the extent. typename OTHER::Extent oExtent = *itExtent; // Add it to the current region. Union (oExtent.m_tnY, oExtent.m_tnXStart, oExtent.m_tnXEnd); } } // Make the current region a copy of the other region. template void BitmapRegion2D::Assign (Status_t &a_reStatus, const BitmapRegion2D &a_rOther) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // If the region is not the exact same size, use the more // generic version. if (m_tnWidth != a_rOther.m_tnWidth || m_tnHeight != a_rOther.m_tnHeight) { Assign > (a_reStatus, *this); return; } // Make sure the region is the exact same size. assert (m_tnWidth == a_rOther.m_tnWidth && m_tnHeight == a_rOther.m_tnHeight); // Copy the other region's bitmap. memcpy (m_pnPoints, a_rOther.m_pnPoints, m_tnBitmapInts * sizeof (unsigned int)); // Copy its active area. m_tnXMin = a_rOther.m_tnXMin; m_tnXMax = a_rOther.m_tnXMax; m_tnYMin = a_rOther.m_tnYMin; m_tnYMax = a_rOther.m_tnYMax; } // Destructor. template BitmapRegion2D::~BitmapRegion2D() { // Free up the bitmap. delete[] m_pnPoints; // One less instance. #ifndef NDEBUG --sm_ulInstances; #endif // NDEBUG } // Return the total number of points contained by the region. template SIZE BitmapRegion2D::NumberOfPoints (void) const { // To make this fast, we precalculate a table, indexed by byte // value, that contains the number of set bits in that byte. if (!m_bSetBitsPerByte) { for (int i = 0; i < 256; ++i) { int8_t nBits = 0; uint8_t nVal = uint8_t (i); for (int j = 0; j < 8; ++j) { if (nVal & 1) ++nBits; nVal >>= 1; } m_anSetBitsPerByte[i] = nBits; } // We only have to do this once. m_bSetBitsPerByte = true; } SIZE tnI, tnLimit; // Used to loop through the bitmap's bytes. SIZE tnPoints; // The number of points we tally. // Loop through the bitmap's bytes, look up how many set bits // there are in each byte, count them up. uint8_t *pnPoints = (uint8_t *) m_pnPoints; tnLimit = m_tnBitmapInts * (sizeof (unsigned int) / sizeof (uint8_t)); tnPoints = 0; for (tnI = 0; tnI < tnLimit; ++tnI) tnPoints += m_anSetBitsPerByte[pnPoints[tnI]]; // Return the number of points we counted. return tnPoints; } // Clear the region, emptying it of all extents. template void BitmapRegion2D::Clear (void) { // Clear all the bits. memset (m_pnPoints, 0, ARRAYSIZE (unsigned int, m_tnBitmapInts)); // Reset the active area. m_tnXMin = m_tnWidth; m_tnXMax = INDEX (0); m_tnYMin = m_tnHeight; m_tnYMax = INDEX (0); } // Add the given point to the region. template void BitmapRegion2D::SetPoint (INDEX a_tnY, INDEX a_tnX) { // Make sure this point is in range. assert (a_tnY >= 0 && a_tnY < m_tnHeight); assert (a_tnX >= 0 && a_tnX < m_tnWidth); // Factor this extent into the active area. m_tnXMin = Min (m_tnXMin, a_tnX); m_tnXMax = Max (m_tnXMax, INDEX (a_tnX + 1)); m_tnYMin = Min (m_tnYMin, a_tnY); m_tnYMax = Max (m_tnYMax, a_tnY); // Set the point. SIZE tnI = a_tnY * m_tnWidth + a_tnX; m_pnPoints[tnI / (g_knBitsPerByte * sizeof (unsigned int))] |= (1U << (tnI % (g_knBitsPerByte * sizeof (unsigned int)))); } // Add the given horizontal extent to the region. template void BitmapRegion2D::Union (INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd) { SIZE tnI; // The index of the bitmap integer to modify. INDEX tnX; // Used to loop through points. // Make sure they gave us a non-empty extent. assert (a_tnXStart < a_tnXEnd); // If this extent is completely outside the region, skip it. if (a_tnY < 0 || a_tnY >= m_tnHeight || a_tnXStart >= m_tnWidth || a_tnXEnd <= 0) return; // If this extent is partially outside the region, clip it. if (a_tnXStart < 0) a_tnXStart = 0; if (a_tnXEnd > m_tnWidth) a_tnXEnd = m_tnWidth; if (a_tnXStart < 0) a_tnXStart = 0; if (a_tnXEnd > m_tnWidth) a_tnXEnd = m_tnWidth; // Factor this extent into the active area. m_tnXMin = Min (m_tnXMin, a_tnXStart); m_tnXMax = Max (m_tnXMax, a_tnXEnd); m_tnYMin = Min (m_tnYMin, a_tnY); m_tnYMax = Max (m_tnYMax, a_tnY); // Loop through all the points, set them. for (tnX = a_tnXStart; tnX < a_tnXEnd; ++tnX) { tnI = a_tnY * m_tnWidth + tnX; m_pnPoints[tnI / (g_knBitsPerByte * sizeof (unsigned int))] |= (1U << (tnI % (g_knBitsPerByte * sizeof (unsigned int)))); } } // Add the given horizontal extent to the region. template void BitmapRegion2D::Union (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Call the non-failing version. Union (a_tnY, a_tnXStart, a_tnXEnd); } // Make the current region represent the union between itself // and the other given region. template void BitmapRegion2D::Union (Status_t &a_reStatus, const BitmapRegion2D &a_rOther) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure the region is the exact same size. assert (m_tnWidth == a_rOther.m_tnWidth && m_tnHeight == a_rOther.m_tnHeight); // Unify with the other region's bitmap. for (SIZE i = 0; i < m_tnBitmapInts; ++i) m_pnPoints[i] |= a_rOther.m_pnPoints[i]; // Factor the other region's active area into our own. m_tnXMin = Min (m_tnXMin, a_rOther.m_tnXMin); m_tnXMax = Max (m_tnXMax, a_rOther.m_tnXMax); m_tnYMin = Min (m_tnYMin, a_rOther.m_tnYMin); m_tnYMax = Max (m_tnYMax, a_rOther.m_tnYMax); } // Merge this extent into the current region. // The new extent can't intersect the region in any way. template void BitmapRegion2D::Merge (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd) { // For a bitmap, Union() is the same thing. Union (a_reStatus, a_tnY, a_tnXStart, a_tnXEnd); } // Merge the other region into ourselves, emptying the other region. template void BitmapRegion2D::Merge (BitmapRegion2D &a_rOther) { // Make sure the region is the exact same size. assert (m_tnWidth == a_rOther.m_tnWidth && m_tnHeight == a_rOther.m_tnHeight); // For a bitmap, this is easy. Status_t eStatus = g_kNoError; Union (eStatus, a_rOther); assert (eStatus == g_kNoError); a_rOther.Clear(); } // Move the contents of the other region into the current region. template void BitmapRegion2D::Move (BitmapRegion2D &a_rOther) { // Make sure we're allowed to do this. assert (CanMove (a_rOther)); // Empty the current region. Clear(); // Swap the contained bitmaps. unsigned int *pnPoints = m_pnPoints; m_pnPoints = a_rOther.m_pnPoints; a_rOther.m_pnPoints = pnPoints; // Swap the active area. INDEX tnActive = a_rOther.m_tnXMin; a_rOther.m_tnXMin = m_tnXMin; m_tnXMin = tnActive; tnActive = a_rOther.m_tnXMax; a_rOther.m_tnXMax = m_tnXMax; m_tnXMax = tnActive; tnActive = a_rOther.m_tnYMin; a_rOther.m_tnYMin = m_tnYMin; m_tnYMin = tnActive; tnActive = a_rOther.m_tnYMax; a_rOther.m_tnYMax = m_tnYMax; m_tnYMax = tnActive; } // Returns true if the other region's contents can be moved // into the current region. template bool BitmapRegion2D::CanMove (const BitmapRegion2D &a_rOther) const { // We can do this if the regions are the same size. return (m_tnWidth == a_rOther.m_tnWidth && m_tnHeight == a_rOther.m_tnHeight); } // Make the current region represent the intersection between // itself and the other given region. template void BitmapRegion2D::Intersection (Status_t &a_reStatus, const BitmapRegion2D &a_rOther) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure the region is the exact same size. assert (m_tnWidth == a_rOther.m_tnWidth && m_tnHeight == a_rOther.m_tnHeight); // Intersect with the other region's bitmap. for (SIZE i = 0; i < m_tnBitmapInts; ++i) m_pnPoints[i] &= a_rOther.m_pnPoints[i]; // The active area may have shrunk, but we don't recalculate it; // that would take too long. } // Subtract the given horizontal extent from the region. template void BitmapRegion2D::Subtract (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd) { SIZE tnI; // The index of the bitmap integer to modify. INDEX tnX; // Used to loop through points. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure they gave us a non-empty extent. assert (a_tnXStart < a_tnXEnd); // If this extent is completely outside the region, skip it. if (a_tnY < 0 || a_tnY >= m_tnHeight || a_tnXStart >= m_tnWidth || a_tnXEnd <= 0) return; // If this extent is partially outside the region, clip it. if (a_tnXStart < 0) a_tnXStart = 0; if (a_tnXEnd > m_tnWidth) a_tnXEnd = m_tnWidth; if (a_tnXStart < 0) a_tnXStart = 0; if (a_tnXEnd > m_tnWidth) a_tnXEnd = m_tnWidth; // Loop through all the points, clear them. for (tnX = a_tnXStart; tnX < a_tnXEnd; ++tnX) { tnI = a_tnY * m_tnWidth + tnX; m_pnPoints[tnI / (g_knBitsPerByte * sizeof (unsigned int))] &= (~(1U << (tnI % (g_knBitsPerByte * sizeof (unsigned int))))); } // The active area may have shrunk, but we don't recalculate it; // that would take too long. } // Subtract the other region from the current region, i.e. // remove from the current region any areas that exist in the // other region. template template void BitmapRegion2D::Subtract (Status_t &a_reStatus, const OTHER &a_rOther) { typename OTHER::ConstIterator itExtent; // Used to loop through the other region's extents. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Loop through the other region's extents, subtract each one. for (itExtent = a_rOther.Begin(); itExtent != a_rOther.End(); ++itExtent) { Subtract (a_reStatus, (*itExtent).m_tnY, (*itExtent).m_tnXStart, (*itExtent).m_tnXEnd); assert (a_reStatus == g_kNoError); // (should always succeed.) if (a_reStatus != g_kNoError) return; } // The active area may have shrunk, but we don't recalculate it; // that would take too long. } #ifdef DIRECT_BITMAPREGION_SUBTRACT // Subtract the other region from the current region, i.e. // remove from the current region any areas that exist in the // other region. template void BitmapRegion2D::Subtract (Status_t &a_reStatus, const BitmapRegion2D &a_rOther) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure the region is the exact same size. assert (m_tnWidth == a_rOther.m_tnWidth && m_tnHeight == a_rOther.m_tnHeight); // If either region is empty, we're done. if (m_tnXMin >= m_tnXMax || m_tnYMin > m_tnYMax || a_rOther.m_tnXMin >= a_rOther.m_tnXMax || a_rOther.m_tnYMin > a_rOther.m_tnYMax) return; // Calculate the active area common to the two regions. INDEX tnXMin = Max (m_tnXMin, a_rOther.m_tnXMin); INDEX tnXMax = Min (m_tnXMax, a_rOther.m_tnXMax); INDEX tnYMin = Max (m_tnYMin, a_rOther.m_tnYMin); INDEX tnYMax = Min (m_tnYMax, a_rOther.m_tnYMax); // If the two active areas don't overlap, we're done. if (tnXMin >= tnXMax || tnYMin > tnYMax) return; // Loop through the common active area, subtract extents. // If the active area encompasses most of the X range, do this faster. INDEX tnBitsPerWord = g_knBitsPerByte * sizeof (unsigned int); if (tnXMin <= tnBitsPerWord && tnXMax >= m_tnWidth - tnBitsPerWord) { // Find the range of words that correspond to the active area. SIZE tnWordIndex = (SIZE (tnYMin) * SIZE (m_tnWidth) + SIZE (tnXMin)) >> Limits::Log2Bits; SIZE tnLastWordIndex = (SIZE (tnYMax) * SIZE (m_tnWidth) + SIZE (tnXMax - INDEX (1))) >> Limits::Log2Bits; // Loop through these words, subtract extents. for (SIZE tnI = tnWordIndex; tnI <= tnLastWordIndex; ++tnI) m_pnPoints[tnI] &= (~(a_rOther.m_pnPoints[tnI])); } else { // Loop through the common active area of each line. for (INDEX tnY = tnYMin; tnY <= tnYMax; ++tnY) { // Find the range of words that correspond to the active area // on this line. SIZE tnWordIndex = (SIZE (tnY) * SIZE (m_tnWidth) + SIZE (tnXMin)) >> Limits::Log2Bits; SIZE tnLastWordIndex = (SIZE (tnY) * SIZE (m_tnWidth) + SIZE (tnXMax - INDEX (1))) >> Limits::Log2Bits; // Loop through these words, subtract extents. for (SIZE tnI = tnWordIndex; tnI <= tnLastWordIndex; ++tnI) m_pnPoints[tnI] &= (~(a_rOther.m_pnPoints[tnI])); } } // The active area may have shrunk, but we don't recalculate it; // that would take too long. } #endif // DIRECT_BITMAPREGION_SUBTRACT // Returns true if the region contains the given point. template bool BitmapRegion2D::DoesContainPoint (INDEX a_tnY, INDEX a_tnX) const { // Make sure the indices are within our extent. assert (a_tnY >= 0 && a_tnY < m_tnHeight); assert (a_tnX >= 0 && a_tnX < m_tnWidth); // Find the bit & return if it's set. SIZE tnI = a_tnY * m_tnWidth + a_tnX; return (m_pnPoints[tnI / (g_knBitsPerByte * sizeof (unsigned int))] & (1U << (tnI % (g_knBitsPerByte * sizeof (unsigned int))))); } // Flood-fill the current region. template template void BitmapRegion2D::FloodFill (Status_t &a_reStatus, CONTROL &a_rControl, bool a_bVerify, bool a_bExpand) { typename CONTROL::ConstIterator itExtent; // An extent we're examining. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // How we set up depends on whether we're to verify all existing // region extents. if (a_bVerify) { // The to-do-list becomes the current region, and we empty // out the current region too. a_rControl.m_oAlreadyDone.Clear(); if (a_rControl.m_oToDo.CanMove (*this)) { // Grab the extents right out of the current region. a_rControl.m_oToDo.Clear(); a_rControl.m_oToDo.Move (*this); } else { // Copy the extents from the current region, then empty it. a_rControl.m_oToDo.Assign (a_reStatus, *this); if (a_reStatus != g_kNoError) return; Clear(); } } else { // The already-done list starts with the region, i.e. every // extent already known to be in the region can avoid getting // tested. a_rControl.m_oAlreadyDone.Assign (a_reStatus, *this); if (a_reStatus != g_kNoError) return; // Start the to-do list with a border around all the extents in // the region. a_rControl.m_oToDo.MakeBorder (a_reStatus, *this); if (a_reStatus != g_kNoError) return; } // Now pull each extent out of the to-do list. Determine which // sub-extents are part of the region. Add those found extents // to the region. Then add all extent surrounding the found extents // to the to-do-next list. itExtent = a_rControl.m_oToDo.Begin(); while (itExtent != a_rControl.m_oToDo.End()) { INDEX tnX; // Where we're looking for extents. // Get the extent, converting the type if necessary. typename CONTROL::Extent oExtent; oExtent.m_tnY = (*itExtent).m_tnY; oExtent.m_tnXStart = (*itExtent).m_tnXStart; oExtent.m_tnXEnd = (*itExtent).m_tnXEnd; INDEX tnY = oExtent.m_tnY; // If this extent shouldn't be considered, skip it. if (!a_rControl.ShouldUseExtent (oExtent)) goto nextExtent; // Make sure our client left us with a valid extent. assert (oExtent.m_tnXStart < oExtent.m_tnXEnd); assert (tnY == oExtent.m_tnY); // (Sanity check) // Run through the pixels described by this extent, see if // they can be added to the region, and remember where to // search next. for (tnX = oExtent.m_tnXStart; tnX < oExtent.m_tnXEnd; ++tnX) { // We're about to check this point. Put it in the // already-checked list now. a_rControl.m_oAlreadyDone.SetPoint (tnY, tnX); // Is this point in the region? if (a_rControl.IsPointInRegion (tnX, tnY)) { // This point is in the region. SetPoint (tnY, tnX); // Now add all surrounding points to the to-do-next list. if (a_bExpand) { // Add the extent above this one. if (tnY > 0 && !a_rControl.m_oToDo.DoesContainPoint (tnY - 1, tnX) && !a_rControl.m_oAlreadyDone.DoesContainPoint (tnY - 1, tnX)) a_rControl.m_oNextToDo.SetPoint (tnY - 1, tnX); // Add the extent to the left. if (tnX > 0 && !a_rControl.m_oToDo.DoesContainPoint (tnY, tnX - 1) && !a_rControl.m_oAlreadyDone.DoesContainPoint (tnY, tnX - 1)) a_rControl.m_oNextToDo.SetPoint (tnY, tnX - 1); // Add the extent to the right. if (tnX < m_tnWidth - 1 && !a_rControl.m_oToDo.DoesContainPoint (tnY, tnX + 1) && !a_rControl.m_oAlreadyDone.DoesContainPoint (tnY, tnX + 1)) a_rControl.m_oNextToDo.SetPoint (tnY, tnX + 1); // Add the extent below this one. if (tnY < m_tnHeight - 1 && !a_rControl.m_oToDo.DoesContainPoint (tnY + 1, tnX) && !a_rControl.m_oAlreadyDone.DoesContainPoint (tnY + 1, tnX)) a_rControl.m_oNextToDo.SetPoint (tnY + 1, tnX); } } } nextExtent: // Move to the next extent. ++itExtent; // If the to-do list needs to be replenished, do so. if (itExtent == a_rControl.m_oToDo.End()) { // Replenish the to-do list. a_rControl.m_oToDo.Clear(); a_rControl.m_oToDo.Move (a_rControl.m_oNextToDo); // Make sure no points will be checked repeatedly. // (This is an expensive check, so only do it if we've // turned on the other expensive checks.) #ifdef DEBUG_BITMAPREGION2D { SIZE nPointsBefore = a_rControl.m_oToDo.NumberOfPoints(); a_rControl.m_oToDo.Subtract (a_reStatus, a_rControl.m_oAlreadyDone); assert (a_reStatus == g_kNoError); SIZE nPointsAfter = a_rControl.m_oToDo.NumberOfPoints(); assert (nPointsBefore == nPointsAfter); } #endif // DEBUG_BITMAPREGION2D // Start over at the beginning. itExtent = a_rControl.m_oToDo.Begin(); } } } // Make the current region represent the border of the other // region, i.e. every pixel that borders the region but isn't // already in the region. template template void BitmapRegion2D::MakeBorder (Status_t &a_reStatus, const OTHER &a_rOther) { typename OTHER::ConstIterator itExtent; // Used to loop through the other region's extents. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Start with an empty region. Clear(); // For every extent in the other region, add every surrounding // extent. That creates a region that looks like the other region, // but also contains the border we're after. for (itExtent = a_rOther.Begin(); itExtent != a_rOther.End(); ++itExtent) { // Add the surrounding extents. UnionSurroundingExtents (a_reStatus, (*itExtent).m_tnY, (*itExtent).m_tnXStart, (*itExtent).m_tnXEnd); if (a_reStatus != g_kNoError) return; } // Finally, subtract the other region. That punches a hole in us, // and creates the border region we're after. Subtract (a_reStatus, a_rOther); if (a_reStatus != g_kNoError) return; } // Add all extents surrounding the given extent. Used by FloodFill(). template void BitmapRegion2D::UnionSurroundingExtents (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Add the extent above this one. if (a_tnY > 0) Union (a_tnY - 1, a_tnXStart, a_tnXEnd); // Add the extent to the left. if (a_tnXStart > 0) Union (a_tnY, a_tnXStart - 1, a_tnXStart); // Add the extent to the right. if (a_tnXEnd < m_tnWidth) Union (a_tnY, a_tnXEnd, a_tnXEnd + 1); // Add the extent below this one. if (a_tnY < m_tnHeight - 1) Union (a_tnY + 1, a_tnXStart, a_tnXEnd); } // Move one of our iterators forward. template void BitmapRegion2D::IteratorForward (ConstIterator &a_ritHere) const { SIZE tnWordIndex, tnBitIndex; // The word/bit index that corresponds to the x/y pixel index. SIZE tnLastWordIndex, tnLastBitIndex; // The word/bit index for the last pixel in the active area or // in the current line. unsigned int nWord; // A bitmap word being examined. unsigned int nMask; // A bitmask we generate. // If the old extent ended outside of the active area, move // into the active area. // This naturally detects an empty active-area, too. if (a_ritHere.m_oExtent.m_tnY < m_tnYMin) { a_ritHere.m_oExtent.m_tnXStart = a_ritHere.m_oExtent.m_tnXEnd = m_tnXMin; a_ritHere.m_oExtent.m_tnY = m_tnYMin; } else if (a_ritHere.m_oExtent.m_tnXEnd >= m_tnXMax) { a_ritHere.m_oExtent.m_tnXStart = a_ritHere.m_oExtent.m_tnXEnd = m_tnXMin; ++a_ritHere.m_oExtent.m_tnY; } else if (a_ritHere.m_oExtent.m_tnXEnd < m_tnXMin) { a_ritHere.m_oExtent.m_tnXStart = a_ritHere.m_oExtent.m_tnXEnd = m_tnXMin; } // If we're past the active area, we're done. if (a_ritHere.m_oExtent.m_tnY > m_tnYMax) { a_ritHere = End(); return; } // We'll start looking for a new extent after the end of the old // extent. Find the word/bit index for that, and the word itself. tnBitIndex = SIZE (a_ritHere.m_oExtent.m_tnY) * SIZE (m_tnWidth) + SIZE (a_ritHere.m_oExtent.m_tnXEnd); tnWordIndex = tnBitIndex >> Limits::Log2Bits; tnBitIndex -= tnWordIndex << Limits::Log2Bits; nWord = m_pnPoints[tnWordIndex]; // Find the index of the last word, given the active area. tnLastBitIndex = SIZE (m_tnYMax) * SIZE (m_tnWidth) + SIZE (m_tnXMax); tnLastWordIndex = tnLastBitIndex >> Limits::Log2Bits; //tnLastBitIndex -= tnLastWordIndex << Limits::Log2Bits; // Get rid of any set bits that have been iterated over already. nWord &= ((~0U) << tnBitIndex); // Skip all clear bits. First check the current word to see if the // rest of its bits are clear, then skip over all all-clear words. if (nWord == 0U) { // The rest of the current word's bits are clear. ++tnWordIndex; tnBitIndex = 0; // Skip over all all-clear words. while (tnWordIndex <= tnLastWordIndex && m_pnPoints[tnWordIndex] == 0U) ++tnWordIndex; // If we reached the end of the bitmap, let our caller know. if (tnWordIndex > tnLastWordIndex) { a_ritHere = End(); return; } // Get the current word. nWord = m_pnPoints[tnWordIndex]; } // Look for the next set bit in the current word. assert (nWord != 0U); #if 0 tnBitIndex = FindFirstSetBit (nWord, tnBitIndex); #else tnBitIndex = ffs (nWord) - 1; #endif // Calculate the x/y index of this first set bit, and the word/bit // index of the end of the line. tnLastBitIndex = tnWordIndex * Limits::Bits + tnBitIndex; a_ritHere.m_oExtent.m_tnY = INDEX (tnLastBitIndex / m_tnWidth); a_ritHere.m_oExtent.m_tnXStart = tnLastBitIndex - SIZE (a_ritHere.m_oExtent.m_tnY) * SIZE (m_tnWidth); tnLastBitIndex = SIZE (a_ritHere.m_oExtent.m_tnY) * SIZE (m_tnWidth) + SIZE (m_tnXMax); tnLastWordIndex = tnLastBitIndex >> Limits::Log2Bits; tnLastBitIndex -= tnLastWordIndex << Limits::Log2Bits; // Skip all set bits. First check the current word to see if the // rest of its bits are set, then skip over all all-set words. nMask = ((~0U) << tnBitIndex); if ((nWord & nMask) == nMask) { // The rest of the current word's bits are set. ++tnWordIndex; tnBitIndex = 0; // Skip over all all-set words. while (tnWordIndex <= tnLastWordIndex && tnWordIndex < m_tnBitmapInts && m_pnPoints[tnWordIndex] == (~0U)) ++tnWordIndex; // If we reached the end of the line, let our caller know. if (tnWordIndex > tnLastWordIndex) { a_ritHere.m_oExtent.m_tnXEnd = m_tnXMax; return; } // Get the current word. nWord = m_pnPoints[tnWordIndex]; } // Look for the next clear bit in the current word. assert (nWord != (~0U)); #if 0 tnBitIndex = FindFirstClearBit (nWord, tnBitIndex); #else nWord |= ~((~0U) << tnBitIndex); tnBitIndex = ffs (~nWord) - 1; #endif // Clip it to the end of the line. if (tnWordIndex == tnLastWordIndex && tnBitIndex > tnLastBitIndex) tnBitIndex = tnLastBitIndex; // Calculate the x index of this first clear bit; it becomes the // end of the extent. tnLastBitIndex = tnWordIndex * Limits::Bits + tnBitIndex; a_ritHere.m_oExtent.m_tnXEnd = tnLastBitIndex - SIZE (a_ritHere.m_oExtent.m_tnY) * SIZE (m_tnWidth); assert (a_ritHere.m_oExtent.m_tnXEnd <= m_tnWidth); } // Move one of our iterators backward. template void BitmapRegion2D::IteratorBackward (ConstIterator &a_ritHere) const { // Not written yet. assert (false); } // Find the first set bit. template int BitmapRegion2D::FindFirstSetBit (unsigned int a_nWord, int a_nSkip) { int nLow, nHigh; // The search range. // Skip the first a_nSkip bits by clearing them. a_nWord &= ((~0U) << a_nSkip); // Make sure at least one bit is set. assert (a_nWord != 0U); // Find the range of all-clear LSB bits, i.e. the highest index // such that it and all lower-index bits are zero. nLow = 0; // faster than nLow = a_nSkip? nHigh = Limits::Bits - 1; while (nLow < nHigh) { // Look in the middle. int nCurrent = (nLow + nHigh) >> 1; // Generate a mask where bits 0-nCurrent are all set, and // the remaining bits are clear. unsigned int nCurrentMask = ~((~0U) << (nCurrent + 1)); // If the nCurrent LSB bits are all clear, look above nCurrent, // otherwise look below nCurrent. if ((a_nWord & nCurrentMask) == 0U) nLow = nCurrent + 1; else nHigh = nCurrent; } // Return the index of the first set bit. assert (nLow == nHigh); return nLow; } // Find the first clear bit. template int BitmapRegion2D::FindFirstClearBit (unsigned int a_nWord, int a_nSkip) { int nLow, nHigh; // The search range. // Skip the first a_nSkip bits by setting them. a_nWord |= ~((~0U) << a_nSkip); // Make sure at least one bit is clear. assert (a_nWord != (~0U)); // Find the range of all-set LSB bits. nLow = 0; // faster than nLow = a_nSkip? nHigh = Limits::Bits - 1; while (nLow < nHigh) { // Look in the middle. int nCurrent = (nLow + nHigh) >> 1; // Generate a mask where bits 0-nCurrent are all set, and // the remaining bits are clear. unsigned int nCurrentMask = ~((~0U) << (nCurrent + 1)); // If the nCurrent LSB bits are all set, look above nCurrent, // otherwise look below nCurrent. if ((a_nWord & nCurrentMask) == nCurrentMask) nLow = nCurrent + 1; else nHigh = nCurrent; } // Return the index of the first clear bit. assert (nLow == nHigh); return nLow; } // Find the last set bit. template int BitmapRegion2D::FindLastSetBit (unsigned int a_nWord, int a_nSkip) { // Not written yet. assert (false); return 0; } // Find the last clear bit. template int BitmapRegion2D::FindLastClearBit (unsigned int a_nWord, int a_nSkip) { // Not written yet. assert (false); return 0; } // Get the first extent in the region. template typename BitmapRegion2D::ConstIterator BitmapRegion2D::Begin (void) const { ConstIterator itBegin; // The iterator we construct. // Start before the beginning of this region. itBegin.m_pThis = this; itBegin.m_oExtent.m_tnY = 0; itBegin.m_oExtent.m_tnXStart = 0; itBegin.m_oExtent.m_tnXEnd = 0; // Move to the first valid extent & return it. return ++itBegin; } // Get one past the last extent in the region. template typename BitmapRegion2D::ConstIterator BitmapRegion2D::End (void) const { ConstIterator itEnd; // The iterator we construct. // Since extents can't be zero-length, a zero-length extent // indicates the end. itEnd.m_pThis = this; itEnd.m_oExtent.m_tnY = 0; itEnd.m_oExtent.m_tnXStart = 0; itEnd.m_oExtent.m_tnXEnd = 0; return itEnd; } // Move forward to the next extent. template typename BitmapRegion2D::ConstIterator& BitmapRegion2D::ConstIterator::operator++() { // Make sure we know what region we're iterating through. assert (m_pThis != NULL); // It does all the work. m_pThis->IteratorForward (*this); return *this; } // Move backward to the previous extent. template typename BitmapRegion2D::ConstIterator& BitmapRegion2D::ConstIterator::operator--() { // Make sure we know what region we're iterating through. assert (m_pThis != NULL); // It does all the work. m_pThis->IteratorBackward (*this); return *this; } // The set-bits-per-byte table. // Used to implement NumberOfPoints(). template int8_t BitmapRegion2D::m_anSetBitsPerByte[256]; template bool BitmapRegion2D::m_bSetBitsPerByte = false; // Default constructor. Must be followed by a call to Init(). template BitmapRegion2D::FloodFillControl::FloodFillControl() { // Nothing to do. } // Initializing constructor. template BitmapRegion2D::FloodFillControl::FloodFillControl (Status_t &a_reStatus, INDEX a_tnWidth, INDEX a_tnHeight) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Initialize ourselves. Init (a_reStatus, a_tnWidth, a_tnHeight); if (a_reStatus != g_kNoError) return; } // Initializer. Must be called on default-constructed objects. template void BitmapRegion2D::FloodFillControl::Init (Status_t &a_reStatus, INDEX a_tnWidth, INDEX a_tnHeight) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Initialize our helper regions. BaseClass::m_oToDo.Init (a_reStatus, a_tnWidth, a_tnHeight); if (a_reStatus != g_kNoError) return; BaseClass::m_oAlreadyDone.Init (a_reStatus, a_tnWidth, a_tnHeight); if (a_reStatus != g_kNoError) return; BaseClass::m_oNextToDo.Init (a_reStatus, a_tnWidth, a_tnHeight); if (a_reStatus != g_kNoError) return; } #ifndef NDEBUG template uint32_t BitmapRegion2D::sm_ulInstances; #endif // NDEBUG #endif // __BITMAPREGION2D_H__ mjpegtools-2.1.0/y4mdenoise/MotionSearcher.hh0000644000175000017500000027502011741063253021544 0ustar glowwormglowworm#ifndef __MOTION_SEARCHER_H__ #define __MOTION_SEARCHER_H__ // This file (C) 2004-2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. #include "config.h" #include #include "mjpeg_types.h" #include "TemplateLib.hh" #include "Limits.hh" #include "DoublyLinkedList.hh" #include "ReferenceFrame.hh" #include "SetRegion2D.hh" #include "BitmapRegion2D.hh" #include "Vector.hh" // HACK: for development error messages. #include // Define this to print region unions/subtractions. #ifdef DEBUG_REGION2D // #define PRINTREGIONMATH #endif // DEBUG_REGION2D // Define this to print details of the search-border's progress. #ifdef DEBUG_REGION2D // #define PRINT_SEARCHBORDER #endif // DEBUG_REGION2D // Define this to prevent reference-frame pixels from being used more // than once. #define USE_REFERENCEFRAMEPIXELS_ONCE // Define this to throttle the output of the pixel-sorter, using only // those matches with the lowest sum-of-absolute-differences. #define THROTTLE_PIXELSORTER_WITH_SAD // Define this to implement set-regions with vectors. // Don't define this to implement set-regions with skip-lists. #define SET_REGION_IMPLEMENTED_WITH_VECTOR // Define this to implement the SearchBorder's border-extent-boundary-sets // with vectors. // Don't define this to implement the SearchBorder's // border-extent-boundary-sets with skip-lists. // // (Even though this option is specific to the internals of SearchBorder, // it's defined here, since all of our other configuration switches are // here.) #define BORDEREXTENTBOUNDARYSET_IMPLEMENTED_WITH_VECTOR // Define this to use bitmap regions to implement zero-motion // flood-fill. #define ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS // Define this to use bitmap regions to implement match-throttle // flood-fill. #define MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS // Define this to use bitmap regions to implement pruning flood-fill. //#define PRUNING_FLOOD_FILL_WITH_BITMAP_REGIONS // Define this to use a bitmap region to implement the // used-reference-pixel region. Don't define it to use a set-based // region to implement the used-reference-pixel region. #define USED_REFERENCE_PIXELS_REGION_IS_BITMAP // We'll be using this variant of the search-border. // (SearchBorder uses SET_REGION_IMPLEMENTED_WITH_VECTOR to configure.) #include "SearchBorder.hh" // We'll be using this variant of the search-window. #ifdef EXPAND_REGIONS #define OPTIONALLY_SORT_PIXEL_GROUPS #endif // EXPAND_REGIONS #ifdef THROTTLE_PIXELSORTER_WITH_SAD #define CALCULATE_SAD #endif // THROTTLE_PIXELSORTER_WITH_SAD #include "SearchWindow.hh" #undef CALCULATE_SAD #undef OPTIONALLY_SORT_PIXEL_GROUPS // The generic motion-searcher class. It's parameterized by the size of // elements in the pixels, the dimension of the pixels, the numeric type // to use in tolerance calculations, the numeric type to use for pixel // indices, a numeric type big enough to hold the product of the largest // expected frame width/height, the width/height of pixel groups to // operate on, a numeric type big enough to hold pixel-dimension * // pixel-group-width * pixel-group-height bits and serve as an array // index, and the types of pixels, reference pixels, and reference // frames to operate on. When constructed, it's configured with the // number of frames over which to accumulate pixel values, the search // radius (in separate x and y directions), the error tolerances, and // throttle values for the number of matches and the size of matches. // // Pixel values are tracked over several frames. The idea is, if the // motion searcher can prove that a particular pixel in several frames // is really the same pixel, it can average together all the pixel's // values to calculate a more accurate value for it. Therefore, output // is delayed by the number of frames specified in the constructor, to // give the motion-searcher the slack to do this. // // The motion-searcher works on groups of pixels. It iterates through a // frame, looking for groups of pixels within the search radius that // match the current group (within the error tolerance). It sorts the // found pixel-groups by sum-of-absolute-differences, keeps the best // match-count-throttle matches, and flood-fills each one, storing the // results in the search-border. Future pixel-sorter matches are // checked against this set, to filter out duplicate matches (and the // associated flood-fills). // // Since this process can generate a lot of information, two throttles // are used -- one on the number of matches, and one on the size of the // largest match. If either is exceeded, the largest matches found are // applied to the frame before searching finishes, until neither throttle // is exceeded. This decreases the amount of work to finish the search, // since some of the frame has been resolved already. If the throttle // values are too low, quality may be impacted, but if the throttle // values are too high, performance may be impacted. // // Similarly, if there are no matches for the current pixel-group, then // it is considered new information, and new reference pixels are // allocated for the group and applied to the new frame before the // search is finished. However, these pixels may be overwritten later // by regions that are applied to the frame. This attempts to improve // the efficiency of processing frames that don't match the previous // frame, in a way that doesn't impact quality. // // Once the entire frame has been searched, the found regions are // applied to the frame, from largest match to smallest, and always // flood-filled first to get rid of any resolved pixels. If such a region // is no longer the largest region, it's put back into the pool, and the // largest remaining region is evaluated instead. // // Any areas of the frame not resolved by this method are new // information, and new reference pixels are allocated for them. template , class REFERENCEPIXEL = ReferencePixel, class REFERENCEFRAME = ReferenceFrame > class MotionSearcher { public: typedef PIXEL Pixel_t; // Our pixel type. typedef REFERENCEPIXEL ReferencePixel_t; // Our reference pixel type. typedef REFERENCEFRAME ReferenceFrame_t; // Our reference frame type. typedef PIXEL_NUM PixelValue_t; // The numeric type to use in pixel values, in each dimension // of our pixels. typedef PIXEL_TOL Tolerance_t; // The numeric type to use in tolerance calculations. MotionSearcher(); // Default constructor. virtual ~MotionSearcher(); // Destructor. void Init (Status_t &a_reStatus, int a_nFrames, PIXELINDEX a_tnWidth, PIXELINDEX a_tnHeight, PIXELINDEX a_tnSearchRadiusX, PIXELINDEX a_tnSearchRadiusY, PixelValue_t a_nZeroTolerance, PixelValue_t a_nTolerance, FRAMESIZE a_nMatchCountThrottle, FRAMESIZE a_nMatchSizeThrottle); // Initializer. Provide the number of frames over which to // accumulate pixel data, the dimensions of the frames, the // search radius, the error tolerances, and the match throttles. const ReferenceFrame_t *GetFrameReadyForOutput (void); // If a frame is ready to be output, return it, otherwise return // NULL. // Call this once before each call to AddFrame(), to ensure that // AddFrame() has the space to accept another frame. Note that // this implies the data in the returned frame will be // invalidated by AddFrame(). void AddFrame (Status_t &a_reStatus, const Pixel_t *a_pPixels); // Add another frame to be analyzed into the system. // The digested version will eventually be returned by either // GetFrameReadyForOutput() or GetRemainingFrames(). const ReferenceFrame_t *GetRemainingFrames (void); // Once there is no more input, call this repeatedly to get the // details of the remaining frames, until it returns NULL. void Purge (void); // Purge ourselves of temporary structures that aren't normally // freed at the end of a frame. (Most are.) // Should be called every once in a while (e.g. every 10 frames). private: int m_nFrames; // The number of reference frames we use. PIXELINDEX m_tnWidth; PIXELINDEX m_tnHeight; FRAMESIZE m_tnPixels; // The dimensions of each reference frame. PIXELINDEX m_tnSearchRadiusX, m_tnSearchRadiusY; // The search radius, i.e. how far from the current pixel // group we look when searching for possible moved instances of // the group. Tolerance_t m_tnTolerance, m_tnTwiceTolerance; // The error tolerance, i.e. the largest difference we're // willing to tolerate between pixels before considering them // to be the same pixel. Also, twice the tolerance. Tolerance_t m_tnZeroTolerance; // The error tolerance for the zero-motion pass. FRAMESIZE m_nMatchCountThrottle; // How many matches we're willing to have for the current // pixel group before we just flood-fill the largest one and // apply it now. FRAMESIZE m_nMatchSizeThrottle; // The size (measured in number of pixels) that the largest // region in the area of the current pixel-group can be before // we just flood-fill the largest one and apply it now. PixelAllocator m_oPixelPool; // Our source for new reference pixels. ReferenceFrame_t **m_ppFrames; // Our reference frames; an array of pointers to frames. int m_nFirstFrame, m_nLastFrame; // The range of frames that contain useful info. // When both equal 0, no frames contain useful info. // When m_nFirstFrame is 0 and m_nLastFrame is m_nFrames, // it's time for GetFrameReadyForOutput() to emit a frame. // When m_nFirstFrame is greater than zero but less than // m_nLastFrame, it means our client is calling // GetRemainingFrames(). ReferenceFrame_t *m_pNewFrame; // The reference-frame representation of the new frame. // Points to one of the instances in m_ppFrames[]. ReferenceFrame_t *m_pReferenceFrame; // The reference frame, against which the new frame is // compared. // Points to one of the instances in m_ppFrames[]. const Pixel_t *m_pNewFramePixels; // The pixels of the new frame (i.e. the raw version). PIXELINDEX m_tnX, m_tnY; // The index of the current pixel group. Actually the index // of the top-left pixel in the current pixel group. This // gets moved in a zigzag pattern, back and forth across the // frame and then down, until the end of the frame is reached. PIXELINDEX m_tnStepX; // Whether we're zigging or zagging. typedef Region2D BaseRegion_t; // The base class for all our region types. #ifdef SET_REGION_IMPLEMENTED_WITH_VECTOR typedef Vector, Less > RegionImp_t; #else // SET_REGION_IMPLEMENTED_WITH_VECTOR typedef SkipList, Less > RegionImp_t; #endif // SET_REGION_IMPLEMENTED_WITH_VECTOR // The container class that implements our set-based region. typedef SetRegion2D Region_t; typedef typename Region_t::Allocator RegionAllocator_t; // How we use SetRegion2D<>. typedef BitmapRegion2D BitmapRegion_t; // How we use BitmapRegion2D<>. typedef SearchBorder BaseSearchBorder_t; // The base class for the type of search-border we'll be using. typedef typename BaseSearchBorder_t::MovedRegion MovedRegion; // A moved region of pixels that has been detected. RegionAllocator_t m_oRegionAllocator; // Used by all our set-regions to allocate space for their extents. typedef Set MovedRegionSet; typedef typename MovedRegionSet::Allocator MovedRegionAllocator_t; MovedRegionAllocator_t m_oMovedRegionSetAllocator; MovedRegionSet m_setRegions; // All moving areas detected so far. // Sorted by decreasing size, then increasing motion vector // length, i.e. the order in which they should be applied to // the reference-frame version of the new frame. #ifdef USED_REFERENCE_PIXELS_REGION_IS_BITMAP BitmapRegion_t m_oUsedReferencePixels; #else // USED_REFERENCE_PIXELS_REGION_IS_BITMAP Region_t m_oUsedReferencePixels; #endif // USED_REFERENCE_PIXELS_REGION_IS_BITMAP // The region describing all parts of the reference frame that // have been found in the new frame. #ifdef USED_REFERENCE_PIXELS_REGION_IS_BITMAP BitmapRegion_t m_oTestedZeroMotionPixels; #else // USED_REFERENCE_PIXELS_REGION_IS_BITMAP Region_t m_oTestedZeroMotionPixels; #endif // USED_REFERENCE_PIXELS_REGION_IS_BITMAP // The region describing all parts of the reference frame that // have been tested in the zero-motion pass. MovedRegion m_oMatchThrottleRegion; // The region that's applied to the frame before motion // detection is finished. Allocated here to avoid lots of // creation & destruction. #ifdef MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS BitmapRegion_t m_oFloodFillRegion; #endif // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS // The region that does the flood-filling for the // match-throttle-region. void ApplyRegionToNewFrame (Status_t &a_reStatus, const MovedRegion &a_rRegion); // Apply this region to the new frame. typedef SearchWindow SearchWindow_t; // The type of search-window we'll be using. SearchWindow_t m_oSearchWindow; // The search window. It contains all the cells needed to // analyze the image. #ifdef THROTTLE_PIXELSORTER_WITH_SAD // A pixel group that matches the current pixel-group, with the // given sum-of-absolute-differences. class MatchedPixelGroup { public: Tolerance_t m_tnSAD; // The sum-of-absolute-differences. const typename SearchWindow_t::PixelGroup *m_pGroup; // The pixel group. MatchedPixelGroup(); // Default constructor. MatchedPixelGroup (Tolerance_t a_tnSAD, const typename SearchWindow_t::PixelGroup *a_pGroup); // Initializing constructor. ~MatchedPixelGroup(); // Destructor. // A comparison class, suitable for Set<>. class SortBySAD { public: inline bool operator() (const MatchedPixelGroup &a_rLeft, const MatchedPixelGroup &a_rRight) const; }; }; typedef Set MatchedPixelGroupSet; typedef typename MatchedPixelGroupSet::Allocator MPGS_Allocator_t; // The type for a set of matched pixel-groups. MPGS_Allocator_t m_oMatchAllocator; MatchedPixelGroupSet m_setMatches; // All the matches for the current pixel-group that we // want to use. #endif // THROTTLE_PIXELSORTER_WITH_SAD // The search-border, specialized to put completed regions into // m_setRegions. class SearchBorder_t : public BaseSearchBorder_t { private: typedef BaseSearchBorder_t BaseClass; // Keep track of who our base class is. public: SearchBorder_t (MovedRegionSet &a_rsetRegions, typename MovedRegion::Allocator &a_rAlloc = MovedRegion::Extents::Imp::sm_oNodeAllocator); // Constructor. Provide a reference to the set where // completed regions will be stored. virtual void OnCompletedRegion (Status_t &a_reStatus, typename SearchBorder_t::MovedRegion *a_pRegion); // Tell BaseSearchBorder_t how to hand us a completed region. private: MovedRegionSet &m_rsetRegions; // A reference to our list of completed regions. }; SearchBorder_t m_oSearchBorder; // The search border, i.e. all regions on the border between // the searched area and the not-yet-searched area, the regions // still under construction. FRAMESIZE SearchBorder_AddNewRegion (Status_t &a_reStatus, PIXELINDEX a_tnMotionX, PIXELINDEX a_tnMotionY); // Add a new region, with the given motion vector, to the // search border. // Flood-fills its area before adding. // Returns the size of the added region. FRAMESIZE SearchBorder_MatchThrottle (Status_t &a_reStatus, FRAMESIZE a_nMatchCount, PIXELINDEX &a_rtnMotionX, PIXELINDEX &a_rtnMotionY); // Get the best region that matched the current pixel-group // (which is usually the largest active-region). Expand it as far // as it can go, i.e. flood-fill in its area. If it's no longer // the largest region, put it back and try again. Otherwise, apply // it to the new frame now. // // Pass the number of pixel-group matches as an argument. If a // best-region candidate is found to have no unresolved pixels, // it's no longer considered a pixel-group match, and that may lead // to the discovery that the match-count-throttle is no longer // being exceeded. // // Returns the number of points flood-filled, and backpatches the // motion vector associated with the best region. // May return zero if analysis reveals that the match-throttles // weren't really exceeded. // A class that helps implement the zero-motion flood-fill. class ZeroMotionFloodFillControl #ifdef ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS : public BitmapRegion_t::FloodFillControl #else // ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS : public Region_t::FloodFillControl #endif // ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS { private: #ifdef ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS typedef typename BitmapRegion_t::FloodFillControl BaseClass; // Keep track of who our base class is. #else // ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS typedef typename Region_t::FloodFillControl BaseClass; // Keep track of who our base class is. #endif // ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS MotionSearcher *m_pMotionSearcher; // The motion-searcher we're working for. public: #ifdef ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS ZeroMotionFloodFillControl(); #else // ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS ZeroMotionFloodFillControl (typename BaseClass::Allocator &a_rAllocator = Region_t::Extents::Imp::sm_oNodeAllocator); #endif // ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS // Default constructor. Must be followed by Init(). void Init (Status_t &a_reStatus, MotionSearcher *a_pMotionSearcher); // Initializer. // Redefined FloodFillControl methods. bool ShouldUseExtent (typename ZeroMotionFloodFillControl::BaseClass::Extent &a_rExtent); // Return true if the flood-fill should examine the given // extent. May modify the extent. bool IsPointInRegion (PIXELINDEX a_tnX, PIXELINDEX a_tnY); // Returns true if the given point should be included in the // flood-fill. }; friend class ZeroMotionFloodFillControl; // Allow the zero-motion flood-fill-control class direct access. ZeroMotionFloodFillControl m_oZeroMotionFloodFillControl; // Used to implement flood-filling the result of the // zero-motion search. // A class that helps implement the match-throttle flood-fill. class MatchThrottleFloodFillControl #ifdef MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS : public BitmapRegion_t::FloodFillControl #else // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS : public Region_t::FloodFillControl #endif // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS { private: #ifdef MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS typedef typename BitmapRegion_t::FloodFillControl BaseClass; // Keep track of who our base class is. #else // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS typedef typename Region_t::FloodFillControl BaseClass; // Keep track of who our base class is. #endif // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS public: #ifdef MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS MatchThrottleFloodFillControl(); #else // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS MatchThrottleFloodFillControl (typename BaseClass::Allocator &a_rAllocator = Region_t::Extents::Imp::sm_oNodeAllocator); #endif // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS // Default constructor. Must be followed by Init(). void Init (Status_t &a_reStatus, MotionSearcher *a_pMotionSearcher); // Initializer. void SetupForFloodFill (PIXELINDEX a_tnMotionX, PIXELINDEX a_tnMotionY); // Set up to to a flood-fill. Provide the motion vector. // Call this before doing a flood-fill with this control // object. // Redefined FloodFillControl methods. bool ShouldUseExtent (typename Region_t::Extent &a_rExtent); // Return true if the flood-fill should examine the given // extent. May modify the extent. bool IsPointInRegion (PIXELINDEX a_tnX, PIXELINDEX a_tnY); // Returns true if the given point should be included in the // flood-fill. private: MotionSearcher *m_pMotionSearcher; // The motion-searcher we're working for. PIXELINDEX m_tnMotionX, m_tnMotionY; // The motion vector to be used for this flood-fill. }; friend class MatchThrottleFloodFillControl; // Allow the match-throttle flood-fill-control class direct access. MatchThrottleFloodFillControl m_oMatchThrottleFloodFillControl; // Used to implement flood-filling a region before // motion-searching is done. // A class that helps implement the pruning flood-fill, i.e. the one // that removes resolved pixels from a candidate moved-region. class PruningFloodFillControl #ifdef PRUNING_FLOOD_FILL_WITH_BITMAP_REGIONS : public BitmapRegion_t::FloodFillControl #else // PRUNING_FLOOD_FILL_WITH_BITMAP_REGIONS : public Region_t::FloodFillControl #endif // PRUNING_FLOOD_FILL_WITH_BITMAP_REGIONS { private: #ifdef PRUNING_FLOOD_FILL_WITH_BITMAP_REGIONS typedef typename BitmapRegion_t::FloodFillControl BaseClass; // Keep track of who our base class is. #else // PRUNING_FLOOD_FILL_WITH_BITMAP_REGIONS typedef typename Region_t::FloodFillControl BaseClass; // Keep track of who our base class is. #endif // PRUNING_FLOOD_FILL_WITH_BITMAP_REGIONS public: #ifdef PRUNING_FLOOD_FILL_WITH_BITMAP_REGIONS PruningFloodFillControl(); #else // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS PruningFloodFillControl (typename BaseClass::Allocator &a_rAllocator = Region_t::Extents::Imp::sm_oNodeAllocator); #endif // PRUNING_FLOOD_FILL_WITH_BITMAP_REGIONS // Default constructor. Must be followed by Init(). void Init (Status_t &a_reStatus, MotionSearcher *a_pMotionSearcher); // Initializer. void SetupForFloodFill (PIXELINDEX a_tnMotionX, PIXELINDEX a_tnMotionY); // Set up to to a flood-fill. Provide the motion vector. // Call this before doing a flood-fill with this control // object. // Redefined FloodFillControl methods. bool ShouldUseExtent (typename Region_t::Extent &a_rExtent); // Return true if the flood-fill should examine the given // extent. May modify the extent. bool IsPointInRegion (PIXELINDEX a_tnX, PIXELINDEX a_tnY); // Returns true if the given point should be included in the // flood-fill. private: MotionSearcher *m_pMotionSearcher; // The motion-searcher we're working for. PIXELINDEX m_tnMotionX, m_tnMotionY; // The motion vector to be used for this flood-fill. }; friend class PruningFloodFillControl; // Allow the zero-motion flood-fill-control class direct access. PruningFloodFillControl m_oPruningFloodFillControl; // Used to implement flood-filling a region to remove any // resolved pixels. }; // Default constructor. template MotionSearcher::MotionSearcher() : m_oRegionAllocator (1048576), m_oMovedRegionSetAllocator (262144), m_setRegions (typename MovedRegion::SortBySizeThenMotionVectorLength(), m_oMovedRegionSetAllocator), m_oMatchThrottleRegion (m_oRegionAllocator), #ifdef THROTTLE_PIXELSORTER_WITH_SAD m_oMatchAllocator (65536), m_setMatches (typename MatchedPixelGroup::SortBySAD(), m_oMatchAllocator), #endif // THROTTLE_PIXELSORTER_WITH_SAD m_oSearchBorder (m_setRegions, m_oRegionAllocator) #ifndef ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS , m_oZeroMotionFloodFillControl (m_oRegionAllocator) #endif // ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS #ifndef MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS , m_oMatchThrottleFloodFillControl (m_oRegionAllocator) #endif // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS #ifndef PRUNING_FLOOD_FILL_WITH_BITMAP_REGIONS , m_oPruningFloodFillControl (m_oRegionAllocator) #endif // PRUNING_FLOOD_FILL_WITH_BITMAP_REGIONS { // No frames yet. m_nFrames = 0; m_ppFrames = NULL; m_nFirstFrame = m_nLastFrame = 0; m_tnWidth = m_tnHeight = PIXELINDEX (0); m_tnPixels = FRAMESIZE (0); // No information on the sort of search to do yet. m_tnSearchRadiusX = m_tnSearchRadiusY = PIXELINDEX (0); m_tnZeroTolerance = m_tnTolerance = m_tnTwiceTolerance = PIXEL_TOL (0); m_nMatchCountThrottle = 0; m_nMatchSizeThrottle = 0; // No active search yet. m_tnX = m_tnY = m_tnStepX = PIXELINDEX (0); m_pNewFrame = NULL; m_pReferenceFrame = NULL; m_pNewFramePixels = NULL; } // Destructor. template MotionSearcher::~MotionSearcher() { // Free up any remaining moved regions. (Testing for a non-zero // size is defined to be safe even if the set hasn't been // initialized, i.e. if we get destroyed before our Init() has been // called.) if (m_setRegions.Size() > 0) { typename MovedRegionSet::Iterator itHere; // The location of the next region to destroy. // Loop through the moved-regions set, remove each item, // destroy it. while (itHere = m_setRegions.Begin(), itHere != m_setRegions.End()) { // Get the moved-region to destroy. MovedRegion *pRegion = *itHere; // Remove it from the set. m_setRegions.Erase (itHere); // Destroy the region. m_oSearchBorder.DeleteRegion (pRegion); } } // Destroy the reference frames. for (int i = 0; i < m_nFrames; i++) { m_ppFrames[i]->Reset(); delete m_ppFrames[i]; } delete[] m_ppFrames; } // Initializer. template void MotionSearcher::Init (Status_t &a_reStatus, int a_nFrames, PIXELINDEX a_tnWidth, PIXELINDEX a_tnHeight, PIXELINDEX a_tnSearchRadiusX, PIXELINDEX a_tnSearchRadiusY, PixelValue_t a_tnZeroTolerance, PixelValue_t a_tnTolerance, FRAMESIZE a_nMatchCountThrottle, FRAMESIZE a_nMatchSizeThrottle) { int i; // Used to loop through things. FRAMESIZE tnPixels; // The number of pixels in each frame. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure they gave us a reasonable number of frames. // (We need at least one for the new frame and one to // compare against the new frame. We prefer more.) assert (a_nFrames >= 2); // Make sure the width & height are reasonable. assert (a_tnWidth > PIXELINDEX (0)); assert (a_tnHeight > PIXELINDEX (0)); // Make sure the search radius is reasonable. assert (a_tnSearchRadiusX > PIXELINDEX (0) && a_tnSearchRadiusY > PIXELINDEX (0) && a_tnSearchRadiusX <= a_tnWidth && a_tnSearchRadiusY <= a_tnHeight); // Make sure the match throttles are reasonable. assert (a_nMatchCountThrottle >= 0 && a_nMatchCountThrottle <= a_tnSearchRadiusX * a_tnSearchRadiusY); assert (a_nMatchSizeThrottle > 0); // Calculate the number of pixels in each frame. tnPixels = FRAMESIZE (a_tnWidth) * FRAMESIZE (a_tnHeight); // Initialize our pixel pool. m_oPixelPool.Initialize (a_reStatus, tnPixels * FRAMESIZE (a_nFrames)); if (a_reStatus != g_kNoError) return; // Allocate space for our pointers to frames. m_ppFrames = new ReferenceFrame_t * [a_nFrames]; if (m_ppFrames == NULL) { a_reStatus = g_kOutOfMemory; return; } // (Initialize each one to NULL, in case we run out of memory while // trying to allocate frames -- if we don't do this, we'll end up // trying to delete garbage pointers.) for (i = 0; i < a_nFrames; ++i) m_ppFrames[i] = NULL; // (Save this parameter now, to make it possible to destroy an // incompletely-initialized object.) m_nFrames = a_nFrames; // Allocate our reference frames. for (i = 0; i < a_nFrames; ++i) { // Allocate the next reference frame. m_ppFrames[i] = new ReferenceFrame_t (a_reStatus, a_tnWidth, a_tnHeight); if (m_ppFrames[i] == NULL) { a_reStatus = g_kOutOfMemory; return; } if (a_reStatus != g_kNoError) return; } // Initialize the search-window. m_oSearchWindow.Init (a_reStatus, a_tnWidth, a_tnHeight, a_tnSearchRadiusX, a_tnSearchRadiusY, a_tnTolerance); if (a_reStatus != g_kNoError) return; // Initialize our set of matches. (We'll use this to sort the // incoming matches by how closely it matches the current // pixel-group, and we'll throw away fuzzier matches.) #ifdef THROTTLE_PIXELSORTER_WITH_SAD typename MatchedPixelGroupSet::InitParams oInitSetMatches (rand(), true /* allocate internal nodes from allocator */); m_setMatches.Init (a_reStatus, true, oInitSetMatches); if (a_reStatus != g_kNoError) return; #endif // THROTTLE_PIXELSORTER_WITH_SAD // Initialize our moved-regions set. m_setRegions.Init (a_reStatus, true); if (a_reStatus != g_kNoError) return; // Initialize the moved-region extents allocator. #ifdef SET_REGION_IMPLEMENTED_WITH_VECTOR m_oRegionAllocator.Init (a_reStatus); if (a_reStatus != g_kNoError) return; #endif // SET_REGION_IMPLEMENTED_WITH_VECTOR // Initialize our used reference-pixels container. #ifdef USED_REFERENCE_PIXELS_REGION_IS_BITMAP m_oUsedReferencePixels.Init (a_reStatus, a_tnWidth, a_tnHeight); #else // USED_REFERENCE_PIXELS_REGION_IS_BITMAP m_oUsedReferencePixels.Init (a_reStatus, m_oRegionAllocator); #endif // USED_REFERENCE_PIXELS_REGION_IS_BITMAP if (a_reStatus != g_kNoError) return; #if defined (USED_REFERENCE_PIXELS_REGION_IS_BITMAP) #if defined (DEBUG_REGION2D) // HACK: too expensive, test region class elsewhere. m_oUsedReferencePixels.SetDebug (false); #endif // DEBUG_REGION2D #endif // USED_REFERENCE_PIXELS_REGION_IS_BITMAP // Initialize our tested zero-motion-pixels container. #ifdef USED_REFERENCE_PIXELS_REGION_IS_BITMAP m_oTestedZeroMotionPixels.Init (a_reStatus, a_tnWidth, a_tnHeight); #else // USED_REFERENCE_PIXELS_REGION_IS_BITMAP m_oTestedZeroMotionPixels.Init (a_reStatus, m_oRegionAllocator); #endif // USED_REFERENCE_PIXELS_REGION_IS_BITMAP if (a_reStatus != g_kNoError) return; #if defined (USED_REFERENCE_PIXELS_REGION_IS_BITMAP) #if defined (DEBUG_REGION2D) // HACK: too expensive, test region class elsewhere. m_oTestedZeroMotionPixels.SetDebug (false); #endif // DEBUG_REGION2D #endif // USED_REFERENCE_PIXELS_REGION_IS_BITMAP // Initialize our match-throttle region. m_oMatchThrottleRegion.Init (a_reStatus); if (a_reStatus != g_kNoError) return; // Initialize the region that does the flood-filling for the // match-throttle-region. #ifdef MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS m_oFloodFillRegion.Init (a_reStatus, a_tnWidth, a_tnHeight); if (a_reStatus != g_kNoError) return; #if defined (DEBUG_REGION2D) // HACK: too expensive, test region class elsewhere. m_oFloodFillRegion.SetDebug (false); #endif // DEBUG_REGION2D #endif // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS // Initialize the search-border. // Note that the search-border is not given the value of // the externally-set match-size-throttle. That was done // back when throttling happened at the end of a pixel-group // search if any of the resulting regions exceeded the // match-size-throttle. Now, those large regions are kept // in the search-border until all the new conditions for // throttling are met. m_oSearchBorder.Init (a_reStatus, a_tnWidth, a_tnHeight, a_tnSearchRadiusX, a_tnSearchRadiusY, PGW, PGH, /* a_nMatchSizeThrottle */ a_tnWidth * a_tnHeight); if (a_reStatus != g_kNoError) return; // Finally, store our parameters. (Convert the tolerance value to // the format used internally.) //m_nFrames = a_nFrames; (Stored above) m_tnWidth = a_tnWidth; m_tnHeight = a_tnHeight; m_tnPixels = tnPixels; m_tnSearchRadiusX = a_tnSearchRadiusX; m_tnSearchRadiusY = a_tnSearchRadiusY; m_tnZeroTolerance = Pixel_t::MakeTolerance (a_tnZeroTolerance); m_tnTolerance = Pixel_t::MakeTolerance (a_tnTolerance); m_tnTwiceTolerance = Pixel_t::MakeTolerance (PixelValue_t (2) * a_tnTolerance); m_nMatchCountThrottle = a_nMatchCountThrottle; m_nMatchSizeThrottle = a_nMatchSizeThrottle; // Initialize our flood-fill controllers. (This happens after we // store our parameters, because these methods may need those // values.) m_oZeroMotionFloodFillControl.Init (a_reStatus, this); if (a_reStatus != g_kNoError) return; m_oMatchThrottleFloodFillControl.Init (a_reStatus, this); if (a_reStatus != g_kNoError) return; m_oPruningFloodFillControl.Init (a_reStatus, this); if (a_reStatus != g_kNoError) return; } // If a frame is ready to be output, return it, otherwise return // NULL. template const typename MotionSearcher::ReferenceFrame_t * MotionSearcher::GetFrameReadyForOutput (void) { ReferenceFrame_t *pFrame; // The frame to return to the caller. int i; // Used to loop through things. // If we have space for the new frame in our reference frames, then // it's not time to emit a frame yet. (We delay emitting frames for // as long as possible, in order to calculate the most accurate // pixel values.) if (m_nFirstFrame != 0 || m_nLastFrame != m_nFrames) return NULL; // Get the frame to return to the caller. pFrame = m_ppFrames[0]; // Shift the remaining frames down. for (i = 1; i < m_nFrames; ++i) m_ppFrames[i - 1] = m_ppFrames[i]; // Our caller will read the data in the frame. By the time the // caller calls AddFrame(), we'll need to use this frame again. // So put it at the end of the list. --m_nLastFrame; m_ppFrames[m_nLastFrame] = pFrame; // Finally, return the frame to our caller. return pFrame; } // HACK: developer debugging output. extern "C" { extern int frame, verbose; }; // Add another frame to be analyzed into the system. template void MotionSearcher::AddFrame (Status_t &a_reStatus, const Pixel_t *a_pPixels) { FRAMESIZE i; // Used to loop through pixels. FRAMESIZE tnNotMovedZeroMotionPixels, tnNotMovedThrottledPixels, tnNotMovedPixels, tnMovedThrottledPixels, tnMovedPixels, tnNoMatchNewPixels, tnNewPixels; // Statistics on the result of our analysis -- the number of // pixels that didn't move, the number that moved, the number // found by flood-filling, and the number of new pixels. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure we can accept a new frame. assert (m_nFirstFrame == 0 && m_nLastFrame < m_nFrames); // Get the reference frame that will become the new frame. m_pNewFrame = m_ppFrames[m_nLastFrame]; m_pNewFramePixels = a_pPixels; // Reset the new frame, so that it doesn't refer to any pixels. // (This frame was previously returned by GetFrameReadyForOutput(), // so it wasn't safe to reset it until now.) m_pNewFrame->Reset(); // Reset our statistics. tnNotMovedZeroMotionPixels = tnNotMovedThrottledPixels = tnNotMovedPixels = tnMovedThrottledPixels = tnMovedPixels = tnNoMatchNewPixels = tnNewPixels = FRAMESIZE (0); // If there is a previous frame, do motion-detection against it. if (m_nFirstFrame != m_nLastFrame) { PIXELINDEX tnLastX, tnLastY; // Used to zigzag through the frame. // Get the reference frame, i.e. the one that we'll do // motion-detection against. (For now, that's the previous // frame. Eventually, we'd like to do motion-detection against // several previous frames, but not yet.) m_pReferenceFrame = m_ppFrames[m_nLastFrame - 1]; // Prepare to search within this frame. m_oSearchWindow.StartFrame (m_pReferenceFrame); m_oSearchBorder.StartFrame (a_reStatus); if (a_reStatus != g_kNoError) return; // Start by processing parts of the image that aren't moving. // Loop through pixel-group-sized chunks of the image, find // pixel-groups within the specified tolerance, and flood-fill // them. If the resulting region exceeds the match-size-throttle, // apply it now. Either way, remember the region that was found // (so that the region doesn't have to be found again). // // Skip if they specified a zero for the tolerance. m_oUsedReferencePixels.Clear(); m_oTestedZeroMotionPixels.Clear(); if (m_tnZeroTolerance != 0) { m_tnY = 0; for (;;) { PIXELINDEX tnPixelX, tnPixelY; // Used to loop through pixels in the pixel-group. m_tnX = 0; for (;;) { ReferencePixel_t *pPrevPixel; // The pixel from the previous frame. #ifdef ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS typename BitmapRegion_t::ConstIterator itExtent; #endif // ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS // Used to convert between region types. // Loop through the pixels to compare, see if they all // match within the tolerance. for (tnPixelY = m_tnY; tnPixelY < m_tnY + PGH; ++tnPixelY) { for (tnPixelX = m_tnX; tnPixelX < m_tnX + PGW; ++tnPixelX) { // If a pixel in this pixel-group has already // been tested in this pass, skip it. if (m_oTestedZeroMotionPixels.DoesContainPoint (tnPixelY, tnPixelX)) goto noMatch; // Get the two pixels to compare. pPrevPixel = m_pReferenceFrame->GetPixel (tnPixelX, tnPixelY); assert (pPrevPixel != NULL); const Pixel_t &rPrevPixel = pPrevPixel->GetValue(); const Pixel_t &rNewPixel = a_pPixels[tnPixelY * m_tnWidth + tnPixelX]; // Compare them. if (!rPrevPixel.IsWithinTolerance (rNewPixel, m_tnZeroTolerance)) { // No match. goto noMatch; } } } // These pixels are within the zero-motion tolerance. // Set up a region describing the current pixel-group. #ifdef ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS m_oFloodFillRegion.Clear(); for (tnPixelY = m_tnY; tnPixelY < m_tnY + PGH; ++tnPixelY) { m_oFloodFillRegion.Merge (a_reStatus, tnPixelY, m_tnX, m_tnX + PGW); if (a_reStatus != g_kNoError) return; } #else // ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS m_oMatchThrottleRegion.Clear(); for (tnPixelY = m_tnY; tnPixelY < m_tnY + PGH; ++tnPixelY) { m_oMatchThrottleRegion.Merge (a_reStatus, tnPixelY, m_tnX, m_tnX + PGW); if (a_reStatus != g_kNoError) return; } #endif // ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS // Set its motion vector. m_oMatchThrottleRegion.SetMotionVector (0, 0); // Set its location. (Needed only for debugging // purposes.) #ifndef NDEBUG m_oMatchThrottleRegion.m_tnX = m_tnX; m_oMatchThrottleRegion.m_tnY = m_tnY; #endif // !NDEBUG // Flood-fill this match, so as to get its full extent. #ifdef ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS m_oFloodFillRegion.FloodFill (a_reStatus, m_oZeroMotionFloodFillControl, false, true); #else // ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS m_oMatchThrottleRegion.FloodFill (a_reStatus, m_oZeroMotionFloodFillControl, false, true); #endif // ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS if (a_reStatus != g_kNoError) return; // Now copy the results of the flood-fill to the // match-throttle region. #ifdef ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS m_oMatchThrottleRegion.Clear(); for (itExtent = m_oFloodFillRegion.Begin(); itExtent != m_oFloodFillRegion.End(); ++itExtent) { // Get the current extent. const typename BitmapRegion_t::Extent &rExtent = *itExtent; // Copy it to the match-throttle region. m_oMatchThrottleRegion.Union (a_reStatus, rExtent.m_tnY, rExtent.m_tnXStart, rExtent.m_tnXEnd); if (a_reStatus != g_kNoError) return; } #endif // ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS // All of these reference pixels have been tested. // There's no need to test them again. { typename MovedRegion::ConstIterator itExtent; for (itExtent = m_oMatchThrottleRegion.Begin(); itExtent != m_oMatchThrottleRegion.End(); ++itExtent) { // Get the current extent. const typename MovedRegion::Extent &rExtent = *itExtent; // Add it to our running total of tested // zero-motion reference-pixels. m_oTestedZeroMotionPixels.Union (a_reStatus, rExtent.m_tnY, rExtent.m_tnXStart, rExtent.m_tnXEnd); if (a_reStatus != g_kNoError) return; } } // If this match is larger than the // match-size-throttle, apply it now. if (m_oMatchThrottleRegion.NumberOfPoints() >= m_nMatchSizeThrottle) { // Apply this region to the new frame. ApplyRegionToNewFrame (a_reStatus, m_oMatchThrottleRegion); if (a_reStatus != g_kNoError) return; // That's more resolved pixels. tnNotMovedZeroMotionPixels += m_oMatchThrottleRegion.NumberOfPoints(); // Clean up after ourselves. m_oMatchThrottleRegion.Clear(); } // Otherwise, just dispose of it. // m_oTestedZeroMotionPixels will prevent us from // finding it again. else m_oMatchThrottleRegion.Clear(); noMatch: // Now move X forward, but in a way that handles // frames whose dimensions are not even multiples of // the pixel-group dimension. if (m_tnX + PGW == m_tnWidth) break; m_tnX += PGW; if (m_tnX > m_tnWidth - PGW) m_tnX = m_tnWidth - PGW; } // Now move Y forward, but in a way that handles // frames whose dimensions are not even multiples of // the pixel-group dimension. if (m_tnY + PGH == m_tnHeight) break; m_tnY += PGH; if (m_tnY > m_tnHeight - PGH) m_tnY = m_tnHeight - PGH; } // Clean up after ourselves. m_oTestedZeroMotionPixels.Clear(); } // Now do the motion-compensated denoising. Start in the // upper-left corner of the frame, and zigzag down the frame // (i.e. move all the way right, then down one line, then all // the way left, then down one line, etc.). Look for matches // for the current pixel-group in the reference frame, and // build regions of such matches. // // (Skip it if they turned motion-detection off.) if (m_tnTolerance > 0) { // Start searching in the upper-left corner, and prepare to // move right. m_tnX = m_tnY = 0; tnLastX = m_tnWidth - PGW; tnLastY = m_tnHeight - PGH; m_tnStepX = 1; // Loop until the entire frame has been searched. for (;;) { typename SearchWindow_t::PixelGroup oCurrentGroup; // The current pixel-group. typename SearchWindow_t::PixelSorterIterator itMatch; // Used to search for matches for the current // pixel-group. #ifdef THROTTLE_PIXELSORTER_WITH_SAD typename MatchedPixelGroupSet::ConstIterator itBestMatch; // One of the best matches found. Tolerance_t tnSAD; // The sum-of-absolute-differences between the // current pixel group and the match. #endif // THROTTLE_PIXELSORTER_WITH_SAD const typename SearchWindow_t::PixelGroup *pMatch; // A pixel-group that matches the current pixel, // within the configured tolerance. FRAMESIZE tnMatches; // The number of matches found. // Create the current pixel-group. If any of its pixels // have been resolved, skip it. { PIXELINDEX x, y; // Used to loop through the current // pixel-group's pixels. for (y = 0; y < PGH; ++y) { for (x = 0; x < PGW; ++x) { PIXELINDEX tnPixelX, tnPixelY; // The index of the current pixel. // Calculate the index of the current pixel. tnPixelX = m_tnX + x; tnPixelY = m_tnY + y; // If this pixel has been resolved already, // skip this pixel-group. if (m_pNewFrame->GetPixel (tnPixelX, tnPixelY) != NULL) goto nextGroup; // Set the pixel value in the pixel-group. oCurrentGroup.m_atPixels[y][x] = a_pPixels[FRAMESIZE (tnPixelY) * FRAMESIZE (m_tnWidth) + FRAMESIZE (tnPixelX)]; } } } // Tell the pixel-group where it is. oCurrentGroup.m_tnX = m_tnX; oCurrentGroup.m_tnY = m_tnY; // HACK #if 0 fprintf (stderr, "Now checking pixel-group, frame %d, " "x %d, y %d\n", frame, int (m_tnX), int (m_tnY)); #endif // No matches yet. tnMatches = 0; // Find matches for the current pixel-group. Search for // them in the pixel-sorter tree, make sure each wasn't // already found (i.e. isn't already in the search-border), // flood-fill each one, and add each to the search-border. // // If the number of matches in the area exceeds the // match-count-throttle, or if the largest region found // exceeds the match-size-throttle, then pick the largest // region that intersects the current pixel-group and apply // it to the frame now. // Set up the search-window in a radius around the // current pixel-group. m_oSearchWindow.PrepareForSearch (a_reStatus, true); if (a_reStatus != g_kNoError) return; // Search for matches for the current pixel-group // within the search radius. m_oSearchWindow.StartSearch (itMatch, oCurrentGroup); #ifdef THROTTLE_PIXELSORTER_WITH_SAD m_setMatches.Clear(); while (pMatch = m_oSearchWindow.FoundNextMatch (itMatch, tnSAD), pMatch != NULL) #else // THROTTLE_PIXELSORTER_WITH_SAD while (pMatch = m_oSearchWindow.FoundNextMatch (itMatch), pMatch != NULL) #endif // THROTTLE_PIXELSORTER_WITH_SAD { // Calculate its motion vector. PIXELINDEX tnMotionX = pMatch->m_tnX - m_tnX; PIXELINDEX tnMotionY = pMatch->m_tnY - m_tnY; #ifdef PRINT_SEARCHBORDER //if (frame == 61 && DIM == 2) fprintf (stderr, "Found match at (%d,%d), " "motion vector (%d,%d)\n", int (m_tnX), int (m_tnY), int (tnMotionX), int (tnMotionY)); #endif // PRINT_SEARCHBORDER // Make sure this match is within the search // radius. (Sanity check.) assert (AbsoluteValue (tnMotionX) <= m_tnSearchRadiusX); assert (AbsoluteValue (tnMotionY) <= m_tnSearchRadiusY); // Make sure all matches refer to unused // reference-frame pixels. #ifndef NDEBUG #ifdef USE_REFERENCEFRAMEPIXELS_ONCE { PIXELINDEX x, y; // Used to loop through the current // pixel-group's pixels. for (y = 0; y < PGH; ++y) { for (x = 0; x < PGW; ++x) { PIXELINDEX tnPixelX, tnPixelY; // The index of the current pixel. // Calculate the index of the current // pixel. tnPixelX = pMatch->m_tnX + x; tnPixelY = pMatch->m_tnY + y; // Make sure this reference-frame pixel // hasn't been used already. assert (!m_oUsedReferencePixels .DoesContainPoint (tnPixelY, tnPixelX)); } } } #endif // USE_REFERENCEFRAMEPIXELS_ONCE #endif // !NDEBUG // That's one more match. ++tnMatches; // See if a region with this motion vector already // intersects/borders the current pixel-group, and // get its size. bool bExistingMatch = m_oSearchBorder.HasExistingMatch (tnMotionX, tnMotionY); // HACK #if 0 fprintf (stderr, "\tFound match, " "motion vector (%d,%d)", int (tnMotionX), int (tnMotionY)); if (!bExistingMatch) fprintf (stderr, " - new\n"); else fprintf (stderr, " - existing\n"); #endif #ifdef THROTTLE_PIXELSORTER_WITH_SAD // If a region with this motion vector already // intersects/borders the current pixel-group, then // this match can be skipped. if (!bExistingMatch) { // If this match is better than our worst so // far, get rid of our worst & use the new one // instead. if (m_setMatches.Size() == m_nMatchCountThrottle) { typename MatchedPixelGroupSet::Iterator itWorst; // The worst match found so far. // Get the worst match. (It's at the end of // the list.) itWorst = m_setMatches.End(); --itWorst; // If the new item is better than our worst, // get rid of our worst to make room for the // new item. if (tnSAD < (*itWorst).m_tnSAD) m_setMatches.Erase (itWorst); } // If this match is close enough to the current // pixel-group, make a note of it. if (m_setMatches.Size() < m_nMatchCountThrottle) { m_setMatches.Insert (a_reStatus, MatchedPixelGroup (tnSAD, pMatch)); if (a_reStatus != g_kNoError) return; } } #else // THROTTLE_PIXELSORTER_WITH_SAD // If a region with this motion vector doesn't already // intersect/border the current pixel-group, then // flood-fill it and add it to the search-border. if (!bExistingMatch) { // Add this region to the search-border. (void) SearchBorder_AddNewRegion (a_reStatus, tnMotionX, tnMotionY); if (a_reStatus != g_kNoError) return; } #endif // THROTTLE_PIXELSORTER_WITH_SAD } #ifdef THROTTLE_PIXELSORTER_WITH_SAD // Now loop through all the good matches found, flood-fill // each one, and add them to the search-border. for (itBestMatch = m_setMatches.Begin(); itBestMatch != m_setMatches.End(); ++itBestMatch) { PIXELINDEX tnMotionX, tnMotionY; // The motion vector of this match. // Get the current match. const MatchedPixelGroup &rMatch = *itBestMatch; // Calculate its motion vector. tnMotionX = rMatch.m_pGroup->m_tnX - m_tnX; tnMotionY = rMatch.m_pGroup->m_tnY - m_tnY; // Add this region to the search-border. (void) SearchBorder_AddNewRegion (a_reStatus, tnMotionX, tnMotionY); if (a_reStatus != g_kNoError) return; } // All done with the matches. m_setMatches.Clear(); #endif // THROTTLE_PIXELSORTER_WITH_SAD // If it's time to throttle matches, do so. // // The idea is that matches are only throttled when the // match-count-throttle is exceeded, and the largest // matches are applied until the match-size-throttle is // satisfied. Previously, matches could be throttled if // only the match-size-throttle was exceeded. But this // led to bad matches getting applied before a better match // could be found, which led to an "earthquaking" sort of // artifact in dark, cloudy areas of the picture. This // ended up being the simple fix for that problem! // // Now, the challenge is to pick a match-size-throttle that // keeps the denoiser running quickly without missing many // good matches, and a match-count-throttle that keeps the // number of candidates high enough to avoid the shaking // artifact described above. if (tnMatches >= m_nMatchCountThrottle /* || m_oSearchBorder.GetSizeOfLargestActiveRegion() >= m_nMatchSizeThrottle */) { // Get the largest active-region from the search-border // and apply it now. Then, keep doing that as long // as the largets active-region exceeds the match-size- // throttle. // This allows at least one region to be applied if the // match-count-throttle is exceeded, and allows the // search-border to avoid doing expensive work for // regions that exceed the match-size-throttle. do { FRAMESIZE tnThrottledPixels; PIXELINDEX tnMotionX, tnMotionY; // Take the largest region that the current // pixel-group matched, flood-fill it, and apply it // to the new frame now, eliminating any competing // moved-regions encountered along the way. tnThrottledPixels = SearchBorder_MatchThrottle (a_reStatus, tnMatches, tnMotionX, tnMotionY); if (a_reStatus != g_kNoError) return; // HACK #if 0 fprintf (stderr, "Match throttle: frame %d, " "x %03d, y %03d, %03d matches, " "%04d flood \r", frame, int (m_tnX), int (m_tnY), int (tnMatches), int (tnThrottledPixels)); #endif // That's more pixels found by match-throttling. if (tnMotionX == 0 && tnMotionY == 0) tnNotMovedThrottledPixels += tnThrottledPixels; else tnMovedThrottledPixels += tnThrottledPixels; } while (m_oSearchBorder.GetSizeOfLargestActiveRegion() >= m_nMatchSizeThrottle); } // If no matches were found for the current pixel-group, // and there are no active border-regions in the area, // then we've found new information. // // NOTE: this dramatically speeds up the analysis of // frames that contain mostly new info, but probably // impacts quality. Flood-fills are allowed to override // the result, though. // // NOTE: We no longer test whether there are any active // border-regions in the area. The logic is, they've been // flood-filled, and if they don't extend into the current // pixel-group, then it's safe to consider the current // pixel-group to be new information. else if (tnMatches == 0) { PIXELINDEX tnX, tnY; for (tnY = m_tnY; tnY < m_tnY + PGH; ++tnY) { for (tnX = m_tnX; tnX < m_tnX + PGW; ++tnX) { // Allocate a new reference pixel. ReferencePixel_t *pNewPixel = m_oPixelPool.Allocate(); // Store the new pixel in the reference frame. m_pNewFrame->SetPixel (tnX, tnY, pNewPixel); // Give it the value from the new frame. pNewPixel->AddSample (a_pPixels[tnY * m_tnWidth + tnX]); } } } nextGroup: // Move to the next pixel-group. if ((m_tnStepX == 1 && m_tnX == tnLastX) || (m_tnStepX == -1 && m_tnX == 0)) { // We need to move down a line. If we're already on // the last line, we're done with the frame. if (m_tnY == tnLastY) break; // We should have found enough matches during this line // to safely apply all regions that exceed the // match-size-throttle. if (m_oSearchBorder.GetSizeOfLargestActiveRegion() >= m_nMatchSizeThrottle) { // Get the largest active-region from the // search-border and apply it now. Then, keep // doing that as long as the largets active-region // exceeds the match-size-throttle. // This allows at least one region to be applied if // the match-count-throttle is exceeded, and allows // the search-border to avoid doing expensive work // for regions that exceed the match-size-throttle. tnMatches = 0; do { FRAMESIZE tnThrottledPixels; PIXELINDEX tnMotionX, tnMotionY; // Take the largest region that the current // pixel-group matched, flood-fill it, and // apply it to the new frame now, eliminating // any competing moved-regions encountered // along the way. tnThrottledPixels = SearchBorder_MatchThrottle (a_reStatus, tnMatches, tnMotionX, tnMotionY); if (a_reStatus != g_kNoError) return; // HACK #if 0 fprintf (stderr, "Match throttle: frame %d, " "x %03d, y %03d, %03d matches, " "%04d flood \r", frame, int (m_tnX), int (m_tnY), int (tnMatches), int (tnThrottledPixels)); #endif // That's more pixels found by // match-throttling. if (tnMotionX == 0 && tnMotionY == 0) tnNotMovedThrottledPixels += tnThrottledPixels; else tnMovedThrottledPixels += tnThrottledPixels; } while (m_oSearchBorder.GetSizeOfLargestActiveRegion() >= m_nMatchSizeThrottle); } // Move down a line. m_oSearchWindow.MoveDown(); m_oSearchBorder.MoveDown (a_reStatus); if (a_reStatus != g_kNoError) return; ++m_tnY; // HACK //fprintf (stderr, "Now on line %d\r", int (m_tnY)); // Now move across the frame in the other direction, // i.e. zigzag. m_tnStepX = -m_tnStepX; } else if (m_tnStepX == 1) { // Move right one pixel. m_oSearchWindow.MoveRight(); m_oSearchBorder.MoveRight (a_reStatus); if (a_reStatus != g_kNoError) return; ++m_tnX; } else { // Move left one pixel. assert (m_tnStepX == -1); m_oSearchWindow.MoveLeft(); m_oSearchBorder.MoveLeft (a_reStatus); if (a_reStatus != g_kNoError) return; --m_tnX; } } // Get all the remaining moved-regions from the search-border. m_oSearchBorder.FinishFrame (a_reStatus); if (a_reStatus != g_kNoError) return; // We've found all the possible moved regions between the // new frame and the reference frame. // Loop through the moved regions found by motion-detection, // prune them of already-resolved pixels, and apply each one // to the new frame. //fprintf (stderr, "Applied extents:"); // HACK while (m_setRegions.Size() > 0) { typename MovedRegionSet::Iterator itRegion; MovedRegion *pRegion; // The moved region to apply next. PIXELINDEX tnMotionX, tnMotionY; // The region's motion vector. // Get the moved region to apply next. itRegion = m_setRegions.Begin(); pRegion = *itRegion; m_setRegions.Erase (itRegion); pRegion->GetMotionVector (tnMotionX, tnMotionY); // Flood-fill the candidate region, re-testing all the // extents. This removes parts that have been resolved // already. m_oPruningFloodFillControl.SetupForFloodFill (tnMotionX, tnMotionY); pRegion->FloodFill (a_reStatus, m_oPruningFloodFillControl, true, false); if (a_reStatus != g_kNoError) return; // If that makes it smaller than the next highest- // priority region we found, put it back in & try again. itRegion = m_setRegions.Begin(); if (itRegion != m_setRegions.End() && pRegion->NumberOfPoints() < (*itRegion)->NumberOfPoints()) { // Are there enough points left in this region for // us to bother with it? if (pRegion->NumberOfPoints() < PGW * PGH) { // No. Just get rid of it. m_oSearchBorder.DeleteRegion (pRegion); } else { // Yes. Put the region back into our set, to be // tried later. #ifndef NDEBUG typename MovedRegionSet::InsertResult oInsertResult = #endif // !NDEBUG m_setRegions.Insert (a_reStatus, pRegion); if (a_reStatus != g_kNoError) { m_oSearchBorder.DeleteRegion (pRegion); return; } assert (oInsertResult.m_bInserted); } // Try the region that's now the highest priority. continue; } // Apply this region to the new frame. ApplyRegionToNewFrame (a_reStatus, *pRegion); if (a_reStatus != g_kNoError) { m_oSearchBorder.DeleteRegion (pRegion); return; } // That's more resolved pixels. if (tnMotionX == 0 && tnMotionY == 0) tnNotMovedPixels += pRegion->NumberOfPoints(); else tnMovedPixels += pRegion->NumberOfPoints(); // We're done with this region. m_oSearchBorder.DeleteRegion (pRegion); } } // Prepare for searching the next frame. m_oSearchWindow.FinishFrame(); } // Motion-searching is done. Loop through the reference frame's // pixels, find any unresolved pixels, and create a new pixel for // them, using the data in the new frame. for (i = 0; i < m_tnPixels; ++i) { ReferencePixel_t *pNewPixel; // If this pixel is still unresolved, give it the value of // the corresponding pixel in the new frame. pNewPixel = m_pNewFrame->GetPixel (i); if (pNewPixel == NULL) { // Allocate a new reference pixel. ReferencePixel_t *pNewPixel = m_oPixelPool.Allocate(); // Store the new pixel in the reference frame. m_pNewFrame->SetPixel (i, pNewPixel); // Give it the value from the new frame. pNewPixel->AddSample (a_pPixels[i]); // That's one more new pixel. ++tnNewPixels; } else if (pNewPixel != NULL && pNewPixel->GetFrameReferences() == 1) { // Count up the earlier-found new pixel. (It wasn't safe to // count them until flood-filling had a chance to override // this decision.) ++tnNoMatchNewPixels; } } // Make sure all pixels were accounted for. // (This is a big sanity check.) assert (tnNotMovedZeroMotionPixels + tnNotMovedThrottledPixels + tnNotMovedPixels + tnMovedThrottledPixels + tnMovedPixels + tnNoMatchNewPixels + tnNewPixels == m_tnPixels); // All done. Remember that the data in the new frame is now valid. ++m_nLastFrame; // Make sure none of the pixels have more references than we have // frames. (Sanity check.) #ifndef NDEBUG #ifdef USE_REFERENCEFRAMEPIXELS_ONCE for (i = 0; i < m_tnPixels; ++i) { int16_t nRefs = m_pNewFrame->GetPixel (i)->GetFrameReferences(); assert (nRefs > 0); assert (nRefs <= m_nFrames); } #endif // USE_REFERENCEFRAMEPIXELS_ONCE #endif // !NDEBUG // We'll have a new reference-frame and new-frame in the next pass. m_pReferenceFrame = m_pNewFrame = NULL; m_pNewFramePixels = NULL; // HACK: print the pixel statistics. if (verbose >= 1) { float fInversePixelsPercent = 100.0f / float (m_tnPixels); fprintf (stderr, "Frame %d: %.1f%%+%.1f%%+%.1f%% not-moved, " "%.1f%%+%.1f%% moved, %.1f%%+%.1f%% new\n", frame, (float (tnNotMovedZeroMotionPixels) * fInversePixelsPercent), (float (tnNotMovedThrottledPixels) * fInversePixelsPercent), (float (tnNotMovedPixels) * fInversePixelsPercent), (float (tnMovedThrottledPixels) * fInversePixelsPercent), (float (tnMovedPixels) * fInversePixelsPercent), (float (tnNoMatchNewPixels) * fInversePixelsPercent), (float (tnNewPixels) * fInversePixelsPercent)); } // Print the allocation totals. #ifndef NDEBUG fprintf (stderr, "%lu moved-regions, %lu pixel-sorters\n", (unsigned long) m_oSearchBorder.GetMovedRegionCount(), (unsigned long) m_oSearchWindow.GetPixelSorterNodeCount()); #endif // !NDEBUG // Purge all remaining temporary memory allocations. m_oMatchThrottleRegion.Purge(); #ifndef ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS m_oZeroMotionFloodFillControl.Purge(); #endif // ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS #ifndef MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS m_oMatchThrottleFloodFillControl.Purge(); #endif // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS #ifndef PRUNING_FLOOD_FILL_WITH_BITMAP_REGIONS m_oPruningFloodFillControl.Purge(); #endif // PRUNING_FLOOD_FILL_WITH_BITMAP_REGIONS // Make sure our temporary memory allocations have been purged. assert (m_oRegionAllocator.GetNumAllocated() == 0); assert (m_oMovedRegionSetAllocator.GetNumAllocated() == 0); } // Once there is no more input, call this repeatedly to get the // details of the remaining frames, until it returns NULL. template const typename MotionSearcher::ReferenceFrame_t * MotionSearcher::GetRemainingFrames (void) { ReferenceFrame_t *pFrame; // The frame to return to the caller. // If there are no frames left, let our caller know. if (m_nFirstFrame == m_nLastFrame) return NULL; // Get the frame to return to the caller. pFrame = m_ppFrames[m_nFirstFrame]; // Remember not to hand it to the caller ever again. ++m_nFirstFrame; // Finally, return the frame to our caller. return pFrame; } // Purge ourselves of temporary structures. template void MotionSearcher::Purge (void) { // Clear out the pixel-sorter. m_oSearchWindow.PurgePixelSorter(); } #ifdef THROTTLE_PIXELSORTER_WITH_SAD // Default constructor. template MotionSearcher::MatchedPixelGroup::MatchedPixelGroup() { // No match yet. m_tnSAD = 0; m_pGroup = NULL; } // Initializing constructor. template MotionSearcher::MatchedPixelGroup::MatchedPixelGroup (Tolerance_t a_tnSAD, const typename SearchWindow_t::PixelGroup *a_pGroup) : m_tnSAD (a_tnSAD), m_pGroup (a_pGroup) { // Nothing else to do. } // Destructor. template MotionSearcher::MatchedPixelGroup::~MatchedPixelGroup() { // Nothing to do. } // A comparison operator, suitable for Set<>. template inline bool MotionSearcher::MatchedPixelGroup::SortBySAD::operator() (const MatchedPixelGroup &a_rLeft, const MatchedPixelGroup &a_rRight) const { // Easy enough. return (a_rLeft.m_tnSAD < a_rRight.m_tnSAD); } #endif // THROTTLE_PIXELSORTER_WITH_SAD // Apply this region to the new frame. template void MotionSearcher ::ApplyRegionToNewFrame (Status_t &a_reStatus, const MovedRegion &a_rRegion) { PIXELINDEX tnMotionX, tnMotionY; // The region's motion vector, i.e. the offset between the // new-frame pixel and the corresponding reference-frame pixel. typename MovedRegion::ConstIterator itExtent; // An extent to apply to the new frame. PIXELINDEX x; // Used to loop through pixels. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Get this region's motion vector. a_rRegion.GetMotionVector (tnMotionX, tnMotionY); // Loop through the region's extents, locate every pixel it // describes, and set it to the corresponding pixel in the // reference-frame representation of the new frame. for (itExtent = a_rRegion.Begin(); itExtent != a_rRegion.End(); ++itExtent) { // Get the next extent. const typename MovedRegion::Extent &rExtent = *itExtent; // Loop through the pixels it represents, set each // new-frame pixel to the corresponding reference-frame // pixel. for (x = rExtent.m_tnXStart; x < rExtent.m_tnXEnd; ++x) { #ifdef PRINT_SEARCHBORDER if (m_pNewFrame->GetPixel (x, rExtent.m_tnY) != NULL && m_pNewFrame->GetPixel (x, rExtent.m_tnY) ->GetFrameReferences() != 1) { fprintf (stderr, "Pixel (%d,%d) already resolved\n", int (x), int (rExtent.m_tnY)); } #endif // PRINT_SEARCHBORDER // Make sure this new-frame pixel hasn't been // resolved yet. assert (m_pNewFrame->GetPixel (x, rExtent.m_tnY) == NULL || m_pNewFrame->GetPixel (x, rExtent.m_tnY) ->GetFrameReferences() == 1); // Get the corresponding reference-frame pixel. ReferencePixel_t *pReferencePixel = m_pReferenceFrame->GetPixel (x + tnMotionX, rExtent.m_tnY + tnMotionY); assert (pReferencePixel != NULL); // Set the new-frame pixel to this reference pixel. m_pNewFrame->SetPixel (x, rExtent.m_tnY, pReferencePixel); // Accumulate the new-frame value of this pixel. pReferencePixel->AddSample (m_pNewFramePixels[FRAMESIZE (rExtent.m_tnY) * FRAMESIZE (m_tnWidth) + FRAMESIZE (x)]); } } #ifdef USE_REFERENCEFRAMEPIXELS_ONCE // All of these reference pixels have been used. for (itExtent = a_rRegion.Begin(); itExtent != a_rRegion.End(); ++itExtent) { // Get the current extent. typename MovedRegion::Extent oExtent = *itExtent; // Move it along the motion vector. oExtent.m_tnY += tnMotionY; oExtent.m_tnXStart += tnMotionX; oExtent.m_tnXEnd += tnMotionX; // Make sure it's already in the frame. assert (oExtent.m_tnY >= 0 && oExtent.m_tnY < m_tnHeight && oExtent.m_tnXStart >= 0 && oExtent.m_tnXEnd <= m_tnWidth); // Add it to our running total of used reference-pixels. m_oUsedReferencePixels.Union (a_reStatus, oExtent.m_tnY, oExtent.m_tnXStart, oExtent.m_tnXEnd); if (a_reStatus != g_kNoError) return; } #endif // USE_REFERENCEFRAMEPIXELS_ONCE // Remove all pixel-groups containing used reference pixels from // the search window. m_oSearchWindow.Prune (a_rRegion, tnMotionX, tnMotionY); } // Default constructor. template MotionSearcher::SearchBorder_t::SearchBorder_t (MovedRegionSet &a_rsetRegions, typename MovedRegion::Allocator &a_rAlloc) : BaseClass (a_rAlloc), m_rsetRegions (a_rsetRegions) { // Nothing else to do. } // Receive a completed region from the search-border. template void MotionSearcher::SearchBorder_t::OnCompletedRegion (Status_t &a_reStatus, typename SearchBorder_t::MovedRegion *a_pRegion) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure they gave us a completed region. assert (a_pRegion != NULL); // Put it in our list. if (a_pRegion->NumberOfPoints() < PGW * PGH) { // This region is too small to be bothered with. // Just get rid of it. this->DeleteRegion (a_pRegion); } else { #ifndef NDEBUG typename MovedRegionSet::InsertResult oInsertResult = #endif // !NDEBUG m_rsetRegions.Insert (a_reStatus, a_pRegion); if (a_reStatus != g_kNoError) return; assert (oInsertResult.m_bInserted); } } // Add a new region, with the given motion vector, to the // search border. Flood-fills its area before adding. template FRAMESIZE MotionSearcher::SearchBorder_AddNewRegion (Status_t &a_reStatus, PIXELINDEX a_tnMotionX, PIXELINDEX a_tnMotionY) { PIXELINDEX tnY; // Used to loop through the pixel-group's lines. // Set up a region describing the current pixel-group. #ifdef MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS m_oFloodFillRegion.Clear(); for (tnY = m_tnY; tnY < m_tnY + PGH; ++tnY) { m_oFloodFillRegion.Merge (a_reStatus, tnY, m_tnX, m_tnX + PGW); if (a_reStatus != g_kNoError) return 0; } #else // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS m_oMatchThrottleRegion.Clear(); for (tnY = m_tnY; tnY < m_tnY + PGH; ++tnY) { m_oMatchThrottleRegion.Merge (a_reStatus, tnY, m_tnX, m_tnX + PGW); if (a_reStatus != g_kNoError) return 0; } #endif // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS // Set its motion vector. m_oMatchThrottleRegion.SetMotionVector (a_tnMotionX, a_tnMotionY); // Set its location. (Needed only for debugging purposes.) #ifndef NDEBUG m_oMatchThrottleRegion.m_tnX = m_tnX; m_oMatchThrottleRegion.m_tnY = m_tnY; #endif // !NDEBUG // Flood-fill this match, so as to get its full extent. m_oMatchThrottleFloodFillControl.SetupForFloodFill (a_tnMotionX, a_tnMotionY); #ifdef MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS m_oFloodFillRegion.FloodFill (a_reStatus, m_oMatchThrottleFloodFillControl, false, true); #else // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS m_oMatchThrottleRegion.FloodFill (a_reStatus, m_oMatchThrottleFloodFillControl, false, true); #endif // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS if (a_reStatus != g_kNoError) return 0; // Now copy the results of the flood-fill to the match-throttle // region, so that it can be added to the search-border. #ifdef MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS m_oMatchThrottleRegion.Clear(); typename BitmapRegion_t::ConstIterator itExtent; for (itExtent = m_oFloodFillRegion.Begin(); itExtent != m_oFloodFillRegion.End(); ++itExtent) { // Get the current extent. const typename BitmapRegion_t::Extent &rExtent = *itExtent; // Copy it to the match-throttle region. m_oMatchThrottleRegion.Merge (a_reStatus, rExtent.m_tnY, rExtent.m_tnXStart, rExtent.m_tnXEnd); if (a_reStatus != g_kNoError) return 0; } #endif // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS // Get the size of the flood-filled region. FRAMESIZE tnThisMatch = m_oMatchThrottleRegion.NumberOfPoints(); // Add this match to our growing set of moved regions. m_oSearchBorder.AddNewRegion (a_reStatus, m_oMatchThrottleRegion); if (a_reStatus != g_kNoError) return 0; // Make sure that emptied the region. // (AddNewRegion() is supposed to do that; this will catch any // changes in that behavior.) assert (m_oMatchThrottleRegion.NumberOfPoints() == 0); // Return the size of the flood-filled region. return tnThisMatch; } // Get the best region that matched the current pixel-group // (which is usually the largest active-region). Expand it as far // as it can go, i.e. flood-fill in its area. If it's no longer // the largest region, put it back and try again. Otherwise, apply // it to the new frame now. // // Pass the number of pixel-group matches as an argument. If a // best-region candidate is found to have no unresolved pixels, // it's no longer considered a pixel-group match, and that may lead // to the discovery that the match-count-throttle is no longer // being exceeded. // // Returns the number of points flood-filled, and backpatches the // motion vector associated with the best region. // May return zero if analysis reveals that the match-throttles // weren't really exceeded. template FRAMESIZE MotionSearcher::SearchBorder_MatchThrottle (Status_t &a_reStatus, FRAMESIZE a_nMatchCount, PIXELINDEX &a_rtnMotionX, PIXELINDEX &a_rtnMotionY) { MovedRegion *pSurvivor; // The only region to survive pruning -- the largest one, with // the shortest motion vector. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Keep testing best-active-region candidates until one really is the // best, or until the match-throttles are no longer being exceeded. while (m_oSearchBorder.GetSizeOfLargestActiveRegion() > 0) { // Get the best active region to apply to the frame now. // This also gives us the size of the second-best active-region. FRAMESIZE tnSecondBestActiveRegionSize = 0; pSurvivor = m_oSearchBorder.ChooseBestActiveRegion (a_reStatus, tnSecondBestActiveRegionSize); if (a_reStatus != g_kNoError) return 0; // Get the region's motion vector. pSurvivor->GetMotionVector (a_rtnMotionX, a_rtnMotionY); // Remove all pixels that were already resolved. m_oPruningFloodFillControl.SetupForFloodFill (a_rtnMotionX, a_rtnMotionY); pSurvivor->FloodFill (a_reStatus, m_oPruningFloodFillControl, true, false); if (a_reStatus != g_kNoError) { m_oSearchBorder.DeleteRegion (pSurvivor); return 0; } #ifdef PRINT_SEARCHBORDER if (frame == 61 && DIM == 2) { fprintf (stderr, "Flood-filled region:\n"); PrintRegion (*pSurvivor); fprintf (stderr, "\n"); } #endif // PRINT_SEARCHBORDER // Remember the number of points in the region. FRAMESIZE tnSurvivorSize = FRAMESIZE (pSurvivor->NumberOfPoints()); // If this region has no unresolved pixels (or too few), try again. if (tnSurvivorSize < PGW * PGH) { // This region is no longer needed. m_oSearchBorder.DeleteRegion (pSurvivor); // Go back and try again. continue; } // If this region is no longer the best choice, put it back // and try again. if (tnSurvivorSize < tnSecondBestActiveRegionSize) { // Put it back. m_oSearchBorder.AddNewRegion (a_reStatus, *pSurvivor); m_oSearchBorder.DeleteRegion (pSurvivor); if (a_reStatus != g_kNoError) return 0; // If the match-size-throttle is no longer exceeded, // then let our caller know that no throttling was needed. if (tnSecondBestActiveRegionSize < m_nMatchSizeThrottle) return 0; // Try again. continue; } // Apply this region to the new frame. ApplyRegionToNewFrame (a_reStatus, *pSurvivor); if (a_reStatus != g_kNoError) { m_oSearchBorder.DeleteRegion (pSurvivor); return 0; } // Clean up the region, return the number of points it had. m_oSearchBorder.DeleteRegion (pSurvivor); return tnSurvivorSize; } // No region was applied to the frame. return 0; } // Default constructor. template MotionSearcher::ZeroMotionFloodFillControl #ifdef ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS ::ZeroMotionFloodFillControl() #else // ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS ::ZeroMotionFloodFillControl (typename BaseClass::Allocator &a_rAllocator) : BaseClass (a_rAllocator) #endif // ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS { // We don't know who we're working for yet. m_pMotionSearcher = NULL; } // Initializer. template void MotionSearcher::ZeroMotionFloodFillControl::Init (Status_t &a_reStatus, MotionSearcher *a_pMotionSearcher) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure they gave us a motion-searcher. assert (a_pMotionSearcher != NULL); // Initialize our base class. BaseClass::Init (a_reStatus #ifdef ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS , a_pMotionSearcher->m_tnWidth, a_pMotionSearcher->m_tnHeight #endif // ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS ); if (a_reStatus != g_kNoError) return; // Remember which motion-searcher we're working for. m_pMotionSearcher = a_pMotionSearcher; } // Return true if the flood-fill should examine the given // extent. May modify the extent. template bool MotionSearcher::ZeroMotionFloodFillControl::ShouldUseExtent (typename ZeroMotionFloodFillControl::BaseClass::Extent &a_rExtent) { #ifdef ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS // Make sure the extent doesn't need to be clipped. assert (a_rExtent.m_tnY >= 0 && a_rExtent.m_tnY < m_pMotionSearcher->m_tnHeight && a_rExtent.m_tnXStart >= 0 && a_rExtent.m_tnXStart < m_pMotionSearcher->m_tnWidth && a_rExtent.m_tnXEnd > 0 && a_rExtent.m_tnXEnd <= m_pMotionSearcher->m_tnWidth); #else // ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS // If this extent is completely off the screen, skip it. if (a_rExtent.m_tnY < 0 || a_rExtent.m_tnY >= m_pMotionSearcher->m_tnHeight || a_rExtent.m_tnXStart >= m_pMotionSearcher->m_tnWidth || a_rExtent.m_tnXEnd <= 0) return false; // If this extent is partially off the screen, clip it. if (a_rExtent.m_tnXStart < 0) a_rExtent.m_tnXStart = 0; if (a_rExtent.m_tnXEnd > m_pMotionSearcher->m_tnWidth) a_rExtent.m_tnXEnd = m_pMotionSearcher->m_tnWidth; #endif // ZERO_MOTION_FLOOD_FILL_WITH_BITMAP_REGIONS // Let our caller know to use this extent. return true; } // Returns true if the given point should be included in the // flood-fill. template bool MotionSearcher::ZeroMotionFloodFillControl::IsPointInRegion (PIXELINDEX a_tnX, PIXELINDEX a_tnY) { // If this pixel has been resolved, skip it. if (m_pMotionSearcher->m_pNewFrame->GetPixel (a_tnX, a_tnY) != NULL) return false; // Get the pixels of interest. const Pixel_t &rNewPixel = m_pMotionSearcher->m_pNewFramePixels [a_tnY * m_pMotionSearcher->m_tnWidth + a_tnX]; ReferencePixel_t *pRefPixel = m_pMotionSearcher->m_pReferenceFrame->GetPixel (a_tnX, a_tnY); // If the new pixel is close enough to the reference pixel, the // point is in the region. if (rNewPixel.IsWithinTolerance (pRefPixel->GetValue(), m_pMotionSearcher->m_tnZeroTolerance)) { // The point is in the region. return true; } // The point is not in the region. return false; } // Default constructor. template MotionSearcher::MatchThrottleFloodFillControl #ifdef MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS ::MatchThrottleFloodFillControl() #else // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS ::MatchThrottleFloodFillControl (typename BaseClass::Allocator &a_rAllocator) : BaseClass (a_rAllocator) #endif // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS { // We don't know who we're working for yet. m_pMotionSearcher = NULL; } // Initializer. template void MotionSearcher::MatchThrottleFloodFillControl::Init (Status_t &a_reStatus, MotionSearcher *a_pMotionSearcher) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure they gave us a motion-searcher. assert (a_pMotionSearcher != NULL); // Initialize our base class. BaseClass::Init (a_reStatus #ifdef MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS , a_pMotionSearcher->m_tnWidth, a_pMotionSearcher->m_tnHeight #endif // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS ); if (a_reStatus != g_kNoError) return; // Remember which motion-searcher we're working for. m_pMotionSearcher = a_pMotionSearcher; } // Set up to to a flood-fill. template void MotionSearcher::MatchThrottleFloodFillControl::SetupForFloodFill (PIXELINDEX a_tnMotionX, PIXELINDEX a_tnMotionY) { // Save the motion vector. m_tnMotionX = a_tnMotionX; m_tnMotionY = a_tnMotionY; } // Return true if the flood-fill should examine the given // extent. May modify the extent. template bool MotionSearcher::MatchThrottleFloodFillControl::ShouldUseExtent (typename Region_t::Extent &a_rExtent) { #ifdef MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS // Make sure the extent doesn't need to be clipped. assert (a_rExtent.m_tnY >= 0 && a_rExtent.m_tnY < m_pMotionSearcher->m_tnHeight && a_rExtent.m_tnXStart >= 0 && a_rExtent.m_tnXStart < m_pMotionSearcher->m_tnWidth && a_rExtent.m_tnXEnd > 0 && a_rExtent.m_tnXEnd <= m_pMotionSearcher->m_tnWidth); // If this extent (with its motion vector) is completely off the // screen, skip it. if (a_rExtent.m_tnY + m_tnMotionY < 0 || a_rExtent.m_tnY + m_tnMotionY >= m_pMotionSearcher->m_tnHeight || a_rExtent.m_tnXStart + m_tnMotionX >= m_pMotionSearcher->m_tnWidth || a_rExtent.m_tnXEnd + m_tnMotionX <= 0) return false; // If this extent (with its motion vector) is partially off the // screen, clip it. if (a_rExtent.m_tnXStart + m_tnMotionX < 0) a_rExtent.m_tnXStart = -m_tnMotionX; if (a_rExtent.m_tnXEnd + m_tnMotionX > m_pMotionSearcher->m_tnWidth) a_rExtent.m_tnXEnd = m_pMotionSearcher->m_tnWidth - m_tnMotionX; #else // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS // If this extent is completely off the screen, skip it. if (a_rExtent.m_tnY < 0 || a_rExtent.m_tnY >= m_pMotionSearcher->m_tnHeight || a_rExtent.m_tnXStart >= m_pMotionSearcher->m_tnWidth || a_rExtent.m_tnXEnd <= 0 || a_rExtent.m_tnY + m_tnMotionY < 0 || a_rExtent.m_tnY + m_tnMotionY >= m_pMotionSearcher->m_tnHeight || a_rExtent.m_tnXStart + m_tnMotionX >= m_pMotionSearcher->m_tnWidth || a_rExtent.m_tnXEnd + m_tnMotionX <= 0) return false; // If this extent is partially off the screen, clip it. if (a_rExtent.m_tnXStart + m_tnMotionX < 0) a_rExtent.m_tnXStart = -m_tnMotionX; if (a_rExtent.m_tnXEnd + m_tnMotionX > m_pMotionSearcher->m_tnWidth) a_rExtent.m_tnXEnd = m_pMotionSearcher->m_tnWidth - m_tnMotionX; if (a_rExtent.m_tnXStart < 0) a_rExtent.m_tnXStart = 0; if (a_rExtent.m_tnXEnd > m_pMotionSearcher->m_tnWidth) a_rExtent.m_tnXEnd = m_pMotionSearcher->m_tnWidth; #endif // MATCH_THROTTLE_FLOOD_FILL_WITH_BITMAP_REGIONS // Let our caller know to use this extent. return true; } // Returns true if the given point should be included in the // flood-fill. template bool MotionSearcher::MatchThrottleFloodFillControl::IsPointInRegion (PIXELINDEX a_tnX, PIXELINDEX a_tnY) { // Get the new pixel, if any. ReferencePixel_t *pNewPixel = m_pMotionSearcher->m_pNewFrame ->GetPixel (a_tnX, a_tnY); // We can potentially flood-fill this pixel if it's unresolved or // if it thinks it's new data. if (pNewPixel == NULL || pNewPixel->GetFrameReferences() == 1) { // Get the reference pixel's coordinates. PIXELINDEX tnRefX = a_tnX + m_tnMotionX; PIXELINDEX tnRefY = a_tnY + m_tnMotionY; // If the corresponding reference pixel hasn't been // used already, see if it matches our pixel. #ifdef USE_REFERENCEFRAMEPIXELS_ONCE if (!m_pMotionSearcher->m_oUsedReferencePixels.DoesContainPoint (tnRefY, tnRefX)) #endif // USE_REFERENCEFRAMEPIXELS_ONCE { // If the new pixel is close enough to it, the point is in // the region. ReferencePixel_t *pRefPixel = m_pMotionSearcher->m_pReferenceFrame->GetPixel (tnRefX, tnRefY); const Pixel_t &rNewPixel = m_pMotionSearcher ->m_pNewFramePixels[a_tnY * m_pMotionSearcher->m_tnWidth + a_tnX]; if (rNewPixel.IsWithinTolerance (pRefPixel->GetValue(), m_pMotionSearcher->m_tnTolerance)) { // Let our caller know the point is in the region. return true; } } } // Let our caller know the point is not in the region. return false; } // Default constructor. template MotionSearcher::PruningFloodFillControl #ifdef PRUNING_FLOOD_FILL_WITH_BITMAP_REGIONS ::PruningFloodFillControl() #else // PRUNING_FLOOD_FILL_WITH_BITMAP_REGIONS ::PruningFloodFillControl (typename BaseClass::Allocator &a_rAllocator) : BaseClass (a_rAllocator) #endif // PRUNING_FLOOD_FILL_WITH_BITMAP_REGIONS { // We don't know who we're working for yet. m_pMotionSearcher = NULL; } // Initializer. template void MotionSearcher::PruningFloodFillControl::Init (Status_t &a_reStatus, MotionSearcher *a_pMotionSearcher) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure they gave us a motion-searcher. assert (a_pMotionSearcher != NULL); // Initialize our base class. BaseClass::Init (a_reStatus #ifdef PRUNING_FLOOD_FILL_WITH_BITMAP_REGIONS , a_pMotionSearcher->m_tnWidth, a_pMotionSearcher->m_tnHeight #endif // PRUNING_FLOOD_FILL_WITH_BITMAP_REGIONS ); if (a_reStatus != g_kNoError) return; // Remember which motion-searcher we're working for. m_pMotionSearcher = a_pMotionSearcher; } // Set up to to a flood-fill. template void MotionSearcher::PruningFloodFillControl::SetupForFloodFill (PIXELINDEX a_tnMotionX, PIXELINDEX a_tnMotionY) { // Save the motion vector. m_tnMotionX = a_tnMotionX; m_tnMotionY = a_tnMotionY; } // Return true if the flood-fill should examine the given // extent. May modify the extent. template bool MotionSearcher::PruningFloodFillControl::ShouldUseExtent (typename Region_t::Extent &a_rExtent) { // Make sure the extent doesn't need to be clipped. // (This style of flood-filling doesn't try to generate new extents // that would have to be filtered.) assert (a_rExtent.m_tnY >= 0 && a_rExtent.m_tnY < m_pMotionSearcher->m_tnHeight && a_rExtent.m_tnXStart >= 0 && a_rExtent.m_tnXStart < m_pMotionSearcher->m_tnWidth && a_rExtent.m_tnXEnd > 0 && a_rExtent.m_tnXEnd <= m_pMotionSearcher->m_tnWidth); // Let our caller know to use this extent. return true; } // Returns true if the given point should be included in the // flood-fill. template bool MotionSearcher::PruningFloodFillControl::IsPointInRegion (PIXELINDEX a_tnX, PIXELINDEX a_tnY) { // Get the new pixel, if any. ReferencePixel_t *pNewPixel = m_pMotionSearcher->m_pNewFrame ->GetPixel (a_tnX, a_tnY); // We can potentially flood-fill this pixel if it's unresolved or // if it thinks it's new data. if (pNewPixel == NULL || pNewPixel->GetFrameReferences() == 1) { // Get the reference pixel's coordinates. PIXELINDEX tnRefX = a_tnX + m_tnMotionX; PIXELINDEX tnRefY = a_tnY + m_tnMotionY; // If the corresponding reference pixel hasn't been // used already, it matches our pixel. #ifdef USE_REFERENCEFRAMEPIXELS_ONCE if (!m_pMotionSearcher->m_oUsedReferencePixels.DoesContainPoint (tnRefY, tnRefX)) #endif // USE_REFERENCEFRAMEPIXELS_ONCE { // Let our caller know the point is in the region. return true; } } // Let our caller know the point is not in the region. return false; } #endif // __MOTION_SEARCHER_H__ mjpegtools-2.1.0/y4mdenoise/Vector.hh0000644000175000017500000011643211204303657020064 0ustar glowwormglowworm#ifndef __VECTOR_H__ #define __VECTOR_H__ // This file (C) 2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. /* A vector class that can be used to implement Set<>. */ #include "config.h" #include #include #include #include "mjpeg_types.h" #include "Status_t.h" #include "VariableSizeAllocator.hh" // Define this to compile in code to double-check and debug the vector. #ifndef NDEBUG #define DEBUG_VECTOR #endif // NDEBUG template class Vector { private: // The type of a node in the vector struct Node { VALUE m_oValue; // The data held by this node. Node() : m_oValue() {} // Default constructor. explicit Node (const VALUE &a_rValue) : m_oValue (a_rValue) {} // Initializing constructor. }; Vector (const Vector &a_rOther); const Vector &operator = (const Vector &a_rOther); // Disallow copying and assignment. public: typedef VariableSizeAllocator Allocator_t; // The type of node allocator to use. static Allocator_t sm_oNodeAllocator; // The default node allocator. // A structure that contains all of our initialization parameters. struct InitParams { public: uint32_t m_nInitialItems, m_nAdditionalItems; // The number of initial/additional items to allocate. InitParams() : m_nInitialItems (128u), m_nAdditionalItems (128u) {} // Default constructor. Pull some values out of thin air. InitParams (uint32_t a_nInitialItems, uint32_t a_nAdditionalItems) : m_nInitialItems (a_nInitialItems), m_nAdditionalItems (a_nAdditionalItems) {} // Initializing constructor. }; Vector (const PRED &a_rPred = PRED(), Allocator_t &a_rAlloc = sm_oNodeAllocator); // Default constructor. Must be followed by Init(). Vector (Status_t &a_reStatus, bool a_bAllowDuplicates, const InitParams &a_rInitParams, const PRED &a_rPred = PRED(), Allocator_t &a_rAlloc = sm_oNodeAllocator); // Constructor. Specify whether or not duplicates are allowed, and // the initial/additional number of items to allocate. void Init (Status_t &a_reStatus, bool a_bAllowDuplicates, const InitParams &a_rInitParams); // Construction method. Specify whether or not duplicates are // allowed, and the initial/additional number of items to allocate. virtual ~Vector (void); // Destructor. #ifdef DEBUG_VECTOR void Invariant (void) const; // Thoroughly analyze the vector for structural integrity. void SetDebug (bool a_bDebug); // Set whether to run the vector invariant before and after // methods. #endif // DEBUG_VECTOR // // Iterator classes. // class Iterator; class ConstIterator; friend class ConstIterator; class ConstIterator { protected: friend class Vector; // Let Vector access m_pNode and m_nNode. Node *m_pNode; // The node we represent. // Used to make accessing the value simple. uint32_t m_nNode; // The index of the node we represent. // Used to avoid integer-division (which is slow on pretty // much every CPU in existence) to convert the node pointer // into an index. const Vector *m_pVector; // The vector that contains this node. public: ConstIterator() { m_pNode = NULL; m_pVector = NULL; } ConstIterator (Node *a_pNode, uint32_t a_nNode, const Vector *a_pVector) : m_pNode (a_pNode), m_nNode (a_nNode), m_pVector (a_pVector) {} ConstIterator (const Iterator &a_rOther) : m_pNode (a_rOther.m_pNode), m_nNode (a_rOther.m_nNode), m_pVector (a_rOther.m_pVector) {} const VALUE &operator*() const { // Make sure this iterator is associated with a vector. assert (m_pVector != NULL); // Make sure this iterator points within this vector. // (This helps to detect stale iterators.) assert (m_pNode >= m_pVector->Begin().m_pNode); assert (m_pNode <= m_pVector->Last().m_pNode); // Easy enough. return m_pNode->m_oValue; } ConstIterator& operator++() { // Make sure this iterator is associated with a vector. assert (m_pVector != NULL); // If they go forward from End(), wrap to the beginning. // If there are no items, End() is the only possible value // for an iterator. if (m_pNode == NULL || m_pVector->Size() == 0u) { m_pNode = m_pVector->Begin().m_pNode; m_nNode = 0u; } // If they go forward past the last item, then they're // at the end of the array. else if (m_pNode == m_pVector->Last().m_pNode) { m_pNode = NULL; m_nNode = 0u; } // Otherwise, move to the next item. else { ++m_pNode; ++m_nNode; } return *this; } ConstIterator operator++(int) { ConstIterator oTmp = *this; ++*this; return oTmp; } ConstIterator& operator--() { // Make sure this iterator is associated with a vector. assert (m_pVector != NULL); // If they go backward from the first item, then they're // at the end of the array. // If there are no items, End() is the only possible value // for an iterator. if (m_pNode == m_pVector->Begin().m_pNode || m_pVector->Size() == 0u) { m_pNode = NULL; m_nNode = 0u; } // If they go backward from End(), wrap to the last item. else if (m_pNode == NULL && m_pVector->Size() > 0u) { m_pNode = m_pVector->Last().m_pNode; if (m_pNode != NULL) m_nNode = m_pVector->Size() - 1u; else m_nNode = 0u; } // Otherwise, move to the previous item. else { --m_pNode; --m_nNode; } return *this; } ConstIterator operator--(int) { ConstIterator oTmp = *this; --*this; return oTmp; } bool operator== (const ConstIterator &a_rOther) const { return (m_pNode == a_rOther.m_pNode) ? true : false; } bool operator!= (const ConstIterator &a_rOther) const { return (m_pNode != a_rOther.m_pNode) ? true : false; } }; friend class Iterator; class Iterator : public ConstIterator { private: typedef ConstIterator BaseClass; // Keep track of who our base class is. public: Iterator() : ConstIterator() {} Iterator (Node *a_pNode, uint32_t a_nNode, Vector *a_pVector) : BaseClass (a_pNode, a_nNode, a_pVector) {} VALUE &operator*() { // Make sure this iterator is associated with a vector. assert (BaseClass::m_pVector != NULL); // Make sure this iterator points within this vector. // (This helps to detect stale iterators.) assert (BaseClass::m_pNode >= BaseClass::m_pVector->Begin().m_pNode); assert (BaseClass::m_pNode <= BaseClass::m_pVector->Last().m_pNode); // Easy enough. return BaseClass::m_pNode->m_oValue; } Iterator& operator++() { ++((BaseClass &)*this); return *this; } Iterator operator++(int) { Iterator oTmp = *this; ++*this; return oTmp; } Iterator& operator--() { --((BaseClass &)*this); return *this; } Iterator operator--(int) { Iterator oTmp = *this; --*this; return oTmp; } bool operator== (const Iterator &a_rOther) const { return (BaseClass::m_pNode == a_rOther.m_pNode) ? true : false; } bool operator!= (const Iterator &a_rOther) const { return (BaseClass::m_pNode != a_rOther.m_pNode) ? true : false; } }; // // Vector methods. // Iterator Begin (void) { return Iterator ((m_nItems == 0u) ? NULL : m_pItems, 0u, this); } // Return an iterator to the beginning of the list. // If there are no items, that's also the end of the list. ConstIterator Begin (void) const { return ConstIterator ((m_nItems == 0u) ? NULL : m_pItems, 0u, this); } // Return an iterator to the beginning of the list. // If there are no items, that's also the end of the list. Iterator Last (void) { assert (m_nItems > 0u); return Iterator (m_pItems + m_nItems - 1u, m_nItems - 1u, this); } // Return an iterator to the last item in the list. // The list must have at least one item in it. ConstIterator Last (void) const { assert (m_nItems > 0u); return ConstIterator (m_pItems + m_nItems - 1u, m_nItems - 1u, this); } // Return an iterator to the last item in the list. // The list must have at least one item in it. Iterator End (void) { return Iterator (NULL, 0u, this); } // Return an iterator to the end of the list. ConstIterator End (void) const { return ConstIterator (NULL, 0u, this); } // Return an iterator to the end of the list. uint32_t Size (void) const { return m_nItems; } // Return the number of items in the list. // (May be called on a default-constructed object, making it // possible for default-constructed subclasses/owners to destroy // themselves safely.) bool Empty (void) const { return (m_nItems == 0) ? true : false; } // Return whether the list is empty. // A structure used to return the result of an insertion. struct InsertResult { Iterator m_itPosition; // Where the item was inserted, or where the duplicate was // found. bool m_bInserted; // true if the item was inserted into the list. }; InsertResult Insert (Status_t &a_reStatus, const VALUE &a_rValue); // Insert an item into the list. Iterator Insert (Status_t &a_reStatus, Iterator a_itPosition, const VALUE &a_rValue); // Insert an item into the list, at this exact location, if it's // safe. Returns where it was really inserted. void Insert (Status_t &a_reStatus, ConstIterator a_itFirst, ConstIterator a_itLast); // Insert a range of items from another vector. Iterator Erase (Iterator a_itHere); // Erase the item here. Return the item following the one // removed. Iterator Erase (Iterator a_itFirst, Iterator a_itLast); // Erase a range of items in this list. Return the item // following the last one removed. void Clear (void); // Empty the list. void Purge (void); // Purge all internally-allocated memory. void Move (Vector &a_rOther); // Move all items from the other vector to ourself. // The current vector must be empty. // This operation cannot fail, i.e. it doesn't allocate memory. bool CanMove (const Vector &a_rOther) const; // Returns true if the two vectors move items between // each other. void Assign (Status_t &a_reStatus, const Vector &a_rOther); // Assign the contents of the other vector to ourselves. Iterator Find (const KEY &a_rKey); // Find the given item in the list. Returns End() if not found. ConstIterator Find (const KEY &a_rKey) const; // Find the given item in the list. Returns End() if not found. Iterator LowerBound (const KEY &a_rKey); // Return the position of the first item that's >= the key. ConstIterator LowerBound (const KEY &a_rKey) const; // Return the position of the first item that's >= the key. Iterator UpperBound (const KEY &a_rKey); // Return the position of the first item that's > the key. ConstIterator UpperBound (const KEY &a_rKey) const; // Return the position of the first item that's > the key. size_t GetSizeOfLargestNode (void) const { return sizeof (Node); } // Return the size of the largest possible node. // (Not used -- it's only to preserve interface compatibility // with SkipList<>.) private: Allocator_t &m_rNodeAllocator; // Where we get memory to allocate nodes. bool m_bAllowDuplicates; // true if we allow duplicate elements. Node *m_pItems; // The array of items we contain. uint32_t m_nItems; // The number of valid items in this vector. uint32_t m_nSpace; // The amount of space for items in this vector. // (Will always be greater than or equal to the number of // valid items.) uint32_t m_nInitialItems, m_nAdditionalItems; // The number of initial/additional items to allocate. KEYFN m_oKeyFn; // How we extract a key from a value. PRED m_oPred; // How we compare keys to each other. void MakeSpace (Status_t &a_reStatus, uint32_t a_nItems); // Make space in the array for the given number of items. void SearchLower (const KEY &a_rKey, uint32_t &a_rnTraverse) const; // Search for an item greater than or equal to a_rKey. void SearchUpper (const KEY &a_rKey, uint32_t &a_rnTraverse) const; // Search for an item greater than a_rKey. #ifdef DEBUG_VECTOR bool m_bDebug; #endif // DEBUG_VECTOR // true if the invariant should be checked. }; // The default node allocator. Allocates 64K at a time. template typename Vector::Allocator_t Vector::sm_oNodeAllocator (65536); // Default constructor. Must be followed by Init(). template Vector::Vector (const PRED &a_rPred, Allocator_t &a_rAlloc) : m_rNodeAllocator (a_rAlloc), m_oPred (a_rPred) { // Set up some defaults. m_bAllowDuplicates = false; m_pItems = NULL; m_nItems = m_nSpace = m_nInitialItems = m_nAdditionalItems = 0; #ifdef DEBUG_VECTOR m_bDebug = false; // Make sure we're intact. Invariant(); #endif // DEBUG_VECTOR } // Constructor. Specify whether or not duplicates are allowed, and // the initial/additional number of items to allocate. template Vector::Vector (Status_t &a_reStatus, bool a_bAllowDuplicates, const InitParams &a_rInitParams, const PRED &a_rPred, Allocator_t &a_rAlloc) : m_rNodeAllocator (a_rAlloc), m_oPred (a_rPred) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Set up some defaults. m_bAllowDuplicates = false; m_pItems = NULL; m_nItems = m_nSpace = m_nInitialItems = m_nAdditionalItems = 0; #ifdef DEBUG_VECTOR m_bDebug = false; #endif // DEBUG_VECTOR // Init() does all the work. Init (a_reStatus, a_rInitParams, a_bAllowDuplicates); } // Construction method. Specify whether or not duplicates are allowed, and // the initial/additional number of items to allocate. template void Vector::Init (Status_t &a_reStatus, bool a_bAllowDuplicates, const InitParams &a_rInitParams) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure the number of initial/additional items is sane. assert (a_rInitParams.m_nInitialItems > 0); assert (a_rInitParams.m_nAdditionalItems > 0); // Make sure we haven't been initialized already. assert (m_nInitialItems == 0); // Fill in the blanks. m_bAllowDuplicates = a_bAllowDuplicates; m_nItems = m_nSpace = 0; m_nInitialItems = a_rInitParams.m_nInitialItems; m_nAdditionalItems = a_rInitParams.m_nAdditionalItems; // No items yet. m_pItems = NULL; // Make sure we're intact. #ifdef DEBUG_VECTOR Invariant(); #endif // DEBUG_VECTOR } // Destructor. template Vector::~Vector (void) { // Make sure we're intact. #ifdef DEBUG_VECTOR Invariant(); #endif // DEBUG_VECTOR // If we have anything to delete, delete it. if (m_pItems != NULL) { for (uint32_t i = 0; i < m_nSpace; ++i) m_pItems[i].~Node(); m_rNodeAllocator.Deallocate (0, m_nSpace * sizeof (Node), (void *) m_pItems); } } #ifdef DEBUG_VECTOR // Set whether to run the vector invariant before and after methods. template void Vector::SetDebug (bool a_bDebug) { // Easy enough. m_bDebug = a_bDebug; } #endif // DEBUG_VECTOR // Insert an item into the list. template typename Vector::InsertResult Vector::Insert (Status_t &a_reStatus, const VALUE &a_rValue) { uint32_t nIndex; // The index where the new node gets inserted. InsertResult oInsertResult; // The result of the insertion. // Make sure we're intact. #ifdef DEBUG_VECTOR Invariant(); #endif // DEBUG_VECTOR // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure we have been initialized properly. assert (m_nInitialItems != 0); // Make space for this new item, if needed. MakeSpace (a_reStatus, m_nItems + 1u); if (a_reStatus != g_kNoError) { // The item cannot be inserted. oInsertResult.m_itPosition = Iterator (NULL, 0u, this); oInsertResult.m_bInserted = false; return oInsertResult; } // Find where to put this key. (Put equal keys at the upper bound.) SearchUpper (m_oKeyFn (a_rValue), nIndex); // Insert this node if there's no duplicate already in here. // // If duplicates are allowed, always insert. // If the new item is to be put at index 0, then there's no item of // the same value in the array, so it's OK to insert. // If the item before the insertion location is less than the item // being inserted, then there's no item of the same value in the array, // so it's OK to insert. if (m_bAllowDuplicates || nIndex == 0 || m_oPred (m_oKeyFn (m_pItems[nIndex - 1u].m_oValue), m_oKeyFn (a_rValue))) { // Move items out of the way to make space for the new item. // Use assignment in a loop instead of memmove(), to preserve // the value's assignment semantics (i.e. to use the value class' // assignment operator). if (nIndex != m_nItems) for (uint32_t i = m_nItems; i > nIndex; --i) m_pItems[i] = m_pItems[i - 1u]; // Install the value. m_pItems[nIndex].m_oValue = a_rValue; ++m_nItems; // Let them know where we put it, and that we did insert it. oInsertResult.m_itPosition = Iterator (m_pItems + nIndex, nIndex, this); oInsertResult.m_bInserted = true; } else { // We didn't insert it. Show them the equal item. oInsertResult.m_itPosition = Iterator (m_pItems + nIndex - 1u, nIndex - 1u, this); oInsertResult.m_bInserted = false; } // Make sure we're intact. #ifdef DEBUG_VECTOR Invariant(); #endif // DEBUG_VECTOR // Let them know what happened. return oInsertResult; } // Insert an item into the list, at this exact location, if it's safe. // Returns where it was really inserted. template typename Vector::Iterator Vector::Insert (Status_t &a_reStatus, Iterator a_itPosition, const VALUE &a_rValue) { const KEY &rKey = m_oKeyFn (a_rValue); // The key of what they're inserting. uint32_t nIndex; // The index where the new node gets inserted. InsertResult oInsertResult; // The result of the insertion. // Make sure we're intact. #ifdef DEBUG_VECTOR Invariant(); #endif // DEBUG_VECTOR // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure this iterator is sane, i.e. that it's associated with // this vector and that the node-pointer and node-index agree. assert (a_itPosition.m_pVector == this); assert (a_itPosition.m_pNode == NULL || (a_itPosition.m_nNode < m_nItems && a_itPosition.m_pNode == m_pItems + a_itPosition.m_nNode)); assert (a_itPosition.m_pNode != NULL || a_itPosition.m_nNode == 0u); // Make sure we have been initialized properly. assert (m_nInitialItems != 0u); // Make space for this new item, if needed. MakeSpace (m_nItems + 1u); // If the given iterator is at the end of the list, fix it to // point one item past the last item in the list. (Such an iterator // isn't generally considered valid, but it's only used internally.) // // At the same time, get the item-index corresponding to this iterator. if (a_itPosition.m_pNode == NULL) { nIndex = m_nItems; a_itPosition.m_pNode = m_pItems + m_nItems; } else { nIndex = a_itPosition.m_nNode; // Since space could have been reallocated by the above call to // MakeSpace(), the given iterator needs to be fixed. a_itPosition.m_pNode = m_pItems + a_itPosition.m_nNode; } // The new item has to fit where this iterator points. Iterator oBefore = a_itPosition; --oBefore; if ((a_itPosition.m_pNode != m_pItems + m_nItems && m_oPred (m_oKeyFn (a_itPosition.m_pNode->m_oValue), rKey)) || (oBefore.m_pNode != NULL && m_oPred (rKey, m_oKeyFn (oBefore.m_pNode->m_oValue)))) { // Don't use their iterator. oInsertResult = Insert (a_reStatus, a_rValue); } // Insert this node if there's no duplicate already in here. // // If duplicates are allowed, always insert. // If the new item is to be put at index 0, then there's no item of // the same value in the array, so it's OK to insert. // If the item before the insertion location is less than the item // being inserted, then there's no item of the same value in the array, // so it's OK to insert. else if (m_bAllowDuplicates || nIndex == 0 || m_oPred (m_oKeyFn (m_pItems[nIndex - 1u].m_oValue), m_oKeyFn (a_rValue))) { // Move items out of the way to make space for the new item. if (nIndex != m_nItems) { uint32_t i = m_nItems; for (;;) { m_pItems[i] = m_pItems[i - 1u]; if (i == nIndex) break; --i; } } // Install the value. m_pItems[nIndex].m_oValue = a_rValue; ++m_nItems; // Let them know where we put it, and that we did insert it. oInsertResult.m_itPosition = Iterator (m_pItems + nIndex, nIndex, this); oInsertResult.m_bInserted = true; } else { // We didn't insert it. Show them the equal item. oInsertResult.m_itPosition = Iterator (m_pItems + nIndex, nIndex, this); oInsertResult.m_bInserted = false; } // Make sure we're intact. #ifdef DEBUG_VECTOR Invariant(); #endif // DEBUG_VECTOR // Let them know what happened. return oInsertResult.m_itPosition; } // Insert a range of items from another vector. template void Vector::Insert (Status_t &a_reStatus, ConstIterator a_itFirst, ConstIterator a_itLast) { ConstIterator itHere; // The next item to insert. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure we have been initialized properly. assert (m_nInitialItems != 0u); // Try to insert every item they gave us. for (itHere = a_itFirst; itHere != a_itLast; itHere++) { Insert (a_reStatus, *itHere); if (a_reStatus != g_kNoError) { // BUG: this is messy. If we can't insert the entire range, // we shouldn't insert any of it. Fix this by preallocating // all necessary nodes. return; } } } // Erase the item here. Return the item following the one removed. template typename Vector::Iterator Vector::Erase (Iterator a_itHere) { // Make sure this iterator is sane, i.e. that it's associated with // this vector and that the node-pointer and node-index agree. assert (a_itHere.m_pVector == this); assert (a_itHere.m_pNode == NULL || (a_itHere.m_nNode < m_nItems && a_itHere.m_pNode == m_pItems + a_itHere.m_nNode)); assert (a_itHere.m_pNode != NULL || a_itHere.m_nNode == 0u); // Make sure we have been initialized properly. assert (m_nInitialItems != 0u); // Make sure we're intact. #ifdef DEBUG_VECTOR Invariant(); #endif // DEBUG_VECTOR // Don't let them erase End(). if (a_itHere.m_pNode == NULL) return Begin(); // Erase it. for (uint32_t i = a_itHere.m_nNode; i < m_nItems - 1u; ++i) m_pItems[i] = m_pItems[i + 1u]; --m_nItems; // The last item in the array was moved down one index. // Clean up the previous copy of the last item by assigning // a default instance to it. (This is probably overkill in // practice, but it keeps our C++ semantics clean.) m_pItems[m_nItems] = Node(); // Make sure we're intact. #ifdef DEBUG_VECTOR Invariant(); #endif // DEBUG_VECTOR // Return an iterator that points past the deleted node. if (a_itHere.m_nNode == m_nItems) { // If the deleted node was the last one in the array, then // one past the deleted node is End(). a_itHere.m_pNode = NULL; a_itHere.m_nNode = 0u; } return a_itHere; } // Erase a range of items in this list. Return the item following the // last one removed. template typename Vector::Iterator Vector::Erase (Iterator a_itFirst, Iterator a_itLast) { // Make sure we're intact. #ifdef DEBUG_VECTOR Invariant(); #endif // DEBUG_VECTOR // Make sure these iterators are sane, i.e. that they're associated // with this vector and that the node-pointer and node-index agree. assert (a_itFirst.m_pVector == this); assert (a_itFirst.m_pNode == NULL || (a_itFirst.m_nNode < m_nItems && a_itFirst.m_pNode == m_pItems + a_itFirst.m_nNode)); assert (a_itFirst.m_pNode != NULL || a_itFirst.m_nNode == 0u); assert (a_itLast.m_pVector == this); assert (a_itLast.m_pNode == NULL || (a_itLast.m_nNode < m_nItems && a_itLast.m_pNode == m_pItems + a_itLast.m_nNode)); assert (a_itLast.m_pNode != NULL || a_itLast.m_nNode == 0u); // Make sure we have been initialized properly. assert (m_nInitialItems != 0u); // Make sure these iterators are in the right order. assert (a_itFirst == Begin() || a_itLast == End() || !m_oPred (m_oKeyFn (a_itLast.m_pNode->m_oValue), m_oKeyFn (a_itFirst.m_pNode->m_oValue))); // If they gave us an empty range, we're done. if (a_itFirst == a_itLast) return a_itLast; // If the last-iterator is at the end of the list, fix it to // point one item past the last item in the list. (Such an iterator // isn't generally considered valid, but it's only used internally.) if (a_itLast.m_pNode == NULL) { a_itLast.m_pNode = m_pItems + m_nItems; a_itLast.m_nNode = m_nItems; } // Sanity check: make sure the node-indices are in the right order. assert (a_itFirst.m_nNode <= a_itLast.m_nNode); // Copy valid items down over the range of deleted items. uint32_t nOffset = a_itLast.m_nNode - a_itFirst.m_nNode; uint32_t nEnd = m_nItems - nOffset; for (uint32_t i = a_itFirst.m_nNode; i < nEnd; ++i) m_pItems[i] = m_pItems[i + nOffset]; // Clean up the previous instances of the moved items by assigning // default instances to them. (This is probably overkill in practice, // but it keeps our C++ semantics clean.) // Never mind...if VALUE's default constructor doesn't initialize // anything, this generates a compiler warning about that. /* Node oDefaultInstance; for (uint32_t i = nEnd; i < m_nItems; ++i) m_pItems[i] = oDefaultInstance; */ // Now we contain less items. m_nItems -= nOffset; // Make sure we're intact. #ifdef DEBUG_VECTOR Invariant(); #endif // DEBUG_VECTOR // Return the end of the removed range. a_itLast.m_pNode -= nOffset; a_itLast.m_nNode -= nOffset; return a_itLast; } // Empty the list. template void Vector::Clear (void) { // Make sure we have been initialized properly. assert (m_nInitialItems != 0u); // Clean up the previous instances of the items by assigning default // instances to them. (This is probably overkill in practice, but it // keeps our C++ semantics clean.) // Never mind...if VALUE's default constructor doesn't initialize // anything, this generates a compiler warning about that. /* Node oDefaultInstance; for (uint32_t i = 0u; i < m_nItems; ++i) m_pItems[i] = oDefaultInstance; */ // Now there are no items. m_nItems = 0u; } // Purge all internally-allocated memory. template void Vector::Purge (void) { // Make sure there are no contained items. assert (m_nItems == 0u); // If we have anything to delete, delete it. if (m_pItems != NULL) { // Destroy the contained items. for (uint32_t i = 0; i < m_nSpace; ++i) m_pItems[i].~Node(); // Deallocate the contained memory. m_rNodeAllocator.Deallocate (0, m_nSpace * sizeof (Node), (void *) m_pItems); // Now there is no contained memory. m_pItems = NULL; m_nSpace = 0u; } } // Move all items from the other vector to ourself. template void Vector::Move (Vector &a_rOther) { Node *p; uint32_t nSpace; // Used to swap structures. // Make sure the vectors can move items between themselves. assert (CanMove (a_rOther)); // Make sure we're all intact. #ifdef DEBUG_VECTOR Invariant(); a_rOther.Invariant(); #endif // DEBUG_VECTOR // Make sure we're empty. assert (m_nItems == 0); // Swap the contained arrays. p = m_pItems; m_pItems = a_rOther.m_pItems; a_rOther.m_pItems = p; // Now we have all their items. m_nItems = a_rOther.m_nItems; a_rOther.m_nItems = 0; // Swap the amount of allocated space. nSpace = m_nSpace; m_nSpace = a_rOther.m_nSpace; a_rOther.m_nSpace = nSpace; // Make sure we're all intact. #ifdef DEBUG_VECTOR Invariant(); a_rOther.Invariant(); #endif // DEBUG_VECTOR } // Returns true if the two vectors can move their items between each other. template bool Vector::CanMove (const Vector &a_rOther) const { // They can if they have the same allocator. return (&m_rNodeAllocator == &a_rOther.m_rNodeAllocator); } // Assign the contents of the other vector to ourselves. template void Vector::Assign (Status_t &a_reStatus, const Vector &a_rOther) { Node *pBegin, *pEnd; // Where we're looking in the other list. // Make sure we're all intact. #ifdef DEBUG_VECTOR Invariant(); a_rOther.Invariant(); #endif // DEBUG_VECTOR // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure we have been initialized properly. assert (m_nInitialItems != 0u); // Get the range of items from the other list. pBegin = a_rOther.Begin().m_pNode; pEnd = a_rOther.End().m_pNode; // Make space for all the items in the other vector, if needed. MakeSpace (a_reStatus, a_rOther.m_nItems); if (a_reStatus != g_kNoError) return; // Copy all the items. for (uint32_t i = 0u; i < a_rOther.m_nItems; ++i) m_pItems[i] = a_rOther.m_pItems[i]; m_nItems = a_rOther.m_nItems; // Make sure we're all intact. #ifdef DEBUG_VECTOR Invariant(); #endif // DEBUG_VECTOR } // Find the given item in the list. Returns End() if not found. template typename Vector::Iterator Vector::Find (const KEY &a_rKey) { Iterator itHere; // What we found. // Make sure we're intact. #ifdef DEBUG_VECTOR Invariant(); #endif // DEBUG_VECTOR // Make sure we have been initialized properly. assert (m_nInitialItems != 0u); // Look for the item. itHere = LowerBound (a_rKey); // LowerBound() returns the first item >= the key. So if this item // is greater than what they were asking for, that means we didn't // find it. if (itHere == End() || m_oPred (a_rKey, m_oKeyFn (itHere.m_pNode->m_oValue))) return End(); else return itHere; } // Find the given item in the list. Returns End() if not found. template typename Vector::ConstIterator Vector::Find (const KEY &a_rKey) const { ConstIterator itHere; // What we found. // Make sure we're intact. #ifdef DEBUG_VECTOR Invariant(); #endif // DEBUG_VECTOR // Make sure we have been initialized properly. assert (m_nInitialItems != 0u); // Look for the item. itHere = LowerBound (a_rKey); // LowerBound() returns the first item >= the key. So if this item // is greater than what they were asking for, that means we didn't // find it. if (itHere == End() || m_oPred (a_rKey, m_oKeyFn (itHere.m_pNode->m_oValue))) return End(); else return itHere; } // Return the position of the first item that's >= the key. template typename Vector::Iterator Vector::LowerBound (const KEY &a_rKey) { // Make sure we have been initialized properly. assert (m_nInitialItems != 0u); // Search for the first item >= the key. uint32_t nIndex; SearchLower (a_rKey, nIndex); // Return what we found. if (nIndex < m_nItems) return Iterator (m_pItems + nIndex, nIndex, this); else return End(); } // Return the position of the first item that's >= the key. template typename Vector::ConstIterator Vector::LowerBound (const KEY &a_rKey) const { // Make sure we have been initialized properly. assert (m_nInitialItems != 0u); // Search for the first item >= the key. uint32_t nIndex; SearchLower (a_rKey, nIndex); // Return what we found. if (nIndex < m_nItems) return ConstIterator (m_pItems + nIndex, nIndex, this); else return End(); } // Return the position of the first item that's > the key. template typename Vector::Iterator Vector::UpperBound (const KEY &a_rKey) { // Make sure we have been initialized properly. assert (m_nInitialItems != 0u); // Search for the first item >= the key. uint32_t nIndex; SearchUpper (a_rKey, nIndex); // Return what we found. if (nIndex < m_nItems) return Iterator (m_pItems + nIndex, nIndex, this); else return End(); } // Return the position of the first item that's > the key. template typename Vector::ConstIterator Vector::UpperBound (const KEY &a_rKey) const { // Make sure we have been initialized properly. assert (m_nInitialItems != 0u); // Search for the first item >= the key. uint32_t nIndex; SearchUpper (a_rKey, nIndex); // Return what we found. if (nIndex < m_nItems) return ConstIterator (m_pItems + nIndex, nIndex, this); else return End(); } // Make space in the array for the given number of items. template void Vector::MakeSpace (Status_t &a_reStatus, uint32_t a_nItems) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure we have been initialized properly. assert (m_nInitialItems != 0u); // If there isn't space for this many items, allocate it, if (m_nSpace < a_nItems) { uint32_t nSpace; // The amount of space the vector will have now. Node *pSpace; // The newly allocated space. // If no items have been allocated yet, do so. // If items have been allocated, allocate some additional items. // Allocate at least as many as they asked for. nSpace = Max (((m_nSpace == 0u) ? m_nInitialItems : m_nSpace + m_nAdditionalItems), a_nItems); // Sanity check: make sure we're trying to allocate more space. assert (nSpace > m_nSpace); // Allocate this much space. pSpace = (Node *) m_rNodeAllocator.Allocate (0, nSpace * sizeof (Node)); if (pSpace == NULL) { a_reStatus = g_kOutOfMemory; return; } // Copy the valid items to their new location. for (uint32_t i = 0; i < m_nItems; ++i) new ((void *)(pSpace + i)) Node (m_pItems[i]); // (Create all of the unused nodes.) for (uint32_t i = m_nItems; i < nSpace; ++i) new ((void *)(pSpace + i)) Node; // Now we have more space for items. if (m_pItems != NULL) { for (uint32_t i = 0; i < m_nSpace; ++i) m_pItems[i].~Node(); m_rNodeAllocator.Deallocate (0, m_nSpace * sizeof (Node), (void *) m_pItems); } m_pItems = pSpace; m_nSpace = nSpace; } } // Search for an item greater than or equal to a_rKey. template void Vector::SearchLower (const KEY &a_rKey, uint32_t &a_rnTraverse) const { uint32_t nIndex; // Where we're searching. uint32_t nLow, nHigh; // The range of items we're searching. // Make sure we're intact. #ifdef DEBUG_VECTOR Invariant(); #endif // DEBUG_VECTOR // Make sure we have been initialized properly. assert (m_nInitialItems != 0u); // Do a binary search through the array, looking for the first // item that's >= a_rKey. nLow = 0; nHigh = m_nItems; while (nLow < nHigh) { // Get the current item. nIndex = (nLow + nHigh) >> 1; const KEY &rKey = m_oKeyFn (m_pItems[nIndex].m_oValue); // If it's less than the item we're looking for, we don't need to // search below this item, and this item is definitely not the one // we're looking for. if (m_oPred (rKey, a_rKey)) nLow = nIndex + 1u; // If it's greater than or equal to the item we're looking for, we // don't need to search above this item, but this item might be the // one we're looking for. else nHigh = nIndex; // Sanity check: make sure we don't enter an infinite loop. assert (nLow == nHigh || ((nLow + nHigh) >> 1) != nIndex); } // Let our caller know what we found. assert (nLow == nHigh); a_rnTraverse = nLow; } // Search for an item greater than a_rKey. template void Vector::SearchUpper (const KEY &a_rKey, uint32_t &a_rnTraverse) const { uint32_t nIndex; // Where we're searching. uint32_t nLow, nHigh; // The range of items we're searching. // Make sure we're intact. #ifdef DEBUG_VECTOR Invariant(); #endif // DEBUG_VECTOR // Make sure we have been initialized properly. assert (m_nInitialItems != 0u); // Do a binary search through the array, looking for the first // item that's > a_rKey. nLow = 0; nHigh = m_nItems; while (nLow < nHigh) { // Get the current item. nIndex = (nLow + nHigh) >> 1; const KEY &rKey = m_oKeyFn (m_pItems[nIndex].m_oValue); // If it's greater than the item we're looking for, we don't need // to search above this item, but this item might be the one we're // looking for. if (m_oPred (a_rKey, rKey)) nHigh = nIndex; // If it's less than or equal to the item we're looking for, we // don't need to search below this item, and this item is // definitely not the one we're looking for. else nLow = nIndex + 1u; // Sanity check: make sure we don't enter an infinite loop. assert (nLow == nHigh || ((nLow + nHigh) >> 1) != nIndex); } // Let our caller know what we found. assert (nLow == nHigh); a_rnTraverse = nLow; } #ifdef DEBUG_VECTOR template void Vector::Invariant (void) const { // Only check the invariant if they requested we do. if (!m_bDebug) return; // If the vector is not fully initialized, we have less to check. if (m_nInitialItems == 0u) { assert (m_pItems == NULL); assert (m_nItems == 0); assert (m_nSpace == 0); assert (m_nAdditionalItems == 0); return; } // If there are any items allocated, check them. if (m_nItems != 0u) { // Make sure we don't have more items than we have space for items. assert (m_nItems <= m_nSpace); // Run through the array, make sure the items are sorted properly. // (The first and last item don't need to be iterated through here, // since there's no item before the first and no item after the // last.) for (uint32_t i = 1u; i < m_nItems - 1u; ++i) { // Make sure that the nodes are in proper sorted order. if (m_bAllowDuplicates) { // The current item has to be >= the previous item. assert (!m_oPred (m_oKeyFn (m_pItems[i].m_oValue), m_oKeyFn (m_pItems[i - 1u].m_oValue))); } else { // The current item has to be > the previous item. assert (m_oPred (m_oKeyFn (m_pItems[i - 1u].m_oValue), m_oKeyFn (m_pItems[i].m_oValue))); } } } } #endif // DEBUG_VECTOR #endif // __VECTOR_H__ mjpegtools-2.1.0/y4mdenoise/VariableSizeAllocator.hh0000644000175000017500000003437411204303657023047 0ustar glowwormglowworm#ifndef __VARIABLESIZEALLOCATOR_H__ #define __VARIABLESIZEALLOCATOR_H__ // This file (C) 2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. #include "config.h" #include "mjpeg_types.h" #include #include "Limits.hh" #include "PlacementAllocator.hh" #include "Set.hh" // Define this to print progress to stderr. //#define VSA_PRINT_PROGRESS // Define this to be a value larger than zero in order to guard // memory allocations from writing out of bounds. #define VSA_GUARD_SIZE 0 // An allocator for variable-sized blocks of memory. It gets large chunks // from the standard memory allocator & divides it up. // // It maintains its own free-space set, using a SkipList<> with a // PlacementAllocator. This allows the free blocks themselves to be used // by the skip-list nodes, allowing for an in-place free-space set. class VariableSizeAllocator { private: // One block of memory. class Block { public: #ifndef NDEBUG void *m_pMemory; #endif // !NDEBUG // The address of the block. // Only needed for verification. size_t m_nBytes; // The size of the block, in bytes. // A comparison class, suitable for Set<>. class SortBySize { public: inline bool operator() (const Block &a_rLeft, const Block &a_rRight) const { return a_rLeft.m_nBytes < a_rRight.m_nBytes; } }; }; typedef SkipList,Block::SortBySize, 10,PlacementAllocator> SetImpl_t; // How the free-space set is implemented internally. public: typedef SetImpl_t::InitParams InitParams; // How that internal type is initialized. VariableSizeAllocator (size_t a_nChunkSize); // Constructor. Specify the number of bytes to allocate at a // time from the standard memory allocator. void Init (Status_t &a_reStatus, const InitParams &a_rInitParams = InitParams()); // Construction method. ~VariableSizeAllocator(); // Destructor. void *Allocate (size_t a_nSize, size_t a_nBytes); // Allocate memory for another object. // Use the given size-bucket, which must be for the given number // of bytes. // Returns NULL if memory is exhausted. void Deallocate (size_t a_nSize, size_t a_nBytes, void *a_pMemory); // Deallocate previously-allocated memory. uint32_t GetNumAllocated (void) const { return m_ulAllocated; } // Get the number of allocated blocks. private: // One chunk of memory. class Chunk { public: Chunk *m_pNext; // The next allocated chunk. char m_aSpace[]; // The memory to divide up. }; size_t m_nChunkSize; // The size of all allocated chunks (unless a particular request is // over this size). Set by the constructor. Chunk *m_pChunks; // A linked-list of all the allocated chunks. char *m_pFreeChunk; size_t m_nFreeChunk; // The next piece of unallocated memory in the // most-recently-allocated chunk. PlacementAllocator m_oPlacementAllocator; // Used to allow Set<> to implement our free-space list in-place. typedef Set FreeSpaceSet_t; FreeSpaceSet_t m_setFreeSpace; // The free-space set. Uses the free-blocks in-place as skip-list // nodes. size_t m_nSmallestBlockSize; // The size of the smallest block that can be allocated. // // Currently, this holds the size of the largest skip-list node // possible in m_setFreeSpace. // There may be other restrictions later. uint32_t m_ulAllocated; // The number of live allocations, i.e. those that haven't been // deleted yet. void Purge (void); // Free up all chunks. // Only safe if there are no live allocations. }; // Constructor. Specify the number of bytes to allocate at a // time from the standard memory allocator. VariableSizeAllocator::VariableSizeAllocator (size_t a_nChunkSize) : m_nChunkSize (a_nChunkSize), m_pChunks (NULL), m_pFreeChunk (NULL), m_nFreeChunk (0), m_oPlacementAllocator (a_nChunkSize), m_setFreeSpace (Block::SortBySize(), m_oPlacementAllocator), m_nSmallestBlockSize (m_setFreeSpace.GetSizeOfLargestNode()), m_ulAllocated (0UL) { // Nothing else to do. } // Construction method. void VariableSizeAllocator::Init (Status_t &a_reStatus, const InitParams &a_rInitParams) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Finish setting up the free-space list. // Allow duplicates, i.e. free blocks of the same size. m_setFreeSpace.Init (a_reStatus, true, a_rInitParams); if (a_reStatus != g_kNoError) return; } // Destructor. VariableSizeAllocator::~VariableSizeAllocator() { // If all allocated objects were deallocated, go ahead and free // up our memory. (If there are any allocated objects left, then // generally, that means this is a global allocator, and since C++ // doesn't guarantee order of destruction for global objects, we // have no guarantee our clients have been destroyed, and so it // isn't safe to delete our memory.) if (m_ulAllocated == 0UL && m_pChunks != NULL) Purge(); } // Allocate memory for another object. // Use the given size-bucket, which must be for the given number // of bytes. // Returns NULL if memory is exhausted. void * VariableSizeAllocator::Allocate (size_t a_nSize, size_t a_nBytes) { void *pAlloc; // The memory we allocate. // Make sure they gave us a valid size. // (This allocator has only one bucket.) assert (a_nSize == 0); // Make sure they gave us a valid number of bytes. assert (a_nBytes >= 0); // Adjust the size of the block so that it's large enough to be in the // free-space set. a_nBytes = Max (a_nBytes, m_nSmallestBlockSize); // Round the number of bytes up to the nearest pointer size. a_nBytes = ((a_nBytes + sizeof (Chunk *) - 1) / sizeof (Chunk *)) * sizeof (Chunk *); // Print our progress. #ifdef VSA_PRINT_PROGRESS fprintf (stderr, "\tVariableSizeAllocator::Allocate(): request for " "%d bytes\n", (int)a_nBytes); fprintf (stderr, "\t\tFree-space set has %d entries\n", (int)m_setFreeSpace.Size()); #endif // VSA_PRINT_PROGRESS // Look for a block of memory that's this size, or larger. // // Look for the upper bound, which will find the first block that's // greater than the requested size, and then get the previous item. // SkipList<> puts equal-valued keys (in this case, equal-size blocks) // at the upper-bound. In order to maximize memory locality, free space // is allocated as a stack, not a queue. Block oSearch; oSearch.m_nBytes = a_nBytes; FreeSpaceSet_t::Iterator itHere = m_setFreeSpace.UpperBound (oSearch); --itHere; if (itHere != m_setFreeSpace.End() && (*itHere).m_nBytes == a_nBytes) { // Get the address of this block. #ifndef NDEBUG void *pMemoryDebug = (*itHere).m_pMemory; #endif // !NDEBUG // Remove this block from the free-space set. m_setFreeSpace.Erase (itHere); // Get the address of the freed block. size_t nBytesUnused = 0; pAlloc = m_oPlacementAllocator.GetDeallocatedMemory (nBytesUnused); // Print our progress. #ifdef VSA_PRINT_PROGRESS fprintf (stderr, "\t\t(Found in free-space set, address %08X)\n", (int)pAlloc); #endif // VSA_PRINT_PROGRESS // Double-check the address and size of the block. assert (pAlloc == pMemoryDebug); // Guard against writing out of bounds. #if VSA_GUARD_SIZE > 0 { uint32_t *pGuard; size_t uGuard; // Guard the area before the block. pGuard = (uint32_t *)pAlloc; uGuard = VSA_GUARD_SIZE; while (uGuard > 0) { --pGuard; assert (*pGuard == 0xDEADBEEF); uGuard -= sizeof (uint32_t); } // Guard the area after the block. pGuard = (uint32_t *)((int)pAlloc + a_nBytes); uGuard = VSA_GUARD_SIZE; while (uGuard > 0) { assert (*pGuard == 0xC0EDBABE); ++pGuard; uGuard -= sizeof (uint32_t); } } #endif // VSA_GUARD_SIZE > 0 // Return the allocated memory. goto allocated; } // Adjust the size of the block for any guard regions. #if VSA_GUARD_SIZE > 0 a_nBytes += 2 * VSA_GUARD_SIZE; #endif // VSA_GUARD_SIZE > 0 // If there's enough unallocated space in the current chunk, // use it. if (m_pFreeChunk != NULL && m_nFreeChunk >= a_nBytes) { // Remember the allocated memory. pAlloc = (void *) m_pFreeChunk; // Move past this new allocated memory. m_pFreeChunk += a_nBytes; m_nFreeChunk -= a_nBytes; // Print our progress. #ifdef VSA_PRINT_PROGRESS fprintf (stderr, "\t\t(Found in current chunk, address %08X, " "%d bytes left)\n", (int)pAlloc, m_nFreeChunk); #endif // VSA_PRINT_PROGRESS // Return the allocated memory. goto allocated; } // We'll have to create a new chunk in order to satisfy this // allocation request. // First, find a place for the rest of this chunk, if it's big enough // to be a free-space block. (Otherwise, it remains unused.) if (m_nFreeChunk >= m_nSmallestBlockSize) { // Set up this chunk to be a free-space block. Block oInsertBlock; #ifndef NDEBUG oInsertBlock.m_pMemory = m_pFreeChunk; #endif // !NDEBUG oInsertBlock.m_nBytes = m_nFreeChunk; // Put this block into the free-space set. // Since the placement allocator doesn't actually allocate memory, // the insertion can't fail. m_oPlacementAllocator.SetAllocatedMemory (m_pFreeChunk, m_nFreeChunk); Status_t eStatus = g_kNoError; #ifndef NDEBUG FreeSpaceSet_t::InsertResult oInsertResult = #endif // !NDEBUG m_setFreeSpace.Insert (eStatus, oInsertBlock); assert (eStatus == g_kNoError); assert (oInsertResult.m_bInserted); // Print our progress. #ifdef VSA_PRINT_PROGRESS fprintf (stderr, "\t\t(Put rest of chunk, address %08X, %d bytes, " "into free-space set)\n", (int)m_pFreeChunk, m_nFreeChunk); #endif // VSA_PRINT_PROGRESS // Now there's no more free chunk. m_pFreeChunk = NULL; m_nFreeChunk = 0; } // Create a new chunk and allocate a portion of it. { // Calculate the size of the new chunk. // Make sure it's big enough to handle this allocation, i.e. in case // it's bigger than the configured chunk size. size_t nChunkSize = ((a_nBytes + 2 * sizeof (Chunk *) - 1) / sizeof (Chunk *)) * sizeof (Chunk *); nChunkSize = Max (nChunkSize, m_nChunkSize); // Add a new chunk to our list. { // Allocate a new chunk. Chunk *pNewChunk = (Chunk *) malloc (nChunkSize); if (pNewChunk == NULL) return NULL; // Hook it into our list. pNewChunk->m_pNext = m_pChunks; m_pChunks = pNewChunk; } // Allocate a portion of the chunk. pAlloc = (void *)(&(m_pChunks->m_aSpace)); // Print our progress. #ifdef VSA_PRINT_PROGRESS fprintf (stderr, "\t\t(Allocated new chunk, address %08X, " "%d bytes)\n", (int)pAlloc, nChunkSize); #endif // VSA_PRINT_PROGRESS // The unallocated portion of the new chunk is here. m_pFreeChunk = m_pChunks->m_aSpace + a_nBytes; assert (((char *)m_pChunks + nChunkSize) // (Sanity check) >= m_pChunks->m_aSpace + a_nBytes); m_nFreeChunk = ((char *)m_pChunks + nChunkSize - a_nBytes) - m_pChunks->m_aSpace; } // (All successful memory allocations end up here. allocated:; // That's one more allocation. ++m_ulAllocated; // Guard against writing out of bounds. #if VSA_GUARD_SIZE > 0 { uint32_t *pGuard; size_t uGuard; // Guard the area before the block. pGuard = (uint32_t *)pAlloc; uGuard = VSA_GUARD_SIZE; while (uGuard > 0) { *pGuard = 0xDEADBEEF; ++pGuard; uGuard -= sizeof (uint32_t); } // Guard the area after the block. pGuard = (uint32_t *)((int)pAlloc + a_nBytes); uGuard = VSA_GUARD_SIZE; while (uGuard > 0) { --pGuard; *pGuard = 0xC0EDBABE; uGuard -= sizeof (uint32_t); } // Give our caller the area between the guards. pAlloc = (void *)((int)pAlloc + VSA_GUARD_SIZE); } #endif // VSA_GUARD_SIZE > 0 // Return the allocated memory. return pAlloc; } // Deallocate previously-allocated memory. void VariableSizeAllocator::Deallocate (size_t a_nSize, size_t a_nBytes, void *a_pMemory) { // Make sure they gave us a valid size. // (This allocator has only one bucket.) assert (a_nSize == 0); // Print our progress. #ifdef VSA_PRINT_PROGRESS fprintf (stderr, "\tVariableSizeAllocator::Deallocate(): freed " "%d bytes at %08X\n", (int)a_nBytes, (int)a_pMemory); #endif // VSA_PRINT_PROGRESS // Guard against writing out of bounds. #if VSA_GUARD_SIZE > 0 { uint32_t *pGuard; size_t uGuard; // Guard the area before the block. pGuard = (uint32_t *)a_pMemory; uGuard = VSA_GUARD_SIZE; while (uGuard > 0) { --pGuard; assert (*pGuard == 0xDEADBEEF); uGuard -= sizeof (uint32_t); } // Guard the area after the block. pGuard = (uint32_t *)((int)a_pMemory + a_nBytes); uGuard = VSA_GUARD_SIZE; while (uGuard > 0) { assert (*pGuard == 0xC0EDBABE); ++pGuard; uGuard -= sizeof (uint32_t); } // Reclaim the given memory and the guard areas. a_pMemory = (void *)((int)a_pMemory - VSA_GUARD_SIZE); a_nBytes += 2 * VSA_GUARD_SIZE; } #endif // VSA_GUARD_SIZE > 0 // Set up this chunk to be a free-space block. Block oInsertBlock; #ifndef NDEBUG oInsertBlock.m_pMemory = a_pMemory; #endif // !NDEBUG oInsertBlock.m_nBytes = a_nBytes; // Put this block into the free-space set. // Since the placement allocator doesn't actually allocate memory, // the insertion can't fail. m_oPlacementAllocator.SetAllocatedMemory (a_pMemory, a_nBytes); Status_t eStatus = g_kNoError; #ifndef NDEBUG FreeSpaceSet_t::InsertResult oInsertResult = #endif // !NDEBUG m_setFreeSpace.Insert (eStatus, oInsertBlock); assert (eStatus == g_kNoError); assert (oInsertResult.m_bInserted); // That's one less allocation. --m_ulAllocated; // If all memory is unallocated, free up our chunks & start over. if (m_ulAllocated == 0UL) Purge(); } // Free up all chunks. void VariableSizeAllocator::Purge (void) { // Make sure there are no live allocations assert (m_ulAllocated == 0UL); // Empty the free-space set. if (m_setFreeSpace.Size() > 0) { // Clear the free-space set. m_setFreeSpace.Clear(); // Forget about any recently deallocated memory. size_t nBytesUnused = 0; (void) m_oPlacementAllocator.GetDeallocatedMemory (nBytesUnused); } // No more free chunk. m_pFreeChunk = NULL; m_nFreeChunk = 0; // Free all allocated chunks. while (m_pChunks != NULL) { // Remember the next chunk. Chunk *pNextChunk = m_pChunks->m_pNext; // Free this chunk. free (m_pChunks); // Move to the next chunk. m_pChunks = pNextChunk; } } #endif // __VARIABLESIZEALLOCATOR_H__ mjpegtools-2.1.0/y4mdenoise/Region2D.hh0000644000175000017500000007034011200710424020216 0ustar glowwormglowworm#ifndef __REGION2D_H__ #define __REGION2D_H__ // This file (C) 2004-2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. // Region2D tracks a 2-dimensional region of arbitrary points. // // It's the base class for more specific implementations of regions, // which only have to be compatible in the interface sense -- they // don't have to support being called properly through a base-class // pointer, they only have to be interchangeable when used as template // parameters. Region2D contains the interface definition & all the // code that will work with any implementation of regions. #include "Status_t.h" #include // The 2-dimensional region class. Parameterized by the numeric type // to use for point indices, and the numeric type to use to count the // contained number of points. // This was an attempt to create a generic base class for 2-dimensional // regions. It can't be done without making many methods virtual, which // would prevent them from being inlined, and thus would impact // performance. Many methods do have a non-region-specific // implementation, just not enough. // The commented-out method prototypes are methods to be implemented by // subclasses. Not all methods have to be implemented, depending on // whether it's appropriate for the subclass, but that may impact how // widely the subclass may be used. template class Region2D { public: // An extent within the region, representing a continuous series of // points in a horizontal line. Used by iterator classes to return // successive parts of the region. class Extent { public: INDEX m_tnY, m_tnXStart, m_tnXEnd; // The y-index, and the start/end x-indices, of the extent. // Note that m_tnXEnd is technically one past the end. Extent() {} // Default constructor. Extent (INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd) : m_tnY (a_tnY), m_tnXStart (a_tnXStart), m_tnXEnd (a_tnXEnd) {} // Initializing constructor. bool operator== (const Extent &a_rOther) const { return (m_tnY == a_rOther.m_tnY && m_tnXStart == a_rOther.m_tnXStart && m_tnXEnd == a_rOther.m_tnXEnd) ? true : false; } // Equality operator. bool operator!= (const Extent &a_rOther) const { return (m_tnY != a_rOther.m_tnY || m_tnXStart != a_rOther.m_tnXStart || m_tnXEnd != a_rOther.m_tnXEnd) ? true : false; } // Inequality operator. inline bool operator < (const Extent &a_rOther) const; // Less-than operator. }; Region2D(); // Default constructor. Must be followed by Init(). template Region2D (Status_t &a_reStatus, const REGION &a_rOther); // Copy constructor. //void Init (Status_t &a_reStatus); // Initializer. Must be called on default-constructed regions. template void Assign (Status_t &a_reStatus, const REGION &a_rOther); // Make the current region a copy of the other region. virtual ~Region2D(); // Destructor. //SIZE NumberOfPoints (void) const; // Return the total number of points contained by the region. void Clear (void); // Clear the region, emptying it of all extents. //void Union (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, // INDEX a_tnXEnd); // Add the given horizontal extent to the region. Note that // a_tnXEnd is technically one past the end of the extent. template void UnionDebug (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd, REGION_TEMP &a_rTemp); // Add the given horizontal extent to the region. Note that // a_tnXEnd is technically one past the end of the extent. // Exhaustively (i.e. slowly) verifies the results, using a // much simpler algorithm. // Requires the use of a temporary region, usually of the // final subclass' type, in order to work. (Since that can't // be known at this level, a template parameter is included for // it.) template void Union (Status_t &a_reStatus, const REGION &a_rOther); // Make the current region represent the union between itself // and the other given region. template void UnionDebug (Status_t &a_reStatus, REGION_O &a_rOther, REGION_TEMP &a_rTemp); // Make the current region represent the union between itself // and the other given region. // Exhaustively (i.e. slowly) verifies the results, using a // much simpler algorithm. // Requires the use of a temporary region, usually of the // final subclass' type, in order to work. (Since that can't // be known at this level, a template parameter is included for // it.) //void Merge (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, // INDEX a_tnXEnd); // Merge this extent into the current region. // The new extent can't intersect any of the region's existing // extents (including being horizontally contiguous). //void Merge (Region2D &a_rOther); // Merge the other region into ourselves, emptying the other // region. Like Union(), but doesn't allocate any new memory. // Also, the other region can't intersect any of the region's // existing extents (including being horizontally contiguous), // and both regions must use the same allocator. //void Move (Region2D &a_rOther); // Move the contents of the other region into the current // region. // The current region must be empty. template bool CanMove (const REGION &a_rOther) const { return false; } // Returns true if the other region's contents can be moved // into the current region. // (False by default; subclasses will have to implement // specialized methods that explain when this is true.) template void Move (REGION &a_rOther) { assert (false); } // Let clients know we can't move extents between regions of // different types by default. //void Intersection (Status_t &a_reStatus, // const Region2D &a_rOther); // Make the current region represent the intersection between // itself and the other given region. //void Subtract (Status_t &a_reStatus, INDEX a_tnY, // INDEX a_tnXStart, INDEX a_tnXEnd); // Subtract the given horizontal extent from the region. Note // that a_tnXEnd is technically one past the end of the extent. template void SubtractDebug (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd, REGION_TEMP &a_rTemp); // Subtract the given horizontal extent from the region. Note // that a_tnXEnd is technically one past the end of the extent. // Exhaustively (i.e. slowly) verifies the results, using a // much simpler algorithm. // Requires the use of a temporary region, usually of the // final subclass' type, in order to work. (Since that can't // be known at this level, a template parameter is included for // it.) template void Subtract (Status_t &a_reStatus, const REGION &a_rOther); // Subtract the other region from the current region, i.e. // remove from the current region any extents that exist in the // other region. template void SubtractDebug (Status_t &a_reStatus, REGION_O &a_rOther, REGION_TEMP &a_rTemp); // Subtract the other region from the current region, i.e. // remove from the current region any extents that exist in the // other region. // Exhaustively (i.e. slowly) verifies the results, using a // much simpler algorithm. // Requires the use of a temporary region, usually of the // final subclass' type, in order to work. (Since that can't // be known at this level, a template parameter is included for // it.) //typedef ... ConstIterator; //ConstIterator Begin (void) const { return m_setExtents.Begin(); } //ConstIterator End (void) const { return m_setExtents.End(); } // Allow our client to iterate through the extents & get their // values. //bool DoesContainPoint (INDEX a_tnY, INDEX a_tnX); // Returns true if the region contains the given point. //bool DoesContainPoint (INDEX a_tnY, INDEX a_tnX, // ConstIterator &a_ritHere); // Returns true if the region contains the given point. // Backpatches the extent that contains the point, or the // extent before where it should be. // A structure that helps implement flood-fills. Clients should // create a derived (or structurally compatible) class that, at a // minimum, describes whether a new point should be added to the // region. (The definition of this class follows the definition of // Region2D<>.) template class FloodFillControl; template void FloodFill (Status_t &a_reStatus, CONTROL &a_rControl, bool a_bVerify, bool a_bExpand); // Flood-fill the current region. // If a_bVerify is true, all existing region points are re-tested. // If a_bExpand is true, all points bordering the current region // are tested for inclusion. template void MakeBorder (Status_t &a_reStatus, const REGION &a_rOther); // Make the current region represent the border of the other // region, i.e. every pixel that's adjacent to a pixel that's // in the region, but isn't already in the region. void UnionSurroundingExtents (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd); // Add all extents surrounding the given extent. // Used by FloodFill() and MakeBorder(). }; template std::ostream & operator<< (std::ostream &a_rOut, const Region2D &a_rRegion); // The flood-fill-control class. template template class Region2D::FloodFillControl { public: // (Although these fields are public, they should be considered // opaque to the client.) REGION m_oToDo; // Extents that still need to be be tested. REGION m_oAlreadyDone; // Extents that have been tested. REGION m_oNextToDo; // Extents contiguous with those that have just been added // to the flood-filled area. typedef typename REGION::ConstIterator ConstIterator; typedef typename REGION::Extent Extent; // The iterator/extent type for running through the above // regions. public: FloodFillControl(); // Default constructor. Must be followed by a call to Init(). FloodFillControl (Status_t &a_reStatus); // Initializing constructor. void Init (Status_t &a_reStatus); // Initializer. Must be called on default-constructed objects. // (May not be valid to call on subclasses, depending on // whether more parameters are needed for its Init().) // Methods to be redefined by clients implementing specific // flood-fills. bool ShouldUseExtent (Extent &a_rExtent) { return true; } // Return true if the flood-fill should examine the given // extent. Clients should redefine this to define their own // criteria for when extents should be used, and to modify the // extent as needed (e.g. to clip the extent to a bounding box). bool IsPointInRegion (INDEX a_tnX, INDEX a_tnY) { return false; } // Returns true if the given point should be included in the // flood-fill. Clients must redefine this to explain their // flood-fill criteria. }; #if 0 // I'm not sure how to do this yet. If the template just takes "class // REGION", I think it'll try to match everything in the world, and // that wouldn't be good. But how to do this??? // Also, iterators aren't actually defined at the Region2D<> level. // Print the region's contents. template std::ostream & operator<< (std::ostream &a_rOut, const Region2D &a_rRegion) { Region2D::ConstIterator itHere; // Used to loop through the region. // Print the region header. a_rOut << "( "; // Print each extent. for (itHere = Begin(); itHere != End(); ++itHere) { // Print the extent. a_rOut << '[' << ((*itHere).m_tnY) << ',' << ((*itHere).m_tnXStart) << '-' << ((*itHere).m_tnXEnd) << "] "; } // Print the region trailer. a_rOut << ")" return a_rOut; } #endif // Default constructor. Must be followed by Init(). template Region2D::Region2D() { // Nothing to do. } // Copy constructor. template template Region2D::Region2D (Status_t &a_reStatus, const REGION &a_rOther) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Copy all the extents. for (typename REGION::ConstIterator itHere = a_rOther.Begin(); itHere != a_rOther.End(); ++itHere) { Merge (a_reStatus, (*itHere).m_tnY, (*itHere).m_tnXStart, (*itHere).m_tnXEnd); if (a_reStatus != g_kNoError) return; } } // Make the current region a copy of the other region. template template void Region2D::Assign (Status_t &a_reStatus, const REGION &a_rOther) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Assign the other region's extents to ourselves. Clear(); for (typename REGION::ConstIterator itHere = a_rOther.Begin(); itHere != a_rOther.End(); ++itHere) { Merge (a_reStatus, (*itHere).m_tnY, (*itHere).m_tnXStart, (*itHere).m_tnXEnd); if (a_reStatus != g_kNoError) return; } } // Destructor. template Region2D::~Region2D() { // Nothing to do. } // Add the given horizontal extent to the region. template template void Region2D::UnionDebug (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd, REGION_TEMP &a_rTemp) { typename REGION::ConstIterator itHere; typename REGION_TEMP::ConstIterator itHereO; INDEX tnX; // Used to loop through points. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Calculate the union. a_rTemp.Assign (a_reStatus, *this); if (a_reStatus != g_kNoError) return; a_rTemp.Union (a_reStatus, a_tnY, a_tnXStart, a_tnXEnd); if (a_reStatus != g_kNoError) return; // Loop through every point in the result, make sure it's in // one of the two input regions. for (itHereO = a_rTemp.Begin(); itHereO != a_rTemp.End(); ++itHereO) { const Extent &rHere = *itHereO; for (tnX = rHere.m_tnXStart; tnX < rHere.m_tnXEnd; ++tnX) { if (!((rHere.m_tnY == a_tnY && (tnX >= a_tnXStart && tnX < a_tnXEnd)) || this->DoesContainPoint (rHere.m_tnY, tnX))) goto error; } } // Loop through every point in the original region, make sure // it's in the result. for (itHere = this->Begin(); itHere != this->End(); ++itHere) { const Extent &rHere = *itHere; for (tnX = rHere.m_tnXStart; tnX < rHere.m_tnXEnd; ++tnX) { if (!a_rTemp.DoesContainPoint (rHere.m_tnY, tnX)) goto error; } } // Loop through every point in the added extent, make sure it's in // the result. for (tnX = a_tnXStart; tnX < a_tnXEnd; ++tnX) { if (!a_rTemp.DoesContainPoint (a_tnY, tnX)) goto error; } // The operation succeeded. Commit it. Assign (a_reStatus, a_rTemp); if (a_reStatus != g_kNoError) return; // All done. return; error: // Handle deviations. fprintf (stderr, "Region2D::Union() failed\n"); fprintf (stderr, "Input region:\n"); PrintRegion (*this); fprintf (stderr, "Input extent: [%d,%d-%d]\n", int (a_tnY), int (a_tnXStart), int (a_tnXEnd)); fprintf (stderr, "Result:\n"); PrintRegion (a_rTemp); assert (false); } // Make the current region represent the union between itself // and the other given region. template template void Region2D::Union (Status_t &a_reStatus, const REGION &a_rOther) { typename REGION::ConstIterator itHere; // Where we are in the other region's extents. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Run through the extents in the other region, add them to the // current region. for (itHere = a_rOther.Begin(); itHere != a_rOther.End(); ++itHere) { // Add this extent to the current region. Union (a_reStatus, (*itHere).m_tnY, (*itHere).m_tnXStart, (*itHere).m_tnXEnd); if (a_reStatus != g_kNoError) return; } } // Make the current region represent the union between itself // and the other given region. template template void Region2D::UnionDebug (Status_t &a_reStatus, REGION_O &a_rOther, REGION_TEMP &a_rTemp) { typename REGION::ConstIterator itHere; typename REGION_O::ConstIterator itHereO; typename REGION_TEMP::ConstIterator itHereT; INDEX tnX; // Used to loop through points. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Calculate the union. a_rTemp.Assign (a_reStatus, *this); if (a_reStatus != g_kNoError) return; a_rTemp.Union (a_reStatus, a_rOther); if (a_reStatus != g_kNoError) return; // Loop through every point in the result, make sure it's in // one of the two input regions. for (itHereT = a_rTemp.Begin(); itHereT != a_rTemp.End(); ++itHereT) { const Extent &rHere = *itHereT; for (tnX = rHere.m_tnXStart; tnX < rHere.m_tnXEnd; ++tnX) { if (!a_rOther.DoesContainPoint (rHere.m_tnY, tnX) && !this->DoesContainPoint (rHere.m_tnY, tnX)) goto error; } } // Loop through every point in the first input region, make sure // it's in the result. for (itHere = this->Begin(); itHere != this->End(); ++itHere) { const Extent &rHere = *itHere; for (tnX = rHere.m_tnXStart; tnX < rHere.m_tnXEnd; ++tnX) { if (!a_rTemp.DoesContainPoint (rHere.m_tnY, tnX)) goto error; } } // Loop through every point in the second input region, make sure // it's in the result. for (itHereO = a_rOther.Begin(); itHereO != a_rOther.End(); ++itHereO) { const Extent &rHere = *itHereO; for (tnX = rHere.m_tnXStart; tnX < rHere.m_tnXEnd; ++tnX) { if (!a_rTemp.DoesContainPoint (rHere.m_tnY, tnX)) goto error; } } // The operation succeeded. Commit it. Assign (a_reStatus, a_rTemp); if (a_reStatus != g_kNoError) return; // All done. return; error: // Handle deviations. fprintf (stderr, "Region2D::Union() failed\n"); fprintf (stderr, "First input region:\n"); PrintRegion (*this); fprintf (stderr, "Second input region:\n"); PrintRegion (a_rOther); fprintf (stderr, "Result:\n"); PrintRegion (a_rTemp); assert (false); } // Subtract the other region from the current region, i.e. // remove from the current region any areas that exist in the // other region. template template void Region2D::SubtractDebug (Status_t &a_reStatus, REGION_O &a_rOther, REGION_TEMP &a_rTemp) { typename REGION::ConstIterator itHere; typename REGION_O::ConstIterator itHereO; typename REGION_TEMP::ConstIterator itHereT; INDEX tnX; // Used to loop through points. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Calculate the difference. a_rTemp.Assign (a_reStatus, *this); if (a_reStatus != g_kNoError) return; a_rTemp.Subtract (a_reStatus, a_rOther); if (a_reStatus != g_kNoError) return; // Loop through every point in the result, make sure it's in // the first input region but not the second. for (itHereT = a_rTemp.Begin(); itHereT != a_rTemp.End(); ++itHereT) { const Extent &rHere = *itHereT; for (tnX = rHere.m_tnXStart; tnX < rHere.m_tnXEnd; ++tnX) { if (!(this->DoesContainPoint (rHere.m_tnY, tnX) && !a_rOther.DoesContainPoint (rHere.m_tnY, tnX))) goto error; } } // Loop through every point in the first input region, and if it's // not in the second input region, make sure it's in the result. for (itHere = this->Begin(); itHere != this->End(); ++itHere) { const Extent &rHere = *itHere; for (tnX = rHere.m_tnXStart; tnX < rHere.m_tnXEnd; ++tnX) { if (!a_rOther.DoesContainPoint (rHere.m_tnY, tnX)) { if (!a_rTemp.DoesContainPoint (rHere.m_tnY, tnX)) goto error; } } } // Loop through every point in the second input region, make sure // it's not in the result. for (itHereO = a_rOther.Begin(); itHereO != a_rOther.End(); ++itHereO) { const Extent &rHere = *itHere; for (tnX = rHere.m_tnXStart; tnX < rHere.m_tnXEnd; ++tnX) { if (a_rTemp.DoesContainPoint (rHere.m_tnY, tnX)) goto error; } } // The operation succeeded. Commit it. Assign (a_reStatus, a_rTemp); if (a_reStatus != g_kNoError) return; // All done. return; error: // Handle deviations. fprintf (stderr, "Region2D::Subtract() failed\n"); fprintf (stderr, "First input region:\n"); PrintRegion (*this); fprintf (stderr, "Second input region:\n"); PrintRegion (a_rOther); fprintf (stderr, "Result:\n"); PrintRegion (a_rTemp); assert (false); } // Flood-fill the current region. template template void Region2D::FloodFill (Status_t &a_reStatus, CONTROL &a_rControl, bool a_bVerify, bool a_bExpand) { typename CONTROL::ConstIterator itExtent; // An extent we're examining. Extent oFoundExtent; // An extent we found to be part of the region. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // How we set up depends on whether we're to verify all existing // region extents. if (a_bVerify) { // The to-do-list becomes the current region, and we empty // out the current region too. a_rControl.m_oAlreadyDone.Clear(); if (a_rControl.m_oToDo.CanMove (*this)) { // Grab the extents right out of the current region. a_rControl.m_oToDo.Clear(); a_rControl.m_oToDo.Move (*this); } else { // Copy the extents from the current region, then empty it. a_rControl.m_oToDo.Assign (a_reStatus, *this); if (a_reStatus != g_kNoError) return; Clear(); } } else { // The already-done list starts with the region, i.e. every // extent already known to be in the region can avoid getting // tested. a_rControl.m_oAlreadyDone.Assign (a_reStatus, *this); if (a_reStatus != g_kNoError) return; // Start the to-do list with a border around all the extents in // the region. a_rControl.m_oToDo.MakeBorder (a_reStatus, *this); if (a_reStatus != g_kNoError) return; } // Now pull each extent out of the to-do list. Determine which // sub-extents are part of the region. Add those found extents // to the region. Then add all extent surrounding the found extents // to the to-do-next list. itExtent = a_rControl.m_oToDo.Begin(); while (itExtent != a_rControl.m_oToDo.End()) { bool bStartedExtent; // true if we've started finding an extent. INDEX tnX; // Where we're looking for extents. // Get the extent, converting the type if necessary. Extent oExtent; oExtent.m_tnY = (*itExtent).m_tnY; oExtent.m_tnXStart = (*itExtent).m_tnXStart; oExtent.m_tnXEnd = (*itExtent).m_tnXEnd; // We're about to check this extent. Put it in the // already-checked list now. a_rControl.m_oAlreadyDone.Union (a_reStatus, oExtent.m_tnY, oExtent.m_tnXStart, oExtent.m_tnXEnd); if (a_reStatus != g_kNoError) return; // If this extent shouldn't be considered, skip it. if (!a_rControl.ShouldUseExtent (oExtent)) goto nextExtent; // Make sure our client left us with a valid extent. assert (oExtent.m_tnXStart < oExtent.m_tnXEnd); // Run through the pixels described by this extent, see if // they can be added to the region, and remember where to // search next. oFoundExtent.m_tnY = oExtent.m_tnY; bStartedExtent = false; for (tnX = oExtent.m_tnXStart; tnX <= oExtent.m_tnXEnd; ++tnX) { // Is this point in the region? if (tnX < oExtent.m_tnXEnd && a_rControl.IsPointInRegion (tnX, oExtent.m_tnY)) { // This point is in the region. Start a new extent // if we didn't have one already, and add the point // to it. if (!bStartedExtent) { oFoundExtent.m_tnXStart = tnX; bStartedExtent = true; } oFoundExtent.m_tnXEnd = tnX + 1; } // This point is not in the region. Any extent we're // building is done. else if (bStartedExtent) { // Add this extent to the region. Union (a_reStatus, oFoundExtent.m_tnY, oFoundExtent.m_tnXStart, oFoundExtent.m_tnXEnd); if (a_reStatus != g_kNoError) return; // Now add all surrounding extents to the to-do-next list. if (a_bExpand) { a_rControl.m_oNextToDo.UnionSurroundingExtents (a_reStatus, oFoundExtent.m_tnY, oFoundExtent.m_tnXStart, oFoundExtent.m_tnXEnd); if (a_reStatus != g_kNoError) return; } // Look for another extent. bStartedExtent = false; } } nextExtent: // Move to the next extent. ++itExtent; // If the to-do list needs to be replenished, do so. if (itExtent == a_rControl.m_oToDo.End()) { // Replenish the to-do list. a_rControl.m_oNextToDo.Subtract (a_reStatus, a_rControl.m_oAlreadyDone); if (a_reStatus != g_kNoError) return; a_rControl.m_oToDo.Clear(); a_rControl.m_oToDo.Move (a_rControl.m_oNextToDo); // Start over at the beginning. itExtent = a_rControl.m_oToDo.Begin(); } } } // Make the current region represent the border of the other // region, i.e. every pixel that borders the region but isn't // already in the region. template template void Region2D::MakeBorder (Status_t &a_reStatus, const REGION &a_rOther) { typename REGION::ConstIterator itExtent; // Used to loop through the other region's extents. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Start with an empty region. Clear(); // For every extent in the other region, add every surrounding // extent. That creates a region that looks like the other region, // but also contains the border we're after. for (itExtent = a_rOther.Begin(); itExtent != a_rOther.End(); ++itExtent) { UnionSurroundingExtents (a_reStatus, (*itExtent).m_tnY, (*itExtent).m_tnXStart, (*itExtent).m_tnXEnd); if (a_reStatus != g_kNoError) return; } // Finally, subtract the other region. That punches a hole in us, // and creates the border region we're after. Subtract (a_reStatus, a_rOther); if (a_reStatus != g_kNoError) return; } // Add all extents surrounding the given extent. Used by FloodFill(). template void Region2D::UnionSurroundingExtents (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Add the extent above this one. Union (a_reStatus, a_tnY - 1, a_tnXStart, a_tnXEnd); if (a_reStatus != g_kNoError) return; // Add the extent in the middle. Union (a_reStatus, a_tnY, a_tnXStart - 1, a_tnXEnd + 1); if (a_reStatus != g_kNoError) return; // Add the extent below this one. Union (a_reStatus, a_tnY + 1, a_tnXStart, a_tnXEnd); if (a_reStatus != g_kNoError) return; } // Less-than operator. template inline bool Region2D::Extent::operator < (const Region2D::Extent &a_rOther) const { // Compare on y, then x-start. if (m_tnY < a_rOther.m_tnY) return true; if (m_tnY > a_rOther.m_tnY) return false; if (m_tnXStart < a_rOther.m_tnXStart) return true; // if (m_tnXStart >= a_rOther.m_tnXStart) return false; } // Default constructor. Must be followed by a call to Init(). template template Region2D::FloodFillControl::FloodFillControl() { // Nothing to do. } // Initializing constructor. template template Region2D::FloodFillControl::FloodFillControl (Status_t &a_reStatus) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Initialize ourselves. Init (a_reStatus); if (a_reStatus != g_kNoError) return; } // Initializer. Must be called on default-constructed objects. template template void Region2D::FloodFillControl::Init (Status_t &a_reStatus) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Initialize our helper regions. m_oToDo.Init (a_reStatus); if (a_reStatus != g_kNoError) return; m_oAlreadyDone.Init (a_reStatus); if (a_reStatus != g_kNoError) return; m_oNextToDo.Init (a_reStatus); if (a_reStatus != g_kNoError) return; } #endif // __REGION2D_H__ mjpegtools-2.1.0/y4mdenoise/newdenoise.hh0000644000175000017500000000703611173460062020760 0ustar glowwormglowworm#ifndef __NEWDENOISE_H__ #define __NEWDENOISE_H__ // This file (C) 2004-2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. #ifdef __cplusplus extern "C" { #endif /* _cplusplus */ /* Initialize the new denoiser. a_nFrames is the number of frames over which to calculate pixel values. a_nWidthY/a_nHeightY is the dimension of the intensity portion of the image; if intensity is not to be denoised, then these values must be 0. a_nWidthCbCr/a_nHeightCbCr is the dimension of the color portion of the image; if color is not to be denoised, then these values must be 0. Returns 0 if successful, -1 if there was some problem (usually, running out of memory). */ int newdenoise_init (int a_nFrames, int a_nWidthY, int a_nHeightY, int a_nWidthCbCr, int a_nHeightCbCr, int a_nInputFD, int a_nOutputFD, const y4m_stream_info_t *a_pStreamInfo, y4m_frame_info_t *a_pFrameInfo); /* Shutdown the new denoiser. Returns 0 if successful, -1 if there was some problem. */ int newdenoise_shutdown (void); /* Read another frame. Usable only in multi-threaded situations. */ int newdenoise_read_frame (uint8_t **a_apPlanes); /* Get space to write another frame. Usable only in multi-threaded situations. */ int newdenoise_get_write_frame (uint8_t **a_apPlanes); /* Write another frame. Usable only in multi-threaded situations. */ int newdenoise_write_frame (void); /* Denoise another frame. a_pInputY/a_pInputCb/a_pInputCr point to the incoming undenoised frame. Any components that are not to be denoised, i.e. because their dimension was set to 0x0 by newdenoise_init(), will not be used, and may be any value, e.g. NULL. If a component that is to be denoised is NULL, then that indicates that the end of input has been reached, and the next denoised frame should be returned. Returns 0 if a_pOutputY/a_pOutputCb/a_pOutputCr contains the next denoised frame, 1 if there was no output written, -1 if there was some error (usually, running out of memory). */ int newdenoise_frame (const uint8_t *a_pInputY, const uint8_t *a_pInputCb, const uint8_t *a_pInputCr, uint8_t *a_pOutputY, uint8_t *a_pOutputCb, uint8_t *a_pOutputCr); int newdenoise_interlaced_frame (const uint8_t *a_pInputY, const uint8_t *a_pInputCb, const uint8_t *a_pInputCr, uint8_t *a_pOutputY, uint8_t *a_pOutputCb, uint8_t *a_pOutputCr); /* Denoiser configuration. */ typedef struct DNSR_GLOBAL { int frames; /* # of frames over which to average */ int interlaced; /* 0 == not interlaced, 1 == interlaced */ int bwonly; /* 1 if we're to denoise intensity only */ int radiusY; /* search radius for intensity */ int radiusCbCr; /* search radius for color */ int zThresholdY; /* zero-motion intensity error threshold */ int zThresholdCbCr; /* zero-motion color error threshold */ int thresholdY; /* intensity error threshold */ int thresholdCbCr; /* color error threshold */ int matchCountThrottle; /* match throttle on count */ int matchSizeThrottle; /* match throttle on size */ int threads; /* bit 0=rw only, bit 1=color in parallel */ struct { int w, h; /* width/height of intensity frame */ int Cw, Ch; /* width/height of color frame */ int ss_h, ss_v; /* ratio between intensity/color sizes */ uint8_t *in[3]; /* frame data read from stdin */ uint8_t *out[3]; /* frame data written to stdout */ } frame; } DNSR_GLOBAL; extern DNSR_GLOBAL denoiser; #ifdef __cplusplus }; #endif /* _cplusplus */ #endif // __NEWDENOISE_H__ mjpegtools-2.1.0/y4mdenoise/Makefile.in0000644000175000017500000005237312217306410020344 0ustar glowwormglowworm# Makefile.in generated by automake 1.12.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Makefile for y4mdenoise VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @HAVE_ALTIVEC_TRUE@am__append_1 = $(top_builddir)/mpeg2enc/libmpeg2encpp.la bin_PROGRAMS = y4mdenoise$(EXEEXT) noinst_PROGRAMS = regiontest$(EXEEXT) subdir = y4mdenoise DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am_regiontest_OBJECTS = regiontest.$(OBJEXT) regiontest_OBJECTS = $(am_regiontest_OBJECTS) regiontest_LDADD = $(LDADD) am_y4mdenoise_OBJECTS = main.$(OBJEXT) newdenoise.$(OBJEXT) y4mdenoise_OBJECTS = $(am_y4mdenoise_OBJECTS) y4mdenoise_DEPENDENCIES = $(LIBMJPEGUTILS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(regiontest_SOURCES) $(y4mdenoise_SOURCES) DIST_SOURCES = $(regiontest_SOURCES) $(y4mdenoise_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALTIVEC_EXTRA_LIBS = @ALTIVEC_EXTRA_LIBS@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDV_CFLAGS = @LIBDV_CFLAGS@ LIBDV_LIBS = @LIBDV_LIBS@ LIBGETOPT_LIB = @LIBGETOPT_LIB@ LIBM_LIBS = @LIBM_LIBS@ LIBOBJS = @LIBOBJS@ LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ LIBPNG_LIBS = @LIBPNG_LIBS@ LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@ LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ LT_STATIC = @LT_STATIC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROGRAM_NOPIC = @PROGRAM_NOPIC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ SDLgfx_LIBS = @SDLgfx_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ V4LCONF_LIBS = @V4LCONF_LIBS@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAINTAINERCLEANFILES = Makefile.in EXTRA_DIST = implementation.html AM_CFLAGS = -DNDEBUG -finline-functions @PROGRAM_NOPIC@ AM_CXXFLAGS = -DNDEBUG -finline-functions @PROGRAM_NOPIC@ INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/utils LIBMJPEGUTILS = $(top_builddir)/utils/libmjpegutils.la $(am__append_1) noinst_HEADERS = \ Allocator.hh \ BitmapRegion2D.hh \ DoublyLinkedList.hh \ Limits.hh \ MotionSearcher.hh \ newdenoise.hh \ PlacementAllocator.hh\ ReferenceFrame.hh \ Region2D.hh \ SearchBorder.hh \ SearchWindow.hh \ Set.hh \ SetRegion2D.hh \ SkipList.hh \ Status_t.h \ TemplateLib.hh \ VariableSizeAllocator.hh \ Vector.hh regiontest_SOURCES = regiontest.cc y4mdenoise_SOURCES = main.c newdenoise.cc y4mdenoise_LDADD = $(LIBMJPEGUTILS) all: all-am .SUFFIXES: .SUFFIXES: .c .cc .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu y4mdenoise/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu y4mdenoise/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list regiontest$(EXEEXT): $(regiontest_OBJECTS) $(regiontest_DEPENDENCIES) $(EXTRA_regiontest_DEPENDENCIES) @rm -f regiontest$(EXEEXT) $(CXXLINK) $(regiontest_OBJECTS) $(regiontest_LDADD) $(LIBS) y4mdenoise$(EXEEXT): $(y4mdenoise_OBJECTS) $(y4mdenoise_DEPENDENCIES) $(EXTRA_y4mdenoise_DEPENDENCIES) @rm -f y4mdenoise$(EXEEXT) $(CXXLINK) $(y4mdenoise_OBJECTS) $(y4mdenoise_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/newdenoise.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regiontest.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< .cc.o: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cc.lo: @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool \ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool clean-noinstPROGRAMS cscopelist \ ctags distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mjpegtools-2.1.0/y4mdenoise/DoublyLinkedList.hh0000644000175000017500000000637411173460062022045 0ustar glowwormglowworm#ifndef __DOUBLY_LINKED_LIST_H__ #define __DOUBLY_LINKED_LIST_H__ // This file (C) 2004-2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. // A cheap doubly-linked-list class. Needs to be the base class for // whatever type it's parameterized with, in order to work. template class DoublyLinkedList { public: TYPE *m_pForward; TYPE *m_pBackward; // Forward/backward pointers. DoublyLinkedList(); // Default constructor. ~DoublyLinkedList(); // Destructor. void InsertBefore (TYPE *a_pThis, TYPE *a_pCell); // Insert the given cell before us in the list. void InsertAfter (TYPE *a_pThis, TYPE *a_pCell); // Insert the given cell after us in the list. void Remove (void); // Remove ourselves from the list we're in. }; // Default constructor. template DoublyLinkedList::DoublyLinkedList() { // Not part of any list. m_pForward = m_pBackward = NULL; } // Destructor. template DoublyLinkedList::~DoublyLinkedList() { // Make sure we're not part of a list any more -- otherwise, our // destruction will leave dangling references. assert (m_pForward == NULL); assert (m_pBackward == NULL); } // Insert the given cell before us in the list. template void DoublyLinkedList::InsertBefore (TYPE *a_pThis, TYPE *a_pCell) { // Make sure they passed us a pointer to ourselves, different only // by type. assert (a_pThis == this); // Make sure they gave us a cell to insert. assert (a_pCell != NULL); // Make sure the cell doesn't think it's in a list already. assert (a_pCell->m_pForward == NULL); assert (a_pCell->m_pBackward == NULL); // Pretty straightforward. a_pCell->m_pBackward = m_pBackward; m_pBackward = a_pCell; a_pCell->m_pForward = a_pThis; assert (a_pCell->m_pBackward->m_pForward == a_pThis); a_pCell->m_pBackward->m_pForward = a_pCell; } // Insert the given cell after us in the list. template void DoublyLinkedList::InsertAfter (TYPE *a_pThis, TYPE *a_pCell) { // Make sure they passed us a pointer to ourselves, different only // by type. assert (a_pThis == this); // Make sure they gave us a cell to insert. assert (a_pCell != NULL); // Make sure the cell doesn't think it's in a list already. assert (a_pCell->m_pForward == NULL); assert (a_pCell->m_pBackward == NULL); // Pretty straightforward. a_pCell->m_pForward = m_pForward; m_pForward = a_pCell; a_pCell->m_pBackward = a_pThis; assert (a_pCell->m_pForward->m_pBackward == a_pThis); a_pCell->m_pForward->m_pBackward = a_pCell; } // Remove ourselves from the list we're in. template void DoublyLinkedList::Remove (void) { // Make sure we think we're in a list. assert (m_pForward != NULL); assert (m_pBackward != NULL); // Get the nodes that we'll be pointing to. (We have to do this // as a separate step, in case we're the last item in a circular // list.) TYPE *pForward = m_pForward; TYPE *pBackward = m_pBackward; // Remove ourselves from the doubly-linked list we're in. m_pBackward->m_pForward = pForward; m_pForward->m_pBackward = pBackward; // Remove our stale links. m_pForward = m_pBackward = NULL; } #endif // __DOUBLY_LINKED_LIST_H__ mjpegtools-2.1.0/y4mdenoise/Limits.hh0000644000175000017500000000467711173460062020071 0ustar glowwormglowworm#ifndef __LIMITS_H__ #define __LIMITS_H__ // This file (C) 2004-2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. #include "config.h" #include "mjpeg_types.h" // Numerical limits. // A class that allows numerical limits to be looked up, for each // numerical type. template class Limits { public: static NUM Min; // This type's minimum value. static NUM Max; // This type's maximum value. static int Bits; // The number of bits in this type. static int Log2Bits; // The base-2-logarithm of the number of bits in this type. }; // Some limits. template <> int8_t Limits::Min = int8_t (0x80); template <> int8_t Limits::Max = int8_t (0x7f); template <> int Limits::Bits = 8; template <> int Limits::Log2Bits = 3; template <> uint8_t Limits::Min = uint8_t (0x00); template <> uint8_t Limits::Max = uint8_t (0xff); template <> int Limits::Bits = 8; template <> int Limits::Log2Bits = 3; template <> int16_t Limits::Min = int16_t (0x8000); template <> int16_t Limits::Max = int16_t (0x7fff); template <> int Limits::Bits = 16; template <> int Limits::Log2Bits = 4; template <> uint16_t Limits::Min = uint16_t (0x0000); template <> uint16_t Limits::Max = uint16_t (0xffff); template <> int Limits::Bits = 16; template <> int Limits::Log2Bits = 4; template <> int32_t Limits::Min = int32_t (0x80000000); template <> int32_t Limits::Max = int32_t (0x7fffffff); template <> int Limits::Bits = 32; template <> int Limits::Log2Bits = 5; template <> uint32_t Limits::Min = uint32_t (0x00000000); template <> uint32_t Limits::Max = uint32_t (0xffffffff); template <> int Limits::Bits = 32; template <> int Limits::Log2Bits = 5; template <> int64_t Limits::Min = int64_t (0x8000000000000000LL); template <> int64_t Limits::Max = int64_t (0x7fffffffffffffffLL); template <> int Limits::Bits = 64; template <> int Limits::Log2Bits = 6; template <> uint64_t Limits::Min = uint64_t (0x0000000000000000ULL); template <> uint64_t Limits::Max = uint64_t (0xffffffffffffffffULL); template <> int Limits::Bits = 64; template <> int Limits::Log2Bits = 6; #endif // __LIMITS_H__ mjpegtools-2.1.0/y4mdenoise/SearchBorder.hh0000644000175000017500000017641611257165730021203 0ustar glowwormglowworm#ifndef __SEARCH_BORDER_H__ #define __SEARCH_BORDER_H__ // This file (C) 2004-2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. #include "config.h" #include #include #include "mjpeg_types.h" #include "TemplateLib.hh" #include "Limits.hh" #include "DoublyLinkedList.hh" #include "Allocator.hh" #include "SetRegion2D.hh" #ifdef sun #include #endif // HACK: for development error messages. #include // Define this to print region unions/subtractions. #ifdef DEBUG_REGION2D // #define PRINTREGIONMATH #endif // DEBUG_REGION2D // Define this to print details of the search-border's progress. #ifdef DEBUG_REGION2D // #define PRINT_SEARCHBORDER #endif // DEBUG_REGION2D // Define this to fix startpoint/endpoint-iterator arrays inline. // Don't define this to use set-lower-bound operations to fix them. // I was hoping the inline method was faster, but it doesn't seem to be, // but I want to preserve the code, for reference if nothing else. //#define FIX_ITERATOR_ARRAYS_INLINE // The generic search-border class. It's parameterized by the numeric // type to use for pixel indices and a numeric type big enough to hold // the product of the largest expected frame width/height. // When constructed, it's configured with the size of the frame in which // it operates, and the width/height of pixel groups to operate on. // // The search border keeps track of all regions on the border between // the searched area and the not-yet-searched area. When no new // pixel-group could possibly intersect a region, that region is removed // from the border and handed back to the client. // // The meaning of the regions it keeps track of is abstract. The // original purpose was to help the motion-searcher keep track of moved // regions, i.e. pixels in the new frame that match pixels in the // reference frame, only moved. But it could presumably be used for // other purposes, e.g. if it assembled regions of pixels that had // exactly one frame reference, it could be used to detect bit noise, // film lint/scratches, or even LaserDisc rot. // // As the search-border proceeds through the frame, it maintains a list // of all regions that intersect with the current pixel-group. That // way, when it comes time to add a new match, all regions that // intersect the current pixel-group are already known, and duplicate // matches can be skipped. template class SearchBorder { public: typedef Region2D BaseRegion_t; // The base class for all our region types. #ifdef SET_REGION_IMPLEMENTED_WITH_VECTOR typedef Vector, Less > RegionImp_t; #else // SET_REGION_IMPLEMENTED_WITH_VECTOR typedef SkipList, Less > RegionImp_t; #endif // SET_REGION_IMPLEMENTED_WITH_VECTOR // The container class that implements our set-based region. typedef SetRegion2D Region_t; // How we use SetRegion2D<>. class MovedRegion; // A moved region of pixels that has been detected. // Derived from Region_t; defined below. SearchBorder (typename Region_t::Allocator &a_rAlloc = Region_t::Extents::Imp::sm_oNodeAllocator); // Default constructor. virtual ~SearchBorder(); // Destructor. void Init (Status_t &a_reStatus, PIXELINDEX a_tnWidth, PIXELINDEX a_tnHeight, PIXELINDEX a_tnSearchRadiusX, PIXELINDEX a_tnSearchRadiusY, PIXELINDEX a_tnPGW, PIXELINDEX a_tnPGH, FRAMESIZE a_tnMatchSizeThrottle); // Initializer. Provide the dimensions of the frame, of the search // window, and of pixel-groups. // Also provide the match-size throttle. The search-border will // keep track of regions of this size, but will avoid expensive // processing of them, and will expect its client to deal with all // such regions before moving to the next pixel-group. void StartFrame (Status_t &a_reStatus); // Initialize the search-border, i.e. start in the upper-left // corner. void MoveRight (Status_t &a_reStatus); // Move one pixel to the right, adding and removing regions from // the potentially-intersecting list. void MoveLeft (Status_t &a_reStatus); // Move one pixel to the left, adding and removing regions from // the potentially-intersecting list. void MoveDown (Status_t &a_reStatus); // Move down a line. Find all regions that can no longer // be contiguous with new matches, and hand them back to the // client. Then rotate the border structures, making the // least-recent current border into the last border, etc. FRAMESIZE GetSizeOfLargestActiveRegion (void) const; // Return the size of the largest active-region. // Returns zero if there are no active-regions. bool HasExistingMatch (PIXELINDEX a_tnMotionX, PIXELINDEX a_tnMotionY) const; // Determine if a region with this motion vector already // intersects/borders the current pixel-group (i.e. it doesn't // need to be flood-filled and added again). // If so, return true. // If not, return false. void AddNewRegion (Status_t &a_reStatus, MovedRegion &a_rRegion); // Add the given region, with the given motion-vector. // Causes a_rRegion to be emptied. void RemoveRegion (MovedRegion *a_pRegion); // Removes the given region from the search-border. MovedRegion *ChooseBestActiveRegion (Status_t &a_reStatus, FRAMESIZE &a_rtnSecondBestActiveRegionSize); // Remove the largest active-region from the search-border and // return it. // Backpatch the size of the second-largest active-region. void FinishFrame (Status_t &a_reStatus); // Clean up the search border at the end of a frame, e.g. hand // all remaining regions back to the client. virtual void OnCompletedRegion (Status_t &a_reStatus, MovedRegion *a_pRegion) = 0; // Hand a completed region to our client. Subclasses must // override this to describe how to do this. void DeleteRegion (MovedRegion *a_pRegion); // Delete a region that was returned by ChooseBestActiveRegion() // or OnCompletedRegion(). // A moved region of pixels that has been detected. // All extents are in the coordinate system of the new frame; that // makes it easy to unify/subtract regions without regard to their // motion vector. class MovedRegion : public Region_t { private: typedef Region_t BaseClass; // Keep track of who our base class is. void *operator new (size_t); void operator delete (void *) {} void *operator new[] (size_t); void operator delete[] (void *); // Disallow allocation from system memory. // (This helps enforce the use of DeleteRegion().) public: MovedRegion (typename BaseClass::Allocator &a_rAlloc = BaseClass::Extents::Imp::sm_oNodeAllocator); // Default constructor. Must be followed by Init(). MovedRegion (Status_t &a_reStatus, typename BaseClass::Allocator &a_rAlloc = BaseClass::Extents::Imp::sm_oNodeAllocator); // Initializing constructor. Creates an empty region. MovedRegion (Status_t &a_reStatus, const MovedRegion &a_rOther); // Copy constructor. void Init (Status_t &a_reStatus); // Initializer. Must be called on default-constructed // regions. void Assign (Status_t &a_reStatus, const MovedRegion &a_rOther); // Make the current region a copy of the other region. virtual ~MovedRegion(); // Destructor. inline void Move (MovedRegion &a_rOther); // Move the contents of the other region into the current // region. // The current region must be empty. inline void SetMotionVector (PIXELINDEX a_tnX, PIXELINDEX a_tnY); // Set the motion vector. inline void GetMotionVector (PIXELINDEX &a_rtnX, PIXELINDEX &a_rtnY) const; // Get the motion vector. // Comparison class, suitable for Set<>. class SortBySizeThenMotionVectorLength { public: inline bool operator() (const MovedRegion *a_pLeft, const MovedRegion *a_pRight) const; }; // Comparison class, suitable for Set<>. class SortBySizeThenMotionVectorLengthThenRegionAddress { public: inline bool operator() (const MovedRegion *a_pLeft, const MovedRegion *a_pRight) const; }; inline FRAMESIZE GetSquaredMotionVectorLength (void) const; // Get the squared length of the motion vector. // Needed by SortBySizeThenMotionVectorLength(). FRAMESIZE m_tnReferences; // The number of beginnings/endings of extents of this // region that are on the border. When this goes to zero, // that means no other matches could possibly be added to // the region, and m_pRegion will get handed back to the // search-border's client. FRAMESIZE m_tnBorderExtents; // The number of region extents that intersect/border the // current pixel-group. private: PIXELINDEX m_tnMotionX, m_tnMotionY; // The motion vector associated with this region. FRAMESIZE m_tnSquaredLength; // The squared length of the motion vector. // Used for sorting. #ifndef NDEBUG public: PIXELINDEX m_tnX, m_tnY; // The location of the pixel-group-match that originally // created this region. // The number of region objects in existence. private: static uint32_t sm_ulInstances; public: static uint32_t GetInstances (void) { return sm_ulInstances; } #endif // NDEBUG }; private: typename Region_t::Allocator &m_rSetRegionExtentAllocator; // Where we get memory to allocate set-region extents. PIXELINDEX m_tnWidth, m_tnHeight; // The dimension of each reference frame. PIXELINDEX m_tnSearchRadiusX, m_tnSearchRadiusY; // The search radius, i.e. how far from the current pixel // group we look when searching for possible moved instances of // the group. PIXELINDEX m_tnPGW, m_tnPGH; // The dimension of pixel groups. PIXELINDEX m_tnX, m_tnY; // The index of the current pixel group. Actually the index // of the top-left pixel in the current pixel group. This // gets moved in a zigzag pattern, back and forth across the // frame and then down, until the end of the frame is reached. PIXELINDEX m_tnStepX; // Whether we're zigging or zagging. FRAMESIZE m_tnMatchSizeThrottle; // The size (measured in number of pixels) that the largest // region in the area of the current pixel-group can be before // we avoid expensive processing of its extents. // A structure that keeps track of which active-region (if any) exists // for a given motion-vector. struct MotionVectorMatch { public: FRAMESIZE m_tnActiveExtents; // The number of active-region extents that intersect/border // the current pixel-group. MotionVectorMatch() : m_tnActiveExtents (0) {} // Default constructor. }; MotionVectorMatch *m_pMotionVectorMatches; // An array of ((2 * m_tnSearchRadiusX + 1) // * (2 * m_tnSearchRadiusY + 1) cells that keep track of which // active-region, if any, exists for a given motion-vector. MotionVectorMatch &GetMotionVectorMatch (PIXELINDEX a_tnMotionX, PIXELINDEX a_tnMotionY) const; // Get the motion-vector-match cell for this motion-vector. void AddMotionVectorMatch (MovedRegion *a_pRegion); // Add the given region to the motion-vector-match array. void RemoveMotionVectorMatch (MovedRegion *a_pRegion); // Remove the given region from the motion-vector-match array. // A class that keeps track of region extents on the border between // the searched area and the not-yet-searched area, i.e. the only // regions that have a chance of growing. class BorderExtentBoundary { public: PIXELINDEX m_tnCounterpartIndex; // The pixel-index of the ending to go with this beginning, or // of the beginning to go with this ending. MovedRegion *m_pRegion; // The region with the given extent. BorderExtentBoundary(); // Default constructor. BorderExtentBoundary (MovedRegion *a_pRegion); // Initializing constructor. ~BorderExtentBoundary(); // Destructor. #ifndef NDEBUG bool operator == (const BorderExtentBoundary &a_rOther) const; #endif // !NDEBUG // Equality operator. bool operator < (const BorderExtentBoundary &a_rOther) const { return m_pRegion < a_rOther.m_pRegion; } // Less-than operator. }; #ifdef BORDEREXTENTBOUNDARYSET_IMPLEMENTED_WITH_VECTOR typedef Set, Vector, Less > > BorderExtentBoundarySet; #else // BORDEREXTENTBOUNDARYSET_IMPLEMENTED_WITH_VECTOR typedef Set, SkipList, Less > > BorderExtentBoundarySet; #endif // BORDEREXTENTBOUNDARYSET_IMPLEMENTED_WITH_VECTOR typedef typename BorderExtentBoundarySet::Allocator BEBS_Allocator_t; BEBS_Allocator_t m_oBorderExtentsAllocator; BorderExtentBoundarySet *m_psetBorderStartpoints, *m_psetBorderEndpoints; // The borders, i.e. the startpoint/endpoints for every // region under construction, for every line in the current // pixel-group's vertical extent. typedef Set MovedRegionSet; typedef typename MovedRegionSet::Allocator MovedRegionSetAllocator_t; MovedRegionSetAllocator_t m_oMovedRegionSetAllocator; MovedRegionSet m_setRegions; // All moving areas detected so far. // Sorted by decreasing size, then increasing motion vector // length, i.e. the order in which they should be applied to // the reference-frame version of the new frame. typedef Allocator<1> MovedRegionAllocator_t; MovedRegionAllocator_t m_oMovedRegionAllocator; // Where we get memory to allocate MovedRegion instances. #ifndef NDEBUG public: static uint32_t GetMovedRegionCount (void) { return MovedRegion::GetInstances(); } #endif // !NDEBUG }; // Default constructor. template SearchBorder::SearchBorder (typename Region_t::Allocator &a_rAlloc) : m_rSetRegionExtentAllocator (a_rAlloc), m_oBorderExtentsAllocator (1048576), m_oMovedRegionSetAllocator (262144), m_setRegions (typename MovedRegion ::SortBySizeThenMotionVectorLengthThenRegionAddress(), m_oMovedRegionSetAllocator), m_oMovedRegionAllocator (262144) { // No frame dimensions yet. m_tnWidth = m_tnHeight = PIXELINDEX (0); // No search radius yet. m_tnSearchRadiusX = m_tnSearchRadiusY = PIXELINDEX (0); // No pixel-group width/height yet. m_tnPGW = m_tnPGH = PIXELINDEX (0); // No active search yet. m_tnX = m_tnY = m_tnStepX = PIXELINDEX (0); // No motion-vector matches yet. m_pMotionVectorMatches = NULL; // No border-startpoint/endpoint sets yet. m_psetBorderStartpoints = m_psetBorderEndpoints = NULL; } // Destructor. template SearchBorder::~SearchBorder() { // Make sure our client didn't stop in the middle of a frame. FRAMESIZE tnPixels = FRAMESIZE (m_tnWidth) * FRAMESIZE (m_tnHeight); #ifndef NDEBUG if (m_psetBorderStartpoints != NULL) { for (FRAMESIZE tnI = 0; tnI < tnPixels; ++tnI) assert (m_psetBorderStartpoints[tnI].Size() == 0); } if (m_psetBorderEndpoints != NULL) { for (FRAMESIZE tnI = 0; tnI < tnPixels; ++tnI) assert (m_psetBorderEndpoints[tnI].Size() == 0); } #endif // !NDEBUG assert (m_setRegions.Size() == 0); // Free up our motion-vector matches. delete[] m_pMotionVectorMatches; // Free up our arrays of border-startpoint/endpoint sets. if (m_psetBorderStartpoints != NULL) { for (FRAMESIZE tnI = 0; tnI < tnPixels; ++tnI) m_psetBorderStartpoints[tnI].~BorderExtentBoundarySet(); free (m_psetBorderStartpoints); } if (m_psetBorderEndpoints != NULL) { for (FRAMESIZE tnI = 0; tnI < tnPixels; ++tnI) m_psetBorderEndpoints[tnI].~BorderExtentBoundarySet(); free (m_psetBorderEndpoints); } } // Initializer. template void SearchBorder::Init (Status_t &a_reStatus, PIXELINDEX a_tnWidth, PIXELINDEX a_tnHeight, PIXELINDEX a_tnSearchRadiusX, PIXELINDEX a_tnSearchRadiusY, PIXELINDEX a_tnPGW, PIXELINDEX a_tnPGH, FRAMESIZE a_tnMatchSizeThrottle) { FRAMESIZE tnMotionVectorMatches; // The number of motion-vector-match cells to allocate. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure the width & height are reasonable. assert (a_tnWidth > PIXELINDEX (0)); assert (a_tnHeight > PIXELINDEX (0)); // Calculate the total number of pixels. FRAMESIZE tnPixels = FRAMESIZE (a_tnWidth) * FRAMESIZE (a_tnHeight); // Initialize the border-extent-boundary allocator. #ifdef BORDEREXTENTBOUNDARYSET_IMPLEMENTED_WITH_VECTOR m_oBorderExtentsAllocator.Init (a_reStatus); if (a_reStatus != g_kNoError) goto cleanup0; #endif // BORDEREXTENTBOUNDARYSET_IMPLEMENTED_WITH_VECTOR // Allocate space for the sets that implement our border-regions. // Since the initializing constructor needs to be called for each // contained item, we can't use array-new. m_psetBorderStartpoints = (BorderExtentBoundarySet *) malloc (sizeof (BorderExtentBoundarySet) * tnPixels); if (m_psetBorderStartpoints == NULL) goto cleanup0; for (FRAMESIZE tnI = 0; tnI < tnPixels; ++tnI) new ((void *)(m_psetBorderStartpoints + tnI)) BorderExtentBoundarySet (Less(), m_oBorderExtentsAllocator); m_psetBorderEndpoints = (BorderExtentBoundarySet *) malloc (sizeof (BorderExtentBoundarySet) * tnPixels); if (m_psetBorderEndpoints == NULL) goto cleanup1; for (FRAMESIZE tnI = 0; tnI < tnPixels; ++tnI) new ((void *)(m_psetBorderEndpoints + tnI)) BorderExtentBoundarySet (Less(), m_oBorderExtentsAllocator); // Initialize the sets that implement our border-regions. { #ifdef BORDEREXTENTBOUNDARYSET_IMPLEMENTED_WITH_VECTOR typename BorderExtentBoundarySet::InitParams oBorderSetInitParams (16, 16); #else // BORDEREXTENTBOUNDARYSET_IMPLEMENTED_WITH_VECTOR typename BorderExtentBoundarySet::InitParams oBorderSetInitParams /* defaults are fine */; #endif // BORDEREXTENTBOUNDARYSET_IMPLEMENTED_WITH_VECTOR for (FRAMESIZE tnI = 0; tnI < tnPixels; ++tnI) { m_psetBorderStartpoints[tnI].Init (a_reStatus, false, oBorderSetInitParams); if (a_reStatus != g_kNoError) goto cleanup2; m_psetBorderEndpoints[tnI].Init (a_reStatus, false, oBorderSetInitParams); if (a_reStatus != g_kNoError) goto cleanup2; } } m_setRegions.Init (a_reStatus, false); if (a_reStatus != g_kNoError) goto cleanup2; // Allocate space for motion-vector matches. tnMotionVectorMatches = (FRAMESIZE (2) * FRAMESIZE (a_tnSearchRadiusX) + FRAMESIZE (1)) * (FRAMESIZE (2) * FRAMESIZE (a_tnSearchRadiusY) + FRAMESIZE (1)); m_pMotionVectorMatches = new MotionVectorMatch[tnMotionVectorMatches]; if (m_pMotionVectorMatches == NULL) goto cleanup2; // Finally, store our parameters. m_tnWidth = a_tnWidth; m_tnHeight = a_tnHeight; m_tnSearchRadiusX = a_tnSearchRadiusX; m_tnSearchRadiusY = a_tnSearchRadiusY; m_tnPGW = a_tnPGW; m_tnPGH = a_tnPGH; m_tnMatchSizeThrottle = a_tnMatchSizeThrottle; // All done. return; // Clean up after errors. //cleanup3: // delete[] m_pMotionVectorMatches; cleanup2: for (FRAMESIZE tnI = 0; tnI < tnPixels; ++tnI) m_psetBorderEndpoints[tnI].~BorderExtentBoundarySet(); free (m_psetBorderEndpoints); m_psetBorderEndpoints = NULL; cleanup1: for (FRAMESIZE tnI = 0; tnI < tnPixels; ++tnI) m_psetBorderStartpoints[tnI].~BorderExtentBoundarySet(); free (m_psetBorderStartpoints); m_psetBorderStartpoints = NULL; cleanup0: ; } // Default constructor. Must be followed by Init(). template SearchBorder::MovedRegion::MovedRegion (typename BaseClass::Allocator &a_rAlloc) : BaseClass (a_rAlloc) { // One more instance. #ifndef NDEBUG ++sm_ulInstances; #endif // !NDEBUG // No motion-vector yet. m_tnMotionX = m_tnMotionY = PIXELINDEX (0); m_tnSquaredLength = FRAMESIZE (0); // No pixel-group-location yet. #ifndef NDEBUG m_tnX = m_tnY = PIXELINDEX (0); #endif // !NDEBUG // No references yet. m_tnReferences = 0; m_tnBorderExtents = 0; } // Initializing constructor. Creates an empty region. template SearchBorder::MovedRegion::MovedRegion (Status_t &a_reStatus, typename BaseClass::Allocator &a_rAlloc) : BaseClass (a_rAlloc) { // One more instance. #ifndef NDEBUG ++sm_ulInstances; #endif // !NDEBUG // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // No motion-vector yet. m_tnMotionX = m_tnMotionY = PIXELINDEX (0); m_tnSquaredLength = FRAMESIZE (0); // No pixel-group-location yet. #ifndef NDEBUG m_tnX = m_tnY = PIXELINDEX (0); #endif // !NDEBUG // No references yet. m_tnReferences = 0; m_tnBorderExtents = 0; // Initialize ourselves. Init (a_reStatus); if (a_reStatus != g_kNoError) return; } // Copy constructor. template SearchBorder::MovedRegion::MovedRegion (Status_t &a_reStatus, const MovedRegion &a_rOther) : BaseClass (a_reStatus, a_rOther) { // One more instance. #ifndef NDEBUG ++sm_ulInstances; #endif // !NDEBUG // No motion-vector yet. m_tnMotionX = m_tnMotionY = PIXELINDEX (0); m_tnSquaredLength = FRAMESIZE (0); // No pixel-group-location yet. #ifndef NDEBUG m_tnX = m_tnY = PIXELINDEX (0); #endif // !NDEBUG // No references yet. m_tnReferences = 0; m_tnBorderExtents = 0; // If copying our base class failed, leave. if (a_reStatus != g_kNoError) return; // Copy the motion vector. m_tnMotionX = a_rOther.m_tnMotionX; m_tnMotionY = a_rOther.m_tnMotionY; m_tnSquaredLength = a_rOther.m_tnSquaredLength; // Copy the pixel-group-location. #ifndef NDEBUG m_tnX = a_rOther.m_tnX; m_tnY = a_rOther.m_tnY; #endif // !NDEBUG } // Initializer. Must be called on default-constructed regions. template void SearchBorder::MovedRegion::Init (Status_t &a_reStatus) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Initialize the base-class. BaseClass::Init (a_reStatus); if (a_reStatus != g_kNoError) return; } // Make the current region a copy of the other region. template void SearchBorder::MovedRegion::Assign (Status_t &a_reStatus, const MovedRegion &a_rOther) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Assign the base class. BaseClass::Assign (a_reStatus, a_rOther); if (a_reStatus != g_kNoError) return; // Copy the motion vector. m_tnMotionX = a_rOther.m_tnMotionX; m_tnMotionY = a_rOther.m_tnMotionY; m_tnSquaredLength = a_rOther.m_tnSquaredLength; // Copy the pixel-group-location. #ifndef NDEBUG m_tnX = a_rOther.m_tnX; m_tnY = a_rOther.m_tnY; #endif // !NDEBUG } // Move the contents of the other region into the current region. // The current region must be empty. template void SearchBorder::MovedRegion::Move (MovedRegion &a_rOther) { // Make sure neither region is already in the search-border, i.e. // that neither has any references. assert (m_tnReferences == 0); assert (m_tnBorderExtents == 0); assert (a_rOther.m_tnReferences == 0); assert (a_rOther.m_tnBorderExtents == 0); // Move the base class. BaseClass::Move (a_rOther); // Copy the motion vector. m_tnMotionX = a_rOther.m_tnMotionX; m_tnMotionY = a_rOther.m_tnMotionY; m_tnSquaredLength = a_rOther.m_tnSquaredLength; // Copy the pixel-group-location. #ifndef NDEBUG m_tnX = a_rOther.m_tnX; m_tnY = a_rOther.m_tnY; #endif // !NDEBUG } // Destructor. template SearchBorder::MovedRegion::~MovedRegion() { // Make sure there are no references left. assert (m_tnReferences == 0); assert (m_tnBorderExtents == 0); // One less instance. #ifndef NDEBUG --sm_ulInstances; #endif // !NDEBUG // Nothing additional to do. } // Set the motion vector. template inline void SearchBorder::MovedRegion::SetMotionVector (PIXELINDEX a_tnX, PIXELINDEX a_tnY) { // Set the motion vector. m_tnMotionX = a_tnX; m_tnMotionY = a_tnY; // Calculate the square of the vector's length. (It's used for // sorting, and we don't want to recalculate it on every comparison.) m_tnSquaredLength = FRAMESIZE (m_tnMotionX) * FRAMESIZE (m_tnMotionX) + FRAMESIZE (m_tnMotionY) * FRAMESIZE (m_tnMotionY); } // Get the motion vector. template inline void SearchBorder::MovedRegion::GetMotionVector (PIXELINDEX &a_rtnX, PIXELINDEX &a_rtnY) const { // Easy enough. a_rtnX = m_tnMotionX; a_rtnY = m_tnMotionY; } // Comparison operator. template inline bool SearchBorder::MovedRegion ::SortBySizeThenMotionVectorLength::operator() (const MovedRegion *a_pLeft, const MovedRegion *a_pRight) const { FRAMESIZE nLeftPoints, nRightPoints; // The number of points in each region. FRAMESIZE tnLeftLen, tnRightLen; // The (squared) length of each motion vector. // Make sure they gave us some regions to compare. assert (a_pLeft != NULL); assert (a_pRight != NULL); // First, compare by the number of points in each region. // Sort bigger regions first. nLeftPoints = a_pLeft->NumberOfPoints(); nRightPoints = a_pRight->NumberOfPoints(); if (nLeftPoints > nRightPoints) return true; if (nLeftPoints < nRightPoints) return false; // Then compare on motion vector length. // Sort smaller vectors first. tnLeftLen = a_pLeft->GetSquaredMotionVectorLength(); tnRightLen = a_pRight->GetSquaredMotionVectorLength(); if (tnLeftLen < tnRightLen) return true; // if (tnLeftLen >= tnRightLen) return false; } // Comparison operator. template inline bool SearchBorder::MovedRegion ::SortBySizeThenMotionVectorLengthThenRegionAddress::operator() (const MovedRegion *a_pLeft, const MovedRegion *a_pRight) const { FRAMESIZE nLeftPoints, nRightPoints; // The number of points in each region. FRAMESIZE tnLeftLen, tnRightLen; // The (squared) length of each motion vector. // Make sure they gave us some regions to compare. assert (a_pLeft != NULL); assert (a_pRight != NULL); // First, compare by the number of points in each region. // Sort bigger regions first. nLeftPoints = a_pLeft->NumberOfPoints(); nRightPoints = a_pRight->NumberOfPoints(); if (nLeftPoints > nRightPoints) return true; if (nLeftPoints < nRightPoints) return false; // Then compare on motion vector length. // Sort smaller vectors first. tnLeftLen = a_pLeft->GetSquaredMotionVectorLength(); tnRightLen = a_pRight->GetSquaredMotionVectorLength(); if (tnLeftLen < tnRightLen) return true; if (tnLeftLen > tnRightLen) return false; // Finally, disambiguate by region address. if (a_pLeft < a_pRight) return true; //if (a_pLeft >= a_pRight) return false; } // Get the squared length of the motion vector. template inline FRAMESIZE SearchBorder::MovedRegion ::GetSquaredMotionVectorLength (void) const { // Easy enough. return m_tnSquaredLength; } #ifndef NDEBUG // The number of region objects in existence. template uint32_t SearchBorder::MovedRegion::sm_ulInstances; #endif // !NDEBUG // Default constructor. template SearchBorder::BorderExtentBoundary ::BorderExtentBoundary() { // Fill in the blanks. m_tnCounterpartIndex = PIXELINDEX (0); m_pRegion = NULL; } // Initializing constructor. template SearchBorder::BorderExtentBoundary ::BorderExtentBoundary (MovedRegion *a_pRegion) { // Make sure they gave us a region. assert (a_pRegion != NULL); // Fill in the blanks. m_tnCounterpartIndex = PIXELINDEX (0); m_pRegion = a_pRegion; } // Destructor. template SearchBorder::BorderExtentBoundary ::~BorderExtentBoundary() { // Nothing to do. } #ifndef NDEBUG // Equality operator. template bool SearchBorder::BorderExtentBoundary ::operator == (const BorderExtentBoundary &a_rOther) const { // Compare ourselves, field by field. return (m_tnCounterpartIndex == a_rOther.m_tnCounterpartIndex && m_pRegion == a_rOther.m_pRegion); } #endif // !NDEBUG // Initialize the search-border, i.e. start in the upper-left corner. template void SearchBorder::StartFrame (Status_t &a_reStatus) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure the borders are empty. #ifndef NDEBUG FRAMESIZE tnPixels = FRAMESIZE (m_tnWidth) * FRAMESIZE (m_tnHeight); assert (m_psetBorderStartpoints != NULL); for (FRAMESIZE tnI = 0; tnI < tnPixels; ++tnI) assert (m_psetBorderStartpoints[tnI].Size() == 0); assert (m_psetBorderEndpoints != NULL); for (FRAMESIZE tnI = 0; tnI < tnPixels; ++tnI) assert (m_psetBorderEndpoints[tnI].Size() == 0); #endif // !NDEBUG assert (m_setRegions.Size() == 0); // Make sure there are no leftover moved-regions from last time. assert (m_oMovedRegionAllocator.GetNumAllocated() == 0); assert (m_rSetRegionExtentAllocator.GetNumAllocated() == 0); // Make sure there are no active-extents for any motion-vectors. #ifndef NDEBUG { FRAMESIZE tnMotionVectorMatches = (FRAMESIZE (2) * FRAMESIZE (m_tnSearchRadiusX) + FRAMESIZE (1)) * (FRAMESIZE (2) * FRAMESIZE (m_tnSearchRadiusY) * + FRAMESIZE (1)); for (FRAMESIZE i = 0; i < tnMotionVectorMatches; ++i) assert (m_pMotionVectorMatches[i].m_tnActiveExtents == 0); } #endif // !NDEBUG // Start in the upper-left corner, and prepare to move to the right. m_tnX = m_tnY = PIXELINDEX (0); m_tnStepX = PIXELINDEX (1); } // Get the motion-vector-match cell for this motion-vector. template typename SearchBorder::MotionVectorMatch & SearchBorder::GetMotionVectorMatch (PIXELINDEX a_tnMotionX, PIXELINDEX a_tnMotionY) const { // Make sure the motion-vector is in range. assert (a_tnMotionX >= -m_tnSearchRadiusX && a_tnMotionX <= m_tnSearchRadiusX); assert (a_tnMotionY >= -m_tnSearchRadiusY && a_tnMotionY <= m_tnSearchRadiusY); // Find the corresponding motion-vector-match cell. FRAMESIZE tnMajorAxis = FRAMESIZE (2) * FRAMESIZE (m_tnSearchRadiusX) + FRAMESIZE (1); FRAMESIZE tnXOffset = FRAMESIZE (a_tnMotionX) + FRAMESIZE (m_tnSearchRadiusX); FRAMESIZE tnYOffset = FRAMESIZE (a_tnMotionY) + FRAMESIZE (m_tnSearchRadiusY); FRAMESIZE tnIndex = tnXOffset + tnMajorAxis * tnYOffset; // Return it to our caller. return m_pMotionVectorMatches[tnIndex]; } // Add the given region to the motion-vector-match array. template void SearchBorder::AddMotionVectorMatch (MovedRegion *a_pRegion) { // Make sure they gave us a region. assert (a_pRegion != NULL); // Get the region's motion vector. PIXELINDEX tnMotionX, tnMotionY; a_pRegion->GetMotionVector (tnMotionX, tnMotionY); // Find the corresponding motion-vector-match cell. MotionVectorMatch &rMatch = GetMotionVectorMatch (tnMotionX, tnMotionY); // That's one more active extent. ++rMatch.m_tnActiveExtents; ++a_pRegion->m_tnBorderExtents; } // Remove the given region from the motion-vector-match array. template void SearchBorder::RemoveMotionVectorMatch (MovedRegion *a_pRegion) { // Make sure they gave us a region. assert (a_pRegion != NULL); // Get the region's motion vector. PIXELINDEX tnMotionX, tnMotionY; a_pRegion->GetMotionVector (tnMotionX, tnMotionY); // Find the corresponding motion-vector-match cell. MotionVectorMatch &rMatch = GetMotionVectorMatch (tnMotionX, tnMotionY); // That's one less active extent. assert (rMatch.m_tnActiveExtents > 0); --rMatch.m_tnActiveExtents; assert (a_pRegion->m_tnBorderExtents > 0); --a_pRegion->m_tnBorderExtents; } // Move one pixel to the right, adding and removing regions from // the potentially-intersecting list. template void SearchBorder::MoveRight (Status_t &a_reStatus) { PIXELINDEX tnI; // Used to loop through iterators. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure we knew we were moving right. assert (m_tnStepX == 1); // Make sure our client didn't leave behind any regions whose size // exceeds the match-size-throttle. #ifndef NDEBUG { typename MovedRegionSet::ConstIterator itMatchThrottle = m_setRegions.Begin(); assert (itMatchThrottle == m_setRegions.End() || (*itMatchThrottle)->NumberOfPoints() < m_tnMatchSizeThrottle); } #endif // !NDEBUG // All active regions with a current-border endpoint at old X, and // all active regions with a first/last-border endpoint at old X + 1, // are no longer active. for (tnI = ((m_tnY > 0) ? 0 : 1); tnI <= m_tnPGH + 1; ++tnI) { // Determine if we're on the first/last-border. // We'll need to adjust a few things by 1 if so. PIXELINDEX tnIfFirstLast = (tnI == 0 || tnI == m_tnPGH + PIXELINDEX (1)) ? 1 : 0; // Make sure there could be endpoints here. // (The endpoint-X is adjusted downward by 1, because the valid // range of endpoint-X values is from 1 to m_tnWidth.) PIXELINDEX tnY = m_tnY + tnI - PIXELINDEX (1); PIXELINDEX tnX = m_tnX + tnIfFirstLast - PIXELINDEX (1); assert (tnY >= 0); if (/* tnY >= 0 && */ tnY < m_tnHeight && tnX >= 0 && tnX < m_tnWidth) { // Get the set of endpoints of interest. const BorderExtentBoundarySet &rEndpointSet = m_psetBorderEndpoints[tnY * m_tnWidth + tnX]; // Remove all active regions that have endpoints at this index. typename BorderExtentBoundarySet::ConstIterator itEndpoint; for (itEndpoint = rEndpointSet.Begin(); itEndpoint != rEndpointSet.End(); ++itEndpoint) { RemoveMotionVectorMatch ((*itEndpoint).m_pRegion); } } } // All active regions with a current-border startpoint at // new X + m_tnPGW, and all active regions with a first/last-border // startpoint at new X + m_tnPGW - 1, are now active. for (tnI = ((m_tnY > 0) ? 0 : 1); tnI <= m_tnPGH + 1; ++tnI) { // Determine if we're on the first/last-border. // We'll need to adjust a few things by 1 if not. PIXELINDEX tnIfNotFirstLast = (tnI == 0 || tnI == m_tnPGH + PIXELINDEX (1)) ? 0 : 1; // Make sure there could be startpoints here. PIXELINDEX tnY = m_tnY + tnI - PIXELINDEX (1); PIXELINDEX tnX = m_tnX + m_tnPGW + tnIfNotFirstLast; assert (tnY >= 0 && tnX >= 0); if (/* tnY >= 0 && */ tnY < m_tnHeight /* && tnX >= 0 */ && tnX < m_tnWidth) { // Get the set of startpoints of interest. const BorderExtentBoundarySet &rStartpointSet = m_psetBorderStartpoints[tnY * m_tnWidth + tnX]; // Add all active regions that have startpoints at this index. typename BorderExtentBoundarySet::ConstIterator itStartpoint; for (itStartpoint = rStartpointSet.Begin(); itStartpoint != rStartpointSet.End(); ++itStartpoint) { AddMotionVectorMatch ((*itStartpoint).m_pRegion); } } } // Finally, move one step to the right. ++m_tnX; } // Move one pixel to the left, adding and removing regions from // the potentially-intersecting list. template void SearchBorder::MoveLeft (Status_t &a_reStatus) { int tnI; // Used to loop through iterators. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure we knew we were moving left. assert (m_tnStepX == -1); // Make sure our client didn't leave behind any regions whose size // exceeds the match-size-throttle. #ifndef NDEBUG { typename MovedRegionSet::ConstIterator itMatchThrottle = m_setRegions.Begin(); assert (itMatchThrottle == m_setRegions.End() || (*itMatchThrottle)->NumberOfPoints() < m_tnMatchSizeThrottle); } #endif // !NDEBUG // All active regions with a current-border startpoint at // old X + m_tnPGW, and all active regions with a last-border // startpoint at old X + m_tnPGW - 1, are no longer active. for (tnI = ((m_tnY > 0) ? 0 : 1); tnI <= m_tnPGH + 1; ++tnI) { // Determine if we're on the first/last-border. // We'll need to adjust a few things by 1 if so. PIXELINDEX tnIfFirstLast = (tnI == 0 || tnI == m_tnPGH + PIXELINDEX (1)) ? 1 : 0; // Make sure there could be startpoints here. PIXELINDEX tnY = m_tnY + tnI - PIXELINDEX (1); PIXELINDEX tnX = m_tnX + m_tnPGW - tnIfFirstLast; assert (tnY >= 0 && tnX >= 0); if (/* tnY >= 0 && */ tnY < m_tnHeight /* && tnX >= 0 */ && tnX < m_tnWidth) { // Get the set of startpoints of interest. const BorderExtentBoundarySet &rStartpointSet = m_psetBorderStartpoints[tnY * m_tnWidth + tnX]; // Remove all active regions that have startpoints at this // index. typename BorderExtentBoundarySet::ConstIterator itStartpoint; for (itStartpoint = rStartpointSet.Begin(); itStartpoint != rStartpointSet.End(); ++itStartpoint) { RemoveMotionVectorMatch ((*itStartpoint).m_pRegion); } } } // All active regions with a current-border endpoint at new X, and // all active regions with a last-border endpoint at new X + 1, are // now active. for (tnI = ((m_tnY > 0) ? 0 : 1); tnI <= m_tnPGH + 1; ++tnI) { // Determine if we're on the first/last-border. // We'll need to adjust a few things by 1 if not. PIXELINDEX tnIfNotFirstLast = (tnI == 0 || tnI == m_tnPGH + PIXELINDEX (1)) ? 0 : 1; // Make sure there could be endpoints here. // (The endpoint-X is adjusted downward by 1, because the valid // range of endpoint-X values is from 1 to m_tnWidth.) PIXELINDEX tnY = m_tnY + tnI - PIXELINDEX (1); PIXELINDEX tnX = m_tnX - tnIfNotFirstLast - PIXELINDEX (1); assert (tnY >= 0); if (/* tnY >= 0 && */ tnY < m_tnHeight && tnX >= 0 && tnX < m_tnWidth) { // Get the set of endpoints of interest. const BorderExtentBoundarySet &rEndpointSet = m_psetBorderEndpoints[tnY * m_tnWidth + tnX]; // Add all active regions that have endpoints at this index. typename BorderExtentBoundarySet::ConstIterator itEndpoint; for (itEndpoint = rEndpointSet.Begin(); itEndpoint != rEndpointSet.End(); ++itEndpoint) { AddMotionVectorMatch ((*itEndpoint).m_pRegion); } } } // Finally, move one step to the left. --m_tnX; } // Move down a line, finding all regions that can no longer be // contiguous with new matches, and handing them back to the client. template void SearchBorder::MoveDown (Status_t &a_reStatus) { FRAMESIZE tnI; typename BorderExtentBoundarySet::Iterator itBorder; // Used to run through the last-border. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make sure our client didn't leave behind any regions whose size // exceeds the match-size-throttle. #ifndef NDEBUG { typename MovedRegionSet::ConstIterator itMatchThrottle = m_setRegions.Begin(); assert (itMatchThrottle == m_setRegions.End() || (*itMatchThrottle)->NumberOfPoints() < m_tnMatchSizeThrottle); } #endif // !NDEBUG // Run through the last border, disconnect the regions from all // endpoints. If that leaves a region with no references and no // siblings, then the region is fully constructed, and it gets // handed back to the client. if (m_tnY > 0) { // Run through the startpoints and endpoints separately. That // leaves some dangling references temporarily, but this avoids // having to do a set-find for the endpoints. for (tnI = 0; tnI < m_tnWidth; ++tnI) { BorderExtentBoundarySet &rStartpointSet = m_psetBorderStartpoints[(m_tnY - PIXELINDEX (1)) * m_tnWidth + tnI]; for (itBorder = rStartpointSet.Begin(); itBorder != rStartpointSet.End(); ++itBorder) { // Get the startpoint, and its under-construction region. const BorderExtentBoundary &rStartpoint = *itBorder; MovedRegion *pRegion = rStartpoint.m_pRegion; // If this extent intersects/borders the current // pixel-group, then a reference to it must be removed // from the motion-vector matches. PIXELINDEX tnXStart = tnI; PIXELINDEX tnXEnd = rStartpoint.m_tnCounterpartIndex; PIXELINDEX tnIfFirstLast = (m_tnY <= m_tnHeight - m_tnPGH) ? 1 : 0; if (tnXEnd >= m_tnX + tnIfFirstLast && tnXStart < m_tnX + m_tnPGW + PIXELINDEX (1) - tnIfFirstLast) { // Remove a reference to this region. RemoveMotionVectorMatch (pRegion); } // That's one less reference to this region. assert (pRegion->m_tnReferences > 0); --pRegion->m_tnReferences; // Make sure there are references left (from the endpoint). assert (pRegion->m_tnReferences > 0); } rStartpointSet.Clear(); } // (Now do the same for the endpoints, ignoring the dangling // references.) for (tnI = 0; tnI < m_tnWidth; ++tnI) { BorderExtentBoundarySet &rEndpointSet = m_psetBorderEndpoints[(m_tnY - PIXELINDEX (1)) * m_tnWidth + tnI]; for (itBorder = rEndpointSet.Begin(); itBorder != rEndpointSet.End(); ++itBorder) { // Get the under-construction region. MovedRegion *pRegion = (*itBorder).m_pRegion; // That's one less reference to this region. assert (pRegion->m_tnReferences > 0); --pRegion->m_tnReferences; // Are there any references left to this region? if (pRegion->m_tnReferences == 0) { // No. The region is fully constructed. Make sure // there are no border-extent references left. assert (pRegion->m_tnBorderExtents == 0); // Remove it from our active-regions set. typename MovedRegionSet::Iterator itRegion = m_setRegions.Find (pRegion); assert (itRegion != m_setRegions.End()); assert ((*itRegion) == pRegion); m_setRegions.Erase (itRegion); // Move it to the list of regions that'll get applied // to the new frame's reference-image representation. OnCompletedRegion (a_reStatus, pRegion); if (a_reStatus != g_kNoError) { DeleteRegion (pRegion); return; } } } rEndpointSet.Clear(); } } // Any region with (if m_tnX == 0) a last-border startpoint at // m_tnPGW or (if m_tnX == m_tnWidth - m_tnPGW) a last-border // endpoint of m_tnX will no longer be contiguous with the current // pixel-group, but they will be the next time the search border // moves left/right. // // Similarly, any region with (if m_tnX == 0) a bottommost-current- // border startpoint at m_tnPGW or (if m_tnX == m_tnWidth - m_tnPGW) a // bottommost-current-border endpoint of m_tnX will now be contiguous // with the current pixel-group. // // But not if we're past the bottom line. This happens when we're // called by FinishFrame(). if (m_tnY < m_tnHeight - m_tnPGH) { if (m_tnX == 0) { // Fix the new last-border. { // Get the set of startpoints of interest. const BorderExtentBoundarySet &rStartpointSet = m_psetBorderStartpoints[m_tnY * m_tnWidth + m_tnPGW]; // Remove all active regions that have startpoints at this // index. typename BorderExtentBoundarySet::ConstIterator itStartpoint; for (itStartpoint = rStartpointSet.Begin(); itStartpoint != rStartpointSet.End(); ++itStartpoint) { RemoveMotionVectorMatch ((*itStartpoint).m_pRegion); } } // Fix the new bottommost-current-border. { PIXELINDEX tnY = m_tnY + m_tnPGH; PIXELINDEX tnX = m_tnPGW; assert (tnY >= 0 && tnX >= 0 && tnX < m_tnWidth); if (/* tnY >= 0 && */ tnY < m_tnHeight /* && tnX >= 0 && tnX < m_tnWidth */) { // Get the set of startpoints of interest. const BorderExtentBoundarySet &rStartpointSet = m_psetBorderStartpoints[tnY * m_tnWidth + tnX]; // Add all active regions that have startpoints at this // index. typename BorderExtentBoundarySet::ConstIterator itStartpoint; for (itStartpoint = rStartpointSet.Begin(); itStartpoint != rStartpointSet.End(); ++itStartpoint) { AddMotionVectorMatch ((*itStartpoint).m_pRegion); } } } // Find all the extents of regions on the first-border // that will intersect/border the new current-pixel-group, // and put them into the border-regions set. // // All extents on the same line as the first-border, // whose startpoint X is less than the pixel-group width, // are extents that intersect/border the new // current-pixel-group. for (tnI = 0; tnI < m_tnPGW; ++tnI) { PIXELINDEX tnY = m_tnY + m_tnPGH + PIXELINDEX (1); PIXELINDEX tnX = tnI; assert (tnY >= 0 && tnX >= 0 && tnX < m_tnWidth); if (/* tnY >= 0 && */ tnY < m_tnHeight /* && tnX >= 0 && tnX < m_tnWidth */) { // Get the set of startpoints of interest. const BorderExtentBoundarySet &rStartpointSet = m_psetBorderStartpoints[tnY * m_tnWidth + tnX]; // Loop through all the relevant startpoints, add them // to the motion-vector matches. typename BorderExtentBoundarySet::ConstIterator itStartpoint; for (itStartpoint = rStartpointSet.Begin(); itStartpoint != rStartpointSet.End(); ++itStartpoint) { AddMotionVectorMatch ((*itStartpoint).m_pRegion); } } } } else { assert (m_tnX == m_tnWidth - m_tnPGW); // Fix the new last-border. { // Get the set of endpoints of interest. // (The endpoint-X is adjusted downward by 1, because the // valid range of endpoint-X values is from 1 to // m_tnWidth.) const BorderExtentBoundarySet &rEndpointSet = m_psetBorderEndpoints[m_tnY * m_tnWidth + (m_tnX - PIXELINDEX (1))]; // Remove all active regions that have endpoints at this // index. typename BorderExtentBoundarySet::ConstIterator itEndpoint; for (itEndpoint = rEndpointSet.Begin(); itEndpoint != rEndpointSet.End(); ++itEndpoint) { RemoveMotionVectorMatch ((*itEndpoint).m_pRegion); } } // Fix the new bottommost-current-border. { // (The endpoint-X is adjusted downward by 1, because the // valid range of endpoint-X values is from 1 to // m_tnWidth.) PIXELINDEX tnY = m_tnY + m_tnPGH; PIXELINDEX tnX = m_tnX - PIXELINDEX (1); assert (tnY >= 0 && tnX < m_tnWidth); if (/* tnY >= 0 && */ tnY < m_tnHeight && tnX >= 0 /* && tnX < m_tnWidth */) { // Get the set of endpoints of interest. const BorderExtentBoundarySet &rEndpointSet = m_psetBorderEndpoints[tnY * m_tnWidth + tnX]; // Remove all active regions that have endpoints at // this index. typename BorderExtentBoundarySet::ConstIterator itEndpoint; for (itEndpoint = rEndpointSet.Begin(); itEndpoint != rEndpointSet.End(); ++itEndpoint) { AddMotionVectorMatch ((*itEndpoint).m_pRegion); } } } // Find all the extents of regions on the first-border // that will intersect/border the new current-pixel-group, // and put them into the border-regions set. if (m_tnY + m_tnPGH + PIXELINDEX (1) < m_tnHeight) { // All extents on the same line as the first-border, // whose endpoint X is greater than (framewidth - PGW), // are extents that intersect/border the new // current-pixel-group. // (The endpoint-X is adjusted downward by 1, because the // valid range of endpoint-X values is from 1 to // m_tnWidth. That cancels out the upward adjustment.) for (tnI = m_tnX /* + PIXELINDEX (1) - PIXELINDEX (1) */; tnI < m_tnWidth; ++tnI) { // Get the set of endpoints of interest. assert (tnI >= 0 && tnI < m_tnWidth); const BorderExtentBoundarySet &rEndpointSet = m_psetBorderEndpoints[(m_tnY + m_tnPGH + PIXELINDEX (1)) * m_tnWidth + tnI]; // Loop through all the relevant endpoints, add their // corresponding startpoints to the border-regions set. typename BorderExtentBoundarySet::ConstIterator itEndpoint; for (itEndpoint = rEndpointSet.Begin(); itEndpoint != rEndpointSet.End(); ++itEndpoint) { AddMotionVectorMatch ((*itEndpoint).m_pRegion); } } } } // Finally, move one step down, and prepare to move the other // direction across the window. ++m_tnY; m_tnStepX = -m_tnStepX; } } // Return the size of the largest active-region. // Returns zero if there are no active-regions. template FRAMESIZE SearchBorder::GetSizeOfLargestActiveRegion (void) const { // Get the largest active-region, if any. typename MovedRegionSet::ConstIterator itFirst = m_setRegions.Begin(); // Return its size, if any. return (itFirst == m_setRegions.End()) ? FRAMESIZE (0) : (*itFirst)->NumberOfPoints(); } // Determine if a region with this motion vector already // intersects/borders the current pixel-group (i.e. it doesn't // need to be flood-filled and added again). // If so, return true. // If not, return false. template bool SearchBorder::HasExistingMatch (PIXELINDEX a_tnMotionX, PIXELINDEX a_tnMotionY) const { // Make sure the motion-vector is in range. assert (a_tnMotionX >= -m_tnSearchRadiusX && a_tnMotionX <= m_tnSearchRadiusX); assert (a_tnMotionY >= -m_tnSearchRadiusY && a_tnMotionY <= m_tnSearchRadiusY); // Find the corresponding motion-vector-match cell. MotionVectorMatch &rMatch = GetMotionVectorMatch (a_tnMotionX, a_tnMotionY); // Return whether there are any regions associated with this // motion vector. return (rMatch.m_tnActiveExtents > 0) ? true : false; } // Add the given region, with the given motion-vector. // Causes a_rRegion to be emptied. template void SearchBorder::AddNewRegion (Status_t &a_reStatus, MovedRegion &a_rRegion) { MovedRegion *pRegion; // Our copy of the newly added region. typename BorderExtentBoundarySet::Iterator itStart, itEnd; // Any startpoint/endpoint inserted into the set, as they're // inserted. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Make space for a new region. pRegion = (MovedRegion *) m_oMovedRegionAllocator.Allocate (0, sizeof (MovedRegion)); if (pRegion == NULL) { a_reStatus = g_kOutOfMemory; goto cleanup0; } // Create a new region. ::new ((void *) pRegion) MovedRegion (a_reStatus, m_rSetRegionExtentAllocator); if (a_reStatus != g_kNoError) goto cleanup1; // Move the contents of the given region into the new region. // This also copies the motion vector and empties the given region. pRegion->Move (a_rRegion); // If the region's size exceeds the match-size-throttle, don't bother // adding its extents to the startpoint/endpoint sets. We expect our // client to deal with these regions before moving to the next // pixel-group. if (pRegion->NumberOfPoints() < m_tnMatchSizeThrottle) { typename MovedRegion::ConstIterator itHere; // Used to loop through the newly added region. BorderExtentBoundary oStartpoint, oEndpoint; // New startpoints/endpoints as we create them. // Set up the unchanging parts of the startpoint and endpoint. oStartpoint.m_pRegion = oEndpoint.m_pRegion = pRegion; // Loop through every extent of the new region, create a startpoint // and endpoint for each one. If the extent intersects or borders // the current pixel-group, make an entry for it in the // active-regions list. // Extents before the first-border can be ignored -- the // search-border traversal will never find them. for (itHere = (m_tnY == PIXELINDEX (0)) ? pRegion->Begin() : pRegion->LowerBound (m_tnY - PIXELINDEX (1), PIXELINDEX (0)); itHere != pRegion->End(); ++itHere) { // Get the current extent. const typename MovedRegion::Extent &rExtent = *itHere; PIXELINDEX tnY = rExtent.m_tnY; PIXELINDEX tnXStart = rExtent.m_tnXStart; PIXELINDEX tnXEnd = rExtent.m_tnXEnd; // Make sure this extent is inside our frame. (Sanity check.) assert (tnY >= 0 && tnY < m_tnHeight); assert (tnXStart >= 0); assert (tnXStart < tnXEnd); assert (tnXEnd <= m_tnWidth); // Make sure it's not before the first-border. (Sanity check.) assert (tnY + PIXELINDEX (1) >= m_tnY); // Create the startpoint and endpoint that represent this // extent. oStartpoint.m_tnCounterpartIndex = tnXEnd; oEndpoint.m_tnCounterpartIndex = tnXStart; // Make a record of this startpoint. BorderExtentBoundarySet &rStartpointSet = m_psetBorderStartpoints[tnY * m_tnWidth + tnXStart]; typename BorderExtentBoundarySet::InsertResult oStartInsertResult = rStartpointSet.Insert (a_reStatus, oStartpoint); if (a_reStatus != g_kNoError) goto cleanup2; assert (oStartInsertResult.m_bInserted); // Remember where this startpoint was inserted. itStart = oStartInsertResult.m_itPosition; // The new startpoint contains another reference to the region. ++pRegion->m_tnReferences; // Make a record of this endpoint. // (The endpoint-X is adjusted downward by 1, because the // valid range of endpoint-X values is from 1 to m_tnWidth.) BorderExtentBoundarySet &rEndpointSet = m_psetBorderEndpoints[tnY * m_tnWidth + (tnXEnd - PIXELINDEX (1))]; typename BorderExtentBoundarySet::InsertResult oEndInsertResult = rEndpointSet.Insert (a_reStatus, oEndpoint); if (a_reStatus != g_kNoError) { rStartpointSet.Erase (itStart); goto cleanup3; } assert (oEndInsertResult.m_bInserted); // Remember where this endpoint was inserted. itEnd = oEndInsertResult.m_itPosition; // The new endpoint contains another reference to the region. ++pRegion->m_tnReferences; // If this extent intersects/borders the current pixel-group, // then a reference to it must be added to the border-regions // set. PIXELINDEX tnIfFirstLast = (tnY + PIXELINDEX (1) == m_tnY || tnY == m_tnY + m_tnPGH) ? 1 : 0; if (tnY + PIXELINDEX (1) >= m_tnY && tnY <= m_tnY + m_tnPGH && tnXEnd >= m_tnX + tnIfFirstLast && tnXStart < m_tnX + m_tnPGW + PIXELINDEX (1) - tnIfFirstLast) { // Add a reference to this region. AddMotionVectorMatch (pRegion); } } } // Does the search-border have any references to this region? if (pRegion->m_tnReferences != 0 || pRegion->NumberOfPoints() >= m_tnMatchSizeThrottle) { // Yes. Add this region to our set of known regions. #ifndef NDEBUG typename MovedRegionSet::InsertResult oInsertResult = #endif // !NDEBUG m_setRegions.Insert (a_reStatus, pRegion); if (a_reStatus != g_kNoError) goto cleanup2; assert (oInsertResult.m_bInserted); } else { // No. The region is fully constructed. Move it to the list of // regions that'll get applied to the new frame's reference-image // representation. assert (pRegion->m_tnBorderExtents == 0); OnCompletedRegion (a_reStatus, pRegion); if (a_reStatus != g_kNoError) { DeleteRegion (pRegion); return; } } // All done. return; // Clean up after errors. //cleanup4: // --pRegion->m_tnReferences; cleanup3: --pRegion->m_tnReferences; cleanup2: RemoveRegion (pRegion); cleanup1: pRegion->~MovedRegion(); m_oMovedRegionAllocator.Deallocate (0, sizeof (MovedRegion), pRegion); cleanup0: ; } // Removes the given region from the search-border. template void SearchBorder::RemoveRegion (MovedRegion *a_pRegion) { // Make sure they gave us a region to remove. assert (a_pRegion != NULL); // Make sure it's one of our border-regions, i.e. that it has // references. // It won't have references if its size exceeds the match-size- // throttle. We expect our client to deal with these regions before // moving to the next pixel-group. assert (a_pRegion->m_tnReferences > 0 || a_pRegion->NumberOfPoints() >= m_tnMatchSizeThrottle); // Remove this region from the border-regions-set. { typename MovedRegionSet::Iterator itErase = m_setRegions.Find (a_pRegion); assert (itErase != m_setRegions.End()); assert ((*itErase) == a_pRegion); m_setRegions.Erase (itErase); } // Remove all the startpoints/endpoints that refer to this region. // They can be easily found by looping through the region's extents. if (a_pRegion->NumberOfPoints() < m_tnMatchSizeThrottle) { typename MovedRegion::ConstIterator itHere; // Used to loop through moved-region extents. BorderExtentBoundary oExtent; // Used to search for startpoints/endpoints. // The extents will all have the same region. oExtent.m_pRegion = a_pRegion; // Loop through the region's extents, find the corresponding // startpoint and endpoint, and remove them. // Extents before the first-border can be ignored -- they were not // put into the startpoint/endpoint sets. for (itHere = (m_tnY == PIXELINDEX (0)) ? a_pRegion->Begin() : a_pRegion->LowerBound (m_tnY - PIXELINDEX (1), PIXELINDEX (0)); itHere != a_pRegion->End(); ++itHere) { typename BorderExtentBoundarySet::Iterator itExtent; // A startpoint/endpoint that we find. #ifndef NDEBUG #ifdef BORDEREXTENTBOUNDARYSET_IMPLEMENTED_WITH_VECTOR PIXELINDEX tnEndpoint; #else // BORDEREXTENTBOUNDARYSET_IMPLEMENTED_WITH_VECTOR BorderExtentBoundary *pEndpoint; #endif // BORDEREXTENTBOUNDARYSET_IMPLEMENTED_WITH_VECTOR #endif // !NDEBUG // The endpoint that corresponds to a found startpoint. // Get the details of this extent. const typename MovedRegion::Extent &rExtent = *itHere; PIXELINDEX tnY = rExtent.m_tnY; PIXELINDEX tnXStart = rExtent.m_tnXStart; PIXELINDEX tnXEnd = rExtent.m_tnXEnd; // Make sure this extent is inside our frame. (Sanity check.) assert (tnY >= 0 && tnY < m_tnHeight); assert (tnXStart >= 0); assert (tnXStart < tnXEnd); assert (tnXEnd <= m_tnWidth); // Look for the corresponding startpoint. oExtent.m_pRegion = a_pRegion; BorderExtentBoundarySet &rStartpointSet = m_psetBorderStartpoints[tnY * m_tnWidth + tnXStart]; itExtent = rStartpointSet.Find (oExtent); // Make sure it was found. assert (itExtent != rStartpointSet.End()); // Remember its endpoint. #ifndef NDEBUG tnEndpoint = (*itExtent).m_tnCounterpartIndex; #endif // !NDEBUG // Remove the startpoint that corresponds to this extent. rStartpointSet.Erase (itExtent); // That's one less reference to this region. assert (a_pRegion->m_tnReferences > 0); --a_pRegion->m_tnReferences; // Look for the corresponding endpoint. // (The endpoint-X is adjusted downward by 1, because the // valid range of endpoint-X values is from 1 to m_tnWidth.) BorderExtentBoundarySet &rEndpointSet = m_psetBorderEndpoints[tnY * m_tnWidth + (tnXEnd - PIXELINDEX (1))]; itExtent = rEndpointSet.Find (oExtent); // Make sure it was found. assert (itExtent != rEndpointSet.End()); // Make sure it's the endpoint that corresponded to this // startpoint. assert (tnXEnd == tnEndpoint); // Remove the endpoint that corresponds to this extent. rEndpointSet.Erase (itExtent); // That's one less reference to this region. assert (a_pRegion->m_tnReferences > 0); --a_pRegion->m_tnReferences; // If this extent intersects/borders the current pixel-group, // then a reference to it must be removed from the // motion-vector matches. PIXELINDEX tnIfFirstLast = (tnY + PIXELINDEX (1) == m_tnY || tnY == m_tnY + m_tnPGH) ? 1 : 0; if (tnY + PIXELINDEX (1) >= m_tnY && tnY <= m_tnY + m_tnPGH && tnXEnd >= m_tnX + tnIfFirstLast && tnXStart < m_tnX + m_tnPGW + PIXELINDEX (1) - tnIfFirstLast) { // Remove a reference to this region. RemoveMotionVectorMatch (a_pRegion); } } } // Make sure this region has no references left. assert (a_pRegion->m_tnReferences == 0); } // Loop through all regions that matched the current pixel-group, // find the single best one, and return it. // Backpatch the size of the second-best active-region. template typename SearchBorder::MovedRegion * SearchBorder::ChooseBestActiveRegion (Status_t &a_reStatus, FRAMESIZE &a_rtnSecondBestActiveRegionSize) { MovedRegion *pSurvivor; // The only region to survive pruning -- the biggest one, with // the shortest motion vector. typename MovedRegionSet::Iterator itFirst, itSecond; // Used to find the largest and second-largest active-regions. // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // Find the largest region and second-largest active-regions. itFirst = m_setRegions.Begin(); assert (itFirst != m_setRegions.End()); pSurvivor = *itFirst; itSecond = itFirst; ++itSecond; a_rtnSecondBestActiveRegionSize = (itSecond == m_setRegions.End()) ? 0 : (*itSecond)->NumberOfPoints(); // Remove this region from our consideration. RemoveRegion (pSurvivor); // Return the region. return pSurvivor; } // Clean up the search border at the end of a frame, e.g. hand all // remaining regions back to the client. template void SearchBorder::FinishFrame (Status_t &a_reStatus) { // Make sure they didn't start us off with an error. assert (a_reStatus == g_kNoError); // It turns out that we can accomplish this by pretending to move // down m_tnPGH+1 lines -- that'll clear out the last-border and the // current-border. for (int i = 0; i <= m_tnPGH; ++i) { MoveDown (a_reStatus); if (a_reStatus != g_kNoError) return; ++m_tnY; } // Make sure that emptied the border. FRAMESIZE tnPixels = FRAMESIZE (m_tnWidth) * FRAMESIZE (m_tnHeight); #ifndef NDEBUG assert (m_psetBorderStartpoints != NULL); for (FRAMESIZE tnI = 0; tnI < tnPixels; ++tnI) assert (m_psetBorderStartpoints[tnI].Size() == 0); assert (m_psetBorderEndpoints != NULL); for (FRAMESIZE tnI = 0; tnI < tnPixels; ++tnI) assert (m_psetBorderEndpoints[tnI].Size() == 0); #endif // !NDEBUG assert (m_setRegions.Size() == 0); // Make sure there are no active-extents for any motion-vectors. #ifndef NDEBUG { FRAMESIZE tnMotionVectorMatches = (FRAMESIZE (2) * FRAMESIZE (m_tnSearchRadiusX) + FRAMESIZE (1)) * (FRAMESIZE (2) * FRAMESIZE (m_tnSearchRadiusY) * + FRAMESIZE (1)); for (FRAMESIZE i = 0; i < tnMotionVectorMatches; ++i) assert (m_pMotionVectorMatches[i].m_tnActiveExtents == 0); } #endif // !NDEBUG // Purge all border-startpoint/endpoint memory. for (FRAMESIZE tnI = 0; tnI < tnPixels; ++tnI) m_psetBorderStartpoints[tnI].Purge(); for (FRAMESIZE tnI = 0; tnI < tnPixels; ++tnI) m_psetBorderEndpoints[tnI].Purge(); // Make sure our temporary memory allocations have been purged. assert (m_oBorderExtentsAllocator.GetNumAllocated() == 0); } // Delete a region that was returned by ChooseBestActiveRegion() // or OnCompletedRegion(). template void SearchBorder::DeleteRegion (MovedRegion *a_pRegion) { // Make sure they gave us a region to delete. assert (a_pRegion != NULL); // Easy enough. a_pRegion->~MovedRegion(); m_oMovedRegionAllocator.Deallocate (0, sizeof (MovedRegion), a_pRegion); } #endif // __SEARCH_BORDER_H__ mjpegtools-2.1.0/y4mdenoise/main.c0000644000175000017500000003063411423114540017362 0ustar glowwormglowworm/*********************************************************** * A new denoiser for the mjpegtools project * * ------------------------------------------------------- * * (C) 2004-2009 Steven Boswell. * * Based on yuvdenoise/main.c, (C) 2001,2002 Stefan Fendt * * * * Licensed and protected by the GNU-General-Public- * * License version 2. See the file COPYING for detailed * * information. * ***********************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "mjpeg_types.h" #include "yuv4mpeg.h" #include "mjpeg_logging.h" #include "config.h" #include "newdenoise.hh" // HACK #include #include void process_commandline(int argc, char *argv[]); void alloc_buffers (void); void display_help (void); DNSR_GLOBAL denoiser; int frame = 0; int verbose = 1; /*********************************************************** * * ***********************************************************/ int main(int argc, char *argv[]) { int fd_in = 0; int fd_out = 1; int errno = 0; y4m_frame_info_t frameinfo; y4m_stream_info_t streaminfo; int chroma_mode; int bInputStreamEnded; frame = 0; /* initialize stream-information */ y4m_accept_extensions (1); y4m_init_stream_info (&streaminfo); y4m_init_frame_info (&frameinfo); /* setup default values for denoiser's parameters */ denoiser.frames = 10; denoiser.interlaced = -1; denoiser.bwonly = 0; denoiser.radiusY = 16; denoiser.radiusCbCr = -1; denoiser.zThresholdY = 0; /* assume medium noise material */ denoiser.zThresholdCbCr = -1; denoiser.thresholdY = 3; /* assume medium noise material */ denoiser.thresholdCbCr = -1; denoiser.matchCountThrottle = 16; denoiser.matchSizeThrottle = 256; denoiser.threads = 1; /* process commandline */ process_commandline(argc, argv); /* If color-specific settings were not specified, copy them from the intensity settings. */ if (denoiser.radiusCbCr == -1) denoiser.radiusCbCr = denoiser.radiusY; if (denoiser.thresholdCbCr == -1) denoiser.thresholdCbCr = denoiser.thresholdY; if (denoiser.zThresholdCbCr == -1) denoiser.zThresholdCbCr = denoiser.zThresholdY; /* Make sure the parameters are consistent. */ { int isConsistent = 1; /* The zero-motion error threshold has to be lower than the motion-compensated error threshold. The zero-motion pass is just a way to speed up detection of unambiguous zero-motion areas, so a higher error threshold would defeat the purpose. */ if (denoiser.zThresholdY > denoiser.thresholdY) { mjpeg_error ("-z setting (%d) cannot be larger than " "-t setting (%d)\n", denoiser.zThresholdY, denoiser.thresholdY); isConsistent = 0; } if (denoiser.zThresholdCbCr > denoiser.thresholdCbCr) { mjpeg_error ("-Z setting (%d) cannot be larger than " "-T setting (%d)\n", denoiser.zThresholdCbCr, denoiser.thresholdCbCr); isConsistent = 0; } /* If the parameters weren't consistent, quit with an error. */ if (!isConsistent) exit (1); } /* open input stream */ if ((errno = y4m_read_stream_header (fd_in, &streaminfo)) != Y4M_OK) mjpeg_error_exit1 ("Couldn't read YUV4MPEG header: %s!", y4m_strerr (errno)); if (y4m_si_get_plane_count (&streaminfo) != 3) mjpeg_error_exit1 ("Only 3-plane formats supported."); denoiser.frame.w = y4m_si_get_width (&streaminfo); denoiser.frame.h = y4m_si_get_height (&streaminfo); chroma_mode = y4m_si_get_chroma (&streaminfo); denoiser.frame.ss_h = y4m_chroma_ss_x_ratio (chroma_mode).d; denoiser.frame.ss_v = y4m_chroma_ss_y_ratio (chroma_mode).d; denoiser.frame.Cw=denoiser.frame.w/denoiser.frame.ss_h; denoiser.frame.Ch=denoiser.frame.h/denoiser.frame.ss_v; /* write the outstream header */ y4m_write_stream_header (fd_out, &streaminfo); /* allocate memory for frames */ if (!(denoiser.threads & 1)) alloc_buffers(); /* set interlacing, if it hasn't been yet. */ if (denoiser.interlaced == -1) { int n = y4m_si_get_interlace(&streaminfo); switch (n) { case Y4M_ILACE_NONE: denoiser.interlaced = 0; break; case Y4M_ILACE_TOP_FIRST: denoiser.interlaced = 1; break; case Y4M_ILACE_BOTTOM_FIRST: denoiser.interlaced = 2; break; default: mjpeg_warn("Unknown interlacing '%d', assuming non-interlaced", n); denoiser.interlaced = 0; break; } } /* if we're processing interlaced material, there is an additional requirement that the number of reference frames be a multiple of 2 (since there are 2 fields per frame). */ if (denoiser.interlaced != 0 && (denoiser.frames & 1) != 0) mjpeg_error_exit1 ("When denoising interlaced material, -f must be" " a multiple of 2"); /* initialize the denoiser */ errno = newdenoise_init (denoiser.frames, denoiser.frame.w, denoiser.frame.h, (denoiser.bwonly) ? 0 : denoiser.frame.Cw, (denoiser.bwonly) ? 0 : denoiser.frame.Ch, fd_in, fd_out, &streaminfo, &frameinfo); if (errno == -1) mjpeg_error_exit1( "Could not initialize denoiser"); /* get space for the first output frame, if necessary */ if (denoiser.threads & 1) { errno = newdenoise_get_write_frame (denoiser.frame.out); if (errno) mjpeg_error_exit1 ("Could not get space for frame %d", frame); } /* read every single frame until the end of the input stream */ bInputStreamEnded = 0; for (;;) { /* If there is another input frame, read it. We may find there is no more input. */ if (!bInputStreamEnded) { /* Read the next frame. */ if (!(denoiser.threads & 1)) errno = y4m_read_frame (fd_in, &streaminfo, &frameinfo, denoiser.frame.in); else errno = newdenoise_read_frame (denoiser.frame.in); /* did stream end unexpectedly ? */ if(errno != Y4M_ERR_EOF && errno != Y4M_OK ) mjpeg_error_exit1( "%s", y4m_strerr( errno ) ); /* Note if the stream ended. */ if (errno == Y4M_ERR_EOF) bInputStreamEnded = 1; } /* One more input frame. */ frame++; //if (frame < 5395) continue; // MAJOR HACK MAJOR HACK MAJOR HACK //if (frame == 5455) break; // MAJOR HACK MAJOR HACK MAJOR HACK // fprintf (stderr, "Frame %d\r", frame); // HACK /* denoise the current frame */ errno = ((denoiser.interlaced == 0) ? newdenoise_frame : newdenoise_interlaced_frame) (((bInputStreamEnded) ? NULL : denoiser.frame.in[0]), ((bInputStreamEnded) ? NULL : denoiser.frame.in[1]), ((bInputStreamEnded) ? NULL : denoiser.frame.in[2]), denoiser.frame.out[0], denoiser.frame.out[1], denoiser.frame.out[2]); if (errno == -1) mjpeg_error_exit1( "Could not denoise frame %d", frame); /* if there was no output from the denoiser, leave. */ if (bInputStreamEnded && errno == 1) break; /* if there was some output from the denoiser, write it. */ if (errno == 0) { /* if b/w was selected, set the frame color to white */ if (denoiser.bwonly) { int i, iExtent = denoiser.frame.Cw * denoiser.frame.Ch; for (i = 0; i < iExtent; ++i) denoiser.frame.out[1][i] = 128; for (i = 0; i < iExtent; ++i) denoiser.frame.out[2][i] = 128; } /* Write the frame. */ if (!(denoiser.threads & 1)) errno = y4m_write_frame ( fd_out, &streaminfo, &frameinfo, denoiser.frame.out); else errno = newdenoise_write_frame(); if (errno) mjpeg_error_exit1 ("Could not write frame %d", frame); /* Get space for the next frame.*/ if (denoiser.threads & 1) { errno = newdenoise_get_write_frame (denoiser.frame.out); if (errno) mjpeg_error_exit1 ("Could not get space for " "frame %d", frame); } } } /* shut down the denoiser */ errno = newdenoise_shutdown(); if (errno != 0) mjpeg_error_exit1 ("Could not shut down denoiser"); /* Exit gently */ return(0); } void process_commandline(int argc, char *argv[]) { char c; while ((c = getopt (argc, argv, "h?z:Z:t:T:r:R:m:M:f:BI:p:v:")) != -1) { switch (c) { case 'h': { display_help(); exit (0); break; } case '?': { display_help(); exit (0); break; } case 'r': { denoiser.radiusY = atoi(optarg); if(denoiser.radiusY<4) { denoiser.radiusY=4; mjpeg_warn ("Minimum allowed search radius is 4 pixels."); } break; } case 'R': { denoiser.radiusCbCr = atoi(optarg); if(denoiser.radiusCbCr<4) { denoiser.radiusCbCr=4; mjpeg_warn ("Minimum allowed color search radius is 4 pixel."); } break; } case 'z': { denoiser.zThresholdY = atoi(optarg); break; } case 'Z': { denoiser.zThresholdCbCr = atoi(optarg); break; } case 't': { denoiser.thresholdY = atoi(optarg); break; } case 'T': { denoiser.thresholdCbCr = atoi(optarg); break; } case 'm': { denoiser.matchCountThrottle = atoi(optarg); break; } case 'M': { denoiser.matchSizeThrottle = atoi(optarg); break; } case 'f': { denoiser.frames = atoi(optarg); break; } case 'B': { denoiser.bwonly = 1; break; } case 'I': { int interlaced = atoi (optarg); if (interlaced != 0 && interlaced != 1 && interlaced != 2) { mjpeg_error_exit1 ("-I must be either 0, 1, or 2"); } denoiser.interlaced = interlaced; break; } case 'p': { int threads = atoi (optarg); if (threads < 0 || threads > 3) { mjpeg_error_exit1 ("-p must be either 0, 1, 2, or 3"); } denoiser.threads = threads; break; } case 'v': verbose = atoi (optarg); if (verbose < 0 || verbose > 2) { mjpeg_error_exit1 ("Verbose level must be [0..2]"); } break; default: fprintf (stderr, "Unknown option '%c'\n", c); display_help(); exit (1); } } } void alloc_buffers(void) { int luma_buffsize; int chroma_buffsize; luma_buffsize = denoiser.frame.w * denoiser.frame.h; chroma_buffsize = denoiser.frame.Cw * denoiser.frame.Ch; denoiser.frame.in[0] = (uint8_t *) malloc (luma_buffsize); denoiser.frame.in[1] = (uint8_t *) malloc (chroma_buffsize); denoiser.frame.in[2] = (uint8_t *) malloc (chroma_buffsize); denoiser.frame.out[0] = (uint8_t *) malloc (luma_buffsize); denoiser.frame.out[1] = (uint8_t *) malloc (chroma_buffsize); denoiser.frame.out[2] = (uint8_t *) malloc (chroma_buffsize); if ( denoiser.frame.in[0] == NULL || denoiser.frame.in[1] == NULL || denoiser.frame.in[2] == NULL || denoiser.frame.out[0] == NULL || denoiser.frame.out[1] == NULL || denoiser.frame.out[2] == NULL) mjpeg_error_exit1( "Out of memory " "when allocating frame buffers"); } void display_help (void) { fprintf (stderr, "y4mdenoise options\n" "------------------\n" "-p parallelism: 0=no threads, 1=r/w thread only, 2=do color in\n" " separate thread (default: 1)\n" "-r Radius for motion-search (default: 16)\n" "-R Radius for color motion-search (default: -r setting)\n" "-t Error tolerance (default: 3)\n" "-T Color error tolerance (default: -t setting)\n" "-z Error tolerance for zero-motion pass (default: 2)\n" "-Z Error tolerance for color's zero-motion pass (default: -z setting)\n" "-m Match-count throttle (keep this many of the best pixel-group\n" " matches found in a radius search) (default: 15)\n" "-M Match-size throttle (apply first match whose flood-fill is the\n" " size of this many pixel-groups or greater) (default: 3)\n" "-f Number of reference frames (default: 10)\n" "-B Black-and-white mode; denoise intensity, set color to white\n" "-I Interlacing type: 0=frame, 1=top-field-first, 2=bottom-field-first\n" " (default: taken from stream header)\n" "-v Verbosity (0=none, 1=normal 2=debug)\n" "-h,-? Help\n" "Intensity pixel-groups are 4x2 (i.e. 4 across and 2 down).\n" "Color pixel-groups are 2x2.\n" ); } mjpegtools-2.1.0/y4mdenoise/Set.hh0000644000175000017500000001437011204303657017353 0ustar glowwormglowworm#ifndef __SET_H__ #define __SET_H__ // This file (C) 2004-2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. // Set is an STL-like set class. // Handles the STL equivalent of MultiSet, too. #include "SkipList.hh" #include "TemplateLib.hh" template , class IMP = SkipList,PRED> > class Set { public: typedef IMP Imp; // The type that implements our internal operations. typedef typename Imp::InitParams InitParams; // How that internal type is initialized. private: Imp m_oImp; // How we implement ourselves. public: typedef typename Imp::Allocator_t Allocator; // The type of allocator to use to allocate items in the set. Set (const PRED &a_rPred = PRED(), Allocator &a_rAlloc = Imp::sm_oNodeAllocator) : m_oImp (a_rPred, a_rAlloc) {} // Default constructor. Must be followed by Init(). Set (Status_t &a_reStatus, bool a_bAllowDuplicates = false, const InitParams &a_rInitParams = InitParams(), const PRED &a_rPred = PRED(), Allocator &a_rAlloc = Imp::sm_oNodeAllocator) : m_oImp (a_reStatus, a_bAllowDuplicates, a_rInitParams, a_rPred, a_rAlloc) {} // Initializing constructor. void Init (Status_t &a_reStatus, bool a_bAllowDuplicates = false, const InitParams &a_rInitParams = InitParams()) { m_oImp.Init (a_reStatus, a_bAllowDuplicates, a_rInitParams); } // Construction method. virtual ~Set (void) {} // Destructor. #ifdef DEBUG_SKIPLIST void SetDebug (bool a_bDebug) { m_oImp.SetDebug (a_bDebug); } // Set whether to run the set invariant before and after // methods. void Invariant (void) const { m_oImp.Invariant(); } // Thoroughly analyze the set for structural integrity. #endif // DEBUG_SKIPLIST typedef typename Imp::Iterator Iterator; typedef typename Imp::ConstIterator ConstIterator; typedef typename Imp::InsertResult InsertResult; // Iterator classes & other helpers. // // Set methods. // Iterator Begin (void) { return m_oImp.Begin(); } // Return an iterator to the beginning of the list. ConstIterator Begin (void) const { return m_oImp.Begin(); } // Return an iterator to the beginning of the list. Iterator End (void) { return m_oImp.End(); } // Return an iterator to the end of the list. ConstIterator End (void) const { return m_oImp.End(); } // Return an iterator to the end of the list. int32_t Size (void) const { return m_oImp.Size(); } // Return the number of items in the list. // (May be called on a default-constructed object, making it // possible for default-constructed subclasses/owners to destroy // themselves safely.) bool Empty (void) const { return m_oImp.Empty(); } // Return whether the list is empty. InsertResult Insert (Status_t &a_reStatus, const TYPE &a_rValue) { return m_oImp.Insert (a_reStatus, a_rValue); } // Insert an item into the list. Iterator Insert (Status_t &a_reStatus, Iterator a_itPosition, const TYPE &a_rValue) { return m_oImp.Insert (a_reStatus, a_itPosition, a_rValue); } // Insert an item into the list, at this exact location, if it's // safe. Returns where it was really inserted. void Insert (Status_t &a_reStatus, ConstIterator a_itFirst, ConstIterator a_itLast) { m_oImp.Insert (a_reStatus, a_itFirst, a_itLast); } // Insert a range of items from another set. Iterator Erase (Iterator a_itHere) { return m_oImp.Erase (a_itHere); } // Erase the item here. Return the item following the one // removed. Iterator Erase (Iterator a_itFirst, Iterator a_itLast) { return m_oImp.Erase (a_itFirst, a_itLast); } // Erase a range of items in this list. Return the item // following the last one removed. void Clear (void) { m_oImp.Clear(); } // Empty the list. void Purge (void) { m_oImp.Purge(); } // Purge all internally-allocated memory. InsertResult Move (Set &a_rOther, Iterator a_itHere) { return m_oImp.Move (a_rOther.m_oImp, a_itHere); } // Remove an item from another set and insert it into ourselves. // Just like an Erase() followed by an Insert(), except that // there's no possibility of the operation failing. void Move (Set &a_rOther, Iterator a_itFirst, Iterator a_itLast) { m_oImp.Move (a_rOther.m_oImp, a_itFirst, a_itLast); } // Remove a range of items from another set and insert them // into ourselves. // Just like an Erase() followed by an Insert(), except that // there's no possibility of the operation failing. void Move (Set &a_rOther) { m_oImp.Move (a_rOther.m_oImp); } // Move all items from the other set to ourself. // The current set must be empty. bool CanMove (const Set &a_rOther) const { return m_oImp.CanMove (a_rOther.m_oImp); } // Returns true if the two sets can move items between // each other. void Assign (Status_t &a_reStatus, const Set &a_rOther) { m_oImp.Assign (a_reStatus, a_rOther.m_oImp); } // Assign the contents of the other set to ourselves. Iterator Find (const TYPE &a_rKey) { return m_oImp.Find (a_rKey); } // Find the given item in the list. Returns End() if not found. ConstIterator Find (const TYPE &a_rKey) const { return m_oImp.Find (a_rKey); } // Find the given item in the list. Returns End() if not found. Iterator LowerBound (const TYPE &a_rKey) { return m_oImp.LowerBound (a_rKey); } // Return the position of the first item that's >= the key. ConstIterator LowerBound (const TYPE &a_rKey) const { return m_oImp.LowerBound (a_rKey); } // Return the position of the first item that's >= the key. Iterator UpperBound (const TYPE &a_rKey) { return m_oImp.UpperBound (a_rKey); } // Return the position of the first item that's > the key. ConstIterator UpperBound (const TYPE &a_rKey) const { return m_oImp.UpperBound (a_rKey); } // Return the position of the first item that's > the key. size_t GetSizeOfLargestNode (void) const { return m_oImp.GetSizeOfLargestNode(); } // Return the size of the largest possible skip-list node. // // (Not generally useful...needed by VariableSizeAllocator, // to make sure all free-space blocks can become part of an // in-place skip-list.) }; #endif // __SET_H__ mjpegtools-2.1.0/y4mdenoise/PlacementAllocator.hh0000644000175000017500000001005311204303656022362 0ustar glowwormglowworm#ifndef __PLACEMENTALLOCATOR_H__ #define __PLACEMENTALLOCATOR_H__ // This file (C) 2009 Steven Boswell. All rights reserved. // Released to the public under the GNU General Public License v2. // See the file COPYING for more information. #include "config.h" #include "mjpeg_types.h" #include "Limits.hh" // An allocator class, compatible with Allocator<>, that allows // placement allocation. // One possible use is to allow Set<> to implement an in-place free-space // list for a variable-size memory allocator. class PlacementAllocator { public: PlacementAllocator (size_t a_nChunkSize); // Constructor. // The value of a_nChunkSize is ignored -- it's present only to // remain compatible with Allocator<>'s interface. ~PlacementAllocator(); // Destructor. void SetAllocatedMemory (void *a_pMemory, size_t a_nBytes); // Set the next block of memory that will be "allocated". // (The next call to Allocate() will return this block.) void *GetDeallocatedMemory (size_t &a_rnBytes); // Get the previous block of memory that was deallocated. // (The previous call to Deallocate() set these values.) void *Allocate (size_t a_nSize, size_t a_nBytes); // Allocate a block of memory of the given number of bytes. // Returns NULL if memory is exhausted. // The value of a_nSize is ignored. void Deallocate (size_t a_nSize, size_t a_nBytes, void *a_pMemory); // Deallocate previously-allocated memory. // The value of a_nSize is ignored. private: void *m_pMemory; size_t m_nBytes; // The current block of memory, and its size. // Set by either SetAllocatedMemory() or Deallocate(). // Retrieved by either Allocate() or GetDeallocatedMemory(). }; // Default constructor. PlacementAllocator::PlacementAllocator (size_t /* a_nChunkSize */) : m_pMemory (NULL), m_nBytes (0) { // Nothing else to do. } // Destructor. PlacementAllocator::~PlacementAllocator() { // Make sure no block of memory is still being tracked. assert (m_pMemory == NULL); } // Set the next block of memory that will be "allocated". // (The next call to Allocate() will return this block.) void PlacementAllocator::SetAllocatedMemory (void *a_pMemory, size_t a_nBytes) { // Make sure there's no existing block of memory being tracked. assert (m_pMemory == NULL); // Keep track of this block of allocated memory. m_pMemory = a_pMemory; m_nBytes = a_nBytes; } // Get the previous block of memory that was deallocated. // (The previous call to Deallocate() set these values.) void * PlacementAllocator::GetDeallocatedMemory (size_t &a_rnBytes) { // Make sure there's a block of deallocated memory. assert (m_pMemory != NULL); // Remember the block of deallocated memory. void *pMemory = m_pMemory; a_rnBytes = m_nBytes; // Remember that this block of deallocated memory has been retrieved. m_pMemory = NULL; m_nBytes = 0; // Return the block of deallocated memory. return pMemory; } // Allocate memory for another object of type TYPE. // Use the given size-bucket, which must be for the given number // of bytes. // Returns NULL if memory is exhausted. void * PlacementAllocator::Allocate (size_t a_nSize, size_t a_nBytes) { // Make sure there's a block of memory to allocate. assert (m_pMemory != NULL); // Make sure it's large enough for this allocation. assert (m_nBytes >= a_nBytes); // Remember the block of memory to allocate. void *pMemory = m_pMemory; // Remember that this block of memory has been allocated. m_pMemory = NULL; m_nBytes = 0; // Return the block of allocated memory. return pMemory; } // Deallocate previously-allocated memory. void PlacementAllocator::Deallocate (size_t a_nSize, size_t a_nBytes, void *a_pMemory) { // Make sure there's a block of memory to deallocate. assert (a_pMemory != NULL); // Allow the tracking of an existing block of memory, i.e. don't assert // that m_pMemory is NULL. // This makes it possible to purge several items at once // without having to "clean up" between them. // Keep track of this block of deallocated memory. m_pMemory = a_pMemory; m_nBytes = a_nBytes; } #endif // __PLACEMENTALLOCATOR_H__ mjpegtools-2.1.0/mjpeg_howto.txt0000644000175000017500000032651212217255472017314 0ustar glowwormglowworm MJPEG HOWTO - An introduction to the MJPEG-tools Praschinger Bernhard v2.00 MJPEG capture/editting/replay and MPEG encoding toolset description ______________________________________________________________________ Table of Contents 1. Introduction 2. Unsorted list of useful Hints 2.1 Some books we found usefull 3. Recording videos 3.1 lavrec examples 3.2 Other recording hints 3.3 Some information about the typical lavrec output while recording 3.4 Notes about "interlace field order - what can go wrong and how to fix it" 3.4.1 There are three bad things that can happen with fields 3.4.2 How can I recognize if I have one of these Problems ? 3.4.3 How can you fix it? 3.4.4 Hey, what about NTSC movies ? 4. Creating videos from other sources 4.1 Creating videos from images 4.2 Decoding streams with mplayer 4.3 Decoding MPEG-2 streams with mpeg2dec 4.4 Other things to know 5. Checking if recording was successful 6. Edit the video 6.1 Edit with glav 6.2 Unify videos 6.3 Separate sound 6.4 Separate images 6.5 Creating movie transitions 7. Converting the stream to MPEG or DIVx videos 7.1 Creating sound 7.2 Converting video 7.2.1 Scaling 7.2.2 High quality scaling: y4mscaler 7.3 Putting the streams together 7.4 Creating MPEG-1 Videos 7.4.1 MPEG-1 Audio creation Example 7.4.2 MPEG-1 Video creation example 7.4.3 MPEG-1 Multiplexing Example 7.5 Creating MPEG-2 Videos 7.5.1 MPEG-2 audio creation example 7.5.2 MPEG-2 Video creation example 7.5.2.1 Which values should be used for VBR Encoding? 7.5.2.2 Encoding destination TV (interlaced) or Monitor (progressive) 7.5.3 MPEG-2 Multiplexing example 7.6 Creating Video CDs (VCDs) 7.6.1 VCD Audio creation Example 7.6.2 VCD Video creation Example 7.6.3 VCD Multiplexing Example 7.6.4 Creating the CD 7.6.5 Notes 7.6.6 Storing MPEGs 7.7 Creating SVCD 7.7.1 SVCD Audio creation Example 7.7.2 SVCD Video creation example 7.7.3 SVCD multiplexing example 7.7.4 SVCD creating the CD 7.8 Creating DVD's 7.8.1 DVD Audio creation example 7.8.2 DVD Video creation example 7.8.3 DVD multiplexing example 7.8.4 DVD creation example 7.9 Creating DIVX Videos 7.9.1 lav2avi.sh 8. Optimizing the stream 8.1 Scaling and offset correction 8.2 Frame rate conversion 9. Transcoding of existing MPEG-2 9.1 If you want to do every step on your own it will look something like this 10. Trading Quality/Speed 10.1 Creating streams to be played from disk using Software players 11. SMP and distributed Encoding 12. Interoperability ______________________________________________________________________ 1. Introduction I wrote this things down, because I had many sheets with notes on them. This should be some kind of summary of collected knowledge over a long period of time. Andrew Stevens helped with encoding and VCD knowledge and hints. Mjpegtools is a set of programs that can do recording, playback, editing and eventual MPEG compression of audio and video under Linux. Although primarily intended for use with capture / playback boards based on the Zoran ZR36067 MJPEG codec chip mjpegtools can easily be used to process and compress MJPEG video streams captured using xawtv using simple frame-buffer devices. The HOWTO for the tools intended to give an an introduction to the MJPEG-tools and the creation of MPEG 1/2 videos. VCD, SVCD and DVD and the transcoding of existing mpeg streams. For more information about the programs read the corresponding man- page. Achtung es gibt auch eine deutsche Version bei: http://sourceforge.net/projects/mjpeg There is also a manpage of this text. You can read it with "man mjpegtools" if installed. We also have a info version you should be able to read it with info The text version of this text is available via cvs. You should get it with the tarball or the precompiled package (RPM and deb). In the following picture you see the typical workflow when you record a video, cut it afterwards and encode it. In the picture you also see the connections to other programs. These parts are in grey. The parts in blue can be done with the mjpegtools. Video encoding workflow 2. Unsorted list of useful Hints You have to compile and install the mjpeg_play package, for this read the README & INSTALL.real an follow the hints from the configure script. If you do not want to compile it, you can download the mjpeg .RPM or .DEB package at Sourceforge, or if available use the one that comes with your distribution. There is a script in the scripts/ directory. This script is something that shows you a way it can be done. It also creates (under certain circumstances) videos that look quite good. Better videos you will only get by tuning the parameters. If you use a Linux kernel from the 2.4 series you will usually have to load the drivers for the Buz or DC10 or LML33 cards. You have to run the update script providing as option the name of your card you have. The script is usually in /usr/src/driver-zoran/. The zoran kernel driver below the kernel 2.4.4 do not work. You have to use the driver available from: http://mjpeg.sourceforge.net/driver-zoran In the 2.6. Linux kernel is the driver for the zoran cards included, you just need to make sure that it is loaded correct. If you have a x64 machine and an kernel that is newer than 2.6.30 we'd be happy to hear that you are able to record from the zoran based card. I'm not soure if that combination works. The driver for the Matrox Marvel card also works, more information about it: http://marvel.sourceforge.net If you compile the tools on a P6 based computer (PPro, P-II, P-III, P-4, Athlon,Duron) then never try to let them run on a P5 based computer (Pentium, Pentium-MMX, K6, K6-x, Cyrix, Via, Winchip). You'll get a "illegal instruction" and the program won't work. That is the same for the newer CPU as well. If you use specific optimizations be aware of them. If lav2yuv dumps core then one possible cause is no dv support was included. To enable it make sure that libdv is installed on the system. This will be necessary if you are using a digital camera (or analog to DV converter such as the Canopus ADVC100 and converting the dv avi format into the MPEG format. Start xawtv to see if you get an picture. If you want to use HW- playback of the recorded streams you have to start xawtv (any TV application works) once to get the streams played back. You should also check the settings of your mixer in the sound card. If you use v4l2 you should give mplayer a try to watch the picture If you compile the tools on a platform other than Linux not all tools will work. Mjpegtools on a OS/X system for example will not have V4L (video4linux) capability. Never try to stop or start the TV application when lavrec runs. If you start or stop the TV application lavrec will stop recording, or your computer could get "frozen". This is a problem of v4l (video4linux). This problem is solved with v4l2. If you use v4l2 you can record the video and stop and start the tv application whenever you want. But v4l2 is currently (7. Jan. 2003) only supported for the zoran based cards (BUZ, DC10, DC10+, LML33) if you use the CVS driver from mjpeg.sf.net tagged with ZORAN_VIDEODEV_2. And this driver only works with the 2.4.20 kernel and the 2.5.* development kernel. One last thing about the data you get before we start: Audio: ( Samplerate * Channels * Bitsize ) / (8 * 1024) CD Quality:(44100 Samples/sec * 2 Chanels * 16 Bit) / (8 * 1024)=172,2 kB/sec The 8 * 1024 convert the value from bit/sec to kByte/sec Video: (width * height * framerate * quality ) / (200 * 1024) PAL HALF Size : (352 * 288 * 25 * 80) / (200 * 1024) = 990 kB/sec PAL FULL size : (720 * 576 * 25 * 80) / (200 * 1024) = 4050 kB/sec NTSC HALF size: (352 * 240 * 30 * 80) / (200 * 1024) = 990 kB/sec NTSC FULL size: (720 * 480 * 30 * 80) / (200 * 1024) = 4050 kB/sec The 1024 converts the Bytes to kBytes. Not every card can record the size mentioned. The Buz and Marvel G400 for example can only record a size of 720x576 when using -d 1, the DC10 records a size of 384x288 when using -d 2. When you add audio and video datarate this is what your hard disk has to be able to write constantly streaming, else you will have lost frames. If you want to play with the --mjpeg-buffer-size. Remember the value should be at least big enough that one frame fits in it. The size of one frame is: (width * height * quality ) / (200 * 1024) = kB If the buffer is too small the rate calculation doesn't match any more and buffer overflows can happen. The maximum value is 512kB. How video works and the difference between the video types is explained here: http://www.mir.com/DMG/ There you also find how to create MPEG Still Images for VCD/SVCD. A good description of DV (Digital Video) can be found here: http://www.uwasa.fi/~f76998/video/conversion/ 2.1. Some books we found usefull written in English: o Digital Video and HDTV by Charles Poyton (ISBN 1-55860-792-7) o Digital Video Compression by Peter Symes (ISBN 0-07-142487-3) o Video Demystified by Keith Jack (ISBN 1-878707-56-6) written in German: o Fernsehtechnik von Rudolf Maeusl (ISBN 3-7785-2374-0) o Professionelle Videotechnik - analoge und digitale Grundlagen von U. Schmidt (ISBN 3-540-43974-9) o Digitale Film- und Videotechnik von U. Schmidt (ISBN 3-446-21827-0) If you know some other really good book about that, write us! 3. Recording videos 3.1. lavrec examples Recording with lavrec looks like this: > lavrec -f a -i P -d 2 record.avi Should start recording now, -f a use AVI as output format, -i P use as input source the SVHS-In with PAL format, -d 2 the size of the pictures are half size (352x288) record.avi name of the created file. Recording is finished by pressing Ctrl-C (on German Keyboards: Strg- C). Sometimes using -f A instead of -f a might be necessary Other example: > lavrec -f q -i n -d 1 -q 80 -s -l 80 -R l -U record.avi Should start recording now, -f q use Quicktime as output format, -i n use Composite-In with NTSC format, -d 1 record pictures with full size (640x480) -q 80 set the quality to 80% of the captured image -s use stereo mode (default mono) -l 80 set the recording level to 80% of the max during recording -R l set the recording source to Line-In -U With this lavrec uses the read instead of mmap for recording this is needed if your sound card does not support the mmap for recording. Setting the mixer does not work with every sound card. If you record with 2 different settings and both recordings are equally loud you should setup the mixer with a mixer program. After that you should use the -l -1 option when you record using lavrec The size of the image depends on the card you use. At full size (-d 1) you get these image sizes: BUZ and LML33: 720x576, the DC10 and DC30: 768x576 Other example: > lavrec -w -f a -i S -d 2 -l -1 record%02d.avi Should start recording, -w Waits for user confirmation to start (press enter) -f a use AVI as output format, -i S use SECAM SVHS-Input (SECAM Composite recording is also possible: -i s) -d 2 the size of the pictures are half size -l -1 do not touch the mixer settings record%02d.avi Here lavrec creates the first file named record00.avi after the file has reached a size of 1.6GB (after about 20 Minutes recording) it starts a new sequence named record01.avi and so on till the recording is stopped or the disk is full. With the release of the 1.9.0 Version mjpegtools is able to handle AVI files larger than 2GB. So that option is present for compatibility. Other example: > lavrec -f a -i t -q 80 -d 2 -C europe-west:SE20 test.avi Should start recording now, -f a use AVI as output format, -i t use tuner input, -q 80 set the quality to 80% of the captured image -d 2 the size of the pictures are half size (352x288) -C choose TV channels, and the corresponding -it and -iT (video source: TV tuner) can currently be used on the Marvel G200/G400 and the Matrox Millenium G200/G400 with Rainbow Runner extension (BTTV-Support is under construction). For more information on how to make the TV tuner parts of these cards work, see the Marvel/Linux project on: http://marvel.sourceforge.net Last example: > lavrec -f a -i p -g 352x288 -q 80 -s -l 70 -R l --software-encoding test03.avi The two new options are -g 352x288, which sets the size of the video to be recorded when using --software-encoding, this enables the software encoding of the recorded images. With this option you can also record from a bttv based card. The processor load is high. This option only works for generic video4linux cards (such as the brooktree-848/878 based cards), it doesn't work for zoran-based cards. 3.2. Other recording hints All lavtools accept a file description like file*.avi so you do not have to name each file but that is a posibility. Note: More options are described in the man-page, but with this you should be able to get started. Here are some hints for sensible settings. Turn the quality to 80% or more for -d 2 capture. At full resolution as low as 40% seems to be visually "perfect". -d 2 is already better than VHS video (a *lot*!). For a Marvel you should not set the quality higher than 50 when you record at full size (-d 1). If you use higher settings (-q 60) it is more likely that you will encounter problems. Higher settings will result in framedrops. If you're aiming to create VCD's then there is little to be gained recording at full resolution as you need to reduce to -d 2 resolution later anyway. you can record at other sizes than the obvious -d 1/2/4. You can use combinations where you use halve horizontal size and full vertical size: -d 21. This would record for NTSC at a size of 352x480. This helps if you want to create SVCDs, scaling the 352 Pixles put to 480 is not that visible for the eye as if you would use the other combination -d 12. Where you have the full horzontal resolution and half vertical this Version will have a size of 720x288 for NTSC 3.3. Some information about the typical lavrec output while recording 0.06.14:22 int: 00040 lst:0 ins:0 del:0 ae:0 td1=0.014 td2=0.029 The first part shows the time lavrec is recording. int: the interval between two frames. lst: the number of lost frames. ins and del: are the number of frames inserted and deleted for sync correction. ae: number of audio errors. td1 and td2 are the audio/video time- difference. o (int) frame interval should be around 33 (NTSC) or 40 (PAL/SECAM). If it is very different, you'll likely get a bad recording and/or many lost frames o (lst) lost frames are bad and mean that something is not working very well during recording (too slow HD, too high CPU usage, ...) Try recording with a greater decimation and possibly a lower quality. o (ins, del) inserted OR deleted frames of them are normal -> sync. If you have many lost AND inserted frames, you're asking too much of your machine. Use less demanding options or try a different sound card. o (ae) audio errors are never good. Should be 0 o (td1, td2) time differenceis always floating around 0, unless sync correction is disabled (--synchronization!=2, 2 is default). 3.4. Notes about "interlace field order - what can go wrong and how to fix it" Firstly, what does it mean for interlace field order to be wrong? The mjpegtools image processing chain is frame-oriented. Since it is video material that is captured each frame comprised of a top field (the 0th, 2nd, 4th and so lines) and a bottom field (the 1st, 3rd, 5th and so on lines). 3.4.1. There are three bad things that can happen with fields 1. This is really only an issue for movies in PAL video where each film frame is sent as a pair of fields. These can be sent top or bottom field first and sadly it's not always the same, though bottom-first appears to be usual. If you capture with the wrong field order (you start capturing each frame with a bottom rather than a top or vice versa) the frames of the movie get split *between* frames in the stream. Played back on a TV where each field is displayed on its own this is harmless. The sequence of fields played back is exactly the same as the sequence of fields broadcast. Unfortunately, playing back on a Computer monitor where both fields of a frame appear at once it looks *terrible* because each frame is effectively mixing two moments 1/25sec apart in time. 2. The two fields can simply be swapped somehow so that top gets treat as bottom and bottom treat as top. Juddering and "slicing" is the result. This occasionally seems to happen due to hardware glitches in the capture card. 3. Somewhere in capturing/processing the *order* in time of the two fields in each frame can get mislabeled somehow. This is not good as it means that when playback eventually takes place a field containing an image sampled earlier in time comes after an image sampled later. Weird "juddering" effects are the results. 3.4.2. How can I recognize if I have one of these Problems ? 1. This can be hard to spot. If you have mysteriously flickery pictures during playback try encoding a snippet with the reverse field-order forced (see below). If things improve you know what the problem was and what the solution is! 2. The two fields can simply be swapped somehow so that top gets treat as bottom and bottom treat as top. Juddering and "slicing" is the result. This occasionally seems to happen due to hardware glitches in the capture card. That problem looks like that: Interlacing problem 3. Somewhere in capturing/processing the *order* in time of the two fields in each frame can get mislabeled somehow. This is not good as it means that when playback eventually takes place a field containing an image sampled earlier in time comes after an image sampled later. Weird "juddering" effects are the result. If you use glav or lavplay be sure that you also use the -F/--flicker option. This disables some things that improve the picture. If you want to look at the video you can also use yuvplay: > lav2yuv | ... | yuvplay If there is a field order problem you should see it with yuvplay. 3.4.3. How can you fix it? 1. To fix this one the fields need to be "shifted" through the frames. Use yuvcorrect's -T BOTT_FORWARD/TOP_FORWARD to shift the way fields are allocated to frames. You can find out the current field order for an MJPEG file by looking at the first few lines of debug output from: > lav2yuv -v 2 the_mjpeg_file > /dev/null Or re-record exchanging -f a for -F A or vice-versa. 2. This isn't too bad either. Use a tool that simply swaps the top and bottom fields a second time. yuvcorrect can do this use the -T LINE_SWITCH. 3. Is easy to fix. Either tell a tool someplace to relabel the fields or simply tell the player to play back in swapped order (the latter can be done "indirectly" by telling mpeg2enc when encoding to reverse the flag (-z b|t) that tells the decoder which field order to use. In order to determine exactly what type of interlacing problem you have, you need to extract some frames from the recorded stream and take a look at them: > mkdir pnm > lav2yuv -f 40 video.avi | y4mtoppm | pnmsplit - pnm/image%d.pnm > rm pnm/image?.pnm > cd pnm > xv First we create a directory where we store the images. The lav2yuv -f 40 writes only the first 40 frames to stdout. The program y4mtoppm converts the frames to pnm images and the pnmsplit splits the picture into two frames in the picture to two single pictures. Then we remove the first 10 images because pnmsplit does not support the %0xd numbering. Without a leading zero in the number, the files will be sorted in the wrong order, leading to confusing playback. Use your favorite graphic program (xv for example) to view the pictures. As each picture only contain one field out of two they will appear scaled vertically. If you look at the pictures you should see the movie slowly advancing. If you have a film you should always see 2 pictures that are nearly the same (because the film frame is split into two field for broadcasting) after each other. You can observe this easily if you have comb effects when you pause the film because both fields will be displayed at the same time. The two pictures that belong together should have an even number and the following odd number. So if you take a look on pictures: 4 and 5 are nearly identical, 5 and 6 differ (have movement), 6 and 7 identical, 7 and 8 differ , .... To fix this problem you have to use yuvcorrect's -T BOTT_FORWARD or TOP_FORWARD. You can also have the problem that the field order (top/bottom) is still wrong. You may have to use yuvcorrect a second time with -M LINE_SWITCH, or use the mpeg2enc -z (b|t) option. To see if you guessed correctly extract the frames again and reorder them using yuvcorrect: > lav2yuv -f 40 video.avi | yuvcorrect -T OPTION | y4mtoppm | pnmsplit - pnm/image%d.pnm Where "OPTION" is what you think will correct the problem. This is for material converted from film. Material produced directly for TV is addressed below. 3.4.4. Hey, what about NTSC movies ? Movies are broadcast in NTSC using "3:2" pulldown which means that half the capture frames contain fields from 1 movie frame and half fields from 2 frames. To undo this effect for efficient MPEG encoding you need to use yuvkineco. If you have an interlaced source like a TV camera you have a frame consists of two fields that are recorded at different points in time. Spotting the problem here is harder. You need to find something moving horizontally from the left to the right. When you extract the fields, the thing should move in small steps from the left to the right, not one large step forward, small step back, large forward, small back...... You have to use the same options mentioned aboth to correct the problem. Do not expect that the field order is always the same (top- or bottom- first) It may change between the channels, between the films, and it may even change within a film. If it changes constant you may have to encode with the mpeg2enc -I 1 or even -I 2. You can only have this problems if you record at full size !!! 4. Creating videos from other sources Here are some hints and descriptions of how to create the videos from other sources like images and other video types. You might also be interested in taking a look at the Transcoding of existing MPEG-2 section. 4.1. Creating videos from images You can use jpeg2yuv to create a yuv stream from separate JPEG images. This stream is sent to stdout, so that it can either be saved into a file, encoded directly to a mpeg video using mpeg2enc or used for anything else. Saving an yuv stream can be done like this: > jpeg2yuv -f 25 -I p -j image%05d.jpg > result.yuv Creates the file result.yuv containing the yuv video data with 25 FPS. The -f option is used to set the frame rate. Note that image%05d.jpg means that the jpeg files are named image00000.jpg, image00001.jpg and so on. (05 means five digits, 04 means four digits, etc.) The -I p is needed for specifing the interlacing. You have to check which type you have. If you don't have interlacing just choose p for progressive If you want to encode a mpeg video directly from jpeg images without saving a separate video file type: > jpeg2yuv -f 25 -I p -j image%05d.jpg | mpeg2enc -o mpegfile.m1v Does the same as above but saves a mpeg video rather than a yuv video. See mpeg2enc section for details on how to use mpeg2enc. You can also use yuvscaler between jpeg2yuv and mpeg2enc. If you want to create a SVCD from your source images: > jpeg2yuv -f 25 -I p -j image%05d.jpg | yuvscaler -O SVCD | mpeg2enc -f 4 -o video.m2v You can use the -b option to set the number of the image to start with. The number of images to be processed can be specified with the -n number. For example, if your first image is image01.jpg rather than image00.jpg and you only want 60 images to be processed type: >jpeg2yuv -b 1 -f 25 -I p -n 60 -j image*.jpg | yuv2lav -o stream_without_sound.avi Adding the sound to the stream then: > lavaddwav stream_without_sound.avi sound.wav stream_with_sound.avi For ppm input there is the ppmtoy4m util. There is a manpage for ppmtoy4m that should be consulted for additional information. To create a mpeg video try this: >cat *.ppm | ppmtoy4m -o 75 -n 60 -F 25:1 | mpeg2enc -o output.m1v cat each *.ppm file to ppmtoy4m. There the first 75 frames (pictures) are ignored and next 60 are encoded by mpeg2enc to output.m1v. You can run it without the -o and -n option. The -F options sets the frame rate, default is NTSC (30000:1001), for PAL you have to use -F 25:1. Other picture formats can also be used if there is a converter to ppm. >ls *.tga | xargs -n1 tgatoppm | ppmtoy4m | yuvplay A list of filenames (ls *.tga) is given to xargs that executes the tgatoppm with one (-n 1) argument per call, and feeds the output into ppmtoy4m. This time the video is only shown on the screen. The xargs is only needed if the converter (tgatoppm) can only operate on a single image at a time. If you want to use the ImageMagick 'convert' tool (a Swiss Army Knife) try: >convert *.gif ppm:- | ppmtoy4m | yuvplay That means take all '.jpg' images in directory, convert to PPM format, pipe to stdout, then to ppmtoy4m for conversion to y4m .... 4.2. Decoding streams with mplayer Decoding the streams with mplayer is a nice way of bringing every video that mplayer can play back to something you can edit or encode to mpeg with mjpegtools. This method has been tested with mplayer 1.0rc2 and should work with newer versions >mkfifo stream.yuv >cat stream.yuv | yuv2lav -o mjpeg_wo.avi & >mplayer -nosound -noframedrop -vo yuv4mpeg anyfile.mpg >mplayer -vo null -ao pcm:file=anyfile.wav anyfile.mpg Now you have an example of a mjpeg encoded AVI without sound. The sound will be in anyfile.wav. You can choose if you want to add the sound to the AVI with lavaddwav and edit the file before encoding. You can also use instead of yuv2lav, mpeg2enc or any other tool from the mjpeg tools so your command might also look like that: > cat stream.yuv | yuvdenoise | yuvscaler -O SVCD | mpeg2enc -f 4 -o video_svcd.m2v cat the wav file into mp2enc to encode it to MP2 audio. The -vo yuv4mpeg option works well with other input types mentioned in the mplayer documentation. 4.3. Decoding MPEG-2 streams with mpeg2dec You can decode mpeg2 streams with the patched mpeg2dec version which creates yuv streams. You can pipe that into any other mjpegtools program. Or you use a mpeg2dec version directly from the libmpeg2 project and use the output mode pgmpipe. With the pgmtoy4m program you can convert that pgm output back to yuv. If you ask yourself why there is a patched version and pgmtoy4m. The answer is that the patch for yuv output was sent several times to the libmpeg2 developers but was never included. Now we have two ways around that problem. Decoding looks like this: > mpeg2dec -s -o pgmpipe ANYTS.VOB | pgmtoy4m -i t -a 10:11 -r 30000:1001 | mpeg2enc -f 8 newvideo.m2v You can decode the audio as described in the Transcoding of existing MPEG-2 Section. 4.4. Other things to know If you have Transport streams from your DVB card, or Satelite Receiver you might want to demultiplex or cut them. A nice tool for that is Project X available from: http://www.lucike.info/page_projectx.htm You can process the streams afterwards as you would do with any mpeg movie or demultiplexed audio video. So the Transcoding of existing MPEG-2 section of this document will be of interest. 5. Checking if recording was successful You can use lavplay or glav. IMPORTANT: NEVER try to run xawtv and lavplay or glav with hardware playback, it will not work. For software playback it works fine. >lavplay -p S record.avi You should see the recorded video and hear the sound. But the decoding of the video is done by the CPU which will place a heavy load on the system. The advantage of this method is you don't need xawtv. The better way: >lavplay -p H record.avi The video is decoded and played by the hardware. The system load is very low. This will play it back on-screen using the hardware rather than software decoding. You might also try: > lavply -p C record.avi Which will play it back using the hardware but to the video output of the card. > glav record.avi Does the same as lavplay but you have an nice GUI. The options for glav and lavplay are nearly the same. Using no option SW playback is used. Using hardware playback a signal for the Composite and SVHS OUT is generated so you can view the movie on your TV. > lav2yuv test.eli | yuvplay Is a other way to get the video without sound. You can use yuvplay once in the encoding command. When you use yuvplay in the encoding command you see the changes made by filters and scaling. You can also use it for slow-motion debugging. NOTE: After loading the driver's you have to start xawtv to set up some things lavplay and glav do not, but they are needed for HW- Playback. Don't forget to close xawtv !! NOTE2: Do not try to send glav an lavplay into background, wont work correct !!! NOTE3: SECAM playback is now (12.3.2001) only in monochrome but the recording and encoding is done right. NOTE4:Bad cables may reduce the quality of the image. Normally you can't see this but when there is text you might notice a small shadow. When you see this you should change the cable. Coming soon: There is a tool which makes recoding videos very simple: Linux Studio. You can download it at: http://ronald.bitfreak.net 6. Edit the video 6.1. Edit with glav Most tasks can be easily done by glav. Like deleting parts of the video, cut paste and copy parts of the videos. glav button description The modifications should be saved because glav does not destructively edit the video. This means that the original video is left untouched and the modifications are kept in an extra "Edit List" file readable with a text editor. These files can be used as an input to the other lavtools programs such as lav2wav, lav2yuv, lavtrans. If you want to cut off the beginning and the end of the stream mark the beginning and the and, and use the "save select" button. The edit list file is than used as input for the lavtools. If you want to split a recorded video to some smaller parts simply select the parts and then save each part to a different listfile. You can see all changes to the video and sound NOW and you do not need to recalculate anything. If you want to get a "destructive" version of your edited video use: > lavtrans -o short_version.avi -f a editlist.eli -o specifies the output name -f a specifies the output format (AVI for example) editlist.eli is the list file where the modifications are described. You generate the list file with the "save all" or "save select" buttons in glav. 6.2. Unify videos > lavtrans -o stream.qt -f q record_1.avi record_2.avi ... record_n.avi -o specifies the outputfile name -f q specifies the output format, quicktime in this case This is usually not needed. Keep in your mind that there is a 2GB file-size-limit on 32Bit systems with an older glibc. Usually not a problem these days 6.3. Separate sound > lavtrans -o sound.wav -f w stream.avi Creates a wav file with the sound of the stream.avi Maybe needed if you want to remove noise or if you want to convert it to another sound format. Another way to split the sound is: > lav2wav editlist.eli >sound.wav 6.4. Separate images >mkdir jpg; lavtrans -o jpg/image%05d.jpg -f i stream.avi First create the directory "jpg". Then lavtrans will create single JPG images in the jpg directory from the stream.avi file. The files will be named: image00000.jpg, image00001.jpg .... The jpg images created contain the whole picture. But if you have recorded at full size the images are stored interlaced. Usually the picture viewers show only the first field in the jpg file. If you want to have the image in a single file you can use that version > lav2yuv -f 1 stream.avi | y4mtoppm -L >file.pnm If you want to split the fields into single files use that: > lav2yuv -f 5 ../stream.avi | y4mtoppm | pnmsplit - image%d.pnm Maybe interesting if you need sample images and do not want to play around with grabbing a single image. 6.5. Creating movie transitions Thanks to Philipp Zabel's lavpipe we can now make simple transitions between movies or combine multiple layers of movies. Philipp wrote this HOWTO on how to make transitions: Let's assume simple this scene: We have two input videos intro.avi and epilogue.mov and want to make intro.avi transition into epilogue.mov with a duration of one second (that is 25 frames for PAL or 30 frames for NTSC). Intro.avi and epiloque.mov have to be of the same format (the same frame rate and resolution). In this example they are both 352x288 PAL files. intro.avi contains 250 frames and epilogue.mov is 1000 frames long. Therefore our output file will contain: the first 225 frames of intro.avi a 25 frame transition containing the last 25 frames of intro.avi and the first 25 frames of epilogue.mov the last 975 frames of epilogue.mov We could get the last 25 frames of intro.avi by calling: >lav2yuv -o 225 -f 25 intro.avi -o 255, the offset, tells lav2yuv to begin with frame # 225 and -f 25 makes it output 25 frames from there on. Another possibility (because negative offsets are counted from the end)is: > lav2yuv -o -25 intro.avi And the first 25 frames of epilogue.mov: > lav2yuv -f 25 epilogue.mov -o defaults to an offset of zero But we need to combine the two streams with lavpipe. So the call would be: > lavpipe "lav2yuv -o 255 -f 25 intro.avi" "lav2yuv -f 25 epilogue.mov" The output of this is a raw yuv stream that can be fed into transist.flt. transist.flt needs to be informed about the duration of the transition and the opacity of the second stream at the beginning and at the end of the transition: -o num opacity of second input at the beginning [0-255] -O num opacity of second input at the end [0-255] -d num duration of transition in frames An opacity of 0 means that the second stream is fully transparent (only stream one visible), at 255 stream two is fully opaque. In our case the correct call (transition from stream 1 to stream 2) would be: > transist.flt -o 0 -O 255 -d 25 The -s and -n parameters equate to the -o and -f parameters of lav2yuv and are only needed if anybody wants to render only a portion of the transition for whatever reason. Please note that this only affects the weighting calculations - none of the input is really skipped. If you use the skip parameter (-s 30, for example) you also need to skip the first 30 frames in lav2yuv (-o 30) in order to get the expected result. If you didn't understand this send an email to the authors or simply ignore -s and -n. The whole procedure will eventually be automated. Now we want to compress the yuv stream with yuv2lav: > yuv2lav -f a -q 80 -o transition.avi Reads the yuv stream from stdin and outputs an avi file (-f a) with compressed jpeg frames of quality 80. Now we have the whole command for creating a transition: > ypipe "lav2yuv -o 255 -f 25 intro.avi" "lav2yuv -f 25 epilogue.mov" | transist.flt -o 0 -O 255 -d 25 | yuv2lav -f a -q 80 -o transition.avi The resulting video can be written as a LAV Edit List (a plain text file) containing the following lines: LAV Edit List PAL 3 intro.avi transition.avi epilogue.mov 0 0 224 1 0 24 2 25 999 This file can be fed into glav or lavplay, or you can pipe it into mpeg2enc with lav2yuv or combine the whole stuff into one single mjpeg file with lavtrans or lav2yuv|yuv2lav. 7. Converting the stream to MPEG or DIVx videos First there is some general description in the encoding process and afterwards there is a detailed description of some commonly used output formats. If you want a one command conversation to mpeg videos try lav2mpeg in the scripts directory The encoding with the lav2mpeg script looks like this for mpeg1 output: >lav2mpeg -a 160 -b 2110 -d 320x240 -m mpeg1 -o output.mpg file.eli o Will create a mpeg1 with videobitrate of 2110kBit/sec and audiobitrate of 160 kBit/sec o at a resolution of 320x240 Or for the generation of mpeg2 output: lav2mpeg -o mpeg2 -O output.mpg file.eli o Will create a mpeg2 with default bitrate in same resolution as the input resolution Better results can be accomplished, however, by trying various options and find out which ones work best for you. These are discussed below. The creation of MPEG-1 movies is explained with more examples and in greater detail because most of the things that can be used for MPEG-1 also work for the other output formats For the creation of of VCD/SVCD Stills sequences (-f 6 / -f 7 in mpeg2enc) you should see: http://www.mir.com/DMG/ Still sequences are needed for the creation of menus in VCD/SVCD. The creation of menus is described in the doku of vcdimager. 7.1. Creating sound MPEG-1 videos need MPEG-1-Layer2 (MP2) sound files. For MPEG-2 videos you can use MPEG-1-Layer2 and MPEG1-Layer3 (MP3). MP3 audio is not an offically valid audio format but many VCD players will recognize it. MP3 audio is not valid for DVDs. You should stick to MP2 because many of the MPEG-2 players (DVD Player for example, usually the Windows Versions have great problems with this too) are not able to play MPEG2-Video and MP3 sound. mp2enc is a MP2 Audio encoder. The toolame encoder is also able to produce an MP2 file. Toolame is much faster than mp2enc but toolame does not peform resampling (48000 to 44100 samples/second). Many hardware players will play SVCDs using 48000 rate audio. For MP3 creation I'm be sure you have an encoder. Example: > lav2wav stream.avi | mp2enc -o sound.mp2 This creates a mpeg sound file out of the stream.avi with 224kBit/sec bitrate and a sample rate of 48kHz. If you audio file has 44.1kHz mp2enc resamples the audio to create a 48kHz output. If you want a 44.1kHz output sample rate you have to add -r 44100 to the mp2enc command Example > cat sound.wav | mp2enc -v 2 -V -o sound.mp2 This creates a VCD (-V bitrate=224, stereo, sampling rate:44100) compatible output from the wav file. With -v 2 mp2enc is more verbose, while encoding you see the number of sec of audio already encoded. You can test the output with: > plaympeg sound.mp2 NOTE: plaympeg is a MPEG-1 Player for Linux, you can use other players as wellr. For audio testing you can also use mpg123. For both audio and video playing there are the universal player like VLC mplayer and others. 7.2. Converting video Creating MPEG-1 and MPEG-2 videos. Normally the first video you create is not the best. For optimal quality/size you need to play with the bitrate, search radius, noise filter .... The options of mpeg2enc are described in the manpage of mpeg2enc. Example: lav2yuv stream.avi stream1.avi | mpeg2enc -o video.m1v This creates an video file with the default constant bitrate of 1152kBit/sec. This is the bitrate you need if you want to create VCDs. You can specify more files and also use the placeholder %nd. Where n describes the number. By default mpeg2enc assumes that you want to encode a not interlaced video to Mpeg-1. If you want to encode a full size video with interlacing that command above will fail. Example: > lav2yuv streami%02d.avi | mpeg2enc -b 1500 -r 16 -o video.m1v mpeg2enc creates a video with a bitrate of 1500kBit/s uses an search radius of 16. That means when trying to find similar 16*16 macroblocks of pixels between frames the encoder looks up to 16 pixels away from the current position of each block. It looks twice as far when comparing frames 1 frame apart and so on. Reasonable values are 16 or 24. The default is 16 so adding the option here is useless. Lower values (0, 8), improve the encoding speed but you get lower quality (more visible artifacts) while higher values (24, 32) improve the quality at the cost of the speed. With the file description of stream%02d.avi all files are processed that match this pattern with 00, 01.... 7.2.1. Scaling Using yuvscaler one can now also scale the video before encoding it. This can be useful for users with a DC10 or DC10+ cards which captures at -d 1 768x576 or -d 2 384x288 (PAL/SECAM) or -d 1 640x480 (NTSC). You get a full description of all commands by reading the manpage or running: >yuvscaler -h Example: > lav2yuv stream.avi | yuvscaler -O VCD | mpeg2enc -o video.m1v This will scale the stream to VCD size which for PAL/SECAM is 352x288 and for NTSC is 352x240. The scaled yuvstream is encoded to MPEG-1. It can also do SVCD scaling to 480x480 (NTSC) or 480x576 (PAL/SECAM): > lav2yuv stream.avi | yuvscaler -O SVCD -M BICUBIC | mpeg2enc -o video.m1v The mode keyword (-M) forces yuvscaler to use the higher quality bicubic algorithms for downscaling and not the default resample algorithms. Upscaling is always done using the bicubic algorithm. Example: > lav2yuv stream.avi | yuvscaler -I USE_450x340+20+30 -O SIZE_320x200 | mpeg2enc -o video.m1v Here we only use a part of the input and specify a nonstandard output resolution. NOTE: yuvscaler can set a active area, and set everything else to black using: -I ACTIVE_WidthxHeight+WidthOffset+HeightOffset 7.2.2. High quality scaling: y4mscaler y4mscaler has been arround for quite some time. But it was for a quite long time a extra tool you needed to compile. There is a comprehensive manpage explaining all the details, there also a lot fo helpful information on the website: Digital Media Group: Video Library http://www.mir.com/DMG/ One unique feature is that is it able to change the subsampling, and Choma Modes. And you can choose the scaler kernels, depending on the source that can help a lot. Example: > cat raw.yuv | y4mscaler -O infer=CLIP -O preset=DVD -O sar=PAL_Wide | mpeg2enc video.m1v In this example y4mscaler will take the input stream and scale it to the coresponding PAL size. The sar option tell to scale is to a wide format (16:9). The infer=clip option will tells y4mscaler that it can clip the top and bottom bars away to scale it to the resulting size. Example: > mpeg2dec -o pgmpipe deluxe.m2v | pgmtoy4m -x 420jpeg -r 25:1 -i t | y4mscaler -I sar=64:36 -I active=344x476+100+48 -O preset=DVD | mpeg2enc -f 8 video.m1v This is a more the job for y4mscaler. We have a weird PAL MPEG source format with 544x576 pixels in a wide screen 16:9 format, that makes black bars all around the original 4:3 image. This command scales the image up to a original 4:3 size, and takes just the interesting center. The SAR is the sample aspect ratio get lost somewhere so we specify it in the beginning. So it is specified again, than you tell y4mscaller the active size of the picture it shall use to scale up. The active keyword is treated different in y4mscaler and yuvscaler. The DVD is a preset for the output format you want. From the stream parameters y4mscaler knows that it is a PAL stream and the output parameters. If you wanted a 16:9 output you would have to use the keyword: DVD_WIDE. Testing is done by: > mplayer video.m1v NOTE:These are only examples. There are more options you can use. You can use most of them together to create high quality videos with the lowest possible bitrate. NOTE2:The higher you set the search radius the longer the conversion will take. In general the more options used the longer encoding takes. NOTE3:MPEG-1 was not designed to be a VBR (variable bitrate stream) !! So if you encode with -q 15 mpeg2enc sets the maximal bitrate -b to 1152. If you want a VBR MPEG-1 you have to set -b very high (2500). NOTE4:Maybe you should give better names than video.mpg. A good idea is to use the options as part of the filename (for example: video_b1500_r16_41_21.m1v). Another possibility is to call all the layer 2 audio files ".mp2" all the MPEG-1 video files ".m1v" and all MPEG-2 video files ".m2v" Easy to see what's happening then. Reserve .mpg for multiplexed MPEG-1/2 streams. 7.3. Putting the streams together Example: > mplex sound.mp2 video.m1v -o my_video.m1v Puts the sound.mp2 and the video.m1v stream together to my_video.mpg Now you can use your preferred MPEG player and watch it. All players (gtv for example) based on the SMPEG library work well for MPEG-1. Other players (which can play MPEG-2 as well as MPEG-1 movies) are: xmovie, xine, and MPlayer VLC, to name some. NOTE: If you have specified the -S option for mpeg2enc mplex will automatically split the files if there is in the output filename a %d (looks like: -o test%d.mpg) The files generated this way are separate stand-alone MPEG steams! NOTE2: xine might have a problem with seeking through videos. mplayer has a problem with the "seek backward/forward" with variable bitrate streams because it goes forward in the file the amount of data for a constant bitrate stream. That amount might be significantly more than 10 seconds or one minute (those are the amount mplayer seeks for each press of the arrow keys). So don't wonder if it seeks much more time forward or backward than you expect. Variable bit-rate multiplexing: Remember to tell mplex you're encoding VBR (-V option) as well as mpeg2enc (see the example scripts). It *could* auto-detect but it is not working yet. You should tell mplex a video buffer size at least as large as the one you specified to "mpeg2enc" Sensible numbers for MPEG-1 might be a ceiling bit-rate of 2800Kbps, a quality ceiling (quantization floor) of 6 and a buffer size of 400K. Example: > mplex -V -r 1740 audio.mp2 video_vbr.m1v -o vbr_stream.mpg Here we multiplex a variable bitrate stream. mplex is a single pass multiplexer so it can't detect the maximal bitrate and we have to specify it. The data rate for the output stream is: audio bitrate + peak videobitrate + 1-2% for mplex information. If audio (-b 224) is 224kBit and the video is 1500kBit (encoded with -b 1500 -q 9) then we have 1724 * 1.01 or about 1740kBit. Example: > plaympeg my_video.mpg or > mplayer my_video.mpg 7.4. Creating MPEG-1 Videos For MPEG-1 videos you can use MP2 audio and MPEG-1 video. A subset of MPEG-1 movies are VCD's. You can use VBR (Variable BitRate) for the Video (although VCDs are almost always use CBR video) but the Audio has to be CBR (Constant BitRate). MPEG-1 is recommended for picture sizes up to 352x288 for PAL and 352x240 for NTSC for larger sizes MPEG-2 is the better choice. There is no exact resolution where MPEG-1 is better than MPEG-2. Just to make soure, MPEG-1 can't handle interlaced sources. If you video is interlaced you need MPEG-2 to get it proper encoded. 7.4.1. MPEG-1 Audio creation Example > lav2wav editlist.eli | mp2enc -r 44100 -o sound.mp2 You can save some bits by telling mp2enc to use a lower bitrate (-b option) like 160 or 192 kBit/s. The -r 44100 option forces mp2enc to generate a 44.1kHz audio file. > lav2wav editlist.eli | mp2enc -b 128 -m -o sound.mp2 This creates a mono output with an bitrate of 128kBit/sec bitrate. The input this time is the editlistfile (can have any name) created with glav so all changes you made in glav are direct processed and handed over to mp2enc. You do NOT have to create an edited stream with lavtrans to get it converted properly. 7.4.2. MPEG-1 Video creation example > lav2yuv editlist.eli | mpeg2enc -b 2000 -r 24 -q 6 -o video.m1v mpeg2enc creates an video with an bitrate of 2000kBit/s (or 2048000Bit/s) but the -q flag activates the variable bitrate and a quality factor of 6. It uses a search radius of 24. Explanation:when mpeg2enc is invoked without the 'q' flag it creates "constantbit-rate" MPEG streams. Where (loosely speaking) the strength of compression (and hence picture quality) is adjusted to ensure that on average each frame of video has exactly the specified number of bits. Such constant bit-rate streams are needed for broadcasting and for low-cost hardware like DVD and VCD players which use slow fixed- speed player hardware. Obviously this is fairly inefficient as it means inactive scenes use up bits that could better be "spent" on rapidly changing scenes. Setting the 'q' flag tells mpeg2enc to generate variable bit-rate streams. For such streams the bit-rate specified is simply the maximum permissible. The 'q' parameter specifies the minimum degree of compression to be applied by specifying how exactly picture information is recorded. Typically 'q' would be set so that quiet scenes would use less than the specified maximum (around 6 or 8) but fast moving scenes would still be bit-rate limited. For archival purposes setting a maximum bit-rate high enough never to be reached (e.g. 10Mbps) and a q of 2 or 3 are reasonable choices. Example: > lav2yuv stream.avi | yuvscaler -I ACTIVE_352x240+0+24 | mpeg2enc -b 1152 -r 16 -4 1 -2 1 -o video.m1v Usually there is at the top and at the bottom a nearly black border and a lot of bandwidth is used for something you do not like. The yuvscaler -I ACTIVE option sets everything that is not in the described area to black but the imagesize (352x288) is not changed. So you have a real black border the encoder only uses a few bits for encoding them. You are still compatible with the VCD's format in this example. To determine the active window extract one frame to the jpeg format: > lavtrans -f i -i 100 -o frame.jpg test.avi Than use your favorite graphic display program to determine the active size. The -4 1 and -2 1 options improves the quality about 10% but conversion is slower. At the size of 352x288 (1/2 PAL size created when using the -d 2 option when recording) the needed bitrate is/should be between 1000 - 1500kBit/s. For NTSC it should be about the same, because the image is smaller but there are more frames per second than in PAL. Anyways, the major factor is quality of the original and the degree of filtering. Poor quality unfiltered material typically needs a higher rate to avoid visible artifacts. If you want to reduce bit-rate without annoying artifacts when compressing broadcast material you should try one (or more) of the noise filters. Example: > lav2yuv stream.avi | mpeg2enc -b 1500 -n s -g 6 -G 20 -P -o video.m1v Here the stream.avi will be encoded with: -b 1500 a Bitrate of 1500kBit/sec -n s the input Video norm is forced to SECAM -P This ensures that 2 B frames appear between adjacent I/P frames. Several common MPEG-1 decoders can't handle streams that do not have 2 B-frames between I/P frames -g 6 -G 20 the encoder can dynamically change the group-of-pictures size to reflect scene changes. This is done by setting a maximum GOP (-G flag) size larger than the minimum (-g flag). For VCDs sensible values might be a minimum of 9 and a maximum of 15. For SVCD 9 and 15 would be good values. If you only want to play it back on SW player you can use other min-max values. Example: > lav2yuv stream*.avi | mpeg2enc -b 1500 -r 16 -4 1 -2 1 -S 630 -B 260 -o video_n1_1500_r16_41_21_S630_B240.m1v lav2yuv processes all the stream files. Then mpeg2enc is given some options that make the encoded stream look nicer. Using -S 630 means that mpeg2enc marks the stream so that mplex generates a new stream every 630MB. One important thing is the use of the -B option which specifies the non-video (audio and mplex information) bitrate. The -B value of 260 should be fine for audio with 224kBit and mplex information. For further information take a look at the encoding scripts in the scripts directory. 7.4.3. MPEG-1 Multiplexing Example Example: >mplex sound.mp2 video.m1v -o my_video.mpg Puts the sound.mp2 and the video.m1v stream together to my_video.mpg. It only works that easy if you have CBR (the -q option was not used with mpeg2enc). Example: mplex -V -r 1740 audio.mp2 video_vbr.m1v -o vbr_stream.mpg Here we multiplex a variable bitrate stream. mplex is now a single pass multiplexer so it can't detect the maximal bitrate and we have to specify it. The data rate for the output stream is: audio bitrate + peak videobitrate + 1-2% for mplex information. If audio (-b 224) has 224kBit, video has 1500kBit (was encoded with -b 1500 -q 9) then we have 1724 * 1.01 or about 1740kBit. 7.5. Creating MPEG-2 Videos MPEG-2 is recommended for sources with a greater picture than 352x240 for NTSC and 352x288 for PAL. MPEG-2 can also handle interlaced sources like recording from TV at full resolution. MPEG-2 allows the usage of mpeg layer 3 (mp3) sound. So you can use your favorite mp3encoder for the creation of the sound. However, MP3 audio is not valid for DVDs. It is best to use MP2 (Layer 2) audio. The audio can also be a VBR stream. MPEG-2 is usually a VBR stream. MPEG-2 creation with optimization requires a lot of CPU power. A film with the double resolution is NOT 4 times larger than an MPEG-1 stream. Depending on your quality settings it will be about 1.5 up to 3 times larger than the MPEG-1 stream at its lower resolution. 7.5.1. MPEG-2 audio creation example > lav2wav editlist.eli | mp2enc -o sound.mp2 You can save some bits by telling mp2enc to use a lower bitrate (-b option) like 160 or 192 kBit/s. You might want to add -r 44100 so that mpeg2enc generates 44.1kHz sampling rate audio. I hope I don't need to explain the usage of an MP3 Encoder. But you should not use all the fancy options that are available. 7.5.2. MPEG-2 Video creation example > lav2yuv editlist.eli | mpeg2enc -f 3 -b 3000 -q 9 -o video.m2v A very simple example for MPEG-2 Video. The most important option is the -f 3. That tells mpeg2enc that it should create a MPEG-2 stream. Because it is a generic MPEG-2 you have to use the -b bitrate options. And should use the -q option because you usually want a space saving VBR stream. When using VBR streams the -b option tells mpeg2enc the maximum bitrate that can be used. The -q option tell mpeg2enc what quality the streams should have. The bitrate has an upper bound of the value specified by -b. > lav2yuv editlist.eli | mpeg2enc -f 3 -4 1 -2 1 -q7 -b 4500 -V 300 -P -g 6 -G 18 -I 1 -o video.m2v This will generate a higher quality MPEG-2 stream because the -4 1 and -2 1 options were used. With -b 4500 -q 7 you tell mpeg2enc the maximal bitrate and the quality factor. -V is the video buffer size used for decoding the stream. For SW playback it can be much higher than the default. Dynamic GOP is set with -g and -G. A larger GOP size can help reduce the bit-rate required for a given quality but very large sizes can introduce artifacts due to DCT/iDCT accumulated rounding errors. The -P option also ensures that 2 B frames appear between adjacent I/P frames. The -I 1 option tells mpeg2enc that the source is a interlaced material like videos. There is (time consuming) interlaced motion compensation logic present in mpeg2enc. Mpeg2enc will use that logic if the size of the frames you encode is larger than the VCD size for your TV Norm. If you deinterlacing the movie with yuvdeinterlace you should tell mpeg2enc that it does not need to do motion estimation for interlaced material. You have to use the -I 0 option of mpeg2enc to say that the frames are already deinterlaced. This will save a lot of time when encoding. If you don't use -I 0 it will not cause problems, the encoding will just take longer. You can also use scaling an options that optimize (denoise) the images to get smaller streams. These options are explained in detail in the following sections. 7.5.2.1. Which values should be used for VBR Encoding? The -q option controls the minimum quantization of the output stream. Quantization controls the precision with which image information is encoded. The lower the value the better the image quality. Values below 4 are extremes and should only be used if you know what you are doing Usually you have to set up a maximum bitrate with the -b option. The tricky task is to set a value for the -q option and the -b option that produces a nice movie without using too much bandwidth and does not introduce too many artifacts. A quality factor should be chosen that way that the mplex output of Peak bit-rate and average bit-rate differ by about 20-25%. If the difference is very small (less than < 10%) it is likely that you will begin to see artifacts in high motion scenes. The most common cause of the average rate being too close (or equal) to the maximum rate is wrong value for the maximal bitrate or a quality factor that is too high. A combination that will produce more artifacts than you can count is a SVCD with a maximal video bitrate of 2500kBit and a quality factor of 1 or 2. For SVCD with a video limit of 2500kBit a quality factor of 7-11 fits quite good (8 is the default). If you use filter programs or have a very good source like digital TV, DVD like material or rendered pictures you can use a quality factor of 6 when creating SVCDs. If your SVCD/DVD player supports non-standard bitrates you can increase the bitrate above the standard maximum of 2788 kBit/sec (video plus audio). When using a higher bitrate and quality factor action scenes will look much better but of course the playing time of the disc will be less. The same (7-11) quality factor for a full size picture and a top bitrate of 3500 to 4000 kBit will produce few artifacts. For SVCD/DVD you can expect a result like the one described if the maximal bitrate is not set too low: q <= 6 real sharp pictures, and good quality q <= 8 good quality q >= 10 average quality q >= 11 not that good q >= 13 here even still sequences might look blocky 7.5.2.2. Encoding destination TV (interlaced) or Monitor (progres- sive) MPEG-2 supports interlaced data in addition to the progressive format. A MPEG-2 movie can be interlaced or progressive. It depends on the source (film or broadcast) and on the viewing device. If you encode a film both fields should be the same. Deinterlace the stream with yuvdeinterlace, or if you have a high quality source, and don't need to use the denoiser with yuvcorrect -T NOT_INTERLACED. Also set the mpeg2enc interlace-mode (-I) option to 0. This means that there is no interlacing. We do not really need deinterlacing here because there is no motion between the fields of the frame. We only need to unite the two fields into a single progressive frame. This movie should play back an any device (TV or Monitor) without problems. If you have an interlaced source (broadcast) you can encode it as interlaced stream. Or deinterlace the stream and encode it as progressive stream. If you deinterlace it with yuvdeinterlace you will lose details. But if you plan to play the recorded stream on your DVD player and your TV it would not be wise to perform deinterlacing. If you only want to play it back on the Monitor (progressive display) the picture looks better when playing it back if it is deinterlaced. If the player you use can do deinterlacing it does not matter if your encoded video has interlaced frames or progressive frames. If you plan to deinterlace the stream you can only do this with yuvdeinterlace and set the mpeg2enc -I 0. If you do not want to deinterlace the stream you do not need to set any special option (do not use yuvdeinterlace and mpeg2enc -I 0) If you like to pause the stream and look on the still you should deinterlace. Because then the image is flicker free when pausing. If you have a film (progressive) with parts from a broadcast (interlaced) mixed together (like in a documentary where some parts from a speaker are recorded interlaced and other parts are filmed) you have to choose between good film sequences with average still images or average looking film sequences with good still images. For good film with average stills do not deinterlace. For average film sequences with good stills then deinterlace (using yuvdeinterlace and mpeg2enc -I 0). 7.5.3. MPEG-2 Multiplexing example > mplex -f 3 -b 300 -r 4750 -V audio.mp3 video.m2v -o final.mpg Now both streams (a mp3 audio and a mpeg2 video) are multiplex into a single stream (final.mpg). You have to use the -f 3 option to tell mplex the output format. You also have to add the -b decoder buffers size option with the same value used when encoding the video. -r is that rate of video + audio +1-2% of mplex information. The -Voption tells that your source for mplexing is a VBR stream. If you don't use this option mplex creates something like a CBR stream with the bitrate you have told it with the -r option. These streams are usually get BIG. 7.6. Creating Video CDs (VCDs) VCD is a constrained version of MPEG-1 video. VCD format was defined by Philips. The goal was to use a single speed CD-drive and other cheap hardware (not flexible) to have a cheap HW-Player. Because of that there are limitations for video and audio used to make a VCD. The bitrate for video is 1152kBit and 224kBit/sec MP2 audio. You are not allowed to use the -q option, dynamic GOP sizes and the video buffer is limited to 46kB. The image size is limited to 352x240 for NTSC, an to 352x288 for PAL. If you have no VCD (only) player and you plan to use your DVD player then it is quite possible that the DVD player will be flexible enough to allow higher bitrates, dynamic GOP sizes, larger video buffer and so on 7.6.1. VCD Audio creation Example > lav2wav stream.avi | mp2enc -V -o sound.mp2 -V force VCD 2.0 compatible output. There the audio samplerate is fixed to 44.1kHz. And you can choose the audio bitrate for mono audio to be 64, 96 or 192kBit/sec. If you have stereo audio you can choose 128, 192, 224 or 384kBit/sec. For hardware players, you should stick to 44.1 224kBps Stereo layer 2 Audio. 7.6.2. VCD Video creation Example > lav2yuv stream.avi | yuvscaler -O VCD | mpeg2enc -f 1 -r 16 -o video.mpg For VCD compatible output the -f 1 sets all options in mpeg2enc as needed. It seems that many VCD players (Avex for example) are not able to play MPEG streams that are encoded with a search radius greater than 16 so do not use the -r option to override the default of 16. > lav2yuv streams.eli | mpeg2enc -f 1 -4 1 -2 1 -S 630 -B 260 -P -o video.m1v Using '-S 630' means that mpeg2enc marks the stream so that mplex generates a new stream every 630MB. One important thing is the use of the -B option which specifies the non-video (audio and mplex information) bitrate. The -B value of 260 should be fine for audio with 224kBit and mplex information. For further information take a look at the encoding scripts in the scripts directory. The multiplexed streams should easily fit on a 650MB CD. The default value (-B) is 700MB for the video. mpeg2enc marks automatically every stream at that size if the -B option is not used to set a different value. If you have a CD where you can write more data (perhaps as much as 800MB) you have to set the -S option or otherwise mpeg2enc will mark the stream at 700 MB, and mplex will split the stream there. Which is almost certainly not what you want. 7.6.3. VCD Multiplexing Example > mplex -f 1 sound.mp2 video.mpg -o vcd_out.mpg The -f 1 option turns on a lot of weird stuff that otherwise has no place in a respectable multiplexer! 7.6.4. Creating the CD The multiplexed streams have to be converted to an VCD compatible. This is done by vcdimager http://www.vcdimager.org/ > vcdimager testvideo.mpg Creates a videocd.bin, the data file, and a videocd.cue which is used as control file for cdrdao. You use cdrdao to burn the image. Cdrdao is yet another fine Sourceforge project which is found at: http://cdrdao.sourceforge.net/ 7.6.5. Notes For MPEG-1 encoding a typical (45 minute running time) show or 90 odd minute movie from an analog broadcast a constant bit-rate of around 1800 kBit/sec should be ideal. The resulting files are around 700M for 45 minutes which fits nicely as a raw XA MODE2 data track on a CD-R. For pure digital sources (DTV or DVD streams and similar) VCD 1152 works fine. Note: If you encode VBR MPEG-1 (-q) remember the Hardware was probably not designed to do the playback because it is not in the specifications. If it works be very happy. I've noticed that it helps when you have an MPEG-1 stream to tell vcdimager that it is an SVCD. vcdimager complains (but only with a warning and not a fatal error) but you should be able to burn it. This could convince the player to use different routines in its firmware and play it back correct but there is no guarantee of that. 7.6.6. Storing MPEGs If you record the data as XA mode 2 tracks you can fit appreciably more on a CD (at the expense of error correction/detection). You can use vcdimager to do this and vcdxrip (part of the vcdimager package) to extract ("rip") the resulting files. For better Quality there are SVCD and XVCD and DVD. Currently SVCD is fully supported with a pre-set format in mplex and tools to create disks. MPEG streams that can be played by DVD player hardware and software can readily produced using mpeg2enc/mplex If your player doesn't support SVCD you may well find it can handle VCD streams that have much higher than standard bit-rates. Often as much as 2500kBit/sec is possible. The several brands of DVD players can also play wildly out of spec SVCD and VCD discs. With higher bit- rates and good quality source material it is worth trying mpeg2enc's -h flag which produce a stream that is as sharp as the limits of the VCD standard permits. However, if your player supports it and you have the patience for the longer encoding times SVCD is a much better alternative. Using a more efficient MPEG format SVCD more than doubles VCD's resolution while typically producing files that are less than twice as big. 7.7. Creating SVCD Super Video CD (SVCD) is an enhancement to Video CD that was developed by a Chinese government-backed committee of manufacturers and researchers. The final SVCD spec was announced in September 1998. A good explanation of the SVCD format from Philips can be found here: http://lipas.uwasa.fi/~f76998/video/svcd/overview/. Record at full TV resolution (means: -d 1 for PAL this is 720x576) The resolution is for NTSC is 480x480 of PAL 480x576, so you know why you should record at full size. 7.7.1. SVCD Audio creation Example > lav2wav stream.avi | mp2enc -V -e -o sound.mp2 The SVCD specifications permit a much wider choice of audio rates, it is not necessary to use 224 kBit/sec. Any audio rate between 32 and 384 kBit/sec is permitted. The audio may be VBR (Variable Bit Rate). The -e enables the CRC error protection for the audio. The CRC has to be enabled to be SVCD standard compliant but it seems that most players don't pay attention to the CRC information. The CRC information need 2 bytes per Audio frame The approximate frame length formula for MPEG-1 layer-II is: (frame length in bytes) = 144 * (byte rate) / (sample rate) If you have the typical VCD settings the CRC data needs about 0,27% of the whole data. In the worst case where you have a MONO 32k Bitrate stream the CRC data needs 1,92%. 7.7.2. SVCD Video creation example > lav2yuv stream.avi | yuvscaler -O SVCD | mpeg2enc -f 4 -q 7 -I 1 -V 200 -o video.m2v -f 4 sets the options for mpeg2enc to SVCD -q 7 tell mpeg2enc to generate a variable bitrate stream -I 1 tell mpeg2enc to assume that the original signal is field interlaced video where the odd rows of pixels are sampled a half frame interval after the even ones in each frame. The -I 0 (progressive output (no field pictures)) option will also work for PAL You can use lower bitrates but the SVCD standard limits total bit-rate (audio and video) to 2788800 Bit/sec. So with 224Kbps audio and overhead 2550 may already be marginally too tight. Since the SVCD format permits any audio rate between 32 and 384 kBit/sec you can save a few bits/sec by using 192k audio (or for non-musical material 160k). SVCD supports variable bitrate (VBR), because MPEG-2 is usually VBR, but with the top video bitrate limit of 2500kBit/sec. With the -f 4 flag the encoder also sets dynamic GOP with a low limit of -g 6 and a high limit of -G 18. This saves a few bits/sec and improves the picture quality during scene changes. When encoding with -f 4 mpeg2enc ignores the video bitrate (-b) and search radius (-r) options. If you use -f 5 you have to specify the bitrate and other options to mpeg2enc. Another possibility for movies in PAL (European style 25 frames/50 fields per sec) video is: > lav2yuv stream.avi | yuvscaler -O SVCD | mpeg2enc -f 4 -I 0 -V 300 -o video.m2v Movies are shot on film at 24 frames/sec. For PAL broadcast the film is simply shown slightly "too fast" at 25 frame/sec (much to the pain of people with an absolute pitch sense of pitch). The -I 0 flag turns off the tedious calculations needed to compensate for field interlacing giving much faster encoding. Unfortunately, movies broadcast in NTSC (US style 30 frames/60 fields sec) video this will produce very poor compression. The "pulldown" sampling used to produce 60 fields a second from a 24 frame a second movie means half the frames in an NTSC *are* field interlaced. Don't forget the -S and -B options mentioned above. You want the stream to fit on a CD don't you ? 7.7.3. SVCD multiplexing example > mplex -f 4 -b 300 -r 2750 sound.mp2 video.m2v -o svcd_out.mpg -f 4 tells mplex to mplex a SVCD -r 2750 is the calculated Audio + Video Bitrate + 1-2% multiplex information -b 300 is the buffer available on the playback device (the same value as used for the video encoding (mpeg2enc's -V option). 7.7.4. SVCD creating the CD Example: > vcdimager -t svcd testvideo.mpg Creates a videocd.bin, the data file, and a videocd.cue which is used as control file for cdrdao. Use cdrdao to burn the image as mentioned earlier. NOTE:If you want to build "custom" VCD/SVCD you will need to use the mplex -f 2 and -f 5 switches. NOTE:The VCD and SVCD stuff may work on your HW player or not. There are many reports that it works quite well. Don't be worried if it does not work. Nor am I responsible for unusable CDs. ("coasters") 7.8. Creating DVD's This statement was correct a few years ago: Everything in this section is new. The limitations I mention here might not exist in the current version. Currently (Dec. 2007) DVD creating is working. You need obviously a DVD writer. I did own a Ricoh DVD+RW that works, and I know of a DVD-RAM writer that is able to to burn DVD-R. That disks also work with a DVD-Player. Now most DVD writers ar able to burn both media + and -, so that should not be a problem any more. Which programs you use for burning depends on the DVD writer drive. For the creation and writing of the VOB, IFO and BUP files we use dvdauthor. Aviable from Sourceforge (you might have guessed it) http://dvdauthor.sourceforge.net. 7.8.1. DVD Audio creation example > lav2wav stream.eli | mp2enc -o sound.mp2 The sample rate has to be 48kHz. The mp2enc does create by default a sample rate of 48kHz. If it is not a 48kHz mp2enc will resample the audio to get the sample rate. If the audio is recorded at 48kHz then no resampling is needed and toolame can be used for the encoding (it is faster than mp2enc). 7.8.2. DVD Video creation example > lav2yuv stream.eli | mpeg2enc -f 8 -o video.m2v -f 8 This sets the options correctly for a MPEG-2 video that is compliant with the DVD standard. The maximum bitrate is set to 7500kBps and the video buffer size is set to 230KB. The default quality factor is set to 8. mpeg2enc sets currenty no automatic sequence length as it does for VCD/SVCD. The other options to get a low bitrate and high quality stream can also be used to override the default settings mentioned above. You can also use yuvdenoise to increase the picture quality if the input data is noisy (from a VHS tape for example). A typical command will look like this: lav2yuv moby.eli | yuvdenoise | mpeg2enc -f 8 -q 7 -4 1 -2 1 -P -I 0 -N -o video_DVD.m2v 7.8.3. DVD multiplexing example > mplex -f 8 sound.mp2 video.m2v -o my_dvdlikestream.mpg -f 8 Here again we specify that we want to have DVD like MPEG stream. mplex cannot do all the fancy things allowed for a DVD, but it is close enough that the HW-DVD players accept it. -o there we specify the output filename. 7.8.4. DVD creation example This topic will be covered by the documentation of the dvdauthor program. For questions please see dvdauthor In general it will work like this: > dvdauthor -o output/ stream1.mpg stream2.mpg ... my_dvdlikestream.mpg; dvdauthor -T -o output/ You will get a directory with AUDIO_TS and VIDEO_TS directories. Burning the data from the disk to a DVD+-R/+-RW writer would be done like this: growisofs -Z /dev/scd2 -dvd-video mydvd/ If you own a DVD+RW/+R drive a good place for more information is: DVD+RW/+R for Linux http://fy.chalmers.se/~appro/linux/DVD+RW/ page. You also need a version of the cdrtools with dvd-video support. The cdrtools 1.11a27 is known to work but newer versions already exist. For other writers the commands to write a DVD will be different. You can get some more information in the dvdauthor package. There is no guarantee that it will work at all !!! 7.9. Creating DIVX Videos 7.9.1. lav2avi.sh Another way of creating DIVX is the program mencoder which is from the mplayer project. http://www.mplayer.hu/. For more information about mencoder please read mencoder/mplayer help and documents. A first and a second pass give at the end of pass hints for bitrate which can be used for encoding to specific size (650 MB, 700 MB and 800 MB). The script lav2avi.sh uses this information if provided (for short streams it is omitted by mencoder). Look for parameter preferedSize in the script. You can also specify other parameters used for encoding with encoderParam option in the script. For a description of the usable parameters take a look in the mplayer/mencoder manual. The outputfilename is that name of your input file (first option) but with the extension avi. If the size of file is less then specified by preferedSize it's because the source was of very high quality (no noise) and the specified bitrate was higher than required. You usually get 700MB for 1.5 hour film at half image size with bitrate around 900 that means for divx good quality (assuming good quality source material of course). The script does a 3 step encoding: o 1st step - audio encoding o 2nd step - first video pass o 3rd step - second video pass The mplayer/mencoder documentation deprecates the use of the 3 pass encoding method (it can cause A/V sync problems) and recommends the use of the 2 pass method. The mencoder/mplayer documentation is extensive and has many helpful hints (and a bitrate calculator in the TOOLS/ directory). For encoding use the fast ffmpeg (lavc) codec. It gives nice results together with high good performance. For audio encoding mp3 is used. For encoding of all parts it uses unix pipes. This mean that you DO NOT need additional space on your hard drive where all glav manipulations will be done. For audio encoding the script uses a FIFO queue. If you want to tweak the script for your own needs use these hints: o Output of 1st step is file called frameno.avi with encoded audio o 2nd step is using frameno.avi and output is text file called lavc_stats.txt with timing informations o 3rd step is using frameno.avi and lavc_stats.txt for encoding the stream to the output file movie2.avi o If you want change only video bitrate keep the file frameno.avi comment out the 1st step encoding and repeate 2nd and 3rd step. Dont forget to remove the line where the frameno.avi is removed. 8. Optimizing the stream Using filters helps to increase the image quality of constant bitrate (CBR) video streams. With VBR (variable bit rate) video the filesize is reduced. Example: > lav2yuv stream.avi | yuvmedianfilter | mpeg2enc -o video.m1v Here the yuvmedianfilter program is used to improve the image. This removes some of low frequence noise in the images. It also softens the image a little. It takes a center pointer and averages the pixels around it that fall within the specified threshold. It then replaces the center pixel with this new value. You can also use the -r (radius) option for an other search radius. NOTE:a radius greater than the default value of 2 is horrendously slow! yuvmedianfilter has separate settings for luma and chroma. You can control the search radius and the trigger threshold independently. If you use a threshold of 0 then filtering is disabled (-t 0 disables luma filtering, -T 0 disables chroma filtering). > lav2yuv stream.avi | yuvmedianfilter -r 3 -t 4 -T 0 | mpeg2enc -o video.m1v This example uses a search radius of 3 pixels for the luma, a threshold of 4 (the default is 2), and disables filtering for the chroma components. Sometimes, depending on the source material, median filtering of the chroma can cause a slight color shift towards green. Filtering on the luma component (disabling the chroma filtering) is the solution to that problem. Example: > lav2yuv stream.avi | yuvdenoise | mpeg2enc -o video.m1v Now we are using yuvdenoise to improve the image. The filter mainly reduces color and luminance-noise and flickering due to phase errors but is also effective at removing speckles. yuvdenoise denoises interlaced if the input is interlaced. You can of course change the denoiser threshold (-g/t). Creating a black border can lower the bitrate of the encoded stream because pure black areas compress much better than noise (captures from analog sources such as VHS and 8mm usually have several lines at the time and bottom that are very noisy). For this you can use the scaler. yuvdenoise uses a different approach to filter the noise. More information about how yuvdenoise works as well as descriptions of its options are found in the manpage. If you have a high quality source you should lower the filter to levels like that: -g 0,255,255 -t 2,2,2. You might also use the mpeg2enc -h/--keep-hf option. That option tells mpeg2enc to keep as much high frequency information as possible. Using -h will greatly increase the bitrate (filesize). If the bitrate is too close to the maximum (set with -b) the encoder will have to decrease the quality to avoid exceeding the maximum bitrate. A builtin filter in mpeg2enc is the -N/--reduce-HF option. This option is not really filter in the usual sense. Rather it changes how exactly the high frequency information is encoded. Often the high frequency is noise. You also have high frequencies on sharp borders or transitions. The -N option can have values between 0.0 and 2.0 where 0.0 does nothing (disables the high frequency quantizer boost) and 2.0 gives the maximum quantization boost. The value to use depends on the desired output quality and filesize. Values of -N less than 0.5 are very subtle while a value of 1.0 will achieve a good balance between bitrate reduction and output quality. Using -N values above 1.5 will noticeably reduce the sharpness of the output picture and are normally used only for poor quality sources (VHS tapes for example). Using yuvmedianfilter's capability to only filter the chroma (-T) is moderately effective at reducing noise in dark scenes without softening the image during normal (brighter) scenes. Median filtering of the luma (-t) will produce a lower bitrate but can cause loss of detail (softening). Chroma only medianfiltering is less agressive and is a good choice to use in combination with yuvdenoise. Combining the filters yuvdenoise, yuvmedianfilter and the mpeg2enc -N option gives a very fine degree of control over the bitrate (filesize). The reduction (or increase) in the bitrate depends on the source material and the exact encoding/filter options used. So we can give no exact numbers how much each option and combination will reduce the filesize, only guidelines. Usually you should use the -N option in a range from 0.5 to 1.5. Below 0.5 it does not reduce the bitrate very much (but does preserve sharpness). At 1.5 and higher you will notice a softening in the video and possibly artifacts (halo/ringing) around edges of objects (text/subtitles especially). If you combine the filters you should use yuvdenoise and maybe afterwards yuvmedianfilter. Maybe yuvmedianfilter even after scaling. Having yuvmedianfilter in the chain does not reduce the bitrate that much. Often the use of yuvdenoise is enough. The yuvmedianfilter helps much if you have low quality sources, and not that much if you already have a rather good quality. When you combine the filter and option you will very likely reduce the filesize to about the half of the filesize without using the options and programs. In general aggressive filtering will produce smaller files (lower bitrate) but reduce the quality (details) of the picture. Less aggressive filtering/processing will preserve more detail but result in larger files. Example: > lav2yuv stream.avi | yuvkineco -F 1 | mpeg2enc -o video.m1v yuvkineco is used for NTSC sources. It does the conversation from 30000.0/1001.0 (about 29.97) fps to 24000.0/1001.0 (about 23.976) fps, you can call it "reverse 2-3 pulldown" more info about this in the README.2-3pulldown. yuvkineco does only remove NTSC specific problems. If you want to improve the image you should also use yuvdenoise: > lav2yuv stream.avi | yuvkineco | yuvdenoise | mpeg2enc -o video.m1v Example > lav2yuv stream.avi | yuvycsnoise | mpeg2enc -o video.m1v yuvycsnoise is also used for NTSC and is specialized for NTSC Y/C separation noise. If video capture hardware has only a poor Y/C separator then at vertical stripes (especially red/blue) noises appear which seem checker flag and bright/dark invert per 1 frame. yuvycsnoise reduces noises of this type. You can also use different thresholds for luma/chroma and the optimizing method. This filter is not needed with working with DV (Digital Video) data. yuvycsnoise works only correct when we have NTSC with: o full height (480 lines) o full motion captured (29.97 fps) o captured with poor Y/C separator hardware For more information about the yuvkineco and yuvycsnoise read the README in the yuvfilters directory. If you want to experiment to determine the optimal settings for the denoiser, scaler and so on replace the mpeg2enc with yuvplay. yuvplay plays back the yuv frames so you can see if the options you have chosen are making the thing better or worse. A command would look like this: > lav2yuv stream.eli | yuvdenoise -options | yuvscaler -options | yuvplay If you want to know how much each tool lowers the average bitrate. You can use this table to see what you can expect if you have a full size video and want to create a DVD with a qality factor of 5 and the allowed maximal bitrate of 8500kb/sec. o no denoising : 8300 kb/s (mostly hitting the upper bound) o yuvenoise : 7700 kb/s o mpeg2enc --reduce-hf : 7400 kb/s o yuvdenoise + yuvmedianfilter : 6000 kb/s o yuvdenoise + mpeg2enc --reduce-hf : 4900 kb/s o all of the above : 3600 kb/s While -N|--reduce-hf or yuvdenoise alone is only a modest improvement, together they reduce the bitrate substantially. There is not really much visible difference between using yuvdenoise alone and yuvdenoise with mpeg2enc --reduce-hf. The usefull values are between 0.0 and 1.5. Where you can say that the higher the quality factor you want, the less this option improves. At a quality factor 4 you save using -N 1.0 about 1%. If you want a quality factor of 9 and use the -N 1.0 you might save up to 40%. But you might save less, that depends on the video you encode!!! If you ask yourself why not alyways use all of the above filters? The answers are that the image softens (loss of detail) and the encoding time increases. Most of the filters each require about the same amount of time as mpeg2enc needs for encoding the video. If you have very high quality material and want to keep every detail you should try to use the mpeg2enc --keep-hf|-h on the other hand. Note: The bitrate reduction you have depends on the material and on the noise of the images. A other interresting mpeg2enc option is the -E|--unit-coeff-elim option. This option is disabled by default. If you enable it, a special "unit coefficient elimination" algorithm, is applied to the encoded picture blocks. Basically this proceedure forces blocks of a type that do not carry much information (but use many bits to encode) to be skipped. A negative value examines the base (DC) as well as the AC coefficients. A positive value means that only texture (AC) coefficients are examined and possibly zeroed. The recommended values lies between -20 and +20. You usually can expect that you have a 5% decreased filesize. The amount the bitrate is reduced can vary considerably, the range spans from not really noticable up to 20%. If you think a other quantization matrice will help use the -K|--custom-quant-matrices option. You can try out your own quanitsation matrice or use another builtin than the default. You can choose between kvcd, tmpgenc, hi-res, and your own. Using -K usually makes the file smaller except the hi-res option (that makes files considerably larger). Exact guidelines are hard to give, sometime a other quanitsation matrix saves almost nothing, and the next time up to 20%. More than 20% is very unlikely, 10-15% at a moderate qualityfactor (-q 8-10) are likely. The higher the qualiy the less it saves, at a quality factor of 4-6 the reduction in bitrate may only be 5% One thing to keep in mind is that the unit coefficient elimination and the quantization matrix option are decreasing the bitrate while maintaining the same visual quality. At this point you can chose to use the smaller file to increase the amount of video that will fit on the disc media or you could chose to increase the quality even more by lowering the -q value by 1 and make a larger (but higher quality) file. 8.1. Scaling and offset correction The basic scaling is described in the Converting video section The scaling takes a part of the picture and scales it to a larger or smaller size. The scaling is done by yuvscaler: lav2yuv test.eli | yuvscaler -I USE_400x400+50+100 | yuvplay Here we only take part of the picture and scale it up to the size of the original frame. But yuvscaler also changes the pixel aspect ratio. That means when you look at the stream using yuvplay it looks like a square in our example. After scaling, if the sample (pixel) aspect ratio were not changed, the video would not display with the proper aspect ratio. Yuvscaler compensates by adjusting the sample aspect ratio. If you have a interlaced video, the height and HeightOffset have to be a multiple by 4 if the video is interlaced. Else the values (width, height, widthoffset, heightoffset) have to be a multiple of 2. A problem that cannot be solved easily with scaling is when the picture is not centered horizontal. On one side you have no black pixels and on the other you have 30 for example. Scaling is here is the wrong solution. y4mshift is the perfect solution because it can shift the image to the left or right. lav2yuv test.eli | y4mshift -n 20 | mpeg2enc -f 3 -b 4000 -q 10 -o video.m2v That will shift the image 20 pixels to the right. If you use a negative the image is shift to the left. You have to use a even number. The inserted pixels are set to black. Some might wonder why the image is not centered and there is a black border around the image when you view what you have recorded. The reason for the black border is in history of the CRT (Cathode Ray Tube) TV technology. The history of the TV standard s a very interesting story but that topic is described in other (large) books. The TV does not show the full picture. A part of the picture is not shown because the TV sets overscan (sometimes as much as 10% but more common today is 5%). But when you capture the video with a card you see the whole image including the border that TVs lose due to overscanning. A horizontal offset is usually not a problem of the capture card. It is a problem when the film is broadcast and not well synchronized with the image. This means that the scan of the source not exactly synchronized with the carrier signal, you wont see that on TV. 8.2. Frame rate conversion Ever needed to convert the framerate from PAL to NTSC or the other direction around ? Or something much simpler like converting the framerate from 24FPS to 24000:1001 for conversation from a film frame rate to a valid NTSC frame rate. Than yuvfps is your program. It can lower the framerate by dropping frames or create a higher framerate by replicating frames. If you have a wrong framerate in the header you can only change the header of the YUV stream and not modify the stream. Because the frames are only replicated (copied) you should denoise first and then change the framerate and scale at als last step. If you have a interlaced source you should also deinterlace before changeing the framerate. If you create a higher frame rate it is very likely that you will have weird flickers when you play it back. If you convert PAL to NTSC (30000:1001 FPS about 29,97 FPS) the frame rate will lower by about the factor 480/576 (NTSC lines / PAL lines). If you lower the frame rate from PAL to NTSC (at 24000:1001) or NTSC FILM (24FPS) the bitrate will be about (480 Lines * 24 FPS) / (576 Lines * 25FPS). If you change the frame rate before denoising the yuvdenoise will have problems finding the noise across the frames and the needed bandwith will slightly increase. Example > lav2yuv video.eli | yuvfps -r 30000:1001 | yuvscaler -O SVCD | mpeg2enc -f 4 -o video_ntsc_svcd.m2v This is a example to convert the source video to a NTSC video running at 30000:1001 FPS (or about 29,97FPS) at SVCD size. Example > lav2yuv video.eli | yuvdenoise | yuvfps -r 24000:1001 | yuvscaler -O SIZE_720x480 | mpeg2enc -f 3 -b 4000 -q 7 -o video_ntsc.m2v This example shows how you should use the tools. Denoise first and than change the framerate and in the last step change the image size. It can happen that yuvscaler or mpeg2enc do not detect the TV norm correct. If that happens you have to add the norm option -n n/p/s to the program that chooses the wrong norm. If you know that the header tells the wrong framerate, you can simply change the framerate of the yuv header this way: > lav2yuv video.eli | yuvfps -r 25:1 -c | mpeg2enc -f 3 -b 4000 -q 7 -o video_pal.m2v You need the -c option. To tell yuvfps that it only should change the header of the stream. With the -r 25:1 you tell yuvfps the frame rate it should write into the header. In your example the PAL frame rate of 25 FPS. You always have to use the fractional form. If you know that the header is wrong, and you need a different output bitrate you can do this in a single step: > lav2yuv video.eli | yuvfps -s 24:1 -r 25:1 | mpeg2enc -o video.m1v 9. Transcoding of existing MPEG-2 For transcoding existing MPEG-2 streams from digital TV cards or DVD a lower data-rate than for broadcast will give good results. Standard VCD 1152 kbps typically works just fine for MPEG-1. The difference is in the Signal/Noise ratio of the original. The noise in the analog stuff makes it much harder to compress. You will also need to manually adjust the audio delay offset relative to video when multiplexing. Very often around 150ms delay seems to do the trick. You have to download the ac3dec and mpeg2dec packages. You can find them at their homepage: mpeg2dec ( http://libmpeg2.sourceforge.net/ ) and ac3dec. For decoding the audio streams mpg123 and mplayer can be very helpfull. You also need sox and toolame. In the scripts directory there is a mpegtranscode script that does most of the work. So transcoding looks like this: > mjpegtranscode -V -o vcd_stream mpeg2src.mpg -V set's the options so that a VCD compatible stream is generated -o vcd_stream a vcd_stream.m1v (video) and vcd_stream.mp2 (audio) is created mpeg2src.mpg specifies the source stream The script prints also something like this: > SYNC 234 mSec You will need to adjust the audio/video startup delays when multiplexing to ensure audio and video are synchronized. The exact delay (in milliseconds) that you need to pass to mplex to synchronize audio and video using the "-v"" is printed by the extract_a52 tool labeled "SYNC" when run with the "s" flag. This is the value th mjpegtranscode script prints out after the SYNC word. Then you need to multiplex them like this: > mplex -f 1 -O 234 vcd_stream.mp2 vcd_stream.m1v -o lowrate.mpg -f 1 Mux format is set to VCD -O 234 Video timestamp offset in mSec, generated by the mjpegtranscoding script, there negative values are allowed vcd_stream.mp2 & vcd_stream.m1v generated files by the script lowrate.mpg the VCD compatible output stream Here we have a SVCD (MPEG-2 video) example: > mjpegtranscode -S -o svcd_stream mpeg2src.mpg You have to multiplex it with: > mplex -f 4 -O 234 svcd_stream.mp2 svcd_stream.m2v -o lowrate.mpg Problem: There is sometimes a problem with NTSC and VCD playback because movies may be recoded with 3:2 pulldown NTSC with 60 fields/sec. mpeg2dec is designed for playback on computers and generates the original 24frames/sec bitrate. If you encode the video now 30frames/sec video is created. This video is now much too short for the encoded audio. The transcoding can be made to work but it must be done manually: > mpeg2dec -s -o pgmpipe mpeg2src.mpg | pgmtoy4m -a 59:54 -r 25:1 -i t | mpeg2enc -I 0 -f 4 -q 9 -V 230 -p -P -o svcd_stream.m2v The -p tells mpeg2enc to generate header flags for 3:2 pull down of 24fps movie. It may also work if you do not add the -p flag. You do not need the -p flag when transcoding to VCD format because it is not supported in mpeg1. 9.1. If you want to do every step on your own it will look something like this Extracting Audio: > cat test2.mpg | extract_a52 - -s | ac3dec -o wav -p sound.wav 2>/dev/null One of the first lines showed contains the label "SYNC" you have to use this time later when multiplexing. The 2>/dev/null redirects the output of ac3dec to /dev/null. In the next step you generate the mpeg audio file: > cat sound.wav | mp2enc -V -v 2 -o audio.mp2 -V forces VCD format, the sampling rate is converted to 44.1kHz from 48kHz -v 2 unnecessary but if you use it mp2enc tells you how many seconds of the audio file are already encoded. -o Specifies the output file. cat test2.mpg | extract_a52 - -s | ac3dec -o wav | sox -t wav /dev/stdin -t wav -r 44100 /dev/stdout | toolame -p 2 -b 224 /dev/stdin audio.mp2 One of the first lines again output contains the label "SYNC". You have to use this time (referred to as "SYNC_value" below) when doing the multiplexing. For VCD creation use: > mpeg2dec -s -o pgmpipe test2.mpg | pgmtoy4m -a 59:54 -r 25:1 -i t | mpeg2enc -s -o video_vcd.m1v mpeg2dec: -s tells mpeg2dec to use program stream demultiplexer -o pgmpipe the output format of the pictures, suitable for pgmtoy4m Mplex with: > mplex -f 1 -O SYNC_value audio.mp2 video_vcd.m1v -o vcd_stream.mpg -f 1 generates an VCD stream -O SYNC_value the value mentioned above For SVCD creation use: > mpeg2dec -s -o mpeg2src.mpg | pgmtoy4m -a 59:54 -r 25:1 -i t | mpeg2enc -f 4 -q 9 -V 230 -o video_svcd.mpg -q 9 Quality factor for the stream (VBR stream) (default q: 12) -V 230 Target video buffer size in KB -o Output file Mplex with: > mplex -f 4 -b 230 audio.mp2 video_svcd -o svcd_stream.mpg -f 4 generate an SVCD stream -b 200 Specify the video buffer size by the playback device. For other video output formats this might work: > mpeg2dec -s -o pgmpipe test2.mpg | pgmtoy4m -a 59:54 -r 25:1 -i t | yuvscaler -O SIZE_320x200 -O NOT_INTERLACED | mpeg2enc -o strange_video.m1v If you want to edit mpeg streams this also works but in a slightly different way. For demultiplexing you can use bbdmux from the bbtools package. Splits out either video or audio very cleanly. You can't get it any more from the homepage from Brent Beyler, it can still be found when you search for it using that keywords " bbtools linux -suse -blackbox". Currenty it can be found at: http://www.nop.org/inkling/ First run: > bbdmux myvideo.mpg You should get something like this: Found stream id 0xE0 = Video Stream 0 Found stream id 0xC0 = MPEG Audio Stream 0 Found stream id 0xBE = Padding Stream Extract audio with: > bbdmux myvideo.mpg 0xC0 audio.mp1 Convert it to wav: > mpg123 -w audio.wav audio.m1v Extract video with: > bbdmux myvideo.mpg 0xE0 video.m1v Converting video to an mjpeg avi stream: > mpeg2dec -o pgmpipe video.m1v | pgmtoy4m -a 59:54 -r 25:1 -i t | yuv2lav -f a -o test.avi Then adding the sound to the avi: > lavaddwav test.avi audio.wav final.avi If the source video has already the size of the target video use -o YUV. Using YUVh makes the video the half size! The rest can be done just like editing and encoding other streams. If you have videos with ac3 sound you only have to adapt the commands above. Extracting Audio: > cat test2.mpg | extract_a52 - -s | ac3dec -o wav 2>dev/null >sound.wav Extract video and adding the audio in a single step : > mpeg2dec -s -o pgmpipe | pgmtoy4m -a 59:54 -r 25:1 -i t | yuvscaler -O VCD | yuv2lav -f a -q 85 -w sound.wav -o test.avi NOTE:You need much disk space. 1GB of video has a size of about 2GB at SVCD format and of course disk space is needed for some temp files. Converting the video to mjpeg also takes some time. On my Athlon 500 I never get more than 6-7 Frames a second. You loose quality each time you convert a stream into an other format! 10. Trading Quality/Speed If absolute quality is your objective a modest improvement can be achieved using the -4 and -2 flags. These control how ruthlessly mpeg2enc discards bad looking matches between sections of adjacent frames during the early stages of the search when it is working with 4*4 and 2*2 clusters of pixels rather than individual pixels. Setting -4 1 -2 1 maximizes quality. -4 4 -2 4 maximizes speed. Note that because the statistical criteria mpeg2enc uses for discarding bad looking matches are usually fairly reliable the increase/decrease in quality is modest (but noticeable). Reducing the radius of the search for matching sections of images also increases speed. However due to the way the search algorithm works the search radius is in effect rounded to the nearest multiple of 8. Furthermore on modern CPU's the speed gained by reducing the radius below 16 is not large enough to make the marked quality reduction worthwhile for most applications. 10.1. Creating streams to be played from disk using Software players Usually MPEG player software is much more flexible than the hardware built into DVD and VCD players. This flexibility allows for significantly better compression to be achieved for the same quality. The trick is to generate video streams that use big video buffers (500KB or more) and variable bitrate encoding (the -f / -q flag to mpeg2enc). Software players will often also correctly play back the more efficient MPEG layer 3 (yes, "MP3" audio format. A good MP3 encoder like lame will produce results comparable to layer 2 at 224Kbps at 128Kbps or 160Kbps. 11. SMP and distributed Encoding Distributed encoding is a quite dark theory for the typical Machine in 2013. So most users can safely skip that point. SMP Encoding is more interresting for the average computer The degree to which mpeg2enc tries to split work between concurrently executing threads is controlled by the -M or --multi-thread [0..32] option. This optimizes mpeg2enc for the specified number of CPUs. By default (-M 1) mpeg2enc runs with just a little multi-threading: reading of frames happens concurrently with compression. This is done to allow encoding pipelines that are split across several machines (see below) to work efficiently without the need for special buffering programs. If you are encoding on a single-CPU machine where RAM is tight you may find turning off multithreading altogether by setting -M 0 works slightly more efficiently. For SMP machines with two ore more processors you can speed up mpeg2enc by setting the number of concurrently executing encoding threads's you wish to utilize (e.g. -M 2). Setting -M 2 or -M 3 on a 2-way machine should allow you to speed up encoding by around 80%. Values above 3 are accepted but have very little effect even on 4 cpu systems. If you have a real fast SMP machine (currently 1.Aug.03) like a dual Athlon MP 2600 or something similar the -M 2 and the filtering might not keep both (or more) CPU's busy. The use of the buffer or bfr program with a 10-20MB buffer helps to keep both CPUs busy. Obviously if your encoding pipeline contains several filtering stages it is likely that you can keep two or more CPU's busy simultaneously even without using -M. Denoising using yuvdenoise or yuvmedianfilter is particular demanding and uses almost as much processing power as MPEG encoding. It you more than one computer you can also split the encoding pipeline between computers using the standard 'rsh' or 'rcmd' remote shell execution commands. For example, if you have two computers: > rsh machine1 lav2yuv "mycapture.eli | yuvscaler -O SVCD | yuvdenoise" | mpeg2enc -f 4 -o mycapture.m2vi Here the computer where you execute the command is doing the MPEG encoding and "machine1" is the machine that is decoding scaling and denoising the captured video. Obviously, for this to work "machine1" has to be able to access the video and the computer where the command is executed has to have space for the encoded video. In practice, it is usually well worth setting up network file-storage using "NFS" or other packages if you are going to do stuff like this. If you have three computers you can take this a stage further, one computer could do the decoding and scaling, the next could do denoising and the third could do MPEG encoding: > rsh machine1 "lav2yuv mycapture.eli | yuvscaler -O SVCD" | yuvdenoise | rsh machine3 mpeg2enc -f 4 -o mycapture.m2v NOTE:How the remote command executions are set up so that the data is sent direct from the machine that produces it to the machine that consumes it. In practice for this to be worthwhile the network you are using must be fast enough to avoid becoming a bottleneck. For Pentium-III class machines or above you will need a 100Mbps Ethernet. For really fast machines a switched 100MBps Ethernet (or better!) may be needed.Setting up the rshd ("Remote Shell Daemon" needed for rsh to do its work and configuring "rsh" is beyond the scope of this document, but its a standard package and should be easily installed and activated on any Linux or BSD distribution. Be aware that this is potentially a security issue so use with care on machines that are visible to outside networks! 12. Interoperability Quicktime files capturing using lavrec can be edited using Broadcast2000. But Broadcast2000 is not available any more on heroinewarrior. mjpeg AVI files captured using the streamer tool from the xawtv package can be edited and compressed and played back using software. Hardware playback is not possible for such files due to limitations in the Zoran hardware currently supported. Videos recorded with NuppelVideo can also be processed with the mjpeg tools. If you have a Macintosh (MAC) and want to use the mjpeg tools look there: http://www.sjoki.uta.fi/~shmhav/SVCD_on_a_Macintosh.html MPEG files produced using the tools are know to play back correctly on: o dxr2 (hardware decoder card) o xine http://xine.sourceforge.net/ o xmovie http://heroinewarrior.com/xmovie.php o mplayer http://www.mplayerhq.hu/ o vlc http://www.videolan.org/ o MPEG-1 only: gtv http://packages.debian.org/stable/graphics/smpeg- gtv o MS Media player version 6 and 7 and later version o severals Software based DVD Player To find out what you HW-player (most of the time DVD player) can do take a look at: http://www.videohelp.com It seems that the MS Media player likes MPEG-1 streams more if you have used -f 1 when multiplexing. If you have any problems or suggestions feel free to mail me (Bernhard Praschinger): waldviertler@users.sourceforge.net There is a lot of stuff added from the HINTS which Andrew Stevens created. Wolfgang Goeller and Steven M. Schultz checked the document for bugs and spelling mistakes. And to the people who have helped me with program descriptions and hints, thanks mjpegtools-2.1.0/y4mutils/0000755000175000017500000000000012217306501016000 5ustar glowwormglowwormmjpegtools-2.1.0/y4mutils/Makefile.am0000644000175000017500000000325411736012467020052 0ustar glowwormglowworm# Makefile for y4mutils MAINTAINERCLEANFILES = Makefile.in AM_CFLAGS = @PROGRAM_NOPIC@ AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/utils LIBMJPEGUTILS = $(top_builddir)/utils/libmjpegutils.la if HAVE_ALTIVEC LIBMJPEGUTILS += $(top_builddir)/mpeg2enc/libmpeg2encpp.la endif bin_PROGRAMS = \ yuvmedianfilter \ pgmtoy4m \ y4mshift \ y4mspatialfilter \ y4mhist \ y4mblack \ y4mtoyuv \ y4minterlace \ yuv4mpeg \ y4mivtc \ yuyvtoy4m if HAVE_LIBQUICKTIME bin_PROGRAMS += y4mtoqt qttoy4m endif y4mivtc_SOURCES = y4mivtc.c y4mivtc_LDADD = $(LIBMJPEGUTILS) yuvmedianfilter_SOURCES = yuvmedianfilter.c yuvmedianfilter_LDADD = $(LIBMJPEGUTILS) pgmtoy4m_SOURCES = pgmtoy4m.c pgmtoy4m_LDADD = $(LIBMJPEGUTILS) y4mshift_SOURCES = y4mshift.c y4mshift_LDADD = $(LIBMJPEGUTILS) y4mspatialfilter_SOURCES = y4mspatialfilter.c y4mspatialfilter_LDADD = $(LIBMJPEGUTILS) $(LIBM_LIBS) y4mhist_SOURCES = y4mhist.c y4mhist_LDADD = $(SDL_LIBS) $(SDLgfx_LIBS) $(LIBMJPEGUTILS) y4mblack_SOURCES = y4mblack.c y4mblack_LDADD = $(LIBMJPEGUTILS) y4minterlace_SOURCES = y4minterlace.c y4minterlace_LDADD = $(LIBMJPEGUTILS) if HAVE_LIBQUICKTIME y4mtoqt_SOURCES = y4mtoqt.c y4mtoqt_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/lavtools $(LIBQUICKTIME_CFLAGS) y4mtoqt_LDADD = $(LIBMJPEGUTILS) $(top_builddir)/lavtools/liblavfile.la qttoy4m_SOURCES = qttoy4m.c qttoy4m_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/lavtools $(LIBQUICKTIME_CFLAGS) qttoy4m_LDADD = $(LIBMJPEGUTILS) $(top_builddir)/lavtools/liblavfile.la endif y4mtoyuv_SOURCES = y4mtoyuv.c y4mtoyuv_LDADD = $(LIBMJPEGUTILS) yuv4mpeg_SOURCES = yuv4mpeg.c yuv4mpeg_LDADD = $(LIBMJPEGUTILS) yuyvtoy4m_SOURCES = yuyvtoy4m.c yuyvtoy4m_LDADD = $(LIBMJPEGUTILS) mjpegtools-2.1.0/y4mutils/pgmtoy4m.c0000644000175000017500000002160210603766241017735 0ustar glowwormglowworm/* * $Id: pgmtoy4m.c,v 1.3 2007/04/01 17:32:17 sms00 Exp $ * * pgmtoy4m converts the PGM output of "mpeg2dec -o pgmpipe" to YUV4MPEG2 on * stdout. * * Note: mpeg2dec uses a rather interesting variation of the PGM format - the * output is not actually traditional "Grey Maps" but rather a catenation of * the Y'CrCb planes. From the libmpeg2 project's video_out_pgm.c: * * Layout of the Y, U, and V buffers in our pgm image * * YY YY YY * 420: YY 422: YY 444: YY * UV UV UUVV * UV UUVV * * The PGM type is P5 ("raw") and the number of rows is really the * total of the Y', Cb and Cr heights. The Cb and Cr data is "joined" * together. * * NOTE: You MAY need to know the field order (top or bottom field first), * sample aspect ratio and frame rate because the PGM format makes * none of that information available! There are defaults provided * that hopefully will do the right thing in the common cases. * * The defaults provided are: 4:2:0, top field first, NTSC rate of * 30000/1001 frames/second, and a sample aspect of 10:11. * * If the incoming chroma space is not 4:2:0 then you MUST specify the * "-x chroma_tag" option or chaos and/or a program crash will occur. */ #include "config.h" #include #include #include #include #include "yuv4mpeg.h" static void usage(char *progname); static void chroma_usage(char *progname); static int getint(int); #define P5MAGIC (('P' * 256) + '5') static int getmagicnumber(int fd) { char ch1 = -1, ch2 = -1; read(fd, &ch1, 1); read(fd, &ch2, 1); return((ch1 * 256) + ch2); } static int piperead(int fd, u_char *buf, int len) { int n = 0; int r = 0; while (r < len) { n = read (fd, buf + r, len - r); if (n <= 0) return(r); r += n; } return(r); } int main(int argc, char **argv) { int width, height, uvlen, verbose = 1, fdout, fdin, c, i; int columns, rows, maxval, magicn, frameno; int ss_h, ss_v, chroma_height, chroma_width; int chroma_mode = Y4M_UNKNOWN; u_char *yuv[3]; u_char junkbuffer[16384]; y4m_ratio_t rate_ratio = y4m_fps_UNKNOWN; y4m_ratio_t aspect_ratio = y4m_sar_UNKNOWN; char ilace = Y4M_ILACE_TOP_FIRST; y4m_frame_info_t oframe; y4m_stream_info_t ostream; fdin = fileno(stdin); fdout = fileno(stdout); y4m_accept_extensions(1); opterr = 0; while ((c = getopt(argc, argv, "i:a:r:hv:x:")) != EOF) { switch (c) { case 'i': switch (optarg[0]) { case 'p': ilace = Y4M_ILACE_NONE; break; case 't': ilace = Y4M_ILACE_TOP_FIRST; break; case 'b': ilace = Y4M_ILACE_BOTTOM_FIRST; break; default: usage(argv[0]); } break; case 'v': verbose = atoi(optarg); if (verbose < 0 || verbose > 3) mjpeg_error_exit1("Verbosity [0..2]"); break; case 'a': i = y4m_parse_ratio(&aspect_ratio, optarg); if (i != Y4M_OK) mjpeg_error_exit1("Invalid aspect: %s", optarg); break; case 'r': i = y4m_parse_ratio(&rate_ratio, optarg); if (i != Y4M_OK) mjpeg_error_exit1("Invalid rate: %s", optarg); break; case 'x': chroma_mode = y4m_chroma_parse_keyword(optarg); if (chroma_mode == Y4M_UNKNOWN) { if (strcmp(optarg, "help") == 0) chroma_usage(argv[0]); mjpeg_error_exit1("bad chroma arg"); } break; case 'h': case '?': default: usage(argv[0]); /* NOTREACHED */ } } if (chroma_mode == Y4M_UNKNOWN) chroma_mode = Y4M_CHROMA_420MPEG2; if (isatty(fdout)) mjpeg_error_exit1("stdout must not be a terminal"); mjpeg_default_handler_verbosity(verbose); /* * Check that the input stream is really a P5 (rawbits PGM) stream, then if it * is retrieve the "rows" and "columns" (width and height) and the maxval. * The maxval will be 255 if the data was generated from mpeg2dec! */ magicn = getmagicnumber(fdin); if (magicn != P5MAGIC) mjpeg_error_exit1("Input not P5 PGM data, got %x", magicn); columns = getint(fdin); rows = getint(fdin); maxval = getint(fdin); mjpeg_info("P5 cols: %d rows: %d maxval: %d", columns, rows, maxval); if (maxval != 255) mjpeg_error_exit1("Maxval (%d) != 255, not mpeg2dec output?", maxval); /* * Put some sanity checks on the sizes - handling up to 4096x4096 should be * enough for now :) */ if (columns < 0 || columns > 4096 || rows < 0 || rows > 4096) mjpeg_error_exit1("columns (%d) or rows(%d) < 0 or > 4096", columns, rows); y4m_init_frame_info(&oframe); y4m_init_stream_info(&ostream); y4m_si_set_chroma(&ostream, chroma_mode); if (y4m_si_get_plane_count(&ostream) != 3) mjpeg_error_exit1("Only the 3 plane formats supported"); ss_h = y4m_chroma_ss_x_ratio(chroma_mode).d; ss_v = y4m_chroma_ss_y_ratio(chroma_mode).d; width = columns; height = (rows * ss_v) / (ss_v + 1); chroma_width = width / ss_h; chroma_height = height / ss_v; uvlen = chroma_height * chroma_width; yuv[0] = malloc(height * width); yuv[1] = malloc(uvlen); yuv[2] = malloc(uvlen); if (yuv[0] == NULL || yuv[1] == NULL || yuv[2] == NULL) mjpeg_error_exit1("malloc yuv[]"); /* * If the (sample) aspect ratio and frame rate were not specified on the * command line try to intuit the video norm of NTSC or PAL by looking at the * height of the frame. */ if (Y4M_RATIO_EQL(aspect_ratio, y4m_sar_UNKNOWN)) { if (height == 480 || height == 240) { aspect_ratio = y4m_sar_NTSC_CCIR601; mjpeg_warn("sample aspect not specified, using NTSC CCIR601 value based on frame height of %d", height); } else if (height == 576 || height == 288) { aspect_ratio = y4m_sar_PAL_CCIR601; mjpeg_warn("sample aspect not specified, using PAL CCIR601 value based on frame height of %d", height); } else { mjpeg_warn("sample aspect not specified and can not be inferred from frame height of %d (leaving sar as unknown", height); } } if (Y4M_RATIO_EQL(rate_ratio, y4m_fps_UNKNOWN)) { if (height == 480 || height == 240) { rate_ratio = y4m_fps_NTSC; mjpeg_warn("frame rate not specified, using NTSC value based on frame height of %d", height); } else if (height == 576 || height == 288) { rate_ratio = y4m_fps_PAL; mjpeg_warn("frame rate not specified, using PAL value based on frame height of %d", height); } else { mjpeg_warn("frame rate not specified and can not be inferred from frame height of %d (using NTSC value)", height); rate_ratio = y4m_fps_NTSC; } } y4m_si_set_interlace(&ostream, ilace); y4m_si_set_framerate(&ostream, rate_ratio); y4m_si_set_sampleaspect(&ostream, aspect_ratio); y4m_si_set_width(&ostream, width); y4m_si_set_height(&ostream, height); y4m_write_stream_header(fdout, &ostream); /* * Now continue reading P5 frames as long as the magic number appears. Corrupt * (malformed) input or EOF will terminate the loop. The columns, rows and * maxval must be read to get to the raw data. It's probably not worth doing * anything (in fact it's unclear what could be done ;)) with the values * if they're different from the first header which was used to set the * output stream parameters. */ frameno = 0; while (1) { for (i = 0; i < height; i++) { piperead(fdin, yuv[0] + i * width, width); piperead(fdin, junkbuffer, 2 * chroma_width - width); } for (i = 0; i < chroma_height; i++) { piperead(fdin, yuv[1] + i * chroma_width, chroma_width); piperead(fdin, yuv[2] + i * chroma_width, chroma_width); } y4m_write_frame(fdout, &ostream, &oframe, yuv); magicn = getmagicnumber(fdin); if (magicn != P5MAGIC) { mjpeg_debug("frame: %d got magic: %x\n", frameno, magicn); break; } columns = getint(fdin); rows = getint(fdin); maxval = getint(fdin); frameno++; mjpeg_debug("frame: %d P5MAGIC cols: %d rows: %d maxval: %d", frameno, columns, rows, maxval); } y4m_fini_frame_info(&oframe); y4m_fini_stream_info(&ostream); return 0; } static void usage(char *progname) { fprintf(stderr, "%s usage: [-v n] [-i t|b|p] [-x chroma] [-a sample aspect] [-r rate]\n", progname); fprintf(stderr, "%s\taspect and rate in ratio form: -a 10:11 and -r 30000:1001 or -r 25:1 for example\n", progname); fprintf(stderr, "%s\t chroma default is 420mpeg2, -x help for list\n", progname); exit(0); } static int getint(int fd) { char ch; int i; do { if (read(fd, &ch, 1) == -1) return(-1); if (ch == '#') { while (ch != '\n') { if (read(fd, &ch, 1) == -1) return(-1); } } } while (isspace(ch)); if (!isdigit(ch)) return(-1); i = 0; do { i = i * 10 + (ch - '0'); if (read(fd, &ch, 1) == -1) break; } while (isdigit(ch)); return(i); } void chroma_usage(char *pname) { int mode = 0; const char *keyword; fprintf(stderr, "%s -x usage: Only the 3 plane formats are actually supported\n", pname); for (mode = 0; (keyword = y4m_chroma_keyword(mode)) != NULL; mode++) fprintf(stderr, "\t%s - %s\n", keyword, y4m_chroma_description(mode)); exit(1); } mjpegtools-2.1.0/y4mutils/yuyvtoy4m.c0000644000175000017500000001217511255224574020175 0ustar glowwormglowworm/* * $Id: yuyvtoy4m.c,v 1.3 2009/09/19 18:57:00 sms00 Exp $ * * A simple progam that can be used to convert 'yuyv' (also known as yuv2) * 4:2:2 packed into 4:2:2 planar format. Additional packings may be added * in the future BUT some of those are 'full range' rather than 'video range'! * Apple calls this 'yuvs' since the bytes within each 16bit word are swapped. * * The other moderately common 4:2:2 packing is UYVY - a simple byte flip within * each 16bit word. Since there's no way for the program to autodetect which * packing is used the '-k' option is provided for the user. If wild/crazy colors * are seen the chances are good that -k is needed ;) * * Used to convert YUY2/YUYV/YUVS to YUV4MPEG2 which is the format used by * mpeg2enc from the mjpeg-tools suite. * * This is strictly a filter, the use is in a pipeline such as the following * which catenates the raw 4:2:2 packed (yuyv) images from a ieee1394 digital * camera into a stream, repacks to 4:2:2 planar, and converts to 4:2:0 before * encoding. Obviously other steps, such as altering the frame rate, etc will * be done. * * The default sample aspect ratio for is square (1:1) because the anticipated use * of this program is with stills from IIDC cameras. * * cat *.raw | yuyvtoy4m -i p -w 1280 -h 960 -a 1:1 -r 24:1 | \ * y4mscaler -O chromass=420_mpeg2 | mpeg2enc ... * * NOTE: Obviously when catenating multiple files together they ALL must have * the same attributes (dimensions, interlacing, etc)! */ #include "config.h" #include #include #include #include #include "yuv4mpeg.h" static void usage(char *); int main(int argc, char **argv) { int sts, c, width = 0, height = 0, frame_len, i, yuyv = 1; y4m_ratio_t rate_ratio = y4m_fps_FILM; y4m_ratio_t aspect_ratio = y4m_sar_SQUARE; int interlace = Y4M_ILACE_NONE; u_char *yuv[3], *input_frame, *Y_p, *Cr_p, *Cb_p, *p; y4m_stream_info_t ostream; y4m_frame_info_t oframe; opterr = 0; if (argc == 1) usage(argv[0]); while ((c = getopt(argc, argv, "w:h:r:i:a:k")) != EOF) { switch (c) { case 'k': yuyv = 0; break; case 'a': sts = y4m_parse_ratio(&aspect_ratio, optarg); if (sts != Y4M_OK) mjpeg_error_exit1("Invalid aspect: %s", optarg); break; case 'w': width = atoi(optarg); break; case 'h': height = atoi(optarg); break; case 'r': sts = y4m_parse_ratio(&rate_ratio, optarg); if (sts != Y4M_OK) mjpeg_error_exit1("Invalid rate: %s", optarg); break; case 'i': switch (optarg[0]) { case 'p': interlace = Y4M_ILACE_NONE; break; case 't': interlace = Y4M_ILACE_TOP_FIRST; break; case 'b': interlace = Y4M_ILACE_BOTTOM_FIRST; break; default: usage(argv[0]); } break; case '?': default: usage(argv[0]); } } if (width <= 0) mjpeg_error_exit1("Invalid or unspecified Width: %d", width); if (height <= 0) mjpeg_error_exit1("Invalid or unspecified Height: %d", height); y4m_accept_extensions(1); y4m_init_stream_info(&ostream); y4m_init_frame_info(&oframe); y4m_si_set_width(&ostream, width); y4m_si_set_height(&ostream, height); y4m_si_set_interlace(&ostream, interlace); y4m_si_set_framerate(&ostream, rate_ratio); y4m_si_set_sampleaspect(&ostream, aspect_ratio); y4m_si_set_chroma(&ostream, Y4M_CHROMA_422); yuv[0] = malloc(y4m_si_get_plane_length(&ostream, 0)); yuv[1] = malloc(y4m_si_get_plane_length(&ostream, 1)); yuv[2] = malloc(y4m_si_get_plane_length(&ostream, 2)); if (yuv[0] == NULL || yuv[1] == NULL || yuv[2] == NULL) mjpeg_error_exit1("Could not malloc memory for 4:2:2 planes"); frame_len = y4m_si_get_framelength(&ostream); input_frame = malloc(frame_len); if (input_frame == NULL) mjpeg_error_exit1("Could not malloc memory for input frame"); y4m_write_stream_header(fileno(stdout), &ostream); while (y4m_read(fileno(stdin), input_frame, frame_len) == Y4M_OK) { Y_p = yuv[0]; Cb_p = yuv[1]; Cr_p = yuv[2]; p = input_frame; if (yuyv) /* YUYV (YUY2) */ { for (i = 0; i < frame_len; i += 4) { *Y_p++ = *p++; *Cb_p++ = *p++; *Y_p++ = *p++; *Cr_p++ = *p++; } } else /* UYVY */ { for (i = 0; i < frame_len; i += 4) { *Cb_p++ = *p++; *Y_p++ = *p++; *Cr_p++ = *p++; *Y_p++ = *p++; } } y4m_write_frame(fileno(stdout), &ostream, &oframe, yuv); } free(yuv[0]); free(yuv[1]); free(yuv[2]); free(input_frame); y4m_fini_stream_info(&ostream); y4m_fini_frame_info(&oframe); exit(0); } static void usage(char *pgm) { fprintf(stderr, "%s repacks YUYV (YUY2) and UYVY 4:2:2 streams into 4:2:2 planar YUV4MPEG2 streams\n", pgm); fprintf(stderr, "usage: -w width -h height [-k] [-a pixel aspect] [-i p|t|b] -r rate\n"); fprintf(stderr, " Interlace codes [-i X]: p (none) t (top first) b (bottom first) (p)\n"); fprintf(stderr, " Rate (as ratio) [-r N:M] (24:1)\n"); fprintf(stderr, " Pixel aspect (as ratio) [-a N:M] (1:1)\n"); fprintf(stderr, " Interpret data as UYVY instead of YUYV [-k] (false)\n"); fprintf(stderr, "NO DEFAULT for width or height!\n"); fprintf(stderr, "\n"); exit(1); } mjpegtools-2.1.0/y4mutils/qttoy4m.c0000644000175000017500000002737510447373263017617 0ustar glowwormglowworm/* * $Id: qttoy4m.c,v 1.11 2006/06/25 02:36:35 sms00 Exp $ * * Extract uncompressed Y'CbCr data from a Quicktime file and generate a * YUV4MPEG2 stream. As many of the attributes (frame rate, sample aspect, etc) * as possible are retrieved from the Quicktime file. However not all QT * files have all the attributes or perhaps they are not exactly as desired. * Commandline options are provided and if used with override information from * the Quicktime file. * * Optionally, if "-A filename" is used, the specified audio track (-t, default * is the first audio track found) will be extracted to a wav file. */ #include "config.h" #include #include #include #include #include #include #include #include "yuv4mpeg.h" #include "mpegconsts.h" #include "lav_io.h" #define nSAMPS 8192 typedef struct WavHeader { uint8_t riff[4]; /* RIFF */ uint32_t riff_length; uint8_t type[4]; uint8_t format[4]; /* FORMAT */ uint32_t format_length; uint16_t tag; /* COMMON */ uint16_t channels; uint32_t rate; uint32_t bytespersecond; uint16_t bytespersample; uint16_t bitspersample; uint8_t data[4]; /* DATA */ uint32_t data_length; } WAVheader; static void fixwavheader(WAVheader *, int); static void do_audio(quicktime_t *, FILE *, int); static void usage(void) { mjpeg_warn("usage: [-r rate] [-a sar] [-i t|b|p] [-t vtrack] [-T atrack] [-A audiofile] input.mov > output.y4m"); mjpeg_warn(" Decode specified video track to YUV4MPEG2 on stdout (-1 disables video output)"); mjpeg_warn(" Extract specified audio track to 'audiofile'"); exit(1); } int main(int argc, char *argv[]) { quicktime_t *file; quicktime_pasp_t pasp; int nfields = 0, dominance = 0, interlace = Y4M_UNKNOWN; FILE *audio_fp = NULL; char *audiofile = NULL; int64_t i, length, width, height; int vtrack = 0, atrack = 0, c, sts, cmodel, ss_h, ss_v; int y4mchroma = Y4M_UNKNOWN, omodel; double qtrate; y4m_stream_info_t ostream; y4m_frame_info_t oframe; y4m_ratio_t rate = y4m_fps_UNKNOWN, sar = y4m_sar_UNKNOWN; uint8_t **qtrows, *yuv[3]; opterr = 0; while ((c = getopt(argc, argv, "T:A:t:i:a:r:h")) != EOF) { switch (c) { case 'T': atrack = atoi(optarg); break; case 'A': audiofile = strdup(optarg); break; case 't': vtrack = atoi(optarg); break; case 'a': sts = y4m_parse_ratio(&sar, optarg); if (sts != Y4M_OK) mjpeg_error_exit1("Invalid aspect: %s", optarg); break; case 'i': switch (optarg[0]) { case 'p': interlace = Y4M_ILACE_NONE; break; case 't': interlace = Y4M_ILACE_TOP_FIRST; break; case 'b': interlace = Y4M_ILACE_BOTTOM_FIRST; break; default: usage(); } break; case 'r': sts = y4m_parse_ratio(&rate, optarg); if (sts != Y4M_OK) mjpeg_error_exit1("Invalid rate: %s", optarg); break; case '?': case 'h': default: usage(); } } argc -= optind; argv += optind; if (argc < 1) usage(); if (!(file = quicktime_open(argv[0], 1, 0))) mjpeg_error_exit1("quicktime_open(%s,1,0)failed\n", argv[0]); if (audiofile != NULL) { if (quicktime_audio_tracks(file) < atrack) mjpeg_warn("No audio track %d in file\n", atrack); else if ((audio_fp = fopen(audiofile, "w")) == NULL) mjpeg_warn("fopen(%s,w) failed\n", audiofile); } if (vtrack < 0) goto doaudio; if (quicktime_supported_video(file, vtrack) == 0) mjpeg_error_exit1("Unsupported video codec"); if (quicktime_video_tracks(file) < vtrack) mjpeg_error_exit1("No video track %d in file\n", vtrack); length = quicktime_video_length(file, vtrack); width = quicktime_video_width(file, vtrack); height = quicktime_video_height(file, vtrack); cmodel = lqt_get_cmodel(file, vtrack); omodel = 0; if (lqt_colormodel_is_yuv(cmodel) == 0) mjpeg_error_exit1("Color space '%s' not Y'CbCr", lqt_colormodel_to_string(cmodel)); if (lqt_colormodel_has_alpha(cmodel) == 1) mjpeg_error_exit1("Color space '%s' has alpha channel", lqt_colormodel_to_string(cmodel)); y4m_accept_extensions(1); y4m_init_stream_info(&ostream); y4m_init_frame_info(&oframe); y4m_si_set_width(&ostream, width); y4m_si_set_height(&ostream, height); /* * Now to map the BC_* values to Y4M_CHROMA_* values. The 16bit types will * hopefully be converted to 8 bit in the decoding. */ switch (cmodel) { case BC_YUV411P: y4mchroma = Y4M_CHROMA_411; break; case BC_YUV422: case BC_YUV422P16: case BC_YUVJ422P: /* should never see */ case BC_YUV422P: /* set color model to 422P to get 8bit planar output */ lqt_set_cmodel(file, vtrack, BC_YUV422P); omodel = BC_YUV422P; y4mchroma = Y4M_CHROMA_422; break; case BC_YUV420P: case BC_YUVJ420P: y4mchroma = Y4M_CHROMA_420JPEG; #if 0 if (lqt_get_chroma_placement(file, vtrack) == LQT_CHROMA_PLACEMENT_DVPAL) y4mchroma = Y4M_CHROMA_PALDV; #endif break; case BC_YUV444P16: case BC_YUV444P: case BC_YUVJ444P: /* should never see */ /* set color model to 444P to get 8bit planar output */ lqt_set_cmodel(file, vtrack, BC_YUV444P); omodel = BC_YUV444P; y4mchroma = Y4M_CHROMA_444; break; default: mjpeg_error_exit1("Unknown/unsupported color model %s", lqt_colormodel_to_string(cmodel)); } /* * Report unsupported conversions. This should never happen unless a new * colormodel is added to the switch statement above. */ if (omodel && !lqt_colormodel_has_conversion(cmodel, omodel)) mjpeg_error_exit1("libquicktime can't convert from %s to %s :(", lqt_colormodel_to_string(cmodel), lqt_colormodel_to_string(omodel)); lqt_colormodel_get_chroma_sub(cmodel, &ss_h, &ss_v); y4m_si_set_chroma(&ostream, y4mchroma); /* * If interlacing was specified on the commandline use it (override/ignore * any 'fiel' atom in the file). Otherwise use the 'fiel' atom if present. * If no command line value and no 'fiel' atom then use 'progressive' and * log a warning. */ if (interlace == Y4M_UNKNOWN) { lqt_get_fiel(file, vtrack, &nfields, &dominance); if (nfields == 0) { mjpeg_warn("no 'fiel' atom and no -i option, assuming PROGRESSIVE"); interlace = Y4M_ILACE_NONE; } else if (nfields == 1) interlace = Y4M_ILACE_NONE; else if (nfields == 2) { if (dominance == 14 || dominance == 6) interlace = Y4M_ILACE_BOTTOM_FIRST; else if (dominance == 9 || dominance == 1) interlace = Y4M_ILACE_TOP_FIRST; else mjpeg_error_exit1("Unknown fiel dominance %d", dominance); } else if (nfields > 2) mjpeg_error_exit1("Bad nfields '%d' in 'fiel' atom", nfields); } y4m_si_set_interlace(&ostream, interlace); /* * If a command line (-a) value given then use the command line value (ignore/ * override the 'pasp' atom if present). If no commandline (-a) option given * but there is a 'pasp' atom then use the latter. If neither 'pasp' or * command line option then assume 1:1 pixels with a warning. */ if (Y4M_RATIO_EQL(sar, y4m_sar_UNKNOWN)) { memset(&pasp, 0, sizeof (pasp)); lqt_get_pasp(file, vtrack, &pasp); if (pasp.hSpacing && pasp.vSpacing) { sar.n = pasp.hSpacing; sar.d = pasp.vSpacing; } else { mjpeg_warn("Missing/malformed 'pasp' atom, -a not specified, 1:1 SAR assumed."); sar = y4m_sar_SQUARE; } } y4m_ratio_reduce(&sar); y4m_si_set_sampleaspect(&ostream, sar); if (Y4M_RATIO_EQL(rate, y4m_fps_UNKNOWN)) { qtrate = quicktime_frame_rate(file, vtrack); if (qtrate == 0.0) mjpeg_error_exit1("frame rate = 0 and no -r given"); rate = mpeg_conform_framerate(qtrate); } y4m_ratio_reduce(&rate); y4m_si_set_framerate(&ostream, rate); /* * Everything needed for the Y4M header has been obtained - so now write * out the YUV4MPEG2 header */ y4m_write_stream_header(fileno(stdout), &ostream); /* * Now allocate the memory for the buffers. */ qtrows = yuv; yuv[0] = (uint8_t *) malloc(width * height); yuv[1] = (uint8_t *) malloc((width / ss_h) * (height / ss_v)); yuv[2] = (uint8_t *) malloc((width / ss_h) * (height / ss_v)); for (i = 0; i < length; i++) { lqt_decode_video(file, qtrows, vtrack); y4m_write_frame(fileno(stdout), &ostream, &oframe, yuv); } /* * Now do the audio if requested and the audio file open succeeded earlier */ doaudio: if (audio_fp) do_audio(file, audio_fp, atrack); quicktime_close(file); exit(0); } static void do_audio(quicktime_t *qtf, FILE *audio_fp, int atrack) { long total_samples_decoded = 0; long audio_rate, l; int audio_sample_size, channels, samples_decoded, i, bigendian; int16_t **qt_audion, *audbuf, *swapbuf = NULL; WAVheader wavhead; bigendian = lav_detect_endian(); audio_rate = quicktime_sample_rate(qtf, atrack); audio_sample_size = quicktime_audio_bits(qtf, atrack) / 8; /* if audio_sample_size != 2 then bail? */ channels = quicktime_track_channels(qtf, atrack); audbuf = (int16_t*)malloc(channels * audio_sample_size * nSAMPS); if (bigendian != 0) swapbuf = (int16_t*)malloc(channels*audio_sample_size*nSAMPS); qt_audion = malloc(channels * sizeof (int16_t **)); for (i = 0; i < channels; i++) qt_audion[i] = (int16_t *)malloc(nSAMPS * audio_sample_size); /* * Need to generate prototype WAV header and write it out - at the end of the * input data a rewind will be done and the WAV header rewritten */ memcpy(wavhead.riff, "RIFF", 4); wavhead.riff_length = sizeof(wavhead) - sizeof(wavhead.riff) - sizeof(wavhead.riff_length); wavhead.data_length = 0; memcpy(wavhead.type, "WAVE", 4); memcpy(wavhead.format, "fmt ", 4); wavhead.format_length = 0x10; wavhead.tag = 0x01; /* PCM */ wavhead.channels = channels; wavhead.rate = audio_rate; wavhead.bytespersecond = audio_rate * channels * audio_sample_size ; wavhead.bytespersample = audio_sample_size * channels; wavhead.bitspersample = audio_sample_size * 8; memcpy(wavhead.data, "data", 4); fwrite(&wavhead, sizeof (wavhead), 1, audio_fp); mjpeg_info("channels: %d audio_rate: %ld audio_sample_size: %d\n", channels, audio_rate, audio_sample_size); while (1) { int64_t last_pos, start_pos; int i, j; start_pos = lqt_last_audio_position(qtf, atrack); lqt_decode_audio_track(qtf, qt_audion, NULL, nSAMPS, atrack); last_pos = lqt_last_audio_position(qtf, atrack); samples_decoded = last_pos - start_pos; /* Interleave the channels of audio into the one buffer provided */ for (i = 0; i < samples_decoded; i++) { for (j = 0; j < channels; j++) audbuf[(channels * i) + j] = qt_audion[j][i]; } l = samples_decoded * audio_sample_size * channels; wavhead.data_length += l; wavhead.riff_length += l; if (bigendian) swab(audbuf, swapbuf, l); fwrite(bigendian ? swapbuf : audbuf, l, 1, audio_fp); total_samples_decoded += samples_decoded; if (samples_decoded < nSAMPS) break; } rewind(audio_fp); fixwavheader(&wavhead, bigendian); fwrite(&wavhead, sizeof (wavhead), 1, audio_fp); mjpeg_info("total samples decoded: %ld\n", total_samples_decoded); fclose(audio_fp); } static void fixwavheader(WAVheader *wave, int bigendian) { uint16_t temp_16; uint32_t temp_32; WAVheader saved; if (bigendian == 0) return; memcpy(&saved, wave, sizeof (*wave)); temp_32 = saved.riff_length; wave->riff_length = reorder_32(temp_32, bigendian); temp_32 = saved.format_length; wave->format_length = reorder_32(temp_32, bigendian); temp_16 = saved.tag; swab(&temp_16, &wave->tag, 2); temp_16 = saved.channels; swab(&temp_16, &wave->channels, 2); temp_32 = saved.rate; wave->rate = reorder_32(temp_32, bigendian); temp_32 = saved.bytespersecond; wave->bytespersecond = reorder_32(temp_32, bigendian); temp_16 = saved.bytespersample; swab(&temp_16, &wave->bytespersample, 2); temp_16 = saved.bitspersample; swab(&temp_16, &wave->bitspersample, 2); temp_32 = saved.data_length; wave->data_length = reorder_32(temp_32, bigendian); } mjpegtools-2.1.0/y4mutils/y4mblack.c0000644000175000017500000001204711255224574017670 0ustar glowwormglowworm/* * $Id: y4mblack.c,v 1.4 2009/09/19 18:57:00 sms00 Exp $ * * Used to generate YUV4MPEG2 frames with the specific interlace, * dimensions, pixel aspect and Y/U/V values. By default the frames * generated are 16/128/128 or pure black. * * This is strictly an output program, stdin is ignored. */ #include "config.h" #include #include #include #include "yuv4mpeg.h" static void usage(char *); static void chroma_usage(char *); int main(int argc, char **argv) { int sts, c, width = 640, height = 480, noheader = 0; int Y = 16, U = 128, V = 128, chroma_mode = Y4M_CHROMA_420MPEG2; int numframes = 1, force = 0; y4m_ratio_t rate_ratio = y4m_fps_NTSC; y4m_ratio_t aspect_ratio = y4m_sar_SQUARE; int plane_length[3]; u_char *yuv[3]; y4m_stream_info_t ostream; y4m_frame_info_t oframe; char interlace = Y4M_ILACE_NONE; opterr = 0; y4m_accept_extensions(1); while ((c = getopt(argc, argv, "Hfx:w:h:r:i:a:Y:U:V:n:")) != EOF) { switch (c) { case 'H': noheader = 1; break; case 'a': sts = y4m_parse_ratio(&aspect_ratio, optarg); if (sts != Y4M_OK) mjpeg_error_exit1("Invalid aspect: %s", optarg); break; case 'w': width = atoi(optarg); break; case 'h': height = atoi(optarg); break; case 'r': sts = y4m_parse_ratio(&rate_ratio, optarg); if (sts != Y4M_OK) mjpeg_error_exit1("Invalid rate: %s", optarg); break; case 'Y': Y = atoi(optarg); break; case 'U': U = atoi(optarg); break; case 'V': V = atoi(optarg); break; case 'i': switch (optarg[0]) { case 'p': interlace = Y4M_ILACE_NONE; break; case 't': interlace = Y4M_ILACE_TOP_FIRST; break; case 'b': interlace = Y4M_ILACE_BOTTOM_FIRST; break; default: usage(argv[0]); } break; case 'x': chroma_mode = y4m_chroma_parse_keyword(optarg); if (chroma_mode == Y4M_UNKNOWN) { if (strcmp(optarg, "help") != 0) mjpeg_error("Invalid -x arg '%s'", optarg); chroma_usage(argv[0]); } break; case 'f': force = 1; break; case 'n': numframes = atoi(optarg); break; case '?': default: usage(argv[0]); } } if (width <= 0) mjpeg_error_exit1("Invalid Width: %d", width); if (height <= 0) mjpeg_error_exit1("Invalid Height: %d", height); if (!force && (Y < 16 || Y > 235)) mjpeg_error_exit1("16 < Y < 235"); if (!force && (U < 16 || U > 240)) mjpeg_error_exit1("16 < U < 240"); if (!force && (V < 16 || V > 240)) mjpeg_error_exit1("16 < V < 240"); y4m_init_stream_info(&ostream); y4m_init_frame_info(&oframe); y4m_si_set_width(&ostream, width); y4m_si_set_height(&ostream, height); y4m_si_set_interlace(&ostream, interlace); y4m_si_set_framerate(&ostream, rate_ratio); y4m_si_set_sampleaspect(&ostream, aspect_ratio); y4m_si_set_chroma(&ostream, chroma_mode); if (y4m_si_get_plane_count(&ostream) != 3) mjpeg_error_exit1("Only the 3 plane formats supported"); plane_length[0] = y4m_si_get_plane_length(&ostream, 0); plane_length[1] = y4m_si_get_plane_length(&ostream, 1); plane_length[2] = y4m_si_get_plane_length(&ostream, 2); yuv[0] = malloc(plane_length[0]); yuv[1] = malloc(plane_length[1]); yuv[2] = malloc(plane_length[2]); /* * Now fill the array once with black but use the provided Y, U and V values */ memset(yuv[0], Y, plane_length[0]); memset(yuv[1], U, plane_length[1]); memset(yuv[2], V, plane_length[2]); if (noheader == 0) y4m_write_stream_header(fileno(stdout), &ostream); while (numframes--) y4m_write_frame(fileno(stdout), &ostream, &oframe, yuv); free(yuv[0]); free(yuv[1]); free(yuv[2]); y4m_fini_stream_info(&ostream); y4m_fini_frame_info(&oframe); exit(0); } void usage(char *pgm) { fprintf(stderr, "%s usage: [-H] [-f] [-n numframes] [-w width] [-h height] [-Y val] [-U val] [-V val] [-a pixel aspect] [-i p|t|b] [-x chroma] [-r rate]\n", pgm); fprintf(stderr, "\n Omit the YUV4MPEG2 header [-H]"); fprintf(stderr, "\n Specify chroma sampling [-x string] (420mpeg2)"); fprintf(stderr, "\n -x help for list"); fprintf(stderr, "\n NOTE: Only 3 plane formats supported"); fprintf(stderr, "\n Allow out of range Y/U/V values [-f]"); fprintf(stderr, "\n Numframes [-n num] (1)"); fprintf(stderr, "\n Width [-w width] (640)"); fprintf(stderr, "\n Height [-h height] (480)"); fprintf(stderr, "\n Interlace codes [-i X] p (none/progressive) t (top first) b (bottom first) (p)"); fprintf(stderr, "\n Rate (as ratio) [-r N:M] (30000:1001)"); fprintf(stderr, "\n Pixel aspect (as ratio) [-a N:M] (1:1)"); fprintf(stderr, "\n Y: [-Y val] (16)"); fprintf(stderr, "\n U: [-U val] (128)"); fprintf(stderr, "\n V: [-V val] (128)"); fprintf(stderr, "\n"); exit(1); } void chroma_usage(char *pgm) { int mode = 0; const char *keyword; fprintf(stderr, "%s -x usage: Only the 3 plane formats are actually supported\n", pgm); for (mode = 0; (keyword = y4m_chroma_keyword(mode)) != NULL; mode++) fprintf(stderr, "\t%s - %s\n", keyword, y4m_chroma_description(mode)); exit(1); } mjpegtools-2.1.0/y4mutils/y4mshift.c0000644000175000017500000002763511255224574017742 0ustar glowwormglowworm /* * $Id: y4mshift.c,v 1.4 2009/09/19 18:57:00 sms00 Exp $ * * written by Steven M. Schultz * * 2003/5/8 - added the ability to place a black border around the frame. * * Simple program to shift the data an even number of pixels. The shift count * is positive for shifting to the right and negative for a left shift. * * Usage: y4mshift -n N [ -b xoffset,yoffset,xsize,ysize ] * * No file arguments are needed since this is a filter only program. */ #include "config.h" #include #include #include #include "yuv4mpeg.h" #define HALFSHIFT (shiftnum / SS_H) void black_border(u_char **, char *, int, int, int, int); void vertical_shift(u_char **, int, int, int, int, int, int); static void usage(char *); int main(int argc, char **argv) { int i, c, width, height, frames, err, chroma_ss, ilace_factor; int shiftnum = 0, shiftY = 0, rightshiftY, rightshiftUV; int vshift = 0, vshiftY = 0, monochrome = 0; int verbose = 0, fdin; int SS_H = 2, SS_V = 2; u_char *yuv[3], *line; char *borderarg = NULL; y4m_stream_info_t istream, ostream; y4m_frame_info_t iframe; fdin = fileno(stdin); y4m_accept_extensions(1); opterr = 0; while ((c = getopt(argc, argv, "hvn:N:b:My:Y:")) != EOF) { switch (c) { case 'M': monochrome = 1; break; case 'b': borderarg = strdup(optarg); break; case 'n': shiftnum = atoi(optarg); break; case 'y': shiftY = atoi(optarg); break; case 'Y': vshiftY = atoi(optarg); break; case 'N': vshift = atoi(optarg); break; case 'v': verbose++; break; case '?': case 'h': default: usage(argv[0]); } } if ( shiftnum + shiftY > 0 ) rightshiftY = 1; else rightshiftY = 0; shiftY = abs(shiftnum + shiftY); /* now shiftY is total Y shift */ if (shiftnum > 0) rightshiftUV = 1; else { rightshiftUV = 0; shiftnum = abs(shiftnum); } y4m_init_stream_info(&istream); y4m_init_frame_info(&iframe); err = y4m_read_stream_header(fdin, &istream); if (err != Y4M_OK) mjpeg_error_exit1("Input stream error: %s\n", y4m_strerr(err)); if (y4m_si_get_plane_count(&istream) != 3) mjpeg_error_exit1("Only 3 plane formats supported"); chroma_ss = y4m_si_get_chroma(&istream); SS_H = y4m_chroma_ss_x_ratio(chroma_ss).d; SS_V = y4m_chroma_ss_y_ratio(chroma_ss).d; if (y4m_si_get_interlace(&istream) == Y4M_ILACE_NONE) ilace_factor = 1; else ilace_factor = 2; if ((shiftnum % SS_H) != 0) usage(argv[0]); if ((vshift % (ilace_factor * SS_V)) != 0) usage(argv[0]); width = y4m_si_get_width(&istream); height = y4m_si_get_height(&istream); if (shiftnum > width / 2) mjpeg_error_exit1("nonsense to shift %d out of %d", shiftnum, width); if (shiftY > width / 2) mjpeg_error_exit1("nonsense to shift %d out of %d\n", shiftY, width); y4m_init_stream_info(&ostream); y4m_copy_stream_info(&ostream, &istream); y4m_write_stream_header(fileno(stdout), &ostream); yuv[0] = malloc(y4m_si_get_plane_length(&istream, 0)); if (yuv[0] == NULL) mjpeg_error_exit1("malloc() failed for plane 0"); yuv[1] = malloc(y4m_si_get_plane_length(&istream, 1)); if (yuv[1] == NULL) mjpeg_error_exit1("malloc() failed for plane 1"); yuv[2] = malloc(y4m_si_get_plane_length(&istream, 2)); if (yuv[2] == NULL) mjpeg_error_exit1("malloc() failed for plane 2"); frames = 0; for (;y4m_read_frame(fdin,&istream,&iframe,yuv) == Y4M_OK; frames++) { if (shiftnum == 0 && shiftY == 0) goto outputframe; for (i = 0; i < height; i++) { /* * Y */ line = &yuv[0][i * width]; if (rightshiftY) { bcopy(line, line + shiftY, width - shiftY); memset(line, 16, shiftY); /* black */ } else { bcopy(line + shiftY, line, width - shiftY); memset(line + width - shiftY, 16, shiftY); } } /* * U */ for (i = 0; i < height / SS_V; i++) { line = &yuv[1][i * (width / SS_H)]; if (rightshiftUV) { bcopy(line, line+HALFSHIFT, (width-shiftnum)/SS_H); memset(line, 128, HALFSHIFT); /* black */ } else { bcopy(line+HALFSHIFT, line, (width-shiftnum)/SS_H); memset(line+(width-shiftnum)/SS_H, 128, HALFSHIFT); } } /* * V */ for (i = 0; i < height / SS_V; i++) { line = &yuv[2][i * (width / SS_H)]; if (rightshiftUV) { bcopy(line, line+HALFSHIFT, (width-shiftnum)/SS_H); memset(line, 128, HALFSHIFT); /* black */ } else { bcopy(line+HALFSHIFT, line, (width-shiftnum)/SS_H); memset(line+(width-shiftnum)/SS_H, 128, HALFSHIFT); } } outputframe: if (vshift) vertical_shift(yuv, vshift, vshiftY, width, height, SS_H, SS_V); if (borderarg) black_border(yuv, borderarg, width, height, SS_H, SS_V); if (monochrome) { memset(&yuv[1][0], 128, (width / SS_H) * (height / SS_V)); memset(&yuv[2][0], 128, (width / SS_H) * (height / SS_V)); } y4m_write_frame(fileno(stdout), &ostream, &iframe, yuv); } y4m_fini_frame_info(&iframe); y4m_fini_stream_info(&istream); y4m_fini_stream_info(&ostream); exit(0); } /* * -b Xoff,Yoff,Xsize,YSize */ void black_border (u_char *yuv[], char *borderstring, int W, int H, int SS_H, int SS_V) { static int parsed = -1; static int BX0, BX1; /* Left, Right border columns */ static int BY0, BY1; /* Top, Bottom border rows */ int i1, i2, i, dy, W2, H2; if (parsed == -1) { parsed = 0; i = sscanf(borderstring, "%d,%d,%d,%d", &BX0, &BY0, &i1, &i2); if (i != 4 || (BX0 % SS_H) || (BY0 % (2*SS_V)) || i1 < 0 || i2 < 0 || (BX0 + i1 > W) || (BY0 + i2 > H)) { mjpeg_warn(" border args invalid - ignored"); return; } BX1 = BX0 + i1; BY1 = BY0 + i2; parsed = 1; } /* * If a borderstring was seen but declared invalid then it * is being ignored so just return. */ if (parsed == 0) return; W2 = W / SS_H; H2 = H / SS_V; /* * Yoff Lines at the top. If the vertical offset is 0 then no top border * is being requested and there is nothing to do. */ if (BY0 != 0) { memset(yuv[0], 16, W * BY0); memset(yuv[1], 128, W2 * BY0/SS_V); memset(yuv[2], 128, W2 * BY0/SS_V); } /* * Height - (Ysize + Yoff) lines at bottom. If the bottom coincides with * the frame size then there is nothing to do. */ if (H != BY1) { memset(&yuv[0][BY1 * W], 16, W * (H - BY1)); memset(&yuv[1][(BY1 / SS_V) * W2], 128, W2 * (H - BY1)/SS_V); memset(&yuv[2][(BY1 / SS_V) * W2], 128, W2 * (H - BY1)/SS_V); } /* * Now the partial lines in the middle. Go from rows BY0 thru BY1 because * the whole rows (0 thru BY0) and (BY1 thru H) have been done above. */ for (dy = BY0; dy < BY1; dy++) { /* * First the columns on the left (x = 0 thru BX0). If the X offset is 0 * then there is nothing to do. */ if (BX0 != 0) { memset(&yuv[0][dy * W], 16, BX0); memset(&yuv[1][dy / SS_V * W2], 128, BX0 / SS_H); memset(&yuv[2][dy / SS_V * W2], 128, BX0 / SS_H); } /* * Then the columns on the right (x = BX1 thru W). If the right border * start coincides with the frame size then there is nothing to do. */ if (W != BX1) { memset(&yuv[0][(dy * W) + BX1], 16, W - BX1); memset(&yuv[1][(dy/SS_V * W2) + BX1/SS_H], 128, (W - BX1)/SS_H); memset(&yuv[2][(dy/SS_V * W2) + BX1/SS_H], 128, (W - BX1)/SS_H); } } } void vertical_shift(u_char **yuv, int vshift, int vshiftY, int width, int height, int SS_H, int SS_V) { int downshiftY, downshiftUV, w2 = width / SS_H, v2; if ( vshift + vshiftY > 0 ) downshiftY = 1; else downshiftY = 0; vshiftY = abs(vshift + vshiftY); /* now shiftY is total Y shift */ if (vshift > 0) downshiftUV = 1; else { downshiftUV = 0; vshift = abs(vshift); } v2 = vshift / SS_V; if (downshiftY) { memmove(&yuv[0][vshiftY * width], &yuv[0][0], (height - vshiftY) * width); memset(&yuv[0][0], 16, vshiftY * width); } else { memmove(&yuv[0][0], &yuv[0][vshiftY * width], (height - vshiftY) * width); memset(&yuv[0][(height - vshiftY) * width], 16, vshiftY * width); } if (downshiftUV) { memmove( &yuv[1][v2 * w2], &yuv[1][0], (height - vshift) / SS_V * w2); memmove( &yuv[2][v2 * w2], &yuv[2][0], (height - vshift) / SS_V * w2); memset(&yuv[1][0], 128, v2 * w2); memset(&yuv[2][0], 128, v2 * w2); } else { memmove(&yuv[1][0], &yuv[1][v2 * w2], (height - vshift) / SS_V * w2); memmove(&yuv[2][0], &yuv[2][v2 * w2], (height - vshift) / SS_V * w2); memset(&yuv[1][((height - vshift) / SS_V) * w2], 128, v2 * w2); memset(&yuv[2][((height - vshift) / SS_V) * w2], 128, v2 * w2); } } static void usage(char *pgm) { fprintf(stderr, "%s: usage: [-v] [-h] [-M] [-b xoff,yoff,xsize,ysize] [-y num] [-Y num] [-N num] -n N\n", pgm); fprintf(stderr, "%s:\t-M = monochrome output\n", pgm); fprintf(stderr, "%s:\t-n N = horizontal shift count - must be multiple of 2 for 4:2:0, multiple of 4 for 4:1:1!\n", pgm); fprintf(stderr, "%s:\t-y num = Y-only horizontal shift count - need not be even\n", pgm); fprintf(stderr, "%s:\t\tpositive count shifts right\n",pgm); fprintf(stderr, "%s:\t\t0 passes the data thru unchanged\n",pgm); fprintf(stderr, "%s:\t\tnegative count shifts left\n", pgm); fprintf(stderr, "%s:\t-N num = vertical shift count - must be multiple of 4 for 4:2:0, multiple of 2 for 4:1:1!\n", pgm); fprintf(stderr, "%s:\t-Y num = Y-only vertical shift count - multiple of 2 for interlaced material\n", pgm); fprintf(stderr, "%s:\t\tnegative count shifts up\n", pgm); fprintf(stderr, "%s:\t\t0 does no vertical shift (is ignored)\n", pgm); fprintf(stderr, "%s:\t\tpositive count shifts down\n", pgm); fprintf(stderr, "%s:\t-b creates black border\n", pgm); fprintf(stderr, "%s:\tShifting is done before border creation\n", pgm); fprintf(stderr, "%s:\t-v print input stream info\n", pgm); fprintf(stderr, "%s:\t-h print this usage summary\n", pgm); exit(1); } mjpegtools-2.1.0/y4mutils/yuvmedianfilter.c0000644000175000017500000005475310503613644021376 0ustar glowwormglowworm/* * Copyright (C) 2001 Mike Bernson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Filter Based on code from Jim Cassburi filter: 2dclean * * This filter look around the current point for a radius and averages * this values that fall inside a threshold. */ #include #include #include #include #include #include #include "yuv4mpeg.h" #include "mjpeg_logging.h" #include "cpu_accel.h" #ifdef HAVE_ASM_MMX #include "mmx.h" #endif // must be less than 24 #define DIVISORBITS 20 int verbose = 1, domean8 = 0; uint8_t *input_frame[3]; uint8_t *output_frame[3]; void filter(int width, int height, uint8_t *const input[], uint8_t *output[]); void filter_buffer(int width, int height, int stride, int radius, int threshold, uint8_t * const input, uint8_t * const output); void filter_buffer_fast(int width, int height, int stride, int radius, int threshold, uint8_t * const input, uint8_t * const output); int threshold_luma = 2; int threshold_chroma = 2; int radius_luma = 2; int radius_chroma = 2; int interlace = -1; int param_skip = 0; int param_fast = 0; int param_weight_type = 0; /* 0 = use param_weight, 1 = 8, 2 = 2.667, 3 = 13.333, 4 = 24 */ double param_weight = -1.0; double cutoff = 0.3333333; #define NUMAVG 1024 unsigned long avg_replace[NUMAVG]; int divisor[NUMAVG],divoffset[NUMAVG]; int chroma_mode; int SS_H = 2; int SS_V = 2; static void Usage(char *name ) { fprintf(stderr, "Usage: %s: [-h] [-r num] [-R num] [-t num] [-T num] [-c cutoff] [-v num]\n" "-h - Print out this help\n" "-r - Radius for luma median (default: 2 pixels)\n" "-R - Radius for chroma median (default: 2 pixels)\n" "-t - Trigger luma threshold (default: 2 [0=disable])\n" "-T - Trigger chroma threshold (default: 2 [0=disable])\n" "-I - Interlacing 0=off 1=on (default: taken from yuv stream)\n" "-f - Fast mode (i.e. no trigger threshold, just simple mean)\n" "-w - Weight given to current pixel vs. pixel in radius (default: 8)\n" "-c - Fraction of pixels that must be within threshold (default: 0.333)\n" "-v - Verbosity [0..2]\n", name); } int main(int argc, char *argv[]) { int i; long long avg, total; int input_fd = 0; int output_fd = 1; int horz; int vert; int c; int frame_count; y4m_stream_info_t istream, ostream; y4m_frame_info_t iframe; y4m_accept_extensions(1); while((c = getopt(argc, argv, "r:R:t:T:v:S:hI:w:fc:")) != EOF) { switch(c) { case 'r': radius_luma = atoi(optarg); break; case 'R': radius_chroma = atoi(optarg); break; case 't': threshold_luma = atoi(optarg); break; case 'T': threshold_chroma = atoi(optarg); break; case 'I': interlace = atoi (optarg); if (interlace != 0 && interlace != 1) { Usage (argv[0]); exit (1); } break; case 'S': param_skip = atoi (optarg); break; case 'f': param_fast = 1; break; case 'w': if (strcmp (optarg, "8") == 0) param_weight_type = 1; else if (strcmp (optarg, "2.667") == 0) param_weight_type = 2; else if (strcmp (optarg, "13.333") == 0) param_weight_type = 3; else if (strcmp (optarg, "24") == 0) param_weight_type = 4; else param_weight_type = 0; param_weight = atof (optarg); break; case 'c': cutoff = atof(optarg); break; case 'v': verbose = atoi (optarg); if (verbose < 0 || verbose >2) { Usage (argv[0]); exit (1); } break; case 'h': Usage (argv[0]); default: exit(0); } } if( param_weight < 0 ) { if( param_fast ) param_weight = 8.0; else param_weight = 1.0; } for( i=1; i>1))/i; divoffset[i]=divisor[i]*(i>>1)+(divisor[i]>>1); } #ifdef HAVE_ASM_MMX if( cpu_accel() & ACCEL_X86_MMXEXT ) domean8=1; #endif mjpeg_info ("fast %d, weight type %d\n", param_fast, param_weight_type); if (radius_luma <= 0 || radius_chroma <= 0) mjpeg_error_exit1("radius values must be > 0!"); if (threshold_luma < 0 || threshold_chroma < 0) mjpeg_error_exit1("threshold values must be >= 0!"); (void)mjpeg_default_handler_verbosity(verbose); y4m_init_stream_info(&istream); y4m_init_stream_info(&ostream); y4m_init_frame_info(&iframe); i = y4m_read_stream_header(input_fd, &istream); if (i != Y4M_OK) mjpeg_error_exit1("Input stream error: %s", y4m_strerr(i)); if (y4m_si_get_plane_count(&istream) != 3) mjpeg_error_exit1("Only 3 plane formats supported"); chroma_mode = y4m_si_get_chroma(&istream); SS_H = y4m_chroma_ss_x_ratio(chroma_mode).d; SS_V = y4m_chroma_ss_y_ratio(chroma_mode).d; mjpeg_debug("chroma subsampling: %dH %dV\n",SS_H,SS_V); if (interlace == -1) { i = y4m_si_get_interlace(&istream); switch (i) { case Y4M_ILACE_NONE: interlace = 0; break; case Y4M_ILACE_BOTTOM_FIRST: case Y4M_ILACE_TOP_FIRST: interlace = 1; break; default: mjpeg_warn("Unknown interlacing '%d', assuming non-interlaced", i); interlace = 0; break; } } if( interlace && y4m_si_get_height(&istream) % 2 != 0 ) mjpeg_error_exit1("Input images have odd number of lines - can't treats as interlaced!" ); horz = y4m_si_get_width(&istream); vert = y4m_si_get_height(&istream); mjpeg_debug("width=%d height=%d luma_r=%d chroma_r=%d luma_t=%d chroma_t=%d", horz, vert, radius_luma, radius_chroma, threshold_luma, threshold_chroma); y4m_copy_stream_info(&ostream, &istream); input_frame[0] = malloc(horz * vert); input_frame[1] = malloc((horz / SS_H) * (vert / SS_V)); input_frame[2] = malloc((horz / SS_H) * (vert / SS_V)); output_frame[0] = malloc(horz * vert); output_frame[1] = malloc((horz / SS_H) * (vert / SS_V)); output_frame[2] = malloc((horz / SS_H) * (vert / SS_V)); y4m_write_stream_header(output_fd, &ostream); frame_count = 0; while (y4m_read_frame(input_fd, &istream, &iframe, input_frame) == Y4M_OK) { frame_count++; if (frame_count > param_skip) { filter(horz, vert, input_frame, output_frame); y4m_write_frame(output_fd, &ostream, &iframe, output_frame); } else y4m_write_frame(output_fd, &ostream, &iframe, input_frame); } for (total=0, avg=0, i=0; i < NUMAVG; i++) { total += avg_replace[i]; avg += avg_replace[i] * i; } mjpeg_info("frames=%d avg=%3.1f", frame_count, ((double)avg)/((double)total)); for (i=0; i < NUMAVG; i++) { mjpeg_debug( "%02d: %6.2f", i, (((double)avg_replace[i]) * 100.0)/(double)(total)); } y4m_fini_stream_info(&istream); y4m_fini_stream_info(&ostream); y4m_fini_frame_info(&iframe); exit(0); } void filter(int width, int height, uint8_t * const input[], uint8_t *output[]) { if (param_fast) { if( interlace ) { filter_buffer_fast(width, height/2, width*2, radius_luma, threshold_luma, input[0], output[0]); filter_buffer_fast(width, height/2, width*2, radius_luma, threshold_luma, input[0]+width, output[0]+width); filter_buffer_fast(width/SS_H, (height/SS_V)/2, (width/SS_H)*2, radius_chroma, threshold_chroma, input[1], output[1]); filter_buffer_fast(width/SS_H, (height/SS_V)/2, (width/SS_H)*2, radius_chroma, threshold_chroma, input[1]+width/SS_H, output[1]+width/SS_H); filter_buffer_fast(width/SS_H, (height/SS_V)/2, (width/SS_H)*2, radius_chroma, threshold_chroma, input[2], output[2]); filter_buffer_fast(width/SS_H, (height/SS_V)/2, (width/SS_H)*2, radius_chroma, threshold_chroma, input[2]+width/SS_H, output[2]+width/SS_H); } else { filter_buffer_fast(width, height, width, radius_luma, threshold_luma, input[0], output[0]); filter_buffer_fast(width/SS_H, height/SS_V, width/SS_H, radius_chroma, threshold_chroma, input[1], output[1]); filter_buffer_fast(width/SS_H, height/SS_V, width/SS_H, radius_chroma, threshold_chroma, input[2], output[2]); } } else { if( interlace ) { filter_buffer(width, height/2, width*2, radius_luma, threshold_luma, input[0], output[0]); filter_buffer(width, height/2, width*2, radius_luma, threshold_luma, input[0]+width, output[0]+width); filter_buffer(width/SS_H, (height/SS_V)/2, (width/SS_H)*2, radius_chroma, threshold_chroma, input[1], output[1]); filter_buffer(width/SS_H, (height/SS_V)/2, (width/SS_H)*2, radius_chroma, threshold_chroma, input[1]+width/SS_H, output[1]+width/SS_H); filter_buffer(width/SS_H, (height/SS_V)/2, (width/SS_H)*2, radius_chroma, threshold_chroma, input[2], output[2]); filter_buffer(width/SS_H, (height/SS_V)/2, (width/SS_H)*2, radius_chroma, threshold_chroma, input[2]+width/SS_H, output[2]+width/SS_H); } else { filter_buffer(width, height, width, radius_luma, threshold_luma, input[0], output[0]); filter_buffer(width/SS_H, height/SS_V, width/SS_H, radius_chroma, threshold_chroma, input[1], output[1]); filter_buffer(width/SS_H, height/SS_V, width/SS_H, radius_chroma, threshold_chroma, input[2], output[2]); } } } #ifdef HAVE_ASM_MMX static inline void mean8(unsigned char *refpix,unsigned char *pixel,int radius_count,int row_stride,int threshold,int8_t *diff,unsigned char *count) { int a,b; pxor_r2r(mm6,mm6); // mm6 (aka count) = 0 pxor_r2r(mm7,mm7); // mm7 (aka diff) = 0 movq_m2r(*refpix,mm3); // mm3 = refpix[0] movd_g2r(0x80808080,mm4); // mm4 = 128 punpcklbw_r2r(mm4,mm4); pxor_r2r(mm4,mm3); // mm3 = refpix[0]-128 movd_g2r(threshold,mm5); // mm5 = threshold punpcklbw_r2r(mm5,mm5); punpcklbw_r2r(mm5,mm5); punpcklbw_r2r(mm5,mm5); for( b=0; b abs(pixel[0]-refpix[0])) ? -1 : 0 psubb_r2r(mm1,mm6); // mm6 += (threshold > abs(pixel[0]-refpix[0])) pand_r2r(mm1,mm0); // mm0 = (threshold > abs(pixel[0]-refpix[0])) ? pixel[0]-refpix[0] : 0 paddb_r2r(mm0,mm7); // mm7 += (threshold > abs(pixel[0]-refpix[0])) ? pixel[0]-refpix[0] : 0 ++pixel; } pixel += row_stride - radius_count; } movq_r2m(mm6,*count); movq_r2m(mm7,*diff); emms(); } #endif static inline void mean1(unsigned char *refpix,unsigned char *pixel,int radius_count,int row_stride,int threshold,int8_t *diff,unsigned char *count) { int reference = *refpix; int total = 0; int cnt = 0; int a,b; for( b = radius_count; b > 0; --b ) { for( a = radius_count; a > 0; --a ) { int d = *pixel - reference; if (d < threshold && d > -threshold) { total += d; cnt++; } ++pixel; } pixel += (row_stride - radius_count); } *diff = total; *count = cnt; } static inline void tally(unsigned char *outpix,unsigned char *refpix,int total,int count,int min_count,int row_stride) { ++avg_replace[count]; /* * If we don't have enough samples to make a decent * pseudo-median use a simple mean */ if (count <= min_count) { *outpix = ( ( (refpix[-row_stride-1] + refpix[-row_stride]) + (refpix[-row_stride+1] + refpix[-1]) ) + ( ((refpix[0]<<3) + 8 + refpix[1]) + (refpix[row_stride-1] + refpix[row_stride]) + refpix[row_stride+1] ) ) >> 4; } else { count += param_weight - 1; //*outpix = (refpix[0]*count + total + count/2) / count; *outpix = refpix[0] + ((total * divisor[count] + divoffset[count])>>DIVISORBITS); } } void filter_buffer(int width, int height, int row_stride, int radius, int threshold, uint8_t * const input, uint8_t * const output) { int radius_count; int x; int y; int offset; int min_count; uint8_t *inpix, *refpix; uint8_t *outpix; static uint8_t count[8]; static int8_t total[8]; radius_count = radius + radius + 1; min_count = ceil((radius_count * radius_count) * cutoff); if (threshold == 0) { for (y = 0; y < height; y++) memcpy(&output[y * row_stride], &input[y * row_stride], width); return; } for(y=0; y < radius; y++) memcpy(&output[y * row_stride], &input[y * row_stride], width); for(y=height - radius; y < height; y++) memcpy(&output[y* row_stride], &input[y*row_stride], width); inpix = &input[0]; outpix = &output[0]; for(y=0; y < height; ++y) { x = 0; while(x> 5; ++avg_replace[9]; ++refpix; ++outpix; } refpix += (row_stride-width+(radius*2)); outpix += (row_stride-width+(radius*2)); } break; case 2: for(y=radius; y < height-radius; y++) { for(x=radius; x < width - radius; x++) { /* Radius 1, weight 8. The 8 pixels surrounding the current one have a weight of 1, the current pixel has a weight of 8, for a total weight of 8*1+8 = 16. */ *outpix = (((int)refpix[-row_stride-1] + (int)refpix[-row_stride] + (int)refpix[-row_stride+1] + (int)refpix[-1] + (int)refpix[1] + (int)refpix[row_stride-1] + (int)refpix[row_stride] + (int)refpix[row_stride+1]) + (((int)refpix[0])<<3) + 8) >> 4; ++avg_replace[9]; ++refpix; ++outpix; } refpix += (row_stride-width+(radius*2)); outpix += (row_stride-width+(radius*2)); } break; case 3: for(y=radius; y < height-radius; y++) { for(x=radius; x < width - radius; x++) { /* Radius 2, weight 8. The 24 pixels surrounding the current one have a weight of 1, the current pixel has a weight of 8, for a total weight of 24*1+8 = 32. */ *outpix = (((int)refpix[-row_stride-row_stride-2] + (int)refpix[-row_stride-row_stride-1] + (int)refpix[-row_stride-row_stride] + (int)refpix[-row_stride-row_stride+1] + (int)refpix[-row_stride-row_stride+2] + (int)refpix[-row_stride-2] + (int)refpix[-row_stride-1] + (int)refpix[-row_stride] + (int)refpix[-row_stride+1] + (int)refpix[-row_stride+2] + (int)refpix[-2] + (int)refpix[-1] + (int)refpix[1] + (int)refpix[2] + (int)refpix[row_stride-2] + (int)refpix[row_stride-1] + (int)refpix[row_stride] + (int)refpix[row_stride+1] + (int)refpix[row_stride+2] + (int)refpix[row_stride+row_stride-2] + (int)refpix[row_stride+row_stride-1] + (int)refpix[row_stride+row_stride] + (int)refpix[row_stride+row_stride+1] + (int)refpix[row_stride+row_stride+2]) + (((int)refpix[0])<<3) + 16) >> 5; ++avg_replace[25]; ++refpix; ++outpix; } refpix += (row_stride-width+(radius*2)); outpix += (row_stride-width+(radius*2)); } break; case 4: for(y=radius; y < height-radius; y++) { for(x=radius; x < width - radius; x++) { /* Radius 1, weight 13.333. The 8 pixels surrounding the current one have a weight of 3, the current pixel has a weight of 40, for a total weight of 8*3+40 = 64. */ *outpix = ((3 * ((int)refpix[-row_stride-1] + (int)refpix[-row_stride] + ((int)refpix[-row_stride+1] + (int)refpix[-1]) + (int)refpix[1] + (int)refpix[row_stride-1] + (int)refpix[row_stride] + (int)refpix[row_stride+1])) + (((int)refpix[0])*40) + 32) >> 6; ++avg_replace[9]; ++refpix; ++outpix; } refpix += (row_stride-width+(radius*2)); outpix += (row_stride-width+(radius*2)); } break; case 5: for(y=radius; y < height-radius; y++) { for(x=radius; x < width - radius; x++) { /* Radius 1, weight 24. The 8 pixels surrounding the current one have a weight of 1, the current pixel has a weight of 24, for a total weight of 8*1+24 = 32. */ *outpix = (((int)refpix[-row_stride-1] + (int)refpix[-row_stride] + (int)refpix[-row_stride+1] + (int)refpix[-1] + (int)refpix[1] + (int)refpix[row_stride-1] + (int)refpix[row_stride] + (int)refpix[row_stride+1]) + (((int)refpix[0])*24) + 16) >> 5; ++avg_replace[9]; ++refpix; ++outpix; } refpix += (row_stride-width+(radius*2)); outpix += (row_stride-width+(radius*2)); } break; default: for(y=radius; y < height-radius; y++) { for(x=radius; x < width - radius; x++) { /* Reset the total pixel value and the count of pixels found in the given radius. */ total = 0; count = 0; /* Now loop through all pixels in a radius around the current one, and add up their values, skipping the current pixel. */ pixel = refpix-offset; b = radius_count; while( b > 0 ) { a = radius_count; --b; while( a > 0 ) { --a; if (pixel != refpix) { total += *pixel; count++; } ++pixel; } pixel += (row_stride - radius_count); } ++avg_replace[count]; /* Finally, calculate the pixel's new value. */ *outpix = (total + (refpix[0] * param_weight) + (count >> 1)) / (count + param_weight); ++refpix; ++outpix; } refpix += (row_stride-width+(radius*2)); outpix += (row_stride-width+(radius*2)); } break; } } mjpegtools-2.1.0/y4mutils/y4mspatialfilter.c0000644000175000017500000003447611255224574021471 0ustar glowwormglowworm/* * y4mspatialfilter.c * * written by Dan Scholnik * spatial FIR filter for noise/bandwidth reduction without scaling * takes yuv4mpeg in and spits the same out * * Usage: y4mspatialfilter [-h] [-v] [-L luma_Xtaps,luma_XBW,luma_Ytaps,luma_YBW] * [-C chroma_Xtaps,chroma_XBW,chroma_Ytaps,chroma_YBW] */ #include "config.h" #include #include #include #include "yuv4mpeg.h" #include "cpu_accel.h" #ifdef HAVE_ASM_MMX #include "mmx.h" #endif #define MIN(a,b) (((a)<(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b)) static void *my_malloc(size_t); static struct filter *get_coeff(int, float); static void convolveFrame(u_char *src,int w,int h,int interlace,struct filter *xtap,struct filter *ytap,float *yuvtmp1,float *yuvtmp2); static void set_accel(int w,int h); static void usage(char *); static void (*pframe_i2f)(u_char *,float *,int); static void (*pframe_f2i)(float *,u_char *,int); static void (*pconvolveLine)(float *,int,int,int,struct filter *,int,float *); struct filter { int len; float **filters; float **qfilters; // for SSE/Altivec -- repeats the filter 4 times }; int main(int argc, char **argv) { int i, c, interlace, frames, err; int ywidth, yheight, uvwidth, uvheight, ylen, uvlen; int verbose = 0, fdin; int NlumaX = 4, NlumaY = 4, NchromaX = 4, NchromaY = 4; float BWlumaX = 0.8, BWlumaY = 0.8, BWchromaX = 0.7, BWchromaY = 0.7; struct filter *lumaXtaps, *lumaYtaps, *chromaXtaps, *chromaYtaps; u_char *yuvinout[3]; float *yuvtmp1,*yuvtmp2; y4m_stream_info_t istream, ostream; y4m_frame_info_t iframe; fdin = fileno(stdin); y4m_accept_extensions(1); /* read command line */ opterr = 0; while ((c = getopt(argc, argv, "hvL:C:x:X:y:Y:")) != EOF) { switch (c) { case 'L': sscanf(optarg,"%d,%f,%d,%f",&NlumaX,&BWlumaX,&NlumaY,&BWlumaY); break; case 'C': sscanf(optarg,"%d,%f,%d,%f",&NchromaX,&BWchromaX,&NchromaY,&BWchromaY); break; case 'x': sscanf(optarg,"%d,%f",&NchromaX,&BWchromaX); break; case 'X': sscanf(optarg,"%d,%f",&NlumaX,&BWlumaX); break; case 'y': sscanf(optarg,"%d,%f",&NchromaY,&BWchromaY); break; case 'Y': sscanf(optarg,"%d,%f",&NlumaY,&BWlumaY); break; case 'v': verbose++; break; case '?': case 'h': default: usage(argv[0]); } } if (BWlumaX <= 0.0 || BWlumaX > 1.0) mjpeg_error_exit1("Horizontal luma bandwidth '%f' not >0 and <=1.0", BWlumaX); if (BWlumaY <= 0.0 || BWlumaY > 1.0) mjpeg_error_exit1("Vertical luma bandwidth '%f' not >0 and <=1.0", BWlumaY); if (BWchromaX <= 0.0 || BWchromaX > 1.0) mjpeg_error_exit1("Horizontal chroma bandwidth '%f' not >0 and <=1.0", BWchromaX); if (BWchromaY <= 0.0 || BWchromaY > 1.0) mjpeg_error_exit1("Vertical chroma bandwidth '%f' not >0 and <=1.0", BWchromaY); /* initialize input stream and check chroma subsampling and interlacing */ y4m_init_stream_info(&istream); y4m_init_frame_info(&iframe); err = y4m_read_stream_header(fdin, &istream); if (err != Y4M_OK) mjpeg_error_exit1("Input stream error: %s\n", y4m_strerr(err)); if (y4m_si_get_plane_count(&istream) != 3) mjpeg_error_exit1("Only the 3 plane formats supported"); i = y4m_si_get_interlace(&istream); switch (i) { case Y4M_ILACE_NONE: interlace = 0; break; case Y4M_ILACE_BOTTOM_FIRST: case Y4M_ILACE_TOP_FIRST: interlace = 1; break; default: mjpeg_warn("Unknown interlacing '%d', assuming non-interlaced", i); interlace = 0; break; } ywidth = y4m_si_get_width(&istream); /* plane 0 = Y */ yheight = y4m_si_get_height(&istream); ylen = ywidth * yheight; uvwidth = y4m_si_get_plane_width(&istream, 1); /* planes 1&2 = U+V */ uvheight = y4m_si_get_plane_height(&istream, 1); uvlen = y4m_si_get_plane_length(&istream, 1); /* initialize output stream */ y4m_init_stream_info(&ostream); y4m_copy_stream_info(&ostream, &istream); y4m_write_stream_header(fileno(stdout), &ostream); /* allocate input and output buffers */ yuvinout[0] = my_malloc(ylen*sizeof(u_char)); yuvinout[1] = my_malloc(uvlen*sizeof(u_char)); yuvinout[2] = my_malloc(uvlen*sizeof(u_char)); yuvtmp1 = my_malloc(MAX(ylen,uvlen)*sizeof(float)); yuvtmp2 = my_malloc(MAX(ylen,uvlen)*sizeof(float)); /* get filter taps */ lumaXtaps = get_coeff(NlumaX, BWlumaX); lumaYtaps = get_coeff(NlumaY, BWlumaY); chromaXtaps = get_coeff(NchromaX, BWchromaX); chromaYtaps = get_coeff(NchromaY, BWchromaY); set_accel(uvwidth,uvheight); if (verbose) y4m_log_stream_info(mjpeg_loglev_t("info"), "", &istream); /* main processing loop */ for (frames=0; y4m_read_frame(fdin,&istream,&iframe,yuvinout) == Y4M_OK; frames++) { if (verbose && ((frames % 100) == 0)) mjpeg_info("Frame %d\n", frames); convolveFrame(yuvinout[0],ywidth,yheight,interlace,lumaXtaps,lumaYtaps,yuvtmp1,yuvtmp2); convolveFrame(yuvinout[1],uvwidth,uvheight,interlace,chromaXtaps,chromaYtaps,yuvtmp1,yuvtmp2); convolveFrame(yuvinout[2],uvwidth,uvheight,interlace,chromaXtaps,chromaYtaps,yuvtmp1,yuvtmp2); y4m_write_frame(fileno(stdout), &ostream, &iframe, yuvinout); } /* clean up */ y4m_fini_frame_info(&iframe); y4m_fini_stream_info(&istream); y4m_fini_stream_info(&ostream); exit(0); } /* Move memory allocation error checking here to clean up code */ /* Aligns values on 16 byte boundaries (to aid in vectorization) */ static void *my_malloc(size_t size) { void *tmp = malloc(size+15); unsigned long addr; if (tmp == NULL) mjpeg_error_exit1("malloc(%ld) failed\n", (long)size); addr=(unsigned long)tmp; addr=(addr+15)&(-16); return (void *)addr; } /* Compute 1D filter coefficients (center and right-side taps only) */ /* To minimize artifacts at the boundaries, compute filters of all sizes */ /* from 1 to length and use shorter filters near the edge of the frame */ /* Also, normalize to a DC gain of 1 */ static struct filter *get_coeff(int length, float bandwidth) { int n,k; struct filter *f; float sum; f=my_malloc(sizeof(struct filter)); f->len=length; f->filters=my_malloc((length+1)*sizeof(float *)); f->qfilters=my_malloc((length+1)*sizeof(float *)); /* C*sinc(C*n).*sinc(2*n/N); Lanczos-weighted */ for(k=0;k<=length;k++) { f->filters[k]=my_malloc((k+1)*sizeof(float *)); f->filters[k][0]=bandwidth; sum=f->filters[k][0]; for(n=1;n<=k;n++) { f->filters[k][n] = bandwidth * sin(M_PI*bandwidth*n)/(M_PI*bandwidth*n) * sin(M_PI*2*n/(2*k+1))/(M_PI*2.0*n/(2*k+1)); sum+=2*f->filters[k][n]; } for(n=0;n<=k;n++) f->filters[k][n]/=sum; // qfilters is the same as filters, but each element is repeated 4 times f->qfilters[k]=my_malloc(4*(k+1)*sizeof(float *)); for( n=0; n<(k+1)*4; n++ ) f->qfilters[k][n]=f->filters[k][n>>2]; } return f; } /* These three routines do the bulk of the work */ static void frame_i2f(u_char *src,float *dst,int l) { int i; for( i=0; ifilters[flen]; for( i=0; iqfilters[flen]; /* arg! why aren't these aligned? */ movups_m2r(all0[0], xmm6); movups_m2r(all255[0],xmm7); for( i=0; ilen;n++) { pconvolveLine(data,width,datastride,height,filter,n,output); data+=datastride; output+=outstride; } /* center, use full-width filter */ for(n=filter->len; nlen; n++) { pconvolveLine(data,width,datastride,height,filter,filter->len,output); data+=datastride; output+=outstride; } /* trailing edge, use filters of decreasing width */ for(n=datalength-filter->len;n #include #include #include "yuv4mpeg.h" #include "mjpeg_logging.h" static void usage(char *); int main(int argc, char **argv) { int chroma_id, fdin, fdout, c, verbose = 1, err, uvlen, ylen; char ilace = Y4M_ILACE_TOP_FIRST; y4m_stream_info_t ostream, istream; y4m_frame_info_t iframe, oframe; y4m_ratio_t rate_ratio = y4m_fps_UNKNOWN; u_char *f1_top[3], *f1_bot[3], *f2_top[3], *f2_bot[3]; u_char **top_field, **bot_field; fdin = fileno(stdin); fdout = fileno(stdout); y4m_accept_extensions(1); mjpeg_default_handler_verbosity(verbose); opterr = 0; while ((c = getopt(argc, argv, "hr:i:v:")) != EOF) { switch (c) { case 'i': if (strcmp("b", optarg) == 0) ilace = Y4M_ILACE_BOTTOM_FIRST; else if (strcmp("t", optarg) == 0) ilace = Y4M_ILACE_TOP_FIRST; else mjpeg_error_exit1("-i arg must be t or b"); break; case 'v': verbose = atoi(optarg); if (verbose < 0 || verbose >= 3) mjpeg_error_exit1("Verbosity [0..2]"); break; case 'r': err = y4m_parse_ratio(&rate_ratio, optarg); if (err != Y4M_OK) mjpeg_error_exit1("invalid/unparseable -r arg"); break; case '?': case 'h': default: usage(argv[0]); } } if (isatty(fdout)) mjpeg_error_exit1("stdout must not be a terminal"); mjpeg_default_handler_verbosity(verbose); y4m_init_stream_info(&istream); y4m_init_frame_info(&iframe); y4m_init_frame_info(&oframe); err = y4m_read_stream_header(fdin, &istream); if (err != Y4M_OK) mjpeg_error_exit1("Input stream error: %s\n", y4m_strerr(err)); if (y4m_si_get_interlace(&istream) != Y4M_ILACE_NONE) mjpeg_error_exit1("Input stream is NOT progressive!"); if (y4m_si_get_plane_count(&istream) != 3) mjpeg_error_exit1("Only the 3 plane formats supported."); chroma_id = y4m_si_get_chroma(&istream); if (y4m_chroma_ss_y_ratio(chroma_id).d != 1) mjpeg_warn("Vertically subsampled chroma (%s) should be upsampled but will proceed.", y4m_chroma_keyword(chroma_id)); /* * NOTE: each buffer to be allocated will only hold 1 field or 1/2 a frame. * thus the size is divided by 2 below */ ylen = y4m_si_get_plane_length(&istream, 0); /* luma size */ uvlen = y4m_si_get_plane_length(&istream, 1); /* chroma plane size */ /* First frame's two field buffers */ f1_top[0] = malloc(ylen / 2); f1_top[1] = malloc(uvlen / 2); f1_top[2] = malloc(uvlen / 2); f1_bot[0] = malloc(ylen / 2); f1_bot[1] = malloc(uvlen / 2); f1_bot[2] = malloc(uvlen / 2); /* Second frame's two field buffers */ f2_top[0] = malloc(ylen / 2); f2_top[1] = malloc(uvlen / 2); f2_top[2] = malloc(uvlen / 2); f2_bot[0] = malloc(ylen / 2); f2_bot[1] = malloc(uvlen / 2); f2_bot[2] = malloc(uvlen / 2); y4m_init_stream_info(&ostream); y4m_copy_stream_info(&ostream, &istream); if (Y4M_RATIO_EQL(rate_ratio, y4m_fps_UNKNOWN)) { rate_ratio = y4m_si_get_framerate(&istream); rate_ratio.d *= 2; y4m_ratio_reduce(&rate_ratio); } y4m_si_set_interlace(&ostream, ilace); y4m_si_set_framerate(&ostream, rate_ratio); y4m_log_stream_info(mjpeg_loglev_t("info"), "ostream", &ostream); y4m_write_stream_header(fdout, &ostream); while ((err = y4m_read_fields(fdin, &istream, &iframe, f1_top, f1_bot)) == Y4M_OK) { y4m_read_fields(fdin, &istream, &iframe, f2_top, f2_bot); if (ilace == Y4M_ILACE_TOP_FIRST) { top_field = f1_top; bot_field = f2_bot; } else { top_field = f2_top; bot_field = f1_bot; } y4m_write_fields(fdout,&ostream, &oframe, top_field, bot_field); } y4m_fini_frame_info(&iframe); y4m_fini_frame_info(&oframe); y4m_fini_stream_info(&istream); y4m_fini_stream_info(&ostream); exit(0); } static void usage(char *progname) { fprintf(stderr, "%s usage: [-v n] [-i t|b] [-r rate]\n", progname); fprintf(stderr, "%s\t-i defaults to (t) top field first\n", progname); fprintf(stderr, "%s\t-r overrides using (input rate)/2\n",progname); exit(0); } mjpegtools-2.1.0/y4mutils/Makefile.in0000644000175000017500000007110112217306410020044 0ustar glowwormglowworm# Makefile.in generated by automake 1.12.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Makefile for y4mutils VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @HAVE_ALTIVEC_TRUE@am__append_1 = $(top_builddir)/mpeg2enc/libmpeg2encpp.la bin_PROGRAMS = yuvmedianfilter$(EXEEXT) pgmtoy4m$(EXEEXT) \ y4mshift$(EXEEXT) y4mspatialfilter$(EXEEXT) y4mhist$(EXEEXT) \ y4mblack$(EXEEXT) y4mtoyuv$(EXEEXT) y4minterlace$(EXEEXT) \ yuv4mpeg$(EXEEXT) y4mivtc$(EXEEXT) yuyvtoy4m$(EXEEXT) \ $(am__EXEEXT_1) @HAVE_LIBQUICKTIME_TRUE@am__append_2 = y4mtoqt qttoy4m subdir = y4mutils DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = @HAVE_LIBQUICKTIME_TRUE@am__EXEEXT_1 = y4mtoqt$(EXEEXT) \ @HAVE_LIBQUICKTIME_TRUE@ qttoy4m$(EXEEXT) am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_pgmtoy4m_OBJECTS = pgmtoy4m.$(OBJEXT) pgmtoy4m_OBJECTS = $(am_pgmtoy4m_OBJECTS) pgmtoy4m_DEPENDENCIES = $(LIBMJPEGUTILS) am__qttoy4m_SOURCES_DIST = qttoy4m.c @HAVE_LIBQUICKTIME_TRUE@am_qttoy4m_OBJECTS = \ @HAVE_LIBQUICKTIME_TRUE@ qttoy4m-qttoy4m.$(OBJEXT) qttoy4m_OBJECTS = $(am_qttoy4m_OBJECTS) @HAVE_LIBQUICKTIME_TRUE@qttoy4m_DEPENDENCIES = $(LIBMJPEGUTILS) \ @HAVE_LIBQUICKTIME_TRUE@ $(top_builddir)/lavtools/liblavfile.la am_y4mblack_OBJECTS = y4mblack.$(OBJEXT) y4mblack_OBJECTS = $(am_y4mblack_OBJECTS) y4mblack_DEPENDENCIES = $(LIBMJPEGUTILS) am_y4mhist_OBJECTS = y4mhist.$(OBJEXT) y4mhist_OBJECTS = $(am_y4mhist_OBJECTS) am__DEPENDENCIES_1 = y4mhist_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(LIBMJPEGUTILS) am_y4minterlace_OBJECTS = y4minterlace.$(OBJEXT) y4minterlace_OBJECTS = $(am_y4minterlace_OBJECTS) y4minterlace_DEPENDENCIES = $(LIBMJPEGUTILS) am_y4mivtc_OBJECTS = y4mivtc.$(OBJEXT) y4mivtc_OBJECTS = $(am_y4mivtc_OBJECTS) y4mivtc_DEPENDENCIES = $(LIBMJPEGUTILS) am_y4mshift_OBJECTS = y4mshift.$(OBJEXT) y4mshift_OBJECTS = $(am_y4mshift_OBJECTS) y4mshift_DEPENDENCIES = $(LIBMJPEGUTILS) am_y4mspatialfilter_OBJECTS = y4mspatialfilter.$(OBJEXT) y4mspatialfilter_OBJECTS = $(am_y4mspatialfilter_OBJECTS) y4mspatialfilter_DEPENDENCIES = $(LIBMJPEGUTILS) $(am__DEPENDENCIES_1) am__y4mtoqt_SOURCES_DIST = y4mtoqt.c @HAVE_LIBQUICKTIME_TRUE@am_y4mtoqt_OBJECTS = \ @HAVE_LIBQUICKTIME_TRUE@ y4mtoqt-y4mtoqt.$(OBJEXT) y4mtoqt_OBJECTS = $(am_y4mtoqt_OBJECTS) @HAVE_LIBQUICKTIME_TRUE@y4mtoqt_DEPENDENCIES = $(LIBMJPEGUTILS) \ @HAVE_LIBQUICKTIME_TRUE@ $(top_builddir)/lavtools/liblavfile.la am_y4mtoyuv_OBJECTS = y4mtoyuv.$(OBJEXT) y4mtoyuv_OBJECTS = $(am_y4mtoyuv_OBJECTS) y4mtoyuv_DEPENDENCIES = $(LIBMJPEGUTILS) am_yuv4mpeg_OBJECTS = yuv4mpeg.$(OBJEXT) yuv4mpeg_OBJECTS = $(am_yuv4mpeg_OBJECTS) yuv4mpeg_DEPENDENCIES = $(LIBMJPEGUTILS) am_yuvmedianfilter_OBJECTS = yuvmedianfilter.$(OBJEXT) yuvmedianfilter_OBJECTS = $(am_yuvmedianfilter_OBJECTS) yuvmedianfilter_DEPENDENCIES = $(LIBMJPEGUTILS) am_yuyvtoy4m_OBJECTS = yuyvtoy4m.$(OBJEXT) yuyvtoy4m_OBJECTS = $(am_yuyvtoy4m_OBJECTS) yuyvtoy4m_DEPENDENCIES = $(LIBMJPEGUTILS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(pgmtoy4m_SOURCES) $(qttoy4m_SOURCES) $(y4mblack_SOURCES) \ $(y4mhist_SOURCES) $(y4minterlace_SOURCES) $(y4mivtc_SOURCES) \ $(y4mshift_SOURCES) $(y4mspatialfilter_SOURCES) \ $(y4mtoqt_SOURCES) $(y4mtoyuv_SOURCES) $(yuv4mpeg_SOURCES) \ $(yuvmedianfilter_SOURCES) $(yuyvtoy4m_SOURCES) DIST_SOURCES = $(pgmtoy4m_SOURCES) $(am__qttoy4m_SOURCES_DIST) \ $(y4mblack_SOURCES) $(y4mhist_SOURCES) $(y4minterlace_SOURCES) \ $(y4mivtc_SOURCES) $(y4mshift_SOURCES) \ $(y4mspatialfilter_SOURCES) $(am__y4mtoqt_SOURCES_DIST) \ $(y4mtoyuv_SOURCES) $(yuv4mpeg_SOURCES) \ $(yuvmedianfilter_SOURCES) $(yuyvtoy4m_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALTIVEC_EXTRA_LIBS = @ALTIVEC_EXTRA_LIBS@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDV_CFLAGS = @LIBDV_CFLAGS@ LIBDV_LIBS = @LIBDV_LIBS@ LIBGETOPT_LIB = @LIBGETOPT_LIB@ LIBM_LIBS = @LIBM_LIBS@ LIBOBJS = @LIBOBJS@ LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ LIBPNG_LIBS = @LIBPNG_LIBS@ LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@ LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ LT_STATIC = @LT_STATIC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROGRAM_NOPIC = @PROGRAM_NOPIC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ SDLgfx_LIBS = @SDLgfx_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ V4LCONF_LIBS = @V4LCONF_LIBS@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAINTAINERCLEANFILES = Makefile.in AM_CFLAGS = @PROGRAM_NOPIC@ AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/utils LIBMJPEGUTILS = $(top_builddir)/utils/libmjpegutils.la $(am__append_1) y4mivtc_SOURCES = y4mivtc.c y4mivtc_LDADD = $(LIBMJPEGUTILS) yuvmedianfilter_SOURCES = yuvmedianfilter.c yuvmedianfilter_LDADD = $(LIBMJPEGUTILS) pgmtoy4m_SOURCES = pgmtoy4m.c pgmtoy4m_LDADD = $(LIBMJPEGUTILS) y4mshift_SOURCES = y4mshift.c y4mshift_LDADD = $(LIBMJPEGUTILS) y4mspatialfilter_SOURCES = y4mspatialfilter.c y4mspatialfilter_LDADD = $(LIBMJPEGUTILS) $(LIBM_LIBS) y4mhist_SOURCES = y4mhist.c y4mhist_LDADD = $(SDL_LIBS) $(SDLgfx_LIBS) $(LIBMJPEGUTILS) y4mblack_SOURCES = y4mblack.c y4mblack_LDADD = $(LIBMJPEGUTILS) y4minterlace_SOURCES = y4minterlace.c y4minterlace_LDADD = $(LIBMJPEGUTILS) @HAVE_LIBQUICKTIME_TRUE@y4mtoqt_SOURCES = y4mtoqt.c @HAVE_LIBQUICKTIME_TRUE@y4mtoqt_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/lavtools $(LIBQUICKTIME_CFLAGS) @HAVE_LIBQUICKTIME_TRUE@y4mtoqt_LDADD = $(LIBMJPEGUTILS) $(top_builddir)/lavtools/liblavfile.la @HAVE_LIBQUICKTIME_TRUE@qttoy4m_SOURCES = qttoy4m.c @HAVE_LIBQUICKTIME_TRUE@qttoy4m_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/lavtools $(LIBQUICKTIME_CFLAGS) @HAVE_LIBQUICKTIME_TRUE@qttoy4m_LDADD = $(LIBMJPEGUTILS) $(top_builddir)/lavtools/liblavfile.la y4mtoyuv_SOURCES = y4mtoyuv.c y4mtoyuv_LDADD = $(LIBMJPEGUTILS) yuv4mpeg_SOURCES = yuv4mpeg.c yuv4mpeg_LDADD = $(LIBMJPEGUTILS) yuyvtoy4m_SOURCES = yuyvtoy4m.c yuyvtoy4m_LDADD = $(LIBMJPEGUTILS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu y4mutils/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu y4mutils/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list pgmtoy4m$(EXEEXT): $(pgmtoy4m_OBJECTS) $(pgmtoy4m_DEPENDENCIES) $(EXTRA_pgmtoy4m_DEPENDENCIES) @rm -f pgmtoy4m$(EXEEXT) $(LINK) $(pgmtoy4m_OBJECTS) $(pgmtoy4m_LDADD) $(LIBS) qttoy4m$(EXEEXT): $(qttoy4m_OBJECTS) $(qttoy4m_DEPENDENCIES) $(EXTRA_qttoy4m_DEPENDENCIES) @rm -f qttoy4m$(EXEEXT) $(LINK) $(qttoy4m_OBJECTS) $(qttoy4m_LDADD) $(LIBS) y4mblack$(EXEEXT): $(y4mblack_OBJECTS) $(y4mblack_DEPENDENCIES) $(EXTRA_y4mblack_DEPENDENCIES) @rm -f y4mblack$(EXEEXT) $(LINK) $(y4mblack_OBJECTS) $(y4mblack_LDADD) $(LIBS) y4mhist$(EXEEXT): $(y4mhist_OBJECTS) $(y4mhist_DEPENDENCIES) $(EXTRA_y4mhist_DEPENDENCIES) @rm -f y4mhist$(EXEEXT) $(LINK) $(y4mhist_OBJECTS) $(y4mhist_LDADD) $(LIBS) y4minterlace$(EXEEXT): $(y4minterlace_OBJECTS) $(y4minterlace_DEPENDENCIES) $(EXTRA_y4minterlace_DEPENDENCIES) @rm -f y4minterlace$(EXEEXT) $(LINK) $(y4minterlace_OBJECTS) $(y4minterlace_LDADD) $(LIBS) y4mivtc$(EXEEXT): $(y4mivtc_OBJECTS) $(y4mivtc_DEPENDENCIES) $(EXTRA_y4mivtc_DEPENDENCIES) @rm -f y4mivtc$(EXEEXT) $(LINK) $(y4mivtc_OBJECTS) $(y4mivtc_LDADD) $(LIBS) y4mshift$(EXEEXT): $(y4mshift_OBJECTS) $(y4mshift_DEPENDENCIES) $(EXTRA_y4mshift_DEPENDENCIES) @rm -f y4mshift$(EXEEXT) $(LINK) $(y4mshift_OBJECTS) $(y4mshift_LDADD) $(LIBS) y4mspatialfilter$(EXEEXT): $(y4mspatialfilter_OBJECTS) $(y4mspatialfilter_DEPENDENCIES) $(EXTRA_y4mspatialfilter_DEPENDENCIES) @rm -f y4mspatialfilter$(EXEEXT) $(LINK) $(y4mspatialfilter_OBJECTS) $(y4mspatialfilter_LDADD) $(LIBS) y4mtoqt$(EXEEXT): $(y4mtoqt_OBJECTS) $(y4mtoqt_DEPENDENCIES) $(EXTRA_y4mtoqt_DEPENDENCIES) @rm -f y4mtoqt$(EXEEXT) $(LINK) $(y4mtoqt_OBJECTS) $(y4mtoqt_LDADD) $(LIBS) y4mtoyuv$(EXEEXT): $(y4mtoyuv_OBJECTS) $(y4mtoyuv_DEPENDENCIES) $(EXTRA_y4mtoyuv_DEPENDENCIES) @rm -f y4mtoyuv$(EXEEXT) $(LINK) $(y4mtoyuv_OBJECTS) $(y4mtoyuv_LDADD) $(LIBS) yuv4mpeg$(EXEEXT): $(yuv4mpeg_OBJECTS) $(yuv4mpeg_DEPENDENCIES) $(EXTRA_yuv4mpeg_DEPENDENCIES) @rm -f yuv4mpeg$(EXEEXT) $(LINK) $(yuv4mpeg_OBJECTS) $(yuv4mpeg_LDADD) $(LIBS) yuvmedianfilter$(EXEEXT): $(yuvmedianfilter_OBJECTS) $(yuvmedianfilter_DEPENDENCIES) $(EXTRA_yuvmedianfilter_DEPENDENCIES) @rm -f yuvmedianfilter$(EXEEXT) $(LINK) $(yuvmedianfilter_OBJECTS) $(yuvmedianfilter_LDADD) $(LIBS) yuyvtoy4m$(EXEEXT): $(yuyvtoy4m_OBJECTS) $(yuyvtoy4m_DEPENDENCIES) $(EXTRA_yuyvtoy4m_DEPENDENCIES) @rm -f yuyvtoy4m$(EXEEXT) $(LINK) $(yuyvtoy4m_OBJECTS) $(yuyvtoy4m_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pgmtoy4m.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qttoy4m-qttoy4m.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/y4mblack.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/y4mhist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/y4minterlace.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/y4mivtc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/y4mshift.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/y4mspatialfilter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/y4mtoqt-y4mtoqt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/y4mtoyuv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuv4mpeg.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuvmedianfilter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuyvtoy4m.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< qttoy4m-qttoy4m.o: qttoy4m.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(qttoy4m_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT qttoy4m-qttoy4m.o -MD -MP -MF $(DEPDIR)/qttoy4m-qttoy4m.Tpo -c -o qttoy4m-qttoy4m.o `test -f 'qttoy4m.c' || echo '$(srcdir)/'`qttoy4m.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/qttoy4m-qttoy4m.Tpo $(DEPDIR)/qttoy4m-qttoy4m.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='qttoy4m.c' object='qttoy4m-qttoy4m.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(qttoy4m_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o qttoy4m-qttoy4m.o `test -f 'qttoy4m.c' || echo '$(srcdir)/'`qttoy4m.c qttoy4m-qttoy4m.obj: qttoy4m.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(qttoy4m_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT qttoy4m-qttoy4m.obj -MD -MP -MF $(DEPDIR)/qttoy4m-qttoy4m.Tpo -c -o qttoy4m-qttoy4m.obj `if test -f 'qttoy4m.c'; then $(CYGPATH_W) 'qttoy4m.c'; else $(CYGPATH_W) '$(srcdir)/qttoy4m.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/qttoy4m-qttoy4m.Tpo $(DEPDIR)/qttoy4m-qttoy4m.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='qttoy4m.c' object='qttoy4m-qttoy4m.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(qttoy4m_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o qttoy4m-qttoy4m.obj `if test -f 'qttoy4m.c'; then $(CYGPATH_W) 'qttoy4m.c'; else $(CYGPATH_W) '$(srcdir)/qttoy4m.c'; fi` y4mtoqt-y4mtoqt.o: y4mtoqt.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(y4mtoqt_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT y4mtoqt-y4mtoqt.o -MD -MP -MF $(DEPDIR)/y4mtoqt-y4mtoqt.Tpo -c -o y4mtoqt-y4mtoqt.o `test -f 'y4mtoqt.c' || echo '$(srcdir)/'`y4mtoqt.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/y4mtoqt-y4mtoqt.Tpo $(DEPDIR)/y4mtoqt-y4mtoqt.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='y4mtoqt.c' object='y4mtoqt-y4mtoqt.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(y4mtoqt_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o y4mtoqt-y4mtoqt.o `test -f 'y4mtoqt.c' || echo '$(srcdir)/'`y4mtoqt.c y4mtoqt-y4mtoqt.obj: y4mtoqt.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(y4mtoqt_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT y4mtoqt-y4mtoqt.obj -MD -MP -MF $(DEPDIR)/y4mtoqt-y4mtoqt.Tpo -c -o y4mtoqt-y4mtoqt.obj `if test -f 'y4mtoqt.c'; then $(CYGPATH_W) 'y4mtoqt.c'; else $(CYGPATH_W) '$(srcdir)/y4mtoqt.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/y4mtoqt-y4mtoqt.Tpo $(DEPDIR)/y4mtoqt-y4mtoqt.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='y4mtoqt.c' object='y4mtoqt-y4mtoqt.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(y4mtoqt_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o y4mtoqt-y4mtoqt.obj `if test -f 'y4mtoqt.c'; then $(CYGPATH_W) 'y4mtoqt.c'; else $(CYGPATH_W) '$(srcdir)/y4mtoqt.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool cscopelist ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mjpegtools-2.1.0/y4mutils/y4mtoqt.c0000644000175000017500000002127510620506170017574 0ustar glowwormglowworm/* * $Id: y4mtoqt.c,v 1.13 2007/05/10 03:07:36 sms00 Exp $ * * Utility to place 4:2:2 or 4:4:4 YUV4MPEG2 data in a Quicktime wrapper. An * audio track can also be added by specifying '-a wavfile' (16bit pcm only). * The interlacing, frame rate, frame size and field order are extracted * from the YUV4MPEG2 header. This is the reverse of 'qttoy4m' which dumps * planar data from a Quicktime file (and optionally a specified audio track * to a wav file). * * Usage: y4mtoqt [-X] [-a wavfile] -o outputfile < 422yuv4mpeg2stream * * -X enables 10bit packed output, 2vuy becomes v210 and v308 becomes v410. */ #include "config.h" #include #include #include #include #include #include "yuv4mpeg.h" #include "avilib.h" static void usage(void); static void do_audio(quicktime_t *, uint8_t *, int, int, int); int main(int argc, char **argv) { char *outfilename = NULL; char *audiofilename = NULL; uint8_t *yuv[3], *p; uint16_t *p16; uint16_t *yuv10[3]; int fdin, y_len, u_len, v_len, nfields = 1, dominance = 0, afd = -1; int imodel = 0, allow_wrong_yv12 = 0; int err, i, c, frames, channels = 0, y4mchroma, tenbit = 0; char *qtchroma = NULL; quicktime_t *qtf; quicktime_pasp_t pasp; #if 0 quicktime_colr_t colr; #endif quicktime_clap_t clap; y4m_stream_info_t istream; y4m_frame_info_t iframe; y4m_ratio_t rate, sar; struct wave_header wavhdr; y4m_accept_extensions(1); fdin = fileno(stdin); opterr = 0; while ((c = getopt(argc, argv, "ko:a:X")) != -1) { switch (c) { case 'k': allow_wrong_yv12 = 1; break; case 'X': tenbit = 1; break; case 'o': outfilename = optarg; break; case 'a': audiofilename = optarg; break; case '?': default: usage(); } } argc -= optind; argv += optind; if (argc) usage(); if (!outfilename) usage(); if (audiofilename) { afd = open(audiofilename, O_RDONLY); if (afd < 0) mjpeg_error_exit1("Can not open audio file '%s'", audiofilename); if (AVI_read_wave_header(afd, &wavhdr) == -1) mjpeg_error_exit1("'%s' is not a valid WAV file", audiofilename); channels = wavhdr.common.wChannels; } y4m_init_stream_info(&istream); y4m_init_frame_info(&iframe); err = y4m_read_stream_header(fdin, &istream); if (err != Y4M_OK) mjpeg_error_exit1("Input header error: %s", y4m_strerr(err)); if (y4m_si_get_plane_count(&istream) != 3) mjpeg_error_exit1("Only 3 plane formats supported"); rate = y4m_si_get_framerate(&istream); switch (y4mchroma = y4m_si_get_chroma(&istream)) { case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420JPEG: /* * Quicktime doesn't appear to have a way to reliably * tell the two non-PALDV variants apart so treat them * both the same (like most other software in the world) */ qtchroma = QUICKTIME_YUV420; /* yv12 */ imodel = BC_YUV420P; break; case Y4M_CHROMA_422: if (tenbit) qtchroma = QUICKTIME_V210; else { qtchroma = QUICKTIME_2VUY; imodel = BC_YUV422P; /* Input is planar */ } break; case Y4M_CHROMA_444: if (tenbit) qtchroma = QUICKTIME_V410; else { qtchroma = QUICKTIME_V308; imodel = BC_YUV444P; /* Need this?? */ } break; default: mjpeg_error_exit1("unsupported chroma sampling: %s", y4m_chroma_keyword(y4mchroma)); break; } y_len = y4m_si_get_plane_length(&istream, 0); u_len = y4m_si_get_plane_length(&istream, 1); v_len = y4m_si_get_plane_length(&istream, 2); yuv[0] = malloc(y_len); yuv[1] = malloc(u_len); yuv[2] = malloc(v_len); if (tenbit) { yuv10[0] = malloc(y_len * sizeof(uint16_t)); yuv10[1] = malloc(u_len * sizeof(uint16_t)); yuv10[2] = malloc(v_len * sizeof(uint16_t)); } qtf = quicktime_open(outfilename, 0, 1); if (!qtf) mjpeg_error_exit1("quicktime_open(%s,0,1) failed", outfilename); quicktime_set_video(qtf, 1, y4m_si_get_width(&istream), y4m_si_get_height(&istream), (double) rate.n / rate.d, qtchroma); if (imodel != 0) lqt_set_cmodel(qtf, 0, imodel); if (audiofilename) quicktime_set_audio(qtf, channels, wavhdr.common.dwSamplesPerSec, wavhdr.common.wBitsPerSample, QUICKTIME_TWOS); /* * http://developer.apple.com/quicktime/icefloe/dispatch019.html#fiel * * "dominance" is what Apple calls "detail". From what I can figure out * the "bottom field" first corresponds to a "detail" setting of 14 and * "top field first" is a "detail" setting of 9. */ switch (y4m_si_get_interlace(&istream)) { case Y4M_ILACE_BOTTOM_FIRST: dominance = 14; /* Weird but that's what Apple says */ nfields = 2; break; case Y4M_ILACE_TOP_FIRST: dominance = 9; nfields = 2; break; case Y4M_UNKNOWN: case Y4M_ILACE_NONE: dominance = 0; nfields = 1; break; case Y4M_ILACE_MIXED: mjpeg_error_exit1("Mixed field dominance unsupported"); break; default: mjpeg_error_exit1("UNKNOWN field dominance %d", y4m_si_get_interlace(&istream)); break; } if (lqt_set_fiel(qtf, 0, nfields, dominance) == 0) mjpeg_error_exit1("lqt_set_fiel(qtf, 0, %d, %d) failed", nfields, dominance); sar = y4m_si_get_sampleaspect(&istream); if (Y4M_RATIO_EQL(sar, y4m_sar_UNKNOWN)) pasp.hSpacing = pasp.vSpacing = 1; else { pasp.hSpacing = sar.n; pasp.vSpacing = sar.d; } if (lqt_set_pasp(qtf, 0, &pasp) == 0) mjpeg_error_exit1("lqt_set_pasp(qtf, 0, %d/%d) failed", pasp.hSpacing, pasp.vSpacing); /* * Don't do this for now - it can crash FinalCutPro if the colr atom is * not exactly correct. */ #if 0 colr.colorParamType = 'nclc'; colr.primaries = 2; colr.transferFunction = 2; colr.matrix = 2; if (lqt_set_colr(qtf, 0, &colr) == 0) mjpeg_error_exit1("lqt_set_colr(qtf, 0,...) failed"); #endif clap.cleanApertureWidthN = y4m_si_get_width (&istream);; clap.cleanApertureWidthD = 1; clap.cleanApertureHeightN = y4m_si_get_height (&istream); clap.cleanApertureHeightD = 1; clap.horizOffN = 0; clap.horizOffD = 1; clap.vertOffN = 0; clap.vertOffD = 1; if (lqt_set_clap(qtf, 0, &clap) == 0) mjpeg_error_exit1("lqt_set_clap(qtf, 0, ...) failed"); for (;y4m_read_frame(fdin,&istream,&iframe,yuv) == Y4M_OK; frames++) { if (tenbit) { p = yuv[0]; p16 = yuv10[0]; for (i = 0; i < y_len; i++) *p16++ = *p++ << 8; p = yuv[1]; p16 = yuv10[1]; for (i = 0; i < u_len; i++) *p16++ = *p++ << 8; p = yuv[2]; p16 = yuv10[2]; for (i = 0; i < v_len; i++) *p16++ = *p++ << 8; } /* * What libquicktime calls 'yv12' (QUICKTIME_YUV420) is actually 'iyuv' * (also known as 'i420'). In order to make the data match the fourcc/label * the U and V planes need to be swapped. After all, if the file is labeled * 'yv12' then the data should be in 'yv12' order! * * Breakage, for compatiblity with quicktime4linux, can be forced by using * '-k'. This allows storing 'iyuv' ('i420') data inside a file that is * labeled as 'yv12' :( * * It should be noted that very very little outside of V4L knows anything * about uncompressed 4:2:0 - the 4:2:0 color space is used but only with * compressed formats it seems. */ if (strcmp(qtchroma, QUICKTIME_YUV420) == 0) { if (allow_wrong_yv12 == 0) { p = yuv[1]; yuv[1] = yuv[2]; yuv[2] = p; } } err = quicktime_encode_video(qtf, tenbit ? (uint8_t **)yuv10: yuv, 0); if (err != 0) mjpeg_error_exit1("quicktime_encode_video failed."); } if (audiofilename) { uint8_t *buffer; int bufsize, n, bps; mjpeg_info("channels %d SamplesPerSec %d bits_sample %d", channels, wavhdr.common.dwSamplesPerSec, wavhdr.common.wBitsPerSample); bps = (wavhdr.common.wBitsPerSample + 7)/8; bufsize = 8192 * channels * bps; buffer = malloc(bufsize); while ((n = AVI_read_wave_pcm_data(afd, buffer, bufsize)) > 0) do_audio(qtf, buffer, channels, bps, n / (channels * bps)); } quicktime_close(qtf); exit(0); } static void do_audio(quicktime_t *qtf, uint8_t *buff, int channels, int bps, int samps) { int res; int i, j; int16_t *qt_audio = (int16_t *)buff, **qt_audion; qt_audion = malloc(channels * sizeof (int16_t **)); for (i = 0; i < channels; i++) qt_audion[i] = (int16_t *)malloc(samps * bps); /* Deinterleave the audio into separate channel buffers */ for (i = 0; i < samps; i++) { for (j = 0; j < channels; j++) qt_audion[j][i] = qt_audio[(channels*i) + j]; } res = lqt_encode_audio_track(qtf, qt_audion, NULL, samps, 0); for (j = 0; j < channels; j++) free(qt_audion[j]); free(qt_audion); } static void usage() { mjpeg_warn("usage: [-k] [-X] [-a inputwavfile] -o outfile"); mjpeg_warn(" -X = use v210 (default 2vuy) for 4:2:2, v410 (default v308) for 4:4:4"); mjpeg_warn(" -k = do not perform lqt workaround (U and V plane swap) (default 0 - i.e. DO the workaround)"); exit(1); } mjpegtools-2.1.0/y4mutils/yuv4mpeg.c0000644000175000017500000001412411255224574017740 0ustar glowwormglowworm/* * $Id: yuv4mpeg.c,v 1.3 2009/09/19 18:57:00 sms00 Exp $ * * A simple progam that's quite useful when dealing with raw/headerless data * from programs such as ffmpeg or fxtv. * * Used to convert standard EYUV to YUV4MPEG2 which is the format used by * mpeg2enc from the mjpeg-tools suite. The main difference between EYUV * and YUV4MPEG2 is a header line giving the dimensions and framerate code * plus a FRAME marker. * * If the -x option is given the input data can be in 4:1:1 format and the * necessary X tag will be added to the YUV4MPEG2 header. This is useful * with programs such as ffmpeg that can produce raw 411 output from NTSC DV * files. * * This is strictly a filter, the use is in a pipeline such as the following * which extracts the PPM data from a video capture, pipes that thru ppmtoeyuv * and then on to this program and finally either into mpeg2enc or to a file. * * fxtv ... | ppmtoeyuv | yuv4mpeg -w W -h H -r M:N | yuvscaler | mpeg2enc ... * * To use ffmpeg to decode DV files, fast denoise, convert to 4:2:0 and * display (or encode): * * ffmpeg -i file.dv -an -f rawvideo -pix_fmt yuv411p /dev/stdout | * yuv4mpeg -x -a 10:11 -w 720 -h 480 -r 30000:1001 -i b | * yuvdenoise -S 0 -f | * y4mscaler -O chromass=420_MPEG2 | * yuvplay (or mpeg2enc -o -f 8 ...) * * The -a, -r, -w and -h values given are the defaults and need not have been * given. The -i (interlace) will default to NONE ('p' or progressive) and * must usually be specified on the command line. * * yuv4mpeg can also be used to catenate multiple pure (headerless) EYUV files: * * cat *.yuv | yuv4mpeg -w W -h H -r M:N | mpeg2enc ... * * The U and V planes can be swapped by using '-k'. This is used to convert * from YV12 which the transcode utilities generate and the IYUV (aka YUV420) * which mpeg2enc wants. * * NOTE: Obviously when catenating multiple files together they ALL must have * the same attributes (dimensions, framerate, etc)! * * NOTE: The "-x" option, if used, specifies the chroma format of the INPUT * and places in the output stream the correct 'C' tag. */ #include "config.h" #include #include #include #include #include "yuv4mpeg.h" static void usage(char *); static void chroma_usage(char *); int main(int argc, char **argv) { int sts, c, width = 720, height = 480, swapuv = 0, ylen, uvlen; int chroma_mode = Y4M_CHROMA_420MPEG2; y4m_ratio_t rate_ratio = y4m_fps_NTSC; y4m_ratio_t aspect_ratio = y4m_sar_NTSC_CCIR601; u_char *yuv[3]; y4m_stream_info_t ostream; y4m_frame_info_t oframe; char interlace = Y4M_ILACE_NONE; opterr = 0; while ((c = getopt(argc, argv, "kw:h:r:i:a:x:")) != EOF) { switch (c) { case 'x': chroma_mode = y4m_chroma_parse_keyword(optarg); if (chroma_mode == Y4M_UNKNOWN) { if (strcmp(optarg, "help") != 0) mjpeg_error("Invalid -x arg '%s'", optarg); chroma_usage(argv[0]); } break; case 'k': swapuv = 1; break; case 'a': sts = y4m_parse_ratio(&aspect_ratio, optarg); if (sts != Y4M_OK) mjpeg_error_exit1("Invalid aspect: %s", optarg); break; case 'w': width = atoi(optarg); break; case 'h': height = atoi(optarg); break; case 'r': sts = y4m_parse_ratio(&rate_ratio, optarg); if (sts != Y4M_OK) mjpeg_error_exit1("Invalid rate: %s", optarg); break; case 'i': switch (optarg[0]) { case 'p': interlace = Y4M_ILACE_NONE; break; case 't': interlace = Y4M_ILACE_TOP_FIRST; break; case 'b': interlace = Y4M_ILACE_BOTTOM_FIRST; break; default: usage(argv[0]); } break; case '?': default: usage(argv[0]); } } if (width <= 0) mjpeg_error_exit1("Invalid Width: %d", width); if (height <= 0) mjpeg_error_exit1("Invalid Height: %d", height); y4m_accept_extensions(1); y4m_init_stream_info(&ostream); y4m_init_frame_info(&oframe); y4m_si_set_width(&ostream, width); y4m_si_set_height(&ostream, height); y4m_si_set_interlace(&ostream, interlace); y4m_si_set_framerate(&ostream, rate_ratio); y4m_si_set_sampleaspect(&ostream, aspect_ratio); y4m_si_set_chroma(&ostream, chroma_mode); if (y4m_si_get_plane_count(&ostream) != 3) mjpeg_error_exit1("Only the 3 plane formats supported"); /* * The assumption is made that the two chroma planes are the same size - can't * see how it would be anything else... */ ylen= y4m_si_get_plane_length(&ostream, 0); uvlen = y4m_si_get_plane_length(&ostream, 1); yuv[0] = malloc(ylen); yuv[1] = malloc(uvlen); yuv[2] = malloc(uvlen); y4m_write_stream_header(fileno(stdout), &ostream); while (1) { if (y4m_read(fileno(stdin), yuv[0], ylen)) break; if (swapuv) { if (y4m_read(fileno(stdin), yuv[2], uvlen)) break; if (y4m_read(fileno(stdin), yuv[1], uvlen)) break; } else { if (y4m_read(fileno(stdin), yuv[1], uvlen)) break; if (y4m_read(fileno(stdin), yuv[2], uvlen)) break; } y4m_write_frame(fileno(stdout), &ostream, &oframe, yuv); } free(yuv[0]); free(yuv[1]); free(yuv[2]); y4m_fini_stream_info(&ostream); y4m_fini_frame_info(&oframe); exit(0); } static void usage(char *pgm) { fprintf(stderr, "%s usage: [-k] -w width -h height [-x chroma] [-a pixel aspect] [-i p|t|b] -r rate\n", pgm); fprintf(stderr, " Swap U and V: -k\n"); fprintf(stderr, " Interlace codes [-i X]: p (none) t (top first) b (bottom first)\n"); fprintf(stderr, " Rate (as ratio) [-r N:M] (30000:1001):\n"); fprintf(stderr, " Pixel aspect (as ratio) [-a N:M] (10:11):\n"); fprintf(stderr, " Specify chroma format [-x string] (420mpeg2)\n"); fprintf(stderr, " -x help for list of formats\n"); fprintf(stderr, " NOTE: Only the 3 plane formats supported"); fprintf(stderr, "\n"); exit(1); } void chroma_usage(char *pgm) { int mode = 0; const char *keyword; fprintf(stderr, "%s -x usage: Only the 3 plane formats are actually supported\n", pgm); for (mode = 0; (keyword = y4m_chroma_keyword(mode)) != NULL; mode++) fprintf(stderr, "\t%s - %s\n", keyword, y4m_chroma_description(mode)); exit(1); } mjpegtools-2.1.0/y4mutils/y4mtoyuv.c0000644000175000017500000000401110603772216017767 0ustar glowwormglowworm/* * $Id: y4mtoyuv.c,v 1.3 2007/04/01 18:06:06 sms00 Exp $ * * Simple program to convert the YUV4MPEG2 format used by the * mjpeg.sourceforge.net suite of programs into pure EYUV format used * by the mpeg4ip project and other programs. * * 2001/10/19 - Rewritten to use the y4m_* routines from mjpegtools. * 2004/1/1 - Added XYSCSS tag handling to deal with 411, 422, 444 data * 2004/4/5 - Rewritten to use the new YUV4MPEG2 API. */ #include "config.h" #include #include #include #include "yuv4mpeg.h" #include "mjpeg_logging.h" static void usage(void); int main(int argc, char **argv) { int c, err; int fd_in = fileno(stdin), fd_out = fileno(stdout); u_char *yuv[3]; int plane_length[3]; y4m_stream_info_t istream; y4m_frame_info_t iframe; opterr = 0; while ((c = getopt(argc, argv, "h")) != EOF) { switch (c) { case 'h': case '?': default: usage(); } } y4m_accept_extensions(1); y4m_init_stream_info(&istream); y4m_init_frame_info(&iframe); err = y4m_read_stream_header(fd_in, &istream); if (err != Y4M_OK) mjpeg_error_exit1("Input stream error: %s\n", y4m_strerr(err)); if (y4m_si_get_plane_count(&istream) != 3) mjpeg_error_exit1("only 3 plane formats supported"); plane_length[0] = y4m_si_get_plane_length(&istream, 0); plane_length[1] = y4m_si_get_plane_length(&istream, 1); plane_length[2] = y4m_si_get_plane_length(&istream, 2); yuv[0] = malloc(plane_length[0]); yuv[1] = malloc(plane_length[1]); yuv[2] = malloc(plane_length[2]); y4m_log_stream_info(mjpeg_loglev_t("info"), "", &istream); while (y4m_read_frame(fd_in, &istream, &iframe, yuv) == Y4M_OK) { if (y4m_write(fd_out, yuv[0], plane_length[0]) != Y4M_OK) break; if (y4m_write(fd_out, yuv[1], plane_length[1]) != Y4M_OK) break; if (y4m_write(fd_out, yuv[2], plane_length[2]) != Y4M_OK) break; } y4m_fini_frame_info(&iframe); y4m_fini_stream_info(&istream); exit(0); } static void usage() { mjpeg_error_exit1(" file.yuv"); /* NOTREACHED */ } mjpegtools-2.1.0/y4mutils/y4mhist.c0000644000175000017500000004454612216627211017565 0ustar glowwormglowworm/* * $Id: y4mhist.c,v 1.13 2013/07/17 23:59:09 sms00 Exp $ * * Simple program to print a crude histogram of the Y'CbCr values for YUV4MPEG2 * stream. Usually used with a small number (single) of frames but that's not * a requirement. Reads stdin until end of stream and then prints the Y'CbCr * counts. */ #include "config.h" #include #include #include #include unsigned long long y_stats[256], u_stats[256], v_stats[256]; unsigned long long fy_stats[256], fu_stats[256], fv_stats[256]; unsigned long long ly_stats[256], lu_stats[256], lv_stats[256]; unsigned char vectorfield[260][260]; int scalepercent; /* the l?_stats means till last frame, and f?_stat means the actual frame */ /* For the graphical history output */ #ifdef HAVE_SDLgfx #include #include /* Defining some colors */ #define white 0xFFFFFFFF #define black 0x000000FF #define red 0xFF0000FF #define blue 0x0000FFFF #define gray 0xA5A5A5FF /* Defining the size of the screen */ #define width 640 #define width_v 940 /* when we use the vectorscope whe have a differnet size */ #define heigth 590 /* Defining where the histograms are */ #define sum1_x 40 #define sum1_y 30 #define frm1_x 340 #define frm1_y 30 #define sum2_x 40 #define sum2_y 180 #define frm2_x 340 #define frm2_y 180 #define sum3_x 40 #define sum3_y 340 #define frm3_x 340 #define frm3_y 340 #define stat 490 #define vector_x 790 #define vector_y 200 /* needed for SDL */ SDL_Surface *screen; int desired_bpp; Uint32 video_flags; long number_of_frames; void HandleEvent() { SDL_Event event; /* Check for events */ while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_KEYDOWN: case SDL_QUIT: exit(0); } } } void ClearScreen(SDL_Surface *screen) { int i; /* Set the screen to black */ if (SDL_LockSurface(screen) == 0 ) { Uint32 Black; Uint8 *pixels; Black = SDL_MapRGB(screen->format, 0, 0, 0); pixels = (Uint8 *)screen->pixels; for ( i=0; ih; ++i ) { memset(pixels, Black, screen->w*screen->format->BytesPerPixel); pixels += screen->pitch; } SDL_UnlockSurface(screen); } } /* Here we draw the layout of the histogram */ void draw_histogram_layout(int x_off, int y_off) { int i, offset; char text[3]; hlineColor(screen, x_off, x_off+257, y_off+101 , white); vlineColor(screen, x_off-1, y_off, y_off+101, white); vlineColor(screen, x_off+257,y_off,y_off+101, white); if (scalepercent == 0) { for (i = 0; i < 15; i++) { offset = i*16+ 16; vlineColor(screen, x_off+offset, y_off+101, y_off+105, white); } vlineColor(screen, x_off+128, y_off+106, y_off+110, white); /* Description of the axis */ stringColor(screen, x_off-5 +16 , y_off+115, "16", white); stringColor(screen, x_off-9 +128, y_off+115, "128", white); stringColor(screen, x_off-9 +240, y_off+115, "240", white); } else { for (i =0; i< 11;i++) { offset = (int)i*21.9 + 16; vlineColor(screen, x_off+offset, y_off+101, y_off+105, white); } } for (i = 0; i < 6; i++) /*Labeling the y axis in percent */ { hlineColor(screen, x_off-5, x_off, y_off+ i*20, white); offset = 100- i*20; sprintf(text, "%i", offset); stringColor(screen, x_off-30 , y_off+ i*20 -3 , text, white); } } /* init the screen */ void y4m_init_area(SDL_Surface *screen) { /* Drawing for the summ of frames */ draw_histogram_layout(sum1_x, sum1_y); draw_histogram_layout(frm1_x, frm1_y); draw_histogram_layout(sum2_x, sum2_y); draw_histogram_layout(frm2_x, frm2_y); draw_histogram_layout(sum3_x, sum3_y); draw_histogram_layout(frm3_x, frm3_y); SDL_UpdateRect(screen,0,0,0,0); } void make_text(int x_off, int y_off, char text[25]) { boxColor(screen, x_off, y_off-20, x_off+256, y_off-5, black); stringColor(screen, x_off+10, y_off-12, text, white); } /* Here we draw the text description for the histograms */ void make_histogram_desc(long number_of_frames) { char framestat[25]; sprintf(framestat, "Y Stat till frame %ld", number_of_frames); make_text(sum1_x, sum1_y, framestat); sprintf(framestat, "U Stat till frame %ld", number_of_frames); make_text(sum2_x, sum2_y, framestat); sprintf(framestat, "V Stat till frame %ld", number_of_frames); make_text(sum3_x, sum3_y, framestat); sprintf(framestat, "Y Stat curent frame"); make_text(frm1_x, frm1_y, framestat); sprintf(framestat, "U Stat curent frame"); make_text(frm2_x, frm2_y, framestat); sprintf(framestat, "V Stat curent frame"); make_text(frm3_x, frm3_y, framestat); } /* Here we draw the souroundings for the color points */ void makepoint(int laeng, int winkel) { int p1_x, p1_y, p2_x, p2_y; int sm,la; sm = 5; la = 10; /* That 57,3 makes the conversation from Grad to radiant */ p1_x = round ( (laeng+la) * cos ((winkel-10) /57.3) ); p1_y = round ( (laeng+la) * sin ((winkel-10) /57.3) ); p2_x = round ( (laeng+sm) * cos ((winkel-10) /57.3) ); p2_y = round ( (laeng+sm) * sin ((winkel-10) /57.3) ); lineColor(screen, vector_x + p1_x, vector_y - p1_y, vector_x + p2_x, vector_y - p2_y,blue); p2_x = round ( (laeng+la) * cos ((winkel-5) /57.3) ); p2_y = round ( (laeng+la) * sin ((winkel-5) /57.3) ); lineColor(screen, vector_x + p1_x, vector_y - p1_y, vector_x + p2_x, vector_y - p2_y,blue); p1_x = round ( (laeng-la) * cos ((winkel-10) /57.3) ); p1_y = round ( (laeng-la) * sin ((winkel-10) /57.3) ); p2_x = round ( (laeng-sm) * cos ((winkel-10) /57.3) ); p2_y = round ( (laeng-sm) * sin ((winkel-10) /57.3) ); lineColor(screen, vector_x + p1_x, vector_y - p1_y, vector_x + p2_x, vector_y - p2_y,blue); p2_x = round ( (laeng-la) * cos ((winkel-5) /57.3) ); p2_y = round ( (laeng-la) * sin ((winkel-5) /57.3) ); lineColor(screen, vector_x + p1_x, vector_y - p1_y, vector_x + p2_x, vector_y - p2_y,blue); p1_x = round ( (laeng+la) * cos ((winkel+10) /57.3) ); p1_y = round ( (laeng+la) * sin ((winkel+10) /57.3) ); p2_x = round ( (laeng+sm) * cos ((winkel+10) /57.3) ); p2_y = round ( (laeng+sm) * sin ((winkel+10) /57.3) ); lineColor(screen, vector_x + p1_x, vector_y - p1_y, vector_x + p2_x, vector_y - p2_y,blue); p2_x = round ( (laeng+la) * cos ((winkel+5) /57.3) ); p2_y = round ( (laeng+la) * sin ((winkel+5) /57.3) ); lineColor(screen, vector_x + p1_x, vector_y - p1_y, vector_x + p2_x, vector_y - p2_y,blue); p1_x = round ( (laeng-la) * cos ((winkel+10) /57.3) ); p1_y = round ( (laeng-la) * sin ((winkel+10) /57.3) ); p2_x = round ( (laeng-sm) * cos ((winkel+10) /57.3) ); p2_y = round ( (laeng-sm) * sin ((winkel+10) /57.3) ); lineColor(screen, vector_x + p1_x, vector_y - p1_y, vector_x + p2_x, vector_y - p2_y,blue); p2_x = round ( (laeng-la) * cos ((winkel+5) /57.3) ); p2_y = round ( (laeng-la) * sin ((winkel+5) /57.3) ); lineColor(screen, vector_x + p1_x, vector_y - p1_y, vector_x + p2_x, vector_y - p2_y,blue); //mjpeg_debug(" 1x %i, 1y %i, 2x %i, 2y %i", p1_x, p1_y, p2_x, p2_y); } /* Here we draw the vectorscope layout */ void make_vectorscope_layout() { int i, p1_x, p1_y, p2_x, p2_y; double temp; char text[4]; boxColor(screen, vector_x-130, vector_y+130, vector_x+130, vector_y-130, black); hlineColor(screen, vector_x-20, vector_x-128, vector_y, white); hlineColor(screen, vector_x+20, vector_x+128, vector_y, white); vlineColor(screen, vector_x, vector_y-20, vector_y-128, white); vlineColor(screen, vector_x, vector_y+20, vector_y+128, white); circleColor(screen,vector_x, vector_y, 20, white); circleColor(screen,vector_x, vector_y, 50, white); circleColor(screen,vector_x, vector_y, 80, white); circleColor(screen,vector_x, vector_y,112, white); for (i =0; i<36; i++) { /* Here we draw the degree scale */ temp = 112* cos (i*(10/57.3)) ; /* sin & cos only accept radiant */ p1_x = round(temp); /* and not degree input */ temp = 112* sin (i*(10/57.3) ); p1_y = round(temp); temp = 117* cos (i*(10/57.3) ); p2_x = round(temp); temp = 117* sin (i*(10/57.3) ); p2_y = round(temp); lineColor(screen, vector_x + p1_x, vector_y + p1_y, vector_x + p2_x, vector_y + p2_y, white); } sprintf(text, "0"); /* Creating the grad description */ stringColor(screen, vector_x + 135 , vector_y - 3, text, white); sprintf(text, "90"); stringColor(screen, vector_x - 7 , vector_y - 145, text, white); sprintf(text, "180"); stringColor(screen, vector_x - 155 , vector_y - 3, text, white); sprintf(text, "270"); stringColor(screen, vector_x - 10 , vector_y + 135, text, white); makepoint( 90, 60); /* length, arc, for purple */ makepoint( 96, 104); /* length, arc, for red */ makepoint( 67, 166); /* length, arc, for yellow */ makepoint( 90, 241); /* length, arc, for green */ makepoint( 96, 283); /* length, arc, for cyan */ makepoint( 67, 346); /* length, arc, for blue */ } /* Here we draw the histogram statistice for the summ of the frames */ void make_histogram_stat(int peak_y, int peak_u, int peak_v, int x_off, int y_off) { char framestat[25]; sprintf(framestat, "Peak Y at : %i", peak_y); stringColor(screen, x_off+10, y_off+10, framestat, white); sprintf(framestat, "Peak U at : %i", peak_u); stringColor(screen, x_off+10, y_off+25, framestat, white); sprintf(framestat, "Peak V at : %i", peak_v); stringColor(screen, x_off+10, y_off+40, framestat, white); } /* Here we delete the old histograms */ void clear_histogram_area() { /* clearing the histogram areas */ boxColor(screen, sum1_x, sum1_y-1, sum1_x+256, sum1_y+100, black); boxColor(screen, sum2_x, sum2_y-1, sum2_x+256, sum2_y+100, black); boxColor(screen, sum3_x, sum3_y-1, sum3_x+256, sum3_y+100, black); boxColor(screen, frm1_x, frm1_y-1, frm1_x+256, frm1_y+100, black); boxColor(screen, frm2_x, frm2_y-1, frm2_x+256, frm2_y+100, black); boxColor(screen, frm3_x, frm3_y-1, frm3_x+256, frm3_y+100, black); /* clearing frame statistics */ boxColor(screen, sum1_x,stat, frm1_x+256,stat+90,black); } /* Show the frame stat */ void make_stat() { int percent_y, percent_u, percent_v, percent_fy, percent_fu, percent_fv; long long num_pixels_y, num_pixels_u, num_pixels_v; long long f_pixels_y, f_pixels_u, f_pixels_v; int peak_y, peak_u, peak_v, peak_fy, peak_fu, peak_fv; int i,j; peak_y = 0; peak_u = 0; peak_v = 0; peak_fy = 0; peak_fu = 0; peak_fv = 0; num_pixels_y = y_stats[0]; num_pixels_u = u_stats[0]; num_pixels_v = v_stats[0]; f_pixels_y = fy_stats[0]; f_pixels_u = fu_stats[0]; f_pixels_v = fv_stats[0]; /* geting the maimal number for all frames */ for (i = 0; i < 255; i++) { /* getting the maximal numbers for Y, U, V for all frames */ if (num_pixels_y < y_stats[i]) { num_pixels_y = y_stats[i]; peak_y = i; } if (num_pixels_u < u_stats[i]) { num_pixels_u = u_stats[i]; peak_u = i; } if (num_pixels_v < v_stats[i]) { num_pixels_v = v_stats[i]; peak_v = i; } /* getting the maximal numbers for Y, U, V for the current frame */ fy_stats[i]= y_stats[i] - ly_stats[i]; ly_stats[i] = y_stats[i]; if (f_pixels_y < fy_stats[i]) { f_pixels_y = fy_stats[i]; peak_fy = i; } fu_stats[i]= u_stats[i] - lu_stats[i]; lu_stats[i] = u_stats[i]; if (f_pixels_u < fu_stats[i]) { f_pixels_u = fu_stats[i]; peak_fu = i; } fv_stats[i]= v_stats[i] - lv_stats[i]; lv_stats[i] = v_stats[i]; if (f_pixels_v < fv_stats[i]) { f_pixels_v = fv_stats[i]; peak_fv = i; } } num_pixels_y = (num_pixels_y /100); num_pixels_u = (num_pixels_u /100); num_pixels_v = (num_pixels_v /100); f_pixels_y = (f_pixels_y /100); f_pixels_u = (f_pixels_u /100); f_pixels_v = (f_pixels_v /100); /* The description for the histogram */ make_histogram_desc(number_of_frames); number_of_frames++; make_vectorscope_layout(); /*draw the vectorscope basic layout*/ clear_histogram_area(); /* Here we delete the old histograms */ make_histogram_stat(peak_y, peak_u, peak_v, sum1_x, stat); make_histogram_stat(peak_fy, peak_fu, peak_fv, frm1_x , stat); for (i = 0; i < 255; i++) { percent_y = (y_stats[i] / num_pixels_y); percent_u = (u_stats[i] / num_pixels_u); percent_v = (v_stats[i] / num_pixels_v); percent_fy = (fy_stats[i] / f_pixels_y); percent_fu = (fu_stats[i] / f_pixels_u); percent_fv = (fv_stats[i] / f_pixels_v); if ((i < 16) || (i > 235)) /* Y luma */ { /* Red means out of the allowed range */ vlineColor(screen,(sum1_x+i),sum1_y+100, ((sum1_y+100)-percent_y),red); vlineColor(screen,(frm1_x+i),frm1_y+100, ((frm1_y+100)-percent_fy),red); } else { vlineColor(screen,(sum1_x+i),sum1_y+100, ((sum1_y+100)-percent_y),gray); vlineColor(screen,(frm1_x+i),frm1_y+100, ((frm1_y+100)-percent_fy),gray); } if ((i < 16) || (i > 240)) /* U V chroma */ { /* Red means out of the allowed range */ vlineColor(screen,(sum2_x+i),sum2_y+100, ((sum2_y+100)-percent_u),red); vlineColor(screen,(sum3_x+i),sum3_y+100, ((sum3_y+100)-percent_v),red); vlineColor(screen,(frm2_x+i),frm2_y+100, ((frm2_y+100)-percent_fu),red); vlineColor(screen,(frm3_x+i),frm3_y+100, ((frm3_y+100)-percent_fv),red); } else { vlineColor(screen,(sum2_x+i),sum2_y+100, ((sum2_y+100)-percent_u),gray); vlineColor(screen,(sum3_x+i),sum3_y+100, ((sum3_y+100)-percent_v),gray); vlineColor(screen,(frm2_x+i),frm2_y+100, ((frm2_y+100)-percent_fu),gray); vlineColor(screen,(frm3_x+i),frm3_y+100, ((frm3_y+100)-percent_fv),gray); } } for (i=0; i < 260; i++) for (j=0; j < 260; j++) if (vectorfield[i][j]== 1) pixelColor(screen, (vector_x+ i- 127), (vector_y+ j- 132) ,red); SDL_UpdateRect(screen,0,0,0,0); } #endif /* HAVE_SDLgfx */ static void usage(void) { fprintf(stderr, "usage: [-t] [-p] [-s num] \n"); fprintf(stderr, " -t emit text summary even if graphical mode enabled\n"); fprintf(stderr, " -p label the scale in percent not absolute numbers\n"); fprintf(stderr, " -s num enable also the vectorscope, allowed numbers 1-16\n"); exit(1); } int main(int argc, char **argv) { int i, fdin, ss_v, ss_h, chroma_ss, textout; int do_vectorscope; int pwidth, pheight; /* Needed for the vectorscope */ int plane0_l, plane1_l, plane2_l; u_char *yuv[3], *cp; #ifdef HAVE_SDLgfx int j; int temp_x, temp_y; u_char *cpx, *cpy; #endif y4m_stream_info_t istream; y4m_frame_info_t iframe; do_vectorscope = 0; scalepercent = 0; #ifdef HAVE_SDLgfx textout = 0; #else textout = 1; #endif while ((i = getopt(argc, argv, "tps:")) != EOF) { switch (i) { case 't': textout = 1; break; case 'p': scalepercent = 1; break; case 's': do_vectorscope = atoi(optarg); break; default: usage(); } } #ifdef HAVE_SDLgfx if ( (do_vectorscope < 0) || (do_vectorscope >16) ) usage(); /* Initialize SDL */ desired_bpp = 8; video_flags = 0; video_flags |= SDL_DOUBLEBUF; number_of_frames = 1; memset(fy_stats, '\0', sizeof (fy_stats)); memset(ly_stats, '\0', sizeof (ly_stats)); if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) mjpeg_error_exit1("Couldn't initialize SDL:%s",SDL_GetError()); atexit(SDL_Quit); /* Clean up on exit */ /* Initialize the display */ if (do_vectorscope == 0) screen = SDL_SetVideoMode(width,heigth,desired_bpp,video_flags); else screen=SDL_SetVideoMode(width_v,heigth,desired_bpp,video_flags); if (screen == NULL) mjpeg_error_exit1("Couldn't set %dx%dx%d video mode: %s", width, heigth, desired_bpp, SDL_GetError()); SDL_WM_SetCaption("y4mhistogram", "y4mhistogram"); y4m_init_area(screen); /* Here we draw the basic layout */ #endif /* HAVE_SDLgfx */ fdin = fileno(stdin); y4m_accept_extensions(1); y4m_init_stream_info(&istream); y4m_init_frame_info(&iframe); if (y4m_read_stream_header(fdin, &istream) != Y4M_OK) mjpeg_error_exit1("stream header error"); if (y4m_si_get_plane_count(&istream) != 3) mjpeg_error_exit1("Only 3 plane formats supported"); pwidth = y4m_si_get_width(&istream); pheight = y4m_si_get_height(&istream); chroma_ss = y4m_si_get_chroma(&istream); ss_h = y4m_chroma_ss_x_ratio(chroma_ss).d; ss_v = y4m_chroma_ss_y_ratio(chroma_ss).d; plane0_l = y4m_si_get_plane_length(&istream, 0); plane1_l = y4m_si_get_plane_length(&istream, 1); plane2_l = y4m_si_get_plane_length(&istream, 2); yuv[0] = malloc(plane0_l); if (yuv[0] == NULL) mjpeg_error_exit1("malloc(%d) plane 0", plane0_l); yuv[1] = malloc(plane1_l); if (yuv[1] == NULL) mjpeg_error_exit1(" malloc(%d) plane 1", plane1_l); yuv[2] = malloc(plane2_l); if (yuv[2] == NULL) mjpeg_error_exit1(" malloc(%d) plane 2\n", plane2_l); while (y4m_read_frame(fdin,&istream,&iframe,yuv) == Y4M_OK) { for (i = 0, cp = yuv[0]; i < plane0_l; i++, cp++) y_stats[*cp]++; /* Y' */ for (i = 0, cp = yuv[1]; i < plane1_l; i++, cp++) u_stats[*cp]++; /* U */ for (i = 0, cp = yuv[2]; i < plane2_l; i++, cp++) v_stats[*cp]++; /* V */ #ifdef HAVE_SDLgfx if (do_vectorscope >= 1 ) { for (i=0; i<260; i++) /* Resetting the vectorfield */ for (j=0;j<260;j++) vectorfield[i][j]=0; cpx = yuv[1]; cpy = yuv[2]; for (i=0; i < (pheight/ss_h); i++) { for (j = 0; j < (pwidth/ss_v); j++) { cpx++; cpy++; /* Have no idea why I have to multiply it with that values But than the vectorsscope works correct. If someone has a explantion or better fix tell me. Bernhard */ temp_x = round( 128+ ((*cpx-128) * 0.7857) ); temp_y = round( 128+ ((*cpy-128) * 1.1143) ); vectorfield[temp_x][temp_y*-1]=1; } /* Here we got to the n'th next line if needed */ i = i + (do_vectorscope-1); cpy = cpy + (pwidth/ss_v) * (do_vectorscope-1); cpx = cpx + (pwidth/ss_v) * (do_vectorscope-1); } } make_stat(); /* showing the sats */ SDL_UpdateRect(screen,0,0,0,0); /* updating all */ /* Events for SDL */ HandleEvent(); #endif } y4m_fini_frame_info(&iframe); y4m_fini_stream_info(&istream); if (textout) { for (i = 0; i < 255; i++) printf("Y %d %lld\n", i, y_stats[i]); for (i = 0; i < 255; i++) printf("U %d %lld\n", i, u_stats[i]); for (i = 0; i < 255; i++) printf("V %d %lld\n", i, v_stats[i]); } exit(0); } mjpegtools-2.1.0/y4mutils/y4mivtc.c0000644000175000017500000001314210433117426017550 0ustar glowwormglowworm/* * $Id: y4mivtc.c,v 1.2 2006/05/18 16:21:42 sms00 Exp $ * * Simple program to remove the 2:3 pulldown from a YUV4MPEG2 stream. This * was written because yuvkineco only works with TOP field first streams and * the 'hack' of using "yuvcorrect -T TOP_FORWARD" introduces a phase error * that prevents yuvkineco from finding/locking-on-to the correct cadence. * * With a 2:3 pulldown 4 film frames are converted into 5 video frames by * repeating fields. The four film frames are usually called "A", "B", "C" * and "D". The 2:3 pulldown process emits: * * A1/A2 B1/B2 B1/C2 C1/D2 D1/D2 * * Reversing that process means reading the first two frames and sending them * to the output unchanged. The next two frames are "combined" by taking * the 'C2' field from frame 3 and using that with 'C1' from frame 4 to create * the original C frame. The last frame is output directly as the 'D' frame. * * NOTE: The file MUST start on the 5 frame boundary containing the 2:3 * sequence! No attempt is made to determine if the file begins with * the "A" frame or not. Also editing can destroy the cadence - if you * edit a file with 2:3 pulldown you have to be careful to make your * edits on the 5 frame boundary containing the complete 2:3:2:3 sequence. * * REMEMBER: Correct 2:3 pulldown removal can only be done if the data starts * on a 2:3:2: boundary AND there are no breaks in cadence. * * You have been warned :) * * 2006/3/13 - Initial release. */ #include "config.h" #include #include #include #include "yuv4mpeg.h" #include "mjpeg_logging.h" static void usage(void); int main(int argc, char **argv) { int c, err, ilace; int fd_in = fileno(stdin), fd_out = fileno(stdout); y4m_ratio_t rate; y4m_stream_info_t si, so; y4m_frame_info_t fi; uint8_t *top1[3], *bot1[3], *top2[3], *bot2[3]; opterr = 0; while ((c = getopt(argc, argv, "h")) != EOF) { switch (c) { case 'h': case '?': default: usage(); } } y4m_accept_extensions(1); y4m_init_stream_info(&si); y4m_init_stream_info(&so); y4m_init_frame_info(&fi); err = y4m_read_stream_header(fd_in, &si); if (err != Y4M_OK) mjpeg_error_exit1("Input stream error: %s\n", y4m_strerr(err)); if (y4m_si_get_plane_count(&si) != 3) mjpeg_error_exit1("only 3 plane formats supported"); rate = y4m_si_get_framerate(&si); if (!Y4M_RATIO_EQL(rate, y4m_fps_NTSC)) mjpeg_error_exit1("input stream not NTSC 30000:1001"); ilace = y4m_si_get_interlace(&si); if (ilace != Y4M_ILACE_BOTTOM_FIRST && ilace != Y4M_ILACE_TOP_FIRST) mjpeg_error_exit1("input stream not interlaced"); top1[0] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,0) / 2); top1[1] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,1) / 2); top1[2] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,2) / 2); bot1[0] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,0) / 2); bot1[1] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,1) / 2); bot1[2] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,2) / 2); top2[0] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,0) / 2); top2[1] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,1) / 2); top2[2] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,2) / 2); bot2[0] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,0) / 2); bot2[1] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,1) / 2); bot2[2] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,2) / 2); y4m_copy_stream_info(&so, &si); y4m_si_set_framerate(&so, y4m_fps_NTSC_FILM); y4m_si_set_interlace(&so, Y4M_ILACE_NONE); /* * At this point the input stream has been verified to be interlaced NTSC, * the output stream rate set to NTSC_FILM, interlacing tag changed to * progressive, and the field buffers allocated. * * Time to write the output stream header and commence processing input. */ y4m_write_stream_header(fd_out, &so); while (1) { err = y4m_read_fields(fd_in, &si, &fi, top1, bot1); if (err != Y4M_OK) goto done; y4m_write_fields(fd_out, &so, &fi, top1, bot1); /* A */ err = y4m_read_fields(fd_in, &si, &fi, top1, bot1); if (err != Y4M_OK) goto done; y4m_write_fields(fd_out, &so, &fi, top1, bot1); /* B */ err = y4m_read_fields(fd_in, &si, &fi, top1, bot1); if (err != Y4M_OK) goto done; err = y4m_read_fields(fd_in, &si, &fi, top2, bot2); if (err != Y4M_OK) { /* * End of input when reading the 2nd "mixed field" frame (C+D). The previous * frame was the first "mixed field" frame (B+C). Rather than emit a mixed * interlaced frame duplicate a field and output the previous frame. */ if (ilace == Y4M_ILACE_BOTTOM_FIRST) y4m_write_fields(fd_out, &so, &fi, bot1,bot1); else y4m_write_fields(fd_out, &so, &fi, top1,top1); goto done; } /* * Now the key part of the processing - effectively discarding the first mixed * frame with fields from frames B + C and creating the C frame from the two * mixed frames. For a BOTTOM FIELD FIRST stream use the 'top' field from * frame 3 and the 'bottom' fields from frame 4. With a TOP FIELD FIRST stream * it's the other way around - use the 'bottom' field from frame 3 and the * 'top' field from frame 4. */ if (ilace == Y4M_ILACE_BOTTOM_FIRST) y4m_write_fields(fd_out, &so, &fi, top1, bot2); /* C */ else y4m_write_fields(fd_out, &so, &fi, top2, bot1); /* C */ err = y4m_read_fields(fd_in, &si, &fi, top1, bot1); y4m_write_fields(fd_out, &so, &fi, top1, bot1); /* D */ } done: y4m_fini_frame_info(&fi); y4m_fini_stream_info(&si); y4m_fini_stream_info(&so); exit(0); } static void usage() { mjpeg_error_exit1(" file-24000:1001.y4m"); /* NOTREACHED */ } mjpegtools-2.1.0/autogen.sh0000755000175000017500000000012310114472144016204 0ustar glowwormglowworm#!/bin/sh # Run this to generate all the initial makefiles, etc. autoreconf -f -i mjpegtools-2.1.0/compile0000755000175000017500000001610312217306406015571 0ustar glowwormglowworm#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2012-03-05.13; # UTC # Copyright (C) 1999-2012 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: mjpegtools-2.1.0/CHANGES0000644000175000017500000000275307164673440015226 0ustar glowwormglowwormChanges to lavtools-1.2 - A.Stevens Merged in improvements to mpeg2enc plus useful additional tools. - G.Ziegler Initial merge of mmx-ed JPEG libs and movtar support. Detached jpeg-6b-mmx and libmovtar into own packages. Changes to lavtools-1.1 - added MPEG video and audi encoders for usage with AVI/Quicktime files and Edit lists - lavplay now can not more output files from edit lists, this is taken over by lavtrans in the utils directory - lavrec: different decimations in x and y direction possibility to capture sub areas time lapse - lavplay: "zoom to fit" - xlav: better user interface - device names for video/audio/mixer device may be set by environment variables - much more small things Changes to lavtools-1.0 - Full Quicktime support in recording and playing - Support of multiple files to overcome 2 GB limit - perfect audio/video synchronization in recording and playback for lip-synchronous videos even after hours of playing. - single frame (is it called stop motion?) capture - GUI to lavplay - use your linux PC as a great video recorder - support of (simple) editing in the GUI: cut your video clips as you like - lavplay supports concatenating video clips, splitting off audio separating video into single images - option in lavrec to wait for user input before starting - support for other audio input sources in lavrec - steering of lavplay (forward, backward, pause etc.) with commands (for real command line hardliners) mjpegtools-2.1.0/yuvdeinterlace/0000755000175000017500000000000012217306501017231 5ustar glowwormglowwormmjpegtools-2.1.0/yuvdeinterlace/Makefile.am0000644000175000017500000000061310520420451021261 0ustar glowwormglowworm# Makefile.am for yuvdeinterlace MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/utils LIBMJPEGUTILS = $(top_builddir)/utils/libmjpegutils.la if HAVE_ALTIVEC LIBMJPEGUTILS += $(top_builddir)/mpeg2enc/libmpeg2encpp.la endif bin_PROGRAMS = yuvdeinterlace noinst_HEADERS = yuvdeinterlace_SOURCES = yuvdeinterlace.cc yuvdeinterlace_LDADD = $(LIBMJPEGUTILS) mjpegtools-2.1.0/yuvdeinterlace/yuvdeinterlace.cc0000644000175000017500000007704411255220017022575 0ustar glowwormglowworm/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" #include #include #include "mjpeg_types.h" #include "yuv4mpeg.h" #include "mjpeg_logging.h" #include "cpu_accel.h" #include "motionsearch.h" #ifdef __GNUC__ #define RESTRICT __restrict__ #else #define RESTRICT #endif namespace { class y4mstream { public: int fd_in; int fd_out; y4m_frame_info_t iframeinfo; y4m_stream_info_t istreaminfo; y4m_frame_info_t oframeinfo; y4m_stream_info_t ostreaminfo; y4mstream () { fd_in = 0; fd_out = 1; }; }; class deinterlacer { public: int width; int height; int cwidth; int cheight; int field_order; int both_fields; int verbose; int input_chroma_subsampling; int output_chroma_subsampling; int vertical_overshot_luma; int vertical_overshot_chroma; int just_anti_alias; y4mstream Y4MStream; uint8_t *inframe[3]; uint8_t *inframe0[3]; uint8_t *inframe1[3]; uint8_t *outframe[3]; uint8_t * RESTRICT scratch; uint8_t * RESTRICT mmap; int_least16_t (* RESTRICT motion[2])[2]; void initialize_memory (int w, int h, int cw, int ch) { int luma_size; int chroma_size; int lmotion_size; int cmotion_size; // Some functions need some vertical overshoot area // above and below the image. So we make the buffer // a little bigger... vertical_overshot_luma = 32 * w; vertical_overshot_chroma = 32 * cw; luma_size = (w * h) + 2 * vertical_overshot_luma; chroma_size = (cw * ch) + 2 * vertical_overshot_chroma; lmotion_size = ((w + 7) / 8) * ((h + 7) / 8); cmotion_size = ((cw + 7) / 8) * ((ch + 7) / 8); inframe[0] = (uint8_t *) calloc (luma_size, 1) + vertical_overshot_luma; inframe[1] = (uint8_t *) calloc (chroma_size, 1) + vertical_overshot_chroma; inframe[2] = (uint8_t *) calloc (chroma_size, 1) + vertical_overshot_chroma; inframe0[0] = (uint8_t *) calloc (luma_size, 1) + vertical_overshot_luma; inframe0[1] = (uint8_t *) calloc (chroma_size, 1) + vertical_overshot_chroma; inframe0[2] = (uint8_t *) calloc (chroma_size, 1) + vertical_overshot_chroma; inframe1[0] = (uint8_t *) calloc (luma_size, 1) + vertical_overshot_luma; inframe1[1] = (uint8_t *) calloc (chroma_size, 1) + vertical_overshot_chroma; inframe1[2] = (uint8_t *) calloc (chroma_size, 1) + vertical_overshot_chroma; outframe[0] = (uint8_t *) calloc (luma_size, 1) + vertical_overshot_luma; outframe[1] = (uint8_t *) calloc (chroma_size, 1) + vertical_overshot_chroma; outframe[2] = (uint8_t *) calloc (chroma_size, 1) + vertical_overshot_chroma; scratch = (uint8_t *) malloc (luma_size) + vertical_overshot_luma; mmap = (uint8_t *) malloc (w * h); motion[0] = (int_least16_t (*)[2]) calloc (lmotion_size, sizeof(motion[0][0])); motion[1] = (int_least16_t (*)[2]) calloc (cmotion_size, sizeof(motion[0][0])); width = w; height = h; cwidth = cw; cheight = ch; } deinterlacer () { both_fields = 0; just_anti_alias = 0; } ~deinterlacer () { free (inframe[0] - vertical_overshot_luma); free (inframe[1] - vertical_overshot_chroma); free (inframe[2] - vertical_overshot_chroma); free (inframe0[0] - vertical_overshot_luma); free (inframe0[1] - vertical_overshot_chroma); free (inframe0[2] - vertical_overshot_chroma); free (inframe1[0] - vertical_overshot_luma); free (inframe1[1] - vertical_overshot_chroma); free (inframe1[2] - vertical_overshot_chroma); free (outframe[0] - vertical_overshot_luma); free (outframe[1] - vertical_overshot_chroma); free (outframe[2] - vertical_overshot_chroma); free (scratch - vertical_overshot_luma); free (mmap); free (motion[0]); free (motion[1]); } void temporal_reconstruct_frame (uint8_t * RESTRICT out, const uint8_t * const in, uint8_t * RESTRICT in0, const uint8_t * const in1, int w, int h, int field, int_least16_t (* RESTRICT lvxy)[2]) { int_fast16_t x, y; int_fast16_t vx, vy, dx, dy, px, py; uint_fast16_t min, sad; int_fast16_t a, b, c, d, e, f, g, m, i; const uint_fast16_t iw = (w + 7) / 8; // the ELA-algorithm overshots by one line above and below the // frame-size, so fill the ELA-overshot-area in the inframe to // ensure that no green or purple lines are generated... std::memcpy (in0 - w, in + w, w); std::memcpy (in0 + (w * h), in + (w * h) - 2 * w, w); // create deinterlaced frame of the reference-field in scratch for (y = (1 - field); y < h; y += 2) for (x = 0; x < w; x++) { a = abs( *(in +x+(y-1)*w)-*(in0+x+(y-1)*w) ); a += abs( *(in1+x+(y-1)*w)-*(in0+x+(y-1)*w) ); b = abs( *(in +x+(y )*w)-*(in0+x+(y )*w) ); b += abs( *(in1+x+(y )*w)-*(in0+x+(y )*w) ); c = abs( *(in +x+(y+1)*w)-*(in0+x+(y+1)*w) ); c += abs( *(in1+x+(y+1)*w)-*(in0+x+(y+1)*w) ); *(scratch+x+(y-1)*w) = *(in0+x+(y-1)*w); if( (a<16 || c<16) && b<16 ) // Pixel is static? { // Yes... *(scratch+x+(y )*w) = *(in0+x+(y )*w); *(mmap+x+y*w) = 255; // mark pixel as static in motion-map... } else { // No... // Do an edge-directed-interpolation m = *(in0+(x-3)+(y-2)*w); m += *(in0+(x-2)+(y-2)*w); m += *(in0+(x-1)+(y-2)*w); m += *(in0+(x-0)+(y-2)*w); m += *(in0+(x+1)+(y-2)*w); m += *(in0+(x+2)+(y-2)*w); m += *(in0+(x+3)+(y-2)*w); m += *(in0+(x-3)+(y-1)*w); m += *(in0+(x-2)+(y-1)*w); m += *(in0+(x-1)+(y-1)*w); m += *(in0+(x-0)+(y-1)*w); m += *(in0+(x+1)+(y-1)*w); m += *(in0+(x+2)+(y-1)*w); m += *(in0+(x+3)+(y-1)*w); m += *(in0+(x-3)+(y+1)*w); m += *(in0+(x-2)+(y+1)*w); m += *(in0+(x-1)+(y+1)*w); m += *(in0+(x-0)+(y+1)*w); m += *(in0+(x+1)+(y+1)*w); m += *(in0+(x+2)+(y+1)*w); m += *(in0+(x+3)+(y+1)*w); m += *(in0+(x-3)+(y+2)*w); m += *(in0+(x-2)+(y+2)*w); m += *(in0+(x-1)+(y+2)*w); m += *(in0+(x-0)+(y+2)*w); m += *(in0+(x+1)+(y+2)*w); m += *(in0+(x+2)+(y+2)*w); m += *(in0+(x+3)+(y+2)*w); m /= 28; a = abs( *(in0+(x-3)+(y-1)*w) - *(in0+(x+3)+(y+1)*w) ); i = ( *(in0+(x-3)+(y-1)*w) + *(in0+(x+3)+(y+1)*w) )/2; a -= abs(m-i); b = abs( *(in0+(x-2)+(y-1)*w) - *(in0+(x+2)+(y+1)*w) ); i = ( *(in0+(x-2)+(y-1)*w) + *(in0+(x+2)+(y+1)*w) )/2; b -= abs(m-i); c = abs( *(in0+(x-1)+(y-1)*w) - *(in0+(x+1)+(y+1)*w) ); i = ( *(in0+(x-1)+(y-1)*w) + *(in0+(x+1)+(y+1)*w) )/2; c -= abs(m-i); e = abs( *(in0+(x+1)+(y-1)*w) - *(in0+(x-1)+(y+1)*w) ); i = ( *(in0+(x+1)+(y-1)*w) + *(in0+(x-1)+(y+1)*w) )/2; e -= abs(m-i); f = abs( *(in0+(x+2)+(y-1)*w) - *(in0+(x-2)+(y+1)*w) ); i = ( *(in0+(x+2)+(y-1)*w) + *(in0+(x-2)+(y+1)*w) )/2; f -= abs(m-i); g = abs( *(in0+(x+3)+(y-1)*w) - *(in0+(x-3)+(y+1)*w) ); i = ( *(in0+(x+3)+(y-1)*w) + *(in0+(x-3)+(y+1)*w) )/2; g -= abs(m-i); d = abs( *(in0+(x )+(y-1)*w) - *(in0+(x )+(y+1)*w) ); i = ( *(in0+(x )+(y-1)*w) + *(in0+(x )+(y+1)*w) )/2; d -= abs(m-i); if (a 512) if (iy && ix && ix < (iw - 1)) { dx = lvxy[ix - 1 + (iy - 1) * iw][0]; dx += lvxy[ix + (iy - 1) * iw][0]; dx += lvxy[ix + 1 + (iy - 1) * iw][0]; dx += lvxy[ix - 1 + (iy ) * iw][0]; dx += lvxy[ix + (iy ) * iw][0]; dx /= 5; dy = lvxy[ix - 1 + (iy - 1) * iw][1]; dy += lvxy[ix + (iy - 1) * iw][1]; dy += lvxy[ix + 1 + (iy - 1) * iw][1]; dy += lvxy[ix - 1 + (iy ) * iw][1]; dy += lvxy[ix + (iy ) * iw][1]; dy /= 10; dy *= 2; sad = psad_00 (scratch + x + y * w, out + (x + dx) + (y + dy) * w, w, 16, min); if (sad < min) { min = sad; vx = dx; vy = dy; } } // if possible check top-left-neighbor-vector if (min > 512) if (iy && ix) { dx = lvxy[ix - 1 + (iy - 1) * iw][0]; dy = lvxy[ix - 1 + (iy - 1) * iw][1]; sad = psad_00 (scratch + x + y * w, out + (x + dx) + (y + dy) * w, w, 16, min); if (sad < min) { min = sad; vx = dx; vy = dy; } } // if possible check top-neighbor-vector if (min > 512) if (iy) { dx = lvxy[ix + (iy - 1) * iw][0]; dy = lvxy[ix + (iy - 1) * iw][1]; sad = psad_00 (scratch + x + y * w, out + (x + dx) + (y + dy) * w, w, 16, min); if (sad < min) { min = sad; vx = dx; vy = dy; } } // if possible check top-right-neighbor-vector if (min > 512) if (iy && ix < (iw - 1)) { dx = lvxy[ix + 1 + (iy - 1) * iw][0]; dy = lvxy[ix + 1 + (iy - 1) * iw][1]; sad = psad_00 (scratch + x + y * w, out + (x + dx) + (y + dy) * w, w, 16, min); if (sad < min) { min = sad; vx = dx; vy = dy; } } // if possible check left-neighbor-vector if (min > 512) if (ix) { dx = lvxy[ix - 1 + iy * iw][0]; dy = lvxy[ix - 1 + iy * iw][1]; sad = psad_00 (scratch + x + y * w, out + (x + dx) + (y + dy) * w, w, 16, min); if (sad < min) { min = sad; vx = dx; vy = dy; } } // check temporal-neighbor-vector if (min > 512) { dx = lvxy[ix + iy * iw][0]; dy = lvxy[ix + iy * iw][1]; sad = psad_00 (scratch + x + y * w, out + (x + dx) + (y + dy) * w, w, 16, min); if (sad < min) { min = sad; vx = dx; vy = dy; } } // search for a better one... px = vx; py = vy; if( min>1024 ) // the found predicted location [px;py] is a bad match... { // Do a large but coarse diamond search arround the prediction-vector // // X // --- // X-X-X // ------- // -X-X-X-X- // ----------- // X-X-X-O-X-X-X // ----------- // -X-X-X-X- // ------- // X-X-X // --- // X // // The locations marked with an X are checked, only. The location marked with // an O was already checked before... // dx = px-2; dy = py; sad = psad_00 (scratch + x + y * w, out + (x + dx) + (y + dy) * w, w, 16, min); if (sad < min) { min = sad; vx = dx; vy = dy; } dx = px+2; dy = py; sad = psad_00 (scratch + x + y * w, out + (x + dx) + (y + dy) * w, w, 16, min); if (sad < min) { min = sad; vx = dx; vy = dy; } dx = px-4; dy = py; sad = psad_00 (scratch + x + y * w, out + (x + dx) + (y + dy) * w, w, 16, min); if (sad < min) { min = sad; vx = dx; vy = dy; } dx = px+4; dy = py; sad = psad_00 (scratch + x + y * w, out + (x + dx) + (y + dy) * w, w, 16, min); if (sad < min) { min = sad; vx = dx; vy = dy; } dx = px; dy = py-4; sad = psad_00 (scratch + x + y * w, out + (x + dx) + (y + dy) * w, w, 16, min); if (sad < min) { min = sad; vx = dx; vy = dy; } dx = px; dy = py+4; sad = psad_00 (scratch + x + y * w, out + (x + dx) + (y + dy) * w, w, 16, min); if (sad < min) { min = sad; vx = dx; vy = dy; } } // update prediction-vector px = vx; py = vy; { // only do a small diamond search here... Either we have passed the large // diamond search or the predicted vector was good enough // // X // --- // XXOXX // --- // X // // The locations marked with an X are checked, only. The location marked with // an O was already checked before... // dx = px-1; dy = py; sad = psad_00 (scratch + x + y * w, out + (x + dx) + (y + dy) * w, w, 16, min); if (sad < min) { min = sad; vx = dx; vy = dy; } dx = px+1; dy = py; sad = psad_00 (scratch + x + y * w, out + (x + dx) + (y + dy) * w, w, 16, min); if (sad < min) { min = sad; vx = dx; vy = dy; } dx = px-2; dy = py; sad = psad_00 (scratch + x + y * w, out + (x + dx) + (y + dy) * w, w, 16, min); if (sad < min) { min = sad; vx = dx; vy = dy; } dx = px+2; dy = py; sad = psad_00 (scratch + x + y * w, out + (x + dx) + (y + dy) * w, w, 16, min); if (sad < min) { min = sad; vx = dx; vy = dy; } dx = px; dy = py-2; sad = psad_00 (scratch + x + y * w, out + (x + dx) + (y + dy) * w, w, 16, min); if (sad < min) { min = sad; vx = dx; vy = dy; } dx = px; dy = py+2; sad = psad_00 (scratch + x + y * w, out + (x + dx) + (y + dy) * w, w, 16, min); if (sad < min) { min = sad; vx = dx; vy = dy; } } // store the found vector, so we can do a candidates-check... lvxy[ix + iy * iw][0] = vx; lvxy[ix + iy * iw][1] = vy; // remove x+y offset... x += 4; y += 4; // reconstruct that block in scratch // do so by using the lowpass (and alias-term) from the current field // and the highpass (and phase-inverted alias-term) from the previous frame(!) #if 1 for (dy = (1 - field); dy < 8; dy += 2) { uint8_t * RESTRICT dest = scratch + x + (y + dy) * w; uint8_t * RESTRICT src1 = scratch + x + (y + dy) * w; uint8_t * RESTRICT src2 = out + (x + vx) + (y + dy + vy) * w; for (dx = 0; dx < 8; dx++) { a = src1[dx - 3 * w] * -1 + src1[dx - 1 * w] * +17 + src1[dx + 1 * w] * +17 + src1[dx + 3 * w] * -1; b = src2[dx - 3 * w] * +1 + src2[dx - 1 * w] * -17 + src2[dx + 0 * w] * +32 + src2[dx + 1 * w] * -17 + src2[dx + 3 * w] * +1; a = a + b; a = a < 0 ? 0 : (a > 8160 ? 255 : (unsigned)a / 32); dest[dx] = a; } } #else for (dy = (1 - field); dy < 8; dy += 2) for (dx = 0; dx < 8; dx++) { *(scratch + (x + dx) + (y + dy) * w) = ( //*(scratch + (x + dx) + (y + dy) * w) + *(out + (x + dx + vx) + (y + dy +vy) * w) )/1; } #endif } for (y = (1 - field); y < h; y += 2) for (x = 0; x < w; x++) { if ( *(mmap+x+y*w)==255 ) // if pixel is static { *(scratch + x + (y) * w) = *(in0+x+(y )*w); } } #if 1 std::memcpy (out, scratch, w * h); #else // copy a gauss-filtered variant of the reconstructed image to the out-buffer // the reason why this must be filtered is not so easy to understand, so I leave // some room for anyone who might try without... :-) // // If you want a starting point: remember an interlaced camera *must* *not* have // more vertical resolution than approximatly 0.6 times the nominal vertical // resolution... (So a progressive-scan camera will allways be better in this // regard but will introduce severe defects when the movie is displayed on an // interlaced screen...) Eitherways, who cares: this is better than a frame-mode // were the missing information is generated via a pixel-shift... :-) for (y = 0; y < h; y++) for (x = 0; x < w; x++) { *(out + x + y * w) = (4 * *(scratch + x + (y) * w)+*(scratch + x + (y-1) * w)+*(scratch + x + (y+1) * w))/6; } #endif antialias_plane ( out, w, h ); } void scale_motion_vectors (int nom, int rshift) { int i; for (i = (width / 8) * (height / 8); i--; ) { motion[0][i][0] = (motion[0][i][0] * nom) >> rshift; motion[0][i][1] = (motion[0][i][1] * nom) >> rshift; } for (i = (cwidth / 8) * (cheight / 8); i--; ) { motion[1][i][0] = (motion[1][i][0] * nom) >> rshift; motion[1][i][1] = (motion[1][i][1] * nom) >> rshift; } } void deinterlace_motion_compensated (int frame) { uint8_t *tmpptr; if(frame) { uint8_t *saveptr[3] = {0, 0, 0}; if(frame == 1) { temporal_reconstruct_frame (outframe[0], inframe0[0], inframe[0], inframe0[0], width, height, field_order, motion[0]); temporal_reconstruct_frame (outframe[1], inframe0[1], inframe[1], inframe0[1], cwidth, cheight, field_order, motion[1]); temporal_reconstruct_frame (outframe[2], inframe0[2], inframe[2], inframe0[2], cwidth, cheight, field_order, motion[1]); temporal_reconstruct_frame (outframe[0], inframe0[0], inframe[0], inframe0[0], width, height, 1 - field_order, motion[0]); temporal_reconstruct_frame (outframe[1], inframe0[1], inframe[1], inframe0[1], cwidth, cheight, 1 - field_order, motion[1]); temporal_reconstruct_frame (outframe[2], inframe0[2], inframe[2], inframe0[2], cwidth, cheight, 1 - field_order, motion[1]); scale_motion_vectors (2, 0); saveptr[0] = inframe1[0]; saveptr[1] = inframe1[1]; saveptr[2] = inframe1[2]; inframe1[0] = inframe[0]; inframe1[1] = inframe[1]; inframe1[2] = inframe[2]; } else if(frame < 0) { saveptr[0] = inframe[0]; saveptr[1] = inframe[1]; saveptr[2] = inframe[2]; inframe[0] = inframe1[0]; inframe[1] = inframe1[1]; inframe[2] = inframe1[2]; } if (field_order == 0) { temporal_reconstruct_frame (outframe[0], inframe[0], inframe0[0], inframe1[0], width, height, 1, motion[0]); temporal_reconstruct_frame (outframe[1], inframe[1], inframe0[1], inframe1[1], cwidth, cheight, 1, motion[1]); temporal_reconstruct_frame (outframe[2], inframe[2], inframe0[2], inframe1[2], cwidth, cheight, 1, motion[1]); y4m_write_frame (Y4MStream.fd_out, &Y4MStream.ostreaminfo, &Y4MStream.oframeinfo, outframe); if (frame == 1) scale_motion_vectors (-1, both_fields); if (both_fields == 1) { temporal_reconstruct_frame (outframe[0], inframe[0], inframe0[0], inframe1[0], width, height, 0, motion[0]); temporal_reconstruct_frame (outframe[1], inframe[1], inframe0[1], inframe1[1], cwidth, cheight, 0, motion[1]); temporal_reconstruct_frame (outframe[2], inframe[2], inframe0[2], inframe1[2], cwidth, cheight, 0, motion[1]); y4m_write_frame (Y4MStream.fd_out, &Y4MStream.ostreaminfo, &Y4MStream.oframeinfo, outframe); } } else { temporal_reconstruct_frame (outframe[0], inframe[0], inframe0[0], inframe1[0], width, height, 0, motion[0]); temporal_reconstruct_frame (outframe[1], inframe[1], inframe0[1], inframe1[1], cwidth, cheight, 0, motion[1]); temporal_reconstruct_frame (outframe[2], inframe[2], inframe0[2], inframe1[2], cwidth, cheight, 0, motion[1]); y4m_write_frame (Y4MStream.fd_out, &Y4MStream.ostreaminfo, &Y4MStream.oframeinfo, outframe); if (frame == 1) scale_motion_vectors (-1, both_fields); if (both_fields == 1) { temporal_reconstruct_frame (outframe[0], inframe[0], inframe0[0], inframe1[0], width, height, 1, motion[0]); temporal_reconstruct_frame (outframe[1], inframe[1], inframe0[1], inframe1[1], cwidth, cheight, 1, motion[1]); temporal_reconstruct_frame (outframe[2], inframe[2], inframe0[2], inframe1[2], cwidth, cheight, 1, motion[1]); y4m_write_frame (Y4MStream.fd_out, &Y4MStream.ostreaminfo, &Y4MStream.oframeinfo, outframe); } } if (frame < 2) { inframe1[0] = saveptr[0]; inframe1[1] = saveptr[1]; inframe1[2] = saveptr[2]; } } tmpptr = inframe1[0]; inframe1[0] = inframe0[0]; inframe0[0] = inframe[0]; inframe[0] = tmpptr; tmpptr = inframe1[1]; inframe1[1] = inframe0[1]; inframe0[1] = inframe[1]; inframe[1] = tmpptr; tmpptr = inframe1[2]; inframe1[2] = inframe0[2]; inframe0[2] = inframe[2]; inframe[2] = tmpptr; } void antialias_plane (uint8_t * RESTRICT out, int w, int h) { int x, y; int vx; uint_fast16_t sad; uint_fast16_t min; int dx; for (y = 2; y < (h - 2); y++) for (x = 2; x < (w - 2); x++) { min = ~0; vx = 0; for (dx = -3; dx <= 3; dx++) { sad = 0; // sad = abs( *(out+(x+dx-3)+(y-1)*w) - *(out+(x-3)+(y+0)*w) ); // sad += abs( *(out+(x+dx-2)+(y-1)*w) - *(out+(x-2)+(y+0)*w) ); sad += abs (*(out + (x + dx - 1) + (y - 1) * w) - *(out + (x - 1) + (y + 0) * w)); sad += abs (*(out + (x + dx + 0) + (y - 1) * w) - *(out + (x + 0) + (y + 0) * w)); sad += abs (*(out + (x + dx + 1) + (y - 1) * w) - *(out + (x + 1) + (y + 0) * w)); // sad += abs( *(out+(x+dx+2)+(y-1)*w) - *(out+(x+2)+(y+0)*w) ); // sad += abs( *(out+(x+dx+3)+(y-1)*w) - *(out+(x+3)+(y+0)*w) ); // sad += abs( *(out+(x-dx-3)+(y+1)*w) - *(out+(x-3)+(y+0)*w) ); // sad += abs( *(out+(x-dx-2)+(y+1)*w) - *(out+(x-2)+(y+0)*w) ); sad += abs (*(out + (x - dx - 1) + (y + 1) * w) - *(out + (x - 1) + (y + 0) * w)); sad += abs (*(out + (x - dx + 0) + (y + 1) * w) - *(out + (x + 0) + (y + 0) * w)); sad += abs (*(out + (x - dx + 1) + (y + 1) * w) - *(out + (x + 1) + (y + 0) * w)); // sad += abs( *(out+(x-dx+2)+(y+1)*w) - *(out+(x+2)+(y+0)*w) ); // sad += abs( *(out+(x-dx+3)+(y+1)*w) - *(out+(x+3)+(y+0)*w) ); if (sad < min) { min = sad; vx = dx; } } if (abs (vx) <= 1) *(scratch + x + y * w) = (2**(out + (x) + (y) * w) + *(out + (x + vx) + (y - 1) * w) + *(out + (x - vx) + (y + 1) * w)) / 4; else if (abs (vx) <= 3) *(scratch + x + y * w) = (2 * *(out + (x - 1) + (y) * w) + 4 * *(out + (x + 0) + (y) * w) + 2 * *(out + (x + 1) + (y) * w) + 1 * *(out + (x + vx - 1) + (y - 1) * w) + 2 * *(out + (x + vx + 0) + (y - 1) * w) + 1 * *(out + (x + vx + 1) + (y - 1) * w) + 1 * *(out + (x - vx - 1) + (y + 1) * w) + 2 * *(out + (x - vx + 0) + (y + 1) * w) + 1 * *(out + (x - vx + 1) + (y + 1) * w)) / 16; else *(scratch + x + y * w) = (2 * *(out + (x - 1) + (y) * w) + 4 * *(out + (x - 1) + (y) * w) + 8 * *(out + (x + 0) + (y) * w) + 4 * *(out + (x + 1) + (y) * w) + 2 * *(out + (x + 1) + (y) * w) + 1 * *(out + (x + vx - 1) + (y - 1) * w) + 2 * *(out + (x + vx - 1) + (y - 1) * w) + 4 * *(out + (x + vx + 0) + (y - 1) * w) + 2 * *(out + (x + vx + 1) + (y - 1) * w) + 1 * *(out + (x + vx + 1) + (y - 1) * w) + 1 * *(out + (x - vx - 1) + (y + 1) * w) + 2 * *(out + (x - vx - 1) + (y + 1) * w) + 4 * *(out + (x - vx + 0) + (y + 1) * w) + 2 * *(out + (x - vx + 1) + (y + 1) * w) + 1 * *(out + (x - vx + 1) + (y + 1) * w)) / 40; } for (y = 2; y < (h - 2); y++) for (x = 2; x < (w - 2); x++) { *(out + (x) + (y) * w) = (*(out + (x) + (y) * w) + *(scratch + (x) + (y + 0) * w)) / 2; } } void antialias_frame () { antialias_plane (inframe[0], width, height); antialias_plane (inframe[1], cwidth, cheight); antialias_plane (inframe[2], cwidth, cheight); y4m_write_frame (Y4MStream.fd_out, &Y4MStream.ostreaminfo, &Y4MStream.oframeinfo, inframe); } }; } int main (int argc, char *argv[]) { int frame = 0; int errno = 0; int ss_h, ss_v; deinterlacer YUVdeint; char c; YUVdeint.field_order = -1; mjpeg_info("-------------------------------------------------"); mjpeg_info( " Motion-Compensating-Deinterlacer"); mjpeg_info("-------------------------------------------------"); while ((c = getopt (argc, argv, "hvds:t:a")) != -1) { switch (c) { case 'h': { mjpeg_info(" Usage of the deinterlacer"); mjpeg_info(" -------------------------"); mjpeg_info(" -v be verbose"); mjpeg_info(" -d output both fields"); mjpeg_info(" -a just antialias the frames! This will"); mjpeg_info(" assume progressive but aliased input."); mjpeg_info(" you can use this to improve badly deinterlaced"); mjpeg_info(" footage. EG: deinterlaced with cubic-interpolation"); mjpeg_info(" or worse..."); mjpeg_info(" -s [n=0/1] forces field-order in case of misflagged streams"); mjpeg_info(" -s0 is bottom-field-first"); mjpeg_info(" -s1 is top-field-first"); exit (0); break; } case 'v': { YUVdeint.verbose = 1; break; } case 'd': { YUVdeint.both_fields = 1; mjpeg_info("Regenerating both fields. Please fix the Framerate."); break; } case 'a': { YUVdeint.just_anti_alias = 1; YUVdeint.field_order = 0; // just to prevent the program to barf in this case mjpeg_info("I will just anti-alias the frames. make sure they are progressive!"); break; } case 't': { mjpeg_info("motion-threshold not used"); break; } case 's': { YUVdeint.field_order = atoi (optarg); if (YUVdeint.field_order != 0) { mjpeg_info("forced top-field-first!"); YUVdeint.field_order = 1; } else { mjpeg_info("forced bottom-field-first!"); YUVdeint.field_order = 0; } break; } } } // initialize motionsearch-library init_motion_search (); #ifdef HAVE_ALTIVEC reset_motion_simd ("sad_00"); #endif // initialize stream-information y4m_accept_extensions (1); y4m_init_stream_info (&YUVdeint.Y4MStream.istreaminfo); y4m_init_frame_info (&YUVdeint.Y4MStream.iframeinfo); y4m_init_stream_info (&YUVdeint.Y4MStream.ostreaminfo); y4m_init_frame_info (&YUVdeint.Y4MStream.oframeinfo); /* open input stream */ if ((errno = y4m_read_stream_header (YUVdeint.Y4MStream.fd_in, &YUVdeint.Y4MStream.istreaminfo)) != Y4M_OK) { mjpeg_error_exit1 ("Couldn't read YUV4MPEG header: %s!", y4m_strerr (errno)); } /* get format information */ YUVdeint.width = y4m_si_get_width (&YUVdeint.Y4MStream.istreaminfo); YUVdeint.height = y4m_si_get_height (&YUVdeint.Y4MStream.istreaminfo); YUVdeint.input_chroma_subsampling = y4m_si_get_chroma (&YUVdeint.Y4MStream.istreaminfo); mjpeg_info("Y4M-Stream is %ix%i(%s)", YUVdeint.width, YUVdeint.height, y4m_chroma_keyword (YUVdeint.input_chroma_subsampling)); /* if chroma-subsampling isn't supported bail out ... */ switch (YUVdeint.input_chroma_subsampling) { case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: case Y4M_CHROMA_444: case Y4M_CHROMA_422: case Y4M_CHROMA_411: ss_h = y4m_chroma_ss_x_ratio (YUVdeint.input_chroma_subsampling).d; ss_v = y4m_chroma_ss_y_ratio (YUVdeint.input_chroma_subsampling).d; YUVdeint.cwidth = YUVdeint.width / ss_h; YUVdeint.cheight = YUVdeint.height / ss_v; break; default: mjpeg_error_exit1 ("%s is not in supported chroma-format. Sorry.", y4m_chroma_keyword (YUVdeint.input_chroma_subsampling)); } /* the output is progressive 4:2:0 MPEG 1 */ y4m_si_set_interlace (&YUVdeint.Y4MStream.ostreaminfo, Y4M_ILACE_NONE); y4m_si_set_chroma (&YUVdeint.Y4MStream.ostreaminfo, YUVdeint.input_chroma_subsampling); y4m_si_set_width (&YUVdeint.Y4MStream.ostreaminfo, YUVdeint.width); y4m_si_set_height (&YUVdeint.Y4MStream.ostreaminfo, YUVdeint.height); y4m_si_set_framerate (&YUVdeint.Y4MStream.ostreaminfo, y4m_si_get_framerate (&YUVdeint.Y4MStream.istreaminfo)); y4m_si_set_sampleaspect (&YUVdeint.Y4MStream.ostreaminfo, y4m_si_get_sampleaspect (&YUVdeint.Y4MStream.istreaminfo)); /* check for field dominance */ if (YUVdeint.field_order == -1) { /* field-order was not specified on commandline. So we try to * get it from the stream itself... */ if (y4m_si_get_interlace (&YUVdeint.Y4MStream.istreaminfo) == Y4M_ILACE_TOP_FIRST) { /* got it: Top-field-first... */ mjpeg_info(" Stream is interlaced, top-field-first."); YUVdeint.field_order = 1; } else if (y4m_si_get_interlace (&YUVdeint.Y4MStream.istreaminfo) == Y4M_ILACE_BOTTOM_FIRST) { /* got it: Bottom-field-first... */ mjpeg_info(" Stream is interlaced, bottom-field-first."); YUVdeint.field_order = 0; } else { mjpeg_error("Unable to determine field-order from input-stream."); mjpeg_error("This is most likely the case when using mplayer to produce the input-stream."); mjpeg_error("Either the stream is misflagged or progressive..."); mjpeg_error("I will stop here, sorry. Please choose a field-order"); mjpeg_error("with -s0 or -s1. Otherwise I can't do anything for you. TERMINATED. Thanks..."); exit (-1); } } // initialize deinterlacer internals YUVdeint.initialize_memory (YUVdeint.width, YUVdeint.height, YUVdeint.cwidth, YUVdeint.cheight); /* write the outstream header */ y4m_write_stream_header (YUVdeint.Y4MStream.fd_out, &YUVdeint.Y4MStream.ostreaminfo); /* read every frame until the end of the input stream and process it */ while (Y4M_OK == (errno = y4m_read_frame (YUVdeint.Y4MStream.fd_in, &YUVdeint.Y4MStream.istreaminfo, &YUVdeint.Y4MStream.iframeinfo, YUVdeint.inframe))) { if (!YUVdeint.just_anti_alias) YUVdeint.deinterlace_motion_compensated (frame); else YUVdeint.antialias_frame (); frame++; } if (!YUVdeint.just_anti_alias) YUVdeint.deinterlace_motion_compensated (-frame); return 0; } mjpegtools-2.1.0/yuvdeinterlace/Makefile.in0000644000175000017500000004462312217306410021306 0ustar glowwormglowworm# Makefile.in generated by automake 1.12.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Makefile.am for yuvdeinterlace VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @HAVE_ALTIVEC_TRUE@am__append_1 = $(top_builddir)/mpeg2enc/libmpeg2encpp.la bin_PROGRAMS = yuvdeinterlace$(EXEEXT) subdir = yuvdeinterlace DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_yuvdeinterlace_OBJECTS = yuvdeinterlace.$(OBJEXT) yuvdeinterlace_OBJECTS = $(am_yuvdeinterlace_OBJECTS) yuvdeinterlace_DEPENDENCIES = $(LIBMJPEGUTILS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(yuvdeinterlace_SOURCES) DIST_SOURCES = $(yuvdeinterlace_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALTIVEC_EXTRA_LIBS = @ALTIVEC_EXTRA_LIBS@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDV_CFLAGS = @LIBDV_CFLAGS@ LIBDV_LIBS = @LIBDV_LIBS@ LIBGETOPT_LIB = @LIBGETOPT_LIB@ LIBM_LIBS = @LIBM_LIBS@ LIBOBJS = @LIBOBJS@ LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ LIBPNG_LIBS = @LIBPNG_LIBS@ LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@ LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ LT_STATIC = @LT_STATIC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROGRAM_NOPIC = @PROGRAM_NOPIC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ SDLgfx_LIBS = @SDLgfx_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ V4LCONF_LIBS = @V4LCONF_LIBS@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/utils LIBMJPEGUTILS = $(top_builddir)/utils/libmjpegutils.la $(am__append_1) noinst_HEADERS = yuvdeinterlace_SOURCES = yuvdeinterlace.cc yuvdeinterlace_LDADD = $(LIBMJPEGUTILS) all: all-am .SUFFIXES: .SUFFIXES: .cc .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu yuvdeinterlace/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu yuvdeinterlace/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list yuvdeinterlace$(EXEEXT): $(yuvdeinterlace_OBJECTS) $(yuvdeinterlace_DEPENDENCIES) $(EXTRA_yuvdeinterlace_DEPENDENCIES) @rm -f yuvdeinterlace$(EXEEXT) $(CXXLINK) $(yuvdeinterlace_OBJECTS) $(yuvdeinterlace_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuvdeinterlace.Po@am__quote@ .cc.o: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cc.lo: @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool cscopelist ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mjpegtools-2.1.0/TODO0000644000175000017500000000310310611307036014673 0ustar glowwormglowwormIMMEDIATE Fix all the BUGS (see BUGS) of course! TASKS OUTSTANDING Documentation. - Maybe an FAQ to complement Bernhard's HOWTO all those standard questions about MPEG, VCD, SVCD all those standard questions about busted audio drivers Code hygiene basically: GNU guidelines! Basically if you want a nice example of how it should be done take a look at the source code for vcdimager! - A lot of the code is in fairly poor shape layout and stylistically. Minimally, some needs running through a C prettifier and having stuff like "unsigned char" replaced with appropriate types from stdint.h via utils/mjpeg_types.h. - Need to test and build scripts for in-line multiplexing. - The filtering / decimation code in the lav* utilities is now redundant with yuvscale in place... it should be removed once we're happy with yuvscale. Major - Continuation of frozen encoding sessions. - Try switching to the somewhat faster transposed fDCT from libavcodec. - "Back-up and try again" and/or "two pass" bit-allocation / quantisation control on a frame by frame basis. Maybe sometime - Find a proper SSE fDCT and iDCT. - Test support for field pictures to mplex. Not urgent since for most sources frame pictures with field DCT/motion compensation seems to give better results. - Improve the appearance of dark scenes. At the present time dark scenes are very prone to splotchy or grey blockiness. Locally reduce quantisation and, if necessary, switch to a different matrix if the dark is long enough. The dark scenes don't use many bits anyway so its not too greedy.. mjpegtools-2.1.0/mpeg2enc/0000755000175000017500000000000012217306500015705 5ustar glowwormglowwormmjpegtools-2.1.0/mpeg2enc/ChangeLog0000644000175000017500000000144007610111441017455 0ustar glowwormglowworm2000 Jul A.Stevens Added more intelligent motion compensation search. Basically, the program now first does a coarse search based on 2*2 pel squares, comparing intensity sums. Since a good match (low difference) here can be expected to correlated with a good 1 and 1/2 pel match it uses only the best fraction (default 1/10th) of these as starting points for more expensive 1 pel search. The best 1 pel match is then used as the basis for a best 1/2 pel match. Integrated SSE/MMX code based on original contribution by Chris Atenasio. N.b. see INSTALL for details of compilation with SSE/MMX. 2000 Jul/Aug Lots to add - see README for the summary... 2003 A.Stevens Shifted to C++ replaced original phase oriented processing with macro-block oriented processing. mjpegtools-2.1.0/mpeg2enc/imageplanes.hh0000644000175000017500000000334411114314210020507 0ustar glowwormglowworm#ifndef _IMAGEPLANES_HH #define _IMAGEPLANES_HH /* (C) 2005 Andrew Stevens */ /* This is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "mjpeg_types.h" #include "encoderparams.hh" /************************************************ * * ImagePlanes - Raw image data with 'margins' around * actual data to allow motion estimation routines etc * to be sloppy about cropping at image edges to save * time. * * ************************************************/ class ImagePlanes { public: enum Planes_Enum { YPLANE=0, UPLANE=1, VPLANE=2, Y22=3, Y44=4, NUM_PLANES }; ImagePlanes( EncoderParams &encoder ); ~ImagePlanes(); inline uint8_t *Plane( unsigned int plane) { return planes[plane]; } inline uint8_t **Planes() { return planes; } protected: static void BorderMark( uint8_t *frame, int total_width, int total_height, int image_data_width, int image_data_height); protected: uint8_t *planes[NUM_PLANES]; }; #endif // _IMAGEPLANES_HH mjpegtools-2.1.0/mpeg2enc/picturereader.cc0000644000175000017500000000524011011315326021050 0ustar glowwormglowworm/* picturereader.cc */ /* (C) 2000/2001/2003 Andrew Stevens, Rainer Johanni */ /* This software is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "picturereader.hh" #include "mpeg2encoder.hh" #include "imageplanes.hh" #include //#include //#include //#include //#include //#include //#include "simd.h" PictureReader::PictureReader( EncoderParams &_encparams ) : encparams( _encparams ) { frames_read = 0; frames_released = 0; istrm_nframes = INT_MAX; } void PictureReader::Init() { } PictureReader::~PictureReader() { for( unsigned int i = 0; i < input_imgs_buf.size(); ++i ) delete input_imgs_buf[i]; } void PictureReader::AllocateBufferUpto( int buffer_slot ) { for( int i = input_imgs_buf.size(); i <= buffer_slot; ++i ) { input_imgs_buf.push_back(new ImagePlanes( encparams )); } } void PictureReader::ReleaseFrame( int num_frame) { while( frames_released <= num_frame ) { input_imgs_buf.push_back( input_imgs_buf.front() ); input_imgs_buf.pop_front(); ++frames_released; } } void PictureReader::FillBufferUpto( int num_frame ) { while(frames_read <= num_frame && frames_read < istrm_nframes ) { AllocateBufferUpto( frames_read-frames_released ); if( LoadFrame( *input_imgs_buf[frames_read-frames_released] ) ) { istrm_nframes = frames_read; mjpeg_info( "Signaling last frame = %d", istrm_nframes-1 ); return; } ++frames_read; } } ImagePlanes *PictureReader::ReadFrame( int num_frame ) { if(istrm_nframes!=INT_MAX && num_frame>=istrm_nframes ) { mjpeg_error("Internal error: PictureReader::ReadFrame: attempt to reading beyond known EOS"); abort(); } FillBufferUpto( num_frame ); return input_imgs_buf[num_frame-frames_released]; } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/streamstate.cc0000644000175000017500000002142310566454254020571 0ustar glowwormglowworm/* (C) 2005 Andrew Stevens * This file is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "streamstate.h" #include #include #include "mjpeg_types.h" #include "mjpeg_logging.h" #include "encoderparams.hh" #include "mpeg2syntaxcodes.h" #include "picturereader.hh" // -------------------------------------------------------------------------------- // Stream state maintenance class StreamState::StreamState( EncoderParams &_encparams, PictureReader &_reader ) : encparams(_encparams), reader(_reader) { } void StreamState::Init( ) { seq_split_length = ((int64_t)encparams.seq_length_limit)*(8*1024*1024); next_split_point = BITCOUNT_OFFSET + seq_split_length; mjpeg_debug( "Split len = %lld", seq_split_length ); frame_num = 0; // All these counters in *encoding* order !! s_idx = 0; g_idx = 0; b_idx = 0; gop_length = 0; // Forces new GOP start 1st sequence. seq_start_frame = 0; gop_start_frame = 0; gop_end_seq = true; // At start we act as after sequence split... GopStart( ); SetTempRef(); } /* Could the following GOP be closed? */ bool StreamState::NextGopClosed() const { return gop_end_seq || encparams.closed_GOPs || gop_start_frame + gop_length == GetNextChapter(); } int StreamState::GetNextChapter() const { // advance return value when gop_start_frame exceeds or equals current chapter point while( !encparams.chapter_points.empty() ) { int next_chapter=encparams.chapter_points.front(); if( next_chapter > gop_start_frame ) return next_chapter; encparams.chapter_points.pop_front(); } return -1; } bool StreamState::CanSplitHere(int offset) const { int nc=GetNextChapter(); // Enforce GOP dimensioning. if( g_idx+offset < encparams.N_min ) return false; // Enforce chapter splits... if( nc < 0 ) return true; int nc_distance = nc - (frame_num+offset); if( nc_distance < 0 || g_idx+offset < encparams.N_min) return false; // Check that legal GOP sizes allow the the next chapter point to // be hit exactly. If it is between x and x+1 minimum GOPs away // it must be x or less maximum gops away as only then can a mixture // of gops sized somewhere between minimum and maximum sizes reach it // exactly. // Division must occur first; rounding down is relied upon! return nc_distance <= (nc_distance/encparams.N_min) * encparams.N_max; } /* Update ss to the next sequence state. */ void StreamState::Next( uint64_t bits_after_mux ) // Estimate of how much output would have been produced { ++frame_num; ++s_idx; ++g_idx; ++b_idx; new_seq = false; /* Are we starting a new B group */ if( b_idx >= bigrp_length ) { b_idx = 0; /* Does this need to be a short B group to make the GOP length come out right ? */ if( bs_short != 0 && g_idx > (int)next_b_drop ) { if( bs_short ) next_b_drop += ((double)gop_length) / (double)(bs_short+1) ; bigrp_length = encparams.M - 1; } else if( !suppress_b_frames ) bigrp_length = encparams.M; else bigrp_length = 1; // Do we need to start next GOP? if( g_idx == gop_length ) { GopStart( ); // Sets frame_type == I_TYPE } else { frame_type = P_TYPE; } } else { frame_type = B_TYPE; } // Figure out if a sequence split is due... if( (next_split_point != 0ULL && bits_after_mux > next_split_point) || (s_idx != 0 && encparams.seq_end_every_gop) ) { mjpeg_info( "Splitting sequence next GOP start" ); next_split_point += seq_split_length; gop_end_seq = true; } SetTempRef(); } /* Switch stream state to force an I-Frame where a P-frame would be expected. Basically: start a new GOP and do the usual house-keeping. */ void StreamState::ForceIFrame() { assert( frame_type != B_TYPE ); GopStart(); SetTempRef(); } /* Switch stream state so that no B frames are used from the current frame and onwards. */ void StreamState::SuppressBFrames() { assert( b_idx == 0 && encparams.M_min == 1); frame_type = P_TYPE; if( encparams.M_min == 1 ) { np += nb; nb = 0; bigrp_length = encparams.M_min; bs_short = 0; suppress_b_frames = true; SetTempRef(); } } void StreamState::SetTempRef() { // Ensure we have read up to the input frame we might need if the next // frame in decode order is an I or P. Make sure we don't go 'of the end' // once we've reached EOS int read_ahead_frame = frame_num+encparams.M; reader.FillBufferUpto( read_ahead_frame ); int last_frame = reader.NumberOfFrames()-1; if( frame_type == B_TYPE ) temp_ref = g_idx - 1; else if( g_idx == 0 && closed_gop) temp_ref = 0; else // I or P frame open GOP temp_ref = g_idx+(bigrp_length-1); // At end of Sequence may need to truncate bigrp! if (temp_ref > (last_frame-gop_start_frame)) temp_ref = (last_frame-gop_start_frame); // DEBUG remove when validated assert( frame_num + temp_ref - g_idx == gop_start_frame + temp_ref ); end_stream = frame_num > last_frame; end_seq = frame_num == last_frame || ( g_idx == gop_length-1 && gop_end_seq); } void StreamState::GopStart( ) { /* If we're starting a GOP and have gone past the current sequence splitting point split the sequence and set the next splitting point. */ suppress_b_frames = false; g_idx = 0; b_idx = 0; frame_type = I_TYPE; /* Normally set closed_GOP in first GOP only... */ closed_gop = NextGopClosed(); // must call this before the gop_end_seq code gop_start_frame = frame_num; /* Sequence ended at end previous GOP so this one starts a new sequence */ if( gop_end_seq ) { /* We split sequence last frame.This is the input stream display * order sequence number of the frame that will become frame 0 in display * order in the new sequence */ seq_start_frame =frame_num; s_idx = 0; gop_end_seq = false; new_seq = true; } // // GOPs initially always start out maximum length - short GOPs occur when we notice // a P frame occurring after the minimum GOP lengthhas been reached // // also shorten a GOP if we have an upcoming chapter point we are aiming for // for( gop_length = encparams.N_max; gop_length > encparams.N_min; gop_length-- ) if( CanSplitHere(gop_length) ) break; mjpeg_info( "NEW GOP INIT length %d", gop_length ); /* First figure out how many B frames we're short from being able to achieve an even M-1 B's per I/P frame. To avoid peaks in necessary data-rate we try to lose the B's in the middle of the GOP. We always *start* with M-1 B's (makes choosing I-frame breaks simpler). A complication is the extra I-frame in the initial closed GOP of a sequence. */ if( encparams.M-1 > 0 ) { int pics_in_bigrps = closed_gop ? gop_length - 1 : gop_length; bs_short = (encparams.M - pics_in_bigrps % encparams.M)%encparams.M; next_b_drop = ((double)gop_length) / (double)(bs_short+1)-1.0 ; } else { bs_short = 0; next_b_drop = 0.0; } /* We aim to spread the dropped B's evenly across the GOP */ bigrp_length = (encparams.M-1); if (closed_gop ) { bigrp_length = 1; np = (gop_length + 2*(encparams.M-1))/encparams.M - 1; /* Closed GOP */ } else { bigrp_length = encparams.M; np = (gop_length + (encparams.M-1))/encparams.M - 1; } /* number of B frames */ nb = gop_length - np - 1; //np = np; //nb = nb; if( np+nb+1 != gop_length ) { mjpeg_error_exit1( "****INTERNAL: inconsistent GOP %d %d %d", gop_length, np, nb); } } mjpegtools-2.1.0/mpeg2enc/transfrm_ref.c0000644000175000017500000001433411445477341020564 0ustar glowwormglowworm/* transfrm.c, Low-level Architecture neutral DCT/iDCT and prediction difference / addition routines */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ /* Modifications and enhancements (C) 2000/2001 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include #include #include "mjpeg_types.h" #include "mjpeg_logging.h" #include "transfrm_ref.h" #include "cpu_accel.h" #include "simd.h" #if defined(HAVE_ASM_MMX) extern void init_x86_transform(); #endif #ifdef HAVE_ALTIVEC #include "../utils/altivec/altivec_transform.h" #endif void fdct( int16_t *blk ); void fdct_ref( int16_t *blk ); void fdct_daan( int16_t *blk ); void fdct_daanf( int16_t *blk ); void idct( int16_t *blk ); void idct_ref( int16_t *blk ); void init_fdct (void); void init_idct (void); /* Pointers to version of transform and prediction manipulation routines to be used.. */ void (*pfdct)( int16_t * blk ); void (*pidct)( int16_t * blk ); void (*padd_pred) (uint8_t *pred, uint8_t *cur, int lx, int16_t *blk); void (*psub_pred) (uint8_t *pred, uint8_t *cur, int lx, int16_t *blk); int (*pfield_dct_best)( uint8_t *cur_lum_mb, uint8_t *pred_lum_mb, int stride); int field_dct_best( uint8_t *cur_lum_mb, uint8_t *pred_lum_mb, int stride ) { /* * calculate prediction error (cur-pred) for top (blk0) * and bottom field (blk1) */ double r,d; int rowoffs = 0; int sumtop, sumbot, sumsqtop, sumsqbot, sumbottop; int j,i; int topvar, botvar; sumtop = sumsqtop = sumbot = sumsqbot = sumbottop = 0; for (j=0; j<8; j++) { for (i=0; i<16; i++) { register int toppix = cur_lum_mb[rowoffs+i] - pred_lum_mb[rowoffs+i]; register int botpix = cur_lum_mb[rowoffs+stride+i] - pred_lum_mb[rowoffs+stride+i]; sumtop += toppix; sumsqtop += toppix*toppix; sumbot += botpix; sumsqbot += botpix*botpix; sumbottop += toppix*botpix; } rowoffs += (stride<<1); } /* Calculate Variances top and bottom. If they're of similar sign estimate correlation if its good use frame DCT otherwise use field. */ r = 0.0; topvar = sumsqtop-sumtop*sumtop/128; botvar = sumsqbot-sumbot*sumbot/128; if (!((topvar>0) ^ (botvar>0))) { d = ((double) topvar) * ((double)botvar); r = (sumbottop-(sumtop*sumbot)/128); if (r>0.5*sqrt(d)) return 0; /* frame DCT */ else return 1; /* field DCT */ } return 1; /* field DCT */ } /* add prediction and prediction error, saturate to 0...255 */ void add_pred(uint8_t *pred, uint8_t *cur, int lx, int16_t *blk) { int i, j; for (j=0; j<8; j++) { for (i=0; i<8; i++) { int16_t rawsum = blk[i] + pred[i]; cur[i] = (rawsum<0) ? 0 : ((rawsum>255) ? 255 : rawsum); } blk+= 8; cur+= lx; pred+= lx; } } /* subtract prediction from block data */ /* static */ void sub_pred(uint8_t *pred, uint8_t *cur, int lx, int16_t *blk) { int i, j; for (j=0; j<8; j++) { for (i=0; i<8; i++) blk[i] = cur[i] - pred[i]; blk+= 8; cur+= lx; pred+= lx; } } /* Initialise DCT transformation routines. Selects the appropriate architecture dependent SIMD routines and initialises pre-computed tables */ void init_transform(void) { int flags; flags = cpu_accel(); pfdct = fdct_ref; pidct = idct_ref; padd_pred = add_pred; psub_pred = sub_pred; pfield_dct_best = field_dct_best; #if defined(HAVE_ASM_MMX) if( flags & ACCEL_X86_MMX ) { init_x86_transform(); } #endif #ifdef HAVE_ALTIVEC if (flags > 0) { #if ALTIVEC_TEST_TRANSFORM # if defined(ALTIVEC_BENCHMARK) mjpeg_info("SETTING AltiVec BENCHMARK for TRANSFORM!"); # elif defined(ALTIVEC_VERIFY) mjpeg_info("SETTING AltiVec VERIFY for TRANSFORM!"); # endif #else mjpeg_info("SETTING AltiVec for TRANSFORM!"); #endif #if ALTIVEC_TEST_FUNCTION(fdct) pfdct = ALTIVEC_TEST_SUFFIX(fdct); #else pfdct = ALTIVEC_SUFFIX(fdct); #endif #if ALTIVEC_TEST_FUNCTION(idct) pidct = ALTIVEC_TEST_SUFFIX(idct); #else pidct = ALTIVEC_SUFFIX(idct); #endif #if ALTIVEC_TEST_FUNCTION(add_pred) padd_pred = ALTIVEC_TEST_SUFFIX(add_pred); #else padd_pred = ALTIVEC_SUFFIX(add_pred); #endif #if ALTIVEC_TEST_FUNCTION(sub_pred) psub_pred = ALTIVEC_TEST_SUFFIX(sub_pred); #else psub_pred = ALTIVEC_SUFFIX(sub_pred); #endif #if ALTIVEC_TEST_FUNCTION(field_dct_best) pfield_dct_best = ALTIVEC_TEST_SUFFIX(field_dct_best); #else pfield_dct_best = ALTIVEC_SUFFIX(field_dct_best); #endif } #endif /* HAVE_ALTIVEC */ init_fdct(); init_idct(); } mjpegtools-2.1.0/mpeg2enc/elemstrmwriter.cc0000644000175000017500000001063311456612024021311 0ustar glowwormglowworm/* ElemStrmFragBuf.cc - bit-level output of MPEG-1/2 elementary video stream */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ /* Modifications and enhancements (C) 2000/2001 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "elemstrmwriter.hh" #include "mpeg2encoder.hh" #include #include ElemStrmWriter::ElemStrmWriter() { flushed = BITCOUNT_OFFSET/8; } ElemStrmWriter::~ElemStrmWriter() { } /* *********************************************************************** */ OutputFragBuf::OutputFragBuf() { pendingbits = 0; unflushed = 0; outcnt = 8; } OutputFragBuf::~OutputFragBuf() { } /* *********************************************************************** */ ElemStrmFragBuf::ElemStrmFragBuf(ElemStrmWriter &_writer ) : OutputFragBuf(), writer(_writer) { buffer = NULL; ResetBuffer(); } ElemStrmFragBuf::~ElemStrmFragBuf() { free( buffer ); } void ElemStrmFragBuf::AdjustBuffer() { buffer_size *= 2; buffer = static_cast(realloc( buffer, sizeof(uint8_t) * buffer_size)); if( !buffer ) mjpeg_error_exit1( "output buffer memory allocation: out of memory" ); } void ElemStrmFragBuf::ResetBuffer() { outcnt = 8; buffer_size = 1024*16; unflushed = 0; AdjustBuffer(); } void ElemStrmFragBuf::FlushBuffer( ) { assert( outcnt == 8 ); writer.WriteOutBufferUpto( buffer, unflushed ); ResetBuffer(); } /************** * * Write least significant n (0<=n<=32) bits of val to output buffer * *************/ void ElemStrmFragBuf::PutBits(uint32_t val, int n) { val = (n == 32) ? val : (val & (~(0xffffffffU << n))); while( n >= outcnt ) { pendingbits = (pendingbits << outcnt ) | (val >> (n-outcnt)); if( unflushed == buffer_size ) AdjustBuffer(); buffer[unflushed] = pendingbits; ++unflushed; n -= outcnt; outcnt = 8; } if( n != 0 ) { pendingbits = (pendingbits< #include "mjpeg_logging.h" #include "mpeg2encoder.hh" #include "mpeg2syntaxcodes.h" #include "picture.hh" #include "macroblock.hh" #include "imageplanes.hh" #include "predict_ref.h" /* predict a rectangular block (all three components) * * src: source frame (Y,U,V) * sfield: source field select (0: frame or top field, 1: bottom field) * dst: destination frame (Y,U,V) * dfield: destination field select (0: frame or top field, 1: bottom field) * * the following values are in luminance picture (frame or field) dimensions * lx: distance of vertically adjacent pels (selects frame or field pred.) * w,h: width and height of block (only 16x16 or 16x8 are used) * x,y: coordinates of destination block * dx,dy: half pel motion vector * addflag: store or add (= average) prediction */ void pred ( uint8_t *src[], int sfield, uint8_t *dst[], int dfield, int lx, int w, int h, int x, int y, int dx, int dy, bool addflag ) { int cc; for (cc=0; cc<3; cc++) { if (cc==1) { /* scale for color components */ /* vertical */ h >>= 1; y >>= 1; dy /= 2; /* horizontal */ w >>= 1; x >>= 1; dx /= 2; lx >>= 1; } ppred_comp( src[cc]+(sfield?lx>>1:0),dst[cc]+(dfield?lx>>1:0), lx,w,h,x,y,dx,dy, (int)addflag); } } /* calculate derived motion vectors (DMV) for dual prime prediction * dmvector[2]: differential motion vectors (-1,0,+1) * mvx,mvy: motion vector (for same parity) * * DMV[2][2]: derived motion vectors (for opposite parity) * * uses global variables pict_struct and topfirst * * Notes: * - all vectors are in field coordinates (even for frame pictures) * */ #ifndef DEBUG_DPME static #endif void calc_DMV( const Picture &picture, /*int pict_struct, int topfirst,*/ MotionVector DMV[Parity::dim], MotionVector &dmvector, int mvx, int mvy ) { if (picture.pict_struct==FRAME_PICTURE) { if (picture.topfirst) { /* vector for prediction of top field from bottom field */ DMV[0][0] = ((mvx +(mvx>0))>>1) + dmvector[0]; DMV[0][1] = ((mvy +(mvy>0))>>1) + dmvector[1] - 1; /* vector for prediction of bottom field from top field */ DMV[1][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0]; DMV[1][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] + 1; } else { /* vector for prediction of top field from bottom field */ DMV[0][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0]; DMV[0][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] - 1; /* vector for prediction of bottom field from top field */ DMV[1][0] = ((mvx +(mvx>0))>>1) + dmvector[0]; DMV[1][1] = ((mvy +(mvy>0))>>1) + dmvector[1] + 1; } } else { /* vector for prediction from field of opposite 'parity' */ DMV[0][0] = ((mvx+(mvx>0))>>1) + dmvector[0]; DMV[0][1] = ((mvy+(mvy>0))>>1) + dmvector[1]; /* correct for vertical field shift */ if (picture.pict_struct==TOP_FIELD) DMV[0][1]--; else DMV[0][1]++; } } /* form prediction for one macroblock * * lx: frame width (identical to global var `width') * * Notes: * - when predicting a P type picture which is the second field of * a frame, the same parity reference field is in oldref, while the * opposite parity reference field is assumed to be in newref! * - intra macroblocks are modelled to have a constant prediction of 128 * for all pels; this results in a DC DCT coefficient symmetric to 0 * - vectors for field prediction in frame pictures are in half pel frame * coordinates (vertical component is twice the field value and always * even) * * already covers dual prime (not yet used) */ void MacroBlock::Predict() { const Picture &picture = ParentPicture(); const int bx = TopleftX(); const int by = TopleftY(); uint8_t **fwd_rec = picture.fwd_rec->Planes(); // Forward prediction uint8_t **bwd_rec = picture.bwd_rec->Planes(); // Backward prediction uint8_t **cur = picture.pred->Planes(); // Frame to predict int lx = picture.encparams.phy_width; int lx2 = picture.encparams.phy_width; bool addflag; int currentfield; uint8_t **predframe; MotionVector DMV[Parity::dim /*pred*/]; if (best_me->mb_type&MB_INTRA) { clearblock( cur,bx,by, picture.pict_struct==BOTTOM_FIELD ? lx : 0, lx2); return; } addflag = false; /* first prediction is stored, second is added and averaged */ if ((best_me->mb_type & MB_FORWARD) || (picture.pict_type==P_TYPE)) { /* forward prediction, including zero MV in P pictures */ if (picture.pict_struct==FRAME_PICTURE) { /* frame picture */ if ( (best_me->motion_type==MC_FRAME) || !(best_me->mb_type & MB_FORWARD)) { /* frame-based prediction in frame picture */ pred( fwd_rec,0,cur,0, lx,16,16,bx,by,best_me->MV[0][0][0],best_me->MV[0][0][1],false); } else if (best_me->motion_type==MC_FIELD) { /* field-based prediction in frame picture * * note scaling of the vertical coordinates (by, MV[][0][1]) * from frame to field! */ /* top field prediction */ pred(fwd_rec,best_me->field_sel[0][0],cur,0, lx<<1,16,8,bx,by>>1, best_me->MV[0][0][0],best_me->MV[0][0][1]>>1,false); /* bottom field prediction */ pred(fwd_rec,best_me->field_sel[1][0],cur,1, lx<<1,16,8,bx,by>>1, best_me->MV[1][0][0],best_me->MV[1][0][1]>>1,false); } else if (best_me->motion_type==MC_DMV) { /* dual prime prediction calculate derived motion vectors */ calc_DMV(picture, DMV, best_me->dualprimeMV, best_me->MV[0][0][0], best_me->MV[0][0][1]>>1); /* predict top field from top field */ pred(fwd_rec,0,cur,0, lx<<1,16,8,bx,by>>1, best_me->MV[0][0][0],best_me->MV[0][0][1]>>1,false); /* predict bottom field from bottom field */ pred(fwd_rec,1,cur,1, lx<<1,16,8,bx,by>>1, best_me->MV[0][0][0],best_me->MV[0][0][1]>>1,false); /* predict and add to top field from bottom field */ pred(fwd_rec,1,cur,0, lx<<1,16,8,bx,by>>1, DMV[0][0],DMV[0][1],true); /* predict and add to bottom field from top field */ pred(fwd_rec,0,cur,1, lx<<1,16,8,bx,by>>1, DMV[1][0],DMV[1][1],true); } else { /* invalid motion_type in frame picture */ mjpeg_error_exit1("Internal: invalid motion_type"); } } else /* TOP_FIELD or BOTTOM_FIELD */ { /* field picture */ currentfield = (picture.pict_struct==BOTTOM_FIELD); /* determine which frame to use for prediction */ if ((picture.pict_type==P_TYPE) && picture.secondfield && (currentfield!=best_me->field_sel[0][0])) predframe = bwd_rec; /* same frame */ else predframe = fwd_rec; /* previous frame */ if ( best_me->motion_type==MC_FIELD || !(best_me->mb_type & MB_FORWARD)) { /* field-based prediction in field picture */ pred(predframe,best_me->field_sel[0][0],cur,currentfield, lx<<1,16,16,bx,by, best_me->MV[0][0][0],best_me->MV[0][0][1],false); } else if (best_me->motion_type==MC_16X8) { /* 16 x 8 motion compensation in field picture */ /* upper half */ pred(predframe,best_me->field_sel[0][0],cur,currentfield, lx<<1,16,8,bx,by, best_me->MV[0][0][0],best_me->MV[0][0][1],false); /* determine which frame to use for lower half prediction */ if ((picture.pict_type==P_TYPE) && picture.secondfield && (currentfield!=best_me->field_sel[1][0])) predframe = bwd_rec; /* same frame */ else predframe = fwd_rec; /* previous frame */ /* lower half */ pred(predframe,best_me->field_sel[1][0],cur,currentfield, lx<<1,16,8,bx,by+8, best_me->MV[1][0][0],best_me->MV[1][0][1],false); } else if (best_me->motion_type==MC_DMV) { /* dual prime prediction */ /* determine which frame to use for prediction */ if (picture.secondfield) predframe = bwd_rec; /* same frame */ else predframe = fwd_rec; /* previous frame */ /* calculate derived motion vectors */ calc_DMV(picture, DMV,best_me->dualprimeMV, best_me->MV[0][0][0], best_me->MV[0][0][1]); /* predict from field of same parity */ pred(fwd_rec,currentfield,cur,currentfield, lx<<1,16,16,bx,by, best_me->MV[0][0][0],best_me->MV[0][0][1],false); /* predict from field of opposite parity */ pred(predframe,!currentfield,cur,currentfield, lx<<1,16,16,bx,by, DMV[0][0],DMV[0][1],true); } else { /* invalid motion_type in field picture */ mjpeg_error_exit1("Internal: invalid motion_type"); } } addflag = true; /* next prediction (if any) will be averaged with this one */ } if (best_me->mb_type & MB_BACKWARD) { /* backward prediction */ if (picture.pict_struct==FRAME_PICTURE) { /* frame picture */ if (best_me->motion_type==MC_FRAME) { /* frame-based prediction in frame picture */ pred(bwd_rec,0,cur,0, lx,16,16,bx,by, best_me->MV[0][1][0],best_me->MV[0][1][1],addflag); } else { /* field-based prediction in frame picture * * note scaling of the vertical coordinates (by, MV[][1][1]) * from frame to field! */ /* top field prediction */ pred(bwd_rec,best_me->field_sel[0][1],cur,0, lx<<1,16,8,bx,by>>1, best_me->MV[0][1][0],best_me->MV[0][1][1]>>1,addflag); /* bottom field prediction */ pred(bwd_rec,best_me->field_sel[1][1],cur,1, lx<<1,16,8,bx,by>>1, best_me->MV[1][1][0],best_me->MV[1][1][1]>>1,addflag); } } else /* TOP_FIELD or BOTTOM_FIELD */ { /* field picture */ currentfield = (picture.pict_struct==BOTTOM_FIELD); if (best_me->motion_type==MC_FIELD) { /* field-based prediction in field picture */ pred(bwd_rec,best_me->field_sel[0][1],cur,currentfield, lx<<1,16,16,bx,by, best_me->MV[0][1][0],best_me->MV[0][1][1],addflag); } else if (best_me->motion_type==MC_16X8) { /* 16 x 8 motion compensation in field picture */ /* upper half */ pred(bwd_rec,best_me->field_sel[0][1],cur,currentfield, lx<<1,16,8,bx,by, best_me->MV[0][1][0],best_me->MV[0][1][1],addflag); /* lower half */ pred(bwd_rec,best_me->field_sel[1][1],cur,currentfield, lx<<1,16,8,bx,by+8, best_me->MV[1][1][0],best_me->MV[1][1][1],addflag); } else { /* invalid motion_type in field picture */ mjpeg_error_exit1("Internal: invalid motion_type"); } } } } mjpegtools-2.1.0/mpeg2enc/quantize_ref.h0000644000175000017500000000633510444645161020572 0ustar glowwormglowworm/* quantize_ref.h, Low-level Architecture neutral quantization / * inverse quantization routines */ /* (C) 2003 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #ifndef _QUANTIZE_H #define _QUANTIZE_H #include "mjpeg_types.h" struct QuantizerWorkSpace; struct QuantizerCalls { int (*pquant_non_intra)( struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int q_scale_type, int dctsatlim, int *nonsat_mquant); int (*pquant_weight_coeff_intra)(struct QuantizerWorkSpace *wsp, int16_t *blk ); int (*pquant_weight_coeff_inter)(struct QuantizerWorkSpace *wsp, int16_t *blk ); void (*piquant_non_intra)(struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int mquant ); void (*piquant_intra)(struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int dc_prec, int mquant ); }; #ifdef __cplusplus extern "C" { #endif void init_quantizer( struct QuantizerCalls *qcalls, struct QuantizerWorkSpace **workspace, int mpeg1, uint16_t intra_q[64], uint16_t inter_q[64]); void shutdown_quantizer(struct QuantizerWorkSpace *workspace); int next_larger_quant( int q_scale_type, int quant ); int quant_code( int q_scale_type, int mquant ); void quant_intra( struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int q_scale_type, int dc_prec, int dctsatlim, int *nonsat_mquant); int quant_non_intra( struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int q_scale_type, int dctsatlim, int *nonsat_mquant); void iquant_intra_m1 ( struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int dc_prec, int mquant); void iquant_intra_m2 ( struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int dc_prec, int mquant); void iquant_non_intra_m1 (struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int mquant); void iquant_non_intra_m2 (struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int mquant); #ifdef __cplusplus } #endif #endif /* _QUANTIZE_H */ /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/macroblock.hh0000644000175000017500000001343510712201605020346 0ustar glowwormglowworm#ifndef _MACROBLOCK_HH #define _MACROBLOCK_HH /* macroblock.hh macroblock class... */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ /* (C) 2000-2004 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include #include "mjpeg_types.h" #include "encodertypes.h" using namespace std; class Picture; typedef int16_t DCTblock[64]; class MotionEst { public: enum Direction { fwd = 0, bwd =1 }; int mb_type; /* intra/forward/backward/interpolated */ int motion_type; /* frame/field/16x8/dual_prime */ MotionVector MV[2][2]; /* motion vectors */ int field_sel[2][2]; /* motion vertical field select */ MotionVector dualprimeMV; /* dual prime vectors */ int var; /* luminance variance after motion compensation (measure of activity) */ }; class Quantizer; class MotionCand; /* macroblock information */ class SubSampledImg; class MacroBlock { public: MacroBlock(Picture &_picture, const unsigned int _i, const unsigned int _j, DCTblock *_dctblocks, DCTblock *_qdctblocks ) : picture(&_picture), i(_i), j(_j), pel( _i, _j ), hpel( _i<<1, _j<<1 ), dctblocks(_dctblocks), qdctblocks(_qdctblocks) { } inline Picture &ParentPicture() const { return *picture; } inline int BaseLumVariance() const { return best_me->var; } inline double Activity() const { return act; } inline const int TopleftX() const { return i; } inline const int TopleftY() const { return j; } inline DCTblock *RawDCTblocks() const { return dctblocks; } inline DCTblock *QuantDCTblocks() const { return qdctblocks; } void Encode(); void MotionEstimateAndModeSelect(); void ForceIFrame(); void ForcePFrame(); void Quantize( Quantizer &quant); // In quantize.cc void IQuantize( Quantizer &quant); void Transform(); // In transfrm.cc void ITransform(); protected: void MotionEstimate(); void SelectCodingModeOnVariance(); void FrameME(); // In motionest.cc void FrameMEs(); void FieldME(); void Predict(); // In predict.cc private: bool FrameDualPrimeCand(uint8_t *ref, const SubSampledImg &ssmb, const MotionCand (&best_fieldmcs)[2][2], MotionCand &best_mc, MotionVector &min_dpmv); private: Picture *picture; unsigned int i,j; // Co-ordinates top-left in picture DEBUG Coord pel; // Co-ordinates top-left in picture (pels) Coord hpel; // Co-ordindates top-left in picture (half-pel) int row_start; // Offset from frame top to start of MB's row DCTblock *dctblocks; DCTblock *qdctblocks; uint32_t lum_mean; uint32_t lum_variance; /* Old public struct information... TODO: This will gradually disappear as C++-ification continues */ public: bool field_dct; // Field DCT encoded rather than frame DCT int mquant; /* quantization parameter */ int cbp; /* coded block pattern */ bool skipped; /* skipped macroblock */ double act; /* activity measure */ int i_act; /* Activity measure if intra coded (I/P-frame) */ int p_act; /* Activity measure for *forward* prediction (P-frame) */ int b_act; /* Activity measure if bi-directionally coded (B-frame) */ vector best_of_kind_me; // The best predicting motion compensation // of each possible kind. MotionEst *best_me; // Best predicting motion estimate overall MotionEst *best_fwd_me; // Best predicting motion compensation requiring only // forward motion compensation #ifdef OUTPUT_STAT double N_act; #endif }; /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ #endif mjpegtools-2.1.0/mpeg2enc/synchrolib.cc0000644000175000017500000001007010172074563020377 0ustar glowwormglowworm/* Synchrolib - various useful synchronisation primitives (C) 2001 Andrew Stevens This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Damn: shouldn't have to write this - but whenever you need something, well *that's* when you don't have Internet access. Bloody annyong that pthread_mutex's lock/unlock is only supposed to work properly if the same thread does the locking and unlocking. Gaah! */ #include #include #include #include "synchrolib.h" /********* * * Synchronisation primitives * ********/ void sync_guard_init( sync_guard_t *guard, int init ) { #ifdef PTHREAD_MUTEX_ERRORCHECK pthread_mutexattr_t mu_attr; pthread_mutexattr_t *p_attr = &mu_attr; pthread_mutexattr_init(&mu_attr); pthread_mutexattr_settype( &mu_attr, PTHREAD_MUTEX_ERRORCHECK ); #else pthread_mutexattr_t *p_attr = NULL; #endif pthread_mutex_init( &guard->mutex, p_attr ); pthread_cond_init( &guard->cond, NULL ); guard->predicate = init; } void sync_guard_test( sync_guard_t *guard) { int e; e = pthread_mutex_lock( &guard->mutex ); if (e != 0) { fprintf(stderr, "#1 pthread_mutex_lock=%d\n", e); abort(); } while( !guard->predicate ) { pthread_cond_wait( &guard->cond, &guard->mutex ); } e = pthread_mutex_unlock(&guard->mutex); if (e != 0) { fprintf(stderr, "#1 pthread_mutex_unlock=%d\n", e); abort(); } } void sync_guard_update( sync_guard_t *guard, int predicate ) { int e; e = pthread_mutex_lock( &guard->mutex ); if (e != 0) { fprintf(stderr, "#2 pthread_mutex_lock=%d\n", e); abort(); } guard->predicate = predicate; pthread_cond_broadcast( &guard->cond ); e = pthread_mutex_unlock(&guard->mutex); if (e != 0) { fprintf(stderr, "#2 pthread_mutex_unlock=%d\n", e); abort(); } } void mp_semaphore_init( mp_semaphore_t *sema, int init_count ) { #ifdef _PTHREAD_MUTEX_ERRORCHECK pthread_mutexattr_t mu_attr; pthread_mutexattr_t *p_attr = &mu_attr; pthread_mutexattr_init(&mu_attr); pthread_mutexattr_settype( &mu_attr, PTHREAD_MUTEX_ERRORCHECK ); #else pthread_mutexattr_t *p_attr = NULL; #endif pthread_mutex_init( &sema->mutex, p_attr ); pthread_cond_init( &sema->raised, NULL ); sema->count = init_count; } void mp_semaphore_wait( mp_semaphore_t *sema) { int e; e = pthread_mutex_lock(&sema->mutex); if (e != 0) { fprintf(stderr, "#3 pthread_mutex_lock=%d\n", e); abort(); } while( sema->count == 0 ) { pthread_cond_wait( &sema->raised, &sema->mutex ); } --(sema->count); e = pthread_mutex_unlock(&sema->mutex); if (e != 0) { fprintf(stderr, "#3 pthread_mutex_unlock=%d\n", e); abort(); } } void mp_semaphore_signal( mp_semaphore_t *sema, int count ) { int e; e = pthread_mutex_lock(&sema->mutex); if (e != 0) { fprintf(stderr, "#4 pthread_mutex_lock=%d\n", e); abort(); } sema->count += count; pthread_cond_broadcast( &sema->raised ); e = pthread_mutex_unlock(&sema->mutex); if (e != 0) { fprintf(stderr, "#4 pthread_mutex_unlock=%d\n", e); abort(); } } void mp_semaphore_set( mp_semaphore_t *sema ) { int e; e = pthread_mutex_lock(&sema->mutex); if (e != 0) { fprintf(stderr, "#5 pthread_mutex_lock=%d\n", e); abort(); } sema->count = 1; pthread_cond_broadcast( &sema->raised ); e = pthread_mutex_unlock(&sema->mutex); if (e != 0) { fprintf(stderr, "#5 pthread_mutex_unlock=%d\n", e); abort(); } } mjpegtools-2.1.0/mpeg2enc/NOTES0000644000175000017500000000752107605553321016537 0ustar glowwormglowwormSOME NOTES IN AND AROUND MPEG ENCODING (1) The importance of precision... Its not just quantizing "about right" that matters. However, mp1e has a very very good idea: why not precompile a combined quantisation / fdct matrix with the multipliers set up "just right" to include the necessary frig factors. If nothing else it saves accumulating numeric errors in the intermediate results of the coefficients! That mp1e guy was *smart*... (2) If you want to accurately compute an integer division using multiplication... Notation: [x](k) means x floor-ed to nearest k. [x] is [x] to the nearest unit. [x / d](1) = [Kx/d](K) = [ [K/d]x +(K%d)x/d ](K) / K Observe that for large K >> d [K/d]x >> (K%d)x/d so that the (K%d)x/d is in effect a rounding correction and hence need not itself be desperately accurate. Thus we expand another step to obtain... = [[K/d]x + [(K%d)[K/d]x + d](K)/K ](K) /K Where d is a very small correction factor. We now observe that since we're flooring to K on the outside we're really only interested in whether the rounding factor generates a "carry" so it doesn't need to be 100% accurate. = [[K/d]x ](K)/K + [[K/d]x]%K + (K%d)[K/d]x + d](K)/K For K twice word size the first term is simply the high word of the product [K/d]x The second term is simply the low word of the product [K/d]x plus the term (K%d)[K/d]x + d which for large K and small d will fit into a single word. Thus the carry can at most be a single bit. We can compute it "exactly" adding a small fixed round up d (32 appears to work nicely for K=2^16) and d < 256). However, for MPEG applications we have fairly limited range of d and x. For these we can get "almost" right results with a (coarse approximation). We know 0 <= K%d < d. We also know the factor gets very small for larger d. Thus we really only need a correction that "works" for small d. Taking a wild guess to try x ~= (K%d)[K/d]x for smallish d. Miracle of miracles it works just great! No too-lows, and only very rare too highs for large x. Thus [x/d] ~= hiword([K/d]x) + (loword([K/d]x)+x) >= K ) Clever eh. The actual computation we quantize in MPEG is [coefficient[i]*32 + quantisation/2) / quantisation*2*coeffquant[i] ] So, combining with Mr mp1e's sneakiness what we need is a table of [K/quantisation*2*coeffquant[i]] for each quantisation. Ooooerrr... If we want to get *really* clever we combine the quantisation with the DCT coefficients to go yet faster.... (3) Predicting motion vectors.... You'd think you could use the motion vectors from the P frame as an upper bound for the those needed in the following (in encoding order) B-frames. Wrrrrrooooong. Doesn't work. Well, actually it works, but: (a) The gains ain't impressive (10% maybe). (b) The is some quality loss. (c) It is well night impossible to get *any* gains in the MPEG-2 interlaced (field MC case) which is where you'd really want the speed gains. (4) The wonderful DCT quantisation matrix Experiments have revealed that if you're compressing on the margins of acceptable quality you do *far* better if you squeeze the higher frequency DCT coefficients using the quantisation matrix rather than simply allow the encoder to jack up the global quantisation factor. Why? The latter starts run an unacceptable risk of producing noticeable mosaic-ing due to big DC offssets. The latter just starts blurring the results by killing off h.f. components. (5) Spares and Sub-sampled matching. You get *good* results searching for sub-sampled matches at sub-sampling resolution. However, if you go below the sampling resolution you *will* miss the odd good match. Furthermore, the sad of sub-sampled match leading (eventually) to an optimal 1-pel match can be surprisingly much higher than you'd expect. 6*sad scaled for sampling density can occasionally be observed. I was amazed... Andrew mjpegtools-2.1.0/mpeg2enc/predict_ref.c0000644000175000017500000001416310163112251020340 0ustar glowwormglowworm/* predict_ref.c, Reference implementations of motion compensated * prediction routines */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ /* Modifications and enhancements (C) 2000/2001 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "config.h" #include "mjpeg_types.h" #include "mjpeg_logging.h" #include "mpeg2syntaxcodes.h" #include "predict_ref.h" #include "cpu_accel.h" #include "simd.h" #if defined(HAVE_ASM_MMX) extern void init_x86_predict(uint32_t cpucap); #endif #ifdef HAVE_ALTIVEC #include "../utils/altivec/altivec_predict.h" #endif void (*ppred_comp)( uint8_t *src, uint8_t *dst, int lx, int w, int h, int x, int y, int dx, int dy, int addflag); /* low level prediction routine (Reference implementation) * * src: prediction source * dst: prediction destination * lx: line width (for both src and dst) * x,y: destination coordinates * dx,dy: half pel motion vector * w,h: size of prediction block * addflag: store or add prediction * * There are also SIMD versions of this routine... */ void pred_comp( uint8_t *src, uint8_t *dst, int lx, int w, int h, int x, int y, int dx, int dy, int addflag) { int xint, xh, yint, yh; int i, j; uint8_t *s, *d; /* half pel scaling */ xint = dx>>1; /* integer part */ xh = dx & 1; /* half pel flag */ yint = dy>>1; yh = dy & 1; /* origins */ s = src + lx*(y+yint) + (x+xint); /* motion vector */ d = dst + lx*y + x; if (!xh && !yh) if (addflag) for (j=0; j>1; s+= lx; d+= lx; } else for (j=0; j>1)+1)>>1; s+= lx; d+= lx; } else for (j=0; j>1; s+= lx; d+= lx; } else if (xh && !yh) if (addflag) for (j=0; j>1)+1)>>1; s+= lx; d+= lx; } else for (j=0; j>1; s+= lx; d+= lx; } else /* if (xh && yh) */ if (addflag) for (j=0; j>2)+1)>>1; s+= lx; d+= lx; } else for (j=0; j>2; s+= lx; d+= lx; } } void clearblock( uint8_t *cur[], int i0, int j0, int field_off, int stride ) { int i, j; uint8_t *p; p = cur[0] + field_off + i0 + stride*j0; for (j=0; j<16; j++) { for (i=0; i<16; i++) p[i] = 128; p+= stride; } // 422 Video i0 >>= 1; j0 >>= 1; stride >>= 1; field_off >>= 1; p = cur[1] + field_off + i0 + stride*j0; for (j=0; j<8; j++) { for (i=0; i<8; i++) p[i] = 128; p+= stride; } p = cur[2] + field_off + i0 + stride*j0; for (j=0; j<8; j++) { for (i=0; i<8; i++) p[i] = 128; p+= stride; } } /* Initialise prediction - currently purely selection of which versions of the various low level computation routines to use */ void init_predict(void) { int cpucap = cpu_accel(); /* Default to reference implementation ... */ ppred_comp = pred_comp; if ( cpucap != 0 ) { #if defined(HAVE_ASM_MMX) init_x86_predict(cpucap); #endif #ifdef HAVE_ALTIVEC # if ALTIVEC_TEST_PREDICT # if defined(ALTIVEC_BENCHMARK) mjpeg_info("SETTING AltiVec BENCHMARK for PREDICTION!"); # elif defined(ALTIVEC_VERIFY) mjpeg_info("SETTING AltiVec VERIFY for PREDICTION!"); # endif # else mjpeg_info("SETTING AltiVec for PREDICTION!"); # endif # if ALTIVEC_TEST_FUNCTION(pred_comp) ppred_comp = ALTIVEC_TEST_SUFFIX(pred_comp); # else ppred_comp = ALTIVEC_SUFFIX(pred_comp); # endif #endif /* HAVE_ALTIVEC */ } } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/Makefile.am0000644000175000017500000000457711442756174017775 0ustar glowwormglowworm# # Automake Makefile template for mpeg2enc++ library # and mpeg2enc command line wrapper. # bin_PROGRAMS = mpeg2enc mpeg2encpp_MMXSSE_INLINE = \ fdct_x86.c \ fdct_mmx.c \ idct_mmx.c \ quant_mmx.c \ predict_mmx.c \ predcomp_mmx.c \ predcomp_mmxe.c \ predict_x86.c \ quantize_x86.c \ transfrm_x86.c EXTRA_DIST = NOTES README TODO INSTALL ChangeLog seqstats.cc seqstats.hh MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/utils LIBMJPEGUTILS = $(top_builddir)/utils/libmjpegutils.la lib_LTLIBRARIES = libmpeg2encpp.la if HAVE_ASM_MMX SIMD_INLINE = $(mpeg2encpp_MMXSSE_INLINE) endif # HAVE_ASM_MMX # Reference implementations of lowlevel routines that may have Architecture # dependent (usually SIMD) implementations mpeg2enc_REF = \ fdct.c \ idct.c \ predict_ref.c \ quantize_ref.c \ transfrm_ref.c mpeg2enc_noinst_header_REF = \ transfrm_ref.h mpeg2enc_inst_header_REF = \ predict_ref.h mpeg2enc_SOURCES = mpeg2enc.cc libmpeg2encpp_la_SOURCES = conform.cc elemstrmwriter.cc encoderparams.cc \ macroblock.cc motionest.cc mpeg2coder.cc mpeg2encoptions.cc \ imageplanes.cc mpeg2encoder.cc \ picture.cc picturereader.cc predict.cc putpic.cc \ streamstate.cc seqencoder.cc \ quantize.cc ratectl.cc stats.cc synchrolib.cc tables.c \ transfrm.cc $(mpeg2enc_REF) \ $(SIMD_INLINE) ontheflyratectlpass1.cc ontheflyratectlpass2.cc \ rate_complexity_model.cc noinst_HEADERS = channel.hh quantize_precomp.h simd.h \ tables.h $(mpeg2enc_noinst_header_REF) rate_complexity_model.hh libmpeg2encpp_includedir = $(pkgincludedir)/mpeg2enc libmpeg2encpp_include_HEADERS = elemstrmwriter.hh encoderparams.hh \ encodertypes.h macroblock.hh mpeg2coder.hh mpeg2encoder.hh mpeg2encoptions.hh \ mpeg2encparams.h picture.hh picturereader.hh quantize.hh quantize_ref.h ratectl.hh \ streamstate.h seqencoder.hh synchrolib.h syntaxconsts.h $(mpeg2enc_inst_header_REF) \ ontheflyratectlpass1.hh ontheflyratectlpass2.hh \ mpeg2syntaxcodes.h imageplanes.hh libmpeg2encpp_la_LDFLAGS = \ ${LT_STATIC} \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -release $(LT_RELEASE) ${EXTRA_LDFLAGS} libmpeg2encpp_la_DEPENDENCIES = $(LIBMJPEGUTILS) libmpeg2encpp_la_LIBADD = $(LIBMJPEGUTILS) @PTHREAD_LIBS@ mpeg2enc_DEPENDENCIES = \ $(LIBMJPEGUTILS) \ libmpeg2encpp.la mpeg2enc_LDADD = \ libmpeg2encpp.la \ $(LIBMJPEGUTILS) \ @PTHREAD_LIBS@ @LIBGETOPT_LIB@ $(LIBM_LIBS) mjpegtools-2.1.0/mpeg2enc/seqencoder.cc0000644000175000017500000006724011456612024020362 0ustar glowwormglowworm/* (C) 2000, 2001, 2005, 2006 Andrew Stevens * This file is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ /* * 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. * */ #include "config.h" #include #include #include #include #include #include "mjpeg_types.h" #include "mjpeg_logging.h" #include "mpeg2syntaxcodes.h" #include "mpeg2encoder.hh" #include "elemstrmwriter.hh" #include "picturereader.hh" #include "seqencoder.hh" #include "ratectl.hh" #include "tables.h" #include "channel.hh" // -------------------------------------------------------------------------------- // Striped Encoding Job parallel despatch classes // // Selection of the way macro blocks are distributed between // threads. // // STRIPED ensures each job processes macroblocks in encoding order // This is useful for parallelising threads generating output. // INTERLEAVED ensures shared caches enjoy reasonable locality of reference. // struct EncoderJob { enum JobPattern { ENCODE_ORDER, INTERLEAVED }; EncoderJob() : shutdown( false ),working(false) {} void (MacroBlock::*encodingFunc)(); Picture *picture; JobPattern pattern; unsigned int stripe; bool shutdown; volatile bool working; }; class ShutdownJob : public EncoderJob { public: ShutdownJob() { shutdown = true; } }; class Despatcher { public: Despatcher(); ~Despatcher(); void Init( unsigned int parallelism ); void Despatch( Picture &picture, void (MacroBlock::*encodingFunc)(), EncoderJob::JobPattern pattern = EncoderJob::INTERLEAVED ); void ParallelWorker(); void WaitForCompletion(); private: static void *ParallelPerformWrapper(void *despatcher); unsigned int parallelism; Channel jobstodo; vector jobpool; pthread_t *worker_threads; }; Despatcher::Despatcher() : worker_threads(0) {} void Despatcher::Init( unsigned int _parallelism ) { parallelism = _parallelism; mjpeg_debug( "PAR = %d\n", parallelism ); if( parallelism > 0 ) { jobpool.resize(parallelism); pthread_attr_t *pattr = 0; EncoderJob job; /* For some Unixen we get a ridiculously small default stack size. Hence we need to beef this up if we can. */ #ifdef HAVE_PTHREADSTACKSIZE #define MINSTACKSIZE 200000 pthread_attr_t attr; size_t stacksize; pthread_attr_init(&attr); pthread_attr_getstacksize(&attr, &stacksize); if (stacksize < MINSTACKSIZE) { pthread_attr_setstacksize(&attr, MINSTACKSIZE); } pattr = &attr; #endif worker_threads = new pthread_t[parallelism]; for( unsigned int i = 0; i < parallelism; ++i ) { jobpool[i].working = false; jobpool[i].stripe = i; mjpeg_debug("Creating worker thread %d", i ); if( pthread_create( &worker_threads[i], pattr, &Despatcher::ParallelPerformWrapper, this ) != 0 ) { mjpeg_error_exit1( "worker thread creation failed: %s", strerror(errno) ); } } } } Despatcher::~Despatcher() { if( worker_threads != 0 ) { WaitForCompletion(); unsigned int i; ShutdownJob shutdownjob; for( i = 0; i < parallelism; ++i ) { jobstodo.Put( &shutdownjob ); } for( i = 0; i < parallelism; ++i ) { pthread_join( worker_threads[i], NULL ); } delete [] worker_threads; } } void *Despatcher::ParallelPerformWrapper(void *despatcher) { static_cast(despatcher)->ParallelWorker(); return 0; } void Despatcher::ParallelWorker() { EncoderJob *job; mjpeg_debug( "Worker thread started" ); pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL ); for(;;) { // Get Job to do and do it!! mjpeg_debug( "Worker: getting" ); jobstodo.Get( job ); if( job->shutdown ) { mjpeg_debug("SHUTDOWN worker" ); pthread_exit( 0 ); } mjpeg_debug( "Working: stripe %d/%d %d", job->stripe, parallelism, job->pattern ); Picture *picture = job->picture; vector::iterator macroblocks_begin; vector::iterator macroblocks_end; switch( picture->pict_struct ) { case FRAME_PICTURE : macroblocks_begin = picture->mbinfo.begin(); macroblocks_end = picture->mbinfo.end(); break; case TOP_FIELD : macroblocks_begin = picture->mbinfo.begin(); macroblocks_end = picture->mbinfo.begin() + picture->mbinfo.size()/2; break; case BOTTOM_FIELD : macroblocks_begin = picture->mbinfo.begin() + picture->mbinfo.size()/2; macroblocks_end = picture->mbinfo.end(); break; } int macroblocks = macroblocks_end-macroblocks_begin; vector::iterator stripe_begin; vector::iterator stripe_end; vector::iterator mbi; int stripe_step; switch( job->pattern ) { case EncoderJob::ENCODE_ORDER : stripe_step = 1; stripe_begin = macroblocks_begin + job->stripe* macroblocks/parallelism; stripe_end = macroblocks_begin + (job->stripe+1)* macroblocks/parallelism; break; default : case EncoderJob::INTERLEAVED : stripe_step = parallelism; stripe_begin = macroblocks_begin+job->stripe; stripe_end = macroblocks_end; break; } for( mbi = stripe_begin; mbi < stripe_end; mbi += stripe_step ) { (*mbi.*job->encodingFunc)(); } mjpeg_debug( "Worker: stripe %d done", job->stripe ); job->working = false; } } void Despatcher::Despatch( Picture &picture, void (MacroBlock::*encodingFunc)(), EncoderJob::JobPattern pattern ) { if( parallelism > 0 ) { for( unsigned int stripe = 0; stripe < parallelism; ++stripe ) { EncoderJob *job = &jobpool[stripe]; // We guanratee a previously despatched stripe has completed before it is redespatched while( job->working ) { jobstodo.WaitForNewConsumers(); } job->working = true; job->pattern = pattern; job->encodingFunc = encodingFunc; job->picture = &picture; jobstodo.Put( job ); } } else { vector::iterator mbi; for( mbi = picture.mbinfo.begin(); mbi < picture.mbinfo.end(); ++mbi ) { (*mbi.*encodingFunc)(); } } } void Despatcher::WaitForCompletion() { // // We know all despatched jobs have completed if the entire // pool of worker threads is waiting on the job despatch // channel // if( parallelism > 0 ) { jobstodo.WaitUntilConsumersWaitingAtLeast( parallelism ); } } // -------------------------------------------------------------------------------- // Sequence Encoder top-level clapass1_ss. // SeqEncoder::SeqEncoder( EncoderParams &_encparams, PictureReader &_reader, Quantizer &_quantizer, ElemStrmWriter &_writer, Pass1RateCtl &_p1ratectl, Pass2RateCtl &_p2ratectl ) : encparams( _encparams ), reader( _reader ), quantizer( _quantizer ), writer( _writer ), pass1ratectl( _p1ratectl ), pass2ratectl( _p2ratectl ), p1_despatcher( *new Despatcher ), pass1_rcstate( pass1ratectl.NewState() ), pass1_ss( _encparams, _reader ) { } SeqEncoder::~SeqEncoder() { delete &p1_despatcher; } /********************* * * Init - Setup encoder once parameters have been set * ********************/ void SeqEncoder::Init() { // // Setup the parallel job despatcher... // p1_despatcher.Init( encparams.encoding_parallelism ); pass1ratectl.Init(); pass2ratectl.Init(); pass1_ss.Init( ); old_ref_picture = 0; // Lots of routines assume (for speed) that // a dummy ref picture is provided even if it is not needed // because the picture being encoded is INTRA new_ref_picture = GetFreshPicture(); free_pictures.push_back( new_ref_picture ); released_ref_frames = 0; } /* * * Generate a new encoding of a picture using the specified rate controller. * * @params encodingFunc generates the macro-block DCTs from the (reconstructed) * image data. Depending on the context it may/may not also perform fresh * motion estimation and compensation. * */ void SeqEncoder::EncodePicture( Picture &picture, RateCtl &ratecontrol) { mjpeg_debug("Start %d %c(%s) %d %d", picture.decode, pict_type_char[picture.pict_type], picture.pict_struct == FRAME_PICTURE ? "prg" : ( (picture.pict_struct == TOP_FIELD) ? "top" : "bot"), picture.temp_ref, picture.present); p1_despatcher.Despatch( picture, &MacroBlock::Encode ); p1_despatcher.WaitForCompletion(); int padding_needed; picture.PutHeaders(); picture.QuantiseAndCode(ratecontrol); ratecontrol.PictUpdate( picture, padding_needed); picture.PutTrailers(padding_needed); picture.Reconstruct(); } /* * * Retain an existing encoding of a picture using the specified rate controller. * * When we retain the encoding of a picture we need to set and update * the rate-controller for the picture so it can update its internal * bit-allocation model based on the retained encoding. * */ void SeqEncoder::RetainPicture( Picture &picture, RateCtl &ratecontrol) { mjpeg_debug("Retain %d %c(%s) %d %d", picture.decode, pict_type_char[picture.pict_type], picture.pict_struct == FRAME_PICTURE ? "prg" : ( (picture.pict_struct == TOP_FIELD) ? "top" : "bot"), picture.temp_ref, picture.present); // Even ff we don't re-encode we need to update the rate controller //to take into account the encoding we a 'recycling' int dummy; pass2ratectl.PictUpdate( picture, dummy ); } void SeqEncoder::EncodeStreamOneStep() { // For now we simply round-robin schedule the // various passes. Later - they get split into // seperate processes/threads!! if( !pass1_ss.EndOfStream() ) { Pass1Process(); // // TODO Sequence splitting really needs to be done in pass-2 // HOwever, the would entail changing GOP structure :-( // in ::GopSetup.... pass1_ss.Next( BitsAfterMux() ); } if( pass2queue.size() > 0 ) { Pass2Process(); } } bool SeqEncoder::EncodeStreamWhile() { return (pass1coded.size() > 0 || pass2queue.size() > 0); } /********************* * * EncodeStream - Where it all happens. This is the top-level loop * that despatches all the encoding work. Encoding is always performed * two-papass1_ss. * Pass 1: a first encoding that determines the GOP * structure, but may only do rough-and-ready bit allocation that is * visually sub-optimal and/or may violate the specified maximum bit-rate. * * Pass 2: Pictures from Pass1 are, if necessary, re-quantised and the results * coded to accurate achieve good bit-allocation and satisfy bit-rate limits. * * In 'single-pass mode' pass 2 re-encodes only if it 'has to'. * In 'look-ahead mode' pass 2 always re-encodes. * In 'Pass 1 of two-pass mode' Pass-2 simply dumps frame complexity and motion * estimation data from Pass-1. * In 'Pass 2 of two-pass mode' Pass-1 rebuilds frames based on ME and complexity * data from a 'Pass 1 of two-pass mode' run and Pass-2 does some final optimisation. * * N.b. almost all the interesting stuff occurs in the Pass1 encoding. If selected: * - A GOP may be low-passed and re-encoded if it looks like excessive quantisation * is needed. * - GOP length is determined (P frames with mostly intra-coded blocks are turned * into I-frames. * * NOTE: Eventually there will be support for Pass2 to occur in seperate threads... * ********************/ void SeqEncoder::EncodeStream() { // // Repeated calls to TransformFrame build up the queue of // Encoded with quantisation controlled by the // pass1 rate controller. do { EncodeStreamOneStep(); } while( EncodeStreamWhile() ); StreamEnd(); } Picture *SeqEncoder::GetFreshPicture() { Picture *fresh; if( free_pictures.size() == 0 ) fresh = new Picture(encparams, writer , quantizer); else { fresh = free_pictures.back(); free_pictures.pop_back(); } return fresh; } void SeqEncoder::ReleasePicture( Picture *picture ) { // We don't want to free up Picture objects for re-use // until we're sure the encoded picture can no longer // be used as a referenced image when encoding later // pictures. So we queue possibly referenced Picture's // until at least *2* newer reference Frame's have been // released. if( picture->FinalFieldOfRefFrame() ) { ++released_ref_frames; released_pictures.push_back( picture ); if( released_ref_frames > 2 ) { Picture *nolonger_refd; do { nolonger_refd = released_pictures.front(); released_pictures.pop_front(); if( nolonger_refd->finalfield ) reader.ReleaseFrame( nolonger_refd->present ); free_pictures.push_back( nolonger_refd ); } while( !nolonger_refd->FinalFieldOfRefFrame() ); } } else { released_pictures.push_back( picture ); } } /* Encode a picture from scratch: motion estimate relative to the reference frames (if any), encode the resulting macro block image data using the best motion estimate available and buffer the result. */ void SeqEncoder::Pass1EncodePicture(Picture &picture, int field) { // Checkpoint rate-control parameters in case GOP re-structuring // requires a re-encoding. pass1_rcstate->Set( pass1ratectl.GetState() ); // Set up picture parameters picture.SetFrameParams( pass1_ss, field ); // Motion estimation picture.MotionSubSampledLum(); p1_despatcher.Despatch( picture, &MacroBlock::MotionEstimateAndModeSelect ); p1_despatcher.WaitForCompletion(); // Set preliminary GOP structure if( pass1_ss.g_idx == 0 ) pass1ratectl.GopSetup( pass1_ss.np, pass1_ss.nb ); // Setup rate control pass1ratectl.PictSetup(picture); // Reconstruct, transform, and encode EncodePicture( picture, pass1ratectl); mjpeg_info("Enc1 %5d %5d(%2d) %c q=%3.2f %s [%.0f%% Intra]", picture.decode, picture.present, picture.temp_ref, pict_type_char[pass1_ss.frame_type], picture.ABQ, picture.pad ? "PAD" : " ", picture.IntraCodedBlocks() * 100.0 ); } /* Re-Encode a picture after type or parameters have been revised from scratch. N.b. this means motion estimation is *RE-DONE* as it is only. */ void SeqEncoder::Pass1ReEncodePicture0(Picture &picture, void (MacroBlock::*modeMotionAdjustFunc)()) { // Flush any previous encoding picture.DiscardCoding(); // Reset rate controller to undo effect of previous encoding pass1ratectl.SetState( pass1_rcstate->Get() ); // Setup picture to reflect possibly adjusted sequence structure picture.SetFrameParams( pass1_ss, 0 ); // Adjust/ or recompute motion estimation and the corresponding coding // mode select p1_despatcher.Despatch( picture, modeMotionAdjustFunc ); p1_despatcher.WaitForCompletion(); // Set new GOP structure (if any) if( pass1_ss.g_idx == 0 ) pass1ratectl.GopSetup( pass1_ss.np, pass1_ss.nb ); // Setup rate control pass1ratectl.PictSetup(picture); // We need to re-run motion estimation here as we may have changed the // GOP structure EncodePicture( picture, pass1ratectl); mjpeg_info("Renc1 %5d %5d(%2d) %c q=%3.2f %s", picture.decode, picture.present, picture.temp_ref, pict_type_char[pass1_ss.frame_type], picture.AQ, picture.pad ? "PAD" : " "); } Picture *SeqEncoder::NextFramePicture0() { Picture *frame_pic; if ( pass1_ss.b_idx == 0 ) // I or P Frame (First frame in B-group) { old_ref_picture = new_ref_picture; new_ref_picture = frame_pic = GetFreshPicture(); frame_pic->fwd_org = old_ref_picture->org_img; frame_pic->fwd_rec = old_ref_picture->rec_img; frame_pic->fwd_ref_frame = old_ref_picture; frame_pic->bwd_ref_frame = 0; } else // B Frame { frame_pic = GetFreshPicture(); frame_pic->fwd_org = old_ref_picture->org_img; frame_pic->fwd_rec = old_ref_picture->rec_img; frame_pic->bwd_org = new_ref_picture->org_img; frame_pic->bwd_rec = new_ref_picture->rec_img; frame_pic->fwd_ref_frame = old_ref_picture; frame_pic->bwd_ref_frame = new_ref_picture; } // Frames are presented at input in playback (presentation) order frame_pic->org_img = reader.ReadFrame( pass1_ss.PresentationNum() ); return frame_pic; } Picture *SeqEncoder::NextFramePicture1(Picture *frame_pic0) { Picture *frame_pic1; frame_pic1 = GetFreshPicture(); frame_pic1->fwd_org = frame_pic0->fwd_org; frame_pic1->fwd_rec = frame_pic0->fwd_rec; frame_pic1->bwd_org = frame_pic0->bwd_org; frame_pic1->bwd_rec = frame_pic0->bwd_rec; frame_pic1->fwd_ref_frame = frame_pic0->fwd_ref_frame; frame_pic1->bwd_ref_frame = frame_pic0->bwd_ref_frame; frame_pic1->org_img = frame_pic0->org_img; return frame_pic1; } void SeqEncoder::Pass1GopSplitting( Picture &picture) { assert( ! picture.secondfield ); // Should this P frame really have been an I-frame ? if( pass1_ss.b_idx ==0 && picture.IntraCodedBlocks() > 0.6 && pass1_ss.CanSplitHere() ) { int old_present = picture.present; if( (!pass1_ss.NextGopClosed() || pass1_ss.BGroupLength() == 1) ) { mjpeg_debug( "GOP split point found here... %d %d %.0f%% intra coded", pass1_ss.NextGopClosed(), pass1_ss.BGroupLength(), picture.IntraCodedBlocks() * 100.0 ); pass1_ss.ForceIFrame(); assert( picture.present == old_present); Pass1ReEncodePicture0( picture, &MacroBlock::ForceIFrame ); } else if( encparams.M_min == 1 ) { // Next GOP is closed - and B-frames. We can't just turn the P into an I // as the first of the next GOP frame would then be the first B frame and not // the current P frame. // Solution: we need to back up and code the remainder of the GOP without // B frames to allow the I frame to be inserted at the right spot. mjpeg_debug( "GOP split forces P-frames only... %.0f%% intra coded", picture.IntraCodedBlocks() * 100.0 ); pass1_ss.SuppressBFrames(); picture.org_img = reader.ReadFrame( pass1_ss.PresentationNum() ); Pass1ReEncodePicture0( picture, &MacroBlock::MotionEstimateAndModeSelect ); } } } /********************* * * Pass1Process - Do a unit of work in building up a queue of * Pass-1 encoded frame's. * * A Frame is encoded based on a normal (maximum) length GOP with quantisation * determined by Pass1 rate controller. * * If the Frame is a P-frame and is almost entirely intra-coded the picture is * converted to an I-frame and the current GOP ended early. * * Once a GOP is succesfully completed its Picture's are transferred to the * pass2queue for Pass-2 encoding. * *********************/ void SeqEncoder::Pass1Process() { Picture *frame_pic[2], *last_pic; frame_pic[0] = NextFramePicture0(); Pass1EncodePicture( *frame_pic[0], 0 ); Pass1GopSplitting( *frame_pic[0] ); pass1coded.push_back( frame_pic[0] ); if( encparams.fieldpic ) { frame_pic[1] = NextFramePicture1( frame_pic[0] ); Pass1EncodePicture( *frame_pic[1], 1 ); pass1coded.push_back( frame_pic[1] ); last_pic = frame_pic[1]; } else { last_pic = frame_pic[0]; } // Find pictures that can now safely be pass 2 encoded unsigned int to_queue = 0; unsigned int i; if( last_pic->end_seq ) { mjpeg_info( "Sequence end reached"); // If end of sequence we flush everything as next GOP won't refer to this frame to_queue = pass1coded.size(); } else if( pass1_ss.b_idx == 0 ) // I or P Frame (First frame in B-group) { // We have a new fwd reference picture: anything decoded before // will no longer be referenced and can be passed on. for( i = 0; i < pass1coded.size(); ++i ) { if( pass1coded[i] == old_ref_picture) break; } to_queue = i == pass1coded.size() ? 0 : i; } // Queue pass-2 codable pictures for pass-2 coding, for( i = 0; i < to_queue; ++i ) { pass2queue.push_back( pass1coded.front() ); pass1coded.pop_front(); } } /********************* * * BitsAfterMux - Estimate the size of the multiplexed stream based * on video stream size and estimate overheads for other * components * *********************/ uint64_t SeqEncoder::BitsAfterMux() const { double frame_periods; uint64_t bits_after_mux; if( encparams.pulldown_32 ) frame_periods = (double)pass1_ss.DecodeNum()*(5.0/4.0); else frame_periods = (double)pass1_ss.DecodeNum(); // // For VBR we estimate total bits based on actual stream size and // an estimate for the other streams based on time. // For CBR we do *both* based on time to account for padding during // muxing. if( encparams.quant_floor > 0.0 ) // VBR bits_after_mux = writer.BitCount() + (uint64_t)((frame_periods / encparams.frame_rate) * encparams.nonvid_bit_rate); else // CBR bits_after_mux = (uint64_t)((frame_periods / encparams.frame_rate) * (encparams.nonvid_bit_rate + encparams.bit_rate)); return bits_after_mux; } /* Encode a picture based on pass-1 data. */ bool SeqEncoder::Pass2EncodePicture(Picture &picture, bool force_reencode) { pass2ratectl.PictSetup(picture); bool reencode = pass2ratectl.ReencodeRequired() || force_reencode; if( reencode ) { // Flush any previous encoding picture.DiscardCoding(); // We retain the motion estimation / compensation from pass-1 // N.b. prediction is still required as the reference images may // have been re-coded! EncodePicture( picture, pass2ratectl); } else { RetainPicture( picture, pass2ratectl ); } mjpeg_info("Pass2 %5d %5d(%2d) %c q=%3.2f %s", picture.decode, picture.present, picture.temp_ref, pict_type_char[picture.pict_type], picture.ABQ, reencode ? "RECODED" : "RETAINED" ); return reencode; } /********************* * * Pass2Process - Do a unit of work in generating pass-2 encoded frames * as each pass-1 coded frame is queued. * * Every time a complete pass-1 GOP is present its statistics are used to * setup the pass-2 bit-rate controller. Frames are then either * commited using the coding generated in pass 1, or if necessary re-encoded * with an update quantisation to ensure they hit the target size and/or * respect buffering constraints. * *********************/ void SeqEncoder::Pass2Process() { // Find end of current GOP by find next I frame *after* // 1st frame of GOP deque::iterator i = pass2queue.begin()+1; while( i < pass2queue.end() ) { if( (*i)->pict_type == I_TYPE ) // First frame of next GOP break; ++i; } // Reached end of Queue without an I-frame or end of sequence // GOP is not yet complete to allow pass-2 coding... if( i == pass2queue.end() && !pass2queue.back()->end_seq) { return; } // Next GOP is [pass2queue.begin,i) // Setup rate control for next GOP based on structure // and statistics inherited from pass 1 pass2ratectl.GopSetup( pass2queue.begin(), i ); bool reference_reencoded = false; int gop_size = i-pass2queue.begin(); for( int p =0; p < gop_size; ++p ) { Picture *pic = pass2queue.front(); bool reencoded = Pass2EncodePicture( *pic, reference_reencoded ); reference_reencoded |= reencoded && pic->pict_type != B_TYPE; pic->CommitCoding(); ReleasePicture( pic ); pass2queue.pop_front(); } } void SeqEncoder::StreamEnd() { uint64_t bits_after_mux = BitsAfterMux(); mjpeg_info( "Parameters for 2nd pass (stream frames, stream frames): -L %u -Z %.0f", pass2ratectl.getEncodedFrames(), pass2ratectl.getStreamComplexity() ); mjpeg_info( "Guesstimated final muxed size = %lld\n", bits_after_mux/8 ); unsigned int i; for( i = 0; i < free_pictures.size(); ++i ) { delete free_pictures[i]; } for( i = 0; i < released_pictures.size(); ++i ) { delete released_pictures[i]; } } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/mpeg2encoder.cc0000644000175000017500000000360310370237325020576 0ustar glowwormglowworm/* mpeg2encoder.hh Top-level class for an instance of the mpeg2enc++ * MPEG-1/2 encoder. That evolved out of the MSSG mpeg2enc reference * encoder */ /* (C) 2003 Andrew Stevens */ /* This Software is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "mpeg2encoder.hh" #include "picturereader.hh" #include "elemstrmwriter.hh" #include "quantize.hh" #include "ratectl.hh" #include "seqencoder.hh" #include "mpeg2coder.hh" #include "simd.h" #include "motionsearch.h" MPEG2Encoder::MPEG2Encoder( MPEG2EncOptions &_options) : options( _options ), parms( options ), reader(0), writer(0), quantizer(0), coder(0), pass1ratectl(0), pass2ratectl(0) { if( !simd_init ) SIMDInitOnce(); simd_init = true; } MPEG2Encoder::~MPEG2Encoder() { delete seqencoder; delete pass1ratectl; delete pass2ratectl; delete coder; delete quantizer; delete writer; delete reader; } bool MPEG2Encoder::simd_init = false; void MPEG2Encoder::SIMDInitOnce() { init_motion_search(); init_transform(); init_predict(); } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/ontheflyratectlpass2.cc0000644000175000017500000004636211456612024022414 0ustar glowwormglowworm/* ratectl.c, bitrate control routines (linear quantization only currently) */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ /* Modifications and enhancements (C) 2000,2001,2002,2003 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "config.h" #include #include #include "mjpeg_types.h" #include "mjpeg_logging.h" #include "mpeg2syntaxcodes.h" #include "tables.h" #include "mpeg2encoder.hh" #include "picture.hh" #include "ontheflyratectlpass2.hh" #include "cpu_accel.h" /***************************** * * On the fly rate controller for encoding pass2. * A simple virtual buffer controller that exploits * limited look-ahead knowledge of the complexity of upcoming frames. * ****************************/ OnTheFlyPass2::OnTheFlyPass2(EncoderParams &encparams ) : Pass2RateCtl(encparams, *this) { buffer_variation = 0; bits_transported = 0; seq_bits_used = 0; total_bits_used = 0; sum_avg_act = 0.0; sum_avg_quant = 0.0; m_encoded_frames = 0; m_control_undershoot = 0; m_picture_xhi_bitrate = 0; m_strm_Xhi = 0.0; m_seq_ctrl_bitrate = encparams.bit_rate; } void OnTheFlyPass2::Init() { /* Gain is set so that feedback is set to recover buffer variation in 0.5 seconds for a typical DVD stream. Gain is reduce in proportion to buffer size and increased in proportion to bit-rate. */ double per_frame_bits = encparams.bit_rate / encparams.decode_frame_rate; int buffer_danger = 3 * per_frame_bits ; buffer_variation_danger = (encparams.video_buffer_size-buffer_danger); overshoot_gain = (2.0 * (230.0*8.0/11000.0)) * encparams.bit_rate / encparams.video_buffer_size; } /********************* * * Initialise rate control parameters for start of new sequence * ********************/ void OnTheFlyPass2::InitSeq() { /* If its stills with a size we have to hit then make the guesstimates of for initial quantisation pessimistic... */ bits_transported = seq_bits_used = 0; field_rate = 2*encparams.decode_frame_rate; fields_per_pict = encparams.fieldpic ? 1 : 2; if( encparams.still_size > 0 ) { per_pict_bits = encparams.still_size * 8; } else { per_pict_bits = static_cast(encparams.fieldpic ? encparams.bit_rate / field_rate : encparams.bit_rate / encparams.decode_frame_rate ); } mean_reencode_A_T_ratio = 1.0; } void OnTheFlyPass2::GopSetup( std::deque::iterator gop_begin, std::deque::iterator gop_end ) { /* At the start of a GOP before any frames have gone the actual buffer state represents a long term average. Any undershoot due to the I_frame of the previous GOP should by now have been caught up. */ gop_buffer_correction = 0; mjpeg_debug( "PASS2 GOP Rate Lookead" ); std::deque::iterator i; double sum_Xhi = 0.0; for( i = gop_begin; i != gop_end; ++i ) { //mjpeg_info( "P2RC: %d xhi = %.0f", (*i)->decode, (*i)->ABQ * (*i)->EncodedSize() ); double frame_Xhi = (*i)->ABQ * (*i)->EncodedSize(); sum_Xhi += frame_Xhi; } GopStats gop_stats; gop_stats.pictures = static_cast(gop_end - gop_begin); gop_stats.Xhi = sum_Xhi; m_gop_stats_Q.push_back( gop_stats ); } /* **************************** * * Reinitialize rate control parameters for start of new GOP * * ****************************/ void OnTheFlyPass2::InitGOP( ) { mjpeg_debug( "PASS2 GOP Rate Init" ); GopStats gop_stats = m_gop_stats_Q.front(); m_gop_stats_Q.pop_front(); fields_in_gop = fields_per_pict * gop_stats.pictures; gop_Xhi = gop_stats.Xhi; //mjpeg_info( "P2RC: GOP actual size %.0f total xhi = %0.f",total_size, gop_Xhi); // Sanity check complexity based allocation to ensure it doesn't cause // buffer underflow unsigned int rep_sample_frames; if( encparams.stream_frames == 0 ) { // No stream length given ... 5 minutes of video ought to be representative rep_sample_frames = 25*5*60; // 5 min of video } else { // 10% of stream or 10 GOPs... rep_sample_frames = std::max( encparams.N_max * 10, encparams.stream_frames / 10 ); } double undershoot = 0.0; if( encparams.target_bitrate > 0 ) { if( m_strm_Xhi < encparams.stream_Xhi && m_encoded_frames < encparams.stream_frames ) { // Two pass encoding we - we know exact # bits under/overshoot from // target. undershoot = m_control_undershoot; m_seq_ctrl_weight = 1.0; double stream_bits = encparams.stream_frames * encparams.target_bitrate / encparams.frame_rate ; m_picture_xhi_bitrate = (field_rate/fields_per_pict) * stream_bits / encparams.stream_frames; } else { // Rate feedback... aim to recover under/overshoot over the // period of a representative sample of frames undershoot = encparams.target_bitrate * m_encoded_frames / encparams.decode_frame_rate - total_bits_used; m_seq_ctrl_weight = std::min( 1.0, static_cast(m_encoded_frames) / rep_sample_frames ); m_picture_xhi_bitrate = 0.0; } double rate_feedback = undershoot * encparams.decode_frame_rate / rep_sample_frames; // // We never set control bitrate higher than peak bitrate as otherwise // we risk under-run... m_seq_ctrl_bitrate = std::max( encparams.bit_rate, encparams.target_bitrate + rate_feedback ); } m_mean_gop_Xhi = gop_Xhi / gop_stats.pictures; // if we don't have 2-pass data we wrogressively shift from per-gop to complete // stream rate-control until rep_sample_frames seen... m_mean_strm_Xhi = m_encoded_frames > 0 ? m_strm_Xhi / m_encoded_frames : m_mean_gop_Xhi; mjpeg_info( "Mean strm Xhi = %.0f mean gop Xhi = %.0f pXhibr=%.4f cbr/abr=%d/%.0f under=%.0f", m_mean_strm_Xhi, m_mean_gop_Xhi, m_picture_xhi_bitrate, m_seq_ctrl_bitrate, encparams.target_bitrate * m_encoded_frames / encparams.decode_frame_rate, undershoot ); } /* **************************** * * Reinitialize rate control parameters for start of new Picture * * @return (re)encoding of picture necessary to achieve rate-control * * * TODO: Fix VBV violations here? * * ****************************/ void OnTheFlyPass2::InitPict(Picture &picture) { actsum = picture.VarSumBestMotionComp(); avg_act = actsum/(double)(encparams.mb_per_pict); sum_avg_act += avg_act; actcovered = 0.0; sum_base_Q = 0.0; sum_actual_Q = 0; mquant_change_ctr = encparams.mb_width/4; // Bitrate model: bits_picture(i) = K(i) / quantisation // Hence use Complexity metric = bits * quantisation // TODO Currently we're just using a dumb reactive feedback correction // to avoid buffer under-run... longer term we should look-ahead and // correct looking-ahead ... double buffer_state_feedback = overshoot_gain * buffer_variation; double rel_overshoot = std::max( 0.0, -buffer_variation/buffer_variation_danger ); int actual_bits = picture.EncodedSize(); double Xhi = picture.ABQ * actual_bits; double ctrl_bitrate; if( encparams.still_size > 0 ) { target_bits = per_pict_bits; ctrl_bitrate = encparams.bit_rate; } else if( encparams.target_bitrate > 0 ) { double seq_ctrl_bitrate; if( m_picture_xhi_bitrate != 0.0 ) { seq_ctrl_bitrate = Xhi*m_picture_xhi_bitrate; } else { seq_ctrl_bitrate = Xhi * (m_seq_ctrl_bitrate+buffer_state_feedback) / m_mean_strm_Xhi; } // As the video buffer empties from 1/4 empty bring the control bitrate progressively // dwn so that at 3/4's empty it never exceeds 3/4's peak rate. This ensures // we don't continue to empty the video buffer due to super-active // frames when its already near-empty... double buffer_danger = std::min(1.0,std::max(0.0,(4.0/3.0)*(rel_overshoot-0.25))); seq_ctrl_bitrate = encparams.bit_rate * 3.0/4.0 * buffer_danger + seq_ctrl_bitrate * (1.0-buffer_danger); if( m_picture_xhi_bitrate != 0.0 ) { ctrl_bitrate = seq_ctrl_bitrate+buffer_state_feedback; } else { // Weighted combination of whole-stream rate-control // and simple rate-control maintaining target gop by gop double gop_ctrl_bitrate = Xhi * (encparams.target_bitrate+buffer_state_feedback) / m_mean_gop_Xhi; ctrl_bitrate = m_seq_ctrl_weight * seq_ctrl_bitrate + (1.0-m_seq_ctrl_weight) * gop_ctrl_bitrate; } // Heuristic // We don't set control bit-rate ludicrously low to avoid // quantisation artefacts even on super-low activity frames. double ctrl_bitrate_floor = std::min( encparams.target_bitrate/3.0, encparams.bit_rate/5.0 ); ctrl_bitrate = std::max( ctrl_bitrate, ctrl_bitrate_floor); // N.b. no multiplication by fields_per_pict as Xhi is actually // sum of field complexities == fields_in_pict * mean_field_Xhi... target_bits = fields_per_pict * ctrl_bitrate / field_rate; } else { ctrl_bitrate = (encparams.bit_rate+buffer_state_feedback); // Heuristic // We don't set control bit-rate more below half target bit rate or // more below target bit-rate than peak rate target rate double ctrl_bitrate_floor = encparams.bit_rate/5.0; ctrl_bitrate = std::max( ctrl_bitrate, ctrl_bitrate_floor); double available_bits = ctrl_bitrate * fields_in_gop/field_rate; target_bits = static_cast(available_bits*Xhi/gop_Xhi); } target_bits = min( target_bits, encparams.video_buffer_size*3/4 ); picture.avg_act = avg_act; picture.sum_avg_act = sum_avg_act; double rel_error = (actual_bits-target_bits) / static_cast(target_bits); double scale_quant_floor = std::max(1.0, encparams.quant_floor); // // Tolerance of overshooting target bit allocation // drops to zero from encparams.coding_tolerance // as buffer_variation gets closer to danger level... double overshoot_tolerance = encparams.coding_tolerance * (1.0-rel_overshoot); double undershoot_tolerance = -encparams.coding_tolerance; // Re-encode if we overshot too much or undershot and weren't yet at the specified // quantization floor. reencode = rel_error > overshoot_tolerance || (rel_error < undershoot_tolerance && picture.ABQ > scale_quant_floor ); //fprintf( stderr, "RE = %.2f OT=%.2f UT=%.02f RENC=%d\n", rel_error, overshoot_tolerance, undershoot_tolerance, reencode ); // If re-encoding to hit a target we adjust *relative* to previous (off-target) base quantisation // Since there is often a tendency for systematically under or over correct we maintain a moving // average of the ratio target_bits/actual_bits after re-encoding ansd use this to correct our // correction double target_ABQ = picture.ABQ * actual_bits / target_bits; // If the correction of the correction looks reasonable... use it... double debiased_target_ABQ = target_ABQ * mean_reencode_A_T_ratio; if( actual_bits > target_bits && debiased_target_ABQ > picture.ABQ || actual_bits < target_bits && debiased_target_ABQ < picture.ABQ ) { target_ABQ = debiased_target_ABQ; } double raw_base_Q; if( scale_quant_floor < target_ABQ ) { sample_T_A = reencode; raw_base_Q = target_ABQ; } else { // If we've hit the quantisation floor we *expect* // (A)ctual bits < (T)arget bits so its not // useful to use the T/A ratio to update our estimate // of bias in our T/A ratio when we're trying to actually // hit the target bits. raw_base_Q = scale_quant_floor; sample_T_A = false; } base_Q = ClipQuant( picture.q_scale_type, fmax( encparams.quant_floor, raw_base_Q ) ); cur_int_base_Q = floor( base_Q + 0.5 ); rnd_error = 0.0; cur_mquant = ScaleQuant( picture.q_scale_type, cur_int_base_Q ); mjpeg_info( "%s: %d - reencode actual %d (%.1f) target %d Q=%.1f BV = %.2f cbr=%.0f", reencode ? "RENC" : "SKIP", picture.decode, actual_bits, picture.ABQ, target_bits, base_Q, buffer_variation/((double)encparams.video_buffer_size), ctrl_bitrate ); } /* * Update rate-controls statistics after pictures has ended.. * * RETURN: The amount of padding necessary for picture to meet syntax or * rate constraints... */ void OnTheFlyPass2::PictUpdate( Picture &picture, int &padding_needed) { ++m_encoded_frames; int actual_bits = picture.EncodedSize(); m_control_undershoot += target_bits-actual_bits; if( sample_T_A ) { double A_T_ratio = actual_bits / static_cast(target_bits); mean_reencode_A_T_ratio = ( RENC_A_T_RATIO_WINDOW * mean_reencode_A_T_ratio + A_T_ratio ) / (RENC_A_T_RATIO_WINDOW+1); } /* Compute the estimate of the current decoder buffer state. We use this to feedback-correct the available bit-pool with a fraction of the current buffer state estimate. Note that since we cannot hold more than a buffer-full! Excess would be padded away / transmission would be halted when the buffer was full. TODO for CBR we should assume padding -> update seq_bits_bits_used and total_bits_used to bring buffer_varation = 0. TODO Really we need to use a VBV model to get this precise.... */ seq_bits_used += actual_bits; total_bits_used += actual_bits; bits_transported += per_pict_bits; buffer_variation = static_cast(bits_transported - seq_bits_used); if( buffer_variation > 0 ) { bits_transported = seq_bits_used; buffer_variation = 0; } /* Rate-control ABQ is the average 'base' quantisation (before adjustments for relative macro-block complexity) of the block. This is what is used as a base-line for adjusting quantisation to meet a bit allocation target. */ if( sum_base_Q != 0.0 ) // 0.0 if old encoding retained... { picture.ABQ = sum_base_Q / encparams.mb_per_pict; picture.AQ = static_cast(sum_actual_Q ) / encparams.mb_per_pict; } double Xhi = picture.ABQ * actual_bits; m_strm_Xhi += Xhi; /* Stats and logging. AQ is the average Quantisation of the block. Its only used for stats display as the integerisation of the quantisation value makes it rather coarse for use in estimating bit-demand */ sum_avg_quant += picture.AQ; picture.SQ = sum_avg_quant; mjpeg_debug( "Frame %c A=%6.0f %.2f", pict_type_char[picture.pict_type], actual_bits/8.0, actual_bits/picture.AQ ); // TODO TODO TODO We generate padding only for still frames.... // TODO TODO TODO the relevant code should be moved from pass-1 which should NOT // pad (to allow a decent estimate of required quantisation) padding_needed = 0; } int OnTheFlyPass2::InitialMacroBlockQuant() { return cur_mquant; } int OnTheFlyPass2::TargetPictureEncodingSize() { return target_bits; } /************* * * SelectQuantization - select a quantisation for the current * macroblock based on the fullness of the virtual decoder buffer. * * NOTE: *Must* be called for all Macroblocks as content-based quantisation tuning is * supported. ************/ int OnTheFlyPass2::MacroBlockQuant( const MacroBlock &mb ) { int lum_variance = mb.BaseLumVariance(); const Picture &picture = mb.ParentPicture(); /* We 'dither' the rounded base quantisation so that average base quantisation is close to the target value. This should help achieve smaller adjustments in coding size reasonably accurately. */ --mquant_change_ctr; if( mquant_change_ctr == 0 ) { mquant_change_ctr = encparams.mb_width/4; rnd_error += (cur_int_base_Q - base_Q); if( rnd_error > 0.5 ) cur_int_base_Q -= 1; else if( rnd_error <= -0.5 ) cur_int_base_Q += 1; } double act_boost; if( lum_variance < encparams.boost_var_ceil ) { if( lum_variance < encparams.boost_var_ceil/2) act_boost = encparams.act_boost; else { double max_boost_var = encparams.boost_var_ceil/2; double above_max_boost = (static_cast(lum_variance)-max_boost_var) / max_boost_var; act_boost = 1.0 + (encparams.act_boost-1.0) * (1.0-above_max_boost); } } else act_boost = 1.0; sum_base_Q += cur_int_base_Q; cur_mquant = ScaleQuant(picture.q_scale_type,cur_int_base_Q/act_boost) ; sum_actual_Q += cur_mquant; return cur_mquant; } #if 0 /* VBV calculations * * generates warnings if underflow or overflow occurs */ /* vbv_end_of_picture * * - has to be called directly after writing picture_data() * - needed for accurate VBV buffer overflow calculation * - assumes there is no byte stuffing prior to the next start code * * Note correction for bytes that will be stuffed away in the eventual CBR * bit-stream. */ void OnTheFlyPass2::VbvEndOfPict(Picture &picture) { } /* calc_vbv_delay * * has to be called directly after writing the picture start code, the * reference point for vbv_delay * * A.Stevens 2000: * Actually we call it just before the start code is written, but anyone * who thinks 32 bits +/- in all these other approximations matters is fooling * themselves. */ void OnTheFlyPass2::CalcVbvDelay(Picture &picture) { /* VBV checks would go here...*/ if( !encparams.mpeg1 || encparams.quant_floor != 0 || encparams.still_size > 0) picture.vbv_delay = 0xffff; else if( encparams.still_size > 0 ) picture.vbv_delay = static_cast(90000.0/encparams.frame_rate/4); } #endif /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/mpeg2encparams.h0000644000175000017500000000535111456612024020773 0ustar glowwormglowworm#ifndef _MPEG2ENCPARAMS_H #define _MPEG2ENCPARAMS_H /* mpeg2encoptions.h - Encoding options for mpeg2enc++ MPEG-1/2 * encoder library */ /* (C) 2000/2001 Andrew Stevens */ /* This Software is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ struct MPEG2EncParams { int in_img_width; // MUST match the actual dimensions of the passed frames! int in_img_height; int display_hsize; // Passed on to display extension header int display_vsize; // not used in encoding. int level; // MPEG-2 main profile level to enforce. int format; int bitrate; int target_bitrate; int nonvid_bitrate; unsigned int stream_frames; // # Frames of entire stream double stream_Xhi; // debug feature total stream complexity... int quant; int searchrad; int mpeg; unsigned int aspect_ratio; unsigned int frame_rate; int fieldenc; /* 0: progressive, 1 = frame pictures, interlace frames with field MC and DCT in picture 2 = field pictures */ int norm; /* 'n': NTSC, 'p': PAL, 's': SECAM, else unspecified */ int me44_red ; int me22_red ; int hf_quant; double hf_q_boost; double act_boost; double boost_var_ceil; int rate_control; /* The rate controller to use */ int video_buffer_size; int seq_length_limit; int min_GOP_size; int max_GOP_size; int closed_GOPs; int preserve_B; int Bgrp_size; int num_cpus; int vid32_pulldown; int svcd_scan_data; int seq_hdr_every_gop; int seq_end_every_gop; int still_size; int pad_stills_to_vbv_buffer_size; int vbv_buffer_still_size; int force_interlacing; int input_interlacing; int hack_svcd_hds_bug; int hack_altscan_bug; int hack_dualprime; int mpeg2_dc_prec; int ignore_constraints; int unit_coeff_elim; int force_cbr; int verbose; }; #endif /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/elemstrmwriter.hh0000644000175000017500000001065311456612024021325 0ustar glowwormglowworm#ifndef _ELEMSTREAMWRITER_HH #define _ELEMSTREAMWRITER_HH /* (C) 2003 Andrew Stevens */ /* This Software is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "mjpeg_types.h" class EncoderParams; class ElemStrmWriter { public: ElemStrmWriter( ); virtual ~ElemStrmWriter() = 0; virtual void WriteOutBufferUpto( const uint8_t *buffer, const uint32_t flush_upto ) = 0; inline uint64_t Flushed() const { return flushed; } virtual uint64_t BitCount() = 0; protected: uint64_t flushed; }; /****************************** * * Elementry stream buffer used to accumulate (byte-aligned) fragments ofencoded video. Currently * each frame has its own buffer. * *****************************/ class OutputFragBuf { public: OutputFragBuf(); virtual ~OutputFragBuf(); /************** * * Flush out buffer * N.b. attempts to flush in non byte-aligned states are illegal * and will abort * *************/ virtual void FlushBuffer() = 0; /************** * * Reset buffer - empty buffer discarding current contents. * * ***********/ virtual void ResetBuffer() = 0; /************** * * Write rightmost (least significant) n (0<=n<=32) bits of val to current buffer * *************/ virtual void PutBits( uint32_t val, int n) = 0; inline void AlignBits() { if (outcnt!=8) PutBits(0,outcnt); } inline bool Aligned() const { return outcnt == 8; } inline int ByteCount() const { return unflushed; } protected: int unflushed; int outcnt; // Bits unwritten in current output byte uint32_t pendingbits; }; /****************************** * * Elementry stream buffer used to accumulate (byte-aligned) fragments ofencoded video. Currently * each frame has its own buffer. * *****************************/ class ElemStrmFragBuf : public OutputFragBuf { public: ElemStrmFragBuf( ElemStrmWriter &outstrm); ~ElemStrmFragBuf(); /************** * * Flush out buffer * N.b. attempts to flush in non byte-aligned states are illegal * and will abort * *************/ virtual void FlushBuffer(); /************** * * Reset buffer - empty buffer discarding current contents. * * ***********/ virtual void ResetBuffer(); /************** * * Write rightmost (least significant) n (0<=n<=32) bits of val to current buffer * *************/ virtual void PutBits( uint32_t val, int n); private: void AdjustBuffer(); protected: ElemStrmWriter &writer; uint8_t *buffer; // Output buffer - used to hold byte // aligned output before flushing or // backing up and re-encoding int buffer_size; }; /****************************** * * Elementry stream buffer used to accumulate (byte-aligned) fragments ofencoded video. Currently * each frame has its own buffer. * *****************************/ class CountOnlyFragBuf : public OutputFragBuf { public: CountOnlyFragBuf(); ~CountOnlyFragBuf(); /************** * * Flush out buffer * N.b. attempts to flush in non byte-aligned states are illegal * and will abort * *************/ virtual void FlushBuffer(); /************** * * Reset buffer - empty buffer discarding current contents. * * ***********/ virtual void ResetBuffer(); /************** * * Write rightmost (least significant) n (0<=n<=32) bits of val to current buffer * *************/ virtual void PutBits( uint32_t val, int n); }; /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ #endif mjpegtools-2.1.0/mpeg2enc/predict_ref.h0000644000175000017500000000315210161621374020352 0ustar glowwormglowworm /* predict.h, Low-level Architecture neutral prediction * (motion compensated reconstruction) routines */ /* (C) 2003 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #ifndef _PREDICT_H #define _PREDICT_H #ifdef __cplusplus extern "C" { #endif extern void (*ppred_comp)( uint8_t *src, uint8_t *dst, int stride, int w, int h, int x, int y, int dx, int dy, int addflag); void pred_comp( uint8_t *src, uint8_t *dst, int stride, int w, int h, int x, int y, int dx, int dy, int addflag); void clearblock ( uint8_t *cur[3], int i0, int j0, int field_off, int stride); void init_predict(void); #ifdef __cplusplus } #endif #endif /* _PREDICT_H */ /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/ontheflyratectlpass2.hh0000644000175000017500000001527611456612024022426 0ustar glowwormglowworm#ifndef _ONTHEFLYRATECTLPASS2_HH #define _ONTHELFYRATECTLPASS2_HH /* (C) 2003 Andrew Stevens */ /* This is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "ratectl.hh" /* The parts of of the rate-controller's state neededfor save/restore if backing off a partial encoding */ class OnTheFlyPass2State : public RateCtlState { public: virtual ~OnTheFlyPass2State() {} virtual RateCtlState *New() const { return new OnTheFlyPass2State; } virtual void Set( const RateCtlState &state ) { *this = static_cast(state); } virtual const RateCtlState &Get() const { return *this; } protected: /*! * Number of frames encoded so far in entire stream */ unsigned int m_encoded_frames; /*! * Sum of differences target_size - actual_size for frames encoded so far * (used for 2-pass encoding rate control). */ int64_t m_control_undershoot; /* * Current feedback-control bitrate for whole-sequence rate control */ unsigned int m_seq_ctrl_bitrate; /* * Weighting 0.0 .. 1.0 to give to whole-sequence rate control * (per-gop rate control gets 1.0-m_seq_ctrl_weight) */ double m_seq_ctrl_weight; /* * Bit-rate for unit of picture complexity (Set to != 0.0 when two-pass encoding * rate control) */ double m_picture_xhi_bitrate; /* * Mean stream picture complexity so far in pass 2 */ double m_mean_strm_Xhi; /* * Mean pass-1 picture complexity in pass 1 */ double m_mean_gop_Xhi; int32_t per_pict_bits; int fields_in_gop; double field_rate; int fields_per_pict; /*! * Gain factor to feedback correction to bitrate used to control * bit allocation to recover decoder buffer fullness */ double overshoot_gain; /*! * Estimated amount of space in nominal decoder buffer at * current point in encoding. */ int32_t buffer_variation; /*! * Bits assumed to be transported to decoder * at current point in current sequence */ int64_t bits_transported; /*! * Total bits decoded at current point in entire stream */ int64_t total_bits_used; /*! * Total bits decoded at current point in current sequence */ int64_t seq_bits_used; int32_t gop_buffer_correction; int target_bits; // target bits for current frame double base_quant; /*! * Sum of picture complexities for current gop */ double gop_Xhi; /*! * Sum of pictures complexities up to current point * in entire stream. */ double m_strm_Xhi; /* Moving average of the final ration actual_bits/target_bits after re-encoding of pictures. Used to avoid a bias to under / over correction */ double mean_reencode_A_T_ratio; /* actsum - Total activity (sum block variances) in frame actcovered - Activity macroblocks so far quantised (used to fine tune quantisation to avoid starving highly active blocks appearing late in frame...) UNUSED avg_act - Current average activity... */ double actsum; double actcovered; double sum_avg_act; double avg_act; double sum_avg_quant; }; class OnTheFlyPass2 : public Pass2RateCtl, public OnTheFlyPass2State { public: OnTheFlyPass2( EncoderParams &encoder ); virtual void Init() ; virtual void GopSetup( std::deque::iterator gop_begin, std::deque::iterator gop_end ); virtual void PictUpdate (Picture &picture, int &padding_needed ); virtual int MacroBlockQuant( const MacroBlock &mb); virtual int InitialMacroBlockQuant(); double SumAvgActivity() { return sum_avg_act; } bool ReencodeRequired() const { return reencode; } unsigned int getEncodedFrames() const { return m_encoded_frames; } double getStreamComplexity() const { return m_strm_Xhi; } protected: virtual int TargetPictureEncodingSize(); virtual void InitSeq( ); virtual void InitGOP( ) ; virtual void InitPict( Picture &picture ); struct GopStats { double Xhi; // total complexity for GOP unsigned int pictures; // number of pictures }; /* * Queue of GOP statistics updated as frames are queued (in encoding order) * for pass-2 encoding. Stats are taken off queue * when first picture of GOP is reached. */ std::deque m_gop_stats_Q; private: #if 0 // TODO: Do we need VBV checking? currently left to muxer virtual void CalcVbvDelay (Picture &picture); virtual void VbvEndOfPict (Picture &picture); #endif double base_Q; // Base quantisation (before adjustments // for relative macroblock activity double cur_int_base_Q; // Current rounded base quantisation double rnd_error; // Cumulative rounding error from base // quantisation rounding int cur_mquant; // Current macroblock quantisation int mquant_change_ctr; // Window used for moving average of // post-correction actual / target bits ratio // for re-encoded frames. static const int RENC_A_T_RATIO_WINDOW = 4; bool reencode; // Current Picture flagged for re-encode to better hit // target bitrate. bool sample_T_A; // Finaly (T)arget and (A)ctual bit ratio should be sampled // to maintain an estimate of current systematic mean T/A ratio after // pass 2 re-encoding. double sum_base_Q; // Accumulates base quantisations encoding int sum_actual_Q; // Accumulates actual quantisation double buffer_variation_danger; // Buffer variation level below full // at which serious risk of data under-run in muxed stream }; /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ #endif mjpegtools-2.1.0/mpeg2enc/quant_mmx.c0000644000175000017500000001275110164041347020074 0ustar glowwormglowworm/* * Copyright (C) 2000 Andrew Stevens * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * quantize_ni_mmx.s: MMX optimized coefficient quantization sub-routine */ #include #include "mjpeg_types.h" #include "mmx.h" void iquantize_non_intra_m1_mmx(int16_t *src, int16_t *dst, uint16_t *quant_mat) { int i; /* * MMX Register usage * mm7 = [1|0..3]W * mm6 = [MAX_UINT16-2047|0..3]W * mm5 = 0 */ /* Load 1 into all 4 words of mm7 */ pxor_r2r(mm7, mm7); pcmpeqw_r2r(mm7, mm7); psrlw_i2r(15, mm7); pxor_r2r(mm6, mm6); for(i=0; i<64; i+=4) /* 64 coeffs in a DCT block */ { movq_m2r(src[0], mm0); /* mm0 = *psrc */ src += 4; movq_r2r(mm0, mm2); /* mm2 = TRUE where *psrc==0 */ pcmpeqw_r2r(mm6, mm2); movq_r2r(mm0, mm3); /* mm3 = TRUE where *psrc<0 */ psraw_i2r(15, mm3); /* Work with absolute value for convenience... */ pxor_r2r (mm3, mm0); /* mm0 = abs(*psrc) */ psubw_r2r(mm3, mm0); paddw_r2r(mm0, mm0); /* mm0 = 2*abs(*psrc) */ paddw_r2r(mm7, mm0); /* mm0 = 2*abs(*psrc) + 1 */ movq_m2r(quant_mat[0], mm4); /* multiply by *quant_mat */ movq_r2r(mm0, mm1); pmullw_r2r(mm4, mm0); pmulhw_r2r(mm4, mm1); quant_mat += 4; pcmpgtw_r2r(mm6, mm1); /* if there was overflow, saturate low bits with all 1's */ por_r2r(mm1, mm0); psrlw_i2r(5, mm0); /* divide by 32 (largest possible value = 65535/32 == 2047) */ /* zero case */ pandn_r2r(mm0, mm2); /* set to 0 where *psrc==0 */ /* mismatch control */ movq_r2r(mm2, mm1); psubw_r2r(mm7, mm2); pcmpeqw_r2r(mm6, mm1); /* mm0 = v==0 */ por_r2r(mm7, mm2); pandn_r2r(mm2, mm1); /* Handle zero case and restoring sign */ pxor_r2r(mm3, mm1); /* retain original sign of *psrc */ psubw_r2r(mm3, mm1); movq_r2m(mm1, dst[0]); dst += 4; } emms(); } /* extmmx Inverse mpeg-2 quantisation routine. */ void iquantize_non_intra_m2_mmx(int16_t *src, int16_t *dst, uint16_t *quant_mat) { int sum; int i; int16_t *dst2; /* * mm0 *psrc, scratch * mm1 *pdst * mm2 TRUE if *psrc is 0, then scratch * mm3 TRUE if *psrc is negative * mm4 Partial sums * mm5 * mm6 <0,0,0,0> * mm7 <1,1,1,1> */ /* Load 1 into all 4 words of mm7 */ pxor_r2r(mm7, mm7); pcmpeqw_r2r(mm7, mm7); psrlw_i2r(15, mm7); pxor_r2r(mm6, mm6); pxor_r2r(mm4, mm4); dst2 = dst; for(i=0; i<64; i+=4) /* 64 coeffs in a DCT block */ { movq_m2r(src[0], mm0); /* mm0 = *psrc */ src += 4; movq_r2r(mm0, mm2); /* mm2 = TRUE where *psrc==0 */ pcmpeqw_r2r(mm6, mm2); movq_r2r(mm0, mm3); /* mm3 = TRUE where *psrc<0 */ psraw_i2r(15, mm3); /* Work with absolute value for convenience... */ pxor_r2r (mm3, mm0); /* mm0 = abs(*psrc) */ psubw_r2r(mm3, mm0); paddw_r2r(mm0, mm0); /* mm0 = 2*abs(*psrc) */ paddw_r2r(mm7, mm0); /* mm0 = 2*abs(*psrc) + 1 */ pandn_r2r(mm0, mm2); /* set to 0 where *psrc==0 */ movq_m2r(quant_mat[0], mm1); /* multiply by *quant_mat */ movq_r2r(mm2, mm0); pmulhw_r2r(mm1, mm2); pmullw_r2r(mm1, mm0); quant_mat += 4; pcmpgtw_r2r(mm6, mm2); /* if there was overflow, saturate low bits with all 1's */ por_r2r(mm2, mm0); psrlw_i2r(5, mm0); /* divide by 32 (largest possible value = 65535/32 == 2047) */ /* Accumulate sum... */ paddw_r2r(mm0, mm4); /* Handle zero case and restoring sign */ pxor_r2r(mm3, mm0); /* retain original sign of *psrc */ psubw_r2r(mm3, mm0); movq_r2m(mm0, dst[0]); dst += 4; } /* Mismatch control compute lower bits of sum... */ movq_r2r(mm4, mm5); psrlq_i2r(32, mm5); paddw_r2r(mm5, mm4); movq_r2r(mm4, mm5); psrlq_i2r(16, mm5); paddw_r2r(mm5, mm4); movd_r2g(mm4, sum); sum &= 1; sum ^= 1; dst2[63] ^= sum; emms(); } /* * Simply add up the sum of coefficients weighted * by their quantisation coefficients */ int32_t quant_weight_coeff_sum_mmx(int16_t *src, int16_t *i_quant_mat) { int32_t sum, sum1, sum2; int i; /* * MMX Register usage * mm7 = [1|0..3]W * mm6 = [2047|0..3]W * mm5 = 0 */ pxor_r2r(mm6, mm6); /* Accumulator */ for(i=0; i<16; i+=2) /* 16 coefficient / quantiser quads to process... */ { movq_m2r(src[0], mm0); movq_m2r(src[4], mm2); pxor_r2r(mm1, mm1); pxor_r2r(mm3, mm3); /* * Compute absolute value of coefficients... */ pcmpgtw_r2r(mm0, mm1); /* (mm0 < 0 ) */ pcmpgtw_r2r(mm2, mm3); /* (mm0 < 0 ) */ pxor_r2r(mm1, mm0); pxor_r2r(mm3, mm2); psubw_r2r(mm1, mm0); psubw_r2r(mm3, mm2); /* * Compute the low and high words of the result.... */ pmaddwd_m2r(i_quant_mat[0], mm0); pmaddwd_m2r(i_quant_mat[4], mm2); src += 8; i_quant_mat += 8; paddd_r2r(mm0, mm6); paddd_r2r(mm2, mm6); } movd_r2g(mm6, sum1); psrlq_i2r(32, mm6); movd_r2g(mm6, sum2); sum = sum1 + sum2; emms(); return sum; } mjpegtools-2.1.0/mpeg2enc/macroblock.cc0000644000175000017500000000567311011315326020340 0ustar glowwormglowworm/* macroblock.hh macroblock class... */ /* (C) 2003 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include #include #include #include "macroblock.hh" #include "mpeg2syntaxcodes.h" #include "picture.hh" void MacroBlock::Encode() { Predict(); Transform(); } void MacroBlock::MotionEstimateAndModeSelect() { MotionEstimate(); SelectCodingModeOnVariance(); } void MacroBlock::MotionEstimate() { if (picture->pict_struct==FRAME_PICTURE) { FrameMEs(); } else { FieldME(); } } void MacroBlock::SelectCodingModeOnVariance() { vector::iterator i; vector::iterator min_me; int best_score = INT_MAX; int best_fwd_score = INT_MAX; int cur_score; assert( best_of_kind_me.begin()->mb_type == MB_INTRA ); // // Select motion estimate with lowest variance // Penalise the INTRA motion type slightly because it can't be // skip coded and the DC coefficient is usually large... for( i = best_of_kind_me.begin(); i < best_of_kind_me.end(); ++ i) { cur_score = i->var + (i->mb_type == MB_INTRA ? 3*3*256 : 0); if( cur_score < best_score ) { best_score = cur_score; best_me = &*i; } if( i->mb_type & MB_BACKWARD == 0 && cur_score < best_fwd_score) { best_fwd_score = cur_score; best_fwd_me = &*i; } } } /********************************************** * * ForceIFrame - Force selection of intra-coding so that that macroblock * can be correctly coded in an I Frame. * *********************************************/ void MacroBlock::ForceIFrame() { vector::iterator i = best_of_kind_me.begin(); assert( i->mb_type == MB_INTRA ); best_me = &*i; } /********************************************** * * ForcePFrame - Force selection of motion-estimation so that that macroblock * can be correctly coded in an P Frame. I.e. use only forward * motion estimatino. * *********************************************/ void MacroBlock::ForcePFrame() { best_me = best_fwd_me; } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/quantize.hh0000644000175000017500000000425610444645161020106 0ustar glowwormglowworm#ifndef _QUANTIZER_HH #define _QUANTIZER_HH /* (C) 2003 Andrew Stevens */ /* This Software is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "mjpeg_types.h" #include "quantize_ref.h" class EncoderParams; class Quantizer : public QuantizerCalls { public: Quantizer( EncoderParams &_encoder ); void Init(); ~Quantizer(); inline void QuantIntra( int16_t *src, int16_t *dst, int q_scale_type, int dcprec, int dctsatlim, int *nonsat_mquant) { quant_intra( workspace, src, dst, q_scale_type, dcprec, dctsatlim, nonsat_mquant ); } inline int QuantInter( int16_t *src, int16_t *dst, int q_scale_type, int dctsatlim, int *nonsat_mquant ) { return (*pquant_non_intra)( workspace, src, dst, q_scale_type, dctsatlim, nonsat_mquant ); } inline int WeightCoeffIntra( int16_t *blk ) { return (*pquant_weight_coeff_intra)(workspace, blk); } inline int WeightCoeffInter( int16_t *blk ) { return (*pquant_weight_coeff_inter)(workspace, blk ); } inline void IQuantIntra( int16_t *src, int16_t *dst, int dc_prec, int mquant ) { (*piquant_intra)(workspace, src, dst, dc_prec, mquant ); } inline void IQuantInter( int16_t *src, int16_t *dst, int mquant ) { (*piquant_non_intra)(workspace, src, dst, mquant ); } private: QuantizerWorkSpace *workspace; EncoderParams &encparams; //int dctsatlim; }; /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ #endif mjpegtools-2.1.0/mpeg2enc/INSTALL0000644000175000017500000000060507151727705016756 0ustar glowwormglowwormAdditional Notes on compilation and installation SSE/MMX Support The top-level ./configure script should automatically turn on the inclusion of SSE/MMX routines for x86 processors. Note that the .o files for MMX and SSE are included as well as the assembly language source. This should save hassle for those who can't be bothered with the job of installing nasm. The files are tiny... mjpegtools-2.1.0/mpeg2enc/mpeg2enc.cc0000644000175000017500000010077111712256556017740 0ustar glowwormglowworm/* mpeg2enc.cc, YUV4MPEG / mjpegtools command line wrapper for * mpeg2enc++ library */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ /* Modifications and enhancements (C) 2000/2001 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include #include #ifdef HAVE_GETOPT_H #include #endif #include #include #include #include #include #include "mpeg2encoder.hh" #include "mpeg2encoptions.hh" #include "encoderparams.hh" #include "picturereader.hh" #include "imageplanes.hh" #include "elemstrmwriter.hh" #include "quantize.hh" #include "ontheflyratectlpass1.hh" #include "ontheflyratectlpass2.hh" #include "seqencoder.hh" #include "mpeg2coder.hh" #include "format_codes.h" #include "mpegconsts.h" #ifdef HAVE_ALTIVEC /* needed for ALTIVEC_BENCHMARK and print_benchmark_statistics() */ #include "../utils/altivec/altivec_conf.h" #endif /************************** * * Derived class for File (actually: pipe and FIFO) based bitstream output * *************************/ class FILE_StrmWriter : public ElemStrmWriter { public: FILE_StrmWriter( EncoderParams &encparams, const char *outfilename ) { /* open output file */ if (!(outfile=fopen(outfilename,"wb"))) { mjpeg_error_exit1("Couldn't create output file %s",outfilename); } } virtual void WriteOutBufferUpto( const uint8_t *buffer, const uint32_t flush_upto ) { size_t written = fwrite( buffer, sizeof(uint8_t), static_cast(flush_upto), outfile ); if( written != static_cast(flush_upto) ) { mjpeg_error_exit1( "%s", strerror(ferror(outfile)) ); } flushed += flush_upto; } virtual ~FILE_StrmWriter() { fclose( outfile ); } virtual uint64_t BitCount() { return flushed * 8LL; } private: FILE *outfile; }; /************************** * * Derived class for File (actually: pipe and FIFO) based input of frames * in the YUV4MPEG2 format * *************************/ class Y4MPipeReader : public PictureReader { public: Y4MPipeReader( EncoderParams &encparams, int istrm_fd ); ~Y4MPipeReader(); void StreamPictureParams( MPEG2EncInVidParams &strm ); protected: bool LoadFrame( ImagePlanes &image ); private: int PipeRead( uint8_t *buf, int len); int pipe_fd; y4m_stream_info_t _si; y4m_frame_info_t _fi; }; Y4MPipeReader::Y4MPipeReader( EncoderParams &encparams, int istrm_fd ) : PictureReader( encparams ), pipe_fd( istrm_fd ) { y4m_init_stream_info(&_si); y4m_init_frame_info(&_fi); } Y4MPipeReader::~Y4MPipeReader() { y4m_fini_stream_info(&_si); y4m_fini_frame_info(&_fi); } /**************************************** * * Initialise the reader and return the parameter of the video stream * to be encoded. * * WARNING: This routine must run before encoder parameters are defined. * TODO: Reader should be constructed before EncoderParams and this * routine invoked from EncoderParams constructor... * *****************************************/ void Y4MPipeReader::StreamPictureParams( MPEG2EncInVidParams &strm ) { int n; y4m_ratio_t sar; if ((n = y4m_read_stream_header (pipe_fd, &_si)) != Y4M_OK) { mjpeg_error("Could not read YUV4MPEG2 header: %s!", y4m_strerr(n)); exit (1); } strm.horizontal_size = y4m_si_get_width(&_si); strm.vertical_size = y4m_si_get_height(&_si); strm.frame_rate_code = mpeg_framerate_code(y4m_si_get_framerate(&_si)); strm.interlacing_code = y4m_si_get_interlace(&_si); /* Deduce MPEG aspect ratio from stream's frame size and SAR... (always as an MPEG-2 code; that's what caller expects). */ sar = y4m_si_get_sampleaspect(&_si); strm.aspect_ratio_code = mpeg_guess_mpeg_aspect_code(2, sar, strm.horizontal_size, strm.vertical_size); if(strm.horizontal_size <= 0) { mjpeg_error_exit1("Horizontal size from input stream illegal"); } if(strm.vertical_size <= 0) { mjpeg_error("Vertical size from input stream illegal"); } } /***************************** * * LoadFrame - pull in the image data planes from pipe (planar YUV420) * * RETURN: true iff EOF or ERROR * ****************************/ bool Y4MPipeReader::LoadFrame( ImagePlanes &image ) { int h,v,y; if ((y = y4m_read_frame_header (pipe_fd, &_si, &_fi)) != Y4M_OK) { if( y != Y4M_ERR_EOF ) mjpeg_warn("Error reading frame header (%d): code%s!", frames_read, y4m_strerr (y)); return true; } v = encparams.vertical_size; h = encparams.horizontal_size; int i; for(i=0;i 255) { mjpeg_error("entry %d (%u) in line %d from '%s' invalid", j, q[i + j], row, fname); i = -1; break; } } i += 8; } fclose(fp); if (i != 128) { mjpeg_error("file '%s' did NOT have 128 values - ignoring custom matrix file", fname); return(-1); } for (j = 0; j < 64; j++) { custom_intra_quantizer_matrix[j] = q[j]; custom_nonintra_quantizer_matrix[j] = q[j + 64]; } if (dbug) { mjpeg_info("INTRA and NONINTRA tables from '%s'",fname); for (j = 0; j < 128; j += 8) { mjpeg_info("%u %u %u %u %u %u %u %u", q[j + 0], q[j + 1], q[j + 2], q[j + 3], q[j + 4], q[j + 5], q[j + 6], q[j + 7]); } } return(0); } void MPEG2EncCmdLineOptions::ParseCustomOption(const char *arg) { if (strcmp(arg, "kvcd") == 0) hf_quant = 3; else if (strcmp(arg, "hi-res") == 0) hf_quant = 2; else if (strcmp(arg, "default") == 0) { hf_quant = 0; hf_q_boost = 0; } else if (strcmp(arg, "tmpgenc") == 0) hf_quant = 4; else if (strcmp(arg, "flat") == 0) hf_quant = 5; else if (strncasecmp(arg, "file=", 5) == 0) { if (ParseCustomMatrixFile(arg + 5, arg[0] == 'F' ? 1 : 0) == 0) hf_quant = 6; } else if (strcmp(arg, "help") == 0) { fprintf(stderr, "Quantization matrix names:\n\n"); fprintf(stderr, "\thelp - this message\n"); fprintf(stderr, "\tkvcd - matrices from http://www.kvcd.net\n"); fprintf(stderr, "\thi-res - high resolution tables (same as -H)\n"); fprintf(stderr, "\tdefault - turn off -N or -H (use standard tables)\n"); fprintf(stderr, "\ttmpgenc - TMPGEnc tables (http://www.tmpgenc.com)\n"); fprintf(stderr, "\tflat - flat tables for high bitrate encoding\n"); fprintf(stderr, "\tfile=filename - filename contains custom matrices\n"); fprintf(stderr, "\t\t8 comma separated values per line. 8 lines per matrix, INTRA matrix first, then NONINTRA\n"); exit(0); } else mjpeg_error_exit1("Unknown type '%s' used with -K/--custom-quant", arg); } void MPEG2EncCmdLineOptions::Usage() { fprintf(stderr, "--verbose|-v num\n" " Level of verbosity. 0 = quiet, 1 = normal 2 = verbose/debug\n" "--format|-f fmt\n" " Encoding profile\n" " [0 = Generic MPEG1, 1 = standard VCD, 2 = user VCD,\n" " 3 = Generic MPEG2, 4 = standard SVCD, 5 = user SVCD,\n" " 6 = VCD Stills sequences, 7 = SVCD Stills sequences, 8|9 = DVD,\n" " 10 = ATSC 480i, 11 = ATSC 480p, 12 = ATSC 720p, 13 = ATSC 1080i]\n" "--display-hsize|-x [32..16383]\n" " Set the the display-horizontal-size hint in MPEG-2 output to\n" " something other than the encoded image width\n" "--display-vsize|-y [32..16383]\n" " Set the the display-vertical-size hint in MPEG-2 output to\n" " something other than the encoded image height\n" "--aspect|-a num\n" " Set displayed image aspect ratio image (default: 2 = 4:3)\n" " [1 = 1:1, 2 = 4:3, 3 = 16:9, 4 = 2.21:1]\n" "--frame-rate|-F num\n" " Set playback frame rate of encoded video\n" " (default: frame rate of input stream)\n" " 0 = Display frame rate code table\n" "--video-bitrate|-b num\n" " Set Bitrate / peak bitrate of compressed video in KBit/sec\n" " (Peak bitrate if a target bitrate and/or quantisation floor is set\n" " (default: 1152.0 for VCD, 2500.0 for SVCD, 7500.0 for DVD)\n" "--target-video-bitrate|-t\n" " Set target bitrate for entire video stream in KBit/sec\n" "--nonvideo-bitrate|-B num\n" " Non-video data bitrate to assume for sequence splitting\n" " calculations (see also --sequence-length).\n" "--quantisation|-q num\n" " Image data quantisation factor [1..31] (1 is best quality, no default)\n" " When quantisation is set variable bit-rate encoding is activated and\n" " the --bitrate value sets an *upper-bound* video data-rate\n" "--ratecontroller|-A [0..1] (default:0)\n" " Specify ratecontrol alorithm\n" "--output|-o pathname\n" " Pathname of output file or fifo (REQUIRED!!!)\n" "--target-still-size|-T size\n" " Size in KB of VCD stills\n" "--interlace-mode|-I num\n" " Sets MPEG 2 motion estimation and encoding modes:\n" " 0 = Progressive (non-interlaced)(Movies)\n" " 1 = Interlaced source material (video)\n" " 2 = Interlaced source material, per-field-encoding (video)\n" "--motion-search-radius|-r num\n" " Motion compensation search radius [0..32] (default 16)\n" "--reduction-4x4|-4 num\n" " Reduction factor for 4x4 subsampled candidate motion estimates\n" " [1..4] [1 = max quality, 4 = max. speed] (default: 2)\n" "--reduction-2x2|-2 num\n" " Reduction factor for 2x2 subsampled candidate motion estimates\n" " [1..4] [1 = max quality, 4 = max. speed] (default: 3)\n" "--min-gop-size|-g num\n" " Minimum size Group-of-Pictures (default depends on selected format)\n" "--max-gop-size|-G num\n" " Maximum size Group-of-Pictures (default depends on selected format)\n" " If min-gop is less than max-gop, mpeg2enc attempts to place GOP\n" " boundaries to coincide with scene changes\n" "--closed-gop|-c\n" " All Group-of-Pictures are closed. Useful for authoring multi-angle DVD\n" "--force-b-b-p|-P\n" " Preserve two B frames between I/P frames when placing GOP boundaries\n" "--quantisation-reduction|-Q num\n" " Max. quantisation reduction for highly active blocks\n" " [0.0 .. 4.0] (default: 0.0)\n" "--quant-reduction-max-var|-X num\n" " Luma variance below which quantisation boost (-Q) is used\n" " [0.0 .. 2500.0](default: 0.0)\n" "--video-buffer|-V num\n" " Target decoders video buffer size in KB (default 46)\n" "--video-norm|-n n|p|s\n" " Tag output to suit playback in specified video norm\n" " (n = NTSC, p = PAL, s = SECAM) (default: PAL)\n" "--sequence-length|-S num\n" " Place a sequence boundary in the video stream so they occur every\n" " num Mbytes once the video is multiplexed with audio etc.\n" " N.b. --non-video-bitrate is used to the bitrate of the other\n" " data that will be multiplexed with this video stream\n" "--3-2-pulldown|-p\n" " Generate header flags for 3-2 pull down of 24fps movie material\n" "--intra_dc_prec|-D [8..11]\n" " Set number of bits precision for DC (base colour) of blocks in MPEG-2\n" "--reduce-hf|-N num\n" " [0.0..2.0] Reduce hf resolution (increase quantization) by num (default: 0.0)\n" "--keep-hf|-H\n" " Maximise high-frequency resolution - useful for high quality sources\n" " and/or high bit-rates)\n" "--sequence-header-every-gop|-s\n" " Include a sequence header every GOP if the selected format doesn't\n" " do so by default.\n" "--no-dummy-svcd-SOF|-d\n" " Do not generate dummy SVCD scan-data for the ISO CD image\n" " generator \"vcdimager\" to fill in.\n" "--playback-field-order|-z b|t\n" " Force setting of playback field order to bottom or top first\n" "--multi-thread|-M num\n" " Activate multi-threading to optimise throughput on a system with num CPU's\n" " [0..32], 0=no multithreading, (default: 0)\n" "--correct-svcd-hds|-C\n" " Force SVCD horizontal_display_size to be 480 - standards say 540 or 720\n" " But many DVD/SVCD players screw up with these values.\n" "--no-constraints\n" " Deactivate constraints for maximum video resolution and sample rate.\n" " Could expose bugs in the software at very high resolutions!\n" "--no-altscan-mpeg2\n" " Deactivate the use of the alternate block pattern for MPEG-2. This is\n" " A work-around for a Bug in an obscure hardware decoder.\n" "--dualprime-mpeg2\n" " Turn ON use of dual-prime motion compensation. Default is OFF unless this option is used\n" "--custom-quant-matrices|-K kvcd|tmpgenc|default|hi-res|file=inputfile|help\n" " Request custom or userspecified (from a file) quantization matrices\n" "--unit-coeff-elim|-E num\n" " Skip picture blocks which appear to carry little information\n" " because they code to only unit coefficients. The number specifies\n" " how aggresively this should be done. A negative value means DC\n" " coefficients are included. Reasonable values -40 to 40\n" "--b-per-refframe| -R 0|1|2\n" " The number of B frames to generate between each I/P frame\n" "--cbr|-u\n" " For MPEG-2 force the use of (suboptimal) ConstantBitRate (CBR) encoding\n" "--chapters X[,Y[,...]]\n" " Specifies which frames should be chapter points (first frame is 0)\n" " Chapter points are I frames on closed GOP's.\n" "--help|-?\n" " Print this lot out!\n" ); exit(0); } void MPEG2EncCmdLineOptions::StartupBanner() { mjpeg_info("Encoding MPEG-%d video to %s",mpeg, outfilename); mjpeg_info("Horizontal size: %d pel",in_img_width); mjpeg_info("Vertical size: %d pel",in_img_height); mjpeg_info("Aspect ratio code: %d = %s", aspect_ratio, mpeg_aspect_code_definition(mpeg,aspect_ratio)); mjpeg_info("Frame rate code: %d = %s", frame_rate, mpeg_framerate_code_definition(frame_rate)); if(bitrate) mjpeg_info("Bitrate: %d KBit/s",bitrate/1000); else mjpeg_info( "Bitrate: VCD"); if(quant) mjpeg_info("Quality factor: %d (Quantisation = %.0f) (1=best, 31=worst)", quant, RateCtl::InvScaleQuant( mpeg == 1 ? 0 : 1, quant) ); mjpeg_info("Field order for input: %s", mpeg_interlace_code_definition(input_interlacing) ); if( seq_length_limit ) { mjpeg_info( "New Sequence every %d Mbytes", seq_length_limit ); mjpeg_info( "Assuming non-video stream of %d Kbps", nonvid_bitrate ); } else mjpeg_info( "Sequence unlimited length" ); mjpeg_info("Search radius: %d",searchrad); if (mpeg == 2) { mjpeg_info("DualPrime: %s", hack_dualprime == 1 ? "yes" : "no"); } } int MPEG2EncCmdLineOptions::SetFromCmdLine( int argc, char *argv[] ) { int n; int nerr = 0; enum LongOnlyOptions { CHAPTERS = 256 }; static const char short_options[]= "l:a:f:x:y:n:b:z:T:B:q:o:S:I:r:M:4:2:A:Q:X:D:g:G:v:V:F:N:updsHcCPK:E:R:t:L:Z:"; #ifdef HAVE_GETOPT_LONG static struct option long_options[]= { { "verbose", 1, 0, 'v' }, { "format", 1, 0, 'f' }, { "level", 1, 0, 'l' }, { "aspect", 1, 0, 'a' }, { "display-hsize", 1, 0, 'x' }, { "display-vsize", 1, 0, 'y' }, { "frame-rate", 1, 0, 'F' }, { "video-bitrate", 1, 0, 'b' }, { "target-video-bitrate", 1, 0, 't' }, { "sequence_length", 1, 0, 'L' }, { "mean-complexity", 1, 0, 'Z' }, { "nonvideo-bitrate", 1, 0, 'B' }, { "intra_dc_prec", 1, 0, 'D' }, { "quantisation", 1, 0, 'q' }, { "output", 1, 0, 'o' }, { "target-still-size", 1, 0, 'T' }, { "interlace-mode", 1, 0, 'I' }, { "motion-search-radius", 1, 0, 'r'}, { "reduction-4x4", 1, 0, '4'}, { "reduction-2x2", 1, 0, '2'}, { "min-gop-size", 1, 0, 'g'}, { "max-gop-size", 1, 0, 'G'}, { "closed-gop", 0, 0, 'c'}, { "force-b-b-p", 0, 0, 'P'}, { "ratecontroller", 1, 0, 'A' }, { "quantisation-reduction", 1, 0, 'Q' }, { "quant-reduction-max-var", 1, 0, 'X' }, { "video-buffer", 1, 0, 'V' }, { "video-norm", 1, 0, 'n' }, { "sequence-length", 1, 0, 'S' }, { "3-2-pulldown", 0, 0, 'p'}, { "keep-hf", 0, 0, 'H' }, { "reduce-hf", 1, 0, 'N' }, { "sequence-header-every-gop", 0, 0, 's'}, { "no-dummy-svcd-SOF", 0, 0, 'd' }, { "correct-svcd-hds", 0, 0, 'C'}, { "no-constraints", 0, &ignore_constraints, 1}, { "no-altscan-mpeg2", 0, &hack_altscan_bug, 1}, { "dualprime-mpeg2", 0, &hack_dualprime, 1}, { "playback-field-order", 1, 0, 'z'}, { "multi-thread", 1, 0, 'M' }, { "custom-quant-matrices", 1, 0, 'K'}, { "unit-coeff-elim", 1, 0, 'E'}, { "b-per-refframe", 1, 0, 'R' }, { "cbr", 0, 0, 'u'}, { "help", 0, 0, '?' }, { "chapters", 1, 0, CHAPTERS }, { 0, 0, 0, 0 } }; while( (n=getopt_long(argc,argv,short_options,long_options, NULL)) != -1 ) #else while( (n=getopt(argc,argv,short_options)) != -1) #endif { switch(n) { case 0 : /* Flag setting handled by getopt-long */ break; case 'l' : /* MPEG-2 level */ if( strcmp( optarg, "high" ) == 0 || strcmp( optarg, "h" ) == 0 ) level = HIGH_LEVEL; else if( strcmp( optarg, "main") == 0 || strcmp( optarg, "m" ) == 0 ) level = MAIN_LEVEL; else { mjpeg_error( "Level must be 'main', 'm', 'high' or 'h'"); ++nerr; } break; case 'b': bitrate = static_cast(atof(optarg)*1000); if( bitrate % 400 != 0 ) { mjpeg_warn( "MPEG bitrate must be a multiple of 400 - rounding up" ); bitrate = (bitrate / 400 + 1) * 400; } break; case 't': target_bitrate = static_cast(atof(optarg)*1000); break; case 'L' : stream_frames = atoi(optarg); break; case 'Z' : stream_Xhi = atof(optarg); if( stream_Xhi < 1000000.0 ) { mjpeg_error( "-Z|mean_complexity fails sanity check (< 1000000.0)"); ++nerr; } break; case 'T' : still_size = atoi(optarg)*1024; if( still_size < 20*1024 || still_size > 500*1024 ) { mjpeg_error( "-T requires arg 20..500" ); ++nerr; } break; case 'B': nonvid_bitrate = atoi(optarg); if( nonvid_bitrate < 0 ) { mjpeg_error("-B requires arg > 0"); ++nerr; } break; case 'D': mpeg2_dc_prec = atoi(optarg)-8; if( mpeg2_dc_prec < 0 || mpeg2_dc_prec > 3 ) { mjpeg_error( "-D requires arg [8..11]" ); ++nerr; } break; case 'C': hack_svcd_hds_bug = 0; break; case 'q': quant = atoi(optarg); if(quant<1 || quant>32) { mjpeg_error("-q option requires arg 1 .. 32"); ++nerr; } break; case 'x' : display_hsize = atoi(optarg); if( display_hsize < 32 || display_hsize >= 16384 ) { mjpeg_error( "-x option must be in range [32..16383]" ); ++nerr; } break; case 'y' : display_vsize = atoi(optarg); if( display_vsize < 32 || display_vsize >= 16384 ) { mjpeg_error( "-y option must be in range [32..16383]" ); ++nerr; } break; case 'a' : aspect_ratio = atoi(optarg); if( aspect_ratio == 0 ) DisplayAspectRatios(); /* Checking has to come later once MPEG 1/2 has been selected...*/ if( aspect_ratio < 0 ) { mjpeg_error( "-a option must be positive"); ++nerr; } break; case 'F' : frame_rate = atoi(optarg); if( frame_rate == 0 ) DisplayFrameRates(); if( !mpeg_valid_framerate_code(frame_rate) ) { mjpeg_error( "illegal -F value (use -F 0 to list options)" ); ++nerr; } break; case 'o': outfilename = optarg; break; case 'I': fieldenc = atoi(optarg); if( fieldenc < 0 || fieldenc > 2 ) { mjpeg_error("-I option requires 0,1 or 2"); ++nerr; } break; case 'r': searchrad = atoi(optarg); if(searchrad<0 || searchrad>32) { mjpeg_error("-r option requires arg 0 .. 32"); ++nerr; } break; case 'M': num_cpus = atoi(optarg); if(num_cpus<0 || num_cpus>32) { mjpeg_error("-M option requires arg 0..32"); ++nerr; } break; case '4': me44_red = atoi(optarg); if(me44_red<0 || me44_red>4) { mjpeg_error("-4 option requires arg 0..4"); ++nerr; } break; case '2': me22_red = atoi(optarg); if(me22_red<0 || me22_red>4) { mjpeg_error("-2 option requires arg 0..4"); ++nerr; } break; case 'v': verbose = atoi(optarg); if( verbose < 0 || verbose > 2 ) ++nerr; break; case 'V' : video_buffer_size = atoi(optarg); if(video_buffer_size<20 || video_buffer_size>4000) { mjpeg_error("-v option requires arg 20..4000"); ++nerr; } break; case 'S' : seq_length_limit = atoi(optarg); if(seq_length_limit<1 ) { mjpeg_error("-S option requires arg > 1"); ++nerr; } break; case 'p' : vid32_pulldown = 1; break; case 'z' : if( strlen(optarg) != 1 || (optarg[0] != 't' && optarg[0] != 'b' ) ) { mjpeg_error("-z option requires arg b or t" ); ++nerr; } else if( optarg[0] == 't' ) force_interlacing = Y4M_ILACE_TOP_FIRST; else if( optarg[0] == 'b' ) force_interlacing = Y4M_ILACE_BOTTOM_FIRST; break; case 'f' : format = atoi(optarg); if( format < MPEG_FORMAT_FIRST || format > MPEG_FORMAT_LAST ) { mjpeg_error("-f option requires arg [%d..%d]", MPEG_FORMAT_FIRST, MPEG_FORMAT_LAST); ++nerr; } break; case 'n' : switch( optarg[0] ) { case 'p' : case 'n' : case 's' : norm = optarg[0]; break; default : mjpeg_error("-n option requires arg n or p, or s."); ++nerr; } break; case 'g' : min_GOP_size = atoi(optarg); break; case 'G' : max_GOP_size = atoi(optarg); break; case 'c' : closed_GOPs = true; break; case 'P' : preserve_B = true; break; case 'N': hf_q_boost = atof(optarg); if (hf_q_boost <0.0 || hf_q_boost > 2.0) { mjpeg_error( "-N option requires arg 0.0 .. 2.0" ); ++nerr; hf_q_boost = 0.0; } if (hf_quant == 0 && hf_q_boost != 0.0) hf_quant = 1; break; case 'H': hf_quant = 2; break; case 'K': ParseCustomOption(optarg); break; case 'u': force_cbr = 1; break; case 'E': unit_coeff_elim = atoi(optarg); if (unit_coeff_elim < -40 || unit_coeff_elim > 40) { mjpeg_error( "-E option range arg -40 to 40" ); ++nerr; } break; case 'R' : Bgrp_size = atoi(optarg)+1; if( Bgrp_size<1 || Bgrp_size>3) { mjpeg_error( "-R option arg 0|1|2" ); ++nerr; } break; case 's' : seq_hdr_every_gop = 1; break; case 'd' : svcd_scan_data = 0; break; case 'A' : rate_control = atoi(optarg); if( rate_control < 0 || rate_control > 1 ) { mjpeg_error( "-A option requires arg [0,1]"); ++nerr; } break; case 'Q' : act_boost = atof(optarg); if( act_boost < 0.0 || act_boost > 4.0) { mjpeg_error( "-Q option requires arg 0.0 .. 4.0"); ++nerr; } break; case 'X' : boost_var_ceil = atof(optarg); if( boost_var_ceil <0 || boost_var_ceil > 50*50 ) { mjpeg_error( "-X option requires arg 0 .. 2500" ); ++nerr; } break; case 256: // --chapters=X for( char *x=strtok(optarg,","); x; x=strtok(0,",") ) chapter_points.push_back(atoi(x)); std::sort(chapter_points.begin(),chapter_points.end()); break; case ':' : mjpeg_error( "Missing parameter to option!" ); case '?': default: ++nerr; } } /* Select input stream */ if(optind!=argc) { if( optind == argc-1 ) { istrm_fd = open( argv[optind], O_RDONLY ); if( istrm_fd < 0 ) { mjpeg_error( "Unable to open: %s: ",argv[optind] ); perror(""); ++nerr; } } else ++nerr; } else istrm_fd = 0; /* stdin */ if(!outfilename) { mjpeg_error("Output file name (-o option) is required!"); ++nerr; } /* * Probably not necessary but err on the safe side. If someone wants to * waste space by using a Constant Bit Rate stream then disable the '-q' * parameter. Further checks for CBR are made in mpeg2encoptions.cc */ if (force_cbr != 0) quant = 0; return nerr; } class YUV4MPEGEncoder : public MPEG2Encoder { public: YUV4MPEGEncoder( MPEG2EncCmdLineOptions &options ); void Encode(); }; YUV4MPEGEncoder::YUV4MPEGEncoder( MPEG2EncCmdLineOptions &cmd_options ) : MPEG2Encoder( cmd_options ) { reader = new Y4MPipeReader( parms, cmd_options.istrm_fd ); MPEG2EncInVidParams strm; reader->StreamPictureParams(strm); cmd_options.SetFormatPresets( strm ); cmd_options.StartupBanner(); writer = new FILE_StrmWriter( parms, cmd_options.outfilename ); quantizer = new Quantizer( parms ); if( cmd_options.rate_control == 0 ) { mjpeg_info( "Using one-pass rate controller" ); pass1ratectl = new OnTheFlyPass1( parms ); pass2ratectl = new OnTheFlyPass2( parms ); } else { mjpeg_info( "Using statistical look-ahead/two-pass rate controller" ); #if 0 pass1ratectl = new VBufPass1RC( parms ); pass2ratectl = new XhiPass2RC( parms ); #else mjpeg_info( "Still needs updating to new interface!" ); abort(); #endif } seqencoder = new SeqEncoder( parms, *reader, *quantizer, *writer, *pass1ratectl, *pass2ratectl ); // This order is important! Don't change... parms.Init( options ); reader->Init(); quantizer->Init(); seqencoder->Init(); } void YUV4MPEGEncoder::Encode( ) { seqencoder->EncodeStream(); } int main( int argc, char *argv[] ) { MPEG2EncCmdLineOptions options; mjpeg_default_handler_verbosity(options.verbose); if( options.SetFromCmdLine( argc, argv ) != 0 ) options.Usage(); mjpeg_default_handler_verbosity(options.verbose); YUV4MPEGEncoder encoder( options ); encoder.Encode(); #ifdef OUTPUT_STAT if( statfile != NULL ) fclose(statfile); #endif #ifdef ALTIVEC_BENCHMARK print_benchmark_statistics(); #endif return 0; } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/quantize.cc0000644000175000017500000001461510450314721020064 0ustar glowwormglowworm/* quantize.c, quantization / inverse quantization */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ /* Modifications and enhancements (C) 2000/2001 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "config.h" #include "encoderparams.hh" #include "mpeg2syntaxcodes.h" #include "picture.hh" #include "macroblock.hh" #include "quantize.hh" #include /******************** * * Unit coefficient elimination. * Zero DCT blocks in with 'only a few widely scattered' unit DCT coefficients. * The basis for this heuristic is that such blocks have a high coding cost * relative to the modest amount of picture information they carry. * * Original implementation: Copyright (c) 2000,2001 Fabrice Bellard. * Same GPL V2 as above. * * I can't be bothered to look up the research papers on this topic so * I can't give the original references... * * RETURN: 1 if block zero-ed, 0 otherwise * *******************/ static int unit_coeff_elimination(DCTblock &block, const uint8_t *scan_pattern, const int start_coeff, const int threshold) { static const char run_shortness_weight[64]= {3,2,2,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}; int score=0; int run=0; int i; // A non-unit DC coefficent makes zero-ing a bad idea... always if( start_coeff > 0 && block[0] > 1 ) return 0; // // Compute a measure of the 'denseness' of the unit coefficients // give up on zero-ing if a non-unit coefficient found... // for(i=start_coeff; i<64; i++) { const int j = scan_pattern[i]; const int level = abs(block[j]); if(level==1) { score += run_shortness_weight[run]; run=0; } else if(level>1) { // Uh-oh non-unit coefficient... zeroing not sensible... return 0; } else { ++run; } } // // The weighted score of the zero runs lengths seperating the unit // coefficients is high (unit coefficients are densely packed // numerous) zero-ing not a good trade-off, abort. // if(score >= threshold) return 0; // // Zero the DCT block... N.b. all scan patterns have the DC coefficient // first. // for(i=start_coeff; i<64; i++) { block[i]=0; } return (block[0] == 0); } // // TODO for efficiency the qdctblocks should be an external buffer managed by the calling slice/picture // coder. // void MacroBlock::Quantize( Quantizer &quant ) { if (best_me->mb_type & MB_INTRA) { quant.QuantIntra( dctblocks[0], qdctblocks[0], picture->q_scale_type, picture->dc_prec, picture->encparams.dctsatlim, &mquant ); cbp = (1<q_scale_type, picture->encparams.dctsatlim, &mquant ); int block; if( picture->unit_coeff_threshold ) { for( block = 0; block < BLOCK_COUNT; ++block ) { int zero = unit_coeff_elimination( qdctblocks[block], picture->scan_pattern, picture->unit_coeff_first, picture->unit_coeff_threshold); cbp &= ~(zero<<(BLOCK_COUNT-1-block)); } } } } void MacroBlock::IQuantize( Quantizer &quant) { int j; if (best_me->mb_type & MB_INTRA) { for (j=0; jdc_prec, mquant); } else { for (j=0;j(this), &workspace, static_cast(encparams.mpeg1), encparams.intra_q, encparams.inter_q ); } Quantizer::~Quantizer() { shutdown_quantizer( workspace ); } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/conform.cc0000644000175000017500000002473610512032560017671 0ustar glowwormglowworm/* conform.c, conformance checks */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ /* Modifications and enhancements (C) 2003 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "config.h" #include #include "mjpeg_logging.h" #include "encoderparams.hh" /* check for (level independent) parameter limits */ void EncoderParams::RangeChecks() { int i; /* range and value checks */ if (horizontal_size<1 || horizontal_size>16383) mjpeg_error_exit1("horizontal_size must be between 1 and 16383"); if (mpeg1 && horizontal_size>4095) mjpeg_error_exit1("horizontal_size must be less than 4096 (MPEG-1)"); if ((horizontal_size&4095)==0) mjpeg_error_exit1("horizontal_size must not be a multiple of 4096"); if ( horizontal_size%2 != 0) mjpeg_error_exit1("horizontal_size must be a even (4:2:0 / 4:2:2)"); if (vertical_size<1 || vertical_size>16383) mjpeg_error_exit1("vertical_size must be between 1 and 16383"); if (mpeg1 && vertical_size>4095) mjpeg_error_exit1("vertical size must be less than 4096 (MPEG-1)"); if ((vertical_size&4095)==0) mjpeg_error_exit1("vertical_size must not be a multiple of 4096"); if (vertical_size%2 != 0) mjpeg_error_exit1("vertical_size must be a even (4:2:0)"); if(fieldpic) { if (vertical_size%2 != 0) mjpeg_error_exit1("vertical_size must be a even (field pictures)"); if ( vertical_size%4 != 0) mjpeg_error_exit1("vertical_size must be a multiple of 4 (4:2:0 field pictures)"); } if (mpeg1) { if (aspectratio<1 || aspectratio>14) mjpeg_error_exit1("pel_aspect_ratio must be between 1 and 14 (MPEG-1)"); } else { if (aspectratio<1 || aspectratio>4) mjpeg_error_exit1("aspect_ratio_information must be 1, 2, 3 or 4"); } if (frame_rate_code<1 || frame_rate_code>8) mjpeg_error_exit1("frame_rate code must be between 1 and 8"); if (bit_rate<=0.0) mjpeg_error_exit1("bit_rate must be positive"); if (bit_rate > ((1<<30)-1)*400.0) mjpeg_error_exit1("bit_rate must be less than 429 Gbit/s"); if (mpeg1 && bit_rate > ((1<<18)-1)*400.0) mjpeg_error_exit1("bit_rate must be less than 104 Mbit/s (MPEG-1)"); if (vbv_buffer_code<1 || vbv_buffer_code>0x3ffff) mjpeg_error_exit1("vbv_buffer_size must be in range 1..(2^18-1)"); if (mpeg1 && vbv_buffer_code>=1024) mjpeg_error_exit1("vbv_buffer_size must be less than 1024 (MPEG-1)"); if (video_format<0 || video_format>5) mjpeg_error_exit1("video_format must be in range 0...5"); if (color_primaries<1 || color_primaries>7 || color_primaries==3) mjpeg_error_exit1("color_primaries must be in range 1...2 or 4...7"); if (transfer_characteristics<1 || transfer_characteristics>7 || transfer_characteristics==3) mjpeg_error_exit1("transfer_characteristics must be in range 1...2 or 4...7"); if (matrix_coefficients<1 || matrix_coefficients>7 || matrix_coefficients==3) mjpeg_error_exit1("matrix_coefficients must be in range 1...2 or 4...7"); if (display_horizontal_size<0 || display_horizontal_size>16383) mjpeg_error_exit1("display_horizontal_size must be in range 0...16383"); if (display_vertical_size<0 || display_vertical_size>16383) mjpeg_error_exit1("display_vertical_size must be in range 0...16383"); if (dc_prec<0 || dc_prec>3) mjpeg_error_exit1("intra_dc_precision must be in range 0...3"); for (i=0; i9) mjpeg_error_exit1("f_code x must be between 1 and 9"); if (motion_data[i].forw_vert_f_code<1 || motion_data[i].forw_vert_f_code>9) mjpeg_error_exit1("f_code y must be between 1 and 9"); if (mpeg1 && motion_data[i].forw_hor_f_code>7) mjpeg_error_exit1("f_code x must be less than 8"); if (mpeg1 && motion_data[i].forw_vert_f_code>7) mjpeg_error_exit1("f_code y must be less than 8"); if (motion_data[i].sxf<=0) mjpeg_error_exit1("search window must be positive"); /* doesn't belong here */ if (motion_data[i].syf<=0) mjpeg_error_exit1("search window must be positive"); if (i!=0) { if (motion_data[i].back_hor_f_code<1 || motion_data[i].back_hor_f_code>9) mjpeg_error_exit1("f_code must be between 1 and 9"); if (motion_data[i].back_vert_f_code<1 || motion_data[i].back_vert_f_code>9) mjpeg_error_exit1("f_code must be between 1 and 9"); if (mpeg1 && motion_data[i].back_hor_f_code>7) mjpeg_error_exit1("f_code must be le less than 8"); if (mpeg1 && motion_data[i].back_vert_f_code>7) mjpeg_error_exit1("f_code must be le less than 8"); if (motion_data[i].sxb<=0) mjpeg_error_exit1("search window must be positive"); if (motion_data[i].syb<=0) mjpeg_error_exit1("search window must be positive"); } } } /* identifies valid profile / level combinations */ static char profile_level_defined[5][4] = { /* HL H-14 ML LL */ {1, 1, 1, 0}, /* HP */ {0, 1, 0, 0}, /* Spat */ {0, 0, 1, 1}, /* SNR */ {1, 1, 1, 1}, /* MP */ {0, 0, 1, 0} /* SP */ }; static struct level_limits { unsigned int hor_f_code; unsigned int vert_f_code; unsigned int hor_size; unsigned int vert_size; unsigned int sample_rate; unsigned int bit_rate; /* Mbit/s */ unsigned int vbv_buffer_size; /* 16384 bit steps */ } maxval_tab[4] = { {9, 5, 1920, 1152, 62668800, 80, 597}, /* HL */ {9, 5, 1440, 1152, 47001600, 60, 448}, /* H-14 */ {8, 5, 720, 576, 10368000, 15, 112}, /* ML */ {7, 4, 352, 288, 3041280, 4, 29} /* LL */ }; static const int SP = 5; static const int MP = 4; static const int SNR = 3; static const int SPAT= 2; static const int HP = 1; static const int LL = 10; static const int ML = 8; static const int H14= 6; static const int HL = 4; void EncoderParams::ProfileAndLevelChecks() { int i; struct level_limits *maxval; if (profile<0 || profile>15) mjpeg_error_exit1("profile must be between 0 and 15"); if (level<0 || level>15) mjpeg_error_exit1("level must be between 0 and 15"); if (profile>=8) { mjpeg_warn("profile uses a reserved value, conformance checks skipped"); return; } if (profileSIMPLE_PROFILE) mjpeg_error_exit1("undefined Profile"); if (profile < MAIN_PROFILE) mjpeg_error_exit1("This encoder currently generates only main or simple profile MPEG-2"); if (levelLOW_LEVEL || level&1) mjpeg_error_exit1("undefined Level"); maxval = &maxval_tab[(level-4) >> 1]; /* check profile@level combination */ if(!profile_level_defined[profile-1][(level-4) >> 1]) mjpeg_error_exit1("undefined profile@level combination"); /* profile (syntax) constraints */ if (profile==SIMPLE_PROFILE && M!=1) mjpeg_error_exit1("Simple Profile does not allow B pictures"); if (profile!=HP && dc_prec==3) mjpeg_error_exit1("11 bit DC precision only allowed in High Profile"); /* level (parameter value) constraints */ for (i=0; i maxval->hor_f_code) mjpeg_error_exit1("forward horizontal f_code greater than permitted in specified Level"); if (motion_data[i].forw_vert_f_code > maxval->vert_f_code) mjpeg_error_exit1("forward vertical f_code greater than permitted in specified Level"); if (i!=0) { if (motion_data[i].back_hor_f_code > maxval->hor_f_code) mjpeg_error_exit1("backward horizontal f_code greater than permitted in specified Level"); if (motion_data[i].back_vert_f_code > maxval->vert_f_code) mjpeg_error_exit1("backward vertical f_code greater than permitted in specified Level"); } } if (!ignore_constraints) { /* Table 8-8 */ if (frame_rate_code > 5 && level >= ML) mjpeg_error_exit1("Picture rate greater than permitted in specified Level"); /* Table 8-10 */ if (horizontal_size > maxval->hor_size) mjpeg_error_exit1("Horizontal size is greater than permitted in specified Level"); if (vertical_size > maxval->vert_size) mjpeg_error_exit1("Vertical size is greater than permitted in specified Level"); /* Table 8-11 */ if (horizontal_size*vertical_size*frame_rate > maxval->sample_rate) mjpeg_error_exit1("Sample rate is greater than permitted in specified Level"); /* Table 8-12 */ if (bit_rate> 1.0e6 * maxval->bit_rate) mjpeg_error_exit1("Bit rate is greater than permitted in specified Level"); } /* Table 8-13 */ if (vbv_buffer_code > maxval->vbv_buffer_size) mjpeg_error_exit1("vbv_buffer_size exceeds High Level limit"); } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/picture.cc0000644000175000017500000005315511456612024017705 0ustar glowwormglowworm/* Picture encoding object */ /* (C) Andrew Stevens 2003 * This file is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ /* * 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. * */ #include "config.h" #include #include #include "mjpeg_types.h" #include "mjpeg_logging.h" #include "mpeg2syntaxcodes.h" #include "cpu_accel.h" #include "motionsearch.h" #include "encoderparams.hh" #include "mpeg2coder.hh" #include "quantize.hh" #include "seqencoder.hh" #include "ratectl.hh" #include "tables.h" #include "imageplanes.hh" Picture::Picture( EncoderParams &_encparams, ElemStrmWriter &writer, Quantizer &_quantizer ) : encparams( _encparams ), quantizer( _quantizer ), coding( new MPEG2CodingBuf( _encparams, writer) ) { int i,j; /* Allocate buffers for picture transformation */ blocks = static_cast( bufalloc(encparams.mb_per_pict*BLOCK_COUNT*sizeof(DCTblock))); qblocks = static_cast( bufalloc(encparams.mb_per_pict*BLOCK_COUNT*sizeof(DCTblock))); DCTblock *block = blocks; DCTblock *qblock = qblocks; for (j=0; j 0) vbv_delay = FFFF_VBV_DELAY; else if( encparams.still_size > 0 ) vbv_delay = static_cast(90000.0/encparams.frame_rate/4); } Picture::~Picture() { delete rec_img; delete pred; delete coding; } /* * * Reconstruct the decoded image for references images and * for statistics * */ void Picture::Reconstruct() { #ifndef OUTPUT_STAT if( pict_type!=B_TYPE) { #endif IQuantize(); ITransform(); CalcSNR(); Stats(); #ifndef OUTPUT_STAT } #endif } /******************************************* * * Set picture encoding parameters that depend * on the frame being encoded. * ******************************************/ void Picture::SetFrameParams( const StreamState &ss, int field ) { new_seq = ss.new_seq; end_seq = ss.end_seq; gop_decode = ss.g_idx; bgrp_decode = ss.b_idx; decode = ss.DecodeNum(); present = ss.PresentationNum(); temp_ref = ss.TemporalReference(); last_picture = ss.EndOfStream(); nb = ss.nb; np = ss.np; closed_gop = ss.closed_gop; dc_prec = encparams.dc_prec; SetFieldParams( field ); } /************************************************************************ * * Set encoding parameters that depend on which field of a frame * is being encoded. * ************************************************************************/ void Picture::SetFieldParams(int field) { secondfield = (field == 1); if( bgrp_decode == 0 ) // Start of a B-group: I or P frame { if (gop_decode==0 ) /* first encoded frame in GOP is I */ { if( field == 0) { gop_start = true; ipflag = 0; pict_type = I_TYPE; if( encparams.fieldpic ) end_seq = false; } else // P field of I-frame { gop_start = false; ipflag = 1; pict_type = P_TYPE; new_seq = false; } } else { pict_type = P_TYPE; gop_start = false; closed_gop = false; new_seq = false; } } else { closed_gop = false; pict_type = B_TYPE; gop_start = false; new_seq = false; } finalfield = !encparams.fieldpic || field == 1; /* Handle picture structure... */ if( encparams.fieldpic ) { /* ... when field encoding */ pict_struct = ((encparams.topfirst) ^ (field == 1)) ? TOP_FIELD : BOTTOM_FIELD; topfirst = 0; repeatfirst = 0; } else if( encparams.pulldown_32 ) { /* ... when encoding 3:2 pulldown frame pictures */ pict_struct = FRAME_PICTURE; switch( present % 4 ) { case 0 : repeatfirst = 1; topfirst = encparams.topfirst; break; case 1 : repeatfirst = 0; topfirst = !encparams.topfirst; break; case 2 : repeatfirst = 1; topfirst = !encparams.topfirst; break; case 3 : repeatfirst = 0; topfirst = encparams.topfirst; break; } } else { /* .. when encoding ordinary frame pictures */ pict_struct = FRAME_PICTURE; repeatfirst = 0; topfirst = encparams.topfirst; } forw_hor_f_code = encparams.motion_data[bgrp_decode].forw_hor_f_code; forw_vert_f_code = encparams.motion_data[bgrp_decode].forw_vert_f_code; sxf = encparams.motion_data[bgrp_decode].sxf; syf = encparams.motion_data[bgrp_decode].syf; switch ( pict_type ) { case I_TYPE : forw_hor_f_code = 15; forw_vert_f_code = 15; back_hor_f_code = 15; back_vert_f_code = 15; break; case P_TYPE : back_hor_f_code = 15; back_vert_f_code = 15; break; case B_TYPE : back_hor_f_code = encparams.motion_data[bgrp_decode].back_hor_f_code; back_vert_f_code = encparams.motion_data[bgrp_decode].back_vert_f_code; sxb = encparams.motion_data[bgrp_decode].sxb; syb = encparams.motion_data[bgrp_decode].syb; break; default: abort(); } /* We currently don't support frame-only DCT/Motion Est. for non progressive frames */ prog_frame = encparams.frame_pred_dct_tab[pict_type-1]; frame_pred_dct = encparams.frame_pred_dct_tab[pict_type-1]; q_scale_type = encparams.qscale_tab[pict_type-1]; intravlc = encparams.intravlc_tab[pict_type-1]; altscan = encparams.altscan_tab[pict_type-1]; scan_pattern = (altscan ? alternate_scan : zig_zag_scan); /* If we're using B frames then we reserve unit coefficient dropping for them as B frames have no 'knock on' information loss */ if( pict_type == B_TYPE || encparams.M == 1 ) { unit_coeff_threshold = abs( encparams.unit_coeff_elim ); unit_coeff_first = encparams.unit_coeff_elim < 0 ? 0 : 1; } else { unit_coeff_threshold = 0; unit_coeff_first = 0; } } void Picture::IQuantize() { int k; for (k=0; k::iterator i; for( i = mbinfo.begin(); i < mbinfo.end(); ++i ) { var_sum += i->best_me->var; } return var_sum; } double Picture::MinVarBestMotionComp() { double min_var = 1.0e26; vector::iterator i; for( i = mbinfo.begin(); i < mbinfo.end(); ++i ) { min_var = fmin( min_var, static_cast(i->best_me->var) ); } return min_var; } double Picture::VarSumBestFwdMotionComp() { double var_sum = 0.0; vector::iterator i; for( i = mbinfo.begin(); i < mbinfo.end(); ++i ) { var_sum += i->best_fwd_me->var; } return var_sum; } double Picture::ActivityBestMotionComp() { double actj,sum; int blksum; sum = 0.0; vector::iterator i; for (i = mbinfo.begin(); i < mbinfo.end(); ++i ) { /* A.Stevens Jul 2000 Luminance variance *has* to be a rotten measure of how active a block in terms of bits needed to code a lossless DCT. E.g. a half-white half-black block has a maximal variance but pretty small DCT coefficients. So.... instead of luminance variance as used in the original we use the absolute sum of DCT coefficients as our block activity measure. */ if( i->best_me->mb_type & MB_INTRA ) { /* Compensate for the wholly disproprotionate weight of the DC coefficients. Shold produce more sensible results... yes... it *is* an mostly empirically derived fudge factor ;-) */ blksum = -80*COEFFSUM_SCALE; for( int l = 0; l < 6; ++l ) blksum += quantizer.WeightCoeffIntra( i->RawDCTblocks()[l] ) ; } else { blksum = 0; for( int l = 0; l < 6; ++l ) blksum += quantizer.WeightCoeffInter( i->RawDCTblocks()[l] ) ; } /* It takes some bits to code even an entirely zero block... It also makes a lot of calculations a lot better conditioned if it can be guaranteed that activity is always distinctly non-zero. */ actj = (double)blksum / (double)COEFFSUM_SCALE; if( actj < 12.0 ) actj = 12.0; i->act = actj; sum += actj; } return sum; } /* inverse transform prediction error and add prediction */ void Picture::ITransform() { vector::iterator mbi; for( mbi = mbinfo.begin(); mbi < mbinfo.end(); ++mbi) { mbi->ITransform(); } } void Picture::MotionSubSampledLum( ) { int linestride; EncoderParams &eparams = encparams; /* In an interlaced field the "next" line is 2 width's down rather than 1 width down . TODO: Shoudn't we be treating the frame as interlaced for frame based interlaced encoding too... or at least for the interlaced ME modes? */ if (!eparams.fieldpic) { linestride = eparams.phy_width; } else { linestride = 2*eparams.phy_width; } uint8_t *org_Y = org_img->Plane(0); psubsample_image( org_Y, linestride, org_Y+eparams.fsubsample_offset, org_Y+eparams.qsubsample_offset ); } // // TODO Coders internal state (.e.g prev_mb) should be taken out of Picture object state // bool Picture::SkippableMotionMode( MotionEst &cur_mb_mm, MotionEst &prev_mb_mm) { if (pict_type==P_TYPE && !(cur_mb_mm.mb_type&MB_FORWARD)) { /* P picture, no motion vectors -> skipable */ return true; } else if(pict_type==B_TYPE ) { /* B frame picture with same prediction type * (forward/backward/interp.) and same active vectors * as in previous macroblock -> skippable */ if ( pict_struct==FRAME_PICTURE && cur_mb_mm.motion_type==MC_FRAME && ((prev_mb_mm.mb_type ^ cur_mb_mm.mb_type) &(MB_FORWARD|MB_BACKWARD))==0 && (!(cur_mb_mm.mb_type&MB_FORWARD) || (PMV[0][0][0]==cur_mb_mm.MV[0][0][0] && PMV[0][0][1]==cur_mb_mm.MV[0][0][1])) && (!(cur_mb_mm.mb_type&MB_BACKWARD) || (PMV[0][1][0]==cur_mb_mm.MV[0][1][0] && PMV[0][1][1]==cur_mb_mm.MV[0][1][1]))) { return true; } /* B field picture macroblock with same prediction * type (forward/backward/interp.) and active * vectors as previous macroblock and same * vertical field selects as current field -> skippable */ if (pict_struct!=FRAME_PICTURE && cur_mb_mm.motion_type==MC_FIELD && ((prev_mb_mm.mb_type^cur_mb_mm.mb_type)&(MB_FORWARD|MB_BACKWARD))==0 && (!(cur_mb_mm.mb_type&MB_FORWARD) || (PMV[0][0][0]==cur_mb_mm.MV[0][0][0] && PMV[0][0][1]==cur_mb_mm.MV[0][0][1] && cur_mb_mm.field_sel[0][0]==(pict_struct==BOTTOM_FIELD))) && (!(cur_mb_mm.mb_type&MB_BACKWARD) || (PMV[0][1][0]==cur_mb_mm.MV[0][1][0] && PMV[0][1][1]==cur_mb_mm.MV[0][1][1] && cur_mb_mm.field_sel[0][1]==(pict_struct==BOTTOM_FIELD)))) { return true; } } return false; } /* ************************************************ * * QuantiseAndEncode - Quantise and Encode a picture. * * NOTE: It may seem perverse to quantise at the same time as * coding-> However, actually makes (limited) sense * - feedback from the *actual* bit-allocation may be used to adjust * quantisation "on the fly". This is good for fast 1-pass no-look-ahead coding-> * - The coded result is in any even only buffered not actually written * out. We can back off and try again with a different quantisation * easily. * - The alternative is calculating size and generating actual codes seperately. * The poorer cache coherence of this latter probably makes the performance gain * modest. * * *********************************************** */ void Picture::QuantiseAndCode(RateCtl &ratectl) { /* Now the actual quantisation and encoding->.. */ int i, j, k; int MBAinc; MacroBlock *cur_mb = 0; int mquant_pred = ratectl.InitialMacroBlockQuant(); k = 0; /* TODO: We're currently hard-wiring each macroblock row as a slice. For MPEG-2 we could do this better and reduce slice start code coverhead... */ for (j=0; jmquant = suggested_mquant; /* Quantize macroblock : N.b. cbp is also set as side-effect of call. */ cur_mb->Quantize( quantizer); /* * Macroblocks that don't end or begin a slice, don't have a coded DCT block and * whose motion compensation is predicted and doesn't need coding can be skipped. * */ if( i!=0 && i!=encparams.mb_width-1 && !cur_mb->cbp && SkippableMotionMode( *cur_mb->best_me, *prev_mb->best_me ) ) { ++MBAinc; if( pict_type == P_TYPE ) { /* reset predictors */ Reset_DC_DCT_Pred(); Reset_MV_Pred(); } } else { int mb_type = cur_mb->best_me->mb_type; /* Code mquant and update prediction if it changed in this macroblock */ if( cur_mb->cbp && cur_mb->mquant != mquant_pred ) { mquant_pred = cur_mb->mquant; mb_type |= MB_QUANT; } /* Inter-coded MB with some coded DCT blocks ===> PATTERN to code */ if ( cur_mb->cbp && !(mb_type & MB_INTRA) ) mb_type|= MB_PATTERN; /* For P frames there's no VLC for 'No MC, Not Coded': * we have to transmit (0,0) motion vectors */ if ( pict_type==P_TYPE && !cur_mb->cbp) mb_type|= MB_FORWARD; coding->PutAddrInc(MBAinc); /* macroblock_address_increment */ MBAinc = 1; coding->PutMBType(pict_type,mb_type); /* macroblock type */ if ( (mb_type & (MB_FORWARD|MB_BACKWARD)) && !frame_pred_dct) coding->PutBits(cur_mb->best_me->motion_type,2); if (pict_struct==FRAME_PICTURE && cur_mb->cbp && !frame_pred_dct) coding->PutBits(cur_mb->field_dct,1); if (mb_type & MB_QUANT) { coding->PutBits(q_scale_type ? map_non_linear_mquant[cur_mb->mquant] : cur_mb->mquant>>1,5); } if (mb_type & MB_FORWARD) { /* forward motion vectors, update predictors */ PutMVs( *cur_mb->best_me, false ); } if (mb_type & MB_BACKWARD) { /* backward motion vectors, update predictors */ PutMVs( *cur_mb->best_me, true ); } if (mb_type & MB_PATTERN) { coding->PutCPB((cur_mb->cbp >> (BLOCK_COUNT-6)) & 63); } /* Output VLC DCT Blocks for Macroblock */ PutDCTBlocks( *cur_mb, mb_type ); /* reset predictors */ if (!(mb_type & MB_INTRA)) Reset_DC_DCT_Pred(); if (mb_type & MB_INTRA || (pict_type==P_TYPE && !(mb_type & MB_FORWARD))) { Reset_MV_Pred(); } } ++k; } /* Slice MB loop */ } /* Slice loop */ } /* ********************************** * * PutHeaders - Put sequence of headers and user data elements that 'belong' * to this frame. We count sequence and GOP headers as belong to the first * following picture. * * ********************************/ void Picture::PutHeaders() { /* Sequence header if new sequence or we're generating for a format like (S)VCD that mandates sequence headers every GOP to do fast forward, rewind etc. */ if( new_seq || decode == 0 || (gop_start && encparams.seq_hdr_every_gop) ) { coding->PutSeqHdr(); } if( gop_start ) { coding->PutGopHdr( decode, closed_gop ); } /* picture header and picture coding extension */ PutHeader(); if( encparams.svcd_scan_data && pict_type == I_TYPE ) { coding->PutUserData( dummy_svcd_scan_data, sizeof(dummy_svcd_scan_data) ); } } /* ********************************** * * PutHeaders - Put padding and sequence ending markers that 'belong' to this picture. * * ********************************/ void Picture::PutTrailers( int padding_needed ) { coding->AlignBits(); if( padding_needed > 0 ) { mjpeg_debug( "Padding coded picture to size: %d extra bytes", padding_needed ); for( int i = 0; i < padding_needed; ++i ) { coding->PutBits(0, 8); } } /* Handle splitting of output stream into sequences of desired size */ if( end_seq ) { coding->PutSeqEnd(); } } int Picture::EncodedSize() const { return coding->ByteCount() * 8; } double Picture::IntraCodedBlocks() const { vector::const_iterator mbi = mbinfo.begin(); int intra = 0; for( mbi = mbinfo.begin(); mbi < mbinfo.end(); ++mbi) { if( mbi->best_me->mb_type&MB_INTRA ) ++intra; } return static_cast(intra) / mbinfo.size(); } /* ********************* * * Commit - Commit to the current encoding of the frame * flush the coder buffer content to the elementary stream output. * * *********************/ void Picture::CommitCoding() { coding->FlushBuffer(); } /* ********************* * * DiscardCoding - Discard the current encoding of the frame * set coder buffer empty discarding current contents. * * *********************/ void Picture::DiscardCoding() { coding->ResetBuffer(); } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/fdct.c0000644000175000017500000003207011445477341017011 0ustar glowwormglowworm/* fdct.c, forward discrete cosine transform, double precision */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ /* Modifications and enhancements (C) 2003 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include #include #include #include #include "mjpeg_types.h" static double aanscales[64]; static float aanscalesf[64]; #define FDCTTEST #define NC_COS6 0.382683432365089771728459984030399//cos(6*pi/16) #define NC_R_SQRT2 0.707106781186547524400844362104849// 1/sqrt(2) #define NC_COS0SQRT2 1.0 //cos(0*pi/16)*sqrt(2) #define NC_COS1SQRT2 1.38703984532214746182161919156644 //cos(1*pi/16)*sqrt(2) #define NC_COS2SQRT2 1.30656296487637652785664317342719 //cos(2*pi/16)*sqrt(2) #define NC_COS3SQRT2 1.17587560241935871697446710461126 //cos(3*pi/16)*sqrt(2) #define NC_COS4SQRT2 1.0 //cos(4*pi/16)*sqrt(2) #define NC_COS5SQRT2 0.785694958387102181277897367657217//cos(5*pi/16)*sqrt(2) #define NC_COS6SQRT2 0.541196100146196984399723205366389//cos(6*pi/16)*sqrt(2) #define NC_COS7SQRT2 0.275899379282943012335957563669373//cos(7*pi/16)*sqrt(2) void init_fdct_daan( void ); void fdct_daan(int16_t *block); void fdct_daanf(int16_t *block); void init_fdct (void); void fdct (int16_t *block); #ifdef FDCTTEST void init_fdct_daan( void ) { int i, j; static const double aansf[8] = { 1.0, // sqrt(2) factor left out here... NC_COS1SQRT2, NC_COS2SQRT2, NC_COS3SQRT2, NC_COS4SQRT2, // cos(4*pi/16) * sqrt(2) = 1.0 exactly NC_COS5SQRT2, NC_COS6SQRT2, NC_COS7SQRT2 }; for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) aanscalesf[ i*8 + j] = aanscales[i*8 + j] = 1.0 / (aansf[i] * aansf[j] * 8.0); } /* * Perform a floating point forward DCT on one block of samples. */ void fdct_daan(int16_t *block) { double tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; double tmp10, tmp11, tmp12, tmp13; double z1, z2, z3, z4, z5, z11, z13; double *dataptr; double data[64]; int16_t *blkptr; int i; /* Pass 1: process rows. */ blkptr = block; dataptr = data; for (i = 0; i < 8; i++) { tmp0 = blkptr[0] + blkptr[7]; tmp7 = blkptr[0] - blkptr[7]; tmp1 = blkptr[1] + blkptr[6]; tmp6 = blkptr[1] - blkptr[6]; tmp2 = blkptr[2] + blkptr[5]; tmp5 = blkptr[2] - blkptr[5]; tmp3 = blkptr[3] + blkptr[4]; tmp4 = blkptr[3] - blkptr[4]; /* Even part */ tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[0] = tmp10 + tmp11; /* phase 3 */ dataptr[4] = tmp10 - tmp11; z1 = (tmp12 + tmp13) * ((double) NC_R_SQRT2); /* c4 */ dataptr[2] = tmp13 + z1; /* phase 5 */ dataptr[6] = tmp13 - z1; /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; /* The rotator is modified from fig 4-8 to avoid extra negations. */ z5 = (tmp10 - tmp12) * ((double) NC_COS6); /* c6 */ z2 = ((double) NC_COS6SQRT2) * tmp10 + z5; /* c2-c6 */ z4 = ((double) NC_COS2SQRT2) * tmp12 + z5; /* c2+c6 */ z3 = tmp11 * ((double) NC_R_SQRT2); /* c4 */ z11 = tmp7 + z3; /* phase 5 */ z13 = tmp7 - z3; dataptr[5] = z13 + z2; /* phase 6 */ dataptr[3] = z13 - z2; dataptr[1] = z11 + z4; dataptr[7] = z11 - z4; dataptr += 8; /* advance pointer to next row */ blkptr += 8; } /* Pass 2: process columns. */ dataptr = data; for (i = 0; i < 8; i++) { tmp0 = dataptr[0] + dataptr[56]; tmp7 = dataptr[0] - dataptr[56]; tmp1 = dataptr[8] + dataptr[48]; tmp6 = dataptr[8] - dataptr[48]; tmp2 = dataptr[16] + dataptr[40]; tmp5 = dataptr[16] - dataptr[40]; tmp3 = dataptr[24] + dataptr[32]; tmp4 = dataptr[24] - dataptr[32]; /* Even part */ tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[0] = tmp10 + tmp11; /* phase 3 */ dataptr[32] = tmp10 - tmp11; z1 = (tmp12 + tmp13) * ((double) NC_R_SQRT2); /* c4 */ dataptr[16] = tmp13 + z1; /* phase 5 */ dataptr[48] = tmp13 - z1; /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; /* The rotator is modified from fig 4-8 to avoid extra negations. */ z5 = (tmp10 - tmp12) * ((double) NC_COS6); /* c6 */ z2 = ((double) NC_COS6SQRT2) * tmp10 + z5; /* c2-c6 */ z4 = ((double) NC_COS2SQRT2) * tmp12 + z5; /* c2+c6 */ z3 = tmp11 * ((double) NC_R_SQRT2); /* c4 */ z11 = tmp7 + z3; /* phase 5 */ z13 = tmp7 - z3; dataptr[40] = z13 + z2; /* phase 6 */ dataptr[24] = z13 - z2; dataptr[8] = z11 + z4; dataptr[56] = z11 - z4; dataptr++; /* advance pointer to next column */ } /* descale */ for (i = 0; i < 64; i++) //block[i] = (int16_t) floor(data[i] * aanscales[i] + 0.499999); block[i] = (int16_t) floor(data[i] * aanscales[i] + 0.5); } /* * Perform a floating point forward DCT on one block of samples. */ void fdct_daanf(int16_t *block) { float tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; float tmp10, tmp11, tmp12, tmp13; float z1, z2, z3, z4, z5, z11, z13; float *dataptr; float data[64]; int16_t *blkptr; int i; /* Pass 1: process rows. */ blkptr = block; dataptr = data; for (i = 0; i < 8; i++) { tmp0 = blkptr[0] + blkptr[7]; tmp7 = blkptr[0] - blkptr[7]; tmp1 = blkptr[1] + blkptr[6]; tmp6 = blkptr[1] - blkptr[6]; tmp2 = blkptr[2] + blkptr[5]; tmp5 = blkptr[2] - blkptr[5]; tmp3 = blkptr[3] + blkptr[4]; tmp4 = blkptr[3] - blkptr[4]; /* Even part */ tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[0] = tmp10 + tmp11; /* phase 3 */ dataptr[4] = tmp10 - tmp11; z1 = (tmp12 + tmp13) * ((double) NC_R_SQRT2); /* c4 */ dataptr[2] = tmp13 + z1; /* phase 5 */ dataptr[6] = tmp13 - z1; /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; /* The rotator is modified from fig 4-8 to avoid extra negations. */ z5 = (tmp10 - tmp12) * ((float) NC_COS6); /* c6 */ z2 = ((float) NC_COS6SQRT2) * tmp10 + z5; /* c2-c6 */ z4 = ((float) NC_COS2SQRT2) * tmp12 + z5; /* c2+c6 */ z3 = tmp11 * ((float) NC_R_SQRT2); /* c4 */ z11 = tmp7 + z3; /* phase 5 */ z13 = tmp7 - z3; dataptr[5] = z13 + z2; /* phase 6 */ dataptr[3] = z13 - z2; dataptr[1] = z11 + z4; dataptr[7] = z11 - z4; dataptr += 8; /* advance pointer to next row */ blkptr += 8; } /* Pass 2: process columns. */ dataptr = data; for (i = 0; i < 8; i++) { tmp0 = dataptr[0] + dataptr[56]; tmp7 = dataptr[0] - dataptr[56]; tmp1 = dataptr[8] + dataptr[48]; tmp6 = dataptr[8] - dataptr[48]; tmp2 = dataptr[16] + dataptr[40]; tmp5 = dataptr[16] - dataptr[40]; tmp3 = dataptr[24] + dataptr[32]; tmp4 = dataptr[24] - dataptr[32]; /* Even part */ tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[0] = tmp10 + tmp11; /* phase 3 */ dataptr[32] = tmp10 - tmp11; z1 = (tmp12 + tmp13) * ((float) NC_R_SQRT2); /* c4 */ dataptr[16] = tmp13 + z1; /* phase 5 */ dataptr[48] = tmp13 - z1; /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; /* The rotator is modified from fig 4-8 to avoid extra negations. */ z5 = (tmp10 - tmp12) * ((float) NC_COS6); /* c6 */ z2 = ((float) NC_COS6SQRT2) * tmp10 + z5; /* c2-c6 */ z4 = ((float) NC_COS2SQRT2) * tmp12 + z5; /* c2+c6 */ z3 = tmp11 * ((float) NC_R_SQRT2); /* c4 */ z11 = tmp7 + z3; /* phase 5 */ z13 = tmp7 - z3; dataptr[40] = z13 + z2; /* phase 6 */ dataptr[24] = z13 - z2; dataptr[8] = z11 + z4; dataptr[56] = z11 - z4; dataptr++; /* advance pointer to next column */ } /* descale */ for (i = 0; i < 64; i++) //block[i] = (int16_t) floor(data[i] * aanscales[i] + 0.499999); block[i] = (int16_t) floor(data[i] * aanscalesf[i] + 0.5f); } struct dct_test { int bounds,maxerr,iter; int me[64],mse[64]; }; extern void dct_test_and_print(struct dct_test *dt,int range,int16_t *origblock,int16_t *block); static struct dct_test fdct_res; /* reference fdct taken from "ieeetest.c" * Written by Tom Lane (tgl@cs.cmu.edu). * Released to public domain 11/22/93. */ /* The cosine lookup table */ /* coslu[a][b] = C(b)/2 * cos[(2a+1)b*pi/16] */ static double coslu[8][8]; void init_fdct_ref(void) { int a,b; double tmp; for(a=0;a<8;a++) for(b=0;b<8;b++) { tmp = cos((double)((a+a+1)*b) * (3.14159265358979323846 / 16.0)); if(b==0) tmp /= sqrt(2.0); coslu[a][b] = tmp * 0.5; } } void fdct_ref (int16_t *block) { int x,y,u,v; double tmp, tmp2; double res[8][8]; for (v=0; v<8; v++) { for (u=0; u<8; u++) { tmp = 0.0; for (y=0; y<8; y++) { tmp2 = 0.0; for (x=0; x<8; x++) { tmp2 += (double) block[y*8+x] * coslu[x][u]; } tmp += coslu[y][v] * tmp2; } res[v][u] = tmp; } } for (v=0; v<8; v++) { for (u=0; u<8; u++) { tmp = res[v][u]; if (tmp < 0.0) { x = - ((int) (0.5 - tmp)); } else { x = (int) (tmp + 0.5); } block[v*8+u] = (int16_t) x; } } } void fdct_test(int16_t *block) { int16_t origblock[64]; memcpy(origblock,block,64*sizeof(int16_t)); fdct_ref(origblock); // fdct_daan(origblock); // fdct_sse(origblock); // fdct(origblock); fdct(block); // fdct_daan(block); // fdct_mmx(block); // fdct_mmx(block); dct_test_and_print(&fdct_res,2048,origblock,block); } #endif #ifndef PI # ifdef M_PI # define PI M_PI # else # define PI 3.14159265358979323846 # endif #endif /* private data */ static int c[8][8]; /* transform coefficients */ /*! * Warning this DCT is actually too imprecise... it really * needs 11-bit precise coefficiencts (FDCT_COS_BITS=11) * to avoid nasty mismatch errors at low q. Unfortunately * it would then need > 32 bits. It is also suspect * that rounding is towards +infinity rather than away from 0. */ #define FDCT_COS_BITS 9 #define FDCT_COS_MUL (1<>FDCT_RES_SHIFT; } } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/mpeg2coder.cc0000644000175000017500000006264111456612024020261 0ustar glowwormglowworm/* mpeg2coder.hh - MPEG2 packed bit / VLC syntax coding engine */ /* (C) 2003 Andrew Stevens */ /* This Software and modifications to existing software are free * software; you can redistribute them and/or modify it under the terms * of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ #include #include #include #include #include "mpeg2syntaxcodes.h" #include "tables.h" #include "mpeg2coder.hh" #include "elemstrmwriter.hh" #include "mpeg2encoder.hh" #include "picture.hh" MPEG2CodingBuf::MPEG2CodingBuf( EncoderParams &_encparams, ElemStrmWriter &_writer ) : encparams( _encparams ), frag_buf( new ElemStrmFragBuf( _writer ) ) { } MPEG2CodingBuf::~MPEG2CodingBuf() { delete frag_buf; } /* convert frame number to time_code * * drop_frame not implemented */ int MPEG2CodingBuf::FrameToTimeCode(int gop_timecode0_frame) { int frame = gop_timecode0_frame; int fps, pict, sec, minute, hour, tc; /* Note: no drop_frame_flag support here, so we're simply rounding the frame rate as per 6.3.8 13818-2 */ fps = (int)(encparams.decode_frame_rate+0.5); pict = frame%fps; frame = (frame-pict)/fps; sec = frame%60; frame = (frame-sec)/60; minute = frame%60; frame = (frame-minute)/60; hour = frame%24; tc = (hour<<19) | (minute<<13) | (1<<12) | (sec<<6) | pict; return tc; } /**************** * * generate sequence header (6.2.2.1, 6.3.3) * ***************/ void MPEG2CodingBuf::PutSeqHdr() { int i; assert( frag_buf->Aligned() ); frag_buf->PutBits(SEQ_START_CODE,32); /* sequence_header_code */ frag_buf->PutBits(encparams.horizontal_size,12); /* horizontal_size_value */ frag_buf->PutBits(encparams.vertical_size,12); /* vertical_size_value */ frag_buf->PutBits(encparams.aspectratio,4); /* aspect_ratio_information */ frag_buf->PutBits(encparams.frame_rate_code,4); /* frame_rate_code */ /* MPEG-1 VBR is FFFF rate code. MPEG-2 VBR is a matter of mux-ing. The ceiling bit_rate is always sent */ if(encparams.mpeg1 && (encparams.quant_floor != 0 || encparams.still_size > 0) ) { frag_buf->PutBits(0xfffff,18); } else { frag_buf->PutBits((int)ceil(encparams.bit_rate/400.0),18); /* bit_rate_value */ } frag_buf->PutBits(1,1); /* marker_bit */ frag_buf->PutBits(encparams.vbv_buffer_code,10); /* vbv_buffer_size_value */ frag_buf->PutBits(encparams.constrparms,1); /* constrained_parameters_flag */ frag_buf->PutBits(encparams.load_iquant,1); /* load_intra_quantizer_matrix */ if (encparams.load_iquant) for (i=0; i<64; i++) /* matrices are always downloaded in zig-zag order */ frag_buf->PutBits(encparams.intra_q[zig_zag_scan[i]],8); /* intra_quantizer_matrix */ frag_buf->PutBits(encparams.load_niquant,1); /* load_non_intra_quantizer_matrix */ if (encparams.load_niquant) for (i=0; i<64; i++) frag_buf->PutBits(encparams.inter_q[zig_zag_scan[i]],8); /* non_intra_quantizer_matrix */ if (!encparams.mpeg1) { PutSeqExt(); PutSeqDispExt(); } frag_buf->AlignBits(); } /************************** * * generate sequence extension (6.2.2.3, 6.3.5) header (MPEG-2 only) * *************************/ void MPEG2CodingBuf::PutSeqExt() { assert( frag_buf->Aligned() ); frag_buf->PutBits(EXT_START_CODE,32); /* extension_start_code */ frag_buf->PutBits(SEQ_ID,4); /* extension_start_code_identifier */ frag_buf->PutBits((encparams.profile<<4)|encparams.level,8); /* profile_and_level_indication */ frag_buf->PutBits(encparams.prog_seq,1); /* progressive sequence */ frag_buf->PutBits(CHROMA420,2); /* chroma_format */ frag_buf->PutBits(encparams.horizontal_size>>12,2); /* horizontal_size_extension */ frag_buf->PutBits(encparams.vertical_size>>12,2); /* vertical_size_extension */ frag_buf->PutBits(((int)ceil(encparams.bit_rate/400.0))>>18,12); /* bit_rate_extension */ frag_buf->PutBits(1,1); /* marker_bit */ frag_buf->PutBits(encparams.vbv_buffer_code>>10,8); /* vbv_buffer_size_extension */ frag_buf->PutBits(0,1); /* low_delay -- currently not implemented */ frag_buf->PutBits(0,2); /* frame_rate_extension_n */ frag_buf->PutBits(0,5); /* frame_rate_extension_d */ frag_buf->AlignBits(); } /***************************** * * generate sequence display extension (6.2.2.4, 6.3.6) * ****************************/ void MPEG2CodingBuf::PutSeqDispExt() { assert( frag_buf->Aligned() ); frag_buf->PutBits(EXT_START_CODE,32); /* extension_start_code */ frag_buf->PutBits(DISP_ID,4); /* extension_start_code_identifier */ frag_buf->PutBits(encparams.video_format,3); /* video_format */ frag_buf->PutBits(1,1); /* colour_description */ frag_buf->PutBits(encparams.color_primaries,8); /* colour_primaries */ frag_buf->PutBits(encparams.transfer_characteristics,8); /* transfer_characteristics */ frag_buf->PutBits(encparams.matrix_coefficients,8); /* matrix_coefficients */ frag_buf->PutBits(encparams.display_horizontal_size,14); /* display_horizontal_size */ frag_buf->PutBits(1,1); /* marker_bit */ frag_buf->PutBits(encparams.display_vertical_size,14); /* display_vertical_size */ frag_buf->AlignBits(); } /******************************** * * Output user data (6.2.2.2.2, 6.3.4.1) * * TODO: string must not embed start codes 0x00 0x00 0x00 0xXX * *******************************/ void MPEG2CodingBuf::PutUserData(const uint8_t *userdata, int len) { int i; assert( frag_buf->Aligned() ); frag_buf->PutBits(USER_START_CODE,32); /* user_data_start_code */ for( i =0; i < len; ++i ) frag_buf->PutBits(userdata[i],8); } /* generate group of pictures header (6.2.2.6, 6.3.9) * * uses tc0 (timecode of first frame) and frame0 (number of first frame) */ void MPEG2CodingBuf::PutGopHdr(int frame,int closed_gop ) { int tc; frag_buf->AlignBits(); frag_buf->PutBits(GOP_START_CODE,32); /* group_start_code */ tc = FrameToTimeCode(frame); frag_buf->PutBits(tc,25); /* time_code */ frag_buf->PutBits(closed_gop,1); /* closed_gop */ frag_buf->PutBits(0,1); /* broken_link */ frag_buf->AlignBits(); } /* generate sequence_end_code (6.2.2) */ void MPEG2CodingBuf::PutSeqEnd(void) { frag_buf->AlignBits(); frag_buf->PutBits(SEQ_END_CODE,32); } /* generate variable length codes for an intra-coded block (6.2.6, 6.3.17) */ void MPEG2CodingBuf::PutIntraBlk(Picture *picture, int16_t *blk, int cc) { int n, dct_diff, run, signed_level; /* DC coefficient (7.2.1) */ dct_diff = blk[0] - picture->dc_dct_pred[cc]; /* difference to previous block */ picture->dc_dct_pred[cc] = blk[0]; if (cc==0) PutDClum(dct_diff); else PutDCchrom(dct_diff); /* AC coefficients (7.2.2) */ run = 0; const uint8_t *scan_tbl = (picture->altscan ? alternate_scan : zig_zag_scan); for (n=1; n<64; n++) { /* use appropriate entropy scanning pattern */ signed_level = blk[scan_tbl[n]]; if (signed_level!=0) { PutAC(run,signed_level,picture->intravlc); run = 0; } else run++; /* count zero coefficients */ } /* End of Block -- normative block punctuation */ if (picture->intravlc) frag_buf->PutBits(6,4); /* 0110 (Table B-15) */ else frag_buf->PutBits(2,2); /* 10 (Table B-14) */ } /* generate variable length codes for a non-intra-coded block (6.2.6, 6.3.17) */ void MPEG2CodingBuf::PutNonIntraBlk(Picture *picture, int16_t *blk) { int n, run, signed_level, first; run = 0; first = 1; for (n=0; n<64; n++) { /* use appropriate entropy scanning pattern */ signed_level = blk[(picture->altscan ? alternate_scan : zig_zag_scan)[n]]; if (signed_level!=0) { if (first) { /* first coefficient in non-intra block */ PutACfirst(run,signed_level); first = 0; } else PutAC(run,signed_level,0); run = 0; } else run++; /* count zero coefficients */ } /* End of Block -- normative block punctuation */ frag_buf->PutBits(2,2); } /* generate variable length code for a motion vector component (7.6.3.1) */ void MPEG2CodingBuf::PutMV(int dmv, int f_code) { int r_size, f, vmin, vmax, dv, temp, motion_code, motion_residual; r_size = f_code - 1; /* number of fixed length code ('residual') bits */ f = 1<vmax) dmv-= dv; else if (dmvvmax) { fprintf(stderr,"Too large MV %03d not in [%04d..:%03d]\n", dmv, vmin, vmax); exit(1); } /* split dmv into motion_code and motion_residual */ temp = ((dmv<0) ? -dmv : dmv) + f - 1; motion_code = temp>>r_size; if (dmv<0) motion_code = -motion_code; motion_residual = temp & (f-1); PutMotionCode(motion_code); /* variable length code */ if (r_size!=0 && motion_code!=0) frag_buf->PutBits(motion_residual,r_size); /* fixed length code */ } /* generate variable length code for DC coefficient (7.2.1) */ void MPEG2CodingBuf::PutDC(const sVLCtable *tab, int val) { int absval, size; absval = abs(val); assert(absval<=encparams.dctsatlim); /* compute dct_dc_size */ size = 0; while (absval) { absval >>= 1; size++; } /* generate VLC for dct_dc_size (Table B-12 or B-13) */ frag_buf->PutBits(tab[size].code,tab[size].len); /* append fixed length code (dc_dct_differential) */ if (size!=0) { if (val>=0) absval = val; else absval = val + (1<PutBits(absval,size); } } /* generate variable length code for DC coefficient (7.2.1) */ int MPEG2CodingBuf::DC_bits(const sVLCtable *tab, int val) { int absval, size; absval = abs(val); /* compute dct_dc_size */ size = 0; while (absval) { absval >>= 1; size++; } /* generate VLC for dct_dc_size (Table B-12 or B-13) */ return tab[size].len+size; } /* generate variable length code for first coefficient * of a non-intra block (7.2.2.2) */ void MPEG2CodingBuf::PutACfirst(int run, int val) { if (run==0 && (val==1 || val==-1)) /* these are treated differently */ frag_buf->PutBits(2|(val<0),2); /* generate '1s' (s=sign), (Table B-14, line 2) */ else PutAC(run,val,0); /* no difference for all others */ } /* generate variable length code for other DCT coefficients (7.2.2) */ void MPEG2CodingBuf::PutAC(int run, int signed_level, int vlcformat) { int level, len; const VLCtable *ptab = NULL; level = abs(signed_level); /* make sure run and level are valid */ if (run<0 || run>63 || level==0 || level>encparams.dctsatlim) { assert( signed_level == -(encparams.dctsatlim+1)); /* Negative range is actually 1 more */ } len = 0; if (run<2 && level<41) { /* vlcformat selects either of Table B-14 / B-15 */ if (vlcformat) ptab = &dct_code_tab1a[run][level-1]; else ptab = &dct_code_tab1[run][level-1]; len = ptab->len; } else if (run<32 && level<6) { /* vlcformat selects either of Table B-14 / B-15 */ if (vlcformat) ptab = &dct_code_tab2a[run-2][level-1]; else ptab = &dct_code_tab2[run-2][level-1]; len = ptab->len; } if (len!=0) /* a VLC code exists */ { frag_buf->PutBits(ptab->code,len); frag_buf->PutBits(signed_level<0,1); /* sign */ } else { /* no VLC for this (run, level) combination: use escape coding (7.2.2.3) */ frag_buf->PutBits(1l,6); /* Escape */ frag_buf->PutBits(run,6); /* 6 bit code for run */ if (encparams.mpeg1) { /* ISO/IEC 11172-2 uses a 8 or 16 bit code */ if (signed_level>127) frag_buf->PutBits(0,8); if (signed_level<-127) frag_buf->PutBits(128,8); frag_buf->PutBits(signed_level,8); } else { /* ISO/IEC 13818-2 uses a 12 bit code, Table B-16 */ frag_buf->PutBits(signed_level,12); } } } /* generate variable length code for other DCT coefficients (7.2.2) */ int MPEG2CodingBuf::AC_bits(int run, int signed_level, int vlcformat) { int level; const VLCtable *ptab; level = abs(signed_level); if (run<2 && level<41) { /* vlcformat selects either of Table B-14 / B-15 */ if (vlcformat) ptab = &dct_code_tab1a[run][level-1]; else ptab = &dct_code_tab1[run][level-1]; return ptab->len+1; } else if (run<32 && level<6) { /* vlcformat selects either of Table B-14 / B-15 */ if (vlcformat) ptab = &dct_code_tab2a[run-2][level-1]; else ptab = &dct_code_tab2[run-2][level-1]; return ptab->len+1; } else { return 12+12; } } /* generate variable length code for macroblock_address_increment (6.3.16) */ void MPEG2CodingBuf::PutAddrInc(int addrinc) { while (addrinc>33) { frag_buf->PutBits(0x08,11); /* macroblock_escape */ addrinc-= 33; } assert( addrinc >= 1 && addrinc <= 33 ); frag_buf->PutBits(addrinctab[addrinc-1].code,addrinctab[addrinc-1].len); } int MPEG2CodingBuf::AddrInc_bits(int addrinc) { int bits = 0; while (addrinc>33) { bits += 11; addrinc-= 33; } return bits + addrinctab[addrinc-1].len; } /* generate variable length code for macroblock_type (6.3.16.1) */ void MPEG2CodingBuf::PutMBType(int pict_type, int mb_type) { frag_buf->PutBits(mbtypetab[pict_type-1][mb_type].code, mbtypetab[pict_type-1][mb_type].len); } int MPEG2CodingBuf::MBType_bits( int pict_type, int mb_type) { return mbtypetab[pict_type-1][mb_type].len; } /* generate variable length code for motion_code (6.3.16.3) */ void MPEG2CodingBuf::PutMotionCode(int motion_code) { int abscode; abscode = abs( motion_code ); frag_buf->PutBits(motionvectab[abscode].code,motionvectab[abscode].len); if (motion_code!=0) frag_buf->PutBits(motion_code<0,1); /* sign, 0=positive, 1=negative */ } int MPEG2CodingBuf::MotionCode_bits( int motion_code ) { int abscode = (motion_code>=0) ? motion_code : -motion_code; return 1+motionvectab[abscode].len; } /* generate variable length code for dmvector[t] (6.3.16.3), Table B-11 */ void MPEG2CodingBuf::PutDMV(int dmv) { if (dmv==0) frag_buf->PutBits(0,1); else if (dmv>0) frag_buf->PutBits(2,2); else frag_buf->PutBits(3,2); } int MPEG2CodingBuf::DMV_bits(int dmv) { return dmv == 0 ? 1 : 2; } /* generate variable length code for coded_block_pattern (6.3.16.4) * * 4:2:2, 4:4:4 not implemented */ void MPEG2CodingBuf::PutCPB(int cbp) { frag_buf->PutBits(cbptable[cbp].code,cbptable[cbp].len); } int MPEG2CodingBuf::CBP_bits(int cbp) { return cbptable[cbp].len; } const MPEG2CodingBuf::VLCtable MPEG2CodingBuf::addrinctab[33]= { {0x01,1}, {0x03,3}, {0x02,3}, {0x03,4}, {0x02,4}, {0x03,5}, {0x02,5}, {0x07,7}, {0x06,7}, {0x0b,8}, {0x0a,8}, {0x09,8}, {0x08,8}, {0x07,8}, {0x06,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} }; /* Table B-2, B-3, B-4 variable length codes for macroblock_type * * indexed by [macroblock_type] */ const MPEG2CodingBuf::VLCtable MPEG2CodingBuf::mbtypetab[3][32]= { /* I */ { {0,0}, {1,1}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {1,2}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0} }, /* P */ { {0,0}, {3,5}, {1,2}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {1,3}, {0,0}, {1,1}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {1,6}, {1,5}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {2,5}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0} }, /* B */ { {0,0}, {3,5}, {0,0}, {0,0}, {2,3}, {0,0}, {3,3}, {0,0}, {2,4}, {0,0}, {3,4}, {0,0}, {2,2}, {0,0}, {3,2}, {0,0}, {0,0}, {1,6}, {0,0}, {0,0}, {0,0}, {0,0}, {2,6}, {0,0}, {0,0}, {0,0}, {3,6}, {0,0}, {0,0}, {0,0}, {2,5}, {0,0} } }; /* Table B-5 ... B-8 variable length codes for macroblock_type in * scalable sequences * * not implemented */ /* Table B-9, variable length codes for coded_block_pattern * * indexed by [coded_block_pattern] */ const MPEG2CodingBuf::VLCtable MPEG2CodingBuf::cbptable[64]= { {0x01,9}, {0x0b,5}, {0x09,5}, {0x0d,6}, {0x0d,4}, {0x17,7}, {0x13,7}, {0x1f,8}, {0x0c,4}, {0x16,7}, {0x12,7}, {0x1e,8}, {0x13,5}, {0x1b,8}, {0x17,8}, {0x13,8}, {0x0b,4}, {0x15,7}, {0x11,7}, {0x1d,8}, {0x11,5}, {0x19,8}, {0x15,8}, {0x11,8}, {0x0f,6}, {0x0f,8}, {0x0d,8}, {0x03,9}, {0x0f,5}, {0x0b,8}, {0x07,8}, {0x07,9}, {0x0a,4}, {0x14,7}, {0x10,7}, {0x1c,8}, {0x0e,6}, {0x0e,8}, {0x0c,8}, {0x02,9}, {0x10,5}, {0x18,8}, {0x14,8}, {0x10,8}, {0x0e,5}, {0x0a,8}, {0x06,8}, {0x06,9}, {0x12,5}, {0x1a,8}, {0x16,8}, {0x12,8}, {0x0d,5}, {0x09,8}, {0x05,8}, {0x05,9}, {0x0c,5}, {0x08,8}, {0x04,8}, {0x04,9}, {0x07,3}, {0x0a,5}, {0x08,5}, {0x0c,6} }; /* Table B-10, variable length codes for motion_code * * indexed by [abs(motion_code)] * sign of motion_code is treated elsewhere */ const MPEG2CodingBuf::VLCtable MPEG2CodingBuf::motionvectab[17]= { {0x01,1}, {0x01,2}, {0x01,3}, {0x01,4}, {0x03,6}, {0x05,7}, {0x04,7}, {0x03,7}, {0x0b,9}, {0x0a,9}, {0x09,9}, {0x11,10}, {0x10,10}, {0x0f,10}, {0x0e,10}, {0x0d,10}, {0x0c,10} }; /* Table B-11, variable length codes for dmvector * * treated elsewhere */ /* Table B-12, variable length codes for dct_dc_size_luminance * * indexed by [dct_dc_size_luminance] */ const MPEG2CodingBuf::sVLCtable MPEG2CodingBuf::DClumtab[12]= { {0x0004,3}, {0x0000,2}, {0x0001,2}, {0x0005,3}, {0x0006,3}, {0x000e,4}, {0x001e,5}, {0x003e,6}, {0x007e,7}, {0x00fe,8}, {0x01fe,9}, {0x01ff,9} }; /* Table B-13, variable length codes for dct_dc_size_chrominance * * indexed by [dct_dc_size_chrominance] */ const MPEG2CodingBuf::sVLCtable MPEG2CodingBuf::DCchromtab[12]= { {0x0000,2}, {0x0001,2}, {0x0002,2}, {0x0006,3}, {0x000e,4}, {0x001e,5}, {0x003e,6}, {0x007e,7}, {0x00fe,8}, {0x01fe,9}, {0x03fe,10},{0x03ff,10} }; /* Table B-14, DCT coefficients table zero * * indexed by [run][level-1] * split into two tables (dct_code_tab1, dct_code_tab2) to reduce size * 'first DCT coefficient' condition and 'End of Block' are treated elsewhere * codes do not include s (sign bit) */ const MPEG2CodingBuf::VLCtable MPEG2CodingBuf::dct_code_tab1[2][40]= { /* run = 0, level = 1...40 */ { {0x03, 2}, {0x04, 4}, {0x05, 5}, {0x06, 7}, {0x26, 8}, {0x21, 8}, {0x0a,10}, {0x1d,12}, {0x18,12}, {0x13,12}, {0x10,12}, {0x1a,13}, {0x19,13}, {0x18,13}, {0x17,13}, {0x1f,14}, {0x1e,14}, {0x1d,14}, {0x1c,14}, {0x1b,14}, {0x1a,14}, {0x19,14}, {0x18,14}, {0x17,14}, {0x16,14}, {0x15,14}, {0x14,14}, {0x13,14}, {0x12,14}, {0x11,14}, {0x10,14}, {0x18,15}, {0x17,15}, {0x16,15}, {0x15,15}, {0x14,15}, {0x13,15}, {0x12,15}, {0x11,15}, {0x10,15} }, /* run = 1, level = 1...18 */ { {0x03, 3}, {0x06, 6}, {0x25, 8}, {0x0c,10}, {0x1b,12}, {0x16,13}, {0x15,13}, {0x1f,15}, {0x1e,15}, {0x1d,15}, {0x1c,15}, {0x1b,15}, {0x1a,15}, {0x19,15}, {0x13,16}, {0x12,16}, {0x11,16}, {0x10,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0} } }; const MPEG2CodingBuf::VLCtable MPEG2CodingBuf::dct_code_tab2[30][5]= { /* run = 2...31, level = 1...5 */ {{0x05, 4}, {0x04, 7}, {0x0b,10}, {0x14,12}, {0x14,13}}, {{0x07, 5}, {0x24, 8}, {0x1c,12}, {0x13,13}, {0x00, 0}}, {{0x06, 5}, {0x0f,10}, {0x12,12}, {0x00, 0}, {0x00, 0}}, {{0x07, 6}, {0x09,10}, {0x12,13}, {0x00, 0}, {0x00, 0}}, {{0x05, 6}, {0x1e,12}, {0x14,16}, {0x00, 0}, {0x00, 0}}, {{0x04, 6}, {0x15,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x07, 7}, {0x11,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x05, 7}, {0x11,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x27, 8}, {0x10,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x23, 8}, {0x1a,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x22, 8}, {0x19,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x20, 8}, {0x18,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x0e,10}, {0x17,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x0d,10}, {0x16,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x08,10}, {0x15,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1f,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1a,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x19,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x17,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x16,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1f,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1e,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1d,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1c,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1b,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1f,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1e,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1d,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1c,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1b,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}} }; /* Table B-15, DCT coefficients table one * * indexed by [run][level-1] * split into two tables (dct_code_tab1a, dct_code_tab2a) to reduce size * 'End of Block' is treated elsewhere * codes do not include s (sign bit) */ const MPEG2CodingBuf::VLCtable MPEG2CodingBuf::dct_code_tab1a[2][40]= { /* run = 0, level = 1...40 */ { {0x02, 2}, {0x06, 3}, {0x07, 4}, {0x1c, 5}, {0x1d, 5}, {0x05, 6}, {0x04, 6}, {0x7b, 7}, {0x7c, 7}, {0x23, 8}, {0x22, 8}, {0xfa, 8}, {0xfb, 8}, {0xfe, 8}, {0xff, 8}, {0x1f,14}, {0x1e,14}, {0x1d,14}, {0x1c,14}, {0x1b,14}, {0x1a,14}, {0x19,14}, {0x18,14}, {0x17,14}, {0x16,14}, {0x15,14}, {0x14,14}, {0x13,14}, {0x12,14}, {0x11,14}, {0x10,14}, {0x18,15}, {0x17,15}, {0x16,15}, {0x15,15}, {0x14,15}, {0x13,15}, {0x12,15}, {0x11,15}, {0x10,15} }, /* run = 1, level = 1...18 */ { {0x02, 3}, {0x06, 5}, {0x79, 7}, {0x27, 8}, {0x20, 8}, {0x16,13}, {0x15,13}, {0x1f,15}, {0x1e,15}, {0x1d,15}, {0x1c,15}, {0x1b,15}, {0x1a,15}, {0x19,15}, {0x13,16}, {0x12,16}, {0x11,16}, {0x10,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0} } }; const MPEG2CodingBuf::VLCtable MPEG2CodingBuf::dct_code_tab2a[30][5]= { /* run = 2...31, level = 1...5 */ {{0x05, 5}, {0x07, 7}, {0xfc, 8}, {0x0c,10}, {0x14,13}}, {{0x07, 5}, {0x26, 8}, {0x1c,12}, {0x13,13}, {0x00, 0}}, {{0x06, 6}, {0xfd, 8}, {0x12,12}, {0x00, 0}, {0x00, 0}}, {{0x07, 6}, {0x04, 9}, {0x12,13}, {0x00, 0}, {0x00, 0}}, {{0x06, 7}, {0x1e,12}, {0x14,16}, {0x00, 0}, {0x00, 0}}, {{0x04, 7}, {0x15,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x05, 7}, {0x11,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x78, 7}, {0x11,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x7a, 7}, {0x10,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x21, 8}, {0x1a,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x25, 8}, {0x19,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x24, 8}, {0x18,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x05, 9}, {0x17,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x07, 9}, {0x16,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x0d,10}, {0x15,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1f,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1a,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x19,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x17,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x16,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1f,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1e,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1d,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1c,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1b,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1f,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1e,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1d,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1c,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1b,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}} }; /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/encodertypes.h0000644000175000017500000000645111011315325020564 0ustar glowwormglowworm#ifndef _ENCODERTYPES_H #define _ENCODERTYPES_H /* Representation classes for many various kinds of geometric entities floating around in an MPEG2 encoder... */ /* (C) 2000-2004 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include class Parity { public: inline static int Invert( int x ) { return 1-x;} static const int top = 0; static const int bot = 1; static const int dim = 2; typedef int type; }; class FieldOrder /* Same as topfirst bit of picture */ { public: static const int botfirst = 0; static const int topfirst = 1; static const int dim = 2; typedef int type; }; class Dim { public: static const int X = 0; static const int Y = 1; static const int dim = 2; typedef int type; }; class Coord; class MotionVector { public: inline MotionVector() {} inline MotionVector( int x, int y ) { val[Dim::X] = x; val[Dim::Y] = y; } inline static MotionVector Frame( const Coord &ref, const Coord &pred ); inline static MotionVector Field( const Coord &ref, const Coord &pred ); inline int &operator [] (int i) { return val[i]; } inline const int &operator [] (int i) const { return val[i]; } inline int CodingPenaltyForSAD() const { return (abs(val[Dim::X]) + abs(val[Dim::Y]))<<3; } inline void Zero() { val[Dim::Y] = val[Dim::X] = 0; } private: int val[Dim::dim]; }; class Coord { public: inline Coord() {} inline Coord( int _x, int _y ) : x(_x), y(_y) {} inline Coord( const Coord &pred, const MotionVector &mv ) : x( pred.x + mv[Dim::X] ), y( pred.y + mv[Dim::Y] ) { } inline void ToField() { y >>= 1; } inline void ToFrame() { y <<= 1; } inline void ToHalfPel() { x <<= 1; y <<= 1; } inline void ToFullPel() { x >>= 1; y >>= 1; } static inline Coord Field(const Coord &base) { return Coord( base.x, base.y >> 1 ); } static inline Coord Frame(const Coord &base) { return Coord( base.x, base.y << 1 ); } static inline Coord HalfPel(const Coord &base) { return Coord( base.x << 1, base.y << 1 ); } static inline Coord FullPel(const Coord &base) { return Coord( base.x >> 1, base.y >> 1 ); } int x; int y; }; inline MotionVector MotionVector::Frame( const Coord &ref, const Coord &pred ) { return MotionVector( ref.x - pred.x, ref.y - pred.y ); } inline MotionVector MotionVector::Field( const Coord &ref, const Coord &pred ) { return MotionVector(ref.x - pred.x,(ref.y<<1) - pred.y ); } struct Rectangle { Coord toplft; Coord botrgt; }; /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ #endif mjpegtools-2.1.0/mpeg2enc/simd.h0000644000175000017500000000434211114314210017005 0ustar glowwormglowworm/* * * simd.h * Copyright (C) 2000 Andrew Stevens * * * * This file is part of mpeg2enc, a free MPEG-2 video stream encoder * based on the original MSSG reference design * * mpeg2enc is free software; you can redistribute new parts * and/or modify under the terms of the GNU General Public License * as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * mpeg2enc is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * See the files for those sections (c) MSSG * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __SIMD_H__ #define __SIMD_H__ #include "stdlib.h" #include "mjpeg_types.h" /* * Interface to SIMD optimiseable low-level routines plus prototypes * neutral implementations * * N.b. linkage and implemenations of such functions is C not C++! * N.b. some of these reference implementations may be invoked by * architecture specific routines as fall-backs. Hence their inclusion here... * */ /* (C) 2003 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "cpu_accel.h" #include "quantize_ref.h" #include "transfrm_ref.h" #include "predict_ref.h" #endif /* __SIMD_H__ */ mjpegtools-2.1.0/mpeg2enc/mpeg2encoptions.hh0000644000175000017500000000326010444645161021354 0ustar glowwormglowworm#ifndef _MPEG2ENCOPTIONS_HH #define _MPEG2ENCOPTIONS_HH /* mpeg2encoptions.h - Encoding options for mpeg2enc++ MPEG-1/2 * encoder library */ /* (C) 2000/2001 Andrew Stevens */ /* This Software is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "mpeg2encparams.h" #include "mpegconsts.h" #include using std::deque; struct MPEG2EncInVidParams { int horizontal_size; int vertical_size; mpeg_aspect_code_t aspect_ratio_code; mpeg_framerate_code_t frame_rate_code; int interlacing_code; }; class MPEG2EncOptions : public MPEG2EncParams { public: MPEG2EncOptions(); bool SetFormatPresets( const MPEG2EncInVidParams &strm ); // True iff fail int InferStreamDataParams( const MPEG2EncInVidParams &strm ); int CheckBasicConstraints(); uint16_t custom_intra_quantizer_matrix[64]; uint16_t custom_nonintra_quantizer_matrix[64]; deque chapter_points; }; #endif /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/quantize_ref.c0000644000175000017500000003320411445477341020565 0ustar glowwormglowworm/* quantize.c, Low-level quantization / inverse quantization * routines */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ /* Modifications and enhancements (C) 2000-2003 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "config.h" #include #include #include #include "syntaxconsts.h" #include "fastintfns.h" #include "cpu_accel.h" #include "tables.h" #include "simd.h" #include "quantize_ref.h" #include "quantize_precomp.h" #ifdef HAVE_ALTIVEC void enable_altivec_quantization(struct QuantizerCalls *calls, int opt_mpeg1); #endif #if defined(HAVE_ASM_MMX) void init_x86_quantization( struct QuantizerCalls *calls, struct QuantizerWorkSpace *wsp, int mpeg1 ); #endif #define fabsshift ((8*sizeof(unsigned int))-1) #define signmask(x) (((int)x)>>fabsshift) static inline int intsamesign(int x, int y) { return (y+(signmask(x) & -(y<<1))); } #undef signmask #undef fabsshift /* * Return the code for a quantisation level */ int quant_code( int q_scale_type, int mquant ) { return q_scale_type ? map_non_linear_mquant[ mquant] : mquant>>1; } /* * * Computes the next quantisation up. Used to avoid saturation * in macroblock coefficients - common in MPEG-1 - which causes * nasty artifacts. * * NOTE: Does no range checking... */ int next_larger_quant( int q_scale_type, int quant ) { if( q_scale_type ) { if( map_non_linear_mquant[quant]+1 > 31 ) return quant; else return non_linear_mquant_table[map_non_linear_mquant[quant]+1]; } else { return ( quant+2 > 31 ) ? quant : quant+2; } } /* * Quantisation for intra blocks using Test Model 5 quantization * * this quantizer has a bias of 1/8 stepsize towards zero * (except for the DC coefficient) * PRECONDITION: src dst point to *disinct* memory buffers... of block_count *adjact* int16_t[64] arrays... * * RETURN: 1 If non-zero coefficients left after quantisaiont 0 otherwise */ void quant_intra( struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int q_scale_type, int dc_prec, int clipvalue, int *nonsat_mquant ) { int16_t *psrc,*pbuf; int i,comp; int x, y, d; int clipping; int mquant = *nonsat_mquant; uint16_t *quant_mat = wsp->intra_q_tbl[mquant] /* intra_q_mat * mquant */; /* * Complicate by handlin clipping by increasing quantisation. This * seems to avoid nasty artifacts in some situations... */ do { clipping = 0; pbuf = dst; psrc = src; for( comp = 0; comp>dc_prec; /* intra_dc_mult */ pbuf[0] = (x>=0) ? (x+(d>>1))/d : -((-x+(d>>1))/d); /* round(x/d) */ for (i=1; i<64 ; i++) { x = psrc[i]; #ifdef ORIGINAL_CODE d = wsp->intra_q_mat[i]; y = (16*(x >= 0 ? x : -x) + (d>>1))/d; /* round(32*x/quant_mat) */ d = (3*mquant+2)>>2; y = (y+d)/mquant; /* (y+0.75*mquant) / mquant) */ #else d = quant_mat[i]; y = ((abs(x)<<5) + d ) /(d<<1); #endif if ( y > clipvalue ) { clipping = 1; mquant = next_larger_quant(q_scale_type, mquant ); quant_mat = wsp->intra_q_tbl[mquant]; break; } pbuf[i] = intsamesign(x,y); } pbuf += 64; psrc += 64; } } while( clipping ); *nonsat_mquant = mquant; } /* * Quantisation matrix weighted Coefficient sum fixed-point * integer with low 16 bits fractional... * To be used for rate control as a measure of dct block * complexity... * */ static int quant_weight_coeff_intra( struct QuantizerWorkSpace *wsp, int16_t *blk ) { uint16_t * i_quant_mat = wsp->i_intra_q_mat; int i; int sum = 0; for( i = 0; i < 64; i+=2 ) { sum += abs((int)blk[i]) * (i_quant_mat[i]) + abs((int)blk[i+1]) * (i_quant_mat[i+1]); } return sum; /* In case you're wondering typical average coeff_sum's for a rather noisy video are around 20.0. */ } static int quant_weight_coeff_inter( struct QuantizerWorkSpace *wsp, int16_t *blk ) { uint16_t * i_quant_mat = wsp->i_inter_q_mat; int i; int sum = 0; for( i = 0; i < 64; i+=2 ) { sum += abs((int)blk[i]) * (i_quant_mat[i]) + abs((int)blk[i+1]) * (i_quant_mat[i+1]); } return sum; /* In case you're wondering typical average coeff_sum's for a rather noisy video are around 20.0. */ } /* * Quantisation for non-intra blocks using Test Model 5 quantization * * this quantizer has a bias of 1/8 stepsize towards zero * (except for the DC coefficient) * * A.Stevens 2000: The above comment is nonsense. Only the intra quantiser does * this. This one just truncates with a modest bias of 1/(4*quant_matrix_scale) * to 1. * * PRECONDITION: src dst point to *disinct* memory buffers... * of block_count *adjacent* int16_t[64] arrays... * * RETURN: A bit-mask of block_count bits indicating non-zero blocks (a 1). * */ int quant_non_intra( struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int q_scale_type, int clipvalue, int *nonsat_mquant) { int i; int x, y, dmquant; int nzflag; int coeff_count; int flags = 0; int saturated = 0; int mquant = *nonsat_mquant; uint16_t *quant_mat = wsp->inter_q_tbl[mquant]; /* inter_q */ coeff_count = 64*BLOCK_COUNT; flags = 0; nzflag = 0; for (i=0; i= 0 ? src[i] : -src[i])*/ ; dmquant = (int)quant_mat[(i&63)]; /* A.Stevens 2003: Given the math of non-intra frame quantisation / inverse quantisation I always thought the funny little foudning factor was bogus. The reconstruction formula for non-intra frames includes a factor that is exactly right for minimising error if quantisation is performed by a simple *truncating* divide! */ y = (x<<4) / dmquant; /* NOW: 16*x / d*mquant OLD: round(16*x/d)/mquant) = (32*x+d>>1)/(d*2)/mquant*/ ; if ( y > clipvalue ) { if( saturated ) { y = clipvalue; } else { int new_mquant = next_larger_quant( q_scale_type, mquant ); if( new_mquant != mquant ) { mquant = new_mquant; quant_mat = wsp->inter_q_tbl[mquant]; } else { saturated = 1; } i=0; nzflag =0; goto restart; } } dst[i] = intsamesign(src[i], y) /* (src[i] >= 0 ? y : -y) */; flags |= dst[i]; } nzflag = (nzflag<<1) | !!flags; *nonsat_mquant = mquant; return nzflag; } /* MPEG-1 inverse quantization */ void iquant_intra_m1(struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int dc_prec, int mquant) { int i, val; uint16_t *quant_mat = wsp->intra_q_mat; dst[0] = src[0] << (3-dc_prec); for (i=1; i<64; i++) { val = (int)(src[i]*quant_mat[i]*mquant)/16; /* mismatch control */ if ((val&1)==0 && val!=0) val+= (val>0) ? -1 : 1; /* saturation */ dst[i] = (val>2047) ? 2047 : ((val<-2048) ? -2048 : val); } } /* MPEG-2 inverse quantization */ void iquant_intra_m2(struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int dc_prec, int mquant) { int i, val, sum; sum = dst[0] = src[0] << (3-dc_prec); for (i=1; i<64; i++) { val = (int)(src[i]*wsp->intra_q_mat[i]*mquant)/16; sum+= dst[i] = (val>2047) ? 2047 : ((val<-2048) ? -2048 : val); } /* mismatch control */ if ((sum&1)==0) dst[63]^= 1; } void iquant_non_intra_m1(struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int mquant ) { uint16_t *quant_mat = wsp->inter_q_tbl[mquant]; int i, val; #ifndef ORIGINAL_CODE for (i=0; i<64; i++) { val = src[i]; if (val!=0) { val = (int)((2*val+(val>0 ? 1 : -1))*quant_mat[i])/32; /* mismatch control */ if ((val&1)==0 && val!=0) val+= (val>0) ? -1 : 1; } /* saturation */ dst[i] = (val>2047) ? 2047 : ((val<-2048) ? -2048 : val); } #else for (i=0; i<64; i++) { val = abs(src[i]); if (val!=0) { val = ((val+val+1)*quant_mat[i]) >> 5; /* mismatch control */ val -= (~(val&1))&(val!=0); val = fastmin(val, 2047); /* Saturation */ } dst[i] = intsamesign(src[i],val); } #endif } void iquant_non_intra_m2(struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int mquant ) { int i, val, sum; uint16_t *quant_mat; sum = 0; #ifdef ORIGINAL_CODE for (i=0; i<64; i++) { val = src[i]; if (val!=0) val = (int)((2*val+(val>0 ? 1 : -1))*inter_q[i]*mquant)/32; sum+= dst[i] = (val>2047) ? 2047 : ((val<-2048) ? -2048 : val); } #else quant_mat = wsp->inter_q_tbl[mquant]; for (i=0; i<64; i++) { val = src[i]; if( val != 0 ) { val = abs(val); val = (int)((val+val+1)*quant_mat[i])>>5; val = intmin( val, 2047); sum += val; } dst[i] = intsamesign(src[i],val); } #endif /* mismatch control */ if ((sum&1)==0) dst[63]^= 1; } /* Initialise quantization routines. Currently just setting up MMX routines if available. TODO: The initialisation of the quantisation tables should move here... */ void init_quantizer( struct QuantizerCalls *calls, struct QuantizerWorkSpace **workspace, int mpeg1, uint16_t intra_q[64], uint16_t inter_q[64]) { int q, i; struct QuantizerWorkSpace *wsp = bufalloc(sizeof(struct QuantizerWorkSpace)); if( ((int)wsp)%16 != 0 ) { printf( "BANG!"); abort(); } *workspace = wsp; for (i = 0; i < 64; i++) { wsp->intra_q_mat[i] = intra_q[i]; wsp->inter_q_mat[i] = inter_q[i]; wsp->i_intra_q_mat[i] = (int)(((double)IQUANT_SCALE) / ((double)intra_q[i])); wsp->i_inter_q_mat[i] = (int)(((double)IQUANT_SCALE) / ((double)inter_q[i])); } for (q = 1; q <= 112; ++q) { for (i = 0; i < 64; i++) { wsp->intra_q_tbl[q][i] = intra_q[i] * q; wsp->inter_q_tbl[q][i] = inter_q[i] * q; wsp->intra_q_tblf[q][i] = (float)wsp->intra_q_tbl[q][i]; wsp->inter_q_tblf[q][i] = (float)wsp->inter_q_tbl[q][i]; wsp->i_intra_q_tblf[q][i] = (float)(1.0 / (wsp->intra_q_tblf[q][i])); wsp->i_intra_q_tbl[q][i] = (IQUANT_SCALE/ wsp->intra_q_tbl[q][i]); wsp->r_intra_q_tbl[q][i] = (IQUANT_SCALE % wsp->intra_q_tbl[q][i]); wsp->i_inter_q_tblf[q][i] = (float)(1.0 / (wsp->inter_q_tblf[q][i])); wsp->i_inter_q_tbl[q][i] = (IQUANT_SCALE/wsp->inter_q_tbl[q][i]); wsp->r_inter_q_tbl[q][i] = (IQUANT_SCALE % wsp->inter_q_tbl[q][i]); } } if( mpeg1 ) { calls->piquant_intra = iquant_intra_m1; calls->piquant_non_intra = iquant_non_intra_m1; } else { calls->piquant_intra = iquant_intra_m2; calls->piquant_non_intra = iquant_non_intra_m2; } calls->pquant_non_intra = quant_non_intra; calls->pquant_weight_coeff_intra = quant_weight_coeff_intra; calls->pquant_weight_coeff_inter = quant_weight_coeff_inter; #if defined(HAVE_ASM_MMX) if( cpu_accel() ) { init_x86_quantization( calls, wsp, mpeg1 ); } #endif #ifdef HAVE_ALTIVEC if (cpu_accel()) enable_altivec_quantization(calls, mpeg1); #endif } void shutdown_quantizer(struct QuantizerWorkSpace *workspace) { free(workspace); } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/transfrm.cc0000644000175000017500000001111110340136334020044 0ustar glowwormglowworm/* transfrm.c, forward / inverse transformation */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* Modifications and enhancements (C) 2000/2001 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include #include "mpeg2syntaxcodes.h" #include "macroblock.hh" #include "picture.hh" #include "encoderparams.hh" #include "imageplanes.hh" #include "transfrm_ref.h" void MacroBlock::Transform() { uint8_t **cur = picture->org_img->Planes(); uint8_t **pred = picture->pred->Planes(); // assert( dctblocks == &blocks[k*block_count]); int i = TopleftX(); int j = TopleftY(); int blocktopleft = j*picture->encparams.phy_width+i; field_dct = ! picture->frame_pred_dct && picture->pict_struct == FRAME_PICTURE && (*pfield_dct_best)( &cur[0][blocktopleft], &pred[0][blocktopleft], picture->encparams.phy_width); int i1, j1, n, cc, offs, lx; for (n=0; npict_struct==FRAME_PICTURE) && field_dct) { /* field DCT */ lx = picture->encparams.phy_width<<1; offs = i + ((n&1)<<3) + picture->encparams.phy_width*(j+((n&2)>>1)); } else { /* frame DCT */ lx = picture->encparams.phy_width2; offs = i + ((n&1)<<3) + lx*(j+((n&2)<<2)); } if (picture->pict_struct==BOTTOM_FIELD) offs += picture->encparams.phy_width; } else { /* chrominance */ /* scale coordinates */ i1 = i>>1; j1 = j>>1; #ifdef NO_NON_420_SUPPORT if(picture->pict_struct==FRAME_PICTURE) && field_dct && (CHROMA420!=CHROMA420)) { /* field DCT */ lx = picture->encparams.phy_chrom_width<<1; offs = i1 + (n&8) + picture->encparams.phy_chrom_width*(j1+((n&2)>>1)); } else #endif { /* frame DCT */ lx = picture->encparams.phy_chrom_width2; offs = i1 + (n&8) + lx*(j1+((n&2)<<2)); } if (picture->pict_struct==BOTTOM_FIELD) offs += picture->encparams.phy_chrom_width; } psub_pred(pred[cc]+offs,cur[cc]+offs,lx, dctblocks[n]); pfdct(dctblocks[n]); } } /* subtract prediction and transform prediction error */ void transform( Picture *picture ) { vector::iterator mbi; for( mbi = picture->mbinfo.begin(); mbi < picture->mbinfo.end(); ++mbi) { mbi->Transform(); } } void MacroBlock::ITransform() { uint8_t **cur = picture->rec_img->Planes(); uint8_t **pred = picture->pred->Planes(); int i1, j1, n, cc, offs, lx; int i = TopleftX(); int j = TopleftY(); for (n=0; npict_struct==FRAME_PICTURE) && field_dct) { /* field DCT */ lx = picture->encparams.phy_width<<1; offs = i + ((n&1)<<3) + picture->encparams.phy_width*(j+((n&2)>>1)); } else { /* frame DCT */ lx = picture->encparams.phy_width2; offs = i + ((n&1)<<3) + lx*(j+((n&2)<<2)); } if (picture->pict_struct==BOTTOM_FIELD) offs += picture->encparams.phy_width; } else { /* chrominance */ /* scale coordinates */ i1 = i>>1; j1 = j>>1; #ifdef NO_NON_420_SUPPORT if ((picture->pict_struct==FRAME_PICTURE) && field_dct && (CHROMA420!=CHROMA420)) { /* field DCT */ lx = picture->encparams.phy_chrom_width<<1; offs = i1 + (n&8) + picture->encparams.phy_chrom_width*(j1+((n&2)>>1)); } else #endif { /* frame DCT */ lx = picture->encparams.phy_chrom_width2; offs = i1 + (n&8) + lx*(j1+((n&2)<<2)); } if (picture->pict_struct==BOTTOM_FIELD) offs += picture->encparams.phy_chrom_width; } pidct(qdctblocks[n]); padd_pred(pred[cc]+offs,cur[cc]+offs,lx,qdctblocks[n]); } } mjpegtools-2.1.0/mpeg2enc/predcomp_mmx.c0000644000175000017500000002177610164361371020566 0ustar glowwormglowworm/* * predcomp_00_mmx.s: * * Extended MMX prediction composition * routines handling the four different interpolation cases... * * Copyright (C) 2000 Andrew Stevens * * * This program is free software; you can reaxstribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include #include "mjpeg_types.h" #include "mmx.h" /* * void predcomp__mmx(char *src,char *dst,int lx, int w, int h, int addflag); * * ix - Interpolation in x iy - Interpolation in y * */ /* The no interpolation case... */ void predcomp_00_mmx(char *src,char *dst,int lx, int w, int h, int addflag) { /* * mm1 = one's mask for src * mm0 = zero mask for src... */ movd_g2r(0x00010001, mm1); punpckldq_r2r(mm1, mm1); pxor_r2r(mm0, mm0); do { movq_m2r(src[0], mm4); /* first 8 bytes of row */ if (addflag) { movq_r2r(mm4, mm5); punpcklbw_r2r(mm0, mm4); punpckhbw_r2r(mm0, mm5); movq_m2r(dst[0], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm0, mm2); punpckhbw_r2r(mm0, mm3); paddw_r2r(mm2, mm4); paddw_r2r(mm3, mm5); paddw_r2r(mm1, mm4); paddw_r2r(mm1, mm5); psrlw_i2r(1, mm4); psrlw_i2r(1, mm5); packuswb_r2r(mm5, mm4); } movq_r2m(mm4, dst[0]); if (w != 8) { movq_m2r(src[8], mm4); /* first 8 bytes of row */ if (addflag) { movq_r2r(mm4, mm5); punpcklbw_r2r(mm0, mm4); punpckhbw_r2r(mm0, mm5); movq_m2r(dst[8], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm0, mm2); punpckhbw_r2r(mm0, mm3); paddw_r2r(mm2, mm4); paddw_r2r(mm3, mm5); paddw_r2r(mm1, mm4); paddw_r2r(mm1, mm5); psrlw_i2r(1, mm4); psrlw_i2r(1, mm5); packuswb_r2r(mm5, mm4); } movq_r2m(mm4, dst[8]); } dst += lx; /* update pointer to next row */ src += lx; h--; } while (h > 0); emms(); } /* The x-axis interpolation case... */ void predcomp_10_mmx(char *src,char *dst,int lx, int w, int h, int addflag) { movd_g2r(0x00010001, mm1); punpckldq_r2r(mm1, mm1); pxor_r2r(mm0, mm0); do { movq_m2r(src[0], mm4); /* first 8 bytes of row */ movq_r2r(mm4, mm5); punpcklbw_r2r(mm0, mm4); punpckhbw_r2r(mm0, mm5); movq_m2r(src[1], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm0, mm2); punpckhbw_r2r(mm0, mm3); paddw_r2r(mm2, mm4); /* Average mm4/mm5 and mm2/mm3 */ paddw_r2r(mm3, mm5); paddw_r2r(mm1, mm4); paddw_r2r(mm1, mm5); psrlw_i2r(1, mm4); psrlw_i2r(1, mm5); if (addflag) { movq_m2r(dst[0], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm0, mm2); punpckhbw_r2r(mm0, mm3); paddw_r2r(mm2, mm4); /* Average mm4/mm5 and mm2/mm3 */ paddw_r2r(mm3, mm5); paddw_r2r(mm1, mm4); paddw_r2r(mm1, mm5); psrlw_i2r(1, mm4); psrlw_i2r(1, mm5); } packuswb_r2r(mm5, mm4); movq_r2m(mm4, dst[0]); if (w != 8) { movq_m2r(src[8], mm4); /* first 8 bytes of row */ movq_r2r(mm4, mm5); punpcklbw_r2r(mm0, mm4); punpckhbw_r2r(mm0, mm5); movq_m2r(src[9], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm0, mm2); punpckhbw_r2r(mm0, mm3); paddw_r2r(mm2, mm4); /* Average mm4/mm5 and mm2/mm3 */ paddw_r2r(mm3, mm5); paddw_r2r(mm1, mm4); paddw_r2r(mm1, mm5); psrlw_i2r(1, mm4); psrlw_i2r(1, mm5); if (addflag) { movq_m2r(dst[8], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm0, mm2); punpckhbw_r2r(mm0, mm3); paddw_r2r(mm2, mm4); /* Average mm4/mm5 and mm2/mm3 */ paddw_r2r(mm3, mm5); paddw_r2r(mm1, mm4); paddw_r2r(mm1, mm5); psrlw_i2r(1, mm4); psrlw_i2r(1, mm5); } packuswb_r2r(mm5, mm4); movq_r2m(mm4, dst[8]); } src += lx; dst += lx; h--; } while (h > 0); emms(); } /* The y-axis interpolation case... */ void predcomp_01_mmx(char *src,char *dst,int lx, int w, int h, int addflag) { movd_g2r(0x00010001, mm1); punpckldq_r2r(mm1, mm1); pxor_r2r(mm0, mm0); do { movq_m2r(src[0], mm4); /* first 8 bytes of row */ movq_r2r(mm4, mm5); src += lx; /* Next row */ punpcklbw_r2r(mm0, mm4); punpckhbw_r2r(mm0, mm5); movq_m2r(src[0], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm0, mm2); punpckhbw_r2r(mm0, mm3); paddw_r2r(mm2, mm4); /* Average mm4/mm5 and mm2/mm3 */ paddw_r2r(mm3, mm5); paddw_r2r(mm1, mm4); paddw_r2r(mm1, mm5); psrlw_i2r(1, mm4); psrlw_i2r(1, mm5); if (addflag) { movq_m2r(dst[0], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm0, mm2); punpckhbw_r2r(mm0, mm3); paddw_r2r(mm2, mm4); /* Average mm4/mm5 and mm2/mm3 */ paddw_r2r(mm3, mm5); paddw_r2r(mm1, mm4); paddw_r2r(mm1, mm5); psrlw_i2r(1, mm4); psrlw_i2r(1, mm5); } packuswb_r2r(mm5, mm4); movq_r2m(mm4, dst[0]); if (w != 8) { src -= lx; /* Back to first row... */ movq_m2r(src[8], mm4); /* first 8 bytes of row */ movq_r2r(mm4, mm5); src += lx; /* Next row */ punpcklbw_r2r(mm0, mm4); punpckhbw_r2r(mm0, mm5); movq_m2r(src[8], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm0, mm2); punpckhbw_r2r(mm0, mm3); paddw_r2r(mm2, mm4); /* Average mm4/mm5 and mm2/mm3 */ paddw_r2r(mm3, mm5); paddw_r2r(mm1, mm4); paddw_r2r(mm1, mm5); psrlw_i2r(1, mm4); psrlw_i2r(1, mm5); if (addflag) { movq_m2r(dst[8], mm2); movq_r2r(mm2, mm3); punpcklbw_r2r(mm0, mm2); punpckhbw_r2r(mm0, mm3); paddw_r2r(mm2, mm4); /* Average mm4/mm5 and mm2/mm3 */ paddw_r2r(mm3, mm5); paddw_r2r(mm1, mm4); paddw_r2r(mm1, mm5); psrlw_i2r(1, mm4); psrlw_i2r(1, mm5); } packuswb_r2r(mm5, mm4); movq_r2m(mm4, dst[8]); } dst += lx; h--; } while (h > 0); emms(); } /* The x-axis and y-axis interpolation case... */ void predcomp_11_mmx(char *src,char *dst,int lx, int w, int h, int addflag) { /* * mm0 = [0,0,0,0]W * mm1 = [1,1,1,1]W * mm2 = [2,2,2,2]W */ movd_g2r(0x00020002, mm2); punpckldq_r2r(mm2, mm2); movd_g2r(0x00010001, mm1); punpckldq_r2r(mm1, mm1); pxor_r2r(mm0, mm0); do { movq_m2r(src[0], mm4); /* mm4 and mm6 accumulate partial sums for interp. */ movq_r2r(mm4, mm6); punpcklbw_r2r(mm0, mm4); punpckhbw_r2r(mm0, mm6); movq_m2r(src[1], mm5); movq_r2r(mm5, mm7); punpcklbw_r2r(mm0, mm5); paddw_r2r(mm5, mm4); punpckhbw_r2r(mm0, mm7); paddw_r2r(mm7, mm6); src += lx; /* update pointer to next row */ movq_m2r(src[0], mm5); /* first 8 bytes 1st row: avg src in x */ movq_r2r(mm5, mm7); punpcklbw_r2r(mm0, mm5); /* Accumulate partial interpolation */ paddw_r2r(mm5, mm4); punpckhbw_r2r(mm0, mm7); paddw_r2r(mm7, mm6); movq_m2r(src[1], mm5); movq_r2r(mm5, mm7); punpcklbw_r2r(mm0, mm5); paddw_r2r(mm5, mm4); punpckhbw_r2r(mm0, mm7); paddw_r2r(mm7, mm6); /* Now round */ paddw_r2r(mm2, mm4); paddw_r2r(mm2, mm6); psrlw_i2r(2, mm4); psrlw_i2r(2, mm6); if (addflag) { movq_m2r(dst[0], mm5); movq_r2r(mm5, mm7); punpcklbw_r2r(mm0, mm5); punpckhbw_r2r(mm0, mm7); paddw_r2r(mm5, mm4); /* Average mm4/mm6 and mm5/mm7 */ paddw_r2r(mm7, mm6); paddw_r2r(mm1, mm4); paddw_r2r(mm1, mm6); psrlw_i2r(1, mm4); psrlw_i2r(1, mm6); } packuswb_r2r(mm6, mm4); movq_r2m(mm4, dst[0]); if (w != 8) { src -= lx; /* Back to first row... */ movq_m2r(src[8], mm4); /* mm4 and mm6 accumulate partial sums for interp. */ movq_r2r(mm4, mm6); punpcklbw_r2r(mm0, mm4); punpckhbw_r2r(mm0, mm6); movq_m2r(src[9], mm5); movq_r2r(mm5, mm7); punpcklbw_r2r(mm0, mm5); paddw_r2r(mm5, mm4); punpckhbw_r2r(mm0, mm7); paddw_r2r(mm7, mm6); src += lx; /* update pointer to next row */ movq_m2r(src[8], mm5); /* first 8 bytes 1st row: avg src in x */ movq_r2r(mm5, mm7); punpcklbw_r2r(mm0, mm5); /* Accumulate partial interpolation */ paddw_r2r(mm5, mm4); punpckhbw_r2r(mm0, mm7); paddw_r2r(mm7, mm6); movq_m2r(src[9], mm5); movq_r2r(mm5, mm7); punpcklbw_r2r(mm0, mm5); paddw_r2r(mm5, mm4); punpckhbw_r2r(mm0, mm7); paddw_r2r(mm7, mm6); /* Now round */ paddw_r2r(mm2, mm4); paddw_r2r(mm2, mm6); psrlw_i2r(2, mm4); psrlw_i2r(2, mm6); if (addflag) { movq_m2r(dst[8], mm5); movq_r2r(mm5, mm7); punpcklbw_r2r(mm0, mm5); punpckhbw_r2r(mm0, mm7); paddw_r2r(mm5, mm4); /* Average mm4/mm6 and mm5/mm7 */ paddw_r2r(mm7, mm6); paddw_r2r(mm1, mm4); paddw_r2r(mm1, mm6); psrlw_i2r(1, mm4); psrlw_i2r(1, mm6); } packuswb_r2r(mm6, mm4); movq_r2m(mm4, dst[8]); } dst += lx; h--; } while (h > 0); emms(); } mjpegtools-2.1.0/mpeg2enc/seqstats.cc0000644000175000017500000000371010443621126020067 0ustar glowwormglowworm /* (C) 2006 Andrew Stevens */ /* This is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "config.h" #include "seqstats.hh" BinaryDistNode::BinaryDistNode() : depth(0) {} BinaryDistNode::BinaryDist() { buckets = 32; dist.resize(buckets); for( i = 0; i< buckets; ++i ) dist[i] = 0.0; lower ; } void BinaryDistNode::InsertSample( double x ) { if( } bool BinaryDistNode::InsertSample( double x, int node_idx ) { BinaryDistNode &node = dist[node_idx]; // Leaf nodes act as 'buckets' if( node.max_child_depth == 0 ) { if( x < node.lower || x > node.upper) { // Split bucket... node.sigma += x; node.n += 1; double lower = fmin(x, node.lower); double upper = fmax(x, node.upper); int lower = node.n / 2.0; int upper = node.n - lower; double median = node.sigma * lower / node.n; double right NewLeafNode( x, 1, x, , node.lower, node_idx*2+1 ); NewLeafNode( node.sigma, node.n, node.lower, node.upper, node_idx*2+2 ); node.max_child_depth = 1; return true; } else if( ) { node.max_child_depth = 1; node.used_children node.sigma += x; node.n += 1; NewLeafNode( x, x, lower, node_idx*2+2); return true; } else } } mjpegtools-2.1.0/mpeg2enc/rate_complexity_model.hh0000644000175000017500000000440311442756174022636 0ustar glowwormglowworm#ifndef RATE_COMPLEXITY_MODEL_HH #define RATE_COMPLEXITY_MODEL_HH // // C++ Interface: rate_complexity_model // // Description: Bit-rate / complexity statistics model of input stream // This is used to figure out the quantisation floor needed // to hit the overall bit-rate (== size) target of the sequence. // // // Author: Andrew Stevens , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "config.h" #include /* (C) 2000-2004 Andrew Stevens */ /* This is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ class BucketSetSampling; class RateComplexityModel { public: RateComplexityModel(); ~RateComplexityModel(); void SetRateControlParams( double max_bitrate, double allocation_exp ); void AddComplexitySample( double xhi ); double FindControlBitrate( double target_bitrate, double init_control_bitrate, double tolerance = 0.01 ); unsigned int GetNumSamples() const { return m_num_samples; } double GetMeanComplexity() const { return m_mean_xhi; } double FrameBitRate( double xhi, double control_bitrate ); protected: // Methods double PredictedBitrate( double control_bitrate); protected: // Variables static const unsigned int SAMPLING_POINTS = 128; BucketSetSampling *m_model; double m_total_xhi; unsigned int m_num_samples; double m_mean_xhi; double m_target_bitrate; double m_allocation_exp; double m_max_bitrate; }; #endif /* RATE_COMPLEXITY_MODEL_HH */ mjpegtools-2.1.0/mpeg2enc/README0000644000175000017500000003046007605553322016603 0ustar glowwormglowwormmpeg2enc encodes MJPEG AVIs, Quicktime Files or Edit List Files to MPEG-1/2 video streams. DISCLAIMER: This software is from the MPEG Software Simulation Group. See notices in source code regarding Patents and miscellaneous IP issues. POST MPEG SSG Development Rainer Johanni changed the input routine so that "lavtools" Edit Lists, AVI's and Quicktime input is accepted, introduced command line params instead of a param file and made some simple optimizations. Rainer also did the initial mod to accept the new special yuv format. Andrew Stevens added more intelligent motion compensation and optimised some key calculations that run badly on modern highly pipelined machines. These were then further refined based on the results of some work by Juan Remero Arroyo (who would have guessed 4*4 blocks still produce useful results!). Chris Atenasio's contributed MMX2/SSE code for the motion compensation macroblock group difference calculation. Andrew Stevens added a lot more MMX1 code for motion compensation and adapted Chris' code for his intelligent motion compensation mods and ported the fdct/idct MMX code to nasm. Andrew Stevens added some simple pre-processing filters to improve output quality when using noisy (e.g. broadcast) source video. Andrew Stevens modified the bit-allocation routines to use a more accurate method of estimating bits needed for good quality results. Andrew Stevens fixed a number of overflow and calculation errors associated with large files. Andrew Stevens ported in and tidied up a number of MMX routines from the bbmpeg project for windows (see www.delphi.com/bbmpeg_ug) to accelerate a few "second line" but nonetheless significantly time-consuming functions. Andrew Stevens added a new much faster MMX / 3Dnow / ISSE based quantization routines. Andrew Stevens replaced the use of SAD with variance for selecting motion compensations. Slightly more expensive but produces *markedly* better results. Similarly added support for checking the quality of the chrominance match achieved. Andrew Stevens added limited SMP support and basic chrominance match checking in motion compensation. Andrew Stevens added support for variable-sized GOP's and sequence splitting at file-size boundaries. James Klikman ported all the SSE/MMX etc stuff to AltiVec In case you're wondering: the upshot of this disclaimer is that the functionality is exactly as per the original but the software now runs around 12 times as fast with sensible (search radius 15) motion compensation settings, and you can now get half-decent looking results when working with typical broadcast quality sources. FAST MOTION COMPENSATION: For MPEG to achieve good quality results it has to find a good match between each 16*16 "macro-block" of pixels in the current frame and a 16*16 region in a preceding or following frame. The better the match the less information it has to drop when compressing. Obviously, finding such a good match in *moving* pictures requires a lot of searching. To do this (reasonably) quickly we use a trick: we first search coarsely comparing sums of 4*4 pixel groups and then 2*2 pixel groups rather than individual pixels. Technically: we do an initial search using sub-sampled data and use this to choose the places to search for detailed single pixel and sub-pixel matches. This reduces the amount of search *dramatically*. Since a good exact matches (down to half-pixels) will also give a good 2*2 match we know the best match should be in amoungst the best 2*2 matches. Similarly for the 2*2 in the 4*4 matches. However, there may be some false positives. So we can't just work with the very best 4*4 and the best 2*2 near that. Instead we discard only those above some threshold. Experiments and a bit of simple statistics revealed that it was exceedingly rare to miss the best match doing this, and even when we did miss the match found was *almost* as good. You can adjust the threshold with the -4 and -2 flags. Between the settings -4 1 -2 1 (highest quality) -4 4 -2 4 (fastest) Quality is impacted by about 10% quantisation (thats around 0.2 of a bit of precision in texture coefficients). Speed is impacted by a factor of 2. One older Pentium-II and P-III Katmai machines the speed factor is more like 3. For most purposes the default settings will be fine. However on P-III Katmai etc -4 2 -2 1 gives a good near-optimum quality setting with reasonably speed. For MPEG-2 encoding it is better to have the search radius set higher than the default of 16. There's very little point going below a radius of 16 as the speed gains are pretty limited. Obviously, your mileage may vary so you may want to fiddle with the setting if you're getting rotten results. Contact andrew.stevens@planet-interkom.de if you think you have found a case where the fast compensation fails! In case you're wondering: the performance gain over brute force search is something like a factor of 5. NOISE FILTERING and BIT DROPPING MPEG compression assumes that the pictures in a video sequence are closely correlated (once you've applied motion compensatino to search for good matches). Unfortunately, if you have a noisy original video source this assumption isn't really true. The noise introduces lots of spurious differences betwen actually very similar pictures. The end result is ugly "artifacted" results where MPEG has dropped real information in favour of spurious noise. The solution is to try to filter the noise out of the source. For mildy noisy stuff mpeg2enc's -N option (which slightly suppresses high-frequency information during compression) works well. Try this for stuff like captures from a good quality broadcast source. However, if that isn't enough lav2yuv has a simple low-pass filtering options -n. -n 1 smooths gently and is mostly imperceptible, -n 2 is rather stronger and is noticeable if you compare source video. However, if you really have noisy sources then -n 1 or -n 2 is infinitely preferable to the swimming sea of artefacts MPEG otherwise generates. If you need -n 2 and aren't in a hurry then the more sophisticated filtering in the yuv2dfilter program does a better job! What's really needed is dynamic noise-reduction in the MPEG encoder... but that's a job for another release! SMARTER BIT ALLOCATION (A.Stevens Aug and Nov 2000) The original source code made heavy use of the variance of blocks as a measure of their information content. This is actually pretty poor as what really counts is how many bits it will take to encoded the quantised DCT of the block without excessive losses. The bit allocation strategy is also very naive, essentially the encoder (more or less) tries to keep the bits allocated to each block the same. This is bad news if you have a picture where a lot of the information content comes low down.... As a first step to better quality encoding the current source now uses the sum of absolute block coefficients as a measure of information content. Bits are then allocated on the basis of how much information is being covered so that bits are held back if high information material comes late in the frame. As a second step some attempt is made to guess the "right" level of quantisation for a frame in advance so that the (inevitably lagging) feedback control of bit-allocation only deals with minor fine-tuning. This prevents annoying "oscillation" of bit-allocation". These modifications appear to give noticeable better results, greatly reducing fringes around sharp contrasts (e.g. titles) whilst still ensuring no significant bit-rate overshoots. The encoder now also tries to predict the likely bit-demand for each frame so it can set quantisation roughly right so that there isn't a "ramping" of quality down a frame with the top (too) good and the bottom (excessively) poor. There is also the -Q option for boosting the bits allocated to very active blocks (ones where motion compensation wasn't possible). The advantage is nice sharp logos and suchlike. The drawback is that noisy material can become "swimmy". If you're getting swimminess try using -Q 1.0. VARIABLE BIT RATE ENCODING The encoder now supports a form of variable bit-rate encoding. You can specify a quality ceiling (for the technical: a quantisation floor). In this case the bitrate is interpeted as a "do not exceed ceiling". The encoder bumps quality up as high as it can without exceeding this rate and the specified quality ceiling. For this option to be usefully use the speed ceiling should be high enough that it is rarely if ever reached and a large video buffer size (say 250 or 400K specified). Sensible numbers for quality ceiling are between 4 and 8. Below 4 and quality gains are probably no longer visible. Above 8 and artefacting may occur. An interesting effect of setting a fixed quality rate is that encoding is actually marginally more efficient as the encoder encodes *changes* in quality setting from screen block to block.. If they don't change they don't use any bits! PERFORMANCE: MMX/MMXEXT/SSE/3D-NOW (A.Stevens Jul/Aug 2000) In addition to improved fast motion compensation the updated code also has x86 assembly language routines for key calculations: 4*4. 8*8 and 16*16 block absolute difference sums, interpolated and simple prediction variances, prediction addition and subtraction, foward and inverse discrete cosine transforms, and quantisation and inverse quantisation. Unfortunately, the original MMX (MMX1) instruction set on the Pentium MMX is somewhat deficient in a couple of key areas (it has obvious "gaps"). Subsequent CPU's all started to fill these gaps in. Thus there is core MMX plus MMX extensions from one or all of: K6, Athlon/Duron, P-III and now even P-IV. Where relevant routines come in several versions to make the most of what is available. As an extra-special bonus for AMD owners some of the quantisation calculations are done (much faster) with the 3D-Now! instructions. Similar stuff for P-III/P-IV SSE instructions is being written. There have also been some gross-me-out hacky optimisations made to the non-MMX code to make it run better on modern pipelined CPU's. However, if you're trying to compress long MPEG sequences on a pre-MMX x86 CPU you *will* need some serious patience ;-). I reckon compressing a 1 hour TV show is now tolerable with the new super-duper fast mpeg2enc and a 300Mhz+ CPU on the job. Personally, I split the work between 4 CPU's: Celeron 366, 2*PIII-450 and a K6-2 500. Anyway to give you some idea what to expect here are some peformance figures. They're for the normal default settings and -4 1 -2 1 which tries to squeeze the last few drops of quality out. Duron-700 : 19fps / 13fps PIII-450 (katmai) : 11 / 6fps PII-400 : 8fps / 4fps Celeron-366 : 7fps / 3fps It is interesting to note the how much less efficient the Intel CPU's are at the motion compensation searches controlled by the -4 and -2 flags. I can only assume an Athlon would absolutely *fly* at this workload. VARIABLE SIZE GOOP's The encoder can be told to dynamically vary the size of groups of pictures to try to avoid scene changes in the middle of groups of pictures. This can help produce better results in sudden cuts and action scenes (especially in conjunction with VBR coding). However, the effect on "normal" video is marginal and for MPEG-1 at least many hardware decoders react allergically to variable-size GOP's. STILL MORE PERFORMANCE? Buy a multi-processor Athlon or P-IV machine! The SMP support now gives a speed up of around 1.9 on dual CPU machines. It should give useful speed scaling on 3 and 4 CPU machines too. Apart from this it is hard to see how big improvements can be made without radical rebuilding of the code. The program now spends around 50% of its time in routines that are already aggressively implement in MMX (etc). Note: the Athlon CPU's are a *lot* faster at a couple of key MMX instructions than the original P-III Katmai's. BETTER QUALITY? - There is still a lot of room for improvements to bit-allocation. - It should also be possible to intelligently use switching of quantisation matrices to suppress mosaicing in very active scenes. I.e. to "blur" rather than "mosaic". - Some minor gains could be made by intelligently selecting f-code's - There are easy gains to be made (for people intending to use software decoders or suitable hardware) by gettting veriable-bit-rate encoding working once again. This is one of the next things on the list and should be pretty easy. mjpegtools-2.1.0/mpeg2enc/predict_x86.c0000644000175000017500000000634110164361371020222 0ustar glowwormglowworm/* predict_ref.h, Low-level Architecture neutral prediction * (motion compensated reconstruction) routines */ /* (C) 2003 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "config.h" #include "mjpeg_types.h" #include "mjpeg_logging.h" #include "simd.h" void predcomp_00_mmxe(uint8_t *src,uint8_t *dst,int lx, int w, int h, int addflag); void predcomp_10_mmxe(uint8_t *src,uint8_t *dst,int lx, int w, int h, int addflag); void predcomp_11_mmxe(uint8_t *src,uint8_t *dst,int lx, int w, int h, int addflag); void predcomp_01_mmxe(uint8_t *src,uint8_t *dst,int lx, int w, int h, int addflag); void pred_comp_mmxe( uint8_t *src, uint8_t *dst, int lx, int w, int h, int x, int y, int dx, int dy, int addflag) { int xint, xh, yint, yh; uint8_t *s, *d; /* half pel scaling */ xint = dx>>1; /* integer part */ xh = dx & 1; /* half pel flag */ yint = dy>>1; yh = dy & 1; /* origins */ s = src + lx*(y+yint) + (x+xint); /* motion vector */ d = dst + lx*y + x; if( xh ) { if( yh ) predcomp_11_mmxe(s,d,lx,w,h,addflag); else /* !yh */ predcomp_10_mmxe(s,d,lx,w,h,addflag); } else /* !xh */ { if( yh ) predcomp_01_mmxe(s,d,lx,w,h,addflag); else /* !yh */ predcomp_00_mmxe(s,d,lx,w,h,addflag); } } void predcomp_00_mmx(uint8_t *src,uint8_t *dst,int lx, int w, int h, int addflag); void predcomp_10_mmx(uint8_t *src,uint8_t *dst,int lx, int w, int h, int addflag); void predcomp_11_mmx(uint8_t *src,uint8_t *dst,int lx, int w, int h, int addflag); void predcomp_01_mmx(uint8_t *src,uint8_t *dst,int lx, int w, int h, int addflag); void pred_comp_mmx( uint8_t *src, uint8_t *dst, int lx, int w, int h, int x, int y, int dx, int dy, int addflag) { int xint, xh, yint, yh; uint8_t *s, *d; /* half pel scaling */ xint = dx>>1; /* integer part */ xh = dx & 1; /* half pel flag */ yint = dy>>1; yh = dy & 1; /* origins */ s = src + lx*(y+yint) + (x+xint); /* motion vector */ d = dst + lx*y + x; if( xh ) { if( yh ) predcomp_11_mmx(s,d,lx,w,h,(int)addflag); else /* !yh */ predcomp_10_mmx(s,d,lx,w,h,(int)addflag); } else /* !xh */ { if( yh ) predcomp_01_mmx(s,d,lx,w,h,(int)addflag); else /* !yh */ predcomp_00_mmx(s,d,lx,w,h,(int)addflag); } } void init_x86_predict( int32_t cpucap ) { if(cpucap & ACCEL_X86_MMXEXT ) /* AMD MMX or SSE... */ { mjpeg_info( "SETTING EXTENDED MMX for PREDICTION!"); ppred_comp = pred_comp_mmxe; } else if(cpucap & ACCEL_X86_MMX ) /* Original MMX... */ { mjpeg_info( "SETTING MMX for PREDICTION!"); ppred_comp = pred_comp_mmx; } } mjpegtools-2.1.0/mpeg2enc/motionest.cc0000644000175000017500000015567410617266361020273 0ustar glowwormglowworm/* motionest.cc, motion estimation */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ /* Modifications and enhancements (C) 2000-2004 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include #include #include #include #include #include #include #include "cpu_accel.h" #include "simd.h" #include "fastintfns.h" #include "motionsearch.h" #include "mjpeg_logging.h" #include "encoderparams.hh" #include "picture.hh" #include "imageplanes.hh" /* See ISO13818-2 7.6.3.5 */ int dualprime_m[FieldOrder::dim][Parity::dim /*ref*/][Parity::dim /*pred*/] = { { { 2, 1 }, { 3, 2 } }, // Botfield first { { 2, 3 }, { 1, 2 } } // Topfield first }; int dualprime_e[Parity::dim /*ref*/ ][Parity::dim /*pred*/ ] = { { 0, +1 }, { -1, 0 } }; /* Macro-block Motion estimation results record */ struct MotionCand { Coord pos; // Half-pel co-ormv[1]dinates of source block int sad; // Sum of absolute difference int var; uint8_t *blk ; // Source block data (in luminace data array) int hx, hy; // Half-pel offsets int fieldsel; // 0 = top 1 = bottom int fieldoff; // Offset from start of frame data to first line // of field. (top = 0, bottom = width ); }; struct SubSampledImg { uint8_t *mb; // One pel uint8_t *fmb; // Two-pel subsampled uint8_t *qmb; // Four-pel subsampled uint8_t *umb; // U compoenent one-pel uint8_t *vmb; // V component one-pel }; /* Main field and frame based motion estimation entry points. */ static void field_estimate (const Picture &picture, uint8_t *toporg, uint8_t *topref, uint8_t *botorg, uint8_t *botref, SubSampledImg *ssmb, int i, int j, int sx, int sy, MotionCand *bestfr, MotionCand *best8u, MotionCand *best8l, MotionCand *bestsp); static void mb_me_search ( const EncoderParams &eparams, uint8_t *org, uint8_t *ref, int fieldoff, SubSampledImg *ssblk, int lx, int i0, int j0, int sx, int sy, int h, int xmax, int ymax, MotionCand *motion ); inline int mv_coding_penalty( int mv_x, int mv_y ) { return (abs(mv_x) + abs(mv_y))<<3; } /* * Compute subsampled images for fast motion compensation search * N.b. Sub-sampling works correctly if we treat interlaced images * as two half-height images side-by-side. */ /* * Compute the variance of the residual of uni-directionally motion * compensated block. * */ static inline int unidir_pred_var( const MotionCand *motion, uint8_t *mb, int lx, int h) { return psumsq(motion->blk, mb, lx, motion->hx, motion->hy, h); } /* * Compute the variance of the residual of bi-directionally motion * compensated block. */ static inline int bidir_pred_var( const MotionCand *motion_f, const MotionCand *motion_b, uint8_t *mb, int lx, int h) { return pbsumsq( motion_f->blk, motion_b->blk, mb, lx, motion_f->hx, motion_f->hy, motion_b->hx, motion_b->hy, h); } /* unidir_var_sum * * Compute the combined variance of luminance and * chrominance information for a particular non-intra macro block * after unidirectional motion estimation... * * Note: results are scaled to give chrominance equal weight to * chrominance. The variance of the luminance portion is computed * at the time the motion estimation is computed. * * TODO: Perhaps we should compute the whole thing in mb_mc_search * not seperate it. However, that would involve a lot of fiddling * with field_* and until its thoroughly debugged and tested I think * I'll leave that alone. Furthermore, it is unclear if its really * worth * doing these computations for B *and* P frames. * * TODO: BUG: ONLY works for 420 video... * */ static int unidir_var_sum( MotionCand *lum_mc, ImagePlanes &ref, SubSampledImg *ssblk, int lx, int h ) { int uvlx = (lx>>1); int uvh = (h>>1); /* N.b. MC co-ordinates are computed in half-pel units! */ int cblkoffset = (lum_mc->fieldoff>>1) + (lum_mc->pos.x>>2) + (lum_mc->pos.y>>2)*uvlx; return lum_mc->var + (psumsq_sub22( ref.Plane(1) + cblkoffset, ssblk->umb, uvlx, uvh) + psumsq_sub22( ref.Plane(2) + cblkoffset, ssblk->vmb, uvlx, uvh)); } /* * bidir_var_sum * Compute the combined variance of luminance and chrominance information * for a particular non-intra macro block after bidirectional * motion estimation... * * Note: results are scaled to give chrominance equal weight to * chrominance. The variance of the luminance portion is computed * at the time the motion estimation is computed. * * Note: results scaled to give chrominance equal weight to chrominance. * * TODO: BUG: ONLY works for 420 video... * * NOTE: Currently unused but may be required if it turns out that taking * chrominance into account in B frames is needed. * */ static int bidir_var_sum( MotionCand *lum_mc_f, MotionCand *lum_mc_b, ImagePlanes &ref_f, ImagePlanes &ref_b, SubSampledImg *ssblk, int lx, int h ) { int uvlx = (lx>>1); int uvh = (h>>1); /* N.b. MC co-ordinates are computed in half-pel units! */ int cblkoffset_f = (lum_mc_f->fieldoff>>1) + (lum_mc_f->pos.x>>2) + (lum_mc_f->pos.y>>2)*uvlx; int cblkoffset_b = (lum_mc_b->fieldoff>>1) + (lum_mc_b->pos.x>>2) + (lum_mc_b->pos.y>>2)*uvlx; return ( pbsumsq( lum_mc_f->blk, lum_mc_b->blk, ssblk->mb, lx, lum_mc_f->hx, lum_mc_f->hy, lum_mc_b->hx, lum_mc_b->hy, h) + pbsumsq_sub22( ref_f.Plane(1) + cblkoffset_f, ref_b.Plane(1) + cblkoffset_b, ssblk->umb, uvlx, uvh ) + pbsumsq_sub22( ref_f.Plane(2) + cblkoffset_f, ref_b.Plane(2) + cblkoffset_b, ssblk->vmb, uvlx, uvh )); } /* * Sum of chrominance variance of a block. */ static inline int chrom_var_sum( SubSampledImg *ssblk, int h, int lx ) { uint32_t var1, var2, dummy_mean; assert( (h>>1) == 8 || (h>>1) == 16 ); pvariance(ssblk->umb,(h>>1),(lx>>1), &var1, &dummy_mean); pvariance(ssblk->vmb,(h>>1),(lx>>1), &var2, &dummy_mean); return (var1+var2)*2; } /* * Compute SAD for bi-directionally motion compensated blocks... */ static inline int bidir_pred_sad( const MotionCand *motion_f, const MotionCand *motion_b, uint8_t *mb, int lx, int h) { return pbsad(motion_f->blk, motion_b->blk, mb, lx, motion_f->hx, motion_f->hy, motion_b->hx, motion_b->hy, h); } #ifdef DEBUG_MC static void display_mb(MotionCand *lum_mc, uint8_t **ref, SubSampledImg *ssblk, int lx, int h ) { int x,y; int sum = 0; int uvlx = (lx>>1); int uvh = (h>>1); /* N.b. MC co-ordinates are computed in half-pel units! */ int lblkoffset = lum_mc->fieldoff + (lum_mc->pos.x>>1) + (lum_mc->pos.y>>1)*lx; /*int cblkoffset = (lum_mc->fieldoff>>1) + (lum_mc->pos.x>>2) + (lum_mc->pos.y>>2)*uvlx;*/ fprintf(stderr, "ref[0] = %08x (%d,%d) width=%d reconbase = %08x blk =%08x\n", (int)ref[0], (lum_mc->pos.x>>1), (lum_mc->pos.y>>1), lx, (int)(ref[0]+lblkoffset), (int)(lum_mc->blk) ); for( y = 0; y < 16; ++y ) { for( x = 0; x< 16; ++x ) { int diff = *(ref[0]+lblkoffset+x+y*lx)-*(ssblk->mb+x+y*lx); sum += diff*diff; fprintf( stderr,"%04d ", diff ); } fprintf(stderr,"\n"); } fprintf(stderr, "sumsq = %d [%d] (%d)\n", sum, lum_mc->var, unidir_pred_var(lum_mc, ssblk->mb, lx, h) ); } #endif void FieldMotionCands( const EncoderParams &eparams, uint8_t *org, uint8_t *ref, SubSampledImg *topssmb, SubSampledImg *botssmb, int i, int j, int sx, int sy, MotionCand *besttop, MotionCand *bestbot, MotionCand (&fieldmcs)[2][2] ) { /* predict top field from top field */ mb_me_search( eparams, org,ref,0,topssmb, eparams.phy_width<<1,i,j>>1,sx,sy>>1,8, eparams.enc_width,eparams.enc_height>>1, &fieldmcs[Parity::top][Parity::top]); /* predict top field from bottom field */ mb_me_search( eparams, org,ref,eparams.phy_width,topssmb, eparams.phy_width<<1,i,j>>1,sx,sy>>1,8, eparams.enc_width,eparams.enc_height>>1, &fieldmcs[Parity::bot][Parity::top]); /* set correct field selectors... */ // TODO fieldset and fieldoff are redundant. Use only fieldoff // and derive fieldset as fieldoff != 0 fieldmcs[Parity::top][Parity::top].fieldsel = 0; fieldmcs[Parity::bot][Parity::top].fieldsel = 1; fieldmcs[Parity::top][Parity::top].fieldoff = 0; fieldmcs[Parity::bot][Parity::top].fieldoff = eparams.phy_width; /* select prediction for top field */ if (fieldmcs[Parity::top][Parity::top].sad<=fieldmcs[Parity::bot][Parity::top].sad) { *besttop = fieldmcs[Parity::top][Parity::top]; } else { *besttop = fieldmcs[Parity::bot][Parity::top]; } /* predict bottom field from top field */ mb_me_search( eparams, org,ref,0,botssmb, eparams.phy_width<<1,i,j>>1,sx,sy>>1,8, eparams.enc_width,eparams.enc_height>>1, &fieldmcs[Parity::top][Parity::bot]); /* predict bottom field from bottom field */ mb_me_search( eparams, org,ref,eparams.phy_width,botssmb, eparams.phy_width<<1,i,j>>1,sx,sy>>1,8, eparams.enc_width,eparams.enc_height>>1, &fieldmcs[Parity::bot][Parity::bot]); /* set correct field selectors... */ fieldmcs[Parity::top][Parity::bot].fieldsel = 0; fieldmcs[Parity::bot][Parity::bot].fieldsel = 1; fieldmcs[Parity::top][Parity::bot].fieldoff = 0; fieldmcs[Parity::bot][Parity::bot].fieldoff = eparams.phy_width; /* select prediction for bottom field */ if (fieldmcs[Parity::bot][Parity::bot].sad<=fieldmcs[Parity::top][Parity::bot].sad) { *bestbot = fieldmcs[Parity::bot][Parity::bot]; } else { *bestbot = fieldmcs[Parity::top][Parity::bot]; } } typedef int (*DualPrimeMeasure)( uint8_t *sameref, uint8_t *crossref, uint8_t *pred_mb, int field_stride, int same_fx, int same_fy, int cross_fx, int cross_fy, int h ); bool DualPrimeMetric( const Picture &picture, DualPrimeMeasure meas, const Coord &same, const Coord (&crossblks)[Parity::dim], // Cross-field ref const MotionVector &dmv, uint8_t *ref, uint8_t *pred_mb, int stride, int &measure ) { Coord cross; int part_meas = 0; // Base MV is out-of-range if( ! picture.InRangeFieldMVRef( same ) ) return false; for( int ppred = Parity::top; ppred <= Parity::bot; ++ppred ) { int same_fieldoff = (ppred == Parity::top ? 0 : stride); Coord cross(crossblks[Parity::Invert(ppred)],dmv); int cross_fieldoff = stride - same_fieldoff; if( ! picture.InRangeFieldMVRef( cross ) ) return false; uint8_t *sameref = ref + same_fieldoff + (same.x>>1) + (stride<<1)*(same.y>>1); uint8_t *crossref = ref + cross_fieldoff + (cross.x>>1) + (stride<<1)*(cross.y>>1); /* compute prediction error */ part_meas += meas( sameref, crossref, pred_mb, stride<<1, same.x&1, same.y&1, cross.x&1, cross.y&1, 8 ); } measure = part_meas; return true; // All vectors legal... } bool MacroBlock::FrameDualPrimeCand (uint8_t *ref, const SubSampledImg &ssmb, const MotionCand (&best_fieldmcs)[Parity::dim][Parity::dim], MotionCand &best_mc, MotionVector &min_dpmv) { int local_dist; int stride = picture->encparams.phy_width; bool dpmvfound = false; // Tricky here we need half-pel field co-ordinates so hpel won't do! const Coord mb( Coord::HalfPel(Coord::Field(pel)) ); /* Calculate Dual Prime distortions for 9 delta candidates * for each of the four minimum field vectors * Note: only for P pictures! */ /* initialize minimum dual prime distortion to maximum * macroblockvariance value. Ensure estimate won't be used if * no legal one can be found... */ int best_sad = 256*16*16; int (&m)[Parity::dim /*ref*/][Parity::dim /*pred*/] = dualprime_m[picture->topfirst]; Coord min_cross[Parity::dim]; Coord min_same; // Iterate over the different suggestions corresponding to the // different possible combinations of reference/prediction // field parity for ( int psugref=Parity::top; psugref<=Parity::bot; psugref++) { // Iterate of over parity predicted MB suggestion for ( int psugpred=Parity::top; psugpred<=Parity::top; psugpred++) { /* convert Cartesian absolute to relative motion vector * values (wrt current macroblock address (i,j) */ MotionVector suggestion = MotionVector::Frame(best_fieldmcs[psugref][psugpred].pos, mb ); /* If the candidate base vector is between opposite polarity fields we have to convert it to a corresponding dual-prime base-vector. N.b. this may *increase* its magnitude outside the legal range so we have to check for this... */ MotionVector base; base[Dim::X] = suggestion[Dim::X]*2/m[psugref][psugpred]; base[Dim::Y] = (suggestion[Dim::Y] - dualprime_e[psugref][psugpred])*2/m[psugref][psugpred]; if( ! picture->Legal( base ) ) continue; /* We use (legal) base motion vectors for the same polarity prediction and to derive the base motion vectors for the cross-polarity predictions */ Coord same( mb, base ); Coord cross[Parity::dim /* ref polarity */]; for( int pref = Parity::top; pref < Parity::dim; ++pref ) { int ppred = Parity::Invert(pref); cross[pref].x = rnddiv2(base[Dim::X] * m[pref][ppred]) + mb.x; cross[pref].y = rnddiv2(base[Dim::Y] * m[pref][ppred]) +dualprime_e[pref][ppred]+mb.y; } /* Now find the best differential motion vector for the cross-polarity predictions */ MotionVector dmv; for (dmv[Dim::Y]=-1; dmv[Dim::Y]<=1; ++dmv[Dim::Y]) { for (dmv[Dim::X]=-1; dmv[Dim::X]<=1; ++dmv[Dim::X]) { local_dist = 0; bool legal = DualPrimeMetric( *picture, pbsad, same, cross, dmv, ref, ssmb.mb, stride, local_dist ); /* update best legal MV with smallest distortion * distortion */ if ( local_dist < best_sad && legal ) { dpmvfound = true; min_dpmv = dmv; best_sad = local_dist; min_same = same; min_cross[Parity::top] = cross[Parity::top]; min_cross[Parity::bot] = cross[Parity::bot]; } } /* end delta x loop */ } /* end delta y loop */ } } if( dpmvfound ) { DualPrimeMetric( *picture, pbsumsq, min_same, min_cross, min_dpmv, ref, ssmb.mb, stride, best_mc.var ); best_mc.sad = best_sad + mv_coding_penalty( min_same.x-mb.x, min_same.y-mb.y ); best_mc.pos = min_same; } return dpmvfound; } static void dpfield_estimate( const Picture &picture, uint8_t *topref, uint8_t *botref, uint8_t *mb, int i, int j, MotionCand *bestsp_mc, MotionCand *bestdp_mc, int *vmcp ) { const EncoderParams &eparams = picture.encparams; uint8_t *sameref, *oppref; int io0,jo0,io,jo,delta_x,delta_y,mvxs,mvys,mvxo0,mvyo0; int imino = 0; int jmino = 0; int imindmv = 0; int jmindmv = 0; int vmc_dp,local_dist; int imins = 0; int jmins = 0; /* Calculate Dual Prime distortions for 9 delta candidates */ /* Note: only for P pictures! */ /* Assign opposite and same reference pointer */ if (picture.pict_struct==TOP_FIELD) { sameref = topref; oppref = botref; } else { sameref = botref; oppref = topref; } /* convert Cartesian absolute to relative motion vector * values (wrt current macroblock address (i,j) */ mvxs = imins - (i<<1); mvys = jmins - (j<<1); /* vector for prediction from field of opposite 'parity' */ mvxo0 = (mvxs+(mvxs>0)) >> 1; /* mvxs / / */ mvyo0 = (mvys+(mvys>0)) >> 1; /* mvys / / 2*/ /* vertical field shift correction */ if (picture.pict_struct==TOP_FIELD) mvyo0--; else mvyo0++; /* convert back to absolute coordinates */ io0 = mvxo0 + (i<<1); jo0 = mvyo0 + (j<<1); /* initialize minimum dual prime distortion to maximum * macroblock variance value */ vmc_dp = 256*256*16*16; for (delta_y = -1; delta_y <= 1; delta_y++) { for (delta_x = -1; delta_x <=1; delta_x++) { /* opposite field coordinates */ io = io0 + delta_x; jo = jo0 + delta_y; if (io >= 0 && io <= (eparams.enc_width-16)<<1 && jo >= 0 && jo <= (eparams.enc_height2-16)<<1) { /* compute prediction error */ local_dist = pbsumsq( sameref + (imins>>1) + eparams.phy_width2*(jmins>>1), oppref + (io>>1) + eparams.phy_width2*(jo>>1), mb, /* current mb location */ eparams.phy_width2, /* adjacent line distance */ imins&1, jmins&1, io&1, jo&1, /* half-pel flags */ 16); /* block height */ /* update delta with least distortion vector */ if (local_dist < vmc_dp) { imino = io; jmino = jo; imindmv = delta_x; jmindmv = delta_y; vmc_dp = local_dist; } } } /* end delta x loop */ } /* end delta y loop */ /* Compute L1 error for decision purposes */ bestdp_mc->sad = pbsad( sameref + (imins>>1) + eparams.phy_width2*(jmins>>1), oppref + (imino>>1) + eparams.phy_width2*(jmino>>1), mb, /* current mb location */ eparams.phy_width2, /* adjacent line distance */ imins&1, jmins&1, imino&1, jmino&1, /* half-pel flags */ 16); /* block height */ bestdp_mc->pos.x = imindmv; bestdp_mc->pos.y = jmindmv; *vmcp = vmc_dp; } /* * Collection motion estimates for the different modes for frame pictures * picture: picture object for which MC is to be computed. * * results: a vector of 'plausible' motion estimates. This function * which is a refined version of the original MSSE reference encoder * only every puts a single, heuristically 'best', estimate into the vector * * TODO: MC_DMV should trigger on the current (dynamically selected) * bigroup length and not the fixed Maximum bi-group length M. */ #ifdef DEBUG_MOTION_EST const static bool trace_me = false; #endif void MacroBlock::FrameMEs() { const Picture &picture = ParentPicture(); const EncoderParams &eparams = picture.encparams; int i = TopleftX(); int j = TopleftY(); // // Motion info for the various possible motion modes... // MotionCand framef_mc; MotionCand frameb_mc; MotionCand dualpf_mc; MotionCand topfldf_mc; MotionCand botfldf_mc; MotionCand topfldb_mc; MotionCand botfldb_mc; MotionCand zeromot_mc; // Pointers to macroblock's contents in YUV and half and quad // subsampled planes, and for FIELD modes, the bottom field // variants... SubSampledImg ssmb; SubSampledImg botssmb; MotionCand best_fieldmcs[2][2]; MotionVector min_dpmv; int mb_row_start = j*eparams.phy_width; MotionEst me; best_of_kind_me.clear(); /* A.Stevens fast motion estimation data is appended to actual luminance information. TODO: The append thing made sense before we had a nice tidy compression record for each picture but now it should really be replaced by additional pointers to seperate buffers. */ ssmb.mb = picture.org_img->Plane(0) + mb_row_start + i; ssmb.umb = (uint8_t*)(picture.org_img->Plane(1) + (i>>1) + (mb_row_start>>2)); ssmb.vmb = (uint8_t*)(picture.org_img->Plane(2) + (i>>1) + (mb_row_start>>2)); ssmb.fmb = (uint8_t*)(picture.org_img->Plane(0) + eparams.fsubsample_offset + ((i>>1) + (mb_row_start>>2))); ssmb.qmb = (uint8_t*)(picture.org_img->Plane(0) + eparams.qsubsample_offset + (i>>2) + (mb_row_start>>4)); /* Zero motion vector - useful for some optimisations */ zeromot_mc.pos.x = (i<<1); /* Damn but its messy carrying doubled */ zeromot_mc.pos.y = (j<<1); /* absolute Co-ordinates for M/C */ zeromot_mc.fieldsel = 0; zeromot_mc.fieldoff = 0; zeromot_mc.blk = picture.fwd_rec->Plane(0)+mb_row_start+i; zeromot_mc.hx = zeromot_mc.hy = 0; /* Compute variance MB as a measure of Intra-coding complexity We include chrominance information here, scaled to compensate for sub-sampling. Silly MPEG forcing chrom/lum to have same quantisations... ;-) */ pvariance(ssmb.mb,16,eparams.phy_width, &lum_variance, &lum_mean ); int intravar = lum_variance + chrom_var_sum(&ssmb,16,eparams.phy_width); // INTRA coding is always an option and always comes first in the list of // motion estimates for the available coding options me.mb_type = MB_INTRA; me.motion_type = 0; me.var = intravar; me.MV[0][0].Zero(); best_of_kind_me.push_back( me ); if (picture.pict_type==P_TYPE) { /* FRAME mode non-intra coding 0 MV and estimated MVs is always possible */ zeromot_mc.var = unidir_pred_var(&zeromot_mc, ssmb.mb, eparams.phy_width, 16 ); me.mb_type = 0; me.motion_type = MC_FRAME; me.var = unidir_var_sum(&zeromot_mc, *picture.fwd_rec, &ssmb, eparams.phy_width, 16 ); best_of_kind_me.push_back( me ); mb_me_search( eparams, picture.fwd_org->Plane(0),picture.fwd_rec->Plane(0), 0, &ssmb, eparams.phy_width, i,j,picture.sxf,picture.syf,16, eparams.enc_width,eparams.enc_height, &framef_mc); framef_mc.fieldoff = 0; me.mb_type = MB_FORWARD; me.motion_type=MC_FRAME; me.var = unidir_var_sum( &framef_mc, *picture.fwd_rec, &ssmb, eparams.phy_width, 16 ); me.MV[0][0] = MotionVector::Frame( framef_mc.pos, hpel ); best_of_kind_me.push_back( me ); /* FIELD modes only possible if appropriate picture type is legal */ if (!picture.frame_pred_dct ) { botssmb.mb = ssmb.mb+eparams.phy_width; botssmb.fmb = ssmb.fmb+(eparams.phy_width>>1); botssmb.qmb = ssmb.qmb+(eparams.phy_width>>2); botssmb.umb = ssmb.umb+(eparams.phy_width>>1); botssmb.vmb = ssmb.vmb+(eparams.phy_width>>1); FieldMotionCands( eparams, picture.fwd_org->Plane(0), picture.fwd_rec->Plane(0), &ssmb, &botssmb, i,j,picture.sxf,picture.syf, &topfldf_mc, &botfldf_mc, best_fieldmcs); me.mb_type = MB_FORWARD; me.motion_type = MC_FIELD; me.var = unidir_var_sum( &topfldf_mc, *picture.fwd_rec, &ssmb, (eparams.phy_width<<1), 8 ) + unidir_var_sum( &botfldf_mc, *picture.fwd_rec, &botssmb, (eparams.phy_width<<1), 8 ); me.MV[0][0] = MotionVector::Field(topfldf_mc.pos, hpel); me.MV[1][0] = MotionVector::Field(botfldf_mc.pos, hpel); me.field_sel[0][0] = topfldf_mc.fieldsel; me.field_sel[1][0] = botfldf_mc.fieldsel; best_of_kind_me.push_back( me ); if ( eparams.dualprime && FrameDualPrimeCand( picture.fwd_rec->Plane(0), ssmb, best_fieldmcs, dualpf_mc, min_dpmv ) ) { me.mb_type = MB_FORWARD; me.motion_type = MC_DMV; me.MV[0][0] = MotionVector::Field(dualpf_mc.pos, hpel); me.dualprimeMV = min_dpmv; // TODO: No actual calculation of chroma variances // just assumed identical per block as luma. me.var = dualpf_mc.var + dualpf_mc.var/2; best_of_kind_me.push_back( me ); } } } else if (picture.pict_type==B_TYPE) { /* FRAME modes: always possible */ // Forward motion estimates mb_me_search( eparams, picture.fwd_org->Plane(0),picture.fwd_rec->Plane(0),0,&ssmb, eparams.phy_width,i,j,picture.sxf,picture.syf, 16,eparams.enc_width,eparams.enc_height, &framef_mc ); framef_mc.fieldoff = 0; // Backword motion estimates... mb_me_search( eparams, picture.bwd_org->Plane(0),picture.bwd_rec->Plane(0),0,&ssmb, eparams.phy_width, i,j,picture.sxb,picture.syb, 16, eparams.enc_width, eparams.enc_height, &frameb_mc); frameb_mc.fieldoff = 0; me.motion_type = MC_FRAME; me.MV[0][0][0] = framef_mc.pos.x - (i<<1); me.MV[0][0][1] = framef_mc.pos.y - (j<<1); me.MV[0][1][0] = frameb_mc.pos.x - (i<<1); me.MV[0][1][1] = frameb_mc.pos.y - (j<<1); me.mb_type = MB_FORWARD; me.var = unidir_var_sum( &framef_mc, *picture.fwd_rec, &ssmb, eparams.phy_width, 16 ); best_of_kind_me.push_back( me ); me.mb_type = MB_BACKWARD; me.var = unidir_var_sum( &frameb_mc, *picture.bwd_rec, &ssmb, eparams.phy_width, 16 ); best_of_kind_me.push_back( me ); me.mb_type = MB_FORWARD|MB_BACKWARD; me.var = bidir_var_sum( &framef_mc, &frameb_mc, *picture.fwd_rec, *picture.bwd_rec, &ssmb, eparams.phy_width, 16 ); best_of_kind_me.push_back( me ); /* FIELD modes only possible if appropriate picture type is legal */ if (!picture.frame_pred_dct ) { botssmb.mb = ssmb.mb+eparams.phy_width; botssmb.fmb = ssmb.fmb+(eparams.phy_width>>1); botssmb.qmb = ssmb.qmb+(eparams.phy_width>>2); botssmb.umb = ssmb.umb+(eparams.phy_width>>1); botssmb.vmb = ssmb.vmb+(eparams.phy_width>>1); // Forward motion estimates... FieldMotionCands( eparams, picture.fwd_org->Plane(0),picture.fwd_rec->Plane(0), &ssmb, &botssmb, i,j,picture.sxf,picture.syf, &topfldf_mc, &botfldf_mc, best_fieldmcs); // Backward motion estimates... FieldMotionCands( eparams, picture.bwd_org->Plane(0),picture.bwd_rec->Plane(0), &ssmb, &botssmb, i,j,picture.sxb,picture.syb, &topfldb_mc, &botfldb_mc, best_fieldmcs); me.motion_type = MC_FIELD; me.MV[0][0][0] = topfldf_mc.pos.x - (i<<1); me.MV[0][0][1] = (topfldf_mc.pos.y<<1) - (j<<1); me.MV[1][0][0] = botfldf_mc.pos.x - (i<<1); me.MV[1][0][1] = (botfldf_mc.pos.y<<1) - (j<<1); me.field_sel[0][0] = topfldf_mc.fieldsel; me.field_sel[1][0] = botfldf_mc.fieldsel; me.MV[0][1][0] = topfldb_mc.pos.x - (i<<1); me.MV[0][1][1] = (topfldb_mc.pos.y<<1) - (j<<1); me.MV[1][1][0] = botfldb_mc.pos.x - (i<<1); me.MV[1][1][1] = (botfldb_mc.pos.y<<1) - (j<<1); me.field_sel[0][1] = topfldb_mc.fieldsel; me.field_sel[1][1] = botfldb_mc.fieldsel; me.mb_type = MB_FORWARD|MB_BACKWARD; me.var = bidir_var_sum( &topfldf_mc, &topfldb_mc, * picture.fwd_rec,*picture.bwd_rec, &ssmb, eparams.phy_width<<1, 8) + bidir_var_sum( &botfldf_mc, &botfldb_mc, *picture.fwd_rec,*picture.bwd_rec, &botssmb, eparams.phy_width<<1, 8); best_of_kind_me.push_back( me ); me.mb_type = MB_FORWARD; me.var = unidir_var_sum( &topfldf_mc, *picture.fwd_rec, &ssmb, (eparams.phy_width<<1), 8 ) + unidir_var_sum( &botfldf_mc, *picture.fwd_rec, &botssmb, (eparams.phy_width<<1), 8 ); best_of_kind_me.push_back( me ); me.mb_type = MB_BACKWARD; me.var = unidir_var_sum( &topfldb_mc, *picture.bwd_rec, &ssmb, (eparams.phy_width<<1), 8 ) + unidir_var_sum( &botfldb_mc, *picture.bwd_rec, &botssmb, (eparams.phy_width<<1), 8 ); best_of_kind_me.push_back( me ); } } } /* * motion estimation for field pictures * picture: picture object for which MC is to be computed. * mbi: pointer to macroblock info of picture object * mb_row_start: offset in chrominance block of start of this MB's row * * results: * mbi-> * me.mb_type: 0, MB_INTRA, MB_FORWARD, MB_BACKWARD, MB_FORWARD|MB_BACKWARD * me.MV[][][]: motion vectors (field format) * me.field_sel: top/bottom field * me.motion_type: MC_FIELD, MC_16X8 * */ void MacroBlock::FieldME() { const Picture &picture = ParentPicture(); const EncoderParams &eparams = picture.encparams; int i = TopleftX(); int j = TopleftY(); int w2; uint8_t *toporg, *topref, *botorg, *botref; SubSampledImg ssmb; MotionCand fieldsp_mc, dualp_mc; MotionCand fieldf_mc, fieldb_mc; MotionCand field8uf_mc, field8lf_mc; MotionCand field8ub_mc, field8lb_mc; int intravar, vmc,v0,dmc,dmcfieldi,dmcfield,dmcfieldf,dmcfieldr,dmc8i; int dmc8f,dmc8r; int vmc_dp,dctl_dp; MotionEst me; w2 = eparams.phy_width<<1; /* Fast motion data sits at the end of the luminance buffer */ ssmb.mb = picture.org_img->Plane(0) + i + w2*j; ssmb.umb = picture.org_img->Plane(1) + ((i>>1)+(w2>>1)*(j>>1)); ssmb.vmb = picture.org_img->Plane(2) + ((i>>1)+(w2>>1)*(j>>1)); ssmb.fmb = picture.org_img->Plane(0) + eparams.fsubsample_offset+((i>>1)+(w2>>1)*(j>>1)); ssmb.qmb = picture.org_img->Plane(0) + eparams.qsubsample_offset+ (i>>2)+(w2>>2)*(j>>2); if (picture.pict_struct==BOTTOM_FIELD) { ssmb.mb += eparams.phy_width; ssmb.umb += (eparams.phy_width >> 1); ssmb.vmb += (eparams.phy_width >> 1); ssmb.fmb += (eparams.phy_width >> 1); ssmb.qmb += (eparams.phy_width >> 2); } pvariance( ssmb.mb, 16, w2, &lum_variance, &lum_mean ); intravar = lum_variance + chrom_var_sum(&ssmb,16,w2); // INTRA coding is always an option and always comes first in the list of // motion estimates for the available coding options me.mb_type = MB_INTRA; me.motion_type = 0; me.var = intravar; me.MV[0][0].Zero(); best_of_kind_me.clear(); best_of_kind_me.push_back( me ); if(picture.pict_type==I_TYPE) { me.mb_type = MB_INTRA; me.var = intravar; } else if (picture.pict_type==P_TYPE) { toporg = picture.fwd_org->Plane(0); topref = picture.fwd_rec->Plane(0); botorg = picture.fwd_org->Plane(0); botref = picture.fwd_rec->Plane(0); if (picture.secondfield) { /* opposite parity field is in same frame */ if (picture.pict_struct==TOP_FIELD) { /* current is top field */ botorg = picture.org_img->Plane(0) ; botref = picture.rec_img->Plane(0); } else { /* current is bottom field */ toporg = picture.org_img->Plane(0); topref = picture.rec_img->Plane(0); } } field_estimate(picture, toporg,topref,botorg,botref,&ssmb, i,j,picture.sxf,picture.syf, &fieldf_mc, &field8uf_mc, &field8lf_mc, &fieldsp_mc); dmcfield = fieldf_mc.sad; dmc8f = field8uf_mc.sad + field8lf_mc.sad; dctl_dp = 100000000; /* Suppress compiler warning */ if ( eparams.dualprime && !picture.ipflag) /* generic condition which permits Dual Prime */ { dpfield_estimate(picture, topref,botref,ssmb.mb,i,j, &fieldsp_mc, &dualp_mc, &vmc_dp); dctl_dp = dualp_mc.sad; } /* select between dual prime, field and 16x8 prediction */ if ( eparams.M==1 && !picture.ipflag && dctl_dpintravar && vmc > 12*256) { me.mb_type = MB_INTRA; me.var = intravar; } else { /* zero MV field prediction from same parity ref. field * (not allowed if ipflag is set) */ if (!picture.ipflag) v0 = psumsq(((picture.pict_struct==BOTTOM_FIELD) ? botref : topref) + i + w2*j, ssmb.mb,w2,0,0,16); else v0 = 1234; /* Keep Compiler happy... */ if (picture.ipflag || (4*v0>5*vmc )) { me.mb_type = MB_FORWARD; me.var = vmc; if (me.motion_type==MC_FIELD) { me.MV[0][0][0] = fieldf_mc.pos.x - (i<<1); me.MV[0][0][1] = fieldf_mc.pos.y - (j<<1); me.field_sel[0][0] = fieldf_mc.fieldsel; } else if (me.motion_type==MC_DMV) { /* same parity vector */ me.MV[0][0][0] = fieldsp_mc.pos.x - (i<<1); me.MV[0][0][1] = fieldsp_mc.pos.y - (j<<1); /* opposite parity vector */ me.dualprimeMV[0] = dualp_mc.pos.x; me.dualprimeMV[1] = dualp_mc.pos.y; } else { me.MV[0][0][0] = field8uf_mc.pos.x - (i<<1); me.MV[0][0][1] = field8uf_mc.pos.y - (j<<1); me.MV[1][0][0] = field8lf_mc.pos.x - (i<<1); me.MV[1][0][1] = field8lf_mc.pos.y - ((j+8)<<1); me.field_sel[0][0] = field8uf_mc.fieldsel; me.field_sel[1][0] = field8lf_mc.fieldsel; } } else { /* No MC */ me.mb_type = 0; me.var = v0; me.motion_type = MC_FIELD; me.MV[0][0][0] = 0; me.MV[0][0][1] = 0; me.field_sel[0][0] = (picture.pict_struct==BOTTOM_FIELD); } } } else /* if (pict_type==B_TYPE) */ { /* forward prediction */ field_estimate( picture, picture.fwd_org->Plane(0), picture.fwd_rec->Plane(0), picture.fwd_org->Plane(0), picture.fwd_rec->Plane(0), &ssmb,i,j,picture.sxf,picture.syf, &fieldf_mc, &field8uf_mc, &field8lf_mc, &fieldsp_mc); dmcfieldf = fieldf_mc.sad; dmc8f = field8uf_mc.sad + field8lf_mc.sad; /* backward prediction */ field_estimate( picture, picture.bwd_org->Plane(0), picture.bwd_rec->Plane(0), picture.bwd_org->Plane(0), picture.bwd_rec->Plane(0), &ssmb,i,j,picture.sxb,picture.syb, &fieldb_mc, &field8ub_mc, &field8lb_mc, &fieldsp_mc); dmcfieldr = fieldb_mc.sad; dmc8r = field8ub_mc.sad + field8lb_mc.sad; /* calculate distances for bidirectional prediction */ /* field */ dmcfieldi = bidir_pred_sad( &fieldf_mc, &fieldb_mc, ssmb.mb, w2, 16); /* 16x8 upper and lower half blocks */ dmc8i = bidir_pred_sad( &field8uf_mc, &field8ub_mc, ssmb.mb, w2, 16 ); dmc8i += bidir_pred_sad( &field8lf_mc, &field8lb_mc, ssmb.mb, w2, 16 ); /* select prediction type of minimum distance */ if (dmcfieldiintravar && vmc > 12*256) { me.mb_type = MB_INTRA; me.var = intravar; } else { me.var = vmc; if (me.motion_type==MC_FIELD) { /* forward */ me.MV[0][0][0] = fieldf_mc.pos.x - (i<<1); me.MV[0][0][1] = fieldf_mc.pos.y - (j<<1); me.field_sel[0][0] = fieldf_mc.fieldsel; /* backward */ me.MV[0][1][0] = fieldb_mc.pos.x - (i<<1); me.MV[0][1][1] = fieldb_mc.pos.y - (j<<1); me.field_sel[0][1] = fieldb_mc.fieldsel; } else /* MC_16X8 */ { /* forward */ me.MV[0][0][0] = field8uf_mc.pos.x - (i<<1); me.MV[0][0][1] = field8uf_mc.pos.y - (j<<1); me.field_sel[0][0] = field8uf_mc.fieldsel; me.MV[1][0][0] = field8lf_mc.pos.x - (i<<1); me.MV[1][0][1] = field8lf_mc.pos.y - ((j+8)<<1); me.field_sel[1][0] = field8lf_mc.fieldsel; /* backward */ me.MV[0][1][0] = field8ub_mc.pos.x - (i<<1); me.MV[0][1][1] = field8ub_mc.pos.y - (j<<1); me.field_sel[0][1] = field8ub_mc.fieldsel; me.MV[1][1][0] = field8lb_mc.pos.x - (i<<1); me.MV[1][1][1] = field8lb_mc.pos.y - ((j+8)<<1); me.field_sel[1][1] = field8lb_mc.fieldsel; } } } if( me.mb_type != MB_INTRA ) { best_of_kind_me.push_back( me ); } } /* * frame picture field mode motion estimates... * * org: top left pel of source reference frame * ref: top left pel of reconstructed reference frame * ssmb: macroblock to be matched * i,j: location of mb relative to ref (=center of search window) * sx,sy: half widths of search window * besttop: location of best field pred. for top field of mb * bestbo : location of best field pred. for bottom field of mb */ /* * field picture motion estimation subroutine * * toporg: address of frame holding original top reference field * topref: address of frame holding reconstructed top reference field * botorg: address of frame holding original bottom reference field * botref: address of frame holding reconstructed bottom reference field * ssmmb: macroblock to be matched * i,j: location of mb (=center of search window) * sx,sy: half width/height of search window * * bestfld: location and distance of best field prediction * best8u: location of best 16x8 pred. for upper half of mb * best8lp: location of best 16x8 pred. for lower half of mb * bdestsp: location and distance of best same parity field * prediction (needed for dual prime, only valid if * ipflag==0) */ static void field_estimate ( const Picture &picture, uint8_t *toporg, uint8_t *topref, uint8_t *botorg, uint8_t *botref, SubSampledImg *ssmb, int i, int j, int sx, int sy, MotionCand *bestfld, MotionCand *best8u, MotionCand *best8l, MotionCand *bestsp) { const EncoderParams &eparams = picture.encparams; MotionCand topfld_mc; MotionCand botfld_mc; int dt, db; int notop, nobot; SubSampledImg botssmb; botssmb.mb = ssmb->mb+eparams.phy_width; botssmb.umb = ssmb->umb+(eparams.phy_width>>1); botssmb.vmb = ssmb->vmb+(eparams.phy_width>>1); botssmb.fmb = ssmb->fmb+(eparams.phy_width>>1); botssmb.qmb = ssmb->qmb+(eparams.phy_width>>2); /* if ipflag is set, predict from field of opposite parity only */ notop = picture.ipflag && (picture.pict_struct==TOP_FIELD); nobot = picture.ipflag && (picture.pict_struct==BOTTOM_FIELD); /* field prediction */ /* predict current field from top field */ if (notop) topfld_mc.sad = dt = 65536; /* infinity */ else mb_me_search(eparams, toporg,topref,0,ssmb, eparams.phy_width<<1, i,j,sx,sy>>1,16, eparams.enc_width,eparams.enc_height>>1, &topfld_mc); dt = topfld_mc.sad; /* predict current field from bottom field */ if (nobot) botfld_mc.sad = db = 65536; /* infinity */ else mb_me_search(eparams, botorg,botref,eparams.phy_width,ssmb, eparams.phy_width<<1, i,j,sx,sy>>1,16, eparams.enc_width,eparams.enc_height>>1, &botfld_mc); db = botfld_mc.sad; /* Set correct field selectors */ topfld_mc.fieldsel = 0; botfld_mc.fieldsel = 1; topfld_mc.fieldoff = 0; botfld_mc.fieldoff = eparams.phy_width; /* same parity prediction (only valid if ipflag==0) */ if (picture.pict_struct==TOP_FIELD) { *bestsp = topfld_mc; } else { *bestsp = botfld_mc; } /* select field prediction */ if (dt<=db) { *bestfld = topfld_mc; } else { *bestfld = botfld_mc; } /* 16x8 motion estimation */ /* predict upper half field from top field */ if (notop) topfld_mc.sad = dt = 65536; else mb_me_search(eparams, toporg,topref,0,ssmb, eparams.phy_width<<1, i,j,sx,sy>>1,8, eparams.enc_width,eparams.enc_height>>1,&topfld_mc); dt = topfld_mc.sad; /* predict upper half field from bottom field */ if (nobot) botfld_mc.sad = db = 65536; else mb_me_search(eparams, botorg,botref,eparams.phy_width,ssmb, eparams.phy_width<<1, i,j,sx,sy>>1,8, eparams.enc_width, eparams.enc_height>>1,&botfld_mc); db = botfld_mc.sad; /* Set correct field selectors */ topfld_mc.fieldsel = 0; botfld_mc.fieldsel = 1; topfld_mc.fieldoff = 0; botfld_mc.fieldoff = eparams.phy_width; /* select prediction for upper half field */ if (dt<=db) { *best8u = topfld_mc; } else { *best8u = botfld_mc; } /* predict lower half field from top field */ /* N.b. For interlaced data width<<4 (width*16) takes us 8 rows down in the same field. Thus for the fast motion data (2*2 sub-sampled) we need to go 4 rows down in the same field. This requires adding width*4 = (width<<2). For the 4*4 sub-sampled motion data we need to go down 2 rows. This requires adding width = width */ if (notop) topfld_mc.sad = dt = 65536; else mb_me_search(eparams, toporg,topref,0,&botssmb, eparams.phy_width<<1, i,j+8,sx,sy>>1,8, eparams.enc_width,eparams.enc_height>>1, &topfld_mc); dt = topfld_mc.sad; /* predict lower half field from bottom field */ if (nobot) botfld_mc.sad = db = 65536; else mb_me_search(eparams, botorg,botref,eparams.phy_width,&botssmb, eparams.phy_width<<1,i,j+8,sx,sy>>1,8, eparams.enc_width,eparams.enc_height>>1, &botfld_mc); db = botfld_mc.sad; /* Set correct field selectors */ topfld_mc.fieldsel = 0; botfld_mc.fieldsel = 1; topfld_mc.fieldoff = 0; botfld_mc.fieldoff = eparams.phy_width; /* select prediction for lower half field */ if (dt<=db) { *best8l = topfld_mc; } else { *best8l = botfld_mc; } } /* Hierarchical block matching motion estimation search * * A.Stevens 2000: This is now a big misnomer. The search is now a * hierarchical/sub-sampling search not a full search. However, * experiments have shown it is always close to optimal and almost * always very close or optimal. * * org: top left pel of source reference frame * ref: top left pel of reconstructed reference frame * fieldoff - Offset to top left pel relevant field in org and ref * if we're doing by-field matching * ssblk: top-left element of macro block to be motion compensated * at 1*1,2*2 and 4*4 subsampling * lx: distance (in bytes) of vertically adjacent pels in ref,blk * This is twice the physical line length if we're doing by-field * matching otherwise the physical line length * i0,j0: center of search window * sx,sy: half widths of search window * h: height of macro block * xmax,ymax: right/bottom limits of search area for macro block * res: pointers to where the result is stored * N.b. as in the original code result is given as * half pel offset from ref(0,0) not the position relative to i0 j0 * as will actually be used. * * TODO: SHould use half-pel co-ordinates relative to i0,j0 for motion vectors * throughout the motion estimation code but this would be damn fiddly to * do without introducing lots of tricky-to-find bugs. * */ #ifdef DEBUG_MOTION_EST static void log_result_set( me_result_set *rs ) { int i; for( i = 0; i < rs->len; ++i ) printf( "%03d: %6d %3d %3d\n", i, rs->mests[i].weight, 2*rs->mests[i].x, 2*rs->mests[i].y ); } static int hash( uint8_t *blk, int stride ) { int i,j; int sum = 0; for( j= 0; j <16; ++j ) for( i = 0; i <16 ; ++i) sum += *(blk+i+j*stride); return sum; } static int dump( uint8_t *blk, int stride ) { int i,j; int sum = 0; for( j= 0; j <16; ++j ) { for( i = 0; i <16 ; ++i) printf( "%02x ", *(blk+i+j*stride) ); if( j & 1 ) printf( "\n" ); } return sum; } #endif static void mb_me_search( const EncoderParams &eparams, uint8_t *org, uint8_t *ref, int fieldoff, SubSampledImg *ssblk, int lx, int i0, int j0, int sx, int sy, int h, int xmax, int ymax, MotionCand *res ) { me_result_s best; int i,j,ilow,ihigh,jlow,jhigh; int x,y; int d; /* NOTE: Surprisingly, the initial motion estimation search works better when the original image not the reference (reconstructed) image is used. */ uint8_t *s22org = (uint8_t*)(org+eparams.fsubsample_offset+(fieldoff>>1)); uint8_t *s44org = (uint8_t*)(org+eparams.qsubsample_offset+(fieldoff>>2)); uint8_t *orgblk; uint8_t *reffld = ref+fieldoff; int flx = lx >> 1; int qlx = lx >> 2; int fh = h >> 1; int qh = h >> 2; me_result_set sub44set; me_result_set sub22set; /* xmax and ymax into more useful form... */ xmax -= 16; ymax -= h; /* The search radii are *always* multiples of 4 to avoid messiness in the initial 4*4 pel search. This is handled by the parameter checking/processing code in readparmfile() */ /* Create a distance-order mests of possible motion estimations based on the fast estimation data - 4*4 pel sums (4*4 sub-sampled) rather than actual pel's. 1/16 the size... */ jlow = j0-sy; jlow = jlow < 0 ? 0 : jlow; jhigh = j0+(sy-1); jhigh = jhigh > ymax ? ymax : jhigh; ilow = i0-sx; ilow = ilow < 0 ? 0 : ilow; ihigh = i0+(sx-1); ihigh = ihigh > xmax ? xmax : ihigh; /* Very rarely this may fail to find matchs due to all the good looking ones being over threshold. hence we make sure we fall back to a 0 motion estimation in this case. The sad for the 0 motion estimation is also very useful as a basis for setting thresholds for rejecting really dud 4*4 and 2*2 sub-sampled matches. */ best.weight = psad_00(reffld+i0+j0*lx,ssblk->mb,lx,h,INT_MAX); best.x = 0; best.y = 0; /* Generate the best matches at 4*4 sub-sampling. The precise fraction of the matches included is controlled by eparams.44_red Note: we use the original picture here for the match... */ pbuild_sub44_mests( &sub44set, ilow, jlow, ihigh, jhigh, i0, j0, best.weight, s44org, ssblk->qmb, qlx, qh, eparams.me44_red); #ifdef DEBUG_MOTION_EST if( trace_me ) log_result_set( &sub44set ); #endif /* Generate the best 2*2 sub-sampling matches from the immediate 2*2 neighbourhoods of the 4*4 sub-sampling matches. The precise fraction of the matches included is controlled by eparams.22_red. Note: we use the original picture here for the match... */ pbuild_sub22_mests( &sub44set, &sub22set, i0, j0, ihigh, jhigh, best.weight, s22org, ssblk->fmb, flx, fh, eparams.me22_red); #ifdef DEBUG_MOTION_EST if( trace_me ) log_result_set( &sub22set ); #endif /* Now choose best 1-pel match from the 2*2 neighbourhoods of the best 2*2 sub-sampled matches. Note that here we start using the reference picture not the original. */ pfind_best_one_pel( &sub22set, reffld, ssblk->mb, i0, j0, ihigh, jhigh, lx, h, &best ); #ifdef DEBUG_MOTION_EST if( trace_me ) { printf( "BST: %6d %3d %3d @ %6d %7d (%7d)\n", best.weight, 2*best.x, 2*best.y, (i0+best.x)+lx*(j0+best.y), hash(reffld+(i0+best.x)+lx*(j0+best.y), lx), hash(ssblk->mb, lx) ); dump( reffld+(i0+best.x)+lx*(j0+best.y), lx ); }; #endif /* Final polish: half-pel search of best 1*1 against reconstructed image. */ res->sad = INT_MAX; x = (i0+best.x)<<1; y = (j0+best.y)<<1; /* Narrow search box to half-pel's around best 1-pel match - half-pel units....*/ ilow = x - (x>(ilow<<1)); ihigh = x + (x<((ihigh)<<1)); jlow = y - (y>(jlow<<1)); jhigh = y+ (y<((jhigh)<<1)); for (j=jlow; j<=jhigh; j++) { for (i=ilow; i<=ihigh; i++) { orgblk = reffld+(i>>1)+((j>>1)*lx); if( i&1 ) { if( j & 1 ) d = psad_11(orgblk,ssblk->mb,lx,h); else d = psad_01(orgblk,ssblk->mb,lx,h); } else { if( j & 1 ) d = psad_10(orgblk,ssblk->mb,lx,h); else d = psad_00(orgblk,ssblk->mb,lx,h,res->sad); } // TODO: Mismatches motionsearch... #ifdef DEBUG_MOTION_EST if( trace_me ) printf( "BSS: %6d %3d %3d @ %6d %7d\n", d, i, j, orgblk-reffld, hash(orgblk, lx) ); #endif d += mv_coding_penalty(i-(i0<<1),j-(j0<<1)); if (dsad) { res->sad = d; res->pos.x = i; res->pos.y = j; res->blk = orgblk; res->hx = i&1; res->hy = j&1; } } } res->var = psumsq(res->blk, ssblk->mb, lx, res->hx, res->hy, h); } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/synchrolib.h0000644000175000017500000000407210161621375020243 0ustar glowwormglowworm/* Synchrolib - various useful synchronisation primitives (C) 2001 Andrew Stevens This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Damn: shouldn't have to write this - but whenever you need something, well *that's* when you don't have Internet access. Bloody annyong that pthread_mutex's lock/unlock is only supposed to work properly if the same thread does the locking and unlocking. Gaah! */ #ifndef SYNCHROLIB_H #define SYNCHROLIB_H #include /* Synchronisation condition */ typedef struct _sync_guard { pthread_mutex_t mutex; pthread_cond_t cond; volatile int predicate; } sync_guard_t; typedef struct _semaphore { pthread_mutex_t mutex; pthread_cond_t raised; volatile int count; } mp_semaphore_t; #define SEMAPHORE_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, \ PTHREAD_COND_INITIALIZER, \ 0 } #define GUARD_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, \ PTHREAD_COND_INITIALIZER, \ 0 } void sync_guard_init( sync_guard_t *guard, int init ); void sync_guard_test( sync_guard_t *guard); void sync_guard_update( sync_guard_t *guard, int predicate ); void mp_semaphore_init( mp_semaphore_t *sema, int init_count ); void mp_semaphore_wait( mp_semaphore_t *sema); void mp_semaphore_signal( mp_semaphore_t *sema, int count ); void mp_semaphore_set( mp_semaphore_t *sema ); #endif mjpegtools-2.1.0/mpeg2enc/seqstats.hh0000644000175000017500000000232510443621126020102 0ustar glowwormglowworm#ifndef _SEQSTATS_HH #define _SEQSTATS_HH /* seqstats.hh, sequence statistics for bitrate control */ /* (C) 2006 Andrew Stevens */ /* This is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ class BinaryDistNode { friend class BinaryDist; protected: BinaryDistNode(); double lower; double upper; double sigma; double n; int max_child_depth; int used_children; }; class BinaryDist { public: BinaryDist(); InsertSample( double x ); protected: int buckets; double upper; double lower; std::vector dist; }; #endif // _SEQSTATS_HHmjpegtools-2.1.0/mpeg2enc/ontheflyratectlpass1.hh0000644000175000017500000001227111442756174022427 0ustar glowwormglowworm#ifndef _ONTHEFLYRATECTLPASS1_HH #define _ONTHELFYRATECTLPASS1_HH /* (C) 2003 Andrew Stevens */ /* This is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "ratectl.hh" /* The parts of of the rate-controller's state neededfor save/restore if backing off a partial encoding */ class OnTheFlyPass1State : public RateCtlState { public: virtual ~OnTheFlyPass1State() {} virtual RateCtlState *New() const { return new OnTheFlyPass1State; } virtual void Set( const RateCtlState &state ) { *this = static_cast(state); } virtual const RateCtlState &Get() const { return *this; } int target_bits; // target_bits int vbuf_fullness; int ratectl_vbuf[NUM_PICT_TYPES]; int per_pict_bits; int fields_in_gop; double field_rate; int fields_per_pict; int buffer_variation; int64_t bits_transported; int64_t bits_used; int gop_buffer_correction; int frame_overshoot_margin; int undershoot_carry; /*! * If our buffer is running down we need to reduce available bits * for encoding to fill it up again. This is the gain expressed * as the fraction of the undershoot to recover over the next second. */ double overshoot_gain; /* actsum - Total activity (sum block lum variances) in frame actcovered - Activity macroblocks so far quantised (used to fine tune quantisation to avoid starving highly active blocks appearing late in frame...) UNUSED avg_act - Current average activity... */ double actsum; double actcovered; double sum_avg_act; double avg_act; double sum_avg_quant; int N[NUM_PICT_TYPES]; int min_d, max_d; int min_q, max_q; double bits_per_mb; bool fast_tune; bool first_gop; /* X's measure global complexity (Chi! not X!) of frame types. * Actually: X = average quantisation * bits allocated in *previous* frame * N.b. the choice of measure is *not* arbitrary. The feedback bit * rate control gets horribly messed up if it is *not* proportionate * to bit demand i.e. bits used scaled for quantisation. * d's are virtual reciever buffer fullness * r is Rate control feedback gain (in* bits/frame) */ double Xhi[NUM_PICT_TYPES]; /* The average complexity of frames of the different types is used * to predict a reasonable bit-allocation for these types. * The AVG_WINDOW set the size of the sliding window for these * averages. Basically I Frames respond very quickly. * B / P frames more or less quickly depending on the target number * of B frames per P frame. */ double K_AVG_WINDOW[NUM_PICT_TYPES]; /* * 'Typical' sizes of the different types of picture in a GOP - these * sizes are needed so that buffer management can compensate for the * 'normal' ebb and flow of buffer space in a GOP (low after a big I frame) * nearly full at the end after lots of smaller B/P frames. * */ int32_t pict_base_bits[NUM_PICT_TYPES]; bool first_encountered[NUM_PICT_TYPES]; // Some statistics for measuring if things are going well. double sum_size[NUM_PICT_TYPES]; int pict_count[NUM_PICT_TYPES]; }; class OnTheFlyPass1 : public Pass1RateCtl, public OnTheFlyPass1State { public: OnTheFlyPass1( EncoderParams &encoder ); virtual void Init() ; virtual void GopSetup( int nb, int np ); virtual void PictUpdate (Picture &picture, int &padding_needed ); virtual int MacroBlockQuant( const MacroBlock &mb); virtual int InitialMacroBlockQuant(); double SumAvgActivity() { return sum_avg_act; } protected: virtual int TargetPictureEncodingSize(); virtual void InitSeq( ); virtual void InitGOP( ) ; virtual void InitPict( Picture &picture ); protected: /*! * Mean bitrate to aim for... */ double ctrl_bitrate; private: double cur_base_Q; // Current base quantisation (before adjustments // for relative macroblock activity int cur_mquant; // Current macroblock quantisation int mquant_change_ctr; double sum_base_Q; // Accumulates base quantisations encoding int sum_actual_Q; // Accumulates actual quantisation // inverse feedback gain: its in weird units // The quantisation is porportionate to the // buffer bit overshoot (virtual buffer fullness) // *divided* by fb_gain A int32_t fb_gain; // VBV calculation data double picture_delay; double next_ip_delay; /* due to frame reordering delay */ double decoding_time; }; /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ #endif mjpegtools-2.1.0/mpeg2enc/Makefile.in0000644000175000017500000007503212217306407017767 0ustar glowwormglowworm# Makefile.in generated by automake 1.12.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Automake Makefile template for mpeg2enc++ library # and mpeg2enc command line wrapper. # VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = mpeg2enc$(EXEEXT) subdir = mpeg2enc DIST_COMMON = README $(libmpeg2encpp_include_HEADERS) \ $(noinst_HEADERS) $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/depcomp ChangeLog INSTALL TODO ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(libmpeg2encpp_includedir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__libmpeg2encpp_la_SOURCES_DIST = conform.cc elemstrmwriter.cc \ encoderparams.cc macroblock.cc motionest.cc mpeg2coder.cc \ mpeg2encoptions.cc imageplanes.cc mpeg2encoder.cc picture.cc \ picturereader.cc predict.cc putpic.cc streamstate.cc \ seqencoder.cc quantize.cc ratectl.cc stats.cc synchrolib.cc \ tables.c transfrm.cc fdct.c idct.c predict_ref.c \ quantize_ref.c transfrm_ref.c fdct_x86.c fdct_mmx.c idct_mmx.c \ quant_mmx.c predict_mmx.c predcomp_mmx.c predcomp_mmxe.c \ predict_x86.c quantize_x86.c transfrm_x86.c \ ontheflyratectlpass1.cc ontheflyratectlpass2.cc \ rate_complexity_model.cc am__objects_1 = fdct.lo idct.lo predict_ref.lo quantize_ref.lo \ transfrm_ref.lo am__objects_2 = fdct_x86.lo fdct_mmx.lo idct_mmx.lo quant_mmx.lo \ predict_mmx.lo predcomp_mmx.lo predcomp_mmxe.lo predict_x86.lo \ quantize_x86.lo transfrm_x86.lo @HAVE_ASM_MMX_TRUE@am__objects_3 = $(am__objects_2) am_libmpeg2encpp_la_OBJECTS = conform.lo elemstrmwriter.lo \ encoderparams.lo macroblock.lo motionest.lo mpeg2coder.lo \ mpeg2encoptions.lo imageplanes.lo mpeg2encoder.lo picture.lo \ picturereader.lo predict.lo putpic.lo streamstate.lo \ seqencoder.lo quantize.lo ratectl.lo stats.lo synchrolib.lo \ tables.lo transfrm.lo $(am__objects_1) $(am__objects_3) \ ontheflyratectlpass1.lo ontheflyratectlpass2.lo \ rate_complexity_model.lo libmpeg2encpp_la_OBJECTS = $(am_libmpeg2encpp_la_OBJECTS) libmpeg2encpp_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(libmpeg2encpp_la_LDFLAGS) $(LDFLAGS) -o $@ PROGRAMS = $(bin_PROGRAMS) am_mpeg2enc_OBJECTS = mpeg2enc.$(OBJEXT) mpeg2enc_OBJECTS = $(am_mpeg2enc_OBJECTS) am__DEPENDENCIES_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libmpeg2encpp_la_SOURCES) $(mpeg2enc_SOURCES) DIST_SOURCES = $(am__libmpeg2encpp_la_SOURCES_DIST) \ $(mpeg2enc_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(libmpeg2encpp_include_HEADERS) $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALTIVEC_EXTRA_LIBS = @ALTIVEC_EXTRA_LIBS@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDV_CFLAGS = @LIBDV_CFLAGS@ LIBDV_LIBS = @LIBDV_LIBS@ LIBGETOPT_LIB = @LIBGETOPT_LIB@ LIBM_LIBS = @LIBM_LIBS@ LIBOBJS = @LIBOBJS@ LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ LIBPNG_LIBS = @LIBPNG_LIBS@ LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@ LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ LT_STATIC = @LT_STATIC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROGRAM_NOPIC = @PROGRAM_NOPIC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ SDLgfx_LIBS = @SDLgfx_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ V4LCONF_LIBS = @V4LCONF_LIBS@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ mpeg2encpp_MMXSSE_INLINE = \ fdct_x86.c \ fdct_mmx.c \ idct_mmx.c \ quant_mmx.c \ predict_mmx.c \ predcomp_mmx.c \ predcomp_mmxe.c \ predict_x86.c \ quantize_x86.c \ transfrm_x86.c EXTRA_DIST = NOTES README TODO INSTALL ChangeLog seqstats.cc seqstats.hh MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/utils LIBMJPEGUTILS = $(top_builddir)/utils/libmjpegutils.la lib_LTLIBRARIES = libmpeg2encpp.la @HAVE_ASM_MMX_TRUE@SIMD_INLINE = $(mpeg2encpp_MMXSSE_INLINE) # Reference implementations of lowlevel routines that may have Architecture # dependent (usually SIMD) implementations mpeg2enc_REF = \ fdct.c \ idct.c \ predict_ref.c \ quantize_ref.c \ transfrm_ref.c mpeg2enc_noinst_header_REF = \ transfrm_ref.h mpeg2enc_inst_header_REF = \ predict_ref.h mpeg2enc_SOURCES = mpeg2enc.cc libmpeg2encpp_la_SOURCES = conform.cc elemstrmwriter.cc encoderparams.cc \ macroblock.cc motionest.cc mpeg2coder.cc mpeg2encoptions.cc \ imageplanes.cc mpeg2encoder.cc \ picture.cc picturereader.cc predict.cc putpic.cc \ streamstate.cc seqencoder.cc \ quantize.cc ratectl.cc stats.cc synchrolib.cc tables.c \ transfrm.cc $(mpeg2enc_REF) \ $(SIMD_INLINE) ontheflyratectlpass1.cc ontheflyratectlpass2.cc \ rate_complexity_model.cc noinst_HEADERS = channel.hh quantize_precomp.h simd.h \ tables.h $(mpeg2enc_noinst_header_REF) rate_complexity_model.hh libmpeg2encpp_includedir = $(pkgincludedir)/mpeg2enc libmpeg2encpp_include_HEADERS = elemstrmwriter.hh encoderparams.hh \ encodertypes.h macroblock.hh mpeg2coder.hh mpeg2encoder.hh mpeg2encoptions.hh \ mpeg2encparams.h picture.hh picturereader.hh quantize.hh quantize_ref.h ratectl.hh \ streamstate.h seqencoder.hh synchrolib.h syntaxconsts.h $(mpeg2enc_inst_header_REF) \ ontheflyratectlpass1.hh ontheflyratectlpass2.hh \ mpeg2syntaxcodes.h imageplanes.hh libmpeg2encpp_la_LDFLAGS = \ ${LT_STATIC} \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -release $(LT_RELEASE) ${EXTRA_LDFLAGS} libmpeg2encpp_la_DEPENDENCIES = $(LIBMJPEGUTILS) libmpeg2encpp_la_LIBADD = $(LIBMJPEGUTILS) @PTHREAD_LIBS@ mpeg2enc_DEPENDENCIES = \ $(LIBMJPEGUTILS) \ libmpeg2encpp.la mpeg2enc_LDADD = \ libmpeg2encpp.la \ $(LIBMJPEGUTILS) \ @PTHREAD_LIBS@ @LIBGETOPT_LIB@ $(LIBM_LIBS) all: all-am .SUFFIXES: .SUFFIXES: .c .cc .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu mpeg2enc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu mpeg2enc/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libmpeg2encpp.la: $(libmpeg2encpp_la_OBJECTS) $(libmpeg2encpp_la_DEPENDENCIES) $(EXTRA_libmpeg2encpp_la_DEPENDENCIES) $(libmpeg2encpp_la_LINK) -rpath $(libdir) $(libmpeg2encpp_la_OBJECTS) $(libmpeg2encpp_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list mpeg2enc$(EXEEXT): $(mpeg2enc_OBJECTS) $(mpeg2enc_DEPENDENCIES) $(EXTRA_mpeg2enc_DEPENDENCIES) @rm -f mpeg2enc$(EXEEXT) $(CXXLINK) $(mpeg2enc_OBJECTS) $(mpeg2enc_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conform.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elemstrmwriter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encoderparams.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdct.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdct_mmx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdct_x86.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idct.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idct_mmx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imageplanes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/macroblock.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/motionest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpeg2coder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpeg2enc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpeg2encoder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpeg2encoptions.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ontheflyratectlpass1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ontheflyratectlpass2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/picture.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/picturereader.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/predcomp_mmx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/predcomp_mmxe.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/predict.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/predict_mmx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/predict_ref.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/predict_x86.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/putpic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quant_mmx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quantize.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quantize_ref.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quantize_x86.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rate_complexity_model.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ratectl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/seqencoder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stats.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/streamstate.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/synchrolib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tables.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transfrm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transfrm_ref.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transfrm_x86.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< .cc.o: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cc.lo: @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-libmpeg2encpp_includeHEADERS: $(libmpeg2encpp_include_HEADERS) @$(NORMAL_INSTALL) @list='$(libmpeg2encpp_include_HEADERS)'; test -n "$(libmpeg2encpp_includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libmpeg2encpp_includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libmpeg2encpp_includedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libmpeg2encpp_includedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libmpeg2encpp_includedir)" || exit $$?; \ done uninstall-libmpeg2encpp_includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(libmpeg2encpp_include_HEADERS)'; test -n "$(libmpeg2encpp_includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libmpeg2encpp_includedir)'; $(am__uninstall_files_from_dir) ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libmpeg2encpp_includedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-libmpeg2encpp_includeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libmpeg2encpp_includeHEADERS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libLTLIBRARIES clean-libtool cscopelist \ ctags distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-libmpeg2encpp_includeHEADERS install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-libLTLIBRARIES \ uninstall-libmpeg2encpp_includeHEADERS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mjpegtools-2.1.0/mpeg2enc/fdct_x86.c0000644000175000017500000003215210450314721017502 0ustar glowwormglowworm#include #include #include "cpu_accel.h" #include "mjpeg_types.h" #include "mmx.h" #define SHUFFLEMAP(A,B,C,D) ((A)*1+(B)*4+(C)*16+(D)*64) #define NC_COS6 0.382683432365089771728459984030399//cos(6*pi/16) #define NC_R_SQRT2 0.707106781186547524400844362104849// 1/sqrt(2) #define NC_COS0SQRT2 1.0 //cos(0*pi/16)*sqrt(2) #define NC_COS1SQRT2 1.38703984532214746182161919156644 //cos(1*pi/16)*sqrt(2) #define NC_COS2SQRT2 1.30656296487637652785664317342719 //cos(2*pi/16)*sqrt(2) #define NC_COS3SQRT2 1.17587560241935871697446710461126 //cos(3*pi/16)*sqrt(2) #define NC_COS4SQRT2 1.0 //cos(4*pi/16)*sqrt(2) #define NC_COS5SQRT2 0.785694958387102181277897367657217//cos(5*pi/16)*sqrt(2) #define NC_COS6SQRT2 0.541196100146196984399723205366389//cos(6*pi/16)*sqrt(2) #define NC_COS7SQRT2 0.275899379282943012335957563669373//cos(7*pi/16)*sqrt(2) void init_fdct_sse( void ); void fdct_sse(int16_t *block); static float aanscales[64]; #define SSECONST(n,x) static float n[4] __attribute__ ((aligned (16))) = { x, x, x, x } SSECONST(fdct_sse_r_sqrt2, NC_R_SQRT2); SSECONST(fdct_sse_cos6, NC_COS6); SSECONST(fdct_sse_cos6sqrt2,NC_COS6SQRT2); SSECONST(fdct_sse_cos2sqrt2,NC_COS2SQRT2); void init_fdct_sse( void ) { int i, j; static const double aansf[8] = { 1.0, // sqrt(2) factor left out here... NC_COS1SQRT2, NC_COS2SQRT2, NC_COS3SQRT2, NC_COS4SQRT2, // cos(4*pi/16) * sqrt(2) = 1.0 exactly NC_COS5SQRT2, NC_COS6SQRT2, NC_COS7SQRT2 }; for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) aanscales[(i << 3) + j] = 1.0 / (aansf[i] * aansf[j] * 8.0); } /* * Perform a floating point forward DCT on one block of samples. */ // computes A'=A-B // B'=A+B #define ADDDIFF(A,B) { double x=A; A-=B; B+=x; } #define MMXADDDIFF_Wt(A,B,C) \ movq_r2r (A,C); \ psubw_r2r(B,A); \ paddw_r2r(C,B); #define MMXADDDIFF_Dt(A,B,C) \ movq_r2r (A,C); \ psubd_r2r(B,A); \ paddd_r2r(C,B); #define SSEADDDIFF_t(A,B,C) \ movaps_r2r(A,C); \ subps_r2r(B,A); \ addps_r2r(C,B); #define SSEADDDIFF(x,y) \ subps_r2r(y, x); \ addps_r2r(y, y); \ addps_r2r(x, y); #define MMXEXTEND_WD(S,DL,DH) \ movq_r2r(S, DL); \ movq_r2r(S, DH); \ psraw_i2r(16, S); \ punpcklwd_r2r(S, DL); \ punpckhwd_r2r(S, DH); #define LOADROTATEff(src, t, x0, x1, x2, x3) \ movaps_m2r((src)[ 0], x0); /* 0a 1a 2a 3a */ \ movaps_m2r((src)[ 8], t); /* 0b 1b 2b 3b */ \ movaps_m2r((src)[16], x3); /* 0c 1c 2c 3c */ \ movaps_m2r((src)[24], x1); /* 0d 1d 2d 3d */ \ \ /* mm0 = 0a 0b 1a 1b */ \ /* mm2 = 2a 2b 3a 3b */ \ movaps_r2r (x0, x2); \ unpcklps_r2r(t, x0); \ unpckhps_r2r(t, x2); \ \ /* mm3 = 0c 0d 1c 1d */ \ /* mmt = 2c 2d 3c 3d */ \ movaps_r2r (x3, t); \ unpcklps_r2r(x1, x3); \ unpckhps_r2r(x1, t); \ \ /* mm0 = 0a 0b 0c 0d */ \ /* mm1 = 1a 1b 1c 1d */ \ movaps_r2r (x3, x1); \ movhlps_r2r(x0, x1); \ movlhps_r2r(x3, x0); \ \ /* mm2 = 2a 2b 2c 2d */ \ /* mm3 = 3a 3b 3c 3d */ \ movaps_r2r ( t, x3); \ movhlps_r2r(x2, x3); \ movlhps_r2r( t, x2); #define STOREXMM(x0, offs) \ mulps_m2r(aanptr[offs], x0); \ cvtps2pi_r2r(x0, mm0); \ movhlps_r2r (x0, x0); \ cvtps2pi_r2r(x0, mm1); \ packssdw_r2r(mm1, mm0); \ movq_r2m (mm0, blkptr[offs]); #if 0 void fdct_basis(int16_t *block) { double tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; double tmp10, tmp11, tmp12, tmp13; double z1, z2, z3, z4, z5, z11, z13; double *dataptr; double data[64]; int16_t *blkptr; int i; // each iteration basically performs the following code: blkptr = block; dataptr = data; for (i = 0; i < 8; i++) { tmp4 = blkptr[0] + blkptr[7]; tmp0 = blkptr[0] - blkptr[7]; tmp5 = blkptr[1] + blkptr[6]; tmp1 = blkptr[1] - blkptr[6]; tmp6 = blkptr[2] + blkptr[5]; tmp2 = blkptr[2] - blkptr[5]; tmp7 = blkptr[3] + blkptr[4]; tmp3 = blkptr[3] - blkptr[4]; /* Even part */ ADDDIFF(tmp4,tmp7); ADDDIFF(tmp5,tmp6); ADDDIFF(tmp7,tmp6); dataptr[0] = tmp6; /* phase 3 */ dataptr[4] = tmp7; tmp5+=tmp4; tmp5 = tmp5 * ((double) NC_R_SQRT2); /* c4 */ ADDDIFF(tmp4,tmp5); dataptr[2] = tmp5; /* phase 5 */ dataptr[6] = tmp4; /* Odd part */ tmp3 = tmp3 + tmp2; /* phase 2 */ tmp2 = tmp2 + tmp1; tmp1 = tmp1 + tmp0; /* The rotator is modified from fig 4-8 to avoid extra negations. */ z5 = (tmp3 - tmp1) * ((double) NC_COS6); /* c6 */ tmp3 = ((double) NC_COS6SQRT2) * tmp3 + z5; /* c2-c6 */ tmp1 = ((double) NC_COS2SQRT2) * tmp1 + z5; /* c2+c6 */ tmp2 = tmp2 * ((double) NC_R_SQRT2); /* c4 */ ADDDIFF(tmp0,tmp2); ADDDIFF(tmp0,tmp3); ADDDIFF(tmp2,tmp1); dataptr[5] = tmp3; /* phase 6 */ dataptr[3] = tmp0; dataptr[1] = tmp1; dataptr[7] = tmp2; dataptr += 8; /* advance pointer to next row */ blkptr += 8; } } #endif void fdct_sse(int16_t *block) { float *dataptr,*aanptr; float data[64] __attribute__((aligned(16))); int16_t *blkptr; int i; /* Pass 1: process rows. */ blkptr = block; dataptr = data; for (i = 0; i < 2; i++) { // mm0=0a,1a,2a,3a // mm1=4a,5a,6a,7a // mm2=0b,1b,2b,3b // mm3=4b,5b,6b,7b movq_m2r(blkptr[16], mm0); movq_m2r(blkptr[20], mm1); movq_m2r(blkptr[24], mm2); movq_m2r(blkptr[28], mm3); pshufw_r2ri(mm1, mm1, SHUFFLEMAP(3,2,1,0)); pshufw_r2ri(mm3, mm3, SHUFFLEMAP(3,2,1,0)); MMXADDDIFF_Wt(mm0, mm1, mm4); MMXADDDIFF_Wt(mm2, mm3, mm5); // mm1=4a,4b,5a,5b // mm4=7a,7b,6a,6b movq_r2r(mm1, mm4); punpcklwd_r2r(mm3, mm1); punpckhwd_r2r(mm3, mm4); pshufw_r2ri(mm4, mm4, SHUFFLEMAP(2,3,0,1)); MMXADDDIFF_Wt(mm1, mm4, mm3); // mm6 = 6a,6b // mm7 = 7a,7b MMXEXTEND_WD(mm4, mm7, mm6); MMXADDDIFF_Dt(mm7, mm6, mm4); cvtpi2ps_r2r( mm6, xmm2 ); cvtpi2ps_r2r( mm7, xmm3 ); movlps_r2m( xmm2, dataptr[0*8+2] ); movlps_r2m( xmm3, dataptr[4*8+2] ); // mm6 = 4a,4b // mm7 = 5a,5b MMXEXTEND_WD(mm1, mm6, mm7); paddd_r2r( mm6, mm7 ); cvtpi2ps_r2r( mm6, xmm0 ); cvtpi2ps_r2r( mm7, xmm1 ); // mm0 = 0a,0b,1a,1b // mm1 = 2a,2b,3a,3b movq_r2r(mm0, mm1); punpcklwd_r2r(mm2, mm0); punpckhwd_r2r(mm2, mm1); // mm4 = 0a,0b // mm5 = 1a,1b // mm6 = 2a,2b // mm7 = 3a,3b MMXEXTEND_WD(mm0, mm4, mm5); MMXEXTEND_WD(mm1, mm6, mm7); cvtpi2ps_r2r( mm4, xmm4 ); paddd_r2r( mm6, mm7 ); cvtpi2ps_r2r( mm7, xmm7 ); paddd_r2r( mm5, mm6 ); cvtpi2ps_r2r( mm6, xmm6 ); paddd_r2r( mm4, mm5 ); cvtpi2ps_r2r( mm5, xmm5 ); movlhps_r2r( xmm0, xmm0 ); movlhps_r2r( xmm1, xmm1 ); movlhps_r2r( xmm4, xmm4 ); movlhps_r2r( xmm5, xmm5 ); movlhps_r2r( xmm6, xmm6 ); movlhps_r2r( xmm7, xmm7 ); // mm0=0a,1a,2a,3a // mm1=4a,5a,6a,7a // mm2=0b,1b,2b,3b // mm3=4b,5b,6b,7b movq_m2r(blkptr[ 0], mm0); movq_m2r(blkptr[ 4], mm1); movq_m2r(blkptr[ 8], mm2); movq_m2r(blkptr[12], mm3); pshufw_r2ri(mm1, mm1, SHUFFLEMAP(3,2,1,0)); pshufw_r2ri(mm3, mm3, SHUFFLEMAP(3,2,1,0)); MMXADDDIFF_Wt(mm0, mm1, mm4); MMXADDDIFF_Wt(mm2, mm3, mm5); // mm1=4a,4b,5a,5b // mm4=7a,7b,6a,6b movq_r2r(mm1, mm4); punpcklwd_r2r(mm3, mm1); punpckhwd_r2r(mm3, mm4); pshufw_r2ri(mm4, mm4, SHUFFLEMAP(2,3,0,1)); MMXADDDIFF_Wt(mm1, mm4, mm3); // mm6 = 6a,6b // mm7 = 7a,7b MMXEXTEND_WD(mm4, mm7, mm6); MMXADDDIFF_Dt(mm7, mm6, mm4); cvtpi2ps_r2r( mm6, xmm2 ); cvtpi2ps_r2r( mm7, xmm3 ); movlps_r2m( xmm2, dataptr[0*8+0] ); movlps_r2m( xmm3, dataptr[4*8+0] ); // mm6 = 4a,4b // mm7 = 5a,5b MMXEXTEND_WD(mm1, mm6, mm7); paddd_r2r( mm6, mm7 ); cvtpi2ps_r2r( mm6, xmm0 ); cvtpi2ps_r2r( mm7, xmm1 ); // mm0 = 0a,0b,1a,1b // mm1 = 2a,2b,3a,3b movq_r2r(mm0, mm1); punpcklwd_r2r(mm2, mm0); punpckhwd_r2r(mm2, mm1); // mm4 = 0a,0b // mm5 = 1a,1b // mm6 = 2a,2b // mm7 = 3a,3b MMXEXTEND_WD(mm0, mm4, mm5); MMXEXTEND_WD(mm1, mm6, mm7); cvtpi2ps_r2r( mm4, xmm4 ); paddd_r2r( mm6, mm7 ); cvtpi2ps_r2r( mm7, xmm7 ); paddd_r2r( mm5, mm6 ); cvtpi2ps_r2r( mm6, xmm6 ); paddd_r2r( mm4, mm5 ); cvtpi2ps_r2r( mm5, xmm5 ); // z1 = (tmp11 + tmp10) * ((double) NC_R_SQRT2); /* c4 */ // dataptr[2] = tmp10 + z1; /* phase 5 */ // dataptr[6] = tmp10 - z1; mulps_m2r(fdct_sse_r_sqrt2[0],xmm1); SSEADDDIFF_t(xmm0, xmm1, xmm2); movaps_r2m( xmm0, dataptr[6*8] ); movaps_r2m( xmm1, dataptr[2*8] ); /* The rotator is modified from fig 4-8 to avoid extra negations. */ // z5 = (tmp7 - tmp5) * ((double) NC_COS6); /* c6 */ movaps_r2r( xmm7, xmm2 ); subps_r2r( xmm5, xmm2 ); mulps_m2r(fdct_sse_cos6[0], xmm2 ); // tmp7 = ((double) NC_COS6SQRT2) * tmp7 + z5; /* c2-c6 */ // tmp5 = ((double) NC_COS2SQRT2) * tmp5 + z5; /* c2+c6 */ // tmp6 = tmp6 * ((double) NC_R_SQRT2); /* c4 */ mulps_m2r(fdct_sse_cos6sqrt2[0], xmm7); mulps_m2r(fdct_sse_cos2sqrt2[0], xmm5); mulps_m2r(fdct_sse_r_sqrt2[0], xmm6 ); addps_r2r(xmm2, xmm7); addps_r2r(xmm2, xmm5); // z16 = tmp4 + tmp6; /* phase 5 */ // z14 = tmp4 - tmp6; SSEADDDIFF_t(xmm4, xmm6, xmm2); SSEADDDIFF_t(xmm4, xmm7, xmm2); SSEADDDIFF_t(xmm6, xmm5, xmm2); // dataptr[5] = z14 + tmp7; /* phase 6 */ // dataptr[3] = z14 - tmp7; // dataptr[1] = z16 + tmp5; // dataptr[7] = z16 - tmp5; movaps_r2m( xmm7, dataptr[5*8] ); movaps_r2m( xmm4, dataptr[3*8] ); movaps_r2m( xmm5, dataptr[1*8] ); movaps_r2m( xmm6, dataptr[7*8] ); dataptr += 4; /* advance pointer to next row */ blkptr += 8*4; } /* Pass 2: process columns. */ dataptr = data; aanptr = aanscales; blkptr = block; for (i = 0; i < 2; i++) { LOADROTATEff(dataptr, xmm4, xmm0, xmm1, xmm2, xmm3); movaps_r2m(xmm0, dataptr[0]); LOADROTATEff(dataptr+4, xmm0, xmm7, xmm6, xmm5, xmm4); movaps_m2r(dataptr[0], xmm0); SSEADDDIFF(xmm0,xmm4); SSEADDDIFF(xmm1,xmm5); SSEADDDIFF(xmm2,xmm6); SSEADDDIFF(xmm3,xmm7); /* Even part */ SSEADDDIFF(xmm4, xmm7); SSEADDDIFF(xmm5, xmm6); SSEADDDIFF(xmm7, xmm6); STOREXMM(xmm6,0); STOREXMM(xmm7,32); addps_r2r(xmm4, xmm5); mulps_m2r(fdct_sse_r_sqrt2[0],xmm5); SSEADDDIFF_t(xmm4, xmm5, xmm6); STOREXMM(xmm5,16); STOREXMM(xmm4,48); /* Odd part */ addps_r2r(xmm2, xmm3); addps_r2r(xmm1, xmm2); addps_r2r(xmm0, xmm1); /* The rotator is modified from fig 4-8 to avoid extra negations. */ movaps_r2r(xmm3, xmm4); subps_r2r(xmm1, xmm4); mulps_m2r(fdct_sse_cos6[0], xmm4); mulps_m2r(fdct_sse_cos6sqrt2[0], xmm3); mulps_m2r(fdct_sse_cos2sqrt2[0], xmm1); mulps_m2r(fdct_sse_r_sqrt2[0], xmm2); addps_r2r(xmm4, xmm3); addps_r2r(xmm4, xmm1); SSEADDDIFF_t(xmm0, xmm2, xmm5); SSEADDDIFF_t(xmm0, xmm3, xmm6); STOREXMM(xmm0,24); STOREXMM(xmm3,40); SSEADDDIFF_t(xmm2, xmm1, xmm7); STOREXMM(xmm2,56); STOREXMM(xmm1, 8); dataptr+=4*8; /* advance pointer to next column */ aanptr+=4; blkptr+=4; } emms(); } mjpegtools-2.1.0/mpeg2enc/picture.hh0000644000175000017500000001731311456612024017713 0ustar glowwormglowworm /* (C) 2000/2001/2002 Andrew Stevens */ /* This is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #ifndef _PICTURE_HH #define _PICTURE_HH #include "mjpeg_types.h" #include "encoderparams.hh" #include "synchrolib.h" #include "macroblock.hh" #include #include "mpeg2syntaxcodes.h" using namespace std; /* Transformed per-picture data */ typedef int MotionVecPred[2][2][2]; typedef int DC_DctPred[3]; class CodingPredictors { public: void Reset_DC_DCT_Pred() { int cc; for (cc=0; cc<3; cc++) dc_dct_pred[cc] = 0; } void Reset_MV_Pred() { int *base=&PMV[0][0][0]; int v; for( v = 0; v < 2*2*2; ++v) base[v]=0; } DC_DctPred dc_dct_pred; MotionVecPred PMV; MacroBlock *prev_mb; }; class RateCtl; class Quantizer; class StreamState; class ElemStrmWriter; class MPEG2CodingBuf; class ImagePlanes; class Picture : public CodingPredictors { public: Picture( EncoderParams &_encparams, ElemStrmWriter &writer, Quantizer &_quantizer ); ~Picture(); void QuantiseAndCode(RateCtl &ratecontrol); void MotionSubSampledLum(); void ITransform(); void IQuantize(); void CalcSNR(); void Stats(); void Reconstruct(); void CommitCoding(); void DiscardCoding(); void SetFrameParams( const StreamState &ss, int field ); // Metrics used for stearing the encoding inline double Complexity() const { return Xhi; } void SetComplexity( double _Xhi ) { Xhi = _Xhi; } int EncodedSize() const; double IntraCodedBlocks() const; // Proportion of Macroblocks coded Intra void PutHeaders(); // Picture/Gop/Sequence headers void PutTrailers( int padding ); // Stuff after picture but before next picture void PutHeader(); double ActivityBestMotionComp(); double VarSumBestMotionComp(); double VarSumBestFwdMotionComp(); double MinVarBestMotionComp(); // // inline bool Legal( const MotionVector &mv ) const { return mv[Dim::X] >= -sxf && mv[Dim::X] < sxf && mv[Dim::Y] >= -syf && mv[Dim::Y] < syf; } inline bool InRangeFrameMVRef( const Coord &crd ) const { return crd.x >= 0 && crd.x <= (encparams.enc_width-16)*2 && crd.y >= 0 && crd.y <= (encparams.enc_height-16)*2; } inline bool InRangeFieldMVRef( const Coord &crd ) const { return crd.x >= 0 && crd.x <= (encparams.enc_width-16)*2 && crd.y >= 0 && crd.y <= (encparams.enc_height/2-16)*2; } inline bool FinalFieldOfRefFrame() const { return pict_type != B_TYPE && finalfield; } protected: void SetFieldParams(int field); void PutSliceHdr( int slice_mb_y, int mquant ); void PutMVs( MotionEst &me, bool back ); void PutDCTBlocks( MacroBlock &mb, int mb_type ); void PutCodingExt(); bool SkippableMotionMode( MotionEst &cur_mb_mm, MotionEst &prev_mb_mm); public: /*************** * * Data areas allocated at construction * **************/ EncoderParams &encparams; Quantizer &quantizer; MPEG2CodingBuf *coding; /* 8*8 block data, raw (unquantised) and quantised, and (eventually but not yet inverse quantised */ DCTblock *blocks; DCTblock *qblocks; /* Macroblocks of picture */ vector mbinfo; /*************** * * Data update as picture is re-used for different images in streams * **************/ int decode; // Number of frame in stream int present; // Number of frame in playback order // == Number of frame in input stream bool last_picture; // Last Picture of a stream bool finalfield; // Last field of a frame /* multiple-reader/single-writer channels Synchronisation sync only: no data is "read"/"written" */ Picture *fwd_ref_frame; Picture *bwd_ref_frame; // 0 if Not B_TYPE /* picture encoding source data */ ImagePlanes *fwd_org, *bwd_org; // Original Images of fwd and bwd // reference pictures ImagePlanes *fwd_rec, *bwd_rec; // Reconstructed Images for fwd and // bwd references pictures ImagePlanes *org_img, *rec_img; // Images for current pict: orginal // and reconstructed. Reconstructed // 0 for B planes except when debugging ImagePlanes *pred; int sxf, syf, sxb, syb; /* MC search limits. */ bool secondfield; /* Second field of field frame */ bool ipflag; /* P pict in IP frame (FIELD pics only)*/ /* picture structure (header) data */ int temp_ref; /* temporal reference */ PICTURE_CODING frame_type; /* picture coding type for frame (I, P or B) */ int gop_decode; /* Frame number in gop (decode order) */ int bgrp_decode; /* Frame number in 'B group' (decode order) */ PICTURE_CODING pict_type; /* picture coding type for current field (I, P or B) */ int vbv_delay; /* video buffering verifier delay (1/90000 seconds) */ int forw_hor_f_code, forw_vert_f_code; int back_hor_f_code, back_vert_f_code; /* motion vector ranges */ int dc_prec; /* DC coefficient prec for intra blocks */ PICTURE_STRUCT pict_struct; /* picture structure (frame, top / bottom) */ int topfirst; /* display top field first */ bool frame_pred_dct; /* Use only frame prediction... */ int intravlc; /* Intra VLC format */ int q_scale_type; /* Quantiser scale... */ bool altscan; /* Alternate scan pattern selected */ const uint8_t *scan_pattern; /* The scan pattern itself */ bool repeatfirst; /* repeat first field after second field */ bool prog_frame; /* progressive frame */ int unit_coeff_threshold; // Unit coefficient density weight // below which zeroing should be applied. int unit_coeff_first; // First coefficient for zeroing purposes... // either 1 or 0. /* Information for GOP start frames */ bool gop_start; /* GOP Start picture */ bool closed_gop; /* GOP is closed */ int nb; /* B frames in GOP */ int np; /* P frames in GOP */ bool new_seq; /* GOP starts new sequence */ bool end_seq; /* Frame ends sequence */ double Xhi; /* Complexity ... product of bits needed to code and quantisation */ /* Rate control statistics */ double AQ; // Mean actual quantisation of encoding (if any) double ABQ; // Mean base quantisation of encoding (if any) /* Statistics... */ int pad; //int split; double SQ; double avg_act; double sum_avg_act; }; /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ #endif mjpegtools-2.1.0/mpeg2enc/rate_complexity_model.cc0000644000175000017500000002236211442756174022630 0ustar glowwormglowworm// // C++ Interface: rate_complexity_model // // Description: Bit-rate / complexity statistics model of input stream // This is used to figure out nominal target bit-rate that should be // set overall bit-rate (== size) target of the sequence given // a specified quantisation floor... // // // Author: Andrew Stevens , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "rate_complexity_model.hh" #include "cpu_accel.h" #include #include #include /* (C) 2000-2004 Andrew Stevens */ /* This is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ //=============================================================================================== // BucketSetSampling - Representation of Statistical distribution based on maintaining a bounded set // of buckets each covering a particular sub-range with a mean // class BucketSetSampling { protected: class Bucket { private: Bucket(); // forbidden public: Bucket( double sample ) : sum( sample ) , min( sample ) , max( sample ) , samples( 1.0 ) { } double Mean() const { return sum / samples; } double Samples() const { return samples; } double sum; double min; double max; double samples; }; public: typedef std::vector BucketVector; BucketSetSampling( unsigned int size_limit ) : m_size_max( size_limit ) { } BucketVector &Buckets() { return buckets; } /************* * * AddSample - Extend statistical distribution model with a new sample * ************/ void AddSample( double sample ) { if( buckets.size() < m_size_max ) { // Until the sample bucket set reaches the specizied maximum size // every statistic is inserted into its own 'sample bucket'. InsertSingleSampleBucket( sample ); } else { // Once the specified bucket set size is reached each statistic is // either inserted into a bucket within whose min/max range it fits // or two buckets are merged to make space for a single-sample bucket. CombineBucket( sample ); } } protected: static double NeighbourDistance( std::vector::iterator l) { // As 'distance' we use the product of the sum of the seperation // mean seperation multiplied by the log of the samples involved. // The idea is to keep seperate buckets that either cover a large // population or very different image complexities std::vector::iterator r = l + 1; double distance = (r->min - l->max) * log( l->samples + r->samples ) ; return distance; } void InsertSingleSampleBucket( double sample ) { // Binary search for the insertion point for the new single-sample // ub and lb are *inclusive* bounds on the possible insertion point Bucket newbucket( sample ); unsigned int lb = 0 ; unsigned int ub = buckets.size(); while( ub-lb > 0 ) { unsigned int pivot = (ub-lb)/2; if( buckets[pivot].min >= sample ) { ub = pivot; } else { lb = pivot; } } // Insert new sample buckets.insert( buckets.begin() + lb, newbucket ); } void CombineBucket( double sample ) { // Binary search for a bucket // ub and lb are *inclusive* bounds on the range // of buckets that cannot contain the new xhi assert( buckets.size() > 1 ); unsigned int lb = 0 ; unsigned int ub = buckets.size()-1; unsigned int pivot = 0; while( ub-lb > 0 ) { pivot = (ub-lb)/2; if( buckets[pivot].min > sample ) { ub = pivot; } else if( buckets[pivot].max < sample ) { lb = pivot; } else { // Containing bucket found!! break; } } // No containing bucket found? ==> Make space by mergeing // neighbours producing smallest variance in combined bucket if( ub-lb == 0 ) { MergeClosestNeighbours(); Bucket newbucket( sample ); buckets.insert( buckets.begin()+lb, newbucket ); } else { Bucket &bucket = buckets[pivot]; bucket.sum += sample; bucket.samples += 1.0; } } void MergeClosestNeighbours() { assert( buckets.size() > 1 ); // // Find the closest neighbours according to the 'NeighbourDistance' // metric std::vector::iterator i,last,min_dist_i; double min_dist = std::numeric_limits::max(); for( i = buckets.begin(); i+1 < buckets.end(); ++i ) { double dist = NeighbourDistance( i ); if( dist < min_dist ) { min_dist = dist; min_dist_i = i; } } // Merge the neighbours! std::vector::iterator m1 = min_dist_i+1; min_dist_i->sum += m1->sum; min_dist_i->max = m1->max; min_dist_i->samples += m1->samples; buckets.erase(m1); } protected: unsigned m_size_max; BucketVector buckets; }; //=============================================================================================== // RateComplexityModel - Model of rate / complexity behaviour of encoded MPEG video sequence // // TODO: Allocation function (calculates allocated bits from complexity metric) // is currently hard-wired. // RateComplexityModel::RateComplexityModel() : m_model( new BucketSetSampling( SAMPLING_POINTS ) ) , m_total_xhi( 0.0 ) , m_mean_xhi( 1.0 ) , m_max_bitrate( 0.0 ) { } RateComplexityModel::~RateComplexityModel() { delete m_model; } void RateComplexityModel::SetRateControlParams( double max_bitrate, double allocation_exp ) { m_max_bitrate = max_bitrate; m_allocation_exp = allocation_exp; } void RateComplexityModel::AddComplexitySample( double xhi ) { m_model->AddSample( xhi ); m_total_xhi += xhi; m_num_samples += 1; m_mean_xhi = m_total_xhi / m_num_samples; } /********************************************* * * FrameBitRate - Calculate the bitrate for bit-allocation * for a frame of complexity \c xhi from \c control_bitrate * approximating * ***********************************************/ double RateComplexityModel::FrameBitRate( double xhi, double control_bitrate ) { return fmin( control_bitrate * xhi * pow( xhi/m_mean_xhi, m_allocation_exp ), m_max_bitrate ); } /********************************************* * * PredictedBitrate - Calculate the expected bitrate based * on the complexity statistics * ***********************************************/ double RateComplexityModel::PredictedBitrate( double control_bitrate) { BucketSetSampling::BucketVector &buckets = m_model->Buckets(); BucketSetSampling::BucketVector::iterator i; double sum_rates = 0.0; for( i = buckets.begin(); i < buckets.end(); ++i ) { sum_rates += FrameBitRate( i->Mean(), control_bitrate ) * i->Samples(); } return sum_rates / m_num_samples; } /********************************************* * * UpdateRateCoefficient Find the rate-coefficient for * which a sequence with the measured statistics should * produce the target bitrate * ***********************************************/ double RateComplexityModel::FindControlBitrate( double target_bitrate, double init_control_bitrate, double tolerance ) { double control_bitrate = init_control_bitrate; double rate = PredictedBitrate(control_bitrate); // Find the correct initial direction and a reasonable initial step-size // for the search double delta = init_control_bitrate * (target_bitrate-rate)/target_bitrate; // PredictedBitrate is monotonic in the rate coefficient... for(;;) { if( fabs( rate - target_bitrate ) / target_bitrate < tolerance ) return control_bitrate; double new_rate = PredictedBitrate(control_bitrate+delta); if( fabs(new_rate-target_bitrate) < fabs( rate - target_bitrate ) ) { control_bitrate += delta; rate = new_rate; // If sign of difference changes we need a smaller step in reverse // direction next time... // N.b. If the sign is the same we retain the current step in case // the solution is too far to reach in less that the current step size. if( (new_rate-target_bitrate < 0) ^ (rate-target_bitrate < 0) ) { delta = - delta / 2.0; } } else { // If the solution didn't improve we've over-shot and need a smaller step-size delta /= 2.0; } } } mjpegtools-2.1.0/mpeg2enc/seqencoder.hh0000644000175000017500000001300410747735115020372 0ustar glowwormglowworm#ifndef _SEQENCODER_HH #define _SEQENCODER_HH /* (C) 2000/2001/2005 Andrew Stevens */ /* This Software is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include #include "mjpeg_types.h" #include "picture.hh" #include "streamstate.h" class MPEG2Encoder; class EncoderParams; class MPEG2CodingBuf; class PictureReader; class Despatcher; class RateCtlState; class Pass1RateCtl; class Pass2RateCtl; class SeqEncoder { public: SeqEncoder( EncoderParams &encparams, PictureReader &reader, Quantizer &quantizer, ElemStrmWriter &writer, Pass1RateCtl &pass1ratectl, Pass2RateCtl &pass2ratectl ); ~SeqEncoder(); /********************************** * * Setup ready to start encoding once parameter objects have * (where relevant) been Init-ed. * *********************************/ void Init(); /********************************** * * Encode Stream setup during Init * *********************************/ void EncodeStream(); /********************************** * * Do a unit of encocoding: Pass1 encode * a buffered frame (if available) * Pass2 encode a buffered Pass1 encoded * frame if enough are buffer. * *********************************/ void EncodeStreamOneStep(); /********************************** * * There are still Pass1-coded frames * buffered remaining to be committed for Pass2 * or pass-2 coded. * * NOTE: Result is only correct * when called AFTER * EncodeStreamOneStep(). * *********************************/ bool EncodeStreamWhile(); /********************************** * * Perform Epilogue to encoding video stream * Ensure all encoding work still being worked on * is completed and flushed. Collects statistics etc etc. * *********************************/ void StreamEnd(); private: /********************************* * * Manage Picture's - they're expensive-ish to allocate so * we maintained a stack already allocated but unused objects. * *********************************/ Picture *GetFreshPicture(); void ReleasePicture( Picture *); /********************************** * * Pass1Process - Unit of pass-1 processing work * generates a pass-1 coded frame ready for pass2 * processing. * *********************************/ void Pass1Process(); /********************************** * * Pass2Process - Unit of pass-2 processing work * Consumes any available pass-1 coded frames ready * for pass2 coding. * If possible generates a frame of coded output. * *********************************/ void Pass2Process(); void Pass1RateCtlSetup( Picture &picture ); void Pass2RateCtlSetup( Picture &picture ); Picture *NextFramePicture0(); Picture *NextFramePicture1(Picture *picture0); void EncodePicture( Picture &picture, RateCtl &ratectl); void RetainPicture( Picture &picture, RateCtl &ratectl); void Pass1GopSplitting( Picture &picture); void Pass1EncodePicture( Picture &picture, int field ); void Pass1ReEncodePicture0( Picture &picture, void (MacroBlock::*modeMotionAdjustFunc)() ); bool Pass2EncodePicture( Picture &picture, bool force_reencode ); uint64_t BitsAfterMux() const; EncoderParams &encparams; PictureReader &reader; Quantizer &quantizer; ElemStrmWriter &writer; Pass1RateCtl &pass1ratectl; Pass2RateCtl &pass2ratectl; // Worker thread despatchers for the two passes // Despatcher &p1_despatcher; //Despatcher &p2_despatcher; // The state of the pass 1 rate controller before encoding. // We need to restore this if we decide to re-encode it in // pass-1 RateCtlState *pass1_rcstate; // Picture's (in decode order) that have been pass1 coded // but are not yet ready to be committed for pass 2 coding... std::deque pass1coded; // Queue of Picture's (in decode order) committed for pass2 encoding std::deque pass2queue; // Picture objects no longer being encoded (signalled by // a called to 'ReleasePicture') but potentially still // referenced by other Picture's and hence not (yet) free // for re-use or destruction. std::deque released_pictures; // Reference frames all of whose field Picture's have been released // ... needed to maintain released_pictures queue. int released_ref_frames; // Picture objects free for re-use. std::vector free_pictures; // Internal state of encoding... StreamState pass1_ss; // Reference pictures in pass-1 Picture *new_ref_picture, *old_ref_picture; }; /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ #endif mjpegtools-2.1.0/mpeg2enc/fdct_mmx.c0000644000175000017500000004571410314351424017666 0ustar glowwormglowworm////////////////////////////////////////////////////////////////////////////// // // fdctam32.c - AP922 MMX(3D-Now) forward-DCT // ---------- // Intel Application Note AP-922 - fast, precise implementation of DCT // http://developer.intel.com/vtune/cbts/appnotes.htm // ---------- // // This routine can use a 3D-Now/MMX enhancement to increase the // accuracy of the fdct_col_4 macro. The dct_col function uses 3D-Now's // PMHULHRW instead of MMX's PMHULHW(and POR). The substitution improves // accuracy very slightly with performance penalty. If the target CPU // does not support 3D-Now, then this function cannot be executed. // // For a fast, precise MMX implementation of inverse-DCT // visit http://www.elecard.com/peter // // v1.0 07/22/2000 (initial release) // // liaor@iname.com http://members.tripod.com/~liaor ////////////////////////////////////////////////////////////////////////////// /* * A.Stevens Jul 2000: ported to nasm syntax and disentangled from * from Win**** compiler specific stuff. * All the real work was done above though. * See above for how to optimise quality on 3DNow! CPU's * Nov 2003 changed to PIC for use in shared libraries * * G.Vervoort Jan 2005: ported to inline asm. */ #include #include "mjpeg_types.h" #include "mmx.h" ////////////////////////////////////////////////////////////////////// // // constants for the forward DCT // ----------------------------- // // Be sure to check that your compiler is aligning all constants to QWORD // (8-byte) memory boundaries! Otherwise the unaligned memory access will // severely stall MMX execution. // ////////////////////////////////////////////////////////////////////// #define BITS_FRW_ACC 3 //; 2 or 3 for accuracy #define SHIFT_FRW_COL BITS_FRW_ACC #define SHIFT_FRW_ROW (BITS_FRW_ACC + 17) //#define RND_FRW_ROW (262144 * (BITS_FRW_ACC - 1)) //; 1 << (SHIFT_FRW_ROW-1) #define RND_FRW_ROW (1 << (SHIFT_FRW_ROW-1)) //#define RND_FRW_COL (2 * (BITS_FRW_ACC - 1)) //; 1 << (SHIFT_FRW_COL-1) #define RND_FRW_COL (1 << (SHIFT_FRW_COL-1)) //concatenated table, for forward DCT transformation static const int16_t fdct_tg_all_16[] ATTR_ALIGN(8) = { 13036, 13036, 13036, 13036, // tg * (2<<16) + 0.5 27146, 27146, 27146, 27146, // tg * (2<<16) + 0.5 -21746, -21746, -21746, -21746, // tg * (2<<16) + 0.5 }; static const int16_t ocos_4_16[4] ATTR_ALIGN(8) = { 23170, 23170, 23170, 23170, //cos * (2<<15) + 0.5 }; static const int64_t fdct_one_corr ATTR_ALIGN(8) = 0x0001000100010001LL; static const int32_t fdct_r_row[2] ATTR_ALIGN(8) = {RND_FRW_ROW, RND_FRW_ROW }; static const int16_t tab_frw_01234567[] ATTR_ALIGN(8) = { // forward_dct coeff table //row0 16384, 16384, 21407, -8867, // w09 w01 w08 w00 16384, 16384, 8867, -21407, // w13 w05 w12 w04 16384, -16384, 8867, 21407, // w11 w03 w10 w02 -16384, 16384, -21407, -8867, // w15 w07 w14 w06 22725, 12873, 19266, -22725, // w22 w20 w18 w16 19266, 4520, -4520, -12873, // w23 w21 w19 w17 12873, 4520, 4520, 19266, // w30 w28 w26 w24 -22725, 19266, -12873, -22725, // w31 w29 w27 w25 //row1 22725, 22725, 29692, -12299, // w09 w01 w08 w00 22725, 22725, 12299, -29692, // w13 w05 w12 w04 22725, -22725, 12299, 29692, // w11 w03 w10 w02 -22725, 22725, -29692, -12299, // w15 w07 w14 w06 31521, 17855, 26722, -31521, // w22 w20 w18 w16 26722, 6270, -6270, -17855, // w23 w21 w19 w17 17855, 6270, 6270, 26722, // w30 w28 w26 w24 -31521, 26722, -17855, -31521, // w31 w29 w27 w25 //row2 21407, 21407, 27969, -11585, // w09 w01 w08 w00 21407, 21407, 11585, -27969, // w13 w05 w12 w04 21407, -21407, 11585, 27969, // w11 w03 w10 w02 -21407, 21407, -27969, -11585, // w15 w07 w14 w06 29692, 16819, 25172, -29692, // w22 w20 w18 w16 25172, 5906, -5906, -16819, // w23 w21 w19 w17 16819, 5906, 5906, 25172, // w30 w28 w26 w24 -29692, 25172, -16819, -29692, // w31 w29 w27 w25 //row3 19266, 19266, 25172, -10426, // w09 w01 w08 w00 19266, 19266, 10426, -25172, // w13 w05 w12 w04 19266, -19266, 10426, 25172, // w11 w03 w10 w02 -19266, 19266, -25172, -10426, // w15 w07 w14 w06, 26722, 15137, 22654, -26722, // w22 w20 w18 w16 22654, 5315, -5315, -15137, // w23 w21 w19 w17 15137, 5315, 5315, 22654, // w30 w28 w26 w24 -26722, 22654, -15137, -26722, // w31 w29 w27 w25, //row4 16384, 16384, 21407, -8867, // w09 w01 w08 w00 16384, 16384, 8867, -21407, // w13 w05 w12 w04 16384, -16384, 8867, 21407, // w11 w03 w10 w02 -16384, 16384, -21407, -8867, // w15 w07 w14 w06 22725, 12873, 19266, -22725, // w22 w20 w18 w16 19266, 4520, -4520, -12873, // w23 w21 w19 w17 12873, 4520, 4520, 19266, // w30 w28 w26 w24 -22725, 19266, -12873, -22725, // w31 w29 w27 w25 //row5 19266, 19266, 25172, -10426, // w09 w01 w08 w00 19266, 19266, 10426, -25172, // w13 w05 w12 w04 19266, -19266, 10426, 25172, // w11 w03 w10 w02 -19266, 19266, -25172, -10426, // w15 w07 w14 w06 26722, 15137, 22654, -26722, // w22 w20 w18 w16 22654, 5315, -5315, -15137, // w23 w21 w19 w17 15137, 5315, 5315, 22654, // w30 w28 w26 w24 -26722, 22654, -15137, -26722, // w31 w29 w27 w25 //row6 21407, 21407, 27969, -11585, // w09 w01 w08 w00 21407, 21407, 11585, -27969, // w13 w05 w12 w04 21407, -21407, 11585, 27969, // w11 w03 w10 w02 -21407, 21407, -27969, -11585, // w15 w07 w14 w06, 29692, 16819, 25172, -29692, // w22 w20 w18 w16 25172, 5906, -5906, -16819, // w23 w21 w19 w17 16819, 5906, 5906, 25172, // w30 w28 w26 w24 -29692, 25172, -16819, -29692, // w31 w29 w27 w25, //row7 22725, 22725, 29692, -12299, // w09 w01 w08 w00 22725, 22725, 12299, -29692, // w13 w05 w12 w04 22725, -22725, 12299, 29692, // w11 w03 w10 w02 -22725, 22725, -29692, -12299, // w15 w07 w14 w06, 31521, 17855, 26722, -31521, // w22 w20 w18 w16 26722, 6270, -6270, -17855, // w23 w21 w19 w17 17855, 6270, 6270, 26722, // w30 w28 w26 w24 -31521, 26722, -17855, -31521 // w31 w29 w27 w25 }; #define x0 (inp + 0*8) #define x1 (inp + 1*8) #define x2 (inp + 2*8) #define x3 (inp + 3*8) #define x4 (inp + 4*8) #define x5 (inp + 5*8) #define x6 (inp + 6*8) #define x7 (inp + 7*8) #define y0 (out + 0*8) #define y1 (out + 1*8) #define y2 (out + 2*8) #define y3 (out + 3*8) #define y4 (out + 4*8) #define y5 (out + 5*8) #define y6 (out + 6*8) #define y7 (out + 7*8) #define round_frw_row fdct_r_row //////////////////////////////////////////////////////////////////////// // // The high-level pseudocode for the fdct_am32() routine : // // fdct_am32() // { // forward_dct_col03(); // dct_column transform on cols 0-3 // forward_dct_col47(); // dct_column transform on cols 4-7 // for ( j = 0; j < 8; j=j+1 ) // forward_dct_row1(j); // dct_row transform on row #j // } // void fdct_mmx(int16_t *blk) { int16_t *inp, *out; int16_t *table; int i; /* transform the left half of the matrix (4 columns) */ out = inp = blk; /* * for ( i = 0; i < 2; i = i + 1) * the for-loop is executed twice. We are better off unrolling the * loop to avoid branch misprediction. * .mmx32_fdct_col03: */ movq_m2r(*x1, mm0); /* 0 ; x1 */ movq_m2r(*x6, mm1); /* 1 ; x6 */ movq_r2r(mm0, mm2); /* 2 ; x1 */ movq_m2r(*x2, mm3); /* 3 ; x2 */ paddsw_r2r(mm1, mm0); /* t1 = x[1] + x[6] */ movq_m2r(*x5, mm4); /* 4 ; x5 */ psllw_i2r(SHIFT_FRW_COL, mm0); /* t1 */ movq_m2r(*x0, mm5); /* 5 ; x0 */ paddsw_r2r(mm3, mm4); /* t2 = x[2] + x[5] */ paddsw_m2r(*x7, mm5); /* t0 = x[0] + x[7] */ psllw_i2r(SHIFT_FRW_COL, mm4); /* t2 */ movq_r2r(mm0, mm6); /* 6 ; t1 */ psubsw_r2r(mm1, mm2); /* 1 ; t6 = x[1] - x[6] */ movq_m2r(*(fdct_tg_all_16 + 4), mm1); /* 1 ; tg_2_16 */ psubsw_r2r(mm4, mm0); /* tm12 = t1 - t2 */ movq_m2r(*x3, mm7); /* x3 */ pmulhw_r2r(mm0, mm1); /* tm12*tg_2_16 */ paddsw_m2r(*x4, mm7); /* t3 = x[3] + x[4] */ psllw_i2r(SHIFT_FRW_COL, mm5); /* t0 */ paddsw_r2r(mm4, mm6); /* 4 ; tp12 = t1 + t2 */ psllw_i2r(SHIFT_FRW_COL, mm7); /* t3 */ movq_r2r(mm5, mm4); /* 4 ; t0 */ psubsw_r2r(mm7, mm5); /* tm03 = t0 - t3 */ paddsw_r2r(mm5, mm1); /* y2 = tm03 + tm12*tg_2_16 */ paddsw_r2r(mm7, mm4); /* 7 ; tp03 = t0 + t3 */ por_m2r(fdct_one_corr, mm1); /* correction y2 +0.5 */ psllw_i2r(SHIFT_FRW_COL+1, mm2); /* t6 */ pmulhw_m2r(*(fdct_tg_all_16 + 4), mm5); /* tm03*tg_2_16 */ movq_r2r(mm4, mm7); /* 7 ; tp03 */ psubsw_m2r(*x5, mm3); /* t5 = x[2] - x[5] */ psubsw_r2r(mm6, mm4); /* y4 = tp03 - tp12 */ movq_r2m(mm1, *y2); /* 1 ; save y2 */ paddsw_r2r(mm6, mm7); /* 6 ; y0 = tp03 + tp12 */ movq_m2r(*x3, mm1); /* 1 ; x3 */ psllw_i2r(SHIFT_FRW_COL+1, mm3); /* t5 */ psubsw_m2r(*x4, mm1); /* t4 = x[3] - x[4] */ movq_r2r(mm2, mm6); /* 6 ; t6 */ movq_r2m(mm4, *y4); /* 4 ; save y4 */ paddsw_r2r(mm3, mm2); /* t6 + t5 */ pmulhw_m2r(*ocos_4_16, mm2); /* tp65 = (t6 + t5)*cos_4_16 */ psubsw_r2r(mm3, mm6); /* 3 ; t6 - t5 */ pmulhw_m2r(*ocos_4_16, mm6); /* tm65 = (t6 - t5)*cos_4_16 */ psubsw_r2r(mm0, mm5); /* 0 ; y6 = tm03*tg_2_16 - tm12 */ por_m2r(fdct_one_corr, mm5); /* correction y6 +0.5 */ psllw_i2r(SHIFT_FRW_COL, mm1); /* t4 */ por_m2r(fdct_one_corr, mm2); /* correction tp65 +0.5 */ movq_r2r(mm1, mm4); /* 4 ; t4 */ movq_m2r(*x0, mm3); /* 3 ; x0 */ paddsw_r2r(mm6, mm1); /* tp465 = t4 + tm65 */ psubsw_m2r(*x7, mm3); /* t7 = x[0] - x[7] */ psubsw_r2r(mm6, mm4); /* 6 ; tm465 = t4 - tm65 */ movq_m2r(*(fdct_tg_all_16 + 0), mm0); /* 0 ; tg_1_16 */ psllw_i2r(SHIFT_FRW_COL, mm3); /* t7 */ movq_m2r(*(fdct_tg_all_16 + 8), mm6); /* 6 ; tg_3_16 */ pmulhw_r2r(mm1, mm0); /* tp465*tg_1_16 */ movq_r2m(mm7, *y0); /* 7 ; save y0 */ pmulhw_r2r(mm4, mm6); /* tm465*tg_3_16 */ movq_r2m(mm5, *y6); /* save y6 */ movq_r2r(mm3, mm7); /* t7 */ movq_m2r(*(fdct_tg_all_16 + 8), mm5); /* 5 ; tg_3_16 */ psubsw_r2r(mm2, mm7); /* tm765 = t7 - tp65 */ paddsw_r2r(mm2, mm3); /* 2 ; tp765 = t7 + tp65 */ pmulhw_r2r(mm7, mm5); /* tm765*tg_3_16 */ paddsw_r2r(mm3, mm0); /* y1 = tp765 + tp465*tg_1_16 */ paddsw_r2r(mm4, mm6); /* tm465*tg_3_16 */ pmulhw_m2r(*(fdct_tg_all_16 + 0), mm3); /* tp765*tg_1_16 */ por_m2r(fdct_one_corr, mm0); /* correction y1 +0.5 */ paddsw_r2r(mm7, mm5); /* tm765*tg_3_16 */ psubsw_r2r(mm6, mm7); /* 6 ; y3 = tm765 - tm465*tg_3_16 */ inp += 4; /* increment pointer */ movq_r2m(mm0, *y1); /* 0 ; save y1 */ paddsw_r2r(mm4, mm5); /* 4 ; y5 = tm765*tg_3_16 + tm465 */ movq_r2m(mm7, *y3); /* 7 ; save y3 */ psubsw_r2r(mm1, mm3); /* 1 ; y7 = tp765*tg_1_16 - tp465 */ movq_r2m(mm5, *y5); /* save y5 */ /* .mmx32_fdct_col47: ; begin processing last four columns */ movq_m2r(*x1, mm0); /* 0 ; x1 */ movq_r2m(mm3, *y7); /* 3 ; save y7 (columns 0-4) */ movq_m2r(*x6, mm1); /* 1 ; x6 */ movq_r2r(mm0, mm2); /* 2 ; x1 */ movq_m2r(*x2, mm3); /* 3 ; x2 */ paddsw_r2r(mm1, mm0); /* t1 = x[1] + x[6] */ movq_m2r(*x5, mm4); /* 4 ; x5 */ psllw_i2r(SHIFT_FRW_COL, mm0); /* t1 */ movq_m2r(*x0, mm5); /* 5 ; x0 */ paddsw_r2r(mm3, mm4); /* t2 = x[2] + x[5] */ paddsw_m2r(*x7, mm5); /* t0 = x[0] + x[7] */ psllw_i2r(SHIFT_FRW_COL, mm4); /* t2 */ movq_r2r(mm0, mm6); /* 6 ; t1 */ psubsw_r2r(mm1, mm2); /* 1 ; t6 = x[1] - x[6] */ movq_m2r(*(fdct_tg_all_16 + 4), mm1); /* 1 ; tg_2_16 */ psubsw_r2r(mm4, mm0); /* tm12 = t1 - t2 */ movq_m2r(*x3, mm7); /* 7 ; x3 */ pmulhw_r2r(mm0, mm1); /* tm12*tg_2_16 */ paddsw_m2r(*x4, mm7); /* t3 = x[3] + x[4] */ psllw_i2r(SHIFT_FRW_COL, mm5); /* t0 */ paddsw_r2r(mm4, mm6); /* 4 ; tp12 = t1 + t2 */ psllw_i2r(SHIFT_FRW_COL, mm7); /* t3 */ movq_r2r(mm5, mm4); /* 4 ; t0 */ psubsw_r2r(mm7, mm5); /* tm03 = t0 - t3 */ paddsw_r2r(mm5, mm1); /* y2 = tm03 + tm12*tg_2_16 */ paddsw_r2r(mm7, mm4); /* 7 ; tp03 = t0 + t3 */ por_m2r(fdct_one_corr, mm1); /* correction y2 +0.5 */ psllw_i2r(SHIFT_FRW_COL+1, mm2); /* t6 */ pmulhw_m2r(*(fdct_tg_all_16 + 4), mm5); /* tm03*tg_2_16 */ movq_r2r(mm4, mm7); /* 7 ; tp03 */ psubsw_m2r(*x5, mm3); /* t5 = x[2] - x[5] */ psubsw_r2r(mm6, mm4); /* y4 = tp03 - tp12 */ movq_r2m(mm1, *(y2+4)); /* save y2 */ paddsw_r2r(mm6, mm7); /* y0 = tp03 + tp12 */ movq_m2r(*x3, mm1); /* 1 ; x3 */ psllw_i2r(SHIFT_FRW_COL+1, mm3); /* t5 */ psubsw_m2r(*x4, mm1); /* t4 = x[3] - x[4] */ movq_r2r(mm2, mm6); /* 6 ; t6 */ movq_r2m(mm4, *(y4+4)); /* save y4 */ paddsw_r2r(mm3, mm2); /* t6 + t5 */ pmulhw_m2r(*ocos_4_16, mm2); /* tp65 = (t6 + t5)*cos_4_16 */ psubsw_r2r(mm3, mm6); /* 3 ; t6 - t5 */ pmulhw_m2r(*ocos_4_16, mm6); /* tm65 = (t6 - t5)*cos_4_16 */ psubsw_r2r(mm0, mm5); /* 0 ; y6 = tm03*tg_2_16 - tm12 */ por_m2r(fdct_one_corr, mm5); /* correction y6 +0.5 */ psllw_i2r(SHIFT_FRW_COL, mm1); /* t4 */ por_m2r(fdct_one_corr, mm2); /* correction tp65 +0.5 */ movq_r2r(mm1, mm4); /* 4 ; t4 */ movq_m2r(*x0, mm3); /* 3 ; x0 */ paddsw_r2r(mm6, mm1); /* tp465 = t4 + tm65 */ psubsw_m2r(*x7, mm3); /* t7 = x[0] - x[7] */ psubsw_r2r(mm6, mm4); /* 6 ; tm465 = t4 - tm65 */ movq_m2r(*(fdct_tg_all_16 + 0), mm0); /* 0 ; tg_1_16 */ psllw_i2r(SHIFT_FRW_COL, mm3); /* t7 */ movq_m2r(*(fdct_tg_all_16 + 8), mm6); /* 6 ; tg_3_16 */ pmulhw_r2r(mm1, mm0); /* tp465*tg_1_16 */ movq_r2m(mm7, *(y0+4)); /* 7 ; save y0 */ pmulhw_r2r(mm4, mm6); /* tm465*tg_3_16 */ movq_r2m(mm5, *(y6+4)); /* 5 ; save y6 */ movq_r2r(mm3, mm7); /* 7 ; t7 */ movq_m2r(*(fdct_tg_all_16 + 8), mm5); /* 5 ; tg_3_16 */ psubsw_r2r(mm2, mm7); /* tm765 = t7 - tp65 */ paddsw_r2r(mm2, mm3); /* 2 ; tp765 = t7 + tp65 */ pmulhw_r2r(mm7, mm5); /* tm765*tg_3_16 */ paddsw_r2r(mm3, mm0); /* y1 = tp765 + tp465*tg_1_16 */ paddsw_r2r(mm4, mm6); /* tm465*tg_3_16 */ pmulhw_m2r(*(fdct_tg_all_16 + 0), mm3); /* tp765*tg_1_16 */ por_m2r(fdct_one_corr, mm0); /* correction y1 +0.5 */ paddsw_r2r(mm7, mm5); /* tm765*tg_3_16 */ psubsw_r2r(mm6, mm7); /* 6 ; y3 = tm765 - tm465*tg_3_16 */ movq_r2m(mm0, *(y1+4)); /* 0 ; save y1 */ paddsw_r2r(mm4, mm5); /* 4 ; y5 = tm765*tg_3_16 + tm465 */ movq_r2m(mm7, *(y3+4)); /* 7 ; save y3 */ psubsw_r2r(mm1, mm3); /* 1 ; y7 = tp765*tg_1_16 - tp465 */ movq_r2m(mm5, *(y5+4)); /* 5 ; save y5 */ movq_r2m(mm3, *(y7+4)); /* 3 ; save y7 */ /* } ; end of forward_dct_col07() */ /* done with dct_row transform */ /* * fdct_mmx32_cols() -- * the following subroutine repeats the row-transform operation, * except with different shift&round constants. This version * does NOT transpose the output again. Thus the final output * is transposed with respect to the source. * * The output is stored into blk[], which destroys the original * input data. */ out = inp = blk; table = (int16_t *)tab_frw_01234567; /* * for ( x = 8; x > 0; --x ) ; transform one row per iteration * ---------- loop begin */ for(i=0; i<8; i++) { movd_m2r(*(inp+6), mm5); /* mm5 = 7 6 */ punpcklwd_m2r(*(inp+4), mm5); /* mm5 = 5 7 4 6 */ movq_r2r(mm5, mm2); /* mm2 = 5 7 4 6 */ psrlq_i2r(32, mm5); /* mm5 = _ _ 5 7 */ movq_m2r(*inp, mm0); /* mm0 = 3 2 1 0 */ punpcklwd_r2r(mm2, mm5); /* mm5 = 4 5 6 7 */ movq_r2r(mm0, mm1); /* mm1 = 3 2 1 0 */ paddsw_r2r(mm5, mm0); /* mm0 = [3+4, 2+5, 1+6, 0+7] (xt3, xt2, xt1, xt0) */ psubsw_r2r(mm5, mm1); /* mm1 = [3-4, 2-5, 1-6, 0-7] (xt7, xt6, xt5, xt4) */ movq_r2r(mm0, mm2); /* mm2 = [ xt3 xt2 xt1 xt0 ] */ /* movq [ xt3xt2xt1xt0 ], mm0; */ /* movq [ xt7xt6xt5xt4 ], mm1; */ punpcklwd_r2r(mm1, mm0); /* mm0 = [ xt5 xt1 xt4 xt0 ] */ punpckhwd_r2r(mm1, mm2); /* mm2 = [ xt7 xt3 xt6 xt2 ] */ movq_r2r(mm2, mm1); /* mm1 */ /* shuffle bytes around */ /* movq mm0, [INP] ; 0 ; x3 x2 x1 x0 */ /* movq mm1, [INP+8] ; 1 ; x7 x6 x5 x4 */ movq_r2r(mm0, mm2); /* 2 ; x3 x2 x1 x0 */ movq_m2r(*table, mm3); /* 3 ; w06 w04 w02 w00 */ punpcklwd_r2r(mm1, mm0); /* x5 x1 x4 x0 */ movq_r2r(mm0, mm5); /* 5 ; x5 x1 x4 x0 */ punpckldq_r2r(mm0, mm0); /* x4 x0 x4 x0 [ xt2 xt0 xt2 xt0 ] */ movq_m2r(*(table+4), mm4); /* 4 ; w07 w05 w03 w01 */ punpckhwd_r2r(mm1, mm2); /* 1 ; x7 x3 x6 x2 */ pmaddwd_r2r(mm0, mm3); /* x4*w06+x0*w04 x4*w02+x0*w00 */ movq_r2r(mm2, mm6); /* 6 ; x7 x3 x6 x2 */ movq_m2r(*(table+16), mm1); /* 1 ; w22 w20 w18 w16 */ punpckldq_r2r(mm2, mm2); /* x6 x2 x6 x2 [ xt3 xt1 xt3 xt1 ] */ pmaddwd_r2r(mm2, mm4); /* x6*w07+x2*w05 x6*w03+x2*w01 */ punpckhdq_r2r(mm5, mm5); /* x5 x1 x5 x1 [ xt6 xt4 xt6 xt4 ] */ pmaddwd_m2r(*(table+8), mm0); /* x4*w14+x0*w12 x4*w10+x0*w08 */ punpckhdq_r2r(mm6, mm6); /* x7 x3 x7 x3 [ xt7 xt5 xt7 xt5 ] */ movq_m2r(*(table+20), mm7); /* 7 ; w23 w21 w19 w17 */ pmaddwd_r2r(mm5, mm1); /* x5*w22+x1*w20 x5*w18+x1*w16 */ /* * mm3 = a1, a0 (y2,y0) * mm1 = b1, b0 (y3,y1) * mm0 = a3,a2 (y6,y4) * mm5 = b3,b2 (y7,y5) */ paddd_m2r(*round_frw_row, mm3); /* +rounder (y2,y0) */ pmaddwd_r2r(mm6, mm7); /* x7*w23+x3*w21 x7*w19+x3*w17 */ pmaddwd_m2r(*(table+12), mm2); /* x6*w15+x2*w13 x6*w11+x2*w09 */ paddd_r2r(mm4, mm3); /* 4 ; a1=sum(even1) a0=sum(even0) ; now ( y2, y0) */ pmaddwd_m2r(*(table+24), mm5); /* x5*w30+x1*w28 x5*w26+x1*w24 */ pmaddwd_m2r(*(table+28), mm6); /* x7*w31+x3*w29 x7*w27+x3*w25 */ paddd_r2r(mm7, mm1); /* 7 ; b1=sum(odd1) b0=sum(odd0) ; now ( y3, y1) */ paddd_m2r(*round_frw_row, mm0); /* +rounder (y6,y4) */ psrad_i2r(SHIFT_FRW_ROW, mm3); /* (y2, y0) */ paddd_m2r(*round_frw_row, mm1); /* +rounder (y3,y1) */ paddd_r2r(mm2, mm0); /* 2 ; a3=sum(even3) a2=sum(even2) ; now (y6, y4) */ paddd_m2r(*round_frw_row, mm5); /* +rounder (y7,y5) */ psrad_i2r(SHIFT_FRW_ROW, mm1); /* y1=a1+b1 y0=a0+b0 */ paddd_r2r(mm6, mm5); /* 6 ; b3=sum(odd3) b2=sum(odd2) ; now ( y7, y5) */ psrad_i2r(SHIFT_FRW_ROW, mm0); /* y3=a3+b3 y2=a2+b2 */ out += 8; /* increment row-output address by 1 row */ psrad_i2r(SHIFT_FRW_ROW, mm5); /* y4=a3-b3 y5=a2-b2 */ inp += 8; /* increment row-address by 1 row */ packssdw_r2r(mm0, mm3); /* 0 ; y6 y4 y2 y0 */ packssdw_r2r(mm5, mm1); /* 3 ; y7 y5 y3 y1 */ movq_r2r(mm3, mm6); /* mm0 = y6 y4 y2 y0 */ punpcklwd_r2r(mm1, mm3); /* y3 y2 y1 y0 */ punpckhwd_r2r(mm1, mm6); /* y7 y6 y5 y4 */ table += 32; /* increment to next table */ movq_r2m(mm3, *(out-8)); /* 1 ; save y3 y2 y1 y0 */ movq_r2m(mm6, *(out-4)); /* 7 ; save y7 y6 y5 y4 */ } emms(); } mjpegtools-2.1.0/mpeg2enc/quantize_precomp.h0000644000175000017500000000256007755435151021466 0ustar glowwormglowworm/* * quantize_precomp.h, Precomputed quantisation tables for various fast * implementations of quantization/ inverse quantization routines * */ /* (C) 2003 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #ifndef _QUANTIZE_PRECOMP_H #define _QUANTIZE_PRECOMP_H struct QuantizerWorkSpace { uint16_t intra_q_mat[64], i_intra_q_mat[64]; uint16_t inter_q_mat[64], i_inter_q_mat[64]; uint16_t intra_q_tbl[113][64], inter_q_tbl[113][64]; uint16_t i_intra_q_tbl[113][64], i_inter_q_tbl[113][64]; uint16_t r_intra_q_tbl[113][64], r_inter_q_tbl[113][64]; float intra_q_tblf[113][64], inter_q_tblf[113][64]; float i_intra_q_tblf[113][64], i_inter_q_tblf[113][64]; }; #endif mjpegtools-2.1.0/mpeg2enc/mpeg2syntaxcodes.h0000644000175000017500000000507410747735115021401 0ustar glowwormglowworm/* mpeg2syntaxcodes.h - Identifying bit-patterns and codes for MPEG2 syntax */ #ifndef _MPEG2SYNTAXCODES_H #define _MPEG2SYNTAXCODES_H /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ #define PICTURE_START_CODE 0x100L #define SLICE_MIN_START 0x101L #define SLICE_MAX_START 0x1AFL #define USER_START_CODE 0x1B2L #define SEQ_START_CODE 0x1B3L #define EXT_START_CODE 0x1B5L #define SEQ_END_CODE 0x1B7L #define GOP_START_CODE 0x1B8L #define ISO_END_CODE 0x1B9L #define PACK_START_CODE 0x1BAL #define SYSTEM_START_CODE 0x1BBL #define FFFF_VBV_DELAY 0xFFFF /* picture coding type */ enum PICTURE_CODING { I_TYPE=1, P_TYPE=2, B_TYPE=3, NUM_PICT_TYPES }; #define FIRST_PICT_TYPE I_TYPE #define LAST_PICT_TYPE B_TYPE /* picture structure */ enum PICTURE_STRUCT { TOP_FIELD=1, BOTTOM_FIELD=2, FRAME_PICTURE=3 }; /* macroblock type */ enum MACROBLOCK_CODING_BITS { MB_INTRA=1, MB_PATTERN=2, MB_BACKWARD=4, MB_FORWARD=8, MB_QUANT=16 }; /* motion_type */ #define MC_FIELD 1 #define MC_FRAME 2 #define MC_16X8 2 #define MC_DMV 3 /* mv_format */ #define MV_FIELD 0 #define MV_FRAME 1 /* chroma_format */ #define CHROMA420 1 //#define CHROMA422 2 //#define CHROMA444 3 /* extension start code IDs */ #define SEQ_ID 1 #define DISP_ID 2 #define QUANT_ID 3 #define SEQSCAL_ID 5 #define PANSCAN_ID 7 #define CODING_ID 8 #define SPATSCAL_ID 9 #define TEMPSCAL_ID 10 #endif mjpegtools-2.1.0/mpeg2enc/mpeg2coder.hh0000644000175000017500000001004211456612024020257 0ustar glowwormglowworm#ifndef _MPEG2CODING_HH #define _MPEG2CODING_HH // TODO should be renamed to mpeg2codingbuf.hh /* mpeg2encoding.hh - (Partial) MPEG2 packed bit / VLC syntax encoding of a Picture */ /* (C) 2003 Andrew Stevens */ /* This Software is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include #include "mjpeg_types.h" #include "synchrolib.h" #include "elemstrmwriter.hh" class Picture; class MPEG2CodingBuf { public: MPEG2CodingBuf( EncoderParams &encoder, ElemStrmWriter &writer ); virtual ~MPEG2CodingBuf(); void PutUserData( const uint8_t *userdata, int len); void PutGopHdr(int frame, int closed_gop ); void PutSeqEnd(); void PutSeqHdr(); void PutIntraBlk(Picture *picture, int16_t *blk, int cc); void PutNonIntraBlk(Picture *picture, int16_t *blk); void PutMV(int dmv, int f_code); void PutDMV(int dmv); void PutAddrInc(int addrinc); void PutMBType(int pict_type, int mb_type); void PutMotionCode(int motion_code); void PutCPB(int cbp); inline void PutBits( uint32_t val, int n) { frag_buf->PutBits( val, n ); } inline int ByteCount() const { return frag_buf->ByteCount(); } inline void AlignBits() { frag_buf->AlignBits(); } inline bool Aligned() const { return frag_buf->Aligned(); } inline void FlushBuffer() { frag_buf->FlushBuffer(); } inline void ResetBuffer() { frag_buf->ResetBuffer(); } private: void PutSeqExt(); void PutSeqDispExt(); int FrameToTimeCode( int gop_timecode0_frame ); inline void PutDClum(int val) { PutDC(DClumtab,val); } inline int DClum_bits( int val ) { return DC_bits(DClumtab,val); } /* generate variable length code for chrominance DC coefficient */ inline void PutDCchrom(int val) { PutDC(DCchromtab,val); } inline int DCchrom_bits(int val) { return DC_bits(DClumtab,val); } /* type definitions for variable length code table entries */ typedef struct { unsigned char code; /* right justified */ char len; } VLCtable; /* for codes longer than 8 bits (excluding leading zeroes) */ typedef struct { unsigned short code; /* right justified */ char len; } sVLCtable; void PutDC(const sVLCtable *tab, int val); int DC_bits(const sVLCtable *tab, int val); void PutACfirst(int run, int val); void PutAC(int run, int signed_level, int vlcformat); int AC_bits(int run, int signed_level, int vlcformat); int AddrInc_bits(int addrinc); int MBType_bits( int pict_type, int mb_type); int MotionCode_bits( int motion_code ); int DMV_bits(int dmv); int CBP_bits(int cbp); private: EncoderParams &encparams; ElemStrmFragBuf *frag_buf; const static VLCtable addrinctab[33]; const static VLCtable mbtypetab[3][32]; const static VLCtable cbptable[64]; const static VLCtable motionvectab[17]; const static sVLCtable DClumtab[12]; const static sVLCtable DCchromtab[12]; const static VLCtable dct_code_tab1[2][40]; const static VLCtable dct_code_tab2[30][5]; const static VLCtable dct_code_tab1a[2][40]; const static VLCtable dct_code_tab2a[30][5]; }; /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ #endif mjpegtools-2.1.0/mpeg2enc/TODO0000644000175000017500000000617010346407114016405 0ustar glowwormglowwormIN PROGRESS - Remove obsolete i,j in macroblocks in favour of Coord.... - Replace appending subsampled luminance to luminance data with a 5-plane picture data model (YUVHQ) - MotionEst should be called 'MacroBlockCodingMode' - Set satlim and scale type in quantizer during init - Move to a buffering output model where a frame can be aborted/restarted with different quantisation if it is coming out too large or too small. - Dynamic B/P selection and selection of I frames without memory-expensive look-ahead. - Improve memory management. Selecting Picture's from a single pool rather than seperate B / I|P pools will save memory buffers. Also, really there is no need for DCT blocks for every picture as encoding is basically serial!! Near Future improvements 0. Replace current variance based motion estimation mode selection with DCT based selection. Next Step: split predictors from Picture state and build a new QuantiseAndPutEncoding that predict's and transforms and quantisatises forall the motion estimates and selects the one that worked best for encoding. - Modify the on-the-fly rate controller so it can handle adjusting quantisation at select Macroblock's and not at *every* macroblock if no fancy per-block quantisation fiddles are active... 1. Add single coefficient dropping to DCT... 2. Split into front-end and library (for gstreamer etc) This will require removal of lots of nasty global scratch variables 3. Add accurate (GOP-structure based) decoder buffer modelling for more aggresive bit-rate optimisation. 4. Seperate the transformation phase (ME, pred, DCT) from the bit allocation and coding phases. This will provide the basis for two-pass encoding and pipelined encoding. 5. The rate control code is now a mess of int64_t , double and int. Needs tidying... 6. Add support for the ATSC Active Format Description and Bar Data extenstions Minor Tidying 1. A lot of parameter passing could be removed from motionest.cc routines by creating an 'MacroBlockMotionModes' object carrying parameters fixed for a block... 2. The order of return from block_dist1_MMXE is silly. Why not retune in the order it is held and adjust find_best_one_pel_MMXE to suit. 3. For Motion estimation in -I 1 we really need both field *and* frame sub-sampled images for motion estimation to be optimal. 5. The code for scene-change gop sizing and ending sequences can in some circumstances mess up as the sizing takes no account of the fact the when a sequence split occurs the I-frame tempref is 0 not M-1. Sometime.... 1. Bring field sequence MC/prediction to same level as progressive sequence. 2. Improve locality of reference by motion-estimating entire 4x4, 2x2, 1x1 phases in a single pass rather doing each for each Macroblock. 3. Check out using dist2 for initial MC calculations as well as final selection? 5. Add low-passing for high-activity regions when a specified quantisation level is exceeded (or block boundary edge energy exceeds some threshold?). 6. Sort out that wretched vbv verification code. The mblockq_ sub-routines intended specification should be documented... mjpegtools-2.1.0/mpeg2enc/idct.c0000644000175000017500000002133010162467376017013 0ustar glowwormglowworm/* idct.c, inverse fast discrete cosine transform */ #include #include #include #include #include #include "mjpeg_types.h" #include "mjpeg_logging.h" #include "transfrm_ref.h" /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ /**********************************************************/ /* inverse two dimensional DCT, Chen-Wang algorithm */ /* (cf. IEEE ASSP-32, pp. 803-816, Aug. 1984) */ /* 32-bit integer arithmetic (8 bit coefficients) */ /* 11 mults, 29 adds per DCT */ /* sE, 18.8.91 */ /**********************************************************/ /* coefficients extended to 12 bit for IEEE1180-1990 */ /* compliance sE, 2.1.94 */ /**********************************************************/ /* this code assumes >> to be a two's-complement arithmetic */ /* right shift: (-2)>>1 == -1 , (-3)>>1 == -2 */ // define if you want to include idct testing code #define IDCTTEST #define W1 2841 /* 2048*sqrt(2)*cos(1*pi/16) */ #define W2 2676 /* 2048*sqrt(2)*cos(2*pi/16) */ #define W3 2408 /* 2048*sqrt(2)*cos(3*pi/16) */ #define W5 1609 /* 2048*sqrt(2)*cos(5*pi/16) */ #define W6 1108 /* 2048*sqrt(2)*cos(6*pi/16) */ #define W7 565 /* 2048*sqrt(2)*cos(7*pi/16) */ /* global declarations */ /* private data */ static int16_t iclip[1024]; /* clipping table */ static int16_t *iclp; /* private prototypes */ static void idctrow (int16_t *blk); static void idctcol (int16_t *blk); /* row (horizontal) IDCT * * 7 pi 1 * dst[k] = sum c[l] * src[l] * cos( -- * ( k + - ) * l ) * l=0 8 2 * * where: c[0] = 128 * c[1..7] = 128*sqrt(2) */ static void idctrow(int16_t *blk) { int x0, x1, x2, x3, x4, x5, x6, x7, x8; /* int16_tcut */ if (!((x1 = blk[4]<<11) | (x2 = blk[6]) | (x3 = blk[2]) | (x4 = blk[1]) | (x5 = blk[7]) | (x6 = blk[5]) | (x7 = blk[3]))) { blk[0]=blk[1]=blk[2]=blk[3]=blk[4]=blk[5]=blk[6]=blk[7]=blk[0]<<3; return; } x0 = (blk[0]<<11) + 128; /* for proper rounding in the fourth stage */ /* first stage */ x8 = W7*(x4+x5); x4 = x8 + (W1-W7)*x4; x5 = x8 - (W1+W7)*x5; x8 = W3*(x6+x7); x6 = x8 - (W3-W5)*x6; x7 = x8 - (W3+W5)*x7; /* second stage */ x8 = x0 + x1; x0 -= x1; x1 = W6*(x3+x2); x2 = x1 - (W2+W6)*x2; x3 = x1 + (W2-W6)*x3; x1 = x4 + x6; x4 -= x6; x6 = x5 + x7; x5 -= x7; /* third stage */ x7 = x8 + x3; x8 -= x3; x3 = x0 + x2; x0 -= x2; x2 = (181*(x4+x5)+128)>>8; x4 = (181*(x4-x5)+128)>>8; /* fourth stage */ blk[0] = (x7+x1)>>8; blk[1] = (x3+x2)>>8; blk[2] = (x0+x4)>>8; blk[3] = (x8+x6)>>8; blk[4] = (x8-x6)>>8; blk[5] = (x0-x4)>>8; blk[6] = (x3-x2)>>8; blk[7] = (x7-x1)>>8; } /* column (vertical) IDCT * * 7 pi 1 * dst[8*k] = sum c[l] * src[8*l] * cos( -- * ( k + - ) * l ) * l=0 8 2 * * where: c[0] = 1/1024 * c[1..7] = (1/1024)*sqrt(2) */ static void idctcol(int16_t *blk) { int x0, x1, x2, x3, x4, x5, x6, x7, x8; /* int16_tcut */ if (!((x1 = (blk[8*4]<<8)) | (x2 = blk[8*6]) | (x3 = blk[8*2]) | (x4 = blk[8*1]) | (x5 = blk[8*7]) | (x6 = blk[8*5]) | (x7 = blk[8*3]))) { blk[8*0]=blk[8*1]=blk[8*2]=blk[8*3]=blk[8*4]=blk[8*5]=blk[8*6]=blk[8*7]= iclp[(blk[8*0]+32)>>6]; return; } x0 = (blk[8*0]<<8) + 8192; /* first stage */ x8 = W7*(x4+x5) + 4; x4 = (x8+(W1-W7)*x4)>>3; x5 = (x8-(W1+W7)*x5)>>3; x8 = W3*(x6+x7) + 4; x6 = (x8-(W3-W5)*x6)>>3; x7 = (x8-(W3+W5)*x7)>>3; /* second stage */ x8 = x0 + x1; x0 -= x1; x1 = W6*(x3+x2) + 4; x2 = (x1-(W2+W6)*x2)>>3; x3 = (x1+(W2-W6)*x3)>>3; x1 = x4 + x6; x4 -= x6; x6 = x5 + x7; x5 -= x7; /* third stage */ x7 = x8 + x3; x8 -= x3; x3 = x0 + x2; x0 -= x2; x2 = (181*(x4+x5)+128)>>8; x4 = (181*(x4-x5)+128)>>8; /* fourth stage */ blk[8*0] = iclp[(x7+x1)>>14]; blk[8*1] = iclp[(x3+x2)>>14]; blk[8*2] = iclp[(x0+x4)>>14]; blk[8*3] = iclp[(x8+x6)>>14]; blk[8*4] = iclp[(x8-x6)>>14]; blk[8*5] = iclp[(x0-x4)>>14]; blk[8*6] = iclp[(x3-x2)>>14]; blk[8*7] = iclp[(x7-x1)>>14]; } /* two dimensional inverse discrete cosine transform */ void idct(int16_t *block) { int i; for (i=0; i<8; i++) idctrow(block+8*i); for (i=0; i<8; i++) idctcol(block+i); } #ifdef IDCTTEST extern void idct_mmx(int16_t *blk); extern void idct_sse(int16_t *blk); static double coslu[8][8]; /* reference idct taken from "ieeetest.c" * Written by Tom Lane (tgl@cs.cmu.edu). * Released to public domain 11/22/93. */ void idct_ref(int16_t *block) { int x,y,u,v; double tmp, tmp2; double res[8][8]; for (y=0; y<8; y++) { for (x=0; x<8; x++) { tmp = 0.0; for (v=0; v<8; v++) { tmp2 = 0.0; for (u=0; u<8; u++) { tmp2 += (double) block[v*8+u] * coslu[x][u]; } tmp += coslu[y][v] * tmp2; } res[y][x] = tmp; } } for (v=0; v<8; v++) { for (u=0; u<8; u++) { tmp = res[v][u]; if (tmp < 0.0) { x = - ((int) (0.5 - tmp)); } else { x = (int) (tmp + 0.5); } block[v*8+u] = x; } } } void init_idct_ref(void) { int a,b; double tmp; for(a=0;a<8;a++) for(b=0;b<8;b++) { tmp = cos((double)((a+a+1)*b) * (3.14159265358979323846 / 16.0)); if(b==0) tmp /= sqrt(2.0); coslu[a][b] = tmp * 0.5; } } struct dct_test { int bounds,maxerr,iter; int me[64],mse[64]; }; void dct_test_and_print(struct dct_test *dt,int range,int16_t *origblock,int16_t *block) { int b,m,i; b=0; m=0; for( i=0; i<64; i++ ) { int x=block[i]-origblock[i]; int ax=abs(x); dt->me[i]+=x; dt->mse[i]+=x*x; if( ax>m ) m=ax; if( block[i]<-range || block[i]>=range ) b++; if( origblock[i]<-range || origblock[i]>=range ) { // mjpeg_info("*********** REFERENCE VERSION OUT OF BOUNDS\n"); } } dt->bounds+=b; if (m > dt->maxerr ) dt->maxerr = m; dt->iter++; if( !(dt->iter&65535) ) { int sme=0,srms=0; for( i=0; i<64; i++ ) { sme+=dt->me[i]; srms+=dt->mse[i]; } mjpeg_info("dct_test[%d]: max error=%d, mean error=%.8f, rms error=%.8f; bounds err=%d\n", dt->iter,dt->maxerr, sme/(dt->iter*64.), srms/(dt->iter*64.), dt->bounds); for( i=0; i<8; i++ ) { int j; for( j=0; j<8; j++ ) fprintf(stderr,"%9.6f%c",((double)dt->me[i*8+j])/dt->iter,j==7?'\n':' '); for( j=0; j<8; j++ ) fprintf(stderr,"%9.6f%c",((double)dt->mse[i*8+j])/dt->iter,j==7?'\n':' '); fprintf(stderr,"\n"); } } } static struct dct_test idct_res; void idct_test(int16_t *block) { int16_t origblock[64]; memcpy(origblock,block,64*sizeof(int16_t)); idct_ref(origblock); // idct(origblock); idct(block); // idct_mmx(block); // idct_sse(block); dct_test_and_print(&idct_res,256,origblock,block); } #endif void init_idct(void) { int i; iclp = iclip+512; for (i= -512; i<512; i++) iclp[i] = (i<-256) ? -256 : ((i>255) ? 255 : i); #ifdef IDCTTEST memset(&idct_res,0,sizeof(idct_res)); init_idct_ref(); #endif } mjpegtools-2.1.0/mpeg2enc/mpeg2encoder.hh0000644000175000017500000000331610444645161020614 0ustar glowwormglowworm#ifndef _MPEG2ENCODER_HH #define _MPEG2ENCODER_HH /* mpeg2encoder.hh Top-level class for an instance of mpeg2enc++ * MPEG-1/2 encoder. */ /* (C) 2003 Andrew Stevens */ /* This Software is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include #include "mpeg2encoptions.hh" #include "encoderparams.hh" class EncoderParams; class PictureReader; class Pass1RateCtl; class Pass2RateCtl; class SeqEncoder; class Quantizer; class Transformer; class MPEG2CodingBuf; class BitStreamWriter; class ElemStrmWriter; class MPEG2Encoder { public: MPEG2Encoder( MPEG2EncOptions &options ); ~MPEG2Encoder(); static void SIMDInitOnce(); static bool simd_init; MPEG2EncOptions &options; EncoderParams parms; PictureReader *reader; ElemStrmWriter *writer; Quantizer *quantizer; MPEG2CodingBuf *coder; Pass1RateCtl *pass1ratectl; Pass2RateCtl *pass2ratectl; SeqEncoder *seqencoder; }; /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ #endif mjpegtools-2.1.0/mpeg2enc/ratectl.hh0000644000175000017500000001110211456612024017664 0ustar glowwormglowworm#ifndef _RATECTL_HH #define _RATECTL_HH /* (C) 2003 Andrew Stevens */ /* This is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include #include "mjpeg_types.h" #include "mpeg2syntaxcodes.h" class MacroBlock; class EncoderParams; class Picture; /* Base class for state of rate-controller. Factory allows us to generate appropriate state objects for a given rate-controller object. Set allow us to set set of a rate-controller from a previously copied state... */ class RateCtlState { public: virtual ~RateCtlState() {} virtual RateCtlState *New() const = 0; virtual void Set( const RateCtlState &state) = 0; virtual const RateCtlState &Get() const = 0; }; class RateCtl { public: RateCtl( EncoderParams &_encparams, RateCtlState &_state ); virtual ~RateCtl() {} /********************* * * Initialise rate control parameters for start of encoding * based on encoding parameters * ********************/ virtual void Init() = 0; /********************* * * Setup rate control for a new picture * IF it is first of sequence new seq. is initialized first * IF it is first of GOP new GOP is initialized 2nd * Finally Picture specific initialization is done. * ********************/ virtual void PictSetup (Picture &picture); /********************* * * Update rate control after coding of new picture (minus padding) * ********************/ virtual void PictUpdate (Picture &picture, int &padding_needed ) = 0; virtual int MacroBlockQuant( const MacroBlock &mb) = 0; virtual int InitialMacroBlockQuant() = 0; inline RateCtlState *NewState() const { return state.New(); } inline void SetState( const RateCtlState &toset) { state.Set( toset ); } inline const RateCtlState &GetState() const { return state.Get(); } // TODO DEBUG virtual double SumAvgActivity() = 0; static double ClipQuant( int q_scale_type, double quant ); static double InvScaleQuant( int q_scale_type, int raw_code ); static int ScaleQuant( int q_scale_type, double quant ); protected: /********************* * * Reinitialize rate control parameters for start of new sequence * ********************/ virtual void InitSeq( ) = 0; /********************* * * Reinitialize rate control parameters for start of new GOP * ********************/ virtual void InitGOP( ) = 0; /* **************************** * * Reinitialize rate control parameters for start of new Picture * * @return (re)encoding of picture to achieve rate-control mandatory * * ****************************/ virtual void InitPict( Picture &picture ) = 0; double ScaleQuantf( int q_scale_type, double quant ); EncoderParams &encparams; RateCtlState &state; }; class Pass1RateCtl : public RateCtl { public: Pass1RateCtl( EncoderParams &encoder, RateCtlState &state ); /********************* * * Setup GOP structure for coding from nominal GOP size parameters * ********************/ virtual void GopSetup( int nb, int np ) = 0; }; class Pass2RateCtl : public RateCtl { public: Pass2RateCtl( EncoderParams &encoder, RateCtlState &state ); /********************* * * Setup GOP structure for coding based on look-ahead data from pass-1 * ********************/ virtual void GopSetup( std::deque::iterator gop_begin, std::deque::iterator gop_end ) = 0; /********************* * @pre PictureSetup called... * @return Re-encoding of picture to achieve rate control mandatory * *********************/ virtual bool ReencodeRequired() const = 0; virtual unsigned int getEncodedFrames() const = 0; virtual double getStreamComplexity() const = 0; }; /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ #endif mjpegtools-2.1.0/mpeg2enc/quantize_x86.c0000644000175000017500000003473710433135231020433 0ustar glowwormglowworm/* quantize_x86.c Quantization / inverse quantization In compiler (gcc) embdeed assmbley language... */ /* Copyright (C) 2000 Andrew Stevens */ /* This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include #include #include #include #include "syntaxconsts.h" #include "mjpeg_logging.h" #include "fastintfns.h" #include "cpu_accel.h" #include "simd.h" #include "mmx.h" #if 0 #include "xmmintrin.h" #endif #include "tables.h" #include "quantize_precomp.h" #include "quantize_ref.h" int quant_weight_coeff_sum_mmx (int16_t *blk, uint16_t *i_quant_mat ); void iquantize_non_intra_m1_mmx(int16_t *src, int16_t *dst, uint16_t *qmat); void iquantize_non_intra_m2_mmx(int16_t *src, int16_t *dst, uint16_t *qmat); /* * Quantisation for non-intra blocks * * Various versions for various SIMD instruction sets. Not all of them * bother to implement the test model 5 quantisation of the reference source * (this has a bias of 1/8 stepsize towards zero - except for the DC coefficient). * * Actually, as far as I can tell even the reference source doesn't quite do it * for non-intra (though it *does* for intra). * * Careful analysis of the code also suggests what it actually does is truncate * with a modest bias towards 1 (the d>>2 factor) * * PRECONDITION: src dst point to *disinct* memory buffers... * of block_count *adjacent* int16_t[64] arrays... * *RETURN: A bit-mask of block_count bits indicating non-zero blocks (a 1). */ #if 0 /* * SSE version: simply truncates to zero, however, the tables have a 2% bias * upwards which partly compensates. */ static int quant_non_intra_sse( struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int q_scale_type, int satlim, int *nonsat_mquant) { __m64 saturated; float *i_quant_matf; int mquant = *nonsat_mquant; const int coeff_count = 64*BLOCK_COUNT; uint32_t nzflag; uint64_t flags; __m64 *psrc, *pdst; __m128 *piqf; int i; uint32_t tmp; // Set truncation as rounding mode... uint32_t oldcsr = _mmgetcsr(); _mm_setcsr( (oldcsr & ~_MM_ROUND_MASK 0x6000) | _MM_ROUND_TOWARD_ZERO ); __m64 zero = _mm_setzero_si64(); __m64 satlim_0123 = _mm_set1_pi16( (int16_t)satlim); __m64 neg_satlim_0123 = _mm_set1_pi16( (int16_t)-satlim); restart: i_quant_matf = (__m128 *)wsp->i_inter_q_tblf[mquant]; flags = 0; piqf = i_quant_matf; saturated = _mm_setzero_si64(); nzflag = 0; psrc = (__m64 *)src; pdst = (__m64 *)dst; for (i=0; i < coeff_count/(2*4) ; i += 2) { int j = i&63; // Sign extend psrc[i] to double words __m128 psrc_i_0_01234 = _mm_cvtpi16_ps( psrc[i] ); __m128 psrc_i_4_01234 = _mm_cvtpi16_ps( psrc[i+4] ); // "Divide" by multiplying by inverse quantisation psrc_i_0_01234 = _mm_mul_ps( psrc_i_0_01234, piqf[j] ); psrc_i_4_01234 = _mm_mul_ps( psrc_i_4_01234, piqf[j] ); // Accumulate saturation __m64 rawquant_0_0123 = _mm_cvtps_pi16(psrc_i_0_01234); __m64 rawquant_4_0123 = _mm_cvtps_pi16(psrc_i_4_01234); saturated = _mm_or_si64( saturated, _mm_cmpgt_pi16( rawquant_0_0123, satlim_0123 ) ); saturated = _mm_or_si64( saturated, _mm_cmpgt_pi16( rawquant_4_0123, satlim_0123 ) ); saturated = _mm_or_si64( saturated, _mm_cmpgt_pi16( rawquant_0_0123, neg_satlim_0123 )); saturated = _mm_or_si64( saturated, _mm_cmpgt_pi16( rawquant_4_0123, neg_satlim_0123 )); pdst[i] = rawquant_0_0123; pdst[i+4] = rawquant_4_0123; // Accumulate zero flags... flags = (uint64_t)_mm_or_si64( _mm_set_pi64x(flags), _mm_or_si64( rawquant_0_0123, rawquant_4_0123 )); // Check if we saturated every block (every 16 grou if( (i & (64/8-1)) == (64/8-1) ) { if( (uint64_t)saturated != (uint64_t)0 ) { int new_mquant = next_larger_quant( q_scale_type, mquant ); if( new_mquant != mquant ) { mquant = new_mquant; goto restart; } else { return quant_non_intra(wsp, src, dst, q_scale_type, satlim, nonsat_mquant); } } nzflag = (nzflag<<1) | ((uint64_t)flags != (uint64_t)0 ); flags = 0; } _mm_empty(); return nzflag; } #endif /* MMX version, that is 100% accurate It works by multiplying by the inverse of the quant factor. However in certain circumstances this results in a value too low. To compensate, it then multiplies by the quant factor, and compares this to the original value. If this new value is less than or equal to the original value minus the quant factor, then the intermediate result is incremented. This adjust-by-1 is all that is needed to correct the result. 8 words are handled per iteration; first four words uses mm0-mm3, last four words use mm4-mm7. */ static int quant_non_intra_mmx( struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int q_scale_type, int satlim, int *nonsat_mquant) { int saturated; int mquant = *nonsat_mquant; int coeff_count = 64*BLOCK_COUNT; uint32_t nzflag, flags; int16_t *psrc, *pdst; uint16_t *pdiv, *pmul; uint16_t *pdivbase, *pmulbase; int i; uint32_t tmp; uint64_t negone_q,satlim_q; /* Load -1 into negone_q */ pxor_r2r( mm6, mm6 ); pcmpeqw_r2r( mm6, mm6 ); movq_r2m( mm6, negone_q ); /* Load satlim into satlim_q */ movd_g2r( satlim, mm7 ); punpcklwd_r2r( mm7, mm7 ); punpckldq_r2r( mm7, mm7 ); movq_r2m( mm7, satlim_q ); pdivbase = wsp->i_inter_q_tbl[mquant]; pmulbase = wsp->inter_q_tbl[mquant]; restart: flags = 0; pdiv = pdivbase; pmul = pmulbase; saturated = 0; nzflag = 0; psrc = src; pdst = dst; for (i=0; i < coeff_count ; i+=8) { movq_m2r( psrc[0], mm3 ); // load values movq_m2r( psrc[4], mm7 ); // load values psllw_i2r( 4, mm3 ); // multiply by 16 psllw_i2r( 4, mm7 ); // multiply by 16 movq_r2r( mm3, mm0 ); // keep sign in mm3, make mm0=abs(mm3) movq_r2r( mm7, mm4 ); // keep sign in mm3, make mm0=abs(mm3) psraw_i2r( 15, mm3 ); psraw_i2r( 15, mm7 ); pxor_r2r( mm3, mm0 ); pxor_r2r( mm7, mm4 ); psubw_r2r( mm3, mm0 ); psubw_r2r( mm7, mm4 ); movq_m2r( pdiv[0], mm1 ); // "divide" by quant movq_m2r( pdiv[4], mm5 ); // "divide" by quant pmulhw_r2r( mm0, mm1 ); pmulhw_r2r( mm4, mm5 ); movq_m2r( pmul[0], mm2 ); // check that x*q > X-q; i.e. make sure x is not off by too much movq_m2r( pmul[4], mm6 ); // check that x*q > X-q; i.e. make sure x is not off by too much psubw_r2r( mm2, mm0 ); psubw_r2r( mm6, mm4 ); pmullw_r2r( mm1, mm2 ); pmullw_r2r( mm5, mm6 ); pcmpgtw_r2r( mm0, mm2 ); pcmpgtw_r2r( mm4, mm6 ); pxor_m2r( negone_q, mm2 ); pxor_m2r( negone_q, mm6 ); psubw_r2r( mm2, mm1 ); // if x*q <= X-q, increment x by 1 psubw_r2r( mm6, mm5 ); // if x*q <= X-q, increment x by 1 movq_r2r( mm1, mm0 ); // stash abs of result away movq_r2r( mm5, mm4 ); // stash abs of result away pxor_r2r( mm3, mm1 ); // make result have same sign as orig value pxor_r2r( mm7, mm5 ); // make result have same sign as orig value psubw_r2r( mm3, mm1 ); psubw_r2r( mm7, mm5 ); movq_r2m( mm1, pdst[0] ); // store result movq_r2m( mm5, pdst[4] ); // store result por_r2r( mm5, mm1 ); movq_r2r( mm1, mm2 ); // set flags for non null responses psrlq_i2r( 32, mm2 ); por_r2r( mm1, mm2 ); movd_r2g( mm2, tmp ); flags |= tmp; pcmpgtw_m2r( satlim_q, mm0 ); // did result exceed satlim? pcmpgtw_m2r( satlim_q, mm4 ); por_r2r( mm4, mm0 ); movq_r2r( mm0, mm1 ); psrlq_i2r( 32, mm1 ); por_r2r( mm1, mm0 ); movd_r2g( mm0, tmp ); saturated |= tmp; pdiv += 8; pmul += 8; pdst += 8; psrc += 8; if( (i & 63) == (63/8)*8 ) { if( saturated ) { int new_mquant = next_larger_quant( q_scale_type, mquant ); if( new_mquant != mquant ) { mquant = new_mquant; goto restart; } else { emms(); return quant_non_intra(wsp, src, dst, q_scale_type, satlim, nonsat_mquant); } } nzflag = (nzflag<<1) | !!flags; flags = 0; pdiv = pdivbase; pmul = pmulbase; } } emms(); //nzflag = (nzflag<<1) | (!!flags); return nzflag; } static void iquant_non_intra_m1_mmx(struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int mquant ) { iquantize_non_intra_m1_mmx(src,dst,wsp->inter_q_tbl[mquant]); } static void iquant_non_intra_m2_mmx(struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int mquant ) { iquantize_non_intra_m2_mmx(src,dst,wsp->inter_q_tbl[mquant]); } static int quant_weight_coeff_x86_intra( struct QuantizerWorkSpace *wsp, int16_t *blk ) { return quant_weight_coeff_sum_mmx( blk, wsp->i_intra_q_mat ); } static int quant_weight_coeff_x86_inter( struct QuantizerWorkSpace *wsp, int16_t *blk ) { return quant_weight_coeff_sum_mmx( blk, wsp->i_inter_q_mat ); } #if 0 extern void iquant_non_intra_m2(struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int mquant ); static void iquant_non_intra_m2_mmxtest( struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int mquant) { int i; int16_t ref[64]; iquant_non_intra_m2(wsp, src,ref,mquant); iquant_non_intra_m2_mmx(wsp, src,dst,mquant); for( i = 0; i < 64; ++i ) { if( dst[i] != ref[i] ) { printf( "OUCH!!! Bad iquant coeff %d: %d ref=%d\n", i, dst[i], ref[i] ); abort(); } } } static int quant_non_intra_test(struct QuantizerWorkSpace *wsp, int16_t *src, int16_t *dst, int q_scale_type, int satlim, int *nonsat_mquant) { int16_t d2[64*BLOCK_COUNT]; int rv1,rv2,mq1,mq2; mq1=*nonsat_mquant; rv1=quant_non_intra(wsp,src,d2,q_scale_type,satlim,&mq1); rv2=quant_non_intra_mmx(wsp,src,dst,q_scale_type,satlim,nonsat_mquant); mq2=*nonsat_mquant; if( rv1!=rv2 ) mjpeg_warn("quant_non_intra disparity: ret=%d vs %d",rv1,rv2); if( mq1!=mq2 ) mjpeg_warn("quant_non_intra disparity: mq=%d vs %d",mq1,mq2); if( memcmp(d2,dst,64*BLOCK_COUNT*sizeof(int16_t)) ) { int i; mjpeg_warn("quant_non_intra disparity: dst differs"); for( i=0; i<64*BLOCK_COUNT; i++ ) { if( d2[i]!=dst[i] ) mjpeg_warn("\t[%d]: %4d vs %4d",i,dst[i],d2[i]); } } return rv2; } #endif static int quant_non_intra_can_use_mmx(struct QuantizerWorkSpace *wsp) { int i; for( i=0; i<64; i++ ) { int q=wsp->inter_q_mat[i]; // if q<0, then bad things happen (mismatched sign) // if q==0, then divide by 0 happens // if q==1 or q==2, then 65536/q >= 32768 (negative sign when using signed multiply) // if q>292, then q*112 (which is the max quant scale) >=32768 (again, negative sign when using signed multiply) if( q<3 || q>292 ) return 0; } return 1; } void init_x86_quantization( struct QuantizerCalls *qcalls, struct QuantizerWorkSpace *wsp, int mpeg1) { int flags = cpu_accel(); int d_quant_nonintra, d_weight_intra, d_weight_nonintra, d_iquant_intra; int d_iquant_nonintra; const char *opt_type1 = "", *opt_type2 = ""; if ((flags & ACCEL_X86_MMX) != 0 ) /* MMX CPU */ { d_quant_nonintra = disable_simd("quant_nonintra"); d_weight_intra = disable_simd("quant_weight_intra"); d_weight_nonintra = disable_simd("quant_weight_nonintra"); d_iquant_intra = disable_simd("iquant_intra"); d_iquant_nonintra = disable_simd("iquant_nonintra"); if (d_quant_nonintra == 0) { if( quant_non_intra_can_use_mmx(wsp) ) { opt_type1 = "MMX and"; qcalls->pquant_non_intra = quant_non_intra_mmx; } else { mjpeg_warn("Non-intra quantization table out of range; disabling MMX"); } } opt_type2 = "MMX"; if (d_weight_intra == 0) qcalls->pquant_weight_coeff_intra = quant_weight_coeff_x86_intra; if (d_weight_nonintra == 0) qcalls->pquant_weight_coeff_inter = quant_weight_coeff_x86_inter; if (mpeg1) { if (d_iquant_nonintra == 0) qcalls->piquant_non_intra = iquant_non_intra_m1_mmx; } else { if (d_iquant_nonintra == 0) qcalls->piquant_non_intra = iquant_non_intra_m2_mmx; } if (d_quant_nonintra) mjpeg_info(" Disabling quant_non_intra"); if (d_iquant_intra) mjpeg_info(" Disabling iquant_intra"); if (d_iquant_nonintra) mjpeg_info(" Disabling iquant_nonintra"); if (d_weight_intra) mjpeg_info(" Disabling quant_weight_intra"); if (d_weight_nonintra) mjpeg_info(" Disabling quant_weight_nonintra"); mjpeg_info( "SETTING %s %s for QUANTIZER!", opt_type1, opt_type2); } } mjpegtools-2.1.0/mpeg2enc/predict_mmx.c0000644000175000017500000000363710162212644020377 0ustar glowwormglowworm/* * predict.s: mmX optimized block summing differencing routines * * Believed to be original Copyright (C) 2000 Brent Byeler * * This program is free software; you can reaxstribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "mjpeg_types.h" #include "mmx.h" void sub_pred_mmx(unsigned char *pred, unsigned char *cur, int lx, int16_t *blk) { int i; pxor_r2r(mm7, mm7); for(i=0; i<8; i++) { movq_m2r(*cur, mm0); cur+=lx; movq_m2r(*pred, mm2); pred+=lx; movq_r2r(mm0, mm1); punpcklbw_r2r(mm7, mm0); punpckhbw_r2r(mm7, mm1); movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); psubw_r2r(mm2, mm0); psubw_r2r(mm3, mm1); movq_r2m(mm0, *blk); movq_r2m(mm1, *(blk+4)); blk+=8; } emms(); } /* add prediction and prediction error, saturate to 0...255 */ void add_pred_mmx(unsigned char *pred, unsigned char *cur, int lx, int16_t *blk) { int i; pxor_r2r(mm7, mm7); for(i=0; i<8; i++) { movq_m2r(*blk, mm0); movq_m2r(*(blk+4), mm1); blk+=8; movq_m2r(*pred, mm2); pred+=lx; movq_r2r(mm2, mm3); punpcklbw_r2r(mm7, mm2); punpckhbw_r2r(mm7, mm3); paddw_r2r(mm2, mm0); paddw_r2r(mm3, mm1); packuswb_r2r(mm1, mm0); movq_r2m(mm0, *cur); cur+=lx; } emms(); } mjpegtools-2.1.0/mpeg2enc/transfrm_ref.h0000644000175000017500000000607511114314210020546 0ustar glowwormglowworm/* transfrm.h, Low-level transformation (DCT/iDCT and prediction * difference picture handling) routines */ /* * 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. * */ /* Modifications and extension (C) 2000-2003 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #ifndef _TRANSFRM_H #define _TRANSFRM_H #include "mjpeg_types.h" #ifdef __cplusplus extern "C" { #endif /* Pointers to version of transform and prediction manipulation routines to be used.. */ extern void (*pfdct)( int16_t * blk ); extern void (*pidct)( int16_t * blk ); extern void (*padd_pred) (uint8_t *pred, uint8_t *cur, int lx, int16_t *blk); extern void (*psub_pred) (uint8_t *pred, uint8_t *cur, int lx, int16_t *blk); extern int (*pfield_dct_best)( uint8_t *cur_lum_mb, uint8_t *pred_lum_mb, int stride); int field_dct_best( uint8_t *cur_lum_mb, uint8_t *pred_lum_mb, int stride); void add_pred (uint8_t *pred, uint8_t *cur, int lx, int16_t *blk); void sub_pred (uint8_t *pred, uint8_t *cur, int lx, int16_t *blk); void init_transform(void); void fdct( int16_t *blk ); void idct( int16_t *blk ); void init_fdct (void); void init_idct (void); #ifdef __cplusplus } #endif #endif /* _TRANSFRM_H */ /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/ratectl.cc0000644000175000017500000001140511445477341017671 0ustar glowwormglowworm/* ratectl.c, bitrate control routines (linear quantization only currently) */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ /* Modifications and enhancements (C) 2000,2001,2002,2003 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "config.h" #include #include #include "mjpeg_types.h" #include "mjpeg_logging.h" #include "mpeg2syntaxcodes.h" #include "tables.h" #include "simd.h" #include "fastintfns.h" #include "mpeg2encoder.hh" #include "picture.hh" #include "ratectl.hh" #include "quantize.hh" RateCtl::RateCtl( EncoderParams &_encparams, RateCtlState &_state ) : encparams( _encparams ), state( _state ) { } void RateCtl::PictSetup( Picture &picture) { /* Handle splitting of output stream into sequences of desired size */ if( picture.new_seq ) { InitSeq(); } if( picture.gop_decode == 0) { InitGOP(); } InitPict( picture ); } double RateCtl::ClipQuant( int q_scale_type, double quant ) { double quantf = quant; if ( q_scale_type ) { /* clip to legal (non-linear) range */ if (quantf<1) { quantf = 1; } if (quantf>111) { quantf = 112; } } else { /* clip mquant to legal (linear) range */ if (quantf<2.0) quantf = 2.0; if (quantf>62.0) quantf = 62.0; } return quantf; } double RateCtl::ScaleQuantf( int q_scale_type, double quant ) { double quantf; if ( q_scale_type ) { int iquantl, iquanth; double wl, wh; wh = quant-floor(quant); wl = 1.0 - wh; iquantl = (int) floor(quant); iquanth = iquantl+1; /* clip to legal (non-linear) range */ if (iquantl<1) { iquantl = 1; iquanth = 1; } if (iquantl>111) { iquantl = 112; iquanth = 112; } quantf = (double) wl * (double)non_linear_mquant_table[map_non_linear_mquant[iquantl]] + wh * (double)non_linear_mquant_table[map_non_linear_mquant[iquanth]] ; } else { /* clip mquant to legal (linear) range */ quantf = quant; if (quantf<2.0) quantf = 2; if (quantf>62.0) quantf = 62.0; } return quantf; } int RateCtl::ScaleQuant( int q_scale_type , double quant ) { double quantf = ClipQuant( q_scale_type, quant ); int iquant = (int)floor(quantf+0.5); if ( q_scale_type ) { iquant = non_linear_mquant_table[map_non_linear_mquant[iquant]]; } else { iquant = (iquant/2)*2; // Must be *even* } return iquant; } double RateCtl::InvScaleQuant( int q_scale_type, int raw_code ) { int i; if( q_scale_type ) { i = 112; while( 0 < i && map_non_linear_mquant[i] != raw_code ) --i; return ((double)i); } else return ((double)raw_code); } Pass1RateCtl::Pass1RateCtl( EncoderParams &_encparams, RateCtlState &_state ) : RateCtl( _encparams, _state ) { } Pass2RateCtl::Pass2RateCtl( EncoderParams &_encparams, RateCtlState &_state ) : RateCtl( _encparams, _state ) { } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/imageplanes.cc0000644000175000017500000000450210566454253020520 0ustar glowwormglowworm#include "imageplanes.hh" /********************* * * Construct ImagePlanes Raw video data container. * Constructs a high-patterned border around each video plane so that * 'blocks' overlapping the border won't match proper blocks inside. * This is useful for * motion estimation routines that, for speed, are a little * sloppy about some of the candidates they consider. * ********************/ ImagePlanes::ImagePlanes( EncoderParams &encparams ) { for( int c = 0; c < NUM_PLANES; ++c ) { // Allocate storage for image data switch( c ) { case 0 : // Y plane planes[c] = new uint8_t[encparams.lum_buffer_size]; BorderMark( planes[c] , encparams.enc_width,encparams.enc_height, encparams.phy_width,encparams.phy_height); break; case 1 : // U plane case 2 : // V plane planes[c] = new uint8_t[encparams.chrom_buffer_size]; BorderMark( planes[c], encparams.enc_chrom_width, encparams.enc_chrom_height, encparams.phy_chrom_width,encparams.phy_chrom_height); break; default : // TODO: shift Y subsampled data from appended in Y buffer to seperate planes planes[c] = 0; break; } } } ImagePlanes::~ImagePlanes() { for( int c = 0; c < NUM_PLANES; ++c ) { if( planes[c] != 0 ) delete [] planes[c]; } } void ImagePlanes::BorderMark( uint8_t *frame, int total_width, int total_height, int image_data_width, int image_data_height) { int i, j; uint8_t *fp; uint8_t mask = 0xff; /* horizontal pixel replication (right border) */ for (j=0; j using std::deque; /* Ensure we don't bury a system in wild spawning of threads... */ #define MAX_WORKER_THREADS 16 /* motion data */ struct motion_data { unsigned int forw_hor_f_code,forw_vert_f_code; /* vector range */ unsigned int sxf,syf; /* search range */ unsigned int back_hor_f_code,back_vert_f_code; unsigned int sxb,syb; }; struct RateCtl; class MPEG2EncOptions; class EncoderParams { public: EncoderParams( const MPEG2EncOptions &options); void Init(const MPEG2EncOptions &options); private: void InitQuantMatrices(const class MPEG2EncOptions &options); void InitEncodingControls(const class MPEG2EncOptions &options); void RangeChecks(); void ProfileAndLevelChecks(); public: /************** * * Global MPEG parameters (set by supplied stream, never * change in a run) * *************/ unsigned int horizontal_size, vertical_size; unsigned int aspectratio; /* aspect ratio information (pel or display) */ unsigned int frame_rate_code; /* coded value of playback display * frame rate */ int dctsatlim; /* Value to saturated DCT coeffs to */ double frame_rate; /* Playback display frames per second N.b. when 3:2 pullback is active this is higher than the frame decode rate. */ double bit_rate; /* bits per second, rate decode buffers filled (max rate) */ double target_bitrate; /* Target bit rate to achieve overall for VBR 0 if no target set */ unsigned int stream_frames; /* # Frames to representatively sample stream */ double stream_Xhi; /* Total stream complexity */ bool seq_hdr_every_gop; bool seq_end_every_gop; /* Useful for Stills sequences... */ bool svcd_scan_data; unsigned int vbv_buffer_code; /* Code for size of VBV buffer (* * 16 kbit) */ double vbv_buffer_size; unsigned int still_size; /* If non-0 encode a stills sequence: 1 I-frame per sequence pseudo VBR. Each frame sized to still_size KB */ unsigned int vbv_buffer_still_size; /* vbv_buffer_size holds still size. Ensure still size matches. */ bool constrparms; /* constrained parameters flag, MPEG-1 only */ bool load_iquant; bool load_niquant; /* use non-default quant. matrices */ int profile, level; /* syntax / parameter constraints */ bool ignore_constraints; /* Disabled conformance checking of * hor_size, vert_size and * samp_rate */ bool dualprime; /* Allow dual prime motion compensation */ bool prog_seq; /* progressive sequence */ int low_delay; /* no B pictures, skipped pictures */ /******* * * sequence specific data (sequence display extension) * ******/ unsigned int video_format; /* component, PAL, NTSC, SECAM or MAC */ unsigned int color_primaries; /* source primary chromaticity coordinates */ unsigned int transfer_characteristics; /* opto-electronic transfer char. (gamma) */ unsigned int matrix_coefficients; /* Eg,Eb,Er / Y,Cb,Cr matrix coefficients */ unsigned int display_horizontal_size; /* display size */ unsigned int display_vertical_size; bool mpeg1; /* ISO/IEC IS 11172-2 sequence */ bool fieldpic; /* use field pictures */ bool pulldown_32; /* 3:2 Pulldown of movie material */ bool topfirst; /************ * * Picture kind specific informatino (picture header flags) * ***********/ int frame_pred_dct_tab[3]; /* use only frame prediction and frame DCT (I,P,B) */ int qscale_tab[3]; /* linear/non-linear quantizaton table */ int intravlc_tab[3]; /* intra vlc format (I,P,B) */ int altscan_tab[3]; /* alternate scan (I,P,B */ unsigned int dc_prec; /**************************** * Encoder internal derived values and parameters *************************** */ int enc_width, enc_height; /* encoded frame size (pels) multiples of 16 or 32 */ int phy_width, phy_height; /* Physical Frame buffer size (pels) may differ from encoded size due to alignment constraints */ int enc_chrom_width,enc_chrom_height; int phy_chrom_width,phy_chrom_height; int lum_buffer_size, chrom_buffer_size; int mb_width, mb_height; /* frame size (macroblocks) */ /* Picture dimensioning (allowing for interlaced/non-interlaced coding) */ int phy_width2, phy_height2, enc_height2, mb_height2, phy_chrom_width2; int qsubsample_offset, fsubsample_offset; int mb_per_pict; /* Number of macro-blocks in a picture */ struct motion_data *motion_data; /* Selected intra/non_intra quantization matrices both ordinary*/ /* and inverted */ uint16_t *intra_q, *inter_q; /* ************************** * Global flags controlling encoding behaviour ************************** */ double decode_frame_rate; /* Actual stream frame * decode-rate. This is lower than * playback rate if 3:2 pulldown is * active. */ int video_buffer_size; /* Video buffer requirement target */ unsigned int N_max; /* number of frames in Group of Pictures (max) */ unsigned int N_min; /* number of frames in Group of Pictures (min) */ int M; /* distance between I/P frames */ int M_min; /* Minimum distance between I/P frames */ bool closed_GOPs; /* Force all GOPs to be closed - useful * for satisfying requirements for * multi-angle DVD authoring */ int me44_red; /* Sub-mean population reduction passes * for 4x4 and 2x2 */ int me22_red; /* Motion compensation stages */ int seq_length_limit; double nonvid_bit_rate; /* Bit-rate for non-video to assume for sequence splitting calculations */ double quant_floor; /* quantisation floor [1..10] (0 for * CBR) */ double act_boost; /* Quantisation reduction factor for blocks with little texture (low variance) */ double boost_var_ceil; /* Variance below which * quantisation boost cuts in */ int encoding_parallelism; /* Maximum number of concurrent worker threads to be used for encoding */ int unit_coeff_elim; /* Threshold of unit coefficient density below which unit coefficient blocks should be zeroed. < 0 implies DCT coefficient should be included. */ double coding_tolerance; /* Fraction of bit allocation that actual coding size may deviate from target set by rate controller before a re-encoding is forced */ deque chapter_points; /* Frame #'s for where chapters occur (I frames, closed GOP's) */ }; #endif /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/mpeg2encoptions.cc0000644000175000017500000004331611456612024021344 0ustar glowwormglowworm/* mpeg2encoptions.cc - Encoder control parameter class */ /* (C) 2000/2001/2003 Andrew Stevens, Rainer Johanni */ /* This software is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include #include "format_codes.h" #include "mpegconsts.h" #include "mpeg2encoder.hh" MPEG2EncOptions::MPEG2EncOptions() { // Parameters initialised to -1 indicate a format-dependent // or stream inferred default. format = MPEG_FORMAT_MPEG1; level = 0; // Use default display_hsize = 0; // Use default display_vsize = 0; // Use default bitrate = 0; target_bitrate = 0; nonvid_bitrate = 0; stream_frames = 0; // none specified by default stream_Xhi = 0.0; // off by default quant = 0; searchrad = 0; // Use default mpeg = 1; aspect_ratio = 0; frame_rate = 0; fieldenc = -1; /* 0: progressive, 1 = frame pictures, interlace frames with field MC and DCT in picture 2 = field pictures */ norm = 0; /* 'n': NTSC, 'p': PAL, 's': SECAM, else unspecified */ rate_control = 0; me44_red = 2; me22_red = 3; hf_quant = 0; hf_q_boost = 0.0; act_boost = 0.0; boost_var_ceil = 10*10; video_buffer_size = 0; seq_length_limit = 0; min_GOP_size = -1; max_GOP_size = -1; closed_GOPs = 0; preserve_B = 0; Bgrp_size = 1; /* * Set the default to 0 until this error: INFO: [mpeg2enc] Signaling last frame = 499 mpeg2enc: seqencoder.cc:433: void SeqEncoder::EncodeStream(): Assertion `pass1coded.size() == 0' failed. Abort * Is fixed. */ num_cpus = 0; vid32_pulldown = 0; svcd_scan_data = -1; seq_hdr_every_gop = 0; seq_end_every_gop = 0; still_size = 0; pad_stills_to_vbv_buffer_size = 0; vbv_buffer_still_size = 0; force_interlacing = Y4M_UNKNOWN; input_interlacing = Y4M_UNKNOWN; mpeg2_dc_prec = 1; ignore_constraints = 0; unit_coeff_elim = 0; force_cbr = 0; verbose = 1; hack_svcd_hds_bug = 1; hack_altscan_bug = 0; /* dual prime Disabled by default. --dualprime-mpeg2 to enable (set to 1) */ hack_dualprime = 0; force_cbr = 0; }; static int infer_mpeg1_aspect_code( char norm, mpeg_aspect_code_t mpeg2_code ) { switch( mpeg2_code ) { case 1 : /* 1:1 */ return 1; case 2 : /* 4:3 */ if( norm == 'p' || norm == 's' ) return 8; else if( norm == 'n' ) return 12; else return 0; case 3 : /* 16:9 */ if( norm == 'p' || norm == 's' ) return 3; else if( norm == 'n' ) return 6; else return 0; default : return 0; /* Unknown */ } } int MPEG2EncOptions::InferStreamDataParams( const MPEG2EncInVidParams &strm) { int nerr = 0; /* Infer norm, aspect ratios and frame_rate if not specified */ if( frame_rate == 0 ) { if(strm.frame_rate_code<1 || strm.frame_rate_code>8) { mjpeg_error("Input stream with unknown frame-rate and no frame-rate specified with -a!"); ++nerr; } else frame_rate = strm.frame_rate_code; } if( norm == 0 && (strm.frame_rate_code==3 || strm.frame_rate_code == 2) ) { mjpeg_info("Assuming norm PAL"); norm = 'p'; } if( norm == 0 && (strm.frame_rate_code==4 || strm.frame_rate_code == 1) ) { mjpeg_info("Assuming norm NTSC"); norm = 'n'; } if( frame_rate != 0 ) { if( strm.frame_rate_code != frame_rate && mpeg_valid_framerate_code(strm.frame_rate_code) ) { mjpeg_warn( "Specified display frame-rate %3.2f will over-ride", Y4M_RATIO_DBL(mpeg_framerate(frame_rate))); mjpeg_warn( "(different!) frame-rate %3.2f of the input stream", Y4M_RATIO_DBL(mpeg_framerate(strm.frame_rate_code))); } } if( aspect_ratio == 0 ) { aspect_ratio = strm.aspect_ratio_code; } if( aspect_ratio == 0 ) { mjpeg_warn( "No aspect ratio specifed and no guess possible: assuming 4:3 display aspect!"); aspect_ratio = 2; } /* Convert to MPEG1 coding if we're generating MPEG1 */ if( mpeg == 1 ) { aspect_ratio = infer_mpeg1_aspect_code( norm, aspect_ratio ); } input_interlacing = strm.interlacing_code; if (input_interlacing == Y4M_UNKNOWN) { mjpeg_warn("Unknown input interlacing; assuming progressive."); input_interlacing = Y4M_ILACE_NONE; } /* 'fieldenc' is dependent on input stream interlacing: a) Interlaced streams are subsampled _per_field_; progressive streams are subsampled over whole frame. b) 'fieldenc' sets/clears the MPEG2 'progressive-frame' flag, which tells decoder how subsampling was performed. */ if (fieldenc == -1) { /* not set yet... so set fieldenc from input interlacing */ switch (input_interlacing) { case Y4M_ILACE_TOP_FIRST: case Y4M_ILACE_BOTTOM_FIRST: fieldenc = 1; /* interlaced frames */ mjpeg_info("Interlaced input - selecting interlaced encoding."); break; case Y4M_ILACE_NONE: fieldenc = 0; /* progressive frames */ mjpeg_info("Progressive input - selecting progressive encoding."); break; default: mjpeg_warn("Unknown input interlacing; assuming progressive."); fieldenc = 0; break; } } else { /* fieldenc has been set already... so double-check for user */ switch (input_interlacing) { case Y4M_ILACE_TOP_FIRST: case Y4M_ILACE_BOTTOM_FIRST: if (fieldenc == 0) { mjpeg_warn("Progressive encoding selected with interlaced input!"); mjpeg_warn(" (This will damage the chroma channels.)"); } break; case Y4M_ILACE_NONE: if (fieldenc != 0) { mjpeg_warn("Interlaced encoding selected with progressive input!"); mjpeg_warn(" (This will damage the chroma channels.)"); } break; } } return nerr; } int MPEG2EncOptions::CheckBasicConstraints() { int nerr = 0; if( vid32_pulldown ) { if( mpeg == 1 ) mjpeg_error_exit1( "MPEG-1 cannot encode 3:2 pulldown (for transcoding to VCD set 24fps)!" ); if( frame_rate != 4 && frame_rate != 5 ) { if( frame_rate == 1 || frame_rate == 2 ) { frame_rate += 3; mjpeg_warn("3:2 movie pulldown with frame rate set to decode rate not display rate"); mjpeg_warn("3:2 Setting frame rate code to display rate = %d (%2.3f fps)", frame_rate, Y4M_RATIO_DBL(mpeg_framerate(frame_rate))); } else { mjpeg_error( "3:2 movie pulldown not sensible for %2.3f fps dispay rate", Y4M_RATIO_DBL(mpeg_framerate(frame_rate))); ++nerr; } } if( fieldenc == 2 ) { mjpeg_error( "3:2 pulldown only possible for frame pictures (-I 1 or -I 0)"); ++nerr; } } if ((mpeg == 1) && (fieldenc != 0)) { mjpeg_error("Interlaced encoding (-I != 0) is not supported by MPEG-1."); ++nerr; } if( !mpeg_valid_aspect_code(mpeg, aspect_ratio) ) { mjpeg_error("For MPEG-%d, aspect ratio code %d is illegal", mpeg, aspect_ratio); ++nerr; } if( min_GOP_size > max_GOP_size ) { mjpeg_error( "Min GOP size must be <= Max GOP size" ); ++nerr; } if( stream_frames > 0 && stream_frames < 4*max_GOP_size ) { mjpeg_error( "-L must be at at least 4 GOP lengths (4 * -G)" ); ++nerr; } if( preserve_B && Bgrp_size == 0 ) { mjpeg_error_exit1("Preserving I/P frame spacing is impossible for still encoding" ); } if( preserve_B && ( min_GOP_size % Bgrp_size != 0 || max_GOP_size % Bgrp_size != 0 ) ) { mjpeg_error("Preserving I/P frame spacing is impossible if min and max GOP sizes are" ); mjpeg_error_exit1("Not both divisible by %d", Bgrp_size ); } switch( format ) { case MPEG_FORMAT_SVCD_STILL : case MPEG_FORMAT_SVCD_NSR : case MPEG_FORMAT_SVCD : if( aspect_ratio != 2 && aspect_ratio != 3 ) mjpeg_error_exit1("SVCD only supports 4:3 and 16:9 aspect ratios"); if( svcd_scan_data ) { mjpeg_warn( "Generating dummy SVCD scan-data offsets to be filled in by \"vcdimager\""); mjpeg_warn( "If you're not using vcdimager you may wish to turn this off using -d"); } break; case MPEG_FORMAT_ATSC480i : if( frame_rate != 4 && frame_rate != 5 ) { mjpeg_warn( "ATSC 480p only supports 29.97 and 30 frames/sec" ); } case MPEG_FORMAT_ATSC480p : if( (in_img_width != 704 && in_img_width != 640) || in_img_height != 480 ) { mjpeg_warn( "ATSC 480i/480p requires 640x480 or 704x480 input images!" ); } if( in_img_width == 704 && aspect_ratio != 2 && aspect_ratio != 3 ) { mjpeg_warn( "ATSC 480i/480p 704x480 only supports aspect ratio codes 2 and 3 (4:3 and 16:9)" ); } if( in_img_width == 640 && aspect_ratio != 1 && aspect_ratio != 2 ) { mjpeg_warn( "ATSC 480i/480p 704x480 only supports aspect ratio codes 1 and 2 (square pixel and 4:3)" ); } break; case MPEG_FORMAT_ATSC720p : if( in_img_width != 1280 || in_img_height != 720 ) { mjpeg_warn( "ATSC 720p requires 1280x720 input images!" ); } if( aspect_ratio != 1 && aspect_ratio != 3 ) { mjpeg_warn( "ATSC 720p only supports aspect ratio codes 1 and 3 (square pixel and 16:9)" ); } break; case MPEG_FORMAT_ATSC1080i : if( in_img_width != 1920 || in_img_height != 1088 ) { mjpeg_warn( "ATSC 1080i requires 1920x1088 input images!" ); } if( aspect_ratio != 1 && aspect_ratio != 3 ) { mjpeg_warn( "ATSC 1080i only supports aspect ratio codes 1 and 3 (square pixel and 16:9)" ); } if( frame_rate > 7 ) { mjpeg_warn( "ATSC 1080i only supports frame rates up to 30 frame/sec/" ); } break; } if( MPEG_ATSC_FORMAT(format) ) { if( bitrate > 38800000 ) { mjpeg_warn( "ATSC specifies a maximum high data rate mode bitrate of 38.8Mbps" ); } if( frame_rate == 3 || frame_rate == 6 ) { mjpeg_warn( "ATSC does not support 25 or 50 frame/sec video" ); } } return nerr; } bool MPEG2EncOptions::SetFormatPresets( const MPEG2EncInVidParams &strm ) { int nerr = 0; in_img_width = strm.horizontal_size; in_img_height = strm.vertical_size; mjpeg_info( "Selecting %s output profile", mpeg_format_code_defintion(format)); switch( format ) { case MPEG_FORMAT_MPEG1 : /* Generic MPEG1 */ if( video_buffer_size == 0 ) video_buffer_size = 46; if (bitrate == 0) bitrate = 1151929; if (searchrad == 0) searchrad = 16; break; case MPEG_FORMAT_VCD : mpeg = 1; bitrate = 1151929; video_buffer_size = 46; preserve_B = true; Bgrp_size = 3; min_GOP_size = 9; max_GOP_size = norm == 'n' ? 18 : 15; case MPEG_FORMAT_VCD_NSR : /* VCD format, non-standard rate */ mpeg = 1; svcd_scan_data = 0; seq_hdr_every_gop = 1; if (bitrate == 0) bitrate = 1151929; if (video_buffer_size == 0) video_buffer_size = 46 * bitrate / 1151929; if (seq_length_limit == 0 ) seq_length_limit = 700; if (nonvid_bitrate == 0) nonvid_bitrate = 230; break; case MPEG_FORMAT_MPEG2 : mpeg = 2; if (!force_cbr && quant == 0) quant = 8; if (video_buffer_size == 0) video_buffer_size = 230; break; case MPEG_FORMAT_SVCD : if (nonvid_bitrate == 0) /* 224 kbps for audio + around 2% of 2788800 bits */ nonvid_bitrate = 288; if (bitrate == 0 || bitrate > 2788800 - nonvid_bitrate * 1000) bitrate = 2788800 - nonvid_bitrate * 1000; max_GOP_size = norm == 'n' ? 18 : 15; video_buffer_size = 230; case MPEG_FORMAT_SVCD_NSR : /* Non-standard data-rate */ mpeg = 2; if (!force_cbr && quant == 0) quant = 8; if( svcd_scan_data == -1 ) svcd_scan_data = 1; if (video_buffer_size == 0) video_buffer_size = 230; if( min_GOP_size == -1 ) min_GOP_size = 9; seq_hdr_every_gop = 1; if (seq_length_limit == 0) seq_length_limit = 700; if (nonvid_bitrate == 0) nonvid_bitrate = 230; break; case MPEG_FORMAT_VCD_STILL : mpeg = 1; quant = 0; /* We want to try and hit our size target */ /* We choose a generous nominal bit-rate as there's only one frame per sequence ;-). It *is* too small to fill the frame-buffer in less than one PAL/NTSC frame period though...*/ bitrate = 8000000; /* Now we select normal/hi-resolution based on the input stream resolution. */ if( in_img_width == 352 && (in_img_height == 240 || in_img_height == 288 ) ) { /* VCD normal resolution still */ if( still_size == 0 ) still_size = 30*1024; if( still_size < 20*1024 || still_size > 42*1024 ) { mjpeg_error_exit1( "VCD normal-resolution stills must be >= 20KB and <= 42KB each"); } /* VBV delay encoded normally */ vbv_buffer_still_size = 46*1024; video_buffer_size = 46; pad_stills_to_vbv_buffer_size = 0; } else if( in_img_width == 704 && (in_img_height == 480 || in_img_height == 576) ) { /* VCD high-resolution stills: only these use vbv_delay to encode picture size... */ if( still_size == 0 ) still_size = 125*1024; if( still_size < 46*1024 || still_size > 220*1024 ) { mjpeg_error_exit1( "VCD normal-resolution stills should be >= 46KB and <= 220KB each"); } vbv_buffer_still_size = still_size; video_buffer_size = 224; pad_stills_to_vbv_buffer_size = 1; } else { mjpeg_error("VCD normal resolution stills must be 352x288 (PAL) or 352x240 (NTSC)"); mjpeg_error_exit1( "VCD high resolution stills must be 704x576 (PAL) or 704x480 (NTSC)"); } seq_hdr_every_gop = 1; seq_end_every_gop = 1; min_GOP_size = 1; max_GOP_size = 1; break; case MPEG_FORMAT_SVCD_STILL : mpeg = 2; quant = 0; /* We want to try and hit our size target */ /* We choose a generous nominal bitrate as there's only one frame per sequence ;-). It *is* too small to fill the frame-buffer in less than one PAL/NTSC frame period though... */ bitrate = 2500000; video_buffer_size = 230; vbv_buffer_still_size = 220*1024; pad_stills_to_vbv_buffer_size = 0; /* Now we select normal/hi-resolution based on the input stream resolution. */ if( in_img_width == 480 && (in_img_height == 480 || in_img_height == 576 ) ) { mjpeg_info( "SVCD normal-resolution stills selected." ); if( still_size == 0 ) still_size = 90*1024; } else if( in_img_width == 704 && (in_img_height == 480 || in_img_height == 576) ) { mjpeg_info( "SVCD high-resolution stills selected." ); if( still_size == 0 ) still_size = 125*1024; } else { mjpeg_error("SVCD normal resolution stills must be 480x576 (PAL) or 480x480 (NTSC)"); mjpeg_error_exit1( "SVCD high resolution stills must be 704x576 (PAL) or 704x480 (NTSC)"); } if( still_size < 30*1024 || still_size > 200*1024 ) { mjpeg_error_exit1( "SVCD resolution stills must be >= 30KB and <= 200KB each"); } seq_hdr_every_gop = 1; seq_end_every_gop = 1; min_GOP_size = 1; max_GOP_size = 1; break; case MPEG_FORMAT_DVD : case MPEG_FORMAT_DVD_NAV : mpeg = 2; if (bitrate == 0) bitrate = 7500000; if (video_buffer_size == 0) video_buffer_size = 230; if (!force_cbr && quant == 0) quant = 8; seq_hdr_every_gop = 1; break; case MPEG_FORMAT_ATSC720p : case MPEG_FORMAT_ATSC1080i : // Need a bigger pixel search radius for HD // images :-( if (searchrad == 0) searchrad = 32; case MPEG_FORMAT_ATSC480i : case MPEG_FORMAT_ATSC480p : mpeg = 2; video_buffer_size = 488; if (bitrate == 0) bitrate = 19400000; if (!force_cbr && quant == 0) quant = 8; } /* * At this point the command line arguments have been processed, the format (-f) * selection has had a chance to set the bitrate. IF --cbr was used and we * STILL do not have a bitrate set then declare an error because a Constant * Bit Rate of 0 makes no sense (most of the time CBR doesn't either ... ;)) */ if (force_cbr && bitrate == 0) { nerr++; mjpeg_error("--cbr used but no bitrate set with -b or -f!"); } switch( mpeg ) { case 1 : if( min_GOP_size == -1 ) min_GOP_size = 12; if( max_GOP_size == -1 ) max_GOP_size = 12; break; case 2: if( max_GOP_size == -1 ) max_GOP_size = (norm == 'n' ? 18 : 15); if( min_GOP_size == -1 ) min_GOP_size = max_GOP_size/2; break; } if( svcd_scan_data == -1 ) svcd_scan_data = 0; if (searchrad == 0) searchrad = 16; nerr += InferStreamDataParams(strm); nerr += CheckBasicConstraints(); return nerr != 0; } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/tables.h0000644000175000017500000000520011445477341017343 0ustar glowwormglowworm/* tables.h, Tables for MPEG syntax */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ /* global syntax look-up tables */ #include "mjpeg_types.h" #ifdef __cplusplus #define CLINKAGE "C" #else #define CLINKAGE #endif #define EXTERNTBL extern CLINKAGE EXTERNTBL const char version[]; EXTERNTBL const char author[]; EXTERNTBL const uint8_t zig_zag_scan[64]; /* zig-zag Macroblock scan */ EXTERNTBL const uint8_t alternate_scan[64]; /* alternate Macroblock scan */ /* default intra quantization matrix */ EXTERNTBL const uint16_t default_intra_quantizer_matrix[64]; EXTERNTBL const uint16_t hires_intra_quantizer_matrix[64]; EXTERNTBL const uint16_t default_nonintra_quantizer_matrix[64]; EXTERNTBL const uint16_t kvcd_intra_quantizer_matrix[64]; EXTERNTBL const uint16_t kvcd_nonintra_quantizer_matrix[64]; EXTERNTBL const uint16_t flat_intra_quantizer_matrix[64]; EXTERNTBL const uint16_t flat_nonintra_quantizer_matrix[64]; EXTERNTBL const uint16_t tmpgenc_intra_quantizer_matrix[64]; EXTERNTBL const uint16_t tmpgenc_nonintra_quantizer_matrix[64]; /* Hires non intra quantization matrix. This *is* the MPEG default... */ EXTERNTBL const uint16_t *hires_nonintra_quantizer_matrix; EXTERNTBL const char pict_type_char[6]; /* Support for the picture layer(!) insertion of scan data fieldsas MPEG user-data section as part of I-frames. */ EXTERNTBL const uint8_t dummy_svcd_scan_data[14]; EXTERNTBL const uint8_t map_non_linear_mquant[113]; EXTERNTBL const uint8_t non_linear_mquant_table[32]; mjpegtools-2.1.0/mpeg2enc/picturereader.hh0000644000175000017500000000404210444645161021075 0ustar glowwormglowworm#ifndef _PICTUREREADER_HH #define _PICTUREREADER_HH /* readpic.h Picture reader base class and basic file I/O based reader */ /* (C) 2000/2001 Andrew Stevens */ /* This Software is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include #include #include "mjpeg_types.h" #include "picture.hh" class EncoderParams; class ImagePlanes; struct MPEG2EncInVidParams; class PictureReader { public: PictureReader(EncoderParams &encoder ); virtual ~PictureReader(); void Init(); void ReadPictureData( int num_frame, ImagePlanes &frame); virtual void StreamPictureParams( MPEG2EncInVidParams &strm ) = 0; ImagePlanes *ReadFrame( int num_frame ); void ReleaseFrame( int num_frame ); void FillBufferUpto( int num_frame ); inline int NumberOfFrames() { return istrm_nframes; } protected: void ReadChunkSequential( int num_frame ); void AllocateBufferUpto( int buffer_slot ); virtual bool LoadFrame( ImagePlanes &image ) = 0; protected: EncoderParams &encparams; int frames_read; int frames_released; std::deque input_imgs_buf; std::deque unused; int istrm_nframes; // Number of frames in stream once EOS known, // Otherwise INT_MAX }; /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ #endif mjpegtools-2.1.0/mpeg2enc/stats.cc0000644000175000017500000003132307746532240017371 0ustar glowwormglowworm/* stats.c, coding statistics */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ /* Modifications and enhancements (C) 2000/2001 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include #include #include #include "picture.hh" #ifdef OUTPUT_STAT static void calcSNR1(org,rec,lx,w,h,pv,pe) unsigned char *org; unsigned char *rec; int lx,w,h; double *pv,*pe; { int i, j; double v1, s1, s2, e2; s1 = s2 = e2 = 0.0; for (j=0; j>1); offs = (cur_picture.pict_struct==BOTTOM_FIELD) ? width : 0; calcSNR1(org[0]+offs,rec[0]+offs,width2,w,h,&v,&e); fprintf(statfile,"Y: variance=%4.4g, MSE=%3.3g (%3.3g dB), SNR=%3.3g dB\n", v, e, 10.0*log10(255.0*255.0/e), 10.0*log10(v/e)); if (chroma_format!=CHROMA444) { w >>= 1; offs >>= 1; } if (chroma_format==CHROMA420) h >>= 1; calcSNR1(org[1]+offs,rec[1]+offs,chrom_width2,w,h,&v,&e); fprintf(statfile,"U: variance=%4.4g, MSE=%3.3g (%3.3g dB), SNR=%3.3g dB\n", v, e, 10.0*log10(255.0*255.0/e), 10.0*log10(v/e)); calcSNR1(org[2]+offs,rec[2]+offs,chrom_width2,w,h,&v,&e); fprintf(statfile,"V: variance=%4.4g, MSE=%3.3g (%3.3g dB), SNR=%3.3g dB\n", v, e, 10.0*log10(255.0*255.0/e), 10.0*log10(v/e)); #endif } void Picture::Stats() { #ifdef OUTPUT_STAT int i, j, k, mb_type; int n_skipped, n_intra, n_ncoded, n_blocks, n_interp, n_forward, n_backward; struct mbinfo *mbi; /* Needs adjusting to reflect its move... */ #ifdef NOT_DONE_YET if (pict_type!=I_TYPE) { fprintf(statfile," forward search window: %d...%d / %d...%d\n", -sxf,sxf,-syf,syf); fprintf(statfile," forward vector range: %d...%d.5 / %d...%d.5\n", -(4<skipped) n_skipped++; else if (mbi->mb_type & MB_INTRA) n_intra++; else if (!(mbi->mb_type & MB_PATTERN)) n_ncoded++; for (i=0; icbp & (1<mb_type & MB_FORWARD) { if (mbi->mb_type & MB_BACKWARD) n_interp++; else n_forward++; } else if (mbi->mb_type & MB_BACKWARD) n_backward++; } fprintf(statfile,"\npicture statistics:\n"); fprintf(statfile," # of intra coded macroblocks: %4d (%.1f%%)\n", n_intra,100.0*(double)n_intra/mb_per_pict); fprintf(statfile," # of coded blocks: %4d (%.1f%%)\n", n_blocks,100.0*(double)n_blocks/(block_count*mb_per_pict)); fprintf(statfile," # of not coded macroblocks: %4d (%.1f%%)\n", n_ncoded,100.0*(double)n_ncoded/mb_per_pict); fprintf(statfile," # of skipped macroblocks: %4d (%.1f%%)\n", n_skipped,100.0*(double)n_skipped/mb_per_pict); fprintf(statfile," # of forw. pred. macroblocks: %4d (%.1f%%)\n", n_forward,100.0*(double)n_forward/mb_per_pict); fprintf(statfile," # of backw. pred. macroblocks: %4d (%.1f%%)\n", n_backward,100.0*(double)n_backward/mb_per_pict); fprintf(statfile," # of interpolated macroblocks: %4d (%.1f%%)\n", n_interp,100.0*(double)n_interp/mb_per_pict); fprintf(statfile,"\nmacroblock_type map:\n"); k = 0; for (j=0; jmb_type; if (mbi->skipped) putc('S',statfile); else if (mb_type & MB_INTRA) putc('I',statfile); else switch (mb_type & (MB_FORWARD|MB_BACKWARD)) { case MB_FORWARD: putc(mbi->motion_type==MC_FIELD ? 'f' : mbi->motion_type==MC_DMV ? 'p' : 'F',statfile); break; case MB_BACKWARD: putc(mbi->motion_type==MC_FIELD ? 'b' : 'B',statfile); break; case MB_FORWARD|MB_BACKWARD: putc(mbi->motion_type==MC_FIELD ? 'd' : 'D',statfile); break; default: putc('0',statfile); break; } if (mb_type & MB_QUANT) putc('Q',statfile); else if (mb_type & (MB_PATTERN|MB_INTRA)) putc(' ',statfile); else putc('N',statfile); putc(' ',statfile); k++; } putc('\n',statfile); } fprintf(statfile,"\nmquant map:\n"); k=0; for (j=0; j 24 ) return; /* useful for debugging */ fprintf(statfile,"\nmacroblock info dump:\n"); k=0; for (j=10; j #include #include #include "mpeg2syntaxcodes.h" #include "tables.h" #include "simd.h" #include "mpeg2encoder.hh" #include "mpeg2coder.hh" #include "ratectl.hh" #include "macroblock.hh" #include "picture.hh" /* output motion vectors (6.2.5.2, 6.3.16.2) * * this routine also updates the predictions for motion vectors (PMV) */ void Picture::PutMVs( MotionEst &me, bool back ) { int hor_f_code; int vert_f_code; if( back ) { hor_f_code = back_hor_f_code; vert_f_code = back_vert_f_code; } else { hor_f_code = forw_hor_f_code; vert_f_code = forw_vert_f_code; } if (pict_struct==FRAME_PICTURE) { if (me.motion_type==MC_FRAME) { /* frame prediction */ coding->PutMV(me.MV[0][back][0]-PMV[0][back][0],hor_f_code); coding->PutMV(me.MV[0][back][1]-PMV[0][back][1],vert_f_code); PMV[0][back][0]=PMV[1][back][0]=me.MV[0][back][0]; PMV[0][back][1]=PMV[1][back][1]=me.MV[0][back][1]; } else if (me.motion_type==MC_FIELD) { /* field prediction */ coding->PutBits(me.field_sel[0][back],1); coding->PutMV(me.MV[0][back][0]-PMV[0][back][0],hor_f_code); coding->PutMV((me.MV[0][back][1]>>1)-(PMV[0][back][1]>>1),vert_f_code); coding->PutBits(me.field_sel[1][back],1); coding->PutMV(me.MV[1][back][0]-PMV[1][back][0],hor_f_code); coding->PutMV((me.MV[1][back][1]>>1)-(PMV[1][back][1]>>1),vert_f_code); PMV[0][back][0]=me.MV[0][back][0]; PMV[0][back][1]=me.MV[0][back][1]; PMV[1][back][0]=me.MV[1][back][0]; PMV[1][back][1]=me.MV[1][back][1]; } else { #ifdef DEBUG_DPME MotionVector DMV[Parity::dim /*pred*/]; calc_DMV(*this, DMV, me.dualprimeMV, me.MV[0][0][0], me.MV[0][0][1]>>1); printf( "PR%06d: %03d %03d %03d %03d %03d %03d\n", dp_mv, me.MV[0][0][0], (me.MV[0][0][1]>>1), DMV[0][0], DMV[0][1], DMV[1][0], DMV[1][1] ); ++dp_mv; if( dp_mv == 45000 ) exit(0); #endif /* dual prime prediction */ coding->PutMV(me.MV[0][back][0]-PMV[0][back][0],hor_f_code); coding->PutDMV(me.dualprimeMV[0]); coding->PutMV((me.MV[0][back][1]>>1)-(PMV[0][back][1]>>1),vert_f_code); coding->PutDMV(me.dualprimeMV[1]); PMV[0][back][0]=PMV[1][back][0]=me.MV[0][back][0]; PMV[0][back][1]=PMV[1][back][1]=me.MV[0][back][1]; } } else { /* field picture */ if (me.motion_type==MC_FIELD) { /* field prediction */ coding->PutBits(me.field_sel[0][back],1); coding->PutMV(me.MV[0][back][0]-PMV[0][back][0],hor_f_code); coding->PutMV(me.MV[0][back][1]-PMV[0][back][1],vert_f_code); PMV[0][back][0]=PMV[1][back][0]=me.MV[0][back][0]; PMV[0][back][1]=PMV[1][back][1]=me.MV[0][back][1]; } else if (me.motion_type==MC_16X8) { /* 16x8 prediction */ coding->PutBits(me.field_sel[0][back],1); coding->PutMV(me.MV[0][back][0]-PMV[0][back][0],hor_f_code); coding->PutMV(me.MV[0][back][1]-PMV[0][back][1],vert_f_code); coding->PutBits(me.field_sel[1][back],1); coding->PutMV(me.MV[1][back][0]-PMV[1][back][0],hor_f_code); coding->PutMV(me.MV[1][back][1]-PMV[1][back][1],vert_f_code); PMV[0][back][0]=me.MV[0][back][0]; PMV[0][back][1]=me.MV[0][back][1]; PMV[1][back][0]=me.MV[1][back][0]; PMV[1][back][1]=me.MV[1][back][1]; } else { /* dual prime prediction */ coding->PutMV(me.MV[0][back][0]-PMV[0][back][0],hor_f_code); coding->PutDMV(me.dualprimeMV[0]); coding->PutMV(me.MV[0][back][1]-PMV[0][back][1],vert_f_code); coding->PutDMV(me.dualprimeMV[1]); PMV[0][back][0]=PMV[1][back][0]=me.MV[0][back][0]; PMV[0][back][1]=PMV[1][back][1]=me.MV[0][back][1]; } } } void Picture::PutDCTBlocks( MacroBlock &mb, int mb_type ) { int comp; int cc; for (comp=0; compPutIntraBlk(this, mb.QuantDCTblocks()[comp],cc); } else { coding->PutNonIntraBlk(this,mb.QuantDCTblocks()[comp]); } } } } /* generate picture header (6.2.3, 6.3.10) */ void Picture::PutHeader() { assert( coding->Aligned() ); coding->PutBits(PICTURE_START_CODE,32); /* picture_start_code */ coding->PutBits(temp_ref,10); /* temporal_reference */ coding->PutBits(pict_type,3); /* picture_coding_type */ coding->PutBits(FFFF_VBV_DELAY,16); /* vbv_delay */ if (pict_type==P_TYPE || pict_type==B_TYPE) { coding->PutBits(0,1); /* full_pel_forward_vector */ if (encparams.mpeg1) coding->PutBits(forw_hor_f_code,3); else coding->PutBits(7,3); /* forward_f_code */ } if (pict_type==B_TYPE) { coding->PutBits(0,1); /* full_pel_backward_vector */ if (encparams.mpeg1) coding->PutBits(back_hor_f_code,3); else coding->PutBits(7,3); /* backward_f_code */ } coding->PutBits(0,1); /* extra_bit_picture */ coding->AlignBits(); if ( !encparams.mpeg1 ) { PutCodingExt(); } } /* generate picture coding extension (6.2.3.1, 6.3.11) * * composite display information (v_axis etc.) not implemented */ void Picture::PutCodingExt() { assert( coding->Aligned() ); coding->PutBits(EXT_START_CODE,32); /* extension_start_code */ coding->PutBits(CODING_ID,4); /* extension_start_code_identifier */ coding->PutBits(forw_hor_f_code,4); /* forward_horizontal_f_code */ coding->PutBits(forw_vert_f_code,4); /* forward_vertical_f_code */ coding->PutBits(back_hor_f_code,4); /* backward_horizontal_f_code */ coding->PutBits(back_vert_f_code,4); /* backward_vertical_f_code */ coding->PutBits(dc_prec,2); /* intra_dc_precision */ coding->PutBits(pict_struct,2); /* picture_structure */ coding->PutBits((pict_struct==FRAME_PICTURE)?topfirst : 0, 1); /* top_field_first */ coding->PutBits(frame_pred_dct,1); /* frame_pred_frame_dct */ coding->PutBits(0,1); /* concealment_motion_vectors -- currently not implemented */ coding->PutBits(q_scale_type,1); /* q_scale_type */ coding->PutBits(intravlc,1); /* intra_vlc_format */ coding->PutBits(altscan,1); /* alternate_scan */ coding->PutBits(repeatfirst,1); /* repeat_first_field */ coding->PutBits(prog_frame,1); /* chroma_420_type */ coding->PutBits(prog_frame,1); /* progressive_frame */ coding->PutBits(0,1); /* composite_display_flag */ coding->AlignBits(); } void Picture::PutSliceHdr( int slice_mb_y, int mquant ) { /* slice header (6.2.4) */ coding->AlignBits(); if (encparams.mpeg1 || encparams.vertical_size<=2800) coding->PutBits(SLICE_MIN_START+slice_mb_y,32); /* slice_start_code */ else { coding->PutBits(SLICE_MIN_START+(slice_mb_y&127),32); /* slice_start_code */ coding->PutBits(slice_mb_y>>7,3); /* slice_vertical_position_extension */ } /* quantiser_scale_code */ coding->PutBits(q_scale_type ? map_non_linear_mquant[mquant] : mquant >> 1, 5); coding->PutBits(0,1); /* extra_bit_slice */ } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/predcomp_mmxe.c0000644000175000017500000001440510163112251020710 0ustar glowwormglowworm/* * predcomp_00_mmxe.s: * * Extended MMX prediction composition * routines handling the four different interpolation cases... * * Copyright (C) 2000 Andrew Stevens * * * This program is free software; you can reaxstribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include #include "mjpeg_types.h" #include "mmx.h" /* * void predcomp__mmxe(char *src,char *dst,int lx, int w, int h, int mask); * * ix - Interpolation in x iy - Interpolation in y * */ /* The no interpolation case... */ void predcomp_00_mmxe(char *src,char *dst,int lx, int w, int h, int mask) { movd_g2r(mask, mm0); pxor_r2r(mm2, mm2); punpckldq_r2r(mm0, mm0); pcmpeqd_r2r(mm2, mm0); movq_r2r(mm0, mm1); pcmpeqd_r2r(mm2, mm0); do { movq_m2r(*src, mm4); /* first 8 bytes of row */ movq_m2r(*dst, mm2); pand_r2r(mm0, mm2); movq_r2r(mm4, mm3); pand_r2r(mm1, mm3); por_r2r(mm3, mm2); pavgb_r2r(mm2, mm4); movq_r2m(mm4, *dst); if (w != 8) { movq_m2r(*(src+8), mm4); /* first 8 bytes of row */ movq_m2r(*(dst+8), mm2); pand_r2r(mm0, mm2); movq_r2r(mm4, mm3); pand_r2r(mm1, mm3); por_r2r(mm3, mm2); pavgb_r2r(mm2, mm4); movq_r2m(mm4, *(dst+8)); } dst += lx; src += lx; h--; } while (h); emms(); } /* The x-axis interpolation case... */ void predcomp_10_mmxe(char *src,char *dst,int lx, int w, int h, int mask) { movd_g2r(mask, mm0); pxor_r2r(mm2, mm2); punpckldq_r2r(mm0, mm0); pcmpeqd_r2r(mm2, mm0); movq_r2r(mm0, mm1); pcmpeqd_r2r(mm2, mm0); do { movq_m2r(*src, mm4); /* first 8 bytes row: avg src in x */ pavgb_m2r(*(src+1), mm4); movq_m2r(*dst, mm2); pand_r2r(mm0, mm2); movq_r2r(mm4, mm3); pand_r2r(mm1, mm3); por_r2r(mm3, mm2); pavgb_r2r(mm2, mm4); /* combine */ movq_r2m(mm4, *dst); if (w != 8) { movq_m2r(*(src+8), mm4); /* first 8 bytes row: avg src in x */ pavgb_m2r(*(src+9), mm4); movq_m2r(*(dst+8), mm2); pand_r2r(mm0, mm2); movq_r2r(mm4, mm3); pand_r2r(mm1, mm3); por_r2r(mm3, mm2); pavgb_r2r(mm2, mm4); /* combine */ movq_r2m(mm4, *(dst+8)); } dst += lx; src += lx; h--; } while (h); emms(); } /* The x-axis and y-axis interpolation case... */ void predcomp_11_mmxe(char *src,char *dst,int lx, int w, int h, int mask) { /* mm2 = [0,0,0,0]W */ /* mm3 = [2,2,2,2]W */ movd_g2r(0x00020002, mm3); punpckldq_r2r(mm3, mm3); movd_g2r(mask, mm0); pxor_r2r(mm2, mm2); punpckldq_r2r(mm0, mm0); pcmpeqd_r2r(mm2, mm0); movq_r2r(mm0, mm1); pcmpeqd_r2r(mm2, mm0); do { movq_m2r(*src, mm4); /* mm4 and mm6 accumulate partial sums for interp. */ movq_r2r(mm4, mm6); punpcklbw_r2r(mm2, mm4); punpckhbw_r2r(mm2, mm6); movq_m2r(*(src+1), mm5); movq_r2r(mm5, mm7); punpcklbw_r2r(mm2, mm5); paddw_r2r(mm5, mm4); punpckhbw_r2r(mm2, mm7); paddw_r2r(mm7, mm6); src += lx; movq_m2r(*src, mm5); /* first 8 bytes 1st row: avg src in x */ movq_r2r(mm5, mm7); punpcklbw_r2r(mm2, mm5); paddw_r2r(mm5, mm4); punpckhbw_r2r(mm2, mm7); paddw_r2r(mm7, mm6); movq_m2r(*(src+1), mm5); movq_r2r(mm5, mm7); punpcklbw_r2r(mm2, mm5); paddw_r2r(mm5, mm4); punpckhbw_r2r(mm2, mm7); paddw_r2r(mm7, mm6); /* Now round and repack... */ paddw_r2r(mm3, mm4); paddw_r2r(mm3, mm6); psrlw_i2r(2, mm4); psrlw_i2r(2, mm6); packuswb_r2r(mm6, mm4); movq_m2r(*dst, mm7); pand_r2r(mm0, mm7); movq_r2r(mm4, mm6); pand_r2r(mm1, mm6); por_r2r(mm6, mm7); pavgb_r2r(mm7, mm4); movq_r2m(mm4, *dst); if (w != 8) { src -= lx; /* Back to 1st row */ movq_m2r(*(src+8), mm4); /* mm4 and mm6 accumulate partial sums for interp. */ movq_r2r(mm4, mm6); punpcklbw_r2r(mm2, mm4); punpckhbw_r2r(mm2, mm6); movq_m2r(*(src+9), mm5); movq_r2r(mm5, mm7); punpcklbw_r2r(mm2, mm5); paddw_r2r(mm5, mm4); punpckhbw_r2r(mm2, mm7); paddw_r2r(mm7, mm6); src += lx; movq_m2r(*(src+8), mm5); /* first 8 bytes 1st row: avg src in x */ movq_r2r(mm5, mm7); punpcklbw_r2r(mm2, mm5); paddw_r2r(mm5, mm4); punpckhbw_r2r(mm2, mm7); paddw_r2r(mm7, mm6); movq_m2r(*(src+9), mm5); movq_r2r(mm5, mm7); punpcklbw_r2r(mm2, mm5); paddw_r2r(mm5, mm4); punpckhbw_r2r(mm2, mm7); paddw_r2r(mm7, mm6); /* Now round and repack... */ paddw_r2r(mm3, mm4); paddw_r2r(mm3, mm6); psrlw_i2r(2, mm4); psrlw_i2r(2, mm6); packuswb_r2r(mm6, mm4); movq_m2r(*(dst+8), mm7); pand_r2r(mm0, mm7); movq_r2r(mm4, mm6); pand_r2r(mm1, mm6); por_r2r(mm6, mm7); pavgb_r2r(mm7, mm4); movq_r2m(mm4, *(dst+8)); } dst += lx; h--; } while (h); emms(); } /* The y-axis interpolation case... */ void predcomp_01_mmxe(char *src,char *dst,int lx, int w, int h, int mask) { movd_g2r(mask, mm0); pxor_r2r(mm2, mm2); punpckldq_r2r(mm0, mm0); pcmpeqd_r2r(mm2, mm0); movq_r2r(mm0, mm1); pcmpeqd_r2r(mm2, mm0); do { movq_m2r(*src, mm4); /* first 8 bytes row */ src+=lx; /* update pointer to next row */ pavgb_m2r(*src, mm4); /* Average in y */ movq_m2r(*dst, mm2); pand_r2r(mm0, mm2); movq_r2r(mm4, mm3); pand_r2r(mm1, mm3); por_r2r(mm3, mm2); pavgb_r2r(mm2, mm4); movq_r2m(mm4, *dst); if (w != 8) { src-=lx; /* Back to prev row */ movq_m2r(*(src+8), mm4); /* first 8 bytes row */ src+=lx; /* update pointer to next row */ pavgb_m2r(*(src+8), mm4); /* Average in y */ movq_m2r(*(dst+8), mm2); pand_r2r(mm0, mm2); movq_r2r(mm4, mm3); pand_r2r(mm1, mm3); por_r2r(mm3, mm2); pavgb_r2r(mm2, mm4); movq_r2m(mm4, *(dst+8)); } dst+=lx; /* update pointer to next row */ h--; } while (h); emms(); } mjpegtools-2.1.0/mpeg2enc/transfrm_x86.c0000644000175000017500000001671511445477341020442 0ustar glowwormglowworm/* transfrm.c, forward / inverse transformation In compiler (gcc) embdeed assembly language... */ /* Modifications and enhancements (C) 2000-2003 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include #include #include "mjpeg_types.h" #include "mjpeg_logging.h" #include "mmx.h" #include "simd.h" /* Routines written in assembler */ extern void fdct_mmx( int16_t * blk ); extern void init_fdct_sse(void); extern void fdct_sse( int16_t * blk ); extern void fdct_test( int16_t * blk ); extern void idct_mmx( int16_t * blk ); extern void idct_sse( int16_t * blk ); extern void idct_test( int16_t * blk ); extern void add_pred_mmx (uint8_t *pred, uint8_t *cur, int lx, int16_t *blk); extern void sub_pred_mmx (uint8_t *pred, uint8_t *cur, int lx, int16_t *blk); static inline void mmx_sum_4_word_accs( mmx_t *accs, int32_t *res ) { movq_m2r( *accs, mm1 ); movq_r2r( mm1, mm3 ); movq_r2r( mm1, mm2 ); /* Generate sign extensions for mm1 words! */ psraw_i2r( 15, mm3 ); punpcklwd_r2r( mm3, mm1 ); punpckhwd_r2r( mm3, mm2 ); paddd_r2r( mm1, mm2 ); movq_r2r( mm2, mm3); psrlq_i2r( 32, mm2); paddd_r2r( mm2, mm3); movd_r2m( mm3, *res ); } static inline void sum_sumsq_8bytes( uint8_t *cur_lum_mb, uint8_t *pred_lum_mb, mmx_t *sumtop_accs, mmx_t *sumbot_accs, mmx_t *sumsqtop_accs, mmx_t *sumsqbot_accs, mmx_t *sumxprod_accs, int stride ) { pxor_r2r(mm0,mm0); /* Load pixels from top field into mm1.w,mm2.w */ movq_m2r( *((mmx_t*)cur_lum_mb), mm1 ); movq_m2r( *((mmx_t*)pred_lum_mb), mm2 ); /* mm3 := mm1 mm4 := mm2 mm1.w[0..3] := mm1.b[0..3]-mm2.b[0..3] */ movq_r2r( mm1, mm3 ); punpcklbw_r2r( mm0, mm1 ); movq_r2r( mm2, mm4 ); punpcklbw_r2r( mm0, mm2 ); psubw_r2r( mm2, mm1 ); /* mm3.w[0..3] := mm3.b[4..7]-mm4.b[4..7] */ punpckhbw_r2r( mm0, mm3 ); punpckhbw_r2r( mm0, mm4 ); psubw_r2r( mm4, mm3 ); /* sumtop_accs->w[0..3] += mm1.w[0..3]; sumtop_accs->w[0..3] += mm3.w[0..3]; mm6 = mm1; mm7 = mm3; */ movq_m2r( *sumtop_accs, mm5 ); paddw_r2r( mm1, mm5 ); paddw_r2r( mm3, mm5 ); movq_r2r( mm1, mm6 ); movq_r2r( mm3, mm7 ); movq_r2m( mm5, *sumtop_accs ); /* *sumsq_top_acc += mm1.w[0..3] * mm1.w[0..3]; *sumsq_top_acc += mm3.w[0..3] * mm3.w[0..3]; */ pmaddwd_r2r( mm1, mm1 ); movq_m2r( *sumsqtop_accs, mm5 ); pmaddwd_r2r( mm3, mm3 ); paddd_r2r( mm1, mm5 ); paddd_r2r( mm3, mm5 ); movq_r2m( mm5, *sumsqtop_accs ); /* Load pixels from bot field into mm1.w,mm2.w */ movq_m2r( *((mmx_t*)(cur_lum_mb+stride)), mm1 ); movq_m2r( *((mmx_t*)(pred_lum_mb+stride)), mm2 ); /* mm2 := mm1 mm4 := mm2 mm1.w[0..3] := mm1.b[0..3]-mm2.b[0..3] */ movq_r2r( mm1, mm3 ); punpcklbw_r2r( mm0, mm1 ); movq_r2r( mm2, mm4 ); punpcklbw_r2r( mm0, mm2 ); psubw_r2r( mm2, mm1 ); /* mm3.w[0..3] := mm3.b[4..7]-mm4.b[4..7] */ punpckhbw_r2r( mm0, mm3 ); punpckhbw_r2r( mm0, mm4 ); psubw_r2r( mm4, mm3 ); /* sumbot_accs->w[0..3] += mm1.w[0..3]; sumbot_accs->w[0..3] += mm3.w[0..3]; mm2 := mm1; mm4 := mm3; */ movq_m2r( *sumbot_accs, mm5 ); paddw_r2r( mm1, mm5 ); movq_r2r( mm1, mm2 ); paddw_r2r( mm3, mm5 ); movq_r2r( mm3, mm4 ); movq_r2m( mm5, *sumbot_accs ); /* *sumsqbot_acc += mm1.w[0..3] * mm1.w[0..3]; *sumsqbot_acc += mm3.w[0..3] * mm3.w[0..3]; */ pmaddwd_r2r( mm1, mm1 ); movq_m2r( *sumsqbot_accs, mm5 ); pmaddwd_r2r( mm3, mm3 ); paddd_r2r( mm1, mm5 ); paddd_r2r( mm3, mm5 ); movq_r2m( mm5, *sumsqbot_accs ); /* Accumulate cross-product *sum_xprod_acc += mm1.w[0..3] * mm6[0..3]; *sum_xprod_acc += mm3.w[0..3] * mm7[0..3]; */ movq_m2r( *sumxprod_accs, mm5 ); pmaddwd_r2r( mm6, mm2); pmaddwd_r2r( mm7, mm4); paddd_r2r( mm2, mm5 ); paddd_r2r( mm4, mm5 ); movq_r2m( mm5, *sumxprod_accs ); emms(); } int field_dct_best_mmx( uint8_t *cur_lum_mb, uint8_t *pred_lum_mb, int stride) { /* * calculate prediction error (cur-pred) for top (blk0) * and bottom field (blk1) */ double r,d; int rowoffs = 0; int sumtop, sumbot, sumsqtop, sumsqbot, sumbottop; int j; int dct_type; int topvar, botvar; mmx_t sumtop_accs, sumbot_accs; mmx_t sumsqtop_accs, sumsqbot_accs, sumxprod_accs; int32_t sumtop_acc, sumbot_acc; int32_t sumsqtop_acc, sumsqbot_acc, sumxprod_acc; pxor_r2r(mm0,mm0); movq_r2m( mm0, *(&sumtop_accs) ); movq_r2m( mm0, *(&sumbot_accs) ); movq_r2m( mm0, *(&sumsqtop_accs) ); movq_r2m( mm0, *(&sumsqbot_accs) ); movq_r2m( mm0, *(&sumxprod_accs) ); sumtop = sumsqtop = sumbot = sumsqbot = sumbottop = 0; sumtop_acc = sumbot_acc = sumsqtop_acc = sumsqbot_acc = sumxprod_acc = 0; for (j=0; j<8; j++) { #ifdef ORIGINAL_CODE for (i=0; i<16; i++) { register int toppix = cur_lum_mb[rowoffs+i] - pred_lum_mb[rowoffs+i]; register int botpix = cur_lum_mb[rowoffs+width+i] - pred_lum_mb[rowoffs+width+i]; sumtop += toppix; sumsqtop += toppix*toppix; sumbot += botpix; sumsqbot += botpix*botpix; sumbottop += toppix*botpix; } #endif sum_sumsq_8bytes( &cur_lum_mb[rowoffs], &pred_lum_mb[rowoffs], &sumtop_accs, &sumbot_accs, &sumsqtop_accs, &sumsqbot_accs, &sumxprod_accs, stride); sum_sumsq_8bytes( &cur_lum_mb[rowoffs+8], &pred_lum_mb[rowoffs+8], &sumtop_accs, &sumbot_accs, &sumsqtop_accs, &sumsqbot_accs, &sumxprod_accs, stride); rowoffs += (stride<<1); } mmx_sum_4_word_accs( &sumtop_accs, &sumtop ); mmx_sum_4_word_accs( &sumbot_accs, &sumbot ); emms(); sumsqtop = sumsqtop_accs.d[0] + sumsqtop_accs.d[1]; sumsqbot = sumsqbot_accs.d[0] + sumsqbot_accs.d[1]; sumbottop = sumxprod_accs.d[0] + sumxprod_accs.d[1]; /* Calculate Variances top and bottom. If they're of similar sign estimate correlation if its good use frame DCT otherwise use field. */ r = 0.0; topvar = sumsqtop-sumtop*sumtop/128; botvar = sumsqbot-sumbot*sumbot/128; if ( !((topvar <= 0) ^ (botvar <= 0)) ) { d = ((double) topvar) * ((double)botvar); r = (sumbottop-(sumtop*sumbot)/128); if (r>0.5*sqrt(d)) return 0; /* frame DCT */ else return 1; /* field DCT */ } else return 1; /* field DCT */ return dct_type; } void init_x86_transform() { char *opt_type1=""; int flags = cpu_accel(); int d_quant_fdct = disable_simd("fdct"); int d_quant_idct = disable_simd("idct"); if( !d_quant_fdct ) pfdct = fdct_mmx; else mjpeg_info(" Disabling fdct"); if( !d_quant_idct ) pidct = idct_mmx; else mjpeg_info(" Disabling idct"); padd_pred = add_pred_mmx; psub_pred = sub_pred_mmx; pfield_dct_best = field_dct_best_mmx; if( flags & ACCEL_X86_SSE ) { init_fdct_sse(); if( !d_quant_fdct ) pfdct = fdct_sse; if( !d_quant_idct ) pidct = idct_sse; opt_type1 = "SSE and "; } mjpeg_info( "SETTING %sMMX for TRANSFORM!",opt_type1); } mjpegtools-2.1.0/mpeg2enc/idct_mmx.c0000644000175000017500000004333410450314721017665 0ustar glowwormglowworm#include #include "cpu_accel.h" #include "mjpeg_types.h" #include "mmx.h" #define ROOT2OVER2 0.70710678118654757 #define W0 1 #define W1 1.3870398453221475 /* sqrt(2)*cos(1*pi/16) */ #define W2 1.3065629648763766 /* sqrt(2)*cos(2*pi/16) */ #define W3 1.1758756024193588 /* sqrt(2)*cos(3*pi/16) */ #define W4 1 #define W5 0.78569495838710235 /* sqrt(2)*cos(5*pi/16) */ #define W6 0.54119610014619712 /* sqrt(2)*cos(6*pi/16) */ #define W7 0.27589937928294311 /* sqrt(2)*cos(7*pi/16) */ #define WIFY(b,v) ((int)((b)*(v)+.5)) #define Wr 16384 #define Wr0 WIFY(Wr,W0) #define Wr1 WIFY(Wr,W1) #define Wr2 WIFY(Wr,W2) #define Wr3 WIFY(Wr,W3) #define Wr4 WIFY(Wr,W4) #define Wr5 WIFY(Wr,W5) #define Wr6 WIFY(Wr,W6) #define Wr7 WIFY(Wr,W7) #define Wrshift 11 #define Wrround (1<<((Wrshift)-1)) #define Wc 16384 #define Wc0 WIFY(Wc,W0) #define Wc1 WIFY(Wc,W1) #define Wc2 WIFY(Wc,W2) #define Wc3 WIFY(Wc,W3) #define Wc4 WIFY(Wc,W4) #define Wc5 WIFY(Wc,W5) #define Wc6 WIFY(Wc,W6) #define Wc7 WIFY(Wc,W7) #define Wcshift 20 #define Wcround (1<<((Wcshift)-1)) // NOTE: Wr*Wc == (1<<(Wrshift+Wcshift)) // also, Wr <= 8<>Wrshift; dst[3] = (x5)>>Wrshift; dst[4] = (x1)>>Wrshift; dst[7] = (x3)>>Wrshift; x7 = MUL_BY_ROOT_2_OVER_2(x7); x6 = MUL_BY_ROOT_2_OVER_2(x6); ADDDIFF(x2, x7); ADDDIFF(x0, x6); dst[1] = (x7)>>Wrshift; dst[2] = (x6)>>Wrshift; dst[5] = (x0)>>Wrshift; dst[6] = (x2)>>Wrshift; */ void idct_mmx(int16_t *block) { int16_t temp[64], *src, *dst; int i; src=block; dst=temp; for( i=0; i<4; src+=16, dst+=2, i++ ) { #define STOREMM(r, d, s) \ psrad_i2r(s, r); \ packssdw_r2r(r, r); \ movd_r2m(r, d); /* first stage */ // x0, x1 = W0*x0 + W1*x1 + 128, W1*x0 - W0*x1 + 128; // x2, x3 = -W2*x2 + W6*x3, W6*x2 + W2*x3; // x4, x5 = W1*x4 + W7*x5, W7*x4 - W1*x5; // x6, x7 = W5*x6 + W3*x7, W3*x6 - W5*x7; movq_m2r(src[0], mm0); movq_m2r(src[8], mm1); movq_r2r(mm0, mm2); punpckldq_r2r(mm1, mm0); punpckhdq_r2r(mm1, mm2); movq_m2r(src[4], mm4); movq_m2r(src[12], mm5); movq_r2r(mm4, mm6); punpckldq_r2r(mm5, mm4); punpckhdq_r2r(mm5, mm6); // mm5 = low word set // mm7 = high word set pxor_r2r(mm5, mm5); pcmpeqw_r2r(mm5, mm5); movq_r2r(mm5, mm7); psrld_i2r(16, mm5); pxor_r2r(mm5, mm7); movq_r2r(mm4, mm1); // 0,1 / 2,3 / 4,5 / 6,7 / 1=4,5 movq_r2r(mm0, mm3); pand_r2r(mm5, mm0); pslld_i2r(16, mm1); por_r2r(mm1, mm0); // 0,4 / 2,3 / 4,5 / 6,7 / 3=0,1 movq_r2r(mm6, mm1); pand_r2r(mm7, mm6); psrld_i2r(16, mm3); por_r2r(mm3, mm6); // 0,4 / 2,3 / 4,5 / 1,7 / 1=6,7 movq_r2r(mm2, mm3); pslld_i2r(16, mm2); pand_r2r(mm5, mm1); por_r2r(mm1, mm2); // 0,4 / 6,2 / 4,5 / 1,7 / 3=2,3 psrld_i2r(16, mm4); pand_r2r(mm7, mm3); por_r2r(mm3, mm4); // 0,4 / 6,2 / 5,3 / 1,7 MMXMULTADD(mm0, mm1, idct_mmx_row_table); MMXMULTADD(mm2, mm3, idct_mmx_row_table+8); MMXMULTADD(mm4, mm5, idct_mmx_row_table+16); MMXMULTADD(mm6, mm7, idct_mmx_row_table+24); paddd_m2r(idct_mmx_row_round[0], mm0); paddd_m2r(idct_mmx_row_round[0], mm1); /* second stage */ MMXADDDIFF(mm6, mm4); MMXADDDIFF(mm7, mm5); /* third stage */ MMXADDDIFF( mm1, mm3 ); MMXADDDIFF( mm0, mm2 ); MMXADDDIFF( mm6, mm7 ); /* fourth stage */ MMXADDDIFF( mm3, mm4 ); MMXADDDIFF( mm1, mm5 ); /* fifth stage */ STOREMM(mm4, dst[0*8], Wrshift); STOREMM(mm5, dst[3*8], Wrshift); STOREMM(mm1, dst[4*8], Wrshift); STOREMM(mm3, dst[7*8], Wrshift); /* sixth stage */ // x6 = (181*x6+128)>>8; // x7 = (181*x7+128)>>8; // actually, this computes, roughly: x6 -= (x6>>8)*75 movq_r2r(mm6, mm4); movq_r2r(mm7, mm5); psrad_i2r(2, mm6); psrad_i2r(2, mm7); psubd_r2r(mm6, mm4); psubd_r2r(mm7, mm5); psrad_i2r(3, mm6); psrad_i2r(3, mm7); psubd_r2r(mm6, mm4); psubd_r2r(mm7, mm5); psrad_i2r(2, mm6); psrad_i2r(2, mm7); psubd_r2r(mm6, mm4); psubd_r2r(mm7, mm5); psrad_i2r(1, mm6); psrad_i2r(1, mm7); psubd_r2r(mm6, mm4); psubd_r2r(mm7, mm5); /* seventh stage */ MMXADDDIFF( mm2, mm5 ); MMXADDDIFF( mm0, mm4 ); /* eighth stage */ STOREMM(mm5, dst[1*8], Wrshift); STOREMM(mm4, dst[2*8], Wrshift); STOREMM(mm0, dst[5*8], Wrshift); STOREMM(mm2, dst[6*8], Wrshift); } src=temp; dst=block; for( i=0; i<4; src+=16, dst+=2, i++ ) { /* first stage */ // x0, x1 = W0*x0 + W1*x1 + 128, W1*x0 - W0*x1 + 128; // x2, x3 = -W2*x2 + W6*x3, W6*x2 + W2*x3; // x4, x5 = W1*x4 + W7*x5, W7*x4 - W1*x5; // x6, x7 = W5*x6 + W3*x7, W3*x6 - W5*x7; movq_m2r(src[0], mm0); movq_m2r(src[8], mm1); movq_r2r(mm0, mm2); punpckldq_r2r(mm1, mm0); punpckhdq_r2r(mm1, mm2); movq_m2r(src[4], mm4); movq_m2r(src[12], mm5); movq_r2r(mm4, mm6); punpckldq_r2r(mm5, mm4); punpckhdq_r2r(mm5, mm6); // mm5 = low word set // mm7 = high word set pxor_r2r(mm5, mm5); pcmpeqw_r2r(mm5, mm5); movq_r2r(mm5, mm7); psrld_i2r(16, mm5); pxor_r2r(mm5, mm7); movq_r2r(mm4, mm1); // 0,1 / 2,3 / 4,5 / 6,7 / 1=4,5 movq_r2r(mm0, mm3); pand_r2r(mm5, mm0); pslld_i2r(16, mm1); por_r2r(mm1, mm0); // 0,4 / 2,3 / 4,5 / 6,7 / 3=0,1 movq_r2r(mm6, mm1); pand_r2r(mm7, mm6); psrld_i2r(16, mm3); por_r2r(mm3, mm6); // 0,4 / 2,3 / 4,5 / 1,7 / 1=6,7 movq_r2r(mm2, mm3); pslld_i2r(16, mm2); pand_r2r(mm5, mm1); por_r2r(mm1, mm2); // 0,4 / 6,2 / 4,5 / 1,7 / 3=2,3 psrld_i2r(16, mm4); pand_r2r(mm7, mm3); por_r2r(mm3, mm4); // 0,4 / 6,2 / 5,3 / 1,7 MMXMULTADD(mm0, mm1, idct_mmx_col_table); MMXMULTADD(mm2, mm3, idct_mmx_col_table+8); MMXMULTADD(mm4, mm5, idct_mmx_col_table+16); MMXMULTADD(mm6, mm7, idct_mmx_col_table+24); paddd_m2r(idct_mmx_col_round[0], mm0); paddd_m2r(idct_mmx_col_round[0], mm1); /* second stage */ MMXADDDIFF(mm6, mm4); MMXADDDIFF(mm7, mm5); /* third stage */ MMXADDDIFF( mm1, mm3 ); MMXADDDIFF( mm0, mm2 ); MMXADDDIFF( mm6, mm7 ); /* fourth stage */ MMXADDDIFF( mm3, mm4 ); MMXADDDIFF( mm1, mm5 ); /* fifth stage */ STOREMM(mm4, dst[0*8], Wcshift); STOREMM(mm5, dst[3*8], Wcshift); STOREMM(mm1, dst[4*8], Wcshift); STOREMM(mm3, dst[7*8], Wcshift); /* sixth stage */ // x6 = (181*x6+128)>>8; // x7 = (181*x7+128)>>8; // actually, this computes, roughly: x6 -= (x6>>8)*75 movq_r2r(mm6, mm4); movq_r2r(mm7, mm5); psrad_i2r(2, mm6); psrad_i2r(2, mm7); psubd_r2r(mm6, mm4); psubd_r2r(mm7, mm5); psrad_i2r(3, mm6); psrad_i2r(3, mm7); psubd_r2r(mm6, mm4); psubd_r2r(mm7, mm5); psrad_i2r(2, mm6); psrad_i2r(2, mm7); psubd_r2r(mm6, mm4); psubd_r2r(mm7, mm5); psrad_i2r(1, mm6); psrad_i2r(1, mm7); psubd_r2r(mm6, mm4); psubd_r2r(mm7, mm5); /* seventh stage */ MMXADDDIFF( mm2, mm5 ); MMXADDDIFF( mm0, mm4 ); /* eighth stage */ STOREMM(mm5, dst[1*8], Wcshift); STOREMM(mm4, dst[2*8], Wcshift); STOREMM(mm0, dst[5*8], Wcshift); STOREMM(mm2, dst[6*8], Wcshift); } emms(); } void idct_sse(int16_t *block) { float temp[64] __attribute__((aligned(16))); float *dst; int i; int16_t *src; src=block; dst=temp; for( i=0; i<2; src+=32, dst+=4, i++) { #define MM2XMMl(mm,x0,x1) \ movq_r2r ( mm, mm6); \ movq_r2r ( mm, mm7); \ psraw_i2r ( 16, mm); \ punpcklwd_r2r( mm, mm6); \ punpckhwd_r2r( mm, mm7); \ cvtpi2ps_r2r ( mm6, x0); \ cvtpi2ps_r2r ( mm7, x1); #define MM2XMM(ml,mh,x0,x1) \ MM2XMMl(mh,x0,x1); \ movlhps_r2r(x0, x0); \ movlhps_r2r(x1, x1); \ MM2XMMl(ml,x0,x1); #define LOADROTATEif(src, x0, x1, x2, x3) \ \ movq_m2r((src)[16], mm2); /* 0c 1c 2c 3c */ \ movq_m2r((src)[24], mm3); /* 0d 1d 2d 3d */ \ movq_m2r((src)[ 0], mm0); /* 0a 1a 2a 3a */ \ movq_m2r((src)[ 8], mm1); /* 0b 1b 2b 3b */ \ \ /* mm5 = 0c 0d 1c 1d */ \ /* mm2 = 2c 2d 3c 3d */ \ movq_r2r(mm2, mm5); \ punpcklwd_r2r(mm3, mm5); \ punpckhwd_r2r(mm3, mm2); \ \ /* mm4 = 0a 0b 1a 1b */ \ /* mm0 = 2a 2b 3a 3b */ \ movq_r2r(mm0, mm4); \ punpcklwd_r2r(mm1, mm4); \ punpckhwd_r2r(mm1, mm0); \ \ MM2XMM(mm4, mm5, x0, x1); \ MM2XMM(mm0, mm2, x2, x3); LOADROTATEif(src, xmm0, xmm6, xmm3, xmm5); LOADROTATEif(src+4, xmm1, xmm4, xmm2, xmm7); // first stage SSEADDDIFF( xmm0, xmm1 ); SSEMULTADD( xmm2, xmm3, idct_sse_table+16 ); SSEMULTADD( xmm4, xmm5, idct_sse_table+32 ); SSEMULTADD( xmm6, xmm7, idct_sse_table+48 ); // third stage SSEADDDIFF( xmm1, xmm3 ); // second stage SSEADDDIFF( xmm6, xmm4 ); SSEADDDIFF( xmm7, xmm5 ); // fourth stage SSEADDDIFF( xmm3, xmm4 ); SSEADDDIFF( xmm1, xmm5 ); movaps_r2m( xmm3, dst[7*8]); movaps_r2m( xmm4, dst[0*8]); movaps_r2m( xmm1, dst[4*8]); movaps_r2m( xmm5, dst[3*8]); SSEADDDIFF_t( xmm6, xmm7, xmm1 ); SSEADDDIFF_t( xmm0, xmm2, xmm1 ); // x7 = MUL_BY_ROOT_2_OVER_2(x7); // x6 = MUL_BY_ROOT_2_OVER_2(x6); movaps_m2r( idct_sse_root2_over2[0], xmm1 ); mulps_r2r( xmm1, xmm7 ); mulps_r2r( xmm1, xmm6 ); SSEADDDIFF_t(xmm2, xmm7, xmm1); SSEADDDIFF_t(xmm0, xmm6, xmm1); movaps_r2m( xmm2, dst[6*8] ); movaps_r2m( xmm7, dst[1*8] ); movaps_r2m( xmm0, dst[5*8] ); movaps_r2m( xmm6, dst[2*8] ); } src=block; dst=temp; for( i=0; i<2; src+=4, dst+=32, i++) { #define LOADROTATEff(src, t, x0, x1, x2, x3) \ movaps_m2r((src)[ 0], x0); /* 0a 1a 2a 3a */ \ movaps_m2r((src)[ 8], t); /* 0b 1b 2b 3b */ \ movaps_m2r((src)[16], x3); /* 0c 1c 2c 3c */ \ movaps_m2r((src)[24], x1); /* 0d 1d 2d 3d */ \ \ /* mm0 = 0a 0b 1a 1b */ \ /* mm2 = 2a 2b 3a 3b */ \ movaps_r2r (x0, x2); \ unpcklps_r2r(t, x0); \ unpckhps_r2r(t, x2); \ \ /* mm3 = 0c 0d 1c 1d */ \ /* mmt = 2c 2d 3c 3d */ \ movaps_r2r (x3, t); \ unpcklps_r2r(x1, x3); \ unpckhps_r2r(x1, t); \ \ /* mm0 = 0a 0b 0c 0d */ \ /* mm1 = 1a 1b 1c 1d */ \ movaps_r2r (x3, x1); \ movhlps_r2r(x0, x1); \ movlhps_r2r(x3, x0); \ \ /* mm2 = 2a 2b 2c 2d */ \ /* mm3 = 3a 3b 3c 3d */ \ movaps_r2r ( t, x3); \ movhlps_r2r(x2, x3); \ movlhps_r2r( t, x2); #define STOREXMM(x0, dst) \ mulps_m2r(*idct_sse_eighth, x0); \ cvtps2pi_r2r(x0, mm0); \ movhlps_r2r (x0, x0); \ cvtps2pi_r2r(x0, mm1); \ packssdw_r2r(mm1, mm0); \ movq_r2m (mm0, dst); LOADROTATEff(dst, xmm1, xmm0, xmm6, xmm3, xmm5); movaps_r2m(xmm0, dst[0]); LOADROTATEff(dst+4, xmm0, xmm1, xmm4, xmm2, xmm7); movaps_m2r(dst[0], xmm0); // first stage SSEADDDIFF( xmm0, xmm1 ); SSEMULTADD( xmm2, xmm3, idct_sse_table+16 ); SSEMULTADD( xmm4, xmm5, idct_sse_table+32 ); SSEMULTADD( xmm6, xmm7, idct_sse_table+48 ); // third stage SSEADDDIFF( xmm1, xmm3 ); // second stage SSEADDDIFF( xmm6, xmm4 ); SSEADDDIFF( xmm7, xmm5 ); // fourth stage SSEADDDIFF( xmm3, xmm4 ); SSEADDDIFF( xmm1, xmm5 ); STOREXMM( xmm3, src[7*8]); STOREXMM( xmm4, src[0*8] ); STOREXMM( xmm1, src[4*8]); STOREXMM( xmm5, src[3*8]); SSEADDDIFF_t( xmm6, xmm7, xmm1 ); SSEADDDIFF_t( xmm0, xmm2, xmm1 ); // x7 = MUL_BY_ROOT_2_OVER_2(x7); // x6 = MUL_BY_ROOT_2_OVER_2(x6); movaps_m2r( idct_sse_root2_over2[0], xmm1 ); mulps_r2r( xmm1, xmm7 ); mulps_r2r( xmm1, xmm6 ); SSEADDDIFF_t(xmm2, xmm7, xmm1); SSEADDDIFF_t(xmm0, xmm6, xmm1); STOREXMM( xmm2, src[6*8] ); STOREXMM( xmm7, src[1*8] ); STOREXMM( xmm0, src[5*8] ); STOREXMM( xmm6, src[2*8] ); } emms(); } mjpegtools-2.1.0/mpeg2enc/streamstate.h0000644000175000017500000000765310566454254020444 0ustar glowwormglowworm#ifndef _STREAMSTATE_H #define _STREAMSTATE_H /* (C) 2005Andrew Stevens */ /* This Software is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "mjpeg_types.h" /************************************************ * * StreamState - MPEG-1/2 streams have a fairly complex structure. The context of each picture * in this structure determines how it is encoded. This is the class for maintaining * iterating through such stream encoding contexts. * **********************************************/ class EncoderParams; class PictureReader; class StreamState { public: StreamState( EncoderParams &encparams, PictureReader &reader ); void Init( ); void Next( uint64_t bits_after_mux ); void ForceIFrame(); void SuppressBFrames(); // Handle seperately - need to know input frame number (set by Next) inline bool EndOfStream() const { return end_stream; } inline int BGroupLength() const { return bigrp_length; } inline int TemporalReference() const { return temp_ref; } inline int PresentationNum() const { return frame_num+temp_ref-g_idx; } inline int DecodeNum() const { return frame_num; } bool NextGopClosed() const; bool CanSplitHere(int offset=0) const; protected: void GopStart(); void SetTempRef(); int GetNextChapter() const; public: // Conext of current frame in hierarchy of structures: sequence, GOP, B-group */ int frame_num; /* Index in total video stream */ int s_idx; /* Index in current sequence */ int g_idx; /* Index in current GOP */ int b_idx; /* Index in current B frame group */ int frame_type; /* Type of indexed frame */ int temp_ref; /* Temporal reference in GOP == presentation order in GOP */ // Context of current sequence and GOP in the input image stream int seq_start_frame; /* Index start current sequence in input stream */ int gop_start_frame; /* Index start current gop in input stream */ // GOP state int gop_length; /* Length of current gop */ int bigrp_length; /* Length of current B-frame group */ int bs_short; /* Number of B frame GOP is short of having M-1 B's for each I/P frame */ bool suppress_b_frames; /* Disable B frames for rest of current GOP */ int np; /* P frames in current GOP */ int nb; /* B frames in current GOP */ double next_b_drop; /* When next B frame drop is due in GOP */ bool closed_gop; /* Current GOP is closed */ // Sequence splitting state bool gop_end_seq; /* Current GOP is last in sequence */ bool end_seq; /* Current frame is last in sequence */ bool new_seq; /* Current GOP/frame starts new sequence */ bool end_stream; /* End of video stream reached - no further coding possible */ private: uint64_t next_split_point; // Keep track of size-based points to split individual sequences uint64_t seq_split_length; EncoderParams &encparams; PictureReader &reader; }; #endif mjpegtools-2.1.0/mpeg2enc/channel.hh0000644000175000017500000001257610566454253017667 0ustar glowwormglowworm/* channel.hh - A class of synchonising FIFO's. Using the default size of 1 gives nice CSP / Occam style channels (C) 2003 Andrew Stevens This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef CHANNEL_HH #define CHANNEL_HH #include template class Channel { public: Channel() : fullness(0), read(0), write(0), consumers_waiting(0), producers_waiting(0) { #ifdef PTHREAD_MUTEX_ERRORCHECK pthread_mutexattr_t mu_attr; pthread_mutexattr_t *p_attr = &mu_attr; pthread_mutexattr_init(&mu_attr); pthread_mutexattr_settype( &mu_attr, PTHREAD_MUTEX_ERRORCHECK ); #else pthread_mutexattr_t *p_attr = NULL; #endif pthread_mutex_init( &atomic, p_attr ); pthread_cond_init( &addition, NULL ); pthread_cond_init( &removal, NULL ); pthread_cond_init( &waiting, NULL ); } void Put( const T &in ) { int e; e = pthread_mutex_lock( &atomic); #ifndef NDEBUG if ( e != 0) { fprintf(stderr, "1 pthread_mutex_lock=%d\n", e); abort(); } #endif if( fullness == size ) { ++producers_waiting; pthread_cond_signal( &waiting ); while( fullness == size ) { pthread_cond_wait( &removal, &atomic); } --producers_waiting; } ++fullness; buffer[write] = in; write = (write + 1) % size; pthread_cond_signal( &addition ); e = pthread_mutex_unlock( &atomic ); #ifndef NDEBUG if (e != 0) { fprintf(stderr, "1 pthread_mutex_unlock=%d\n", e); abort(); } #endif } void Get( T &out ) { int e; e = pthread_mutex_lock( &atomic); #ifndef NDEBUG if ( e != 0) { fprintf(stderr, "2 pthread_mutex_lock=%d\n", e); abort(); } #endif if( fullness == 0 ) { ++consumers_waiting; pthread_cond_signal( &waiting ); while( fullness == 0 ) { pthread_cond_wait( &addition, &atomic ); } --consumers_waiting; } --fullness; out = buffer[read]; read = (read + 1) % size; pthread_cond_signal( &removal ); e = pthread_mutex_unlock( &atomic ); #ifndef NDEBUG if (e != 0) { fprintf(stderr, "2 pthread_mutex_unlock=%d\n", e); abort(); } #endif } void WaitForNewConsumers() { int e; e = pthread_mutex_lock( &atomic); #ifndef NDEBUG if ( e != 0) { fprintf(stderr, "5 pthread_mutex_lock=%d\n", e); abort(); } #endif unsigned int wait_for = consumers_waiting+1; while( fullness > 0 || consumers_waiting < wait_for ) { pthread_cond_wait( &waiting, &atomic); } e = pthread_mutex_unlock( &atomic ); #ifndef NDEBUG if ( e != 0) { fprintf(stderr, "5 pthread_mutex_unlock=%d\n", e); abort(); } #endif } void WaitUntilConsumersWaitingAtLeast( unsigned int wait_for ) { int e; e = pthread_mutex_lock( &atomic); #ifndef NDEBUG if ( e != 0) { fprintf(stderr, "3 pthread_mutex_lock=%d\n", e); abort(); } #endif while( fullness > 0 || consumers_waiting < wait_for ) { pthread_cond_wait( &waiting, &atomic); } e = pthread_mutex_unlock( &atomic ); #ifndef NDEBUG if (e != 0) { fprintf(stderr, "3 pthread_mutex_unlock=%d\n", e); abort(); } #endif } void WaitUntilProducersWaitingAtLeast( unsigned int wait_for ) { int e; e = pthread_mutex_lock( &atomic); #ifndef NDEBUG if ( e != 0) { fprintf(stderr, "4 pthread_mutex_lock=%d\n", e); abort(); } #endif while( fullness < size || producers_waiting < wait_for ) { pthread_cond_wait( &waiting, &atomic); } e = pthread_mutex_unlock( &atomic ); #ifndef NDEBUG if (e != 0) { fprintf(stderr, "4 pthread_mutex_unlock=%d\n", e); abort(); } #endif } private: pthread_cond_t addition; pthread_cond_t removal; pthread_cond_t waiting; pthread_mutex_t atomic; volatile unsigned int fullness; volatile unsigned int read; volatile unsigned int write; volatile unsigned int consumers_waiting; volatile unsigned int producers_waiting; T buffer[size]; }; #endif // CHANNEL_HH mjpegtools-2.1.0/mpeg2enc/ontheflyratectlpass1.cc0000644000175000017500000005635311452124503022410 0ustar glowwormglowworm/* ratectl.c, bitrate control routines (linear quantization only currently) */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ /* Modifications and enhancements (C) 2000,2001,2002,2003 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "config.h" #include #include #include "mjpeg_types.h" #include "mjpeg_logging.h" #include "mpeg2syntaxcodes.h" #include "tables.h" #include "mpeg2encoder.hh" #include "picture.hh" #include "ontheflyratectlpass1.hh" #include "cpu_accel.h" /***************************** * * On-the-fly rate controller for coding pass1. The constructor sets up the initial * control and estimator parameter values to values that experience * suggest make sense. All the important ones are dynamically * tuned anyway so these values are not too critical. * ****************************/ OnTheFlyPass1::OnTheFlyPass1(EncoderParams &encparams ) : Pass1RateCtl(encparams, *this) { buffer_variation = 0; bits_transported = 0; bits_used = 0; frame_overshoot_margin = 0; sum_avg_act = 0.0; sum_avg_quant = 0.0; } /********************* * * Initialise rate control parameters for start of encoding * based on encoding parameters * ********************/ void OnTheFlyPass1::Init() { /* Reaction paramer - i.e. quantisation feedback gain relative to bit over/undershoot. For normal frames it is fairly modest as we can compensate over multiple frames and can average out variations in image complexity. For stills we set it a higher so corrections take place more rapidly *within* a single frame. */ if( encparams.target_bitrate > 0 ) ctrl_bitrate = encparams.target_bitrate; else ctrl_bitrate = encparams.bit_rate; if( encparams.still_size > 0 ) fb_gain = (int)floor(2.0*ctrl_bitrate/encparams.decode_frame_rate); else fb_gain = (int)floor(4.0*ctrl_bitrate/encparams.decode_frame_rate); /* Set the virtual buffers for per-frame rate control feedback to values corresponding to the quantisation floor (if specified) or a "reasonable" quantisation (6.0) if not. */ double init_quant = (encparams.quant_floor > 0.0 ? encparams.quant_floor : 6.0); int i; for( i = FIRST_PICT_TYPE; i <= LAST_PICT_TYPE; ++i ) { ratectl_vbuf[i] = static_cast(init_quant * fb_gain / 62.0); Xhi[i] = 1.0; // Not used in first frame, set so init // for valgrind, debug messages etc. sum_size[i] = 0.0; pict_count[i] = 0; } first_gop = true; K_AVG_WINDOW[I_TYPE] = 2.0; switch( encparams.M ) { case 1 : // P K_AVG_WINDOW[P_TYPE] = 8.0; K_AVG_WINDOW[B_TYPE] = 1.0; // dummy break; case 2 : // BP K_AVG_WINDOW[P_TYPE] = 4.0; K_AVG_WINDOW[B_TYPE] = 4.0; break; default: // BBP K_AVG_WINDOW[P_TYPE] = 3.0; K_AVG_WINDOW[B_TYPE] = 7.0; break; } /* We assume that having less than 4 frame intervals worth buffered is cutting it fine for avoiding under-runs. This is the buffer_safe margin. The gain values represent the fraction of the under/over shoot to be recovered during one second. Gain is lower if the buffer space above the buffer safe margin is large. Gain is currently set to so that if the buffer is down to the buffer_safe margin the deficit should be recovered in one second. */ if( encparams.still_size > 0 ) { per_pict_bits = encparams.still_size * 8; undershoot_carry = 0; overshoot_gain = 1.0; } else { per_pict_bits = static_cast(encparams.fieldpic ? ctrl_bitrate / field_rate : ctrl_bitrate / encparams.decode_frame_rate ); int buffer_danger = 4 * per_pict_bits ; int safe_buffer_variation = (encparams.video_buffer_size - buffer_danger); if( safe_buffer_variation < 0 ) mjpeg_error_exit1("Rate control can't cope with a video buffer smaller 4 frame intervals"); undershoot_carry = safe_buffer_variation/6; /* Gain is set so that feedback is set to recover buffer variation in 4 seconds for a typical DVD stream. Gain is reduced in proportion to buffer size and increased in proportion to bit-rate. Note this a very low gain and may well produce buffer variations above the actual buffer size. However, we don't care as the second pass will clean things up taking advantage of look-ahead. */ overshoot_gain = (0.25 * (230.0*8.0/11000.0)) * encparams.bit_rate / encparams.video_buffer_size; //fprintf( stderr, "VBS=%d BD=%d Overshoot gain = %.2f", encparams.video_buffer_size, buffer_danger, overshoot_gain ); } next_ip_delay = 0.0; decoding_time = 0.0; } /********************* * * Setup GOP structure for coding. * ********************/ void OnTheFlyPass1::GopSetup( int np, int nb ) { N[P_TYPE] = encparams.fieldpic ? 2*np+1 : 2*np; N[B_TYPE] = encparams.fieldpic ? 2*nb : 2*nb; N[I_TYPE] = encparams.fieldpic ? 1 : 2; fields_in_gop = N[I_TYPE] + N[P_TYPE] + N[B_TYPE]; } /********************* * * Update rate control parameters for start of new sequence * ********************/ void OnTheFlyPass1::InitSeq() { /* If its stills with a size we have to hit then make the guesstimates of for initial quantisation pessimistic... */ bits_transported = bits_used = 0; field_rate = 2*encparams.decode_frame_rate; fields_per_pict = encparams.fieldpic ? 1 : 2; } /********************* * * Update rate control parameters for start of new GOP * ********************/ void OnTheFlyPass1::InitGOP( ) { /* At the start of a GOP before any frames have gone the actual buffer state represents a long term average. Any undershoot due to the I_frame of the previous GOP should by now have been caught up. */ gop_buffer_correction = 0; /* Each still is encoded independently so we reset rate control for each one. They're all I-frames so each stills is a GOP too. */ int i; if( first_gop || encparams.still_size > 0) { mjpeg_debug( "FIRST GOP INIT"); fast_tune = true; first_gop = false; for( i = FIRST_PICT_TYPE; i <= LAST_PICT_TYPE; ++i ) { first_encountered[i] = true; pict_base_bits[i] = per_pict_bits; } } else { mjpeg_debug( "REST GOP INIT" ); int available_bits = static_cast( (ctrl_bitrate+buffer_variation*overshoot_gain) * fields_in_gop/field_rate); double Xsum = 0.0; for( i = FIRST_PICT_TYPE; i <= LAST_PICT_TYPE; ++i ) Xsum += N[i]*Xhi[i]; for( i = FIRST_PICT_TYPE; i <= LAST_PICT_TYPE; ++i ) pict_base_bits[i] = static_cast(fields_per_pict*available_bits*Xhi[i]/Xsum); fast_tune = false; } } /* **************************** * * Update rate control parameters for start of new Picture * * ****************************/ void OnTheFlyPass1::InitPict(Picture &picture) { int available_bits; double Xsum; /* TODO: A.Stevens Nov 2000 - This modification needs testing visually. Weird. The original code used the average activity of the *previous* frame as the basis for quantisation calculations for rather than the activity in the *current* frame. That *has* to be a bad idea..., surely, here we try to be smarter by using the current values and keeping track of how much of the frames activitity has been covered as we go along. We also guesstimate the relationship between (sum of DCT coefficients) and actual quantisation weighted activty. We use this to try to predict the activity of each frame. */ actsum = picture.VarSumBestMotionComp(); avg_act = actsum/(double)(encparams.mb_per_pict); sum_avg_act += avg_act; actcovered = 0.0; sum_base_Q = 0.0; sum_actual_Q = 0; /* Allocate target bits for frame based on frames numbers in GOP weighted by: - global complexity averages - predicted activity measures T = available_bits * (Nx * Xx) / Sigma_j (Nj * Xj) N.b. B frames are an exception as there is *no* predictive element in their bit-allocations. The reason this is done is that highly active B frames are inevitably the result of transients and/or scene changes. Psycho-visual considerations suggest there's no point rendering sudden transients terribly well as they're not percieved accurately anyway. In the case of scene changes similar considerations apply. In this case also we want to save bits for the next I or P frame where they will help improve other frames too. Note that we have to calulate per-frame bits by scaling the one-second bit-pool to a one-GOP bit-pool. */ if( encparams.still_size > 0 ) available_bits = per_pict_bits; else { int feedback_correction = static_cast( fast_tune ? buffer_variation * overshoot_gain : (buffer_variation+gop_buffer_correction) * overshoot_gain ); // Sanity limit - don't want negative available bits or // ludicrously small available bits. "Bad guesses" will be fixed by // 2nd pass anyway... available_bits = std::max( ctrl_bitrate * 0.2, ctrl_bitrate+feedback_correction ) * fields_in_gop/field_rate; } Xsum = 0.0; int i; for( i = FIRST_PICT_TYPE; i <= LAST_PICT_TYPE; ++i ) Xsum += N[i]*Xhi[i]; vbuf_fullness = ratectl_vbuf[picture.pict_type]; double first_weight[NUM_PICT_TYPES]; first_weight[I_TYPE] = 1.0; first_weight[P_TYPE] = 1.7; first_weight[B_TYPE] = 1.7*2.0; double gop_frac = 0.0; if( first_encountered[picture.pict_type] ) { for( i = FIRST_PICT_TYPE; i <= LAST_PICT_TYPE; ++i ) gop_frac += N[i]/first_weight[i]; target_bits = static_cast(fields_per_pict*available_bits / (gop_frac * first_weight[picture.pict_type])); } else target_bits = static_cast(fields_per_pict*available_bits*Xhi[picture.pict_type]/Xsum); /* If we're fed a sequences of identical or near-identical images we can get actually get allocations for frames that exceed the video buffer size! This of course won't work so we arbitrarily limit any individual frame to 3/4's of the buffer. */ target_bits = min( target_bits, encparams.video_buffer_size*3/4 ); mjpeg_debug( "Frame %c T=%05d A=%06d Xi=%.2f Xp=%.2f Xb=%.2f", pict_type_char[picture.pict_type], (int)target_bits/8, (int)available_bits/8, Xhi[I_TYPE], Xhi[P_TYPE],Xhi[B_TYPE] ); /* To account for the wildly different sizes of frames we compute a correction to the current instantaneous buffer state that accounts for the fact that all other thing being equal buffer will go down a lot after the I-frame decode but fill up again through the B and P frames. For this we use the base bit allocations of the picture's "pict_base_bits" which will pretty accurately add up to a GOP-length's of bits not the more dynamic predictive T target bit-allocation (which *won't* add up very well). */ gop_buffer_correction += (pict_base_bits[picture.pict_type]-per_pict_bits); /* Undershot bits have been "returned" */ vbuf_fullness = max( vbuf_fullness, 0 ); //fprintf( stderr, "T=%05d A=%06d GBC = %d VBF=%d", (int)target_bits/8, (int)available_bits/8, (int)gop_buffer_correction/8, // (int)vbuf_fullness/8); /* We don't let the target volume get absurdly low as it makes some of the prediction maths ill-condtioned. At these levels quantisation is always minimum anyway */ target_bits = max( target_bits, 4000 ); if( encparams.still_size > 0 && encparams.vbv_buffer_still_size ) { /* If stills size must match then target low to ensure no overshoot. */ mjpeg_debug( "Setting VCD HR still overshoot margin to %d bytes", target_bits/(16*8) ); frame_overshoot_margin = target_bits/16; target_bits -= frame_overshoot_margin; } picture.avg_act = avg_act; picture.sum_avg_act = sum_avg_act; cur_base_Q = fmax( vbuf_fullness*62.0/fb_gain, encparams.quant_floor); cur_mquant = ScaleQuant( picture.q_scale_type, cur_base_Q ); mquant_change_ctr = encparams.mb_width/2-1; //fprintf( stderr, " CBQ = %.1f CMQ=%03d\n", cur_base_Q, cur_mquant); } /* * Update rate-controls statistics after pictures has ended.. * * RETURN: The amount of padding necessary for picture to meet syntax or * rate constraints... */ void OnTheFlyPass1::PictUpdate( Picture &picture, int &padding_needed) { int32_t actual_bits; /* Actual (inc. padding) picture bit counts */ int frame_overshoot; actual_bits = picture.EncodedSize(); frame_overshoot = (int)actual_bits-(int)target_bits; /* For the virtual buffers for quantisation feedback it is the actual under/overshoot *including* padding. Otherwise the buffers go zero. */ vbuf_fullness += frame_overshoot; /* Warn if it looks like we've busted the safety margins in stills size specification. Adjust padding to account for safety margin if we're padding to suit stills whose size has to be specified in advance in vbv_buffer_size. */ picture.pad = 0; int padding_bits = 0; if( encparams.still_size > 0 && encparams.vbv_buffer_still_size) { if( frame_overshoot > frame_overshoot_margin ) { mjpeg_warn( "Rate overshoot: VCD hi-res still %d bytes too large! ", ((int)actual_bits)/8-encparams.still_size); } // // Aim for an actual size squarely in the middle of the 2048 // byte granuality of the still_size coding. This gives a // safety margin for headers etc. // frame_overshoot = frame_overshoot - frame_overshoot_margin; if( frame_overshoot < -2048*8 ) frame_overshoot += 1024*8; // Make sure we pad nicely to byte alignment if( frame_overshoot < 0 ) { padding_bits = (((actual_bits-frame_overshoot)>>3)<<3)-actual_bits; picture.pad = 1; } } /* Adjust the various bit counting parameters for the padding bytes that * will be added */ actual_bits += padding_bits ; frame_overshoot += padding_bits; /* Compute the estimate of the current decoder buffer state. We use this to feedback-correct the available bit-pool with a fraction of the current buffer state estimate. If we're ahead of the game we allow a small increase in the pool. If we dropping towards a dangerously low buffer we decrease the pool (rather more vigorously). Note that since we cannot hold more than a buffer-full if we have a positive buffer_variation in VBR we assume we only sent until the buffer was full in CBR we assume it was padded away. */ bits_used += actual_bits; bits_transported += per_pict_bits; //mjpeg_debug( "TR=%" PRId64 " USD=%" PRId64 "", bits_transported/8, bits_used/8); buffer_variation = static_cast(bits_transported - bits_used); if( buffer_variation > 0 ) { bits_transported = bits_used; buffer_variation = 0; } //fprintf( stderr, "BV=%d A=%d T=%d\n", (int)buffer_variation/8, actual_bits/8, target_bits/8 ); /* Rate-control ABQ is the average 'base' quantisation (before adjustments for relative macro-block complexity) of the block. This is what is used as a base-line for adjusting quantisation to meet a */ picture.ABQ = sum_base_Q / encparams.mb_per_pict; picture.AQ = static_cast(sum_actual_Q ) / encparams.mb_per_pict; sum_avg_quant += picture.AQ; /* X (Chi - Complexity!) is an estimate of "bit-demand" for the frame. I.e. how many bits it would need to be encoded without quantisation. It is used in adaptively allocating bits to busy frames. It is simply calculated as bits actually used times average target (not rounded!) quantisation. K is a running estimate of how bit-demand relates to frame activity - bits demand per activity it is used to allow prediction of quantisation needed to hit a bit-allocation. */ double actual_Xhi = actual_bits * picture.AQ; picture.SetComplexity( actual_Xhi ); /* To handle longer sequences with little picture content where I, B and P frames are of unusually similar size we insist I frames assumed to be at least one and a half times as complex as typical P frames */ if( picture.pict_type == I_TYPE ) actual_Xhi = fmax(actual_Xhi, 1.5*Xhi[P_TYPE]); /* Stats and logging AQ is the average Quantisation of the block. Its only used for stats display as the integerisation of the quantisation value makes it rather coarse for use in estimating bit-demand */ picture.SQ = sum_avg_quant; /* Xhi are used as a guesstimate of *typical* frame activities based on the past. Thus we don't want anomalous outliers due to scene changes swinging things too much (this is handled by the predictive complexity measure stuff) so we use moving averages. The weightings are intended so all 3 averages have similar real-time decay periods based on an assumption of 20-30Hz frame rates. */ ratectl_vbuf[picture.pict_type] = vbuf_fullness; sum_size[picture.pict_type] += actual_bits/8.0; pict_count[picture.pict_type] += 1; if( first_encountered[picture.pict_type] ) { Xhi[picture.pict_type] = actual_Xhi; first_encountered[picture.pict_type] = false; } else { double win = fast_tune ? K_AVG_WINDOW[picture.pict_type] / 1.7 : K_AVG_WINDOW[picture.pict_type]; Xhi[picture.pict_type] = (actual_Xhi + win*Xhi[picture.pict_type])/(win+1.0); } mjpeg_debug( "Frame %c A=%6.0f %.2f: I = %6.0f P = %5.0f B = %5.0f", pict_type_char[picture.pict_type], actual_bits/8.0, actual_Xhi, sum_size[I_TYPE]/pict_count[I_TYPE], sum_size[P_TYPE]/pict_count[P_TYPE], sum_size[B_TYPE]/pict_count[B_TYPE] ); padding_needed = padding_bits/8; } int OnTheFlyPass1::InitialMacroBlockQuant() { return cur_mquant; } int OnTheFlyPass1::TargetPictureEncodingSize() { return target_bits; } /************* * * SelectQuantization - select a quantisation for the current * macroblock based on the fullness of the virtual decoder buffer. * * NOTE: *Must* be called for all Macroblocks as content-based quantisation tuning is * supported. ************/ int OnTheFlyPass1::MacroBlockQuant( const MacroBlock &mb ) { int lum_variance = mb.BaseLumVariance(); const Picture &picture = mb.ParentPicture(); if( mquant_change_ctr == 0 || lum_variance < encparams.boost_var_ceil ) { /* A.Stevens 2000 : we measure how much *information* (total activity) has been covered and aim to release bits in proportion. We keep track of a virtual buffer that catches the difference between the bits allocated and the bits we actually used. The fullness of this buffer controls quantisation. */ /* Guesstimate a virtual buffer fullness based on bits used vs. bits in proportion to activity encoded */ double dj = static_cast(vbuf_fullness) + static_cast(picture.EncodedSize()) - actcovered * target_bits / actsum; /* scale against dynamic range of mquant and the bits/picture count. encparams.quant_floor != 0.0 is the VBR case where we set a bitrate as a (high) maximum and then put a floor on quantisation to achieve a reasonable overall size. Not that this *is* baseline quantisation. Not adjust for local activity. Otherwise we end up blurring active macroblocks. Silly in a VBR context. */ /* Heuristic: We decrease quantisation for macroblocks with markedly low luminace variance. This helps make gentle gradients (e.g. smooth backgrounds) look better at (hopefully) small additonal cost in coding bits */ double act_boost; if( lum_variance < encparams.boost_var_ceil ) { // Force update for *next* macroblock as this may need a 'normal' // quantisation without any boosying mquant_change_ctr = 0; // Calculate quantisation reduction.... if( lum_variance < encparams.boost_var_ceil/2) act_boost = encparams.act_boost; else { double max_boost_var = encparams.boost_var_ceil/2; double above_max_boost = (static_cast(lum_variance)-max_boost_var) / max_boost_var; act_boost = 1.0 + (encparams.act_boost-1.0) * (1.0-above_max_boost); } } else act_boost = 1.0; cur_base_Q = ClipQuant( picture.q_scale_type, fmax(dj*62.0/fb_gain,encparams.quant_floor) ); cur_mquant = ScaleQuant(picture.q_scale_type,cur_base_Q/act_boost) ; } --mquant_change_ctr; if( mquant_change_ctr < 0) { mquant_change_ctr = encparams.mb_width/2-1; } sum_base_Q += cur_base_Q; sum_actual_Q += cur_mquant; /* Update activity covered */ actcovered += lum_variance; return cur_mquant; } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/tables.c0000644000175000017500000001612511445477341017346 0ustar glowwormglowworm/* tables.c, Tables for MPEG syntax */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ #include #include "tables.h" const char version[] ="MSSG+ 1.3 2001/6/10 (development of mpeg2encode V1.2, 96/07/19)" ; const char author[] ="(C) 1996, MPEG Software Simulation Group, (C) 2000, 2001,2002 Andrew Stevens, Rainer Johanni" ; /* zig-zag scan */ const uint8_t zig_zag_scan[64] = { 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 } ; /* alternate scan */ const uint8_t alternate_scan[64] = { 0,8,16,24,1,9,2,10,17,25,32,40,48,56,57,49, 41,33,26,18,3,11,4,12,19,27,34,42,50,58,35,43, 51,59,20,28,5,13,6,14,21,29,36,44,52,60,37,45, 53,61,22,30,7,15,23,31,38,46,54,62,39,47,55,63 } ; /* default intra quantization matrix */ const uint16_t default_intra_quantizer_matrix[64] = { 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 } ; const uint16_t hires_intra_quantizer_matrix[64] = { 8, 16, 18, 20, 24, 25, 26, 30, 16, 16, 20, 23, 25, 26, 30, 30, 18, 20, 22, 24, 26, 28, 29, 31, 20, 21, 23, 24, 26, 28, 31, 31, 21, 23, 24, 25, 28, 30, 30, 33, 23, 24, 25, 28, 30, 30, 33, 36, 24, 25, 26, 29, 29, 31, 34, 38, 25, 26, 28, 29, 31, 34, 38, 42 } ; const uint16_t default_nonintra_quantizer_matrix[64] = { 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 } ; const uint16_t kvcd_intra_quantizer_matrix[64] = { 8, 9, 12, 22, 26, 27, 29, 34, 9, 10, 14, 26, 27, 29, 34, 37, 12, 14, 18, 27, 29, 34, 37, 38, 22, 26, 27, 31, 36, 37, 38, 40, 26, 27, 29, 36, 39, 38, 40, 48, 27, 29, 34, 37, 38, 40, 48, 58, 29, 34, 37, 38, 40, 48, 58, 69, 34, 37, 38, 40, 48, 58, 69, 79 } ; const uint16_t kvcd_nonintra_quantizer_matrix[64] = { 16, 18, 20, 22, 24, 26, 28, 30, 18, 20, 22, 24, 26, 28, 30, 32, 20, 22, 24, 26, 28, 30, 32, 34, 22, 24, 26, 30, 32, 32, 34, 36, 24, 26, 28, 32, 34, 34, 36, 38, 26, 28, 30, 32, 34, 36, 38, 40, 28, 30, 32, 34, 36, 38, 42, 42, 30, 32, 34, 36, 38, 40, 42, 44 } ; const uint16_t flat_intra_quantizer_matrix[64] = { 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 } ; const uint16_t flat_nonintra_quantizer_matrix[64] = { 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 } ; const uint16_t tmpgenc_intra_quantizer_matrix[64] = { /* The original HEX table for reference 08, 10, 13, 16, 1A, 1B, 1D, 22, 10, 10, 16, 18, 1B, 1D, 22, 25, 13, 16, 1A, 1B, 1D, 22, 22, 26, 16, 16, 1A, 1B, 1D, 22, 25, 28, 16, 1A, 1B, 1D, 20, 23, 28, 30, 1A, 1B, 1D, 20, 23, 28, 30, 3A, 1A, 1B, 1D, 22, 26, 2E, 38, 45, 1B, 1D, 23, 26, 2E, 38, 45, 53 */ /* Decimal table */ 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 } ; const uint16_t tmpgenc_nonintra_quantizer_matrix[64] = { /* The original HEX table for reference 10, 11, 12, 13, 14, 15, 16, 17, 11, 12, 13, 14, 15, 16, 17, 18, 12, 13, 14, 15, 16, 17, 18, 19, 13, 14, 15, 16, 17, 18, 1A, 1B, 14, 15, 16, 17, 19, 1A, 1B, 1C, 15, 16, 17, 18, 1A, 1B, 1C, 1E, 16, 17, 18, 1A, 1B, 1C, 1E, 1F, 17, 18, 19, 1B, 1C, 1E, 1F, 21 */ /* DECIMAL table */ 16, 17, 18, 19, 20, 21, 22, 23, 17, 18, 19, 20, 21, 22, 23, 24, 18, 19, 20, 21, 22, 23, 24, 25, 19, 20, 21, 22, 23, 24, 26, 27, 20, 21, 22, 23, 25, 26, 27, 28, 21, 22, 23, 24, 26, 27, 28, 30, 22, 23, 24, 26, 27, 28, 30, 31, 23, 24, 25, 27, 28, 30, 31, 33 } ; /* Hires non intra quantization matrix. THis *is* the MPEG default... */ const uint16_t *hires_nonintra_quantizer_matrix = &default_nonintra_quantizer_matrix[0] ; const char pict_type_char[6] = {'X', 'I', 'P', 'B', 'D', 'X'} ; /* Support for the picture layer(!) insertion of scan data fieldsas MPEG user-data section as part of I-frames. */ const uint8_t dummy_svcd_scan_data[14] = { 0x10, /* Scan data tag */ 14, /* Length */ 0x00, 0x80, 0x81, /* Dummy data - this will be filled */ 0x00, 0x80, 0x81, /* By the multiplexor or cd image */ 0xff, 0xff, 0xff, /* creation software */ 0xff, 0xff, 0xff } ; /* non-linear quantization coefficient table */ const uint8_t non_linear_mquant_table[32] = { 0, 1, 2, 3, 4, 5, 6, 7, 8,10,12,14,16,18,20,22, 24,28,32,36,40,44,48,52, 56,64,72,80,88,96,104,112 }; /* non-linear mquant table for mapping from scale to code * since reconstruction levels are not bijective with the index map, * it is up to the designer to determine most of the quantization levels */ const uint8_t map_non_linear_mquant[113] = { 0 ,1 , 2, 3, 4, 5, 6, 7, 8, 8, 9 ,9, 10,10,11,11,12,12,13,13, 14,14,15,15,16,16,16,17,17,17, 18,18,18,18,19,19,19,19,20,20, 20,20,21,21,21,21,22,22,22,22, 23,23,23,23,24,24,24,24,24,24, 24,25,25,25,25,25,25,25,26,26, 26,26,26,26,26,26,27,27,27,27, 27,27,27,27,28,28,28,28,28,28, 28,29,29,29,29,29,29,29,29,29, 29,30,30,30,30,30,30,30,31,31, 31,31,31 }; mjpegtools-2.1.0/mpeg2enc/encoderparams.cc0000644000175000017500000005727211456612024021061 0ustar glowwormglowworm/* encoderparams - class holding all the various control parameters for and individual encoder instance. For speed a lot of address offsets/sizes are computed once-and-for-all and held in this object. */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ /* Modifications and enhancements (C) 2000,2001,2002,2003 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include #include "encoderparams.hh" #include "format_codes.h" #include "mpegconsts.h" #include "mpeg2encoptions.hh" //#include "mpeg2syntaxcodes.h" #include "tables.h" #include "ratectl.hh" #include "cpu_accel.h" #include "motionsearch.h" #include // REMOVE #define MAX(a,b) ( (a)>(b) ? (a) : (b) ) #define MIN(a,b) ( (a)<(b) ? (a) : (b) ) EncoderParams::EncoderParams( const MPEG2EncOptions &encoptions) { } void EncoderParams::InitEncodingControls( const MPEG2EncOptions &options) { coding_tolerance = 0.1; /* Tune threading and motion compensation for specified number of CPU's and specified speed parameters. */ act_boost = 1.0+options.act_boost; boost_var_ceil = options.boost_var_ceil; switch( options.num_cpus ) { case 0 : /* Special case for debugging... turns of all multi-threading */ encoding_parallelism = 0; break; case 1 : /* Currently this is the default option */ encoding_parallelism = 1; break; case 2: encoding_parallelism = 2; break; default : encoding_parallelism = options.num_cpus > MAX_WORKER_THREADS-1 ? MAX_WORKER_THREADS-1 : options.num_cpus; break; } me44_red = options.me44_red; me22_red = options.me22_red; unit_coeff_elim = options.unit_coeff_elim; /* round picture dimensions to nearest multiple of 16 or 32 */ mb_width = (horizontal_size+15)/16; mb_height = prog_seq ? (vertical_size+15)/16 : 2*((vertical_size+31)/32); mb_height2 = fieldpic ? mb_height>>1 : mb_height; /* for field pictures */ enc_width = 16*mb_width; enc_height = 16*mb_height; #ifdef DEBUG_MOTION_EST static const int MARGIN = 64; #else static const int MARGIN = 8; #endif #ifdef HAVE_ALTIVEC /* Pad phy_width to 64 so that the rowstride of 4*4 * sub-sampled data will be a multiple of 16 (ideal for AltiVec) * and the rowstride of 2*2 sub-sampled data will be a multiple * of 32. Height does not affect rowstride, no padding needed. */ phy_width = (enc_width + 63) & (~63); #else phy_width = enc_width+MARGIN; #endif phy_height = enc_height+MARGIN; /* Calculate the sizes and offsets in to luminance and chrominance buffers. A.Stevens 2000 for luminance data we allow space for fast motion estimation data. This is actually 2*2 pixel sub-sampled uint8_t followed by 4*4 sub-sampled. We add an extra row to act as a margin to allow us to neglect / postpone edge condition checking in time-critical loops... */ phy_chrom_width = phy_width>>1; phy_chrom_height = phy_height>>1; enc_chrom_width = enc_width>>1; enc_chrom_height = enc_height>>1; phy_height2 = fieldpic ? phy_height>>1 : phy_height; enc_height2 = fieldpic ? enc_height>>1 : enc_height; phy_width2 = fieldpic ? phy_width<<1 : phy_width; phy_chrom_width2 = fieldpic ? phy_chrom_width<<1 : phy_chrom_width; lum_buffer_size = (phy_width*phy_height) + sizeof(uint8_t) *(phy_width/2)*(phy_height/2) + sizeof(uint8_t) *(phy_width/4)*(phy_height/4); chrom_buffer_size = phy_chrom_width*phy_chrom_height; fsubsample_offset = (phy_width)*(phy_height) * sizeof(uint8_t); qsubsample_offset = fsubsample_offset + (phy_width/2)*(phy_height/2)*sizeof(uint8_t); mb_per_pict = mb_width*mb_height2; #ifdef OUTPUT_STAT /* open statistics output file */ if (!(statfile = fopen(statname,"w"))) { mjpeg_error_exit1( "Couldn't create statistics output file %s", statname); } #endif } static int f_code( int max_radius ) { int c=5; if( max_radius < 64) c = 4; if( max_radius < 32) c = 3; if( max_radius < 16) c = 2; if( max_radius < 8) c = 1; return c; } void EncoderParams::Init( const MPEG2EncOptions &options ) { int i; const char *msg = 0; //istrm_nframes = 999999999; /* determined by EOF of stdin */ N_min = options.min_GOP_size; /* I frame distance */ N_max = options.max_GOP_size; closed_GOPs = options.closed_GOPs; mjpeg_info( "GOP SIZE RANGE %d TO %d %s", N_min, N_max, closed_GOPs ? "(all GOPs closed)" : "" ); M = options.Bgrp_size; /* I or P frame distance */ M_min = options.preserve_B ? M : 1; if( M > N_max ) M = N_max; mpeg1 = (options.mpeg == 1); fieldpic = (options.fieldenc == 2); dualprime = options.hack_dualprime == 1 && M == 1; pulldown_32 = options.vid32_pulldown; aspectratio = options.aspect_ratio; frame_rate_code = options.frame_rate; // SVCD and probably DVD? mandate progressive_sequence = 0 switch( options.format ) { case MPEG_FORMAT_SVCD : case MPEG_FORMAT_SVCD_NSR : case MPEG_FORMAT_SVCD_STILL : case MPEG_FORMAT_DVD : case MPEG_FORMAT_DVD_NAV : prog_seq = 0; break; case MPEG_FORMAT_ATSC1080i : case MPEG_FORMAT_ATSC480i : prog_seq = frame_rate_code == 1 || frame_rate_code == 2 ? 0 : 1; break; case MPEG_FORMAT_ATSC720p : case MPEG_FORMAT_ATSC480p : prog_seq = 1; break; default : // If we want 3:2 pulldown must code prog_seq as otherwise // repeat_first_field and topfirst encode frame repetitions!!! prog_seq = (options.mpeg == 1 || (options.fieldenc == 0 && !options.vid32_pulldown)); break; } dctsatlim = mpeg1 ? 255 : 2047; /* If we're using a non standard (VCD?) profile bit-rate adjust the vbv buffer accordingly... */ if(options.bitrate == 0 ) { mjpeg_error_exit1( "Generic format - must specify bit-rate!" ); } still_size = 0; if( MPEG_STILLS_FORMAT(options.format) ) { vbv_buffer_code = options.vbv_buffer_still_size / 2048; vbv_buffer_still_size = options.pad_stills_to_vbv_buffer_size; bit_rate = options.bitrate; still_size = options.still_size; } else if( options.mpeg == 1 ) { /* Scale VBV relative to VCD */ bit_rate = MAX(10000, options.bitrate); vbv_buffer_code = (20 * options.bitrate / 1151929); } else { bit_rate = MAX(10000, options.bitrate); vbv_buffer_code = MIN(112,options.video_buffer_size / 2); } target_bitrate = options.target_bitrate; if( target_bitrate > bit_rate ) { target_bitrate = bit_rate; mjpeg_warn( "Target bit rate may not exceed specified (max) bit-rate: reducing to %.0fKbps", target_bitrate ); } stream_Xhi = options.stream_Xhi; stream_frames = options.stream_frames; vbv_buffer_size = vbv_buffer_code*16384; if( options.quant ) { quant_floor = RateCtl::InvScaleQuant( options.mpeg == 1 ? 0 : 1, options.quant ); mjpeg_info( "Quant code = %.0f quantizer-scale = %d", quant_floor, options.quant ); } else { quant_floor = 0.0; /* Larger than max quantisation */ } video_buffer_size = options.video_buffer_size * 1024 * 8; seq_hdr_every_gop = options.seq_hdr_every_gop; seq_end_every_gop = options.seq_end_every_gop; svcd_scan_data = options.svcd_scan_data; ignore_constraints = options.ignore_constraints; seq_length_limit = options.seq_length_limit; nonvid_bit_rate = options.nonvid_bitrate * 1000; low_delay = 0; constrparms = (options.mpeg == 1 && !MPEG_STILLS_FORMAT(options.format)); profile = MAIN_PROFILE; level = options.level; // Force appropriate level for standards-compliant preset-formats switch(options.format) { case MPEG_FORMAT_ATSC720p : case MPEG_FORMAT_ATSC1080i : level = HIGH_LEVEL; break; case MPEG_FORMAT_SVCD_STILL : case MPEG_FORMAT_SVCD : case MPEG_FORMAT_DVD : case MPEG_FORMAT_DVD_NAV : case MPEG_FORMAT_VCD : default : level = MAIN_LEVEL; break; }; if( level == 0 ) level = MAIN_LEVEL; if( MPEG_SDTV_FORMAT(options.format) ) { switch(options.norm) { case 'p': video_format = 1; break; case 'n': video_format = 2; break; case 's': video_format = 3; break; default: video_format = 5; break; /* unspec. */ } switch(options.norm) { case 's': case 'p': /* ITU BT.470 B,G */ color_primaries = 5; transfer_characteristics = 5; /* Gamma = 2.8 (!!) */ matrix_coefficients = 5; msg = "PAL B/G"; break; case 'n': /* SMPTPE 170M "modern NTSC" */ color_primaries = 6; matrix_coefficients = 6; transfer_characteristics = 6; msg = "NTSC"; break; default: /* unspec. */ color_primaries = 2; matrix_coefficients = 2; transfer_characteristics = 2; msg = "unspecified"; break; } } else { video_format = 0; // 'Component' switch( options.format ) { case MPEG_FORMAT_ATSC480i : /* SMPTPE 170M "modern NTSC" */ case MPEG_FORMAT_ATSC480p : color_primaries = 6; matrix_coefficients = 6; transfer_characteristics = 6; break; case MPEG_FORMAT_ATSC720p :/* ITU.R BT.709 HDTV */ case MPEG_FORMAT_ATSC1080i : color_primaries = 1; matrix_coefficients = 1; transfer_characteristics = 1; break; default : abort(); }; }; mjpeg_info( "Setting colour/gamma parameters to \"%s\"", msg); horizontal_size = options.in_img_width; vertical_size = options.in_img_height; switch( options.format ) { case MPEG_FORMAT_SVCD_STILL : case MPEG_FORMAT_SVCD_NSR : case MPEG_FORMAT_SVCD : case MPEG_FORMAT_DVD : case MPEG_FORMAT_DVD_NAV : /* It would seem DVD and perhaps SVCD demand a 540 pixel display size for 4:3 aspect video. However, many players expect 480 and go weird if this isn't set... */ if( options.hack_svcd_hds_bug ) { display_horizontal_size = options.in_img_width; display_vertical_size = options.in_img_height; } else { display_horizontal_size = aspectratio == 2 ? 540 : 720; display_vertical_size = options.in_img_height; } break; // ATSC 1080i is unusual in that it *requires* display of 1080 lines // when 1088 are coded case MPEG_FORMAT_ATSC1080i : display_vertical_size = 1080; break; default: if( options.display_hsize <= 0 ) display_horizontal_size = options.in_img_width; else display_horizontal_size = options.display_hsize; if( options.display_vsize <= 0 ) display_vertical_size = options.in_img_height; else display_vertical_size = options.display_vsize; break; } dc_prec = options.mpeg2_dc_prec; /* 9 bits */ topfirst = 0; if( ! prog_seq ) { int fieldorder; if( options.force_interlacing != Y4M_UNKNOWN ) { mjpeg_info( "Forcing playback video to be: %s", mpeg_interlace_code_definition( options.force_interlacing ) ); fieldorder = options.force_interlacing; } else fieldorder = options.input_interlacing; topfirst = (fieldorder == Y4M_ILACE_TOP_FIRST || fieldorder ==Y4M_ILACE_NONE ); } else topfirst = 0; // Restrict to frame motion estimation and DCT modes only when MPEG1 // or when progressive content is specified for MPEG2. // Note that for some profiles although we have progressive sequence // header bit = 0 we still only encode with frame modes (for speed). frame_pred_dct_tab[0] = frame_pred_dct_tab[1] = frame_pred_dct_tab[2] = (options.mpeg == 1 || options.fieldenc == 0) ? 1 : 0; mjpeg_info( "Progressive format frames = %d", frame_pred_dct_tab[0] ); qscale_tab[0] = qscale_tab[1] = qscale_tab[2] = options.mpeg == 1 ? 0 : 1; mjpeg_info( "q_scale_type = %d", qscale_tab[0] ); intravlc_tab[0] = intravlc_tab[1] = intravlc_tab[2] = options.mpeg == 1 ? 0 : 1; altscan_tab[2] = altscan_tab[1] = altscan_tab[0] = (options.mpeg == 1 || options.hack_altscan_bug) ? 0 : 1; /* A.Stevens 2000: The search radius *has* to be a multiple of 8 for the new fast motion compensation search to work correctly. We simply round it up if needs be. */ int searchrad = options.searchrad; if(searchrad*M>127) { searchrad = 127/M; mjpeg_warn("Search radius reduced to %d",searchrad); } { int radius_x = searchrad; int radius_y = searchrad*vertical_size/horizontal_size; /* TODO: These f-codes should really be adjusted for each picture type... */ motion_data = (struct motion_data *)malloc(M*sizeof(struct motion_data)); if (!motion_data) mjpeg_error_exit1("malloc failed"); for (i=0; i768 || vertical_size>576 || ((horizontal_size+15)/16)*((vertical_size+15)/16)>396 || ((horizontal_size+15)/16)*((vertical_size+15)/16)*frame_rate>396*25.0 || frame_rate>30.0) { mjpeg_info( "size - setting constrained_parameters_flag = 0"); constrparms = 0; } } if (constrparms) { for (i=0; i4) { mjpeg_info("Hor. motion search forces constrained_parameters_flag = 0"); constrparms = 0; break; } if (motion_data[i].forw_vert_f_code>4) { mjpeg_info("Ver. motion search forces constrained_parameters_flag = 0"); constrparms = 0; break; } if (i!=0) { if (motion_data[i].back_hor_f_code>4) { mjpeg_info("Hor. motion search setting constrained_parameters_flag = 0"); constrparms = 0; break; } if (motion_data[i].back_vert_f_code>4) { mjpeg_info("Ver. motion search setting constrained_parameters_flag = 0"); constrparms = 0; break; } } } } } /* relational checks */ if ( mpeg1 ) { if (!prog_seq) { mjpeg_warn("mpeg1 specified - setting progressive_sequence = 1"); prog_seq = 1; } if (dc_prec!=0) { mjpeg_info("mpeg1 - setting intra_dc_precision = 0"); dc_prec = 0; } for (i=0; i<3; i++) if (qscale_tab[i]) { mjpeg_info("mpeg1 - setting qscale_tab[%d] = 0",i); qscale_tab[i] = 0; } for (i=0; i<3; i++) if (intravlc_tab[i]) { mjpeg_info("mpeg1 - setting intravlc_tab[%d] = 0",i); intravlc_tab[i] = 0; } for (i=0; i<3; i++) if (altscan_tab[i]) { mjpeg_info("mpeg1 - setting altscan_tab[%d] = 0",i); altscan_tab[i] = 0; } } if ( !mpeg1 && constrparms) { mjpeg_info("not mpeg1 - setting constrained_parameters_flag = 0"); constrparms = 0; } if( (!prog_seq || fieldpic != 0 ) && ( (vertical_size+15) / 16)%2 != 0 ) { mjpeg_warn( "Frame height won't split into two equal field pictures..."); mjpeg_warn( "forcing encoding as progressive video"); prog_seq = 1; pulldown_32 = false; fieldpic = 0; } if (prog_seq && fieldpic != 0) { mjpeg_info("prog sequence - forcing progressive frame encoding"); fieldpic = 0; } if (prog_seq && topfirst ) { mjpeg_info("prog sequence setting top_field_first = 0"); topfirst = 0; } /* search windows */ for (i=0; i (4U< (4U< (4U< (4U<(orgquant * qboost); } void EncoderParams::InitQuantMatrices( const MPEG2EncOptions &options ) { int i, v; const char *msg = NULL; const uint16_t *qmat = 0; const uint16_t *niqmat = 0; load_iquant = 0; load_niquant = 0; /* bufalloc to ensure alignment */ intra_q = static_cast(bufalloc(sizeof(uint16_t[64]))); inter_q = static_cast(bufalloc(sizeof(uint16_t[64]))); switch (options.hf_quant) { case 0: /* No -N, -H or -K used. Default matrices */ msg = "Using default unmodified quantization matrices"; qmat = default_intra_quantizer_matrix; niqmat = default_nonintra_quantizer_matrix; break; case 1: /* "-N value" used but not -K or -H */ msg = "Using -N modified default quantization matrices"; qmat = default_intra_quantizer_matrix; niqmat = default_nonintra_quantizer_matrix; load_iquant = 1; load_niquant = 1; break; case 2: /* -H used OR -H followed by "-N value" */ msg = "Setting hi-res intra Quantisation matrix"; qmat = hires_intra_quantizer_matrix; niqmat = hires_nonintra_quantizer_matrix; load_iquant = 1; if(options.hf_q_boost) load_niquant = 1; /* Custom matrix if -N used */ break; case 3: msg = "KVCD Notch Quantization Matrix"; qmat = kvcd_intra_quantizer_matrix; niqmat = kvcd_nonintra_quantizer_matrix; load_iquant = 1; load_niquant = 1; break; case 4: msg = "TMPGEnc Quantization matrix"; qmat = tmpgenc_intra_quantizer_matrix; niqmat = tmpgenc_nonintra_quantizer_matrix; load_iquant = 1; load_niquant = 1; break; case 5: msg = "Flat quantization matrix for ultra high quality encoding"; load_iquant = 1; load_niquant = 1; qmat = flat_intra_quantizer_matrix; niqmat = flat_nonintra_quantizer_matrix; break; case 6: /* -K file=qmatrixfilename */ msg = "Loading custom matrices from user specified file"; load_iquant = 1; load_niquant = 1; qmat = options.custom_intra_quantizer_matrix; niqmat = options.custom_nonintra_quantizer_matrix; break; default: mjpeg_error_exit1("Help! Unknown hf_quant value %d", options.hf_quant); /* NOTREACHED */ } if (msg) mjpeg_info( "%s", msg); for (i = 0; i < 64; i++) { v = quant_hfnoise_filt(qmat[i], i, options.hf_q_boost); if (v < 1 || v > 255) mjpeg_error_exit1("bad intra value after -N adjust"); intra_q[i] = v; v = quant_hfnoise_filt(niqmat[i], i, options.hf_q_boost); if (v < 1 || v > 255) mjpeg_error_exit1("bad nonintra value after -N adjust"); inter_q[i] = v; } } /* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/mpeg2enc/syntaxconsts.h0000644000175000017500000000313610346407114020645 0ustar glowwormglowworm/* syntaxparams.h, Global constants controlling MPEG syntax */ /* (C) 2003 Andrew Stevens */ /* These modifications are free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #ifndef _SYNTAXCONSTS_H #define _SYNTAXCONSTS_H /* SCale factor for fast integer arithmetic routines */ /* Changed this and you *must* change the quantisation routines as they depend on its absolute value */ #define IQUANT_SCALE_POW2 16 #define IQUANT_SCALE (1</dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @HAVE_ALTIVEC_TRUE@am__append_1 = $(top_builddir)/mpeg2enc/libmpeg2encpp.la bin_PROGRAMS = yuvdenoise$(EXEEXT) subdir = yuvdenoise DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_yuvdenoise_OBJECTS = main.$(OBJEXT) yuvdenoise_OBJECTS = $(am_yuvdenoise_OBJECTS) yuvdenoise_DEPENDENCIES = $(LIBMJPEGUTILS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(yuvdenoise_SOURCES) DIST_SOURCES = $(yuvdenoise_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALTIVEC_EXTRA_LIBS = @ALTIVEC_EXTRA_LIBS@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDV_CFLAGS = @LIBDV_CFLAGS@ LIBDV_LIBS = @LIBDV_LIBS@ LIBGETOPT_LIB = @LIBGETOPT_LIB@ LIBM_LIBS = @LIBM_LIBS@ LIBOBJS = @LIBOBJS@ LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ LIBPNG_LIBS = @LIBPNG_LIBS@ LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@ LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ LT_STATIC = @LT_STATIC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROGRAM_NOPIC = @PROGRAM_NOPIC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ SDLgfx_LIBS = @SDLgfx_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ V4LCONF_LIBS = @V4LCONF_LIBS@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/utils LIBMJPEGUTILS = $(top_builddir)/utils/libmjpegutils.la $(am__append_1) AM_CFLAGS = -O3 -funroll-all-loops -ffast-math yuvdenoise_SOURCES = main.c yuvdenoise_LDADD = $(LIBMJPEGUTILS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu yuvdenoise/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu yuvdenoise/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list yuvdenoise$(EXEEXT): $(yuvdenoise_OBJECTS) $(yuvdenoise_DEPENDENCIES) $(EXTRA_yuvdenoise_DEPENDENCIES) @rm -f yuvdenoise$(EXEEXT) $(LINK) $(yuvdenoise_OBJECTS) $(yuvdenoise_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool cscopelist ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mjpegtools-2.1.0/yuvdenoise/main.c0000644000175000017500000014036311525733152017506 0ustar glowwormglowworm/*********************************************************** * YUVDENOISER for the mjpegtools * * ------------------------------------------------------- * * (C) 2001-2004 Stefan Fendt * * * * Licensed and protected by the GNU-General-Public- * * License version 2 or if you prefer any later version of * * that license). See the file LICENSE for detailed infor- * * mation. * * * * FILE: main.c * * * ***********************************************************/ /* 2010-09-22, Franz Brauße * - added SSE2-accelerated versions of filter_plane_median() * and temporal_filter_planes() */ #include #include #include #include #include "config.h" #include "mjpeg_types.h" #include "yuv4mpeg.h" #include "mjpeg_logging.h" #include "cpu_accel.h" #include "motionsearch.h" #if defined(__SSE3__) # include #elif defined(__SSE2__) # include #endif int verbose = 1; int width = 0; int height = 0; int lwidth = 0; int lheight = 0; int cwidth = 0; int cheight = 0; int input_chroma_subsampling = 0; int input_interlaced = 0; int hq_mode = 0; int renoise_Y=0; int renoise_U=0; int renoise_V=0; int temp_Y_thres = 0; int temp_U_thres = 0; int temp_V_thres = 0; int med_pre_Y_thres = 0; int med_pre_U_thres = 0; int med_pre_V_thres = 0; int med_post_Y_thres = 0; int med_post_U_thres = 0; int med_post_V_thres = 0; int gauss_Y = 0; int gauss_U = 0; int gauss_V = 0; uint8_t *frame1[3]; uint8_t *frame2[3]; uint8_t *frame3[3]; uint8_t *frame4[3]; uint8_t *frame5[3]; uint8_t *frame6[3]; uint8_t *frame7[3]; uint8_t *scratchplane1; uint8_t *scratchplane2; uint8_t *outframe[3]; int buff_offset; int buff_size; uint16_t transform_L16[256]; uint8_t transform_G8[65536]; /*********************************************************** * helper-functions * ***********************************************************/ static void (*filter_plane_median)(uint8_t *, int, int, int); static void (*temporal_filter_planes)(int, int, int, int); void gauss_filter_plane (uint8_t * frame, int w, int h, int t) { int i; int v; uint8_t * src = frame; uint8_t * dst = scratchplane1; if(t==0) return; memcpy ( src-w*2, src, w ); memcpy ( src-w , src, w ); memcpy ( src+(w*h) , src+(w*h)-w, w ); memcpy ( src+(w*h)+w, src+(w*h)-w, w ); for(i=0;i<(w*h);i++) { v = *(src -2)*1; v += *(src-w -1)*1; v += *(src -1)*2; v += *(src+w -1)*1; v += *(src-w*2 )*1; v += *(src-w )*2; v += *(src )*4; v += *(src+w )*2; v += *(src+w*2 )*1; v += *(src-w +1)*1; v += *(src +1)*2; v += *(src+w +1)*1; v += *(src +2)*1; v /= 20; v = *(src)*(256-t) + (v)*(t); v /= 256; *(dst)=v; dst++; src++; } memcpy ( frame,scratchplane1,w*h ); } void temporal_filter_planes_MC (int idx, int w, int h, int t) { uint32_t sad,min; uint32_t r, c, m; int32_t d; int x,y,sx,sy; uint32_t v; int x1,y1; int x2,y2; int x3,y3; int x5,y5; int x6,y6; int x7,y7; uint8_t *f1 = frame1[idx]; uint8_t *f2 = frame2[idx]; uint8_t *f3 = frame3[idx]; uint8_t *f4 = frame4[idx]; uint8_t *f5 = frame5[idx]; uint8_t *f6 = frame6[idx]; uint8_t *f7 = frame7[idx]; uint8_t *of = outframe[idx]; #if 1 if (t == 0) // shortcircuit filter if t = 0... { memcpy (of, f4, w * h); return; } #endif for (y = 0; y < h; y+=16) for (x = 0; x < w; x+=16) { // find best matching 16x16 block for f3 min=psad_00 ( f4+(x)+(y)*w,f3+(x)+(y)*w,w,16,0x00ffffff ); x3=y3=0; for (sy=-4; sy < 4; sy++) for (sx=-4; sx < 4; sx++) { sad = psad_00 ( f4+(x)+(y)*w,f3+(x+sx)+(y+sy)*w,w,16,0x00ffffff ); sad += psad_00 ( f4+(x+8)+(y)*w,f3+(x+sx+8)+(y+sy)*w,w,16,0x00ffffff ); if(sad> 16) & 0xff); /* pixel a */ v[1] = _mm_set1_epi16((k6 >> 24) & 0xff); /* pixel b */ v[2] = _mm_set1_epi16((k6 >> 32) & 0xff); /* pixel c */ v[3] = _mm_set1_epi16((k6 >> 40) & 0xff); /* pixel d */ // stage 1: c0 for a,b: (0,1) -> (1,4), c1 for c,d: (0,3) -> (1,6) c0 = _mm_set_epi32((k0 >> 8) & 0xff00ff, (k0 >> 16) & 0xff00ff, (k1 >> 8) & 0xff00ff, (k1 >> 16) & 0xff00ff); c1 = _mm_set_epi32((k0 >> 24) & 0xff00ff, (k0 >> 32) & 0xff00ff, (k1 >> 24) & 0xff00ff, (k1 >> 32) & 0xff00ff); t[0] = _mm_sub_epi16(_mm_max_epu8(c0, v[0]), _mm_min_epu8(c0, v[0])); t[1] = _mm_sub_epi16(_mm_max_epu8(c0, v[1]), _mm_min_epu8(c0, v[1])); t[2] = _mm_sub_epi16(_mm_max_epu8(c1, v[2]), _mm_min_epu8(c1, v[2])); t[3] = _mm_sub_epi16(_mm_max_epu8(c1, v[3]), _mm_min_epu8(c1, v[3])); e[0] = _mm_subs_epu16(lvl, t[0]); e[1] = _mm_subs_epu16(lvl, t[1]); e[2] = _mm_subs_epu16(lvl, t[2]); e[3] = _mm_subs_epu16(lvl, t[3]); a[0] = _mm_madd_epi16(e[0], c0); a[1] = _mm_madd_epi16(e[1], c0); a[2] = _mm_madd_epi16(e[2], c1); a[3] = _mm_madd_epi16(e[3], c1); // stage 2: c0 for a,b: (3,1) -> (4,4), c1 for c,d: (3,3) -> (4,6) c0 = _mm_set_epi32((k2 >> 8) & 0xff00ff, (k2 >> 16) & 0xff00ff, (k3 >> 8) & 0xff00ff, (k3 >> 16) & 0xff00ff); c1 = _mm_set_epi32((k2 >> 24) & 0xff00ff, (k2 >> 32) & 0xff00ff, (k3 >> 24) & 0xff00ff, (k3 >> 32) & 0xff00ff); t[0] = _mm_sub_epi16(_mm_max_epu8(c0, v[0]), _mm_min_epu8(c0, v[0])); t[1] = _mm_sub_epi16(_mm_max_epu8(c0, v[1]), _mm_min_epu8(c0, v[1])); t[2] = _mm_sub_epi16(_mm_max_epu8(c1, v[2]), _mm_min_epu8(c1, v[2])); t[3] = _mm_sub_epi16(_mm_max_epu8(c1, v[3]), _mm_min_epu8(c1, v[3])); t[0] = _mm_subs_epu16(lvl, t[0]); t[1] = _mm_subs_epu16(lvl, t[1]); t[2] = _mm_subs_epu16(lvl, t[2]); t[3] = _mm_subs_epu16(lvl, t[3]); e[0] = _mm_add_epi16(t[0], e[0]); e[1] = _mm_add_epi16(t[1], e[1]); e[2] = _mm_add_epi16(t[2], e[2]); e[3] = _mm_add_epi16(t[3], e[3]); a[0] = _mm_add_epi32(_mm_madd_epi16(t[0], c0), a[0]); a[1] = _mm_add_epi32(_mm_madd_epi16(t[1], c0), a[1]); a[2] = _mm_add_epi32(_mm_madd_epi16(t[2], c1), a[2]); a[3] = _mm_add_epi32(_mm_madd_epi16(t[3], c1), a[3]); // stage 3: // pixel a: (0,0) -> (4,0), (2,1), (2,3), (2,4) c0 = _mm_set_epi32(((k0 & 0xff) << 16) | (k1 & 0xff), ((k2 & 0xff) << 16) | (k3 & 0xff), (k6 >> 8) & 0xff00ff, (k6 & 0xff) | ((k6 >> 16) & 0xff0000)); t[0] = _mm_sub_epi16(_mm_max_epu8(c0, v[0]), _mm_min_epu8(c0, v[0])); t[0] = _mm_subs_epu16(lvl, t[0]); e[0] = _mm_add_epi16(t[0], e[0]); a[0] = _mm_add_epi32(_mm_madd_epi16(t[0], c0), a[0]); // pixel c: (0,2) -> (4,2), (2,3), (2,5), (2,6) c1 = _mm_set_epi32((k0 & 0xff0000) | ((k1 >> 16) & 0xff), (k2 & 0xff0000) | ((k3 >> 16) & 0xff), (k6 >> 24) & 0xff00ff, ((k6 >> 16) & 0xff) | ((k6 >> 32) & 0xff0000)); t[2] = _mm_sub_epi16(_mm_max_epu8(c1, v[2]), _mm_min_epu8(c1, v[2])); t[2] = _mm_subs_epu16(lvl, t[2]); e[2] = _mm_add_epi16(t[2], e[2]); a[2] = _mm_add_epi32(_mm_madd_epi16(t[2], c1), a[2]); // pixel b: (0,5) -> (4,5), (2,1), (2,2), (2,4), (2,5) c0 = _mm_set_epi32(((k0 >> 24) & 0xff0000) | ((k1 >> 40) & 0xff), ((k2 >> 24) & 0xff0000) | ((k3 >> 40) & 0xff), (k6 >> 16) & 0xff00ff, ((k6 >> 8) & 0xff) | ((k6 >> 24) & 0xff0000)); t[1] = _mm_sub_epi16(_mm_max_epu8(c0, v[1]), _mm_min_epu8(c0, v[1])); t[1] = _mm_subs_epu16(lvl, t[1]); e[1] = _mm_add_epi16(t[1], e[1]); a[1] = _mm_add_epi32(_mm_madd_epi16(t[1], c0), a[1]); // pixel d: (0,7) -> (4,7), (2,3), (2,4), (2,6), (2,7) c1 = _mm_set_epi32(((k0 >> 40) & 0xff0000) | (k1 >> 56), ((k2 >> 40) & 0xff0000) | (k3 >> 56), (k6 >> 32) & 0xff00ff, ((k6 >> 24) & 0xff) | ((k6 >> 40) & 0xff0000)); t[3] = _mm_sub_epi16(_mm_max_epu8(c1, v[3]), _mm_min_epu8(c1, v[3])); t[3] = _mm_subs_epu16(lvl, t[3]); e[3] = _mm_add_epi16(t[3], e[3]); a[3] = _mm_add_epi32(_mm_madd_epi16(t[3], c1), a[3]); /* add them all together (a loop j=0 to 4 slows things down with gcc 4.4.4) */ uint32_t tmp; #if defined(__SSE3__) int j; __m128 f0, f1, f2, flvl; __m128i zero, vv; flvl = _mm_set1_ps((float)level); zero = _mm_setzero_si128(); vv = _mm_set_epi32((k6 >> 40) & 0xff, (k6 >> 32) & 0xff, (k6 >> 24) & 0xff, (k6 >> 16) & 0xff); f0 = _mm_hadd_ps(_mm_cvtepi32_ps(a[0]), _mm_cvtepi32_ps(a[1])); f1 = _mm_hadd_ps(_mm_cvtepi32_ps(a[2]), _mm_cvtepi32_ps(a[3])); f0 = _mm_hadd_ps(f0, f1); f0 = _mm_add_ps(f0, _mm_mul_ps(flvl, _mm_cvtepi32_ps(vv))); # ifdef OLD_ROUNDING /* avg *= 2 */ f0 = _mm_mul_ps(f0, _mm_set1_ps(2.0f)); # endif for (j=0; j<4; j++) e[j] = _mm_unpacklo_epi16(_mm_add_epi16(e[j], _mm_srli_si128(e[j], 8)), zero); f1 = _mm_hadd_ps(_mm_cvtepi32_ps(e[0]), _mm_cvtepi32_ps(e[1])); f2 = _mm_hadd_ps(_mm_cvtepi32_ps(e[2]), _mm_cvtepi32_ps(e[3])); f1 = _mm_hadd_ps(f1, f2); f1 = _mm_add_ps(f1, flvl); f0 = _mm_div_ps(f0, f1); # ifdef OLD_ROUNDING /* r = (r+1) / 2 */ vv = _mm_cvttps_epi32(f0); vv = _mm_srli_epi32(_mm_add_epi32(vv, _mm_set1_epi32(1)), 1); # else vv = _mm_cvtps_epi32(f0); # endif vv = _mm_packus_epi16(_mm_packs_epi32(vv, zero), zero); tmp = _mm_cvtsi128_si32(vv); #else // p[0] e[0] = _mm_add_epi16(e[0], _mm_srli_si128(e[0], 8)); /* 8 words */ e[0] = _mm_add_epi16(e[0], _mm_srli_si128(e[0], 4)); e[0] = _mm_add_epi16(e[0], _mm_srli_si128(e[0], 2)); cnt = level + (_mm_cvtsi128_si32(e[0]) & 0xffff); a[0] = _mm_add_epi32(a[0], _mm_srli_si128(a[0], 8)); /* 4 dwords */ a[0] = _mm_add_epi32(a[0], _mm_srli_si128(a[0], 4)); avg = p[0] * level * 2 + (_mm_cvtsi128_si32(a[0]) << 1); tmp = ((avg/cnt) + 1) / 2; // p[1] e[1] = _mm_add_epi16(e[1], _mm_srli_si128(e[1], 8)); /* 8 words */ e[1] = _mm_add_epi16(e[1], _mm_srli_si128(e[1], 4)); e[1] = _mm_add_epi16(e[1], _mm_srli_si128(e[1], 2)); cnt = level + (_mm_cvtsi128_si32(e[1]) & 0xffff); a[1] = _mm_add_epi32(a[1], _mm_srli_si128(a[1], 8)); /* 4 dwords */ a[1] = _mm_add_epi32(a[1], _mm_srli_si128(a[1], 4)); avg = p[1] * level * 2 + (_mm_cvtsi128_si32(a[1]) << 1); tmp |= (((avg/cnt) + 1) / 2) << 8; // p[2] e[2] = _mm_add_epi16(e[2], _mm_srli_si128(e[2], 8)); /* 8 words */ e[2] = _mm_add_epi16(e[2], _mm_srli_si128(e[2], 4)); e[2] = _mm_add_epi16(e[2], _mm_srli_si128(e[2], 2)); cnt = level + (_mm_cvtsi128_si32(e[2]) & 0xffff); a[2] = _mm_add_epi32(a[2], _mm_srli_si128(a[2], 8)); /* 4 dwords */ a[2] = _mm_add_epi32(a[2], _mm_srli_si128(a[2], 4)); avg = p[2] * level * 2 + (_mm_cvtsi128_si32(a[2]) << 1); tmp |= (((avg/cnt) + 1) / 2) << 16; // p[3] e[3] = _mm_add_epi16(e[3], _mm_srli_si128(e[3], 8)); /* 8 words */ e[3] = _mm_add_epi16(e[3], _mm_srli_si128(e[3], 4)); e[3] = _mm_add_epi16(e[3], _mm_srli_si128(e[3], 2)); cnt = level + (_mm_cvtsi128_si32(e[3]) & 0xffff); a[3] = _mm_add_epi32(a[3], _mm_srli_si128(a[3], 8)); /* 4 dwords */ a[3] = _mm_add_epi32(a[3], _mm_srli_si128(a[3], 4)); avg = p[3] * level * 2 + (_mm_cvtsi128_si32(a[3]) << 1); tmp |= (((avg/cnt) + 1) / 2) << 24; #endif *(uint32_t *)d = tmp; d += 4; p += 4; } _mm_empty(); memcpy(plane,scratchplane2,w*h); } #endif void filter_plane_median_p ( uint8_t * plane, int w, int h, int level) { int i; int min; int max; int avg; int cnt; int c; int e; uint8_t * p; uint8_t * d; if(level==0) return; p = plane; d = scratchplane1; // remove strong outliers from the image. An outlier is a pixel which lies outside // of max-thres and min+thres of the surrounding pixels. This should not cause blurring // and it should leave an evenly spread noise-floor to the image. for(i=0;i<=(w*h);i++) { // reset min/max-filter min=255; max=0; // check every remaining position arround the reference-pixel for being min/max... min=(min>*(p-w-1))? *(p-w-1):min; max=(max<*(p-w-1))? *(p-w-1):max; min=(min>*(p-w+0))? *(p-w+0):min; max=(max<*(p-w+0))? *(p-w+0):max; min=(min>*(p-w+1))? *(p-w+1):min; max=(max<*(p-w+1))? *(p-w+1):max; min=(min>*(p -1))? *(p -1):min; max=(max<*(p -1))? *(p -1):max; min=(min>*(p +1))? *(p +1):min; max=(max<*(p +1))? *(p +1):max; min=(min>*(p+w-1))? *(p+w-1):min; max=(max<*(p+w-1))? *(p+w-1):max; min=(min>*(p+w+0))? *(p+w+0):min; max=(max<*(p+w+0))? *(p+w+0):max; min=(min>*(p+w+1))? *(p+w+1):min; max=(max<*(p+w+1))? *(p+w+1):max; if( *(p)<(min) ) { *(d)=min; } else if( *(p)>(max) ) { *(d)=max; } else { *(d)=*(p); } d++; p++; } // in the second stage we try to average similar spatial pixels, only. This, like // a median, should also not reduce sharpness but flatten the noisefloor. This // part is quite similar to what 2dclean/yuvmedianfilter do. But because of the // different weights given to the pixels it is less aggressive... p = scratchplane1; d = scratchplane2; // this filter needs values outside of the imageplane, so we just copy the first line // and the last line into the out-of-range area... memcpy ( p-w , p, w ); memcpy ( p-w*2, p, w ); memcpy ( p+(w*h) , p+(w*h)-w, w ); memcpy ( p+(w*h)+w, p+(w*h)-w, w ); for(i=0;i<=(w*h);i++) { avg=*(p)*level*2; cnt=level; c = *(p-w*2-2); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p-w*2-1); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p-w*2); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p-w*2+1); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p-w*2+2); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p-w*1-2); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p-w*1-1); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p-w*1); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p-w*1+1); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p-w*1+2); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p-2); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p-1); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p+1); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p+2); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p+w*1-2); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p+w*1-1); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p+w*1); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p+w*1+1); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p+w*1+2); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p+w*2-2); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p+w*2-1); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p+w*2); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p+w*2+1); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; c = *(p+w*2+2); e = abs(c-*(p)); e = ((level-e)<0)? 0:level-e; avg += e*c*2; cnt += e; *(d)=(((avg/cnt)+1)/2); d++; p++; } memcpy(plane,scratchplane2,w*h); } /*********************************************************** * Main Loop * ***********************************************************/ static void init_accel() { filter_plane_median = filter_plane_median_p; temporal_filter_planes = temporal_filter_planes_p; uint32_t tmp; #if defined(__SSE2__) int d = 0; /* __asm__ volatile("cpuid" : "=d"(d) : "a"(1) : "ebx", "ecx"); */ __asm__ volatile("movl %%ebx, %1; cpuid; movl %1, %%ebx" : "=d"(d), "=&g"(tmp) : "a"(1) : "ecx"); if ((d & (1 << 26))) { mjpeg_info("SETTING SSE2 for standard Temporal-Noise-Filter"); temporal_filter_planes = temporal_filter_planes_sse2; /*__asm__ volatile("cpuid" : "=d"(d) : "a"(0x80000001) : "ebx", "ecx");*/ __asm__ volatile("movl %%ebx, %1; cpuid; movl %1, %%ebx" : "=d"(d), "=&g"(tmp) : "a"(0x80000001) : "ecx"); if ((d & (1 << 29))) { /* x86_64 processor */ mjpeg_info("SETTING SSE2 for Median-Filter"); filter_plane_median = filter_plane_median_sse2; } } #endif } int main (int argc, char *argv[]) { int c; int fd_in = fileno(stdin); int fd_out = fileno(stdout); int err = 0; char *msg = NULL; y4m_ratio_t rx, ry; y4m_frame_info_t iframeinfo; y4m_stream_info_t istreaminfo; y4m_frame_info_t oframeinfo; y4m_stream_info_t ostreaminfo; mjpeg_info("yuvdenoise version %s", VERSION); while ((c = getopt (argc, argv, "qhvt:g:m:M:r:G:")) != -1) { switch (c) { case 'h': { mjpeg_info("... | yuvdenoise [OPTIONS] | ..."); mjpeg_info("Brief description of the accepted options:\n"); mjpeg_info("-g [Y=0...255],[U=0...255],[V=0...255]"); mjpeg_info(" This sets the parameters [Y,U,V] for the gauss-filter. 0 means no filtering,"); mjpeg_info(" which is the default, 255 is maximum gaussfiltering. Some camera manufacturers"); mjpeg_info(" think it's a good idea to sharpen the frames extremly. This however will raise"); mjpeg_info(" typical video-compression-artifacts (ringing, blocking, alias, etc...). If you"); mjpeg_info(" desire to have a video free of these, you can raise the gauss-filter-values"); mjpeg_info(" until your image is undesirable soft... (Short: setting decent values helps"); mjpeg_info(" both: the viewer and the encoder -- setting too high values is ugly.) This may"); mjpeg_info(" also help with extremly noisy images from a weak air-captured signal..."); mjpeg_info(" Unlike y4mspatialfilter this will not boost ringing artifacts.\n"); mjpeg_info("-m [0...255],[0...255],[0...255]"); mjpeg_info(" Spatial-Pre-Filter. This one helps with really noisy signals. You should not"); mjpeg_info(" use this with moderate to low noise material. Used with care it helps the tem-"); mjpeg_info(" poral-filter a lot. Misuse will lead to rather dull images (like an overly median-filtered image..."); mjpeg_info("-t [0...255],[0...255],[0...255]"); mjpeg_info(" Temporal-Noise-Filter. This one dramaticaly reduces noise without loosing sharpness. If set too high, however, it may introduce visable ghost-images or smear. "); mjpeg_info("-M [0...255],[0...255],[0...255]"); mjpeg_info(" Spatial-Post-Filter. This one removes spatial noise left by the temporal-filter."); mjpeg_info(" Used with care it can dramaticaly lower the bitrate. Using it with to high settings will lead to the same artifacts as the spatial-pre-filter produces."); mjpeg_info("-G [0...255],[0...255],[0...255]"); mjpeg_info(" Set -m,-t,-M values at once. -t is boosted by a factor of 2. Useful if you do"); mjpeg_info(" not want to tweak all the values by hand... which is better."); mjpeg_info("-r [0...255],[0...255],[0...255]"); mjpeg_info(" Add some static masking noise. Might be used as an effect, too... *g*"); mjpeg_info("-q HighQuality-Mode. Warning: On almost any machine this is dead slow..."); exit (0); break; } case 'v': { verbose = 1; break; } case 'q': { hq_mode = 1; break; } case 't': { sscanf (optarg, "%i,%i,%i", &temp_Y_thres, &temp_U_thres, &temp_V_thres); break; } case 'g': { sscanf (optarg, "%i,%i,%i", &gauss_Y, &gauss_U, &gauss_V); break; } case 'm': { sscanf (optarg, "%i,%i,%i", &med_pre_Y_thres, &med_pre_U_thres, &med_pre_V_thres); break; } case 'M': { sscanf (optarg, "%i,%i,%i", &med_post_Y_thres, &med_post_U_thres, &med_post_V_thres); break; } case 'G': { sscanf (optarg, "%i,%i,%i", &med_pre_Y_thres, &med_pre_U_thres, &med_pre_V_thres); med_post_Y_thres = temp_Y_thres = med_pre_Y_thres; med_post_U_thres = temp_U_thres = med_pre_U_thres; med_post_V_thres = temp_V_thres = med_pre_V_thres; temp_Y_thres *= 2; temp_U_thres *= 2; temp_V_thres *= 2; break; } case 'r': { sscanf (optarg, "%i,%i,%i", &renoise_Y, &renoise_U, &renoise_V); break; } case '?': default: exit (1); } } mjpeg_info("Using the following thresholds/settings:"); mjpeg_info("Gauss-Pre-Filter [Y,U,V] : [%i,%i,%i]", gauss_Y, gauss_U, gauss_V); mjpeg_info("Median-Pre-Filter [Y,U,V] : [%i,%i,%i]", med_pre_Y_thres, med_pre_U_thres, med_pre_V_thres); mjpeg_info("Temporal-Noise-Filter [Y,U,V] : [%i,%i,%i]", temp_Y_thres, temp_U_thres, temp_V_thres); mjpeg_info("Median-Post-Filter [Y,U,V] : [%i,%i,%i]", med_post_Y_thres, med_post_U_thres, med_post_V_thres); mjpeg_info("Renoise [Y,U,V] : [%i,%i,%i]", renoise_Y, renoise_U, renoise_V); mjpeg_info("HQ-Mode : %s", (hq_mode==0? "off":"on")); /* initialize stream-information */ y4m_accept_extensions (1); y4m_init_stream_info (&istreaminfo); y4m_init_frame_info (&iframeinfo); y4m_init_stream_info (&ostreaminfo); y4m_init_frame_info (&oframeinfo); /* open input stream */ if ((err = y4m_read_stream_header (fd_in, &istreaminfo)) != Y4M_OK) mjpeg_error_exit1("Couldn't read YUV4MPEG header: %s!", y4m_strerr (err)); /* get format information */ width = y4m_si_get_width (&istreaminfo); height = y4m_si_get_height (&istreaminfo); input_chroma_subsampling = y4m_si_get_chroma (&istreaminfo); input_interlaced = y4m_si_get_interlace (&istreaminfo); mjpeg_info("Y4M-Stream %ix%i(%s)", width, height, y4m_chroma_description (input_chroma_subsampling)); lwidth = width; lheight = height; // Setup the denoiser to use the appropriate chroma processing if (input_chroma_subsampling == Y4M_CHROMA_420JPEG || input_chroma_subsampling == Y4M_CHROMA_420MPEG2 || input_chroma_subsampling == Y4M_CHROMA_420PALDV) msg = "Processing Mode : 4:2:0"; else if (input_chroma_subsampling == Y4M_CHROMA_411) msg = "Processing Mode : 4:1:1"; else if (input_chroma_subsampling == Y4M_CHROMA_422) msg = "Processing Mode : 4:2:2"; else if (input_chroma_subsampling == Y4M_CHROMA_444) msg = "Processing Mode : 4:4:4"; else mjpeg_error_exit1 (" ### Unsupported Y4M Chroma sampling ### "); rx = y4m_chroma_ss_x_ratio (input_chroma_subsampling); ry = y4m_chroma_ss_y_ratio (input_chroma_subsampling); cwidth = width / rx.d; cheight = height / ry.d; mjpeg_info("%s %s", msg, (input_interlaced == Y4M_ILACE_NONE) ? "progressive" : "interlaced"); mjpeg_info("Luma-Plane : %ix%i pixels", lwidth, lheight); mjpeg_info("Chroma-Plane : %ix%i pixels", cwidth, cheight); if (input_interlaced != Y4M_ILACE_NONE) { // process the fields as images side by side lwidth *= 2; cwidth *= 2; lheight /= 2; cheight /= 2; } y4m_si_set_interlace (&ostreaminfo, y4m_si_get_interlace (&istreaminfo)); y4m_si_set_chroma (&ostreaminfo, y4m_si_get_chroma (&istreaminfo)); y4m_si_set_width (&ostreaminfo, width); y4m_si_set_height (&ostreaminfo, height); y4m_si_set_framerate (&ostreaminfo, y4m_si_get_framerate (&istreaminfo)); y4m_si_set_sampleaspect (&ostreaminfo, y4m_si_get_sampleaspect (&istreaminfo)); /* write the outstream header */ y4m_write_stream_header (fd_out, &ostreaminfo); /* now allocate the needed buffers */ { /* calculate the memory offset needed to allow the processing * functions to overshot. The biggest overshot is needed for the * MC-functions, so we'll use 8*width... */ buff_offset = lwidth * 8; buff_size = buff_offset * 2 + lwidth * lheight; frame1[0] = buff_offset + (uint8_t *) malloc (buff_size); frame1[1] = buff_offset + (uint8_t *) malloc (buff_size); frame1[2] = buff_offset + (uint8_t *) malloc (buff_size); frame2[0] = buff_offset + (uint8_t *) malloc (buff_size); frame2[1] = buff_offset + (uint8_t *) malloc (buff_size); frame2[2] = buff_offset + (uint8_t *) malloc (buff_size); frame3[0] = buff_offset + (uint8_t *) malloc (buff_size); frame3[1] = buff_offset + (uint8_t *) malloc (buff_size); frame3[2] = buff_offset + (uint8_t *) malloc (buff_size); frame4[0] = buff_offset + (uint8_t *) malloc (buff_size); frame4[1] = buff_offset + (uint8_t *) malloc (buff_size); frame4[2] = buff_offset + (uint8_t *) malloc (buff_size); frame5[0] = buff_offset + (uint8_t *) malloc (buff_size); frame5[1] = buff_offset + (uint8_t *) malloc (buff_size); frame5[2] = buff_offset + (uint8_t *) malloc (buff_size); frame6[0] = buff_offset + (uint8_t *) malloc (buff_size); frame6[1] = buff_offset + (uint8_t *) malloc (buff_size); frame6[2] = buff_offset + (uint8_t *) malloc (buff_size); frame7[0] = buff_offset + (uint8_t *) malloc (buff_size); frame7[1] = buff_offset + (uint8_t *) malloc (buff_size); frame7[2] = buff_offset + (uint8_t *) malloc (buff_size); outframe[0] = buff_offset + (uint8_t *) malloc (buff_size); outframe[1] = buff_offset + (uint8_t *) malloc (buff_size); outframe[2] = buff_offset + (uint8_t *) malloc (buff_size); scratchplane1 = buff_offset + (uint8_t *) malloc (buff_size); scratchplane2 = buff_offset + (uint8_t *) malloc (buff_size); mjpeg_info("Buffers allocated."); } /* initialize motion_library */ init_motion_search (); init_accel(); /* read every frame until the end of the input stream and process it */ while (Y4M_OK == (err = y4m_read_frame (fd_in, &istreaminfo, &iframeinfo, frame1))) { static uint32_t frame_nr = 0; uint8_t *temp[3]; frame_nr++; gauss_filter_plane (frame1[0], lwidth, lheight, gauss_Y); gauss_filter_plane (frame1[1], cwidth, cheight, gauss_U); gauss_filter_plane (frame1[2], cwidth, cheight, gauss_V); filter_plane_median (frame1[0], lwidth, lheight, med_pre_Y_thres); filter_plane_median (frame1[1], cwidth, cheight, med_pre_U_thres); filter_plane_median (frame1[2], cwidth, cheight, med_pre_V_thres); if(hq_mode==1) { temporal_filter_planes_MC (0, lwidth, lheight, temp_Y_thres); temporal_filter_planes_MC (1, cwidth, cheight, temp_U_thres); temporal_filter_planes_MC (2, cwidth, cheight, temp_V_thres); } else { temporal_filter_planes (0, lwidth, lheight, temp_Y_thres); temporal_filter_planes (1, cwidth, cheight, temp_U_thres); temporal_filter_planes (2, cwidth, cheight, temp_V_thres); } filter_plane_median (outframe[0], lwidth, lheight, med_post_Y_thres); filter_plane_median (outframe[1], cwidth, cheight, med_post_U_thres); filter_plane_median (outframe[2], cwidth, cheight, med_post_V_thres); renoise (outframe[0], lwidth, lheight, renoise_Y ); renoise (outframe[1], cwidth, cheight, renoise_U ); renoise (outframe[2], cwidth, cheight, renoise_V ); if (frame_nr >= 4) y4m_write_frame (fd_out, &ostreaminfo, &oframeinfo, outframe); // rotate buffer pointers to rotate input-buffers temp[0] = frame7[0]; temp[1] = frame7[1]; temp[2] = frame7[2]; frame7[0] = frame6[0]; frame7[1] = frame6[1]; frame7[2] = frame6[2]; frame6[0] = frame5[0]; frame6[1] = frame5[1]; frame6[2] = frame5[2]; frame5[0] = frame4[0]; frame5[1] = frame4[1]; frame5[2] = frame4[2]; frame4[0] = frame3[0]; frame4[1] = frame3[1]; frame4[2] = frame3[2]; frame3[0] = frame2[0]; frame3[1] = frame2[1]; frame3[2] = frame2[2]; frame2[0] = frame1[0]; frame2[1] = frame1[1]; frame2[2] = frame1[2]; frame1[0] = temp[0]; frame1[1] = temp[1]; frame1[2] = temp[2]; } // write out the left frames... y4m_write_frame (fd_out, &ostreaminfo, &oframeinfo, frame4); y4m_write_frame (fd_out, &ostreaminfo, &oframeinfo, frame3); y4m_write_frame (fd_out, &ostreaminfo, &oframeinfo, frame2); y4m_write_frame (fd_out, &ostreaminfo, &oframeinfo, frame1); /* free allocated buffers */ { free (frame1[0] - buff_offset); free (frame1[1] - buff_offset); free (frame1[2] - buff_offset); free (frame2[0] - buff_offset); free (frame2[1] - buff_offset); free (frame2[2] - buff_offset); free (frame3[0] - buff_offset); free (frame3[1] - buff_offset); free (frame3[2] - buff_offset); free (frame4[0] - buff_offset); free (frame4[1] - buff_offset); free (frame4[2] - buff_offset); free (frame5[0] - buff_offset); free (frame5[1] - buff_offset); free (frame5[2] - buff_offset); free (frame6[0] - buff_offset); free (frame6[1] - buff_offset); free (frame6[2] - buff_offset); free (frame7[0] - buff_offset); free (frame7[1] - buff_offset); free (frame7[2] - buff_offset); free (outframe[0] - buff_offset); free (outframe[1] - buff_offset); free (outframe[2] - buff_offset); free (scratchplane1 - buff_offset); free (scratchplane2 - buff_offset); mjpeg_info("Buffers freed."); } /* did stream end unexpectedly ? */ if (err != Y4M_ERR_EOF) mjpeg_error_exit1 ("%s", y4m_strerr (err)); /* Exit gently */ return (0); } mjpegtools-2.1.0/aclocal.m40000644000175000017500000126425212217306403016063 0ustar glowwormglowworm# generated automatically by aclocal 1.12.1 -*- Autoconf -*- # Copyright (C) 1996-2012 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) # serial 57 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_CC_BASENAME(CC) # ------------------- # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. m4_defun([_LT_CC_BASENAME], [for cc_temp in $1""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from `configure', and `config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # `config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain="$ac_aux_dir/ltmain.sh" ])# _LT_PROG_LTMAIN # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the `libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to `config.status' so that its # declaration there will have the same value as in `configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags="_LT_TAGS"dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the `libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into `config.status', and then the shell code to quote escape them in # for loops in `config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # `#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test $lt_write_fail = 0 && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ \`$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test $[#] != 0 do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try \`$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try \`$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test "$silent" = yes && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # _LT_COPYING _LT_LIBTOOL_TAGS # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) _LT_PROG_REPLACE_SHELLFNS mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS="$save_LDFLAGS" ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[[012]]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test "$lt_cv_ld_force_load" = "yes"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" m4_if([$1], [CXX], [ if test "$lt_cv_apple_cc_single_mod" != "yes"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script which will find a shell with a builtin # printf (which we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case "$ECHO" in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [ --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified).], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([${with_sysroot}]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and in which our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD="${LD-ld}_sol2" fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test x"[$]$2" = xyes; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" ]) if test x"[$]$2" = xyes; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links="nottested" if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", [Define to the sub-directory in which libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existent directories. if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([], [sys_lib_dlsearch_path_spec], [2], [Run-time system search path for libraries]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program which can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program which can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi]) if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64 which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global defined # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS="$save_LDFLAGS"]) if test "$lt_cv_irix_exported_symbol" = yes; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting ${shlibpath_var} if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC="$lt_save_CC" ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GXX" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared # libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ func_to_tool_file "$lt_outputfile"~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; gnu*) ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd2*) # C++ shared libraries are fairly broken _LT_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(GCC, $1)="$GXX" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test "$_lt_caught_CXX_error" != yes AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case ${prev}${p} in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" || test $p = "-R"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test "$pre_test_object_deps_done" = no; then case ${prev} in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)="${prev}${p}" else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)="$p" else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)="$p" else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test "X$F77" = "Xno"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_F77" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$G77" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" CFLAGS="$lt_save_CFLAGS" fi # test "$_lt_disable_F77" != yes AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test "X$FC" = "Xno"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_FC" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test "$_lt_disable_FC" != yes AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [AC_MSG_CHECKING([whether the shell understands some XSI constructs]) # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes AC_MSG_RESULT([$xsi_shell]) _LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) AC_MSG_CHECKING([whether the shell understands "+="]) lt_shell_append=no ( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes AC_MSG_RESULT([$lt_shell_append]) _LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) # ------------------------------------------------------ # In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and # '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. m4_defun([_LT_PROG_FUNCTION_REPLACE], [dnl { sed -e '/^$1 ()$/,/^} # $1 /c\ $1 ()\ {\ m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) } # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: ]) # _LT_PROG_REPLACE_SHELLFNS # ------------------------- # Replace existing portable implementations of several shell functions with # equivalent extended shell implementations where those features are available.. m4_defun([_LT_PROG_REPLACE_SHELLFNS], [if test x"$xsi_shell" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"}]) _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl func_split_long_opt_name=${1%%=*} func_split_long_opt_arg=${1#*=}]) _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) fi if test x"$lt_shell_append" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl func_quote_for_eval "${2}" dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) fi ]) # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine which file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS # Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, # Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 7 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option `$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl `shared' nor `disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) ]) ])# _LT_SET_OPTIONS # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the `shared' and # `disable-shared' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the `static' and # `disable-static' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the `fast-install' # and `disable-fast-install' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the `pic-only' and `no-pic' # LT_INIT options. # MODE is either `yes' or `no'. If omitted, it defaults to `both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS="$lt_save_ifs" ;; esac], [pic_mode=default]) test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59 which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) # ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 3337 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.2]) m4_define([LT_PACKAGE_REVISION], [1.3337]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.2' macro_revision='1.3337' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 1 (pkg-config-0.24) # # Copyright © 2004 Scott James Remnant . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # PKG_PROG_PKG_CONFIG([MIN-VERSION]) # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])# PKG_PROG_PKG_CONFIG # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # Check to see whether a particular set of modules exists. Similar # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) # only at the first occurence in configure.ac, so if the first place # it's called might be skipped (such as if it is within an "if", you # have to call PKG_CHECK_EXISTS manually # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])# _PKG_CONFIG # _PKG_SHORT_ERRORS_SUPPORTED # ----------------------------- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])# _PKG_SHORT_ERRORS_SUPPORTED # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], # [ACTION-IF-NOT-FOUND]) # # # Note that if there is a possibility the first call to # PKG_CHECK_MODULES might not happen, you should be sure to include an # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac # # # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])# PKG_CHECK_MODULES # PKG_INSTALLDIR(DIRECTORY) # ------------------------- # Substitutes the variable pkgconfigdir as the location where a module # should install pkg-config .pc files. By default the directory is # $libdir/pkgconfig, but the default can be changed by passing # DIRECTORY. The user can override through the --with-pkgconfigdir # parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ]) dnl PKG_INSTALLDIR # PKG_NOARCH_INSTALLDIR(DIRECTORY) # ------------------------- # Substitutes the variable noarch_pkgconfigdir as the location where a # module should install arch-independent pkg-config .pc files. By # default the directory is $datadir/pkgconfig, but the default can be # changed by passing DIRECTORY. The user can override through the # --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ]) dnl PKG_NOARCH_INSTALLDIR # Copyright (C) 2002-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 8 # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.12' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.12.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.12.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # Figure out how to run the assembler. -*- Autoconf -*- # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 5 # AM_PROG_AS # ---------- AC_DEFUN([AM_PROG_AS], [# By default we simply use the C compiler to build assembly code. AC_REQUIRE([AC_PROG_CC]) test "${CCAS+set}" = set || CCAS=$CC test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS AC_ARG_VAR([CCAS], [assembler compiler command (defaults to CC)]) AC_ARG_VAR([CCASFLAGS], [assembler compiler flags (defaults to CFLAGS)]) _AM_IF_OPTION([no-dependencies],, [_AM_DEPENDENCIES([CCAS])])dnl ]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 10 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 17 # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 6 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each '.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 19 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.62])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated. For more info, see: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl dnl Support for Objective C++ was only introduced in Autoconf 2.65, dnl but we still cater to Autoconf 2.62. m4_ifdef([AC_PROG_OBJCXX], [AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])])dnl ]) _AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl dnl The 'parallel-tests' driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 8 # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering # Copyright (C) 1996-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 7 # AM_MAINTAINER_MODE([DEFAULT-MODE]) # ---------------------------------- # Control maintainer-specific portions of Makefiles. # Default is to disable them, unless 'enable' is passed literally. # For symmetry, 'disable' may be passed as well. Anyway, the user # can override the default with the --enable/--disable switch. AC_DEFUN([AM_MAINTAINER_MODE], [m4_case(m4_default([$1], [disable]), [enable], [m4_define([am_maintainer_other], [disable])], [disable], [m4_define([am_maintainer_other], [enable])], [m4_define([am_maintainer_other], [enable]) m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) dnl maintainer-mode's default is 'disable' unless 'enable' is passed AC_ARG_ENABLE([maintainer-mode], [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], am_maintainer_other[ make rules and dependencies not useful (and sometimes confusing) to the casual installer])], [USE_MAINTAINER_MODE=$enableval], [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) AC_MSG_RESULT([$USE_MAINTAINER_MODE]) AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) MAINT=$MAINTAINER_MODE_TRUE AC_SUBST([MAINT])dnl ] ) AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 5 # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Copyright (C) 1999-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 6 # AM_PROG_CC_C_O # -------------- # Like AC_PROG_CC_C_O, but changed for automake. AC_DEFUN([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC_C_O])dnl AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o if test "$am_t" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi dnl Make sure AC_PROG_CC is never called again, or it will override our dnl setting of CC. m4_define([AC_PROG_CC], [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 7 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 6 # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 9 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' _am_tools=${am_cv_prog_tar_$1-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of '-'. for _am_tool in $_am_tools do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([acinclude.m4]) mjpegtools-2.1.0/README.DV0000644000175000017500000001134707461641370015417 0ustar glowwormglowworm MJPEGtools v1.6.0 and onwards, when compiled with libdv, support DV video streams, stored as "Type 2 AVI" files. Building and installation (if you want to compile from source): 1. Download and install libdv from libdv.sourceforge.net. (v0.9 and up are known to work.) 2. Download and unpack the v1.6.0 source tarball, or get a clean CVS checkout of the development branch of mjpeg_play. 3. configure && make && make install in mjpeg_play This should automatically detect libdv if it is installed. Grabbing DV input: 0. You should already have a DV camcorder and an IEEE-1394 board and everything set up for 1394 capture, otherwise have a look at: http://linux1394.sourceforge.net/ http://www.schirmacher.de/arne/dvgrab/ Two programs that I found very useful for resolving problems and controlling the camcorder through IEEE 1394 are: dvcont - http://www.spectsoft.com/idi/dvcont/ gscanbus - http://www.ivistar.de/0500opensource.php3?lang=en If your camcorder allows you to record either 12bit or 16bit audio you should make sure to set it to 16bit recording since that is the sound format expected by the MJPEGtools. Some camcorders have 12bit sound as the default factory setting, so check that *before* you start recording your videos. 1. Start replay on the camcorder. 2. Use dvgrab with the option "--format dv2" to capture the DV data in AVI 'Type 2' format. Only this format is supported by lav2yuv; capturing with the default '--format dv1' won't work. 3. If you want to preview and edit (simple cut and paste editing) the raw DV files you can use kino from: http://www.schirmacher.de/arne/kino/ . Make sure to set dv2 format for saving in the preferences. Using lav2yuv with DV: Simply follow all other documentation for "lav2yuv"; your Type 2 DV AVI file will be treated similarly to an MJPEG AVI file. For example: lav2yuv my-dv-file.avi | yuvplay * lav2yuv accepts DV AVI files directly or as parts of editlists. * Both PAL and NTSC streams are handled. * Sample aspect ratio is automatically detected. Interlacing is always set to bottom-field-first (because DV is always bottom-field-first). * You can extract the sound from the DV files using either "lav2wav" or "lavtrans -f w". Once extracted to a WAV file, you can encode it to MPEG Layer II audio with "mp2enc", which is capable of resampling the 48kHz stream to 44.1kHz. (Some hardware VCD and SVCD players will accept 48kHz audio, however this is non-standard.) ------------------------------------------------------------------------------ Additional Notes (of purely HISTORICAL value) 1. The recent version of lav2yuv can also read raw YUV data from quicktime files that were written in planar YUV 4:2:0 format. This is one of the output file formats offered by bcast2000 for rendering scenes. 2. This is a short description of the de-interlacing algorithm taken from the source file DI_TwoFrame.c from deinterlace.sourceforge.net. This algorithm is a combination of simpler algorithms found in Windows programs like flaskMPEG or AVIsynth. /////////////////////////////////////////////////////////////////////////////// // Deinterlace the latest field, attempting to weave wherever it won'tcause // visible artifacts. // // The data from the most recently captured field is always copied to theoverlay // verbatim. For the data from the previous field, the following algorithm is // applied to each pixel. // // We use the following notation for the top, middle, and bottom pixels // of concern: // // Field 1 | Field 2 | Field 3 | Field 4 | // | T0 | | T1 | scanline we copied in lastiteration // M0 | | M1 | | intermediate scanline fromalternate field // | B0 | | B1 | scanline we just copied // // We will weave M1 into the image if any of the following is true: // - M1 is similar to either B1 or T1. This indicates that no weave // artifacts would be visible. The SpatialTolerance setting controls // how far apart the luminances can be before pixels are considered // non-similar. // - T1 and B1 and M1 are old. In that case any weave artifact that // appears isn't due to fast motion, since it was there in the previous // frame too. By "old" I mean similar to their counterparts in the // previous frame; TemporalTolerance controls the maximum squared // luminance difference above which a pixel is considered "new". // /////////////////////////////////////////////////////////////////////////////// mjpegtools-2.1.0/yuvscaler/0000755000175000017500000000000012217306501016223 5ustar glowwormglowwormmjpegtools-2.1.0/yuvscaler/Makefile.am0000644000175000017500000000100011736012553020254 0ustar glowwormglowworm# Makefile for yuvscaler MAINTAINERCLEANFILES = Makefile.in AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/utils LIBMJPEGUTILS = $(top_builddir)/utils/libmjpegutils.la if HAVE_ALTIVEC LIBMJPEGUTILS += $(top_builddir)/mpeg2enc/libmpeg2encpp.la endif bin_PROGRAMS = \ yuvscaler noinst_HEADERS = \ yuvscaler.h EXTRA_DIST = yuvscaler_implementation.txt yuvscaler_CFLAGS=@PROGRAM_NOPIC@ yuvscaler_SOURCES = yuvscaler.c yuvscaler_resample.c yuvscaler_bicubic.c yuvscaler_LDADD = $(LIBMJPEGUTILS) $(LIBM_LIBS) mjpegtools-2.1.0/yuvscaler/yuvscaler_resample.c0000644000175000017500000010374110323630014022275 0ustar glowwormglowworm#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include "yuv4mpeg.h" #include "mjpeg_types.h" #include "yuvscaler.h" // From outide MAIN : global variables extern unsigned int input_width; extern unsigned int output_width; // Downscaling ratios extern unsigned int input_height_slice; extern unsigned int output_height_slice; extern unsigned int input_width_slice; extern unsigned int output_width_slice; extern int interlaced; extern unsigned int output_active_width; extern unsigned int output_active_height; extern int line_switching; extern unsigned int specific; extern unsigned int out_nb_col_slice, out_nb_line_slice; extern uint8_t *divide; // From inside MAIN function // ************************************************************************************* int average_coeff (unsigned int input_length, unsigned int output_length, unsigned int *coeff) { // This function calculates multiplicative coeeficients to average an input (vector of) length // input_length into an output (vector of) length output_length; // We sequentially store the number-of-non-zero-coefficients, followed by the coefficients // themselvesc, and that, output_length time int last_coeff = 0, remaining_coeff, still_to_go = 0, in, out, non_zero = 0, nb; unsigned int *non_zero_p = NULL; unsigned int *pointer; if ((output_length > input_length) || (input_length == 0) || (output_length == 0) || (coeff == NULL)) { mjpeg_error ("Function average_coeff : arguments are wrong"); mjpeg_error ("input length = %d, output length = %d, input = %p", input_length, output_length, coeff); exit (1); } #ifdef DEBUG mjpeg_debug ("Function average_coeff : input length = %d, output length = %d, input = %p", input_length, output_length, coeff); #endif pointer = coeff; if (output_length == 1) { *pointer = input_length; pointer++; for (in = 0; in < input_length; in++) { *pointer = 1; pointer++; } } else { for (in = 0; in < output_length; in++) { non_zero = 0; non_zero_p = pointer; pointer++; still_to_go = input_length; if (last_coeff > 0) { remaining_coeff = output_length - last_coeff; *pointer = remaining_coeff; pointer++; non_zero++; still_to_go -= remaining_coeff; } nb = (still_to_go / output_length); #ifdef DEBUG mjpeg_debug ("in=%d,nb=%d,stgo=%d ol=%d", in, nb, still_to_go, output_length); #endif for (out = 0; out < nb; out++) { *pointer = output_length; pointer++; } still_to_go -= nb * output_length; non_zero += nb; if ((last_coeff = still_to_go) != 0) { *pointer = last_coeff; #ifdef DEBUG mjpeg_debug ("non_zero=%d,last_coeff=%d", non_zero, last_coeff); #endif pointer++; // now pointer points onto the next number-of-non_zero-coefficients non_zero++; *non_zero_p = non_zero; } else { if (in != output_length - 1) { mjpeg_error ("There is a common divider between %d and %d\n This should not be the case", input_length, output_length); exit (1); } } } *non_zero_p = non_zero; if (still_to_go != 0) { mjpeg_error ("Function average_coeff : calculus doesn't stop right : %d", still_to_go); } } #ifdef DEBUG if (verbose == 2) { int i, j; for (i = 0; i < output_length; i++) { mjpeg_debug ("line=%d", i); non_zero = *coeff; coeff++; mjpeg_debug (" "); for (j = 0; j < non_zero; j++) { fprintf (stderr, "%d : %d ", j, *coeff); coeff++; } fprintf (stderr, "\n"); } } #endif return (0); } // ************************************************************************************* // ************************************************************************************* int average (uint8_t * input, uint8_t * output, unsigned int *height_coeff, unsigned int *width_coeff, unsigned int half) { // This function average an input matrix of name input and of size local_input_width*(local_out_nb_line_slice*input_height_slice) // into an output matrix of name output and of size local_output_width*(local_out_nb_line_slice+output_height_slice) // input and output images are interleaved // if half==1 => we are dealing with an U or V component => height and width are / 2 => for speed sake, we use >>half unsigned int local_input_width = input_width >> half; unsigned int local_output_width = output_width >> half; unsigned int local_out_nb_col_slice = out_nb_col_slice >> half; unsigned int local_out_nb_line_slice = out_nb_line_slice >> half; uint8_t *input_line_p[input_height_slice]; uint8_t *output_line_p[output_height_slice]; unsigned int *H_var, *W_var, *H, *W; uint8_t *u_c_p; int j, nb_H, nb_W, in_line, first_line, out_line; int out_col_slice, out_col; int out_line_slice; int current_line, last_line; unsigned long int value = 0; //Init mjpeg_debug ("Start of average"); //End of INIT if (interlaced == Y4M_ILACE_NONE) { mjpeg_debug ("Non-interlaced downscaling"); // output frames are not interlaced => averaging will generate output lines is growing order, // output_height_slice lines per output_height_slice lines. // More important is the following question : // is input frames CONTENT interlaced or not (input frames are then said progressives). If content is interlaced (odd lines corresponds to time t // and even lines to another time t+dt with dt=1/(2*frame_rate)), then input frames should be DEINTERLACED prior to averaging // So, if input frames are interlaced, we will suppose they are progressives // TO BE PROGRAMMED, cf. FlaskMPEG for (out_line_slice = 0; out_line_slice < local_out_nb_line_slice; out_line_slice++) { u_c_p = input + out_line_slice * input_height_slice * local_input_width; for (in_line = 0; in_line < input_height_slice; in_line++) { input_line_p[in_line] = u_c_p; u_c_p += local_input_width; } u_c_p = output + out_line_slice * output_height_slice * local_output_width; for (out_line = 0; out_line < output_height_slice; out_line++) { output_line_p[out_line] = u_c_p; u_c_p += local_output_width; } for (out_col_slice = 0; out_col_slice < local_out_nb_col_slice; out_col_slice++) { H = height_coeff; first_line = 0; for (out_line = 0; out_line < output_height_slice; out_line++) { nb_H = *H; W = width_coeff; for (out_col = 0; out_col < output_width_slice; out_col++) { H_var = H + 1; nb_W = *W; value = 0; last_line = first_line + nb_H; for (current_line = first_line; current_line < last_line; current_line++) { W_var = W + 1; // we average nb_W columns of input : we increment input_line_p[current_line] and W_var each time, except for the last value where // input_line_p[current_line] and W_var do not need to be incremented, but H_var does for (j = 0; j < nb_W - 1; j++) value += (*H_var) * (*W_var++) * (*input_line_p[current_line]++); value += (*H_var++) * (*W_var) * (*input_line_p[current_line]); } // Straiforward implementation is // *(output_line_p[out_line]++)=value/diviseur; // round_off_error=value%diviseur; // Here, we speed up things but using the pretabulated nearest integral parts *(output_line_p[out_line]++) = divide[value]; W += nb_W + 1; } H += nb_H + 1; first_line += nb_H - 1; input_line_p[first_line] -= input_width_slice - 1; // If last line of input is to be reused in next loop, // make the pointer points at the correct place } input_line_p[first_line] += input_width_slice - 1; for (in_line = 0; in_line < input_height_slice; in_line++) input_line_p[in_line]++; } } } else { // output frames are interlaced, line numbers gioes from 0 to n-1. // Therefore, downscaling is done between odd lines, then between even lines, but we do not mix odd and even lines. // So, we have to calculate the even and odd part of out_line_slice. // If the odd part is naturally out_line_slice % 2, the even part is (out_line_slice/2)*2. For speed reason, // the even part will be xritten as out_line_slice & ~(unsigned int) 1 mjpeg_debug ("Interlaced downscaling"); for (out_line_slice = 0; out_line_slice < local_out_nb_line_slice; out_line_slice++) { u_c_p = input + ((out_line_slice & ~(unsigned int) 1) * input_height_slice + out_line_slice % 2) * local_input_width; for (in_line = 0; in_line < input_height_slice; in_line++) { input_line_p[in_line] = u_c_p; u_c_p += 2 * local_input_width; } u_c_p = output + ((out_line_slice & ~(unsigned int) 1) * output_height_slice + out_line_slice % 2) * local_output_width; for (out_line = 0; out_line < output_height_slice; out_line++) { output_line_p[out_line] = u_c_p; u_c_p += 2 * local_output_width; } for (out_col_slice = 0; out_col_slice < local_out_nb_col_slice; out_col_slice++) { H = height_coeff; first_line = 0; for (out_line = 0; out_line < output_height_slice; out_line++) { nb_H = *H; W = width_coeff; for (out_col = 0; out_col < output_width_slice; out_col++) { H_var = H + 1; nb_W = *W; value = 0; last_line = first_line + nb_H; for (current_line = first_line; current_line < last_line; current_line++) { W_var = W + 1; // we average nb_W columns of input : we increment input_line_p[current_line] and W_var each time, except for the last value where // input_line_p[current_line] and W_var do not need to be incremented, but H_var does for (j = 0; j < nb_W - 1; j++) value += (*H_var) * (*W_var++) * (*input_line_p[current_line]++); value += (*H_var++) * (*W_var) * (*input_line_p[current_line]); } // Straiforward implementation is // *(output_line_p[out_line]++)=value/diviseur; // round_off_error=value%diviseur; // Here, we speed up things but using the pretabulated integral parts *(output_line_p[out_line]++) = divide[value]; W += nb_W + 1; } H += nb_H + 1; first_line += nb_H - 1; input_line_p[first_line] -= input_width_slice - 1; // If last line of input is to be reused in next loop, // make the pointer points at the correct place } input_line_p[first_line] += input_width_slice - 1; for (in_line = 0; in_line < input_height_slice; in_line++) input_line_p[in_line]++; } } } mjpeg_debug ("End of average"); return (0); } // ************************************************************************************* // ************************************************************************************* int average_specific (uint8_t * input, uint8_t * output, unsigned int *height_coeff, unsigned int *width_coeff, unsigned int half) { // This function gathers code that are speed enhanced due to specific downscaling ratios unsigned int line_index; unsigned int local_output_active_height = output_active_height >> half; unsigned int local_input_width = input_width >> half; unsigned int local_output_width = output_width >> half; unsigned int local_output_active_width = output_active_width >> half; unsigned int local_out_nb_col_slice = out_nb_col_slice >> half; unsigned int local_out_nb_line_slice = out_nb_line_slice >> half; unsigned int number,in_line_offset,out_line_offset; // specific==1, 4 uint8_t temp_uint8_t; uint8_t *in_line_p; uint8_t *out_line_p; unsigned int *W_var, *W; int j, nb_W; unsigned int out_col_slice, out_col; int treatment = 0; unsigned long int value = 0, value1 = 0, value2 = 0, value3 = 0; // Specific==2 uint8_t *in_first_line_p, *in_second_line_p; unsigned int out_line; // specific=3 unsigned char *u_c_p; unsigned int in_line; uint8_t *input_line_p[input_height_slice]; // specific=5 unsigned int *H_var, *H; unsigned int nb_H, first_line, last_line, current_line; unsigned int out_line_slice; uint8_t *output_line_p[output_height_slice]; //Init mjpeg_debug ("Start of average_specific %u", specific); //End of INIT if (specific == 1) { treatment = 1; mjpeg_debug ("Non interlaced and/or interlaced treatment"); // We just take the average along the width, not the height, line per line // Infered from average, with input_height_slice=output_height_slice=1; for (line_index = 0; line_index < local_output_active_height; line_index++) { in_line_p = input + line_index * local_input_width; out_line_p = output + line_index * local_output_width; for (out_col_slice = 0; out_col_slice < local_out_nb_col_slice; out_col_slice++) { W = width_coeff; for (out_col = 0; out_col < output_width_slice; out_col++) { nb_W = *W; value = 0; W_var = W + 1; for (j = 0; j < nb_W - 1; j++) value += (*W_var++) * (*in_line_p++); value += (*W_var) * (*in_line_p); *(out_line_p++) = divide[value]; W += nb_W + 1; } in_line_p++; } } } if (specific == 2) { treatment = 2; // SPECIAL FAST Full_size to VCD downscaling : 2to1 for width and height // Since 2 to 1 height dowscaling, no need for line switching // Drawback: slight distortion on width if (interlaced == Y4M_ILACE_NONE) { mjpeg_debug ("Non-interlaced downscaling"); for (out_line = 0; out_line < local_output_active_height; out_line++) { in_first_line_p = input + out_line * (local_input_width << 1); in_second_line_p = in_first_line_p + local_input_width; out_line_p = output + out_line * local_output_width; for (out_col = 0; out_col < local_output_active_width; out_col++) { // Division of integers is always made by default. This results in a systematic drift towards smaller values. // What we really need, // is a division that takes the nearest integer. // So, we add 1/2 of the divider to the value to be divided // *(out_line_p++) = // (2 + *(in_first_line_p) + *(in_first_line_p + 1) + // *(in_second_line_p) + *(in_second_line_p + 1)) >> 2; *(out_line_p++) = divide[*(in_first_line_p) + *(in_first_line_p + 1) + *(in_second_line_p) + *(in_second_line_p + 1)]; in_first_line_p += 2; in_second_line_p += 2; } } } else { mjpeg_debug ("Interlaced downscaling"); for (line_index = 0; line_index < local_output_active_height; line_index++) { in_first_line_p = input + (((line_index & ~(unsigned int) 1) << 1) + (line_index % 2)) * local_input_width; in_second_line_p = in_first_line_p + (local_input_width << 1); out_line_p = output + line_index * local_output_width; for (out_col = 0; out_col < local_output_active_width; out_col++) { /* *(out_line_p++) = (2 + *(in_first_line_p) + *(in_first_line_p + 1) + *(in_second_line_p) + *(in_second_line_p + 1)) >> 2; */ *(out_line_p++) = divide[*(in_first_line_p) + *(in_first_line_p + 1) + * (in_second_line_p) + * (in_second_line_p + 1)]; in_first_line_p += 2; in_second_line_p += 2; } } } } if (specific == 3) { treatment = 3; // input_height_slice=2, output_height_slice=1 => input lines will be summed together. // infered from average with output_height_slice=1 and explicity writting of the for(in_line=0;in_line> half); out_col_slice++) { W = width_coeff; for (out_col = 0; out_col < output_width_slice; out_col++) { nb_W = *W; value = 0; W_var = W + 1; for (j = 0; j < nb_W - 1; j++) value += (*W_var++) * ((*input_line_p[0]++) + (*input_line_p[1]++)); value += (*W_var) * (*input_line_p[0] + *input_line_p[1]); *(out_line_p++) = divide[value]; W += nb_W + 1; } input_line_p[0]++; input_line_p[1]++; } } } } if (specific == 4) { // just a copy: we copy line per line (warning! these lines are output_width long BUT we only copy output_active_width length of them) treatment = 4; mjpeg_debug ("Non-interlaced or interlaced downscaling"); for (line_index = 0; line_index < local_output_active_height; line_index++) // ; memcpy (output + line_index * local_output_width, input + line_index * local_input_width, local_output_active_width); } if (specific == 5) { // We downscale only lines along the height, not the width treatment = 5; if (interlaced == Y4M_ILACE_NONE) { mjpeg_debug ("Non-interlaced downscaling"); for (out_line_slice = 0; out_line_slice < local_out_nb_line_slice; out_line_slice++) { for (in_line = 0; in_line < input_height_slice; in_line++) { number = out_line_slice * input_height_slice + in_line; input_line_p[in_line] = input + number * local_input_width; } u_c_p = output + out_line_slice * output_height_slice * local_output_width; for (out_line = 0; out_line < output_height_slice; out_line++) { output_line_p[out_line] = u_c_p; u_c_p += local_output_width; } for (out_col = 0; out_col < local_output_active_width; out_col++) { H = height_coeff; first_line = 0; for (out_line = 0; out_line < output_height_slice; out_line++) { nb_H = *H; H_var = H + 1; value = 0; last_line = first_line + nb_H; for (current_line = first_line; current_line < last_line; current_line++) value += (*H_var++) * (*input_line_p[current_line]); *(output_line_p[out_line]++) = divide[value]; H += nb_H + 1; first_line += nb_H - 1; } for (in_line = 0; in_line < input_height_slice; in_line++) input_line_p[in_line]++; } } } else { mjpeg_debug ("Interlaced downscaling"); for (out_line_slice = 0; out_line_slice < local_out_nb_line_slice; out_line_slice++) { u_c_p = input + ((out_line_slice & ~(unsigned int) 1) * input_height_slice + out_line_slice % 2) * local_input_width; for (in_line = 0; in_line < input_height_slice; in_line++) { input_line_p[in_line] = u_c_p; u_c_p += 2 * local_input_width; } u_c_p = output + ((out_line_slice & ~(unsigned int) 1) * output_height_slice + out_line_slice % 2) * local_output_width; for (out_line = 0; out_line < output_height_slice; out_line++) { output_line_p[out_line] = u_c_p; u_c_p += 2 * local_output_width; } for (out_col = 0; out_col < local_output_active_width; out_col++) { H = height_coeff; first_line = 0; for (out_line = 0; out_line < output_height_slice; out_line++) { nb_H = *H; H_var = H + 1; value = 0; last_line = first_line + nb_H; for (current_line = first_line; current_line < last_line; current_line++) value += (*H_var++) * (*input_line_p[current_line]); *(output_line_p[out_line]++) = divide[value]; H += nb_H + 1; first_line += nb_H - 1; } for (in_line = 0; in_line < input_height_slice; in_line++) input_line_p[in_line]++; } } } } if (specific == 6) { // Dedicated SVCD: we downscale 3 for 2 on width, and 1 to 1 on height. Infered from specific=1 // For width, W points are "2 2 1 2 1 2" => we can explicitely write down the calculs of value treatment = 6; mjpeg_debug ("Non interlaced and/or interlaced treatment"); in_line_offset = local_input_width - local_out_nb_col_slice * 3; out_line_offset = local_output_width - local_out_nb_col_slice * 2; in_line_p = input; out_line_p = output; for (line_index = 0; line_index < local_output_active_height; line_index++) { // in_line_p = input + line_index * local_input_width; // out_line_p = output + line_index * local_output_width; for (out_col_slice = 0; out_col_slice < local_out_nb_col_slice; out_col_slice++) { temp_uint8_t = in_line_p[1]; // *(out_line_p++) = divide[((*in_line_p) << 1) + temp_uint8_t]; *(out_line_p++) = (((*in_line_p) << 1) + temp_uint8_t + 1) / 3; in_line_p += 2; // *(out_line_p++) = divide[temp_uint8_t + ((*in_line_p++) << 1)]; *(out_line_p++) = (temp_uint8_t + ((*in_line_p++) << 1) + 1) / 3; } in_line_p += in_line_offset; out_line_p += out_line_offset; } } if (specific == 7) { // Dedicated to WIDE2STD alone downscaling: 4 to 3 on height, width not downscaled // For the height, H is equal to 2 3 1 2 2 2 2 1 3 // Infered from specific=5 treatment = 7; if (interlaced == Y4M_ILACE_NONE) { mjpeg_debug ("Non-interlaced downscaling"); for (out_line_slice = 0; out_line_slice < local_out_nb_line_slice; out_line_slice++) { input_line_p[0] = input + (4 * out_line_slice + 0) * local_input_width; input_line_p[1] = input + (4 * out_line_slice + 1) * local_input_width; input_line_p[2] = input + (4 * out_line_slice + 2) * local_input_width; input_line_p[3] = input + (4 * out_line_slice + 3) * local_input_width; output_line_p[0] = output + 3 * out_line_slice * local_output_width; output_line_p[1] = output_line_p[0] + local_output_width; output_line_p[2] = output_line_p[1] + local_output_width; for (out_col = 0; out_col < local_output_active_width; out_col++) { *(output_line_p[0]++) = divide[3 * (*input_line_p[0]++) + (*input_line_p[1])]; *(output_line_p[1]++) = divide[2 * (*input_line_p[1]++) + 2 * (*input_line_p[2])]; *(output_line_p[2]++) = divide[(*input_line_p[2]++) + 3 * (*input_line_p[3]++)]; } } } else { mjpeg_debug ("Interlaced downscaling"); for (out_line_slice = 0; out_line_slice < local_out_nb_line_slice; out_line_slice++) { u_c_p = input + ((out_line_slice & ~(unsigned int) 1) * input_height_slice + (out_line_slice % 2)) * local_input_width; for (in_line = 0; in_line < input_height_slice; in_line++) { input_line_p[in_line] = u_c_p; u_c_p += 2 * local_input_width; } u_c_p = output + ((out_line_slice & ~(unsigned int) 1) * output_height_slice + (out_line_slice % 2)) * local_output_width; for (out_line = 0; out_line < output_height_slice; out_line++) { output_line_p[out_line] = u_c_p; u_c_p += 2 * local_output_width; } for (out_col = 0; out_col < local_output_active_width; out_col++) { *(output_line_p[0]++) = divide[3 * (*input_line_p[0]++) + (*input_line_p[1])]; *(output_line_p[1]++) = divide[2 * (*input_line_p[1]++) + 2 * (*input_line_p[2])]; *(output_line_p[2]++) = divide[(*input_line_p[2]++) + 3 * (*input_line_p[3]++)]; } } } } if (specific == 8) { // Special FASTWIDE2VCD mode: 2 to 1 for width, and 8 to 3 for height // *8 is replaced by <<3 and 2* by <<1 // Drawback: slight distortion on width // Coefficient for horizontal downscaling : (3,3,2), (1,3,3,1), (2,3,3) treatment = 8; if (interlaced == Y4M_ILACE_NONE) { mjpeg_debug ("Non-interlaced downscaling"); for (out_line_slice = 0; out_line_slice < local_out_nb_line_slice; out_line_slice++) { input_line_p[0] = input + (8 * out_line_slice + 0) * local_input_width; input_line_p[1] = input + (8 * out_line_slice + 1) * local_input_width; input_line_p[2] = input + (8 * out_line_slice + 2) * local_input_width; input_line_p[3] = input + (8 * out_line_slice + 3) * local_input_width; input_line_p[4] = input + (8 * out_line_slice + 4) * local_input_width; input_line_p[5] = input + (8 * out_line_slice + 5) * local_input_width; input_line_p[6] = input + (8 * out_line_slice + 6) * local_input_width; input_line_p[7] = input + (8 * out_line_slice + 7) * local_input_width; output_line_p[0] = output + out_line_slice * 3 * local_output_width; output_line_p[1] = output_line_p[0] + local_output_width; output_line_p[2] = output_line_p[1] + local_output_width; for (out_col = 0; out_col < local_output_active_width; out_col++) { *(output_line_p[0]++) = divide[3 * (*input_line_p[0] + (*input_line_p[0] + 1)) + 3 * (*input_line_p[1] + (*input_line_p[1] + 1)) + 2 * (*input_line_p[2] + (*input_line_p[2] + 1))]; input_line_p[0] += 2; input_line_p[1] += 2; *(output_line_p[1]++) = divide[(*input_line_p[2] + (*input_line_p[2] + 1)) + 3 * (*input_line_p[3] + (*input_line_p[3] + 1)) + 3 * (*input_line_p[4] + (*input_line_p[4] + 1)) + (*input_line_p[5] + (*input_line_p[5] + 1))]; input_line_p[2] += 2; input_line_p[3] += 2; input_line_p[4] += 2; *(output_line_p[2]++) = divide[2 * (*input_line_p[5] + (*input_line_p[5] + 1)) + 3 * (*input_line_p[6] + (*input_line_p[6] + 1)) + 3 * (*input_line_p[7] + (*input_line_p[7] + 1))]; input_line_p[5] += 2; input_line_p[6] += 2; input_line_p[7] += 2; } } } else { mjpeg_debug ("Interlaced downscaling"); for (out_line_slice = 0; out_line_slice < local_out_nb_line_slice; out_line_slice++) { input_line_p[0] = input + (((out_line_slice & ~(unsigned int) 1) << 3) + (out_line_slice % 2)) * local_input_width; input_line_p[1] = input_line_p[0] + (local_input_width << 1); input_line_p[2] = input_line_p[1] + (local_input_width << 1); input_line_p[3] = input_line_p[2] + (local_input_width << 1); input_line_p[4] = input_line_p[3] + (local_input_width << 1); input_line_p[5] = input_line_p[4] + (local_input_width << 1); input_line_p[6] = input_line_p[5] + (local_input_width << 1); input_line_p[7] = input_line_p[6] + (local_input_width << 1); output_line_p[0] = output + ((out_line_slice & ~(unsigned int) 1) * 3 + (out_line_slice % 2)) * local_output_width; output_line_p[1] = output_line_p[0] + (local_output_width << 1); output_line_p[2] = output_line_p[1] + (local_output_width << 1); for (out_col = 0; out_col < local_output_active_width; out_col++) { *(output_line_p[0]++) = divide[3 * (*input_line_p[0] + (*input_line_p[0] + 1)) + 3 * (*input_line_p[1] + (*input_line_p[1] + 1)) + 2 * (*input_line_p[2] + (*input_line_p[2] + 1))]; input_line_p[0] += 2; input_line_p[1] += 2; *(output_line_p[1]++) = divide[(*input_line_p[2] + (*input_line_p[2] + 1)) + 3 * (*input_line_p[3] + (*input_line_p[3] + 1)) + 3 * (*input_line_p[4] + (*input_line_p[4] + 1)) + (*input_line_p[5] + (*input_line_p[5] + 1))]; input_line_p[2] += 2; input_line_p[3] += 2; input_line_p[4] += 2; *(output_line_p[2]++) = divide[2 * (*input_line_p[5] + (*input_line_p[5] + 1)) + 3 * (*input_line_p[6] + (*input_line_p[6] + 1)) + 3 * (*input_line_p[7] + (*input_line_p[7] + 1))]; input_line_p[5] += 2; input_line_p[6] += 2; input_line_p[7] += 2; } } } } if (specific == 9) { // Special WIDE2VCD, on height : 8->3 treatment = 9; if (interlaced == Y4M_ILACE_NONE) { mjpeg_debug ("Non-interlaced downscaling"); // input frames are not interlaced, as are output frames. // So, we average input_height_slice following lines into output_height_slice lines for (out_line_slice = 0; out_line_slice < local_out_nb_line_slice; out_line_slice++) { for (in_line = 0; in_line < input_height_slice; in_line++) { number = out_line_slice * input_height_slice + in_line; input_line_p[in_line] = input + number * local_input_width; } u_c_p = output + out_line_slice * output_height_slice * local_output_width; for (out_line = 0; out_line < output_height_slice; out_line++) { output_line_p[out_line] = u_c_p; u_c_p += local_output_width; } for (out_col_slice = 0; out_col_slice < local_out_nb_col_slice; out_col_slice++) { W = width_coeff; for (out_col = 0; out_col < output_width_slice; out_col++) { nb_W = *W; value1 = value2 = value3 = 0; W_var = W + 1; for (j = 0; j < nb_W - 1; j++) { value1 += (*W_var) * (3 * (*input_line_p[0]++) + 3 * (*input_line_p[1]++) + 2 * (*input_line_p[2])); value2 += (*W_var) * ((*input_line_p[2]++) + 3 * (*input_line_p[3]++) + 3 * (*input_line_p[4]++) + (*input_line_p[5])); value3 += (*W_var++) * (2 * (*input_line_p[5]++) + 3 * (*input_line_p[6]++) + 3 * (*input_line_p[7]++)); } value1 += (*W_var) * (3 * (*input_line_p[0]) + 3 * (*input_line_p[1]) + 2 * (*input_line_p[2])); value2 += (*W_var) * ((*input_line_p[2]) + 3 * (*input_line_p[3]) + 3 * (*input_line_p[4]) + (*input_line_p[5])); value3 += (*W_var) * (2 * (*input_line_p[5]) + 3 * (*input_line_p[6]) + 3 * (*input_line_p[7])); *(output_line_p[0]++) = divide[value1]; *(output_line_p[1]++) = divide[value2]; *(output_line_p[2]++) = divide[value3]; W += nb_W + 1; } input_line_p[0]++; input_line_p[1]++; input_line_p[2]++; input_line_p[3]++; input_line_p[4]++; input_line_p[5]++; input_line_p[6]++; input_line_p[7]++; } } } else { mjpeg_debug ("Interlaced downscaling"); for (out_line_slice = 0; out_line_slice < local_out_nb_line_slice; out_line_slice++) { u_c_p = input + ((out_line_slice & ~(unsigned int) 1) * input_height_slice + (out_line_slice % 2)) * local_input_width; for (in_line = 0; in_line < input_height_slice; in_line++) { input_line_p[in_line] = u_c_p; u_c_p += 2 * local_input_width; } u_c_p = output + ((out_line_slice & ~(unsigned int) 1) * output_height_slice + (out_line_slice % 2)) * local_output_width; for (out_line = 0; out_line < output_height_slice; out_line++) { output_line_p[out_line] = u_c_p; u_c_p += 2 * local_output_width; } for (out_col_slice = 0; out_col_slice < local_out_nb_col_slice; out_col_slice++) { H = height_coeff; first_line = 0; for (out_line = 0; out_line < output_height_slice; out_line++) { nb_H = *H; W = width_coeff; for (out_col = 0; out_col < output_width_slice; out_col++) { H_var = H + 1; nb_W = *W; value = 0; last_line = first_line + nb_H; for (current_line = first_line; current_line < last_line; current_line++) { W_var = W + 1; // we average nb_W columns of input : we increment input_line_p[current_line] and W_var each time, except for the last value where // input_line_p[current_line] and W_var do not need to be incremented, but H_var does for (j = 0; j < nb_W - 1; j++) value += (*H_var) * (*W_var++) * (*input_line_p[current_line]++); value += (*H_var++) * (*W_var) * (*input_line_p[current_line]); } // Straiforward implementation is // *(output_line_p[out_line]++)=value/diviseur; // round_off_error=value%diviseur; // Here, we speed up things but using the pretabulated integral parts *(output_line_p[out_line]++) = divide[value]; W += nb_W + 1; } H += nb_H + 1; first_line += nb_H - 1; input_line_p[first_line] -= input_width_slice - 1; // If last line of input is to be reused in next loop, // make the pointer points at the correct place } input_line_p[first_line] += input_width_slice - 1; for (in_line = 0; in_line < input_height_slice; in_line++) input_line_p[in_line]++; } } } } if (treatment == 0) mjpeg_error_exit1 ("Unknown specific downscaling treatment %u", specific); mjpeg_debug ("End of average_specific"); return (0); } mjpegtools-2.1.0/yuvscaler/yuvscaler.c0000644000175000017500000022237210727547417020435 0ustar glowwormglowworm/* * yuvscaler.c * Copyright (C) 2001-2004 Xavier Biquard * * * Scales arbitrary sized yuv frame to yuv frames suitable for VCD, SVCD or specified * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ // Implementation: there are two scaling methods: one for not_interlaced output and one for interlaced output. // // First version doing only downscaling with no interlacing // June 2001: interlacing capable version // July 2001: upscaling capable version // September 2001: line switching // September/October 2001: new yuv4mpeg header // October 2001: first MMX part for bicubic // September/November 2001: what a mess this code! => cleaning and splitting // December 2001: implementation of time reordering of frames // January 2002: sample aspect ratio calculation by Matto // February 2002: interlacing specification now possible. Replaced alloca with malloc // Mars 2002: sample aspect ratio calculations are back! // May/June 2002: remove file reading capabilities (do not duplicate lav2yuv), add -O DVD, add color chrominance correction // as well as luminance linear reequilibrium. Lots of code cleaning, function renaming, etc... // Keywords concerning interlacing/preprocessing now under INPUT case // October 2002: yuvscaler functionnalities not related to image rescaling now part of yuvcorrect // January 2003: reimplementation of the bicubic algorithm => goes faster // December-January 2004: First MMX subroutine for bicubic calculus => speed x2 // January-February 2004: make it go even faster // This first MMX version showed the limits of the use of cspline_w and cspline_h pointers => second // MMX version will implement dedicated cspline_w and cspline_h pointers for MMX treatment // // // TODO: // no more global variables for librarification // Remove file reading/writing // treat the interlace case + specific cases #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include "mjpeg_logging.h" #include "yuv4mpeg.h" #include "mjpeg_types.h" #include "yuvscaler.h" #include "mpegconsts.h" #ifdef HAVE_ASM_MMX #include #include "../utils/mmx.h" #endif #define yuvscaler_VERSION "11-Dec-2007" // For pointer address alignement #define ALIGNEMENT 16 // 16 bytes alignement for mmx registers in SIMD instructions for Pentium #define MAXWIDTHNEIGHBORS 16 float PI = 3.141592654; // For input unsigned int input_width; unsigned int input_height; y4m_ratio_t input_sar; // see yuv4mpeg.h and yuv4mpeg_intern.h for possible values unsigned int input_useful = 0; // =1 if specified unsigned int input_useful_width = 0; unsigned int input_useful_height = 0; unsigned int input_discard_col_left = 0; unsigned int input_discard_col_right = 0; unsigned int input_discard_line_above = 0; unsigned int input_discard_line_under = 0; unsigned int input_black = 0; //=1 if black borders on input frames unsigned int input_black_line_above = 0; unsigned int input_black_line_under = 0; unsigned int input_black_col_right = 0; unsigned int input_black_col_left = 0; unsigned int input_active_height = 0; unsigned int input_active_width = 0; uint8_t input_y_min, input_y_max; float Ufactor, Vfactor, Gamma; // Downscaling ratios unsigned int input_height_slice; unsigned int output_height_slice; unsigned int input_width_slice; unsigned int output_width_slice; // For padded_input unsigned int padded_width = 0; unsigned int padded_height = 0; // For output unsigned int display_width; unsigned int display_height; unsigned int output_width; unsigned int output_height; unsigned int output_active_width; unsigned int output_active_height; unsigned int output_black_line_above = 0; unsigned int output_black_line_under = 0; unsigned int output_black_col_right = 0; unsigned int output_black_col_left = 0; unsigned int output_skip_line_above = 0; unsigned int output_skip_line_under = 0; unsigned int output_skip_col_right = 0; unsigned int output_skip_col_left = 0; unsigned int black = 0, black_line = 0, black_col = 0; // =1 if black lines must be generated on output unsigned int skip = 0, skip_line = 0, skip_col = 0; // =1 if lines or columns from the active output will not be displayed on output frames // NB: as these number may not be multiple of output_[height,width]_slice, it is not possible to remove the corresponding pixels in // the input frame, a solution that could speed up things. unsigned int vcd = 0; //=1 if vcd output was selected unsigned int svcd = 0; //=1 if svcd output was selected unsigned int dvd = 0; //=1 if dvd output was selected // Global variables int interlaced = -1; //=Y4M_ILACE_NONE for not-interlaced scaling, =Y4M_ILACE_TOP_FIRST or Y4M_ILACE_BOT_FIRST for interlaced scaling int norm = -1; // =0 for PAL and =1 for NTSC int wide = 0; // =1 for wide (16:9) input to standard (4:3) output conversion int ratio = 0; int size_keyword = 0; // =1 is the SIZE keyword has been used int infile = 0; // =0 for stdin (default) =1 for file int algorithm = -1; // =0 for resample, and =1 for bicubic unsigned int specific = 0; // is >0 if a specific downscaling speed enhanced treatment of data is possible unsigned int mono = 0; // is =1 for monochrome output // Keywords for argument passing const char VCD_KEYWORD[] = "VCD"; const char HIRESSTILL[] = "HIRESSTILL"; const char LOSVCDSTILL[] = "LOSVCDSTILL"; const char LOVCDSTILL[] = "LOVCDSTILL"; const char SVCD_KEYWORD[] = "SVCD"; const char DVD_KEYWORD[] = "DVD"; const char SIZE_KEYWORD[] = "SIZE_"; const char USE_KEYWORD[] = "USE_"; const char WIDE2STD_KEYWORD[] = "WIDE2STD"; const char INFILE_KEYWORD[] = "INFILE_"; const char RATIO_KEYWORD[] = "RATIO_"; const char MONO_KEYWORD[] = "MONOCHROME"; const char FASTVCD[] = "FASTVCD"; const char FAST_WIDE2VCD[] = "FAST_WIDE2VCD"; const char WIDE2VCD[] = "WIDE2VCD"; const char RESAMPLE[] = "RESAMPLE"; const char BICUBIC[] = "BICUBIC"; const char ACTIVE[] = "ACTIVE"; const char NO_HEADER[] = "NO_HEADER"; const char NOMMX[] = "NOMMX"; // Specific to BICUBIC algorithm // 2048=2^11 #define FLOAT2INTEGER 2048 #define FLOAT2INTEGERPOWER 11 unsigned int bicubic_div_width = FLOAT2INTEGER, bicubic_div_height = FLOAT2INTEGER; unsigned int multiplicative; // Unclassified unsigned long int diviseur; uint8_t *divide; unsigned short int *u_i_p; unsigned int out_nb_col_slice, out_nb_line_slice; const static char *legal_opt_flags = "k:I:d:n:v:M:m:O:whtg"; int verbose = 1; #define PARAM_LINE_MAX 256 uint8_t blacky = 16; uint8_t blackuv = 128; uint8_t no_header = 0; // =1 for no stream header output #ifdef HAVE_ASM_MMX int16_t *mmx_padded, *mmx_cubic; int32_t *mmx_res; int mmx = 1; // =1 for mmx activated, =0 for deactivated/not available #endif int32_t *intermediate,*intermediate_p,*inter_begin; // ************************************************************************************* void yuvscaler_print_usage (char *argv[]) { fprintf (stderr, "usage: yuvscaler -I [input_keyword] -M [mode_keyword] -O [output_keyword] [-S 0|1] [-n p|s|n] [-v 0-2] [-h]\n" "yuvscaler UPscales or DOWNscales arbitrary-sized YUV frames coming from stdin (in YUV4MPEG 4:2:2 format)\n" "to a specified YUV frame sizes to stdout. Please use yuvcorrect for interlacing or color corrections\n" "\n" "yuvscaler is keyword driven :\n" "\t -I for keyword concerning INPUT frame characteristics\n" "\t -M for keyword concerning the scaling MODE of yuvscaler\n" "\t -O for keyword concerning OUTPUT frame characteristics\n" "\n" "Possible input keyword are:\n" "\t USE_WidthxHeight+WidthOffset+HeightOffset to select a useful area of the input frame (all multiple of 2,\n" "\t Height and HeightOffset multiple of 4 if interlaced), the rest of the image being discarded\n" "\t ACTIVE_WidthxHeight+WidthOffset+HeightOffset to select an active area of the input frame (all multiple of 2,\n" "\t Height and HeightOffset multiple of 4 if interlaced), the rest of the image being made black\n" "\n" "Possible mode keyword are:\n" "\t BICUBIC to use the (Mitchell-Netravalli) high-quality bicubic upscaling and/or downscaling algorithm\n" "\t RESAMPLE to use a classical resampling algorithm -only for downscaling- that goes much faster than bicubic\n" "\t For coherence reason, yuvscaler will use RESAMPLE if only downscaling is necessary, BICUBIC otherwise\n" "\t WIDE2STD to converts widescreen (16:9) input frames to standard output (4:3), generating necessary black lines\n" "\t RATIO_WidthIn_WidthOut_HeightIn_HeightOut to specified conversion ratios of\n" "\t WidthIn/WidthOut for width and HeightIN/HeightOut for height to be applied to the useful area.\n" "\t The output active area that results from scaling the input useful area might be different\n" "\t from the display area specified thereafter using the -O KEYWORD syntax.\n" "\t In that case, yuvscaler will automatically generate necessary black lines and columns and/or skip necessary\n" "\t lines and columns to get an active output centered within the display size.\n" "\t WIDE2VCD to transcode wide (16:9) frames to VCD (equivalent to -M WIDE2STD -O VCD)\n" "\t FASTVCD to transcode full sized frames to VCD (equivalent to -M RATIO_2_1_2_1 -O VCD)\n" "\t FAST_WIDE2VCD to transcode full sized wide (16:9) frames to VCD (-M WIDE2STD -M RATIO_2_1_2_1 -O VCD)\n" "\t NO_HEADER to suppress stream header generation on output (chaining scaling with different ratios)\n" "\t By default, yuvscaler will use either interlaced or not-interlaced scaling according to the input header interlace information.\n" "\t If this information is missing in the header (cf. mpeg2dec), yuvscaler will use interlaced acaling\n" "\n" "Possible output keywords are:\n" "\t MONOCHROME to generate monochrome frames on output\n" "\t VCD to generate VCD compliant frames, taking care of PAL and NTSC standards, not-interlaced/progressive frames\n" "\t SVCD to generate SVCD compliant frames, taking care of PAL and NTSC standards, any interlacing types\n" "\t DVD to generate DVD compliant frames, taking care of PAL and NTSC standards, any interlacing types\n" "\t (SVCD and DVD: if input is not-interlaced/progressive, output interlacing will be taken as top_first)\n" "\t HIRESSTILL to generate HIgh-RESolution STILL images: not-interlaced/progressive frames of size 704x(PAL-576,NTSC-480)\n" "\t LOSVCDSTILL to generate LOw-resolution SVCD still images, not-interlaced/progressive frames, size 480x(PAL-576,NTSC-480)\n" "\t LOVCDSTILL to generate LOw-resolution VCD still images, not-interlaced/progressive frames, size 352x(PAL-288,NTSC-240)\n" "\t SIZE_WidthxHeight to generate frames of size WidthxHeight on output (multiple of 2, Height of 4 if interlaced)\n" "\n" "-n (usually not necessary) if norm could not be determined from data flux, specifies the OUTPUT norm for VCD/SVCD p=pal,s=secam,n=ntsc\n" "-v Specifies the degree of verbosity: 0=quiet, 1=normal, 2=verbose/debug\n" "-h : print this lot!\n"); exit (1); } // ************************************************************************************* // ************************************************************************************* void yuvscaler_print_information (y4m_stream_info_t in_streaminfo, y4m_ratio_t frame_rate) { // This function print USER'S INFORMATION const char TOP_FIRST[] = "INTERLACED_TOP_FIRST"; const char BOT_FIRST[] = "INTERLACED_BOTTOM_FIRST"; const char NOT_INTER[] = "NOT_INTERLACED"; const char PROGRESSIVE[] = "PROGRESSIVE"; y4m_log_stream_info (mjpeg_loglev_t("info"), "input: ", &in_streaminfo); switch (interlaced) { case Y4M_ILACE_NONE: mjpeg_info ("from %ux%u, take %ux%u+%u+%u, %s/%s", input_width, input_height, input_useful_width, input_useful_height, input_discard_col_left, input_discard_line_above, NOT_INTER, PROGRESSIVE); break; case Y4M_ILACE_TOP_FIRST: mjpeg_info ("from %ux%u, take %ux%u+%u+%u, %s", input_width, input_height, input_useful_width, input_useful_height, input_discard_col_left, input_discard_line_above, TOP_FIRST); break; case Y4M_ILACE_BOTTOM_FIRST: mjpeg_info ("from %ux%u, take %ux%u+%u+%u, %s", input_width, input_height, input_useful_width, input_useful_height, input_discard_col_left, input_discard_line_above, BOT_FIRST); break; default: mjpeg_info ("from %ux%u, take %ux%u+%u+%u", input_width, input_height, input_useful_width, input_useful_height, input_discard_col_left, input_discard_line_above); } if (input_black == 1) { mjpeg_info ("with %u and %u black line above and under", input_black_line_above, input_black_line_under); mjpeg_info ("and %u and %u black col left and right", input_black_col_left, input_black_col_right); mjpeg_info ("%u %u", input_active_width, input_active_height); } mjpeg_info ("scale to %ux%u, %ux%u being displayed", output_active_width, output_active_height, display_width, display_height); switch (algorithm) { case 0: mjpeg_info ("Scaling uses the %s algorithm, ", RESAMPLE); break; case 1: mjpeg_info ("Scaling uses the %s algorithm, ", BICUBIC); break; default: mjpeg_error_exit1 ("Unknown algorithm %d", algorithm); } if (black == 1) { mjpeg_info ("black lines: %u above and %u under", output_black_line_above, output_black_line_under); mjpeg_info ("black columns: %u left and %u right", output_black_col_left, output_black_col_right); } if (skip == 1) { mjpeg_info ("skipped lines: %u above and %u under", output_skip_line_above, output_skip_line_under); mjpeg_info ("skipped columns: %u left and %u right", output_skip_col_left, output_skip_col_right); } mjpeg_info ("frame rate: %.3f fps", Y4M_RATIO_DBL (frame_rate)); } // ************************************************************************************* // ************************************************************************************* uint8_t yuvscaler_nearest_integer_division (unsigned long int p, unsigned long int q) { // This function returns the nearest integer of the ratio p/q. // As this ratio in yuvscaler corresponds to a pixel value, it should be between 0 and 255 unsigned long int ratio = p / q; unsigned long int reste = p % q; unsigned long int frontiere = q - q / 2; // Do **not** change this into q/2 => it is not the same for odd q numbers if (reste >= frontiere) ratio++; if ((ratio < 0) || (ratio > 255)) mjpeg_error_exit1 ("Division error: %lu/%lu not in [0;255] range !!\n", p, q); return ((uint8_t) ratio); } // ************************************************************************************* // ************************************************************************************* static y4m_ratio_t yuvscaler_calculate_output_sar (int out_w, int out_h, int in_w, int in_h, y4m_ratio_t in_sar) { // This function calculates the sample aspect ratio (SAR) for the output stream, // given the input->output scale factors, and the input SAR. if (Y4M_RATIO_EQL (in_sar, y4m_sar_UNKNOWN)) { return y4m_sar_UNKNOWN; } else { y4m_ratio_t out_sar; /* out_SAR_w in_SAR_w input_W output_H --------- = -------- * ------- * -------- out_SAR_h in_SAR_h input_H output_W */ out_sar.n = in_sar.n * in_w * out_h; out_sar.d = in_sar.d * in_h * out_w; y4m_ratio_reduce (&out_sar); return out_sar; } } // ************************************************************************************* // ************************************************************************************* int yuvscaler_y4m_read_frame (int fd, y4m_stream_info_t *si, y4m_frame_info_t * frameinfo, unsigned long int buflen, uint8_t * buf) { // This function reads a frame from input stream. It does the same thing as the y4m_read_frame function (from yuv4mpeg.c) // May be replaced directly by it in the near future static int err = Y4M_OK; if ((err = y4m_read_frame_header (fd, si, frameinfo)) == Y4M_OK) { if ((err = y4m_read (fd, buf, buflen)) != Y4M_OK) { mjpeg_info ("Couldn't read FRAME content: %s!", y4m_strerr (err)); return (err); } } else { if (err != Y4M_ERR_EOF) mjpeg_info ("Couldn't read FRAME header: %s!", y4m_strerr (err)); else mjpeg_info ("End of stream!"); return (err); } return Y4M_OK; } // ************************************************************************************* // ************************************************************************************* // PREPROCESSING // ************************************************************************************* int blackout (uint8_t * input_y, uint8_t * input_u, uint8_t * input_v) { // The blackout function makes input borders pixels become black unsigned int line; uint8_t *right; // Y COMPONENT for (line = 0; line < input_black_line_above; line++) { memset (input_y, blacky, input_useful_width); input_y += input_width; } right = input_y + input_black_col_left + input_active_width; for (line = 0; line < input_active_height; line++) { memset (input_y, blacky, input_black_col_left); memset (right, blacky, input_black_col_right); input_y += input_width; right += input_width; } for (line = 0; line < input_black_line_under; line++) { memset (input_y, blacky, input_useful_width); input_y += input_width; } // U COMPONENT for (line = 0; line < (input_black_line_above >> 1); line++) { memset (input_u, blackuv, input_useful_width >> 1); input_u += input_width >> 1; } right = input_u + ((input_black_col_left + input_active_width) >> 1); for (line = 0; line < (input_active_height >> 1); line++) { memset (input_u, blackuv, input_black_col_left >> 1); memset (right, blackuv, input_black_col_right >> 1); input_u += input_width >> 1; right += input_width >> 1; } for (line = 0; line < (input_black_line_under >> 1); line++) { memset (input_u, blackuv, input_useful_width >> 1); input_u += input_width >> 1; } // V COMPONENT for (line = 0; line < (input_black_line_above >> 1); line++) { memset (input_v, blackuv, input_useful_width >> 1); input_v += input_width >> 1; } right = input_v + ((input_black_col_left + input_active_width) >> 1); for (line = 0; line < (input_active_height >> 1); line++) { memset (input_v, blackuv, input_black_col_left >> 1); memset (right, blackuv, input_black_col_right >> 1); input_v += input_width >> 1; right += input_width >> 1; } for (line = 0; line < (input_black_line_under >> 1); line++) { memset (input_v, blackuv, input_useful_width >> 1); input_v += input_width >> 1; } return (0); } // ************************************************************************************* // ************************************************************************************* void handle_args_global (int argc, char *argv[]) { // This function takes care of the global variables // initialisation that are independent of the input stream // The main goal is to know whether input frames originate from file or stdin int c; while ((c = getopt (argc, argv, legal_opt_flags)) != -1) { switch (c) { case 'v': verbose = atoi (optarg); if (verbose < 0 || verbose > 2) { mjpeg_error_exit1 ("Verbose level must be [0..2]"); } break; case 'n': // TV norm for SVCD/VCD output switch (*optarg) { case 'p': case 's': norm = 0; break; case 'n': norm = 1; break; default: mjpeg_error_exit1 ("Illegal norm letter specified: %c", *optarg); } break; case 'h': // case '?': yuvscaler_print_usage (argv); break; default: break; } } if (optind != argc) yuvscaler_print_usage (argv); } // ************************************************************************************* // ************************************************************************************* void handle_args_dependent (int argc, char *argv[]) { // This function takes care of the global variables // initialisation that may depend on the input stream // It does also coherence check on input, useful_input, display, output_active sizes and ratio sizes int c; unsigned int ui1, ui2, ui3, ui4; int output, input, mode; // By default, display sizes is the same as input size display_width = input_width; display_height = input_height; optind = 1; while ((c = getopt (argc, argv, legal_opt_flags)) != -1) { switch (c) { // ************** // OUTPUT KEYWORD // ************** case 'O': output = 0; if (strcmp (optarg, VCD_KEYWORD) == 0) { output = 1; vcd = 1; svcd = 0; // if user gives VCD, SVCD and DVD keywords, take last one only into account dvd = 0; display_width = 352; if (norm == 0) { mjpeg_info ("VCD output format requested in PAL/SECAM norm"); display_height = 288; } else if (norm == 1) { mjpeg_info ("VCD output format requested in NTSC norm"); display_height = 240; } else mjpeg_error_exit1 ("No norm specified, cannot determine VCD output size. Please use the -n option!"); } if (strcmp (optarg, SVCD_KEYWORD) == 0) { output = 1; svcd = 1; vcd = 0; // if user gives VCD, SVCD and DVD keywords, take last one only into account dvd = 0; display_width = 480; if (norm == 0) { mjpeg_info ("SVCD output format requested in PAL/SECAM norm"); display_height = 576; } else if (norm == 1) { mjpeg_info ("SVCD output format requested in NTSC norm"); display_height = 480; } else mjpeg_error_exit1 ("No norm specified, cannot determine SVCD output size. Please use the -n option!"); } if (strcmp (optarg, DVD_KEYWORD) == 0) { output = 1; vcd = 0; svcd = 0; // if user gives VCD, SVCD and DVD keywords, take last one only into account dvd = 1; display_width = 720; if (norm == 0) { mjpeg_info ("DVD output format requested in PAL/SECAM norm"); display_height = 576; } else if (norm == 1) { mjpeg_info ("DVD output format requested in NTSC norm"); display_height = 480; } else mjpeg_error_exit1 ("No norm specified, cannot determine DVD output size. Please use the -n option!"); } if (strncmp (optarg, SIZE_KEYWORD, 5) == 0) { output = 1; if (sscanf (optarg, "SIZE_%ux%u", &ui1, &ui2) == 2) { // Coherence check: sizes must be multiple of 2 if ((ui1 % 2 == 0) && (ui2 % 2 == 0)) { display_width = ui1; display_height = ui2; size_keyword = 1; } else mjpeg_error_exit1 ("Unconsistent SIZE keyword, not multiple of 2: %s", optarg); // A second check will eventually be done when output interlacing is finally known } else mjpeg_error_exit1 ("Wrong number of argument to SIZE keyword: %s", optarg); } // Theoritically, this should go into yuvcorrect, but I hesitate to do so if (strcmp (optarg, HIRESSTILL) == 0) { output = 1; interlaced = Y4M_ILACE_NONE; display_width = 704; if (norm == 0) { mjpeg_info ("HIRESSTILL output format requested in PAL/SECAM norm"); display_height = 576; } else if (norm == 1) { mjpeg_info ("HIRESSTILL output format requested in NTSC norm"); display_height = 480; } else mjpeg_error_exit1 ("No norm specified, cannot determine HIRESSTILL output size. Please use the -n option!"); } if (strcmp (optarg, LOSVCDSTILL) == 0) { output = 1; interlaced = Y4M_ILACE_NONE; display_width = 480; if (norm == 0) { mjpeg_info ("LOSVCDSTILL output format requested in PAL/SECAM norm"); display_height = 576; } else if (norm == 1) { mjpeg_info ("LOSVCDSTILL output format requested in NTSC norm"); display_height = 480; } else mjpeg_error_exit1 ("No norm specified, cannot determine LOSVCDSTILL output size. Please use the -n option!"); } if (strcmp (optarg, LOVCDSTILL) == 0) { output = 1; interlaced = Y4M_ILACE_NONE; display_width = 352; if (norm == 0) { mjpeg_info ("LOVCDSTILL output format requested in PAL/SECAM norm"); display_height = 288; } else if (norm == 1) { mjpeg_info ("LOVCDSTILL output format requested in NTSC norm"); display_height = 240; } else mjpeg_error_exit1 ("No norm specified, cannot determine LOVCDSTILL output size. Please use the -n option!"); } if (strcmp (optarg, MONO_KEYWORD) == 0) { output = 1; mono = 1; } if (output == 0) mjpeg_error_exit1 ("Uncorrect output keyword: %s", optarg); break; // ************** // MODE KEYOWRD // ************* case 'M': mode = 0; if (strcmp (optarg, WIDE2STD_KEYWORD) == 0) { wide = 1; mode = 1; } // developper's Testing purpose only if (strcmp (optarg, NOMMX) == 0) { #ifdef HAVE_ASM_MMX mmx = 0; #endif mode = 1; } if (strcmp (optarg, RESAMPLE) == 0) { mode = 1; algorithm = 0; } if (strcmp (optarg, BICUBIC) == 0) { mode = 1; algorithm = 1; } if (strcmp (optarg, NO_HEADER) == 0) { mode = 1; no_header = 1; } if (strncmp (optarg, RATIO_KEYWORD, 6) == 0) { if (sscanf (optarg, "RATIO_%u_%u_%u_%u", &ui1, &ui2, &ui3, &ui4) == 4) { // A coherence check will be done when the useful input sizes are known ratio = 1; mode = 1; input_width_slice = ui1; output_width_slice = ui2; input_height_slice = ui3; output_height_slice = ui4; } if (ratio == 0) mjpeg_error_exit1 ("Unconsistent RATIO keyword: %s", optarg); } if (strcmp (optarg, FAST_WIDE2VCD) == 0) { wide = 1; mode = 1; ratio = 1; input_width_slice = 2; output_width_slice = 1; input_height_slice = 2; output_height_slice = 1; vcd = 1; svcd = 0; // if user gives VCD and SVCD keyword, take last one only into account display_width = 352; if (norm == 0) { mjpeg_info ("VCD output format requested in PAL/SECAM norm"); display_height = 288; } else if (norm == 1) { mjpeg_info ("VCD output format requested in NTSC norm"); display_height = 240; } else mjpeg_error_exit1 ("No norm specified, cannot determine VCD output size. Please use the -n option!"); } if (strcmp (optarg, WIDE2VCD) == 0) { wide = 1; mode = 1; vcd = 1; svcd = 0; // if user gives VCD and SVCD keyword, take last one only into account display_width = 352; if (norm == 0) { mjpeg_info ("VCD output format requested in PAL/SECAM norm"); display_height = 288; } else if (norm == 1) { mjpeg_info ("VCD output format requested in NTSC norm"); display_height = 240; } else mjpeg_error_exit1 ("No norm specified, cannot determine VCD output size. Please use the -n option!"); } if (strcmp (optarg, FASTVCD) == 0) { mode = 1; vcd = 1; svcd = 0; // if user gives VCD and SVCD keyword, take last one only into account ratio = 1; input_width_slice = 2; output_width_slice = 1; input_height_slice = 2; output_height_slice = 1; display_width = 352; if (norm == 0) { mjpeg_info ("VCD output format requested in PAL/SECAM norm"); display_height = 288; } else if (norm == 1) { mjpeg_info ("VCD output format requested in NTSC norm"); display_height = 240; } else mjpeg_error_exit1 ("No norm specified, cannot determine VCD output size. Please use the -n option!"); } if (mode == 0) mjpeg_error_exit1 ("Uncorrect mode keyword: %s", optarg); break; // ************** // INPUT KEYOWRD // ************* case 'I': input = 0; if (strncmp (optarg, USE_KEYWORD, 4) == 0) { input = 1; if (sscanf (optarg, "USE_%ux%u+%u+%u", &ui1, &ui2, &ui3, &ui4) == 4) { // Coherence check: // every values must be multiple of 2 // and if input is interlaced, height offsets must be multiple of 4 // since U and V have half Y resolution and are interlaced // and the required zone must be inside the input size if ((ui1 % 2 == 0) && (ui2 % 2 == 0) && (ui3 % 2 == 0) && (ui4 % 2 == 0) && (ui1 + ui3 <= input_width) && (ui2 + ui4 <= input_height)) { input_useful_width = ui1; input_useful_height = ui2; input_discard_col_left = ui3; input_discard_line_above = ui4; input_discard_col_right = input_width - input_useful_width - input_discard_col_left; input_discard_line_under = input_height - input_useful_height - input_discard_line_above; input_useful = 1; } else mjpeg_error_exit1 ("Unconsistent USE keyword: %s, offsets/sizes not multiple of 2 or offset+size>input size", optarg); if (interlaced != Y4M_ILACE_NONE) { if ((input_useful_height % 4 != 0) || (input_discard_line_above % 4 != 0)) mjpeg_error_exit1 ("Unconsistent USE keyword: %s, height offset or size not multiple of 4 but input is interlaced!!", optarg); } } else mjpeg_error_exit1 ("Uncorrect USE input flag argument: %s", optarg); } if (strncmp (optarg, ACTIVE, 6) == 0) { input = 1; if (sscanf (optarg, "ACTIVE_%ux%u+%u+%u", &ui1, &ui2, &ui3, &ui4) == 4) { // Coherence check : offsets must be multiple of 2 since U and V have half Y resolution // if interlaced, height must be multiple of 4 // and the required zone must be inside the input size if ((ui1 % 2 == 0) && (ui2 % 2 == 0) && (ui3 % 2 == 0) && (ui4 % 2 == 0) && (ui1 + ui3 <= input_width) && (ui2 + ui4 <= input_height)) { input_active_width = ui1; input_active_height = ui2; input_black_col_left = ui3; input_black_line_above = ui4; input_black_col_right = input_width - input_active_width - input_black_col_left; input_black_line_under = input_height - input_active_height - input_black_line_above; input_black = 1; } else mjpeg_error_exit1 ("Unconsistent ACTIVE keyword: %s, offsets/sizes not multiple of 2 or offset+size>input size", optarg); if (interlaced != Y4M_ILACE_NONE) { if ((input_active_height % 4 != 0) || (input_black_line_above % 4 != 0)) mjpeg_error_exit1 ("Unconsistent ACTIVE keyword: %s, height offset or size not multiple of 4 but input is interlaced!!", optarg); } } else mjpeg_error_exit1 ("Uncorrect ACTIVE input flag argument: %s", optarg); } if (input == 0) mjpeg_error_exit1 ("Uncorrect input keyword: %s", optarg); break; default: break; } } // Interlacing warnings if (vcd == 1) { if ((interlaced == Y4M_ILACE_TOP_FIRST) || (interlaced == Y4M_ILACE_BOTTOM_FIRST)) mjpeg_warn ("Interlaced input frames will be downscaled to non-interlaced VCD frames\nIf quality is an issue, please consider deinterlacing input frames with yuvdeinterlace"); interlaced = Y4M_ILACE_NONE; } // Size Keyword final coherence check if ((interlaced != Y4M_ILACE_NONE) && (size_keyword == 1)) { if (display_height % 4 != 0) mjpeg_error_exit1 ("Unconsistent SIZE keyword, Height is not multiple of 4 but output interlaced!!"); } // Unspecified input variables specification if (input_useful_width == 0) input_useful_width = input_width; if (input_useful_height == 0) input_useful_height = input_height; // Ratio coherence check against input_useful size if (ratio == 1) { if ((input_useful_width % input_width_slice == 0) && (input_useful_height % input_height_slice == 0)) { output_active_width = (input_useful_width / input_width_slice) * output_width_slice; output_active_height = (input_useful_height / input_height_slice) * output_height_slice; } else mjpeg_error_exit1 ("Specified input ratios (%u and %u) does not divide input useful size (%u and %u)!", input_width_slice, input_height_slice, input_useful_width, input_useful_height); } // if USE and ACTIVE keywords were used, redefined input ACTIVE size relative to USEFUL zone if ((input_black == 1) && (input_useful == 1)) { input_black_line_above = input_black_line_above > input_discard_line_above ? input_black_line_above - input_discard_line_above : 0; input_black_line_under = input_black_line_under > input_discard_line_under ? input_black_line_under - input_discard_line_under : 0; input_black_col_left = input_black_col_left > input_discard_col_left ? input_black_col_left - input_discard_col_left : 0; input_black_col_right = input_black_col_right > input_discard_col_right ? input_black_col_right - input_discard_col_right : 0; input_active_width = input_useful_width - input_black_col_left - input_black_col_right; input_active_height = input_useful_height - input_black_line_above - input_black_line_under; if ((input_active_width == input_useful_width) && (input_active_height == input_useful_height)) input_black = 0; // black zone is not enterely inside useful zone } // Unspecified output variables specification if (output_active_width == 0) output_active_width = display_width; if (output_active_height == 0) output_active_height = display_height; // if (display_width == 0) // display_width = output_active_width; // if (display_height == 0) // display_height = output_active_height; if (wide == 1) output_active_height = (output_active_height * 3) / 4; // Common pitfall! it is 3/4 not 9/16! // Indeed, Standard ratio is 4:3, so 16:9 has an height that is 3/4 smaller than the display_height // At this point, input size, input_useful size, output_active size and display size are specified // Time for the final coherence check and black and skip initialisations // Final check output_width = output_active_width > display_width ? output_active_width : display_width; output_height = output_active_height > display_height ? output_active_height : display_height; if (interlaced == Y4M_ILACE_NONE) { if ((output_active_width % 2 !=0) || (output_active_height % 2 != 0) || (display_width % 2 != 0) || (display_height % 2 != 0)) mjpeg_error_exit1 ("Output sizes are not multiple of 2 !!! %ux%u, %ux%u being displayed", output_active_width, output_active_height, display_width, display_height); } else { if ((output_active_width % 2 != 0) || (output_active_height % 4 != 0) || (display_width % 2 != 0) || (display_height % 4 != 0)) mjpeg_error_exit1 ("Output sizes are not multiple of 2 on width and 4 on height (interlaced)! %ux%u, %ux%u being displayed", output_active_width, output_active_height, display_width, display_height); } // Skip and black initialisations // if (output_active_width > display_width) { skip = 1; skip_col = 1; // output_skip_col_right and output_skip_col_left must be even numbers output_skip_col_right = ((output_active_width - display_width) / 4)*2; output_skip_col_left = output_active_width - display_width - output_skip_col_right; } if (output_active_width < display_width) { black = 1; black_col = 1; // output_black_col_right and output_black_col_left must be even numbers output_black_col_right = ((display_width - output_active_width) / 4)*2; output_black_col_left = display_width - output_active_width - output_black_col_right; } if (output_active_height > display_height) { skip = 1; skip_line = 1; // output_skip_line_above and output_skip_line_under must be even numbers output_skip_line_above = ((output_active_height - display_height) / 4)*2; output_skip_line_under = output_active_height - display_height - output_skip_line_above; } if (output_active_height < display_height) { black = 1; black_line = 1; // output_black_line_above and output_black_line_under must be even numbers output_black_line_above = ((display_height - output_active_height) / 4)*2; output_black_line_under = display_height - output_active_height - output_black_line_above; } } // ************************************************************************************* // MAIN // ************************************************************************************* int main (int argc, char *argv[]) { int input_fd = 0; int output_fd = 1; // DDD and time use // int input_fd = open("./yuvscaler.input",O_RDONLY); // int output_fd = open("./yuvscaler.output",O_WRONLY); // DDD use int err = Y4M_OK, nb; unsigned long int i, j, h, w; long int frame_num = 0; unsigned int *height_coeff = NULL, *width_coeff = NULL; uint8_t *input = NULL, *output = NULL, *padded_input = NULL, *padded_bottom = NULL, *padded_top = NULL; uint8_t *input_y, *input_u, *input_v; uint8_t *output_y, *output_u, *output_v; uint8_t *frame_y, *frame_u, *frame_v; uint8_t **frame_y_p = NULL, **frame_u_p = NULL, **frame_v_p = NULL; // size is not yet known => pointer of pointer uint8_t *u_c_p; //u_c_p = uint8_t pointer unsigned int divider; // SPECIFIC TO BICUBIC unsigned int *in_line = NULL, *in_col = NULL, out_line, out_col; unsigned long int somme; float *a = NULL, *b = NULL; int16_t *cspline_w=NULL,*cspline_h=NULL; uint16_t width_offset=0,height_offset=0,left_offset=0,top_offset=0,right_offset=0,bottom_offset=0; uint16_t height_pad=0,width_pad=0,width_neighbors=0,height_neighbors=0; // On constate que souvent, le dernier coeff cspline est nul => // pas la peine de le prendre en compte dans les calculs // Attention ! optimisation vitesse yuvscaler_bicubic.c suppose que zero_width_neighbors=0 ou 1 seulement uint8_t zero_width_neighbors=1,zero_height_neighbors=1; float width_scale,height_scale; int16_t cspline_value = 0; int16_t *pointer; // SPECIFIC TO YUV4MPEG unsigned long int nb_pixels; y4m_frame_info_t frameinfo; y4m_stream_info_t in_streaminfo; y4m_stream_info_t out_streaminfo; y4m_ratio_t frame_rate = y4m_fps_UNKNOWN; // Initialisation of global variables that are independent of the input stream, input_file in particular handle_args_global (argc, argv); // Information output if (verbose) { mjpeg_info ("yuvscaler %s %s", PACKAGE_VERSION, yuvscaler_VERSION); mjpeg_info ("(C) 2001-2004 Xavier Biquard , yuvscaler -h for help, or man yuvscaler"); } // mjpeg tools global initialisations mjpeg_default_handler_verbosity (verbose); y4m_init_stream_info (&in_streaminfo); y4m_init_stream_info (&out_streaminfo); y4m_init_frame_info (&frameinfo); // *************************************************************** // Get video stream informations (size, framerate, interlacing, sample aspect ratio). // The in_streaminfo structure is filled in accordingly // *************************************************************** if (y4m_read_stream_header (input_fd, &in_streaminfo) != Y4M_OK) mjpeg_error_exit1 ("Could'nt read YUV4MPEG header!"); input_width = y4m_si_get_width (&in_streaminfo); input_height = y4m_si_get_height (&in_streaminfo); frame_rate = y4m_si_get_framerate (&in_streaminfo); interlaced = y4m_si_get_interlace (&in_streaminfo); // *************************************************************** // INITIALISATIONS // Norm determination from header (this has precedence over user's specification through the -n flag) if (Y4M_RATIO_EQL (frame_rate, y4m_fps_PAL)) norm = 0; if (Y4M_RATIO_EQL (frame_rate, y4m_fps_NTSC)) norm = 1; if (norm < 0) { mjpeg_warn ("Could not infer norm (PAL/SECAM or NTSC) from input data (frame size=%dx%d, frame rate=%d:%d fps)!!", input_width, input_height, frame_rate.n, frame_rate.d); } // Deal with args that depend on input stream handle_args_dependent (argc, argv); // Scaling algorithm determination if ((algorithm == 0) || (algorithm == -1)) { // Coherences check: resample can only downscale not upscale if ((input_useful_width < output_active_width) || (input_useful_height < output_active_height)) { if (algorithm == 0) mjpeg_info ("Resampling algorithm can only downscale, not upscale => switching to bicubic algorithm"); algorithm = 1; } else algorithm = 0; } // USER'S INFORMATION OUTPUT yuvscaler_print_information (in_streaminfo, frame_rate); divider = pgcd (input_useful_width, output_active_width); input_width_slice = input_useful_width / divider; output_width_slice = output_active_width / divider; mjpeg_debug ("divider,i_w_s,o_w_s = %d,%d,%d", divider, input_width_slice, output_width_slice); divider = pgcd (input_useful_height, output_active_height); input_height_slice = input_useful_height / divider; output_height_slice = output_active_height / divider; mjpeg_debug ("divider,i_w_s,o_w_s = %d,%d,%d", divider, input_height_slice, output_height_slice); diviseur = input_height_slice * input_width_slice; mjpeg_debug ("Diviseur=%ld", diviseur); mjpeg_info ("Scaling ratio for width is %u to %u", input_width_slice, output_width_slice); mjpeg_info ("and is %u to %u for height", input_height_slice, output_height_slice); // Now that we know about scaling ratios, we can optimize treatment of an active input zone: // we must also check final new size is multiple of 2 on width and 2 or 4 on height if (input_black == 1) { if (((nb = input_black_line_above / input_height_slice) > 0) && ((nb * input_height_slice) % 2 == 0)) { if (interlaced == Y4M_ILACE_NONE) { input_useful = 1; black = 1; black_line = 1; output_black_line_above += nb * output_height_slice; input_black_line_above -= nb * input_height_slice; input_discard_line_above += nb * input_height_slice; } if ((interlaced != Y4M_ILACE_NONE) && ((nb * input_height_slice) % 4 == 0)) { input_useful = 1; black = 1; black_line = 1; output_black_line_above += nb * output_height_slice; input_black_line_above -= nb * input_height_slice; input_discard_line_above += nb * input_height_slice; } } if (((nb = input_black_line_under / input_height_slice) > 0) && ((nb * input_height_slice) % 2 == 0)) { if (interlaced == Y4M_ILACE_NONE) { input_useful = 1; black = 1; black_line = 1; output_black_line_under += nb * output_height_slice; input_black_line_under -= nb * input_height_slice; input_discard_line_under += nb * input_height_slice; } if ((interlaced != Y4M_ILACE_NONE) && ((nb * input_height_slice) % 4 == 0)) { input_useful = 1; black = 1; black_line = 1; output_black_line_under += nb * output_height_slice; input_black_line_under -= nb * input_height_slice; input_discard_line_under += nb * input_height_slice; } } if (((nb = input_black_col_left / input_width_slice) > 0) && ((nb * input_height_slice) % 2 == 0)) { input_useful = 1; black = 1; black_col = 1; output_black_col_left += nb * output_width_slice; input_black_col_left -= nb * input_width_slice; input_discard_col_left += nb * input_width_slice; } if (((nb = input_black_col_right / input_width_slice) > 0) && ((nb * input_height_slice) % 2 == 0)) { input_useful = 1; black = 1; black_col = 1; output_black_col_right += nb * output_width_slice; input_black_col_right -= nb * input_width_slice; input_discard_col_right += nb * input_width_slice; } input_useful_height = input_height - input_discard_line_above - input_discard_line_under; input_useful_width = input_width - input_discard_col_left - input_discard_col_right; input_active_width = input_useful_width - input_black_col_left - input_black_col_right; input_active_height = input_useful_height - input_black_line_above - input_black_line_under; if ((input_active_width == input_useful_width) && (input_active_height == input_useful_height)) input_black = 0; // black zone doesn't go beyong useful zone output_active_width = (input_useful_width / input_width_slice) * output_width_slice; output_active_height = (input_useful_height / input_height_slice) * output_height_slice; // USER'S INFORMATION OUTPUT mjpeg_info (" --- Newly speed optimized parameters ---"); yuvscaler_print_information (in_streaminfo, frame_rate); } // Take care of the case where ratios are 1:1 and 1:1 => in the resample algorithm category by convention if ((output_height_slice == 1) && (input_height_slice == 1) && (output_width_slice == 1) && (input_width_slice == 1)) algorithm =0; // RESAMPLE RESAMPLE RESAMPLE if (algorithm == 0) { // SPECIFIC // Is a specific downscaling speed enhanced treatment available? if ((output_width_slice == 1) && (input_width_slice == 1)) specific = 5; if ((output_width_slice == 1) && (input_width_slice == 1) && (input_height_slice == 4) && (output_height_slice == 3)) specific = 7; if ((input_height_slice == 2) && (output_height_slice == 1)) specific = 3; if ((output_height_slice == 1) && (input_height_slice == 1)) specific = 1; if ((output_height_slice == 1) && (input_height_slice == 1) && (output_width_slice == 2) && (input_width_slice == 3)) specific = 6; if ((output_height_slice == 1) && (input_height_slice == 1) && (output_width_slice == 1) && (input_width_slice == 1)) specific = 4; if ((input_height_slice == 2) && (output_height_slice == 1) && (input_width_slice == 2) && (output_width_slice == 1)) specific = 2; if ((input_height_slice == 8) && (output_height_slice == 3)) specific = 9; if ((input_height_slice == 8) && (output_height_slice == 3) && (input_width_slice == 2) && (output_width_slice == 1)) specific = 8; if (specific) mjpeg_info ("Specific downscaling routing number %u", specific); // To determine scaled value of pixels in the case of the resample algorithm, we have to divide a long int by // the long int "diviseur". So, to speed up downscaling, we tabulate all possible results of this division // using the divide vector and the function yuvscaler_nearest_integer_division. if (! (divide = (uint8_t *) malloc ((1 + 255 * diviseur) * sizeof (uint8_t) + ALIGNEMENT))) mjpeg_error_exit1 ("Could not allocate memory for divide table. STOP!"); mjpeg_debug ("before alignement: divide=%p", divide); // alignement instructions if (((unsigned long) divide % ALIGNEMENT) != 0) divide = (uint8_t *) ((((unsigned long) divide / ALIGNEMENT) + 1) * ALIGNEMENT); mjpeg_debug ("after alignement: divide=%p", divide); u_c_p = divide; for (i = 0; i <= 255 * diviseur; i++) *(u_c_p++) = yuvscaler_nearest_integer_division (i, diviseur); // Calculate averaging coefficient // For the height height_coeff = malloc ((input_height_slice + 1) * output_height_slice * sizeof (unsigned int)); average_coeff (input_height_slice, output_height_slice, height_coeff); // For the width width_coeff = malloc ((input_width_slice + 1) * output_width_slice * sizeof (unsigned int)); average_coeff (input_width_slice, output_width_slice, width_coeff); } // END OF RESAMPLE RESAMPLE RESAMPLE // BICUBIC BICUBIC BICUBIC if (algorithm == 1) { // SPECIFIC // Is a specific downscaling speed enhanced treatment available? // We only downscale on height, not width. // Ex: 16/9 to 4/3 conversion if ((output_width_slice == 1) && (input_width_slice == 1)) specific = 5; // We only downscale on width, not height // Ex: Full size to SVCD if ((output_height_slice == 1) && (input_height_slice == 1)) specific = 1; if (specific) mjpeg_info ("Specific downscaling routing number %u", specific); // specific=0; // Let us tabulate several values which are explained below: // // Given the scaling factor "height_scale" on height and "width_scale" on width, to an output pixel of coordinates (out_col,out_line) // corresponds an input pixel of coordinates (in_col,in_line), where in_col = out_col/width_scale and in_line = out_line/height_scale. // As pixel coordinates are integer values, we take for in_col and out_col the nearest smaller integer // value: in_col = floor(out_col/width_scale) and in_line = floor(out_line/height_scale). // The input pixel of coordinates (in_col,in_line) is called the base input pixel // Thus, we make an error conventionnally named "b" for columns and "a" for lines // with b = out_col/width_scale - floor(out_col/width_scale) and a = out_line/height_scale - floor(out_line/height_scale). // Please note that a and b are inside range [0,1[. // // For upscaling along w (resp. h), we need to take into account the 4 nearest neighbors along w (resp. h) of the base input pixel. // For downscaling along w (resp. h), we need to take into account AT LEAST 6 nearest neighbors of the base input pîxel. // And the real number of neighbors pixel from the base input pixel to be taken into account depends on the scaling ratios. // We have to take into account "width_neighbors" neighbors on the width and "height_neighbors" on the height; // with width_neighbors = 2*nearest_higher_integer(2/width_scale), or 4 if upscaling (output_width_slice>input_width_slice) // and width_offset=(width_neighbors/2)-1; // with height_neighbors = 2*nearest_higher_integer(2/height_scale), or 4 if upscaling (output_height_slice>input_height_slice) // and height_offset=(height_neighbors/2)-1; // // ***************** // The general formula giving the value of the output pixel as a function of the input pixels is: // OutputPixel(out_col,out_line)= // Sum(h=-height_offset,...(height_neigbors-height_offset-1))Sum(w=-width_offset,...(width_neigbors-width_offset-1)) // InputPixel(in_col+w,in_line+h)*BicubicCoefficient((b-w)*scale_width)*BicubicCoefficient((a-h)*scale_height)*scale_height*scale_width // ***************** // Please note that [theoretically] (a-h)*scale_height is [-2:2], as well as (b-w)*scale_width. // But, as height_neigbors is the nearest higher integer, the practical range for "(a-h)*scale_height" and "(b-w)*scale_width" is // extended from theorital [-2:2] to [-3:3] => "(a-h)*scale_height" and "(b-w)*scale_width" are considered 0 outside of [-2:2]. // Please note also that for upscaling only, scale_height and scale_width are artifially taken as 1.0 in the formula. // // For an easier implementation, it is preferable that h and w start from 0. Therefore, in the general formula, we will replace // "h" by "h-height_offset" and "w" by "w-width_offset". // // Moreover, the output pixel value depends on at least the 4x4 nearest neighbors from the base input pixel in the input image. // As a consequence, if the base input pixel is at on the border of the image, the bicubic algorithm will try to find values // outside the input image => to avoid this, we will pad the input image height_offset pixel on the top, width_offset pixels on the left, // (and right_offset pixels on the right and bottom_offset pixels at the bottom). // Therefore, in the general formula, we will replace InputPixel(x,y) by PaddedInputPixel(x+width_offset,y+height_offset). // // ***************** // Finally, the general formula may be rewritten as: // OutputPixel(out_col,out_line)= // Sum(h=0,...(height_neigbors-1))Sum(w=0...(width_neigbors-1)) // PaddedInputPixel(in_col+w,in_line+h)*BicubicCoefficient((b-w+width_offset)*scale_width)*BicubicCoefficient((a-h+height_offset)*scale_height)*scale_height*scale_width // ***************** // // // ***************** // IMPLEMENTATION // ***************** // To insure a fast implementation of the general formula, we will pre-calculate all possible values of // BicubicCoefficient((b-w+width_offset)*scale_width)*scale_width, and tabulate them as cspline_w: // cspline_w[w,out_col]=BicubicCoefficient((b[out_col]-w+width_offset)*scale_width)*scale_width. // And the same stands for height: // cspline_h[h,out_line]=BicubicCoefficient((a[out_line]-h+height_offset)*scale_height)*scale_height // // To be continued ... height_scale=(float)output_height_slice/(float)input_height_slice; if (height_scale>1.0) height_scale=1.0; width_scale=(float)output_width_slice/(float)input_width_slice; if (width_scale>1.0) width_scale=1.0; width_neighbors = (2 * input_width_slice ) / output_width_slice; if (((2 * input_width_slice ) % output_width_slice)!=0) width_neighbors++; width_neighbors*=2; if (width_neighbors < 4) width_neighbors = 4; width_offset = left_offset = width_neighbors/2-1; width_pad=width_neighbors - 1; right_offset=width_neighbors/2; height_neighbors = (2 * input_height_slice ) / output_height_slice; if (((2 * input_height_slice ) % output_height_slice)!=0) height_neighbors++; height_neighbors*=2; if (height_neighbors < 4) height_neighbors = 4; height_offset = top_offset = height_neighbors/2-1; height_pad=height_neighbors - 1; bottom_offset=height_neighbors/2; mjpeg_debug("height_scale=%f, width_scale=%f, width_neighbors=%d, height_neighbors=%d",height_scale,width_scale,width_neighbors,height_neighbors); // Memory allocations #ifdef HAVE_ASM_MMX if (!(mmx_res = (int32_t *) malloc (2 * sizeof (int32_t) + ALIGNEMENT))) mjpeg_error_exit1 ("Could not allocate memory for mmx registers. STOP!"); // alignement instructions if (((unsigned long int) mmx_res % ALIGNEMENT) != 0) mmx_res = (int32_t *) ((((unsigned long int) mmx_res / ALIGNEMENT) + 1) * ALIGNEMENT); if (mmx==1) { if (width_neighbors <= MAXWIDTHNEIGHBORS) { mjpeg_info("MMX accelerated treatment activated"); mmx = 1; } else { mmx=0; mjpeg_warn("MMX accelerated treatment not available for downscaling ratio larger than 4 to 1"); mjpeg_warn("If you still want to use an MMX treatment (not really useful for such a large downscaling ratio"); mjpeg_warn("please use multiple yuvscaler downscaling to achieve the desired downscaling ratio"); } } #endif // Il faudrait peut-être aligner correctement tous ces pointeurs, en particulier cspline_w_neighbors et cspline_h_neighbors // qui sont amplement utilisés dans les routines de scaling => il faut aussi aligner cspline_w et cspline_h if ( !(cspline_w = (int16_t *) malloc ( width_neighbors * output_active_width * sizeof (int16_t))) || !(cspline_h = (int16_t *) malloc ( height_neighbors * output_active_height * sizeof (int16_t))) || !(in_col = (unsigned int *) malloc ( output_active_width * sizeof (unsigned int))) || !(b = (float *) malloc ( output_active_width * sizeof (float))) || !(in_line = (unsigned int *) malloc ( output_active_height * sizeof (unsigned int))) || !(a = (float *) malloc ( output_active_height * sizeof (float))) ) mjpeg_error_exit1 ("Could not allocate memory for bicubic tables. STOP!"); // Initialisation of bicubic tables pointer=cspline_h; for (out_line = 0; out_line < output_active_height; out_line++) { in_line[out_line] = (out_line * input_height_slice) / output_height_slice; // mjpeg_debug("in_line[%u]=%u",out_line,in_line[out_line]); a[out_line] = (float) ((out_line * input_height_slice) % output_height_slice) / (float) output_height_slice; somme=0; for (h=0;h display_width, line per line frame output for each component for (i = 0; i < display_height; i++) { if (y4m_write (output_fd, frame_y_p[i], display_width) != Y4M_OK) goto out_error; } for (i = 0; i < display_height / 2; i++) { if (y4m_write (output_fd, frame_u_p[i], display_width / 2) != Y4M_OK) goto out_error; } for (i = 0; i < display_height / 2; i++) { if (y4m_write (output_fd, frame_v_p[i], display_width / 2) != Y4M_OK) goto out_error; } } } } // End of master loop => no more frame in stdin if (err != Y4M_ERR_EOF) mjpeg_error_exit1 ("Couldn't read frame number %ld!", frame_num); else mjpeg_info ("Normal exit: end of stream with frame number %ld!", frame_num); y4m_fini_stream_info (&in_streaminfo); y4m_fini_stream_info (&out_streaminfo); y4m_fini_frame_info (&frameinfo); return 0; out_error: mjpeg_error_exit1 ("Unable to write to output - aborting!"); return 1; } // ************************************************************************************* unsigned int pgcd (unsigned int num1, unsigned int num2) { // Calculates the biggest common divider between num1 and num2, after Euclid's // pgcd(a,b)=pgcd(b,a%b) // My thanks to Chris Atenasio unsigned int c, bigger, smaller; if (num2 < num1) { smaller = num2; bigger = num1; } else { smaller = num1; bigger = num2; } while (smaller) { c = bigger % smaller; bigger = smaller; smaller = c; } return (bigger); } // ************************************************************************************* // if ((output_width_slice == 1) && (input_width_slice == 1) // && (input_height_slice == 4) && (output_height_slice == 3)) // specific = 7; // if ((output_height_slice == 1) && (input_height_slice == 1) // && (output_width_slice == 2) && (input_width_slice == 3)) // specific = 6; // if ((input_height_slice == 2) && (output_height_slice == 1)) // specific = 3; // Full size to VCD // if ((input_height_slice == 2) && (output_height_slice == 1) // && (input_width_slice == 2) && (output_width_slice == 1)) // specific = 2; // if ((input_height_slice == 8) && (output_height_slice == 3)) // specific = 9; // if ((input_height_slice == 8) && (output_height_slice == 3) // && (input_width_slice == 2) && (output_width_slice == 1)) // specific = 8; // alignement instructions /* if (((unsigned int) cspline_w % ALIGNEMENT) != 0) cspline_w = (int16_t *) ((((unsigned int) cspline_w / ALIGNEMENT) + 1) * ALIGNEMENT); if (((unsigned int) cspline_h % ALIGNEMENT) != 0) cspline_h = (int16_t *) ((((unsigned int) cspline_h / ALIGNEMENT) + 1) * ALIGNEMENT); if (((unsigned int) cspline_w_neighbors % ALIGNEMENT) != 0) cspline_w_neighbors = (int16_t **) ((((unsigned int) cspline_w_neighbors / ALIGNEMENT) + 1) * ALIGNEMENT); if (((unsigned int) cspline_h_neighbors % ALIGNEMENT) != 0) cspline_h_neighbors = (int16_t **) ((((unsigned int) cspline_h_neighbors / ALIGNEMENT) + 1) * ALIGNEMENT); */ /* * Local variables: * tab-width: 8 * indent-tabs-mode: nil * End: */ mjpegtools-2.1.0/yuvscaler/yuvscaler_bicubic.c0000644000175000017500000007613310323630014022071 0ustar glowwormglowworm/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ // Version of the 25/05/2003 // Copyright X. Biquard xbiquard@free.fr // Great speed Warning : function mjpeg_debug implies an implicit test => may slow down a lot the execution // of the program. // SIMD accelerated multiplications with csplineh not possible since value to be multiply do not stand // in int16_t, but in int32_t // Maybe possible in SSE since xmm registers of 128 bits available // IL FAUT NETTOYER LE HEADER : PAS BESOIN DE TOUTES CES VARIABLES GLOBALES A LA CON #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include "yuv4mpeg.h" #include "mjpeg_types.h" #include "yuvscaler.h" #include "../utils/mmx.h" extern unsigned int output_active_width; extern unsigned int output_active_height; extern unsigned int output_width; extern unsigned int input_width; extern unsigned int input_useful_width; extern unsigned int input_useful_height; extern unsigned int specific; // Defines #define FLOAT2INTEGERPOWER 11 #define FLOAT2INTOFFSET 1024 #define DBLEFLOAT2INT 22 #define DBLEFLOAT2INTOFFSET 2097152 // MMX test #ifdef HAVE_ASM_MMX extern int32_t *mmx_res; extern int mmx; // =1 for mmx activated #endif // MMX test extern int32_t *intermediate; // ************************************************************************************* int cubic_scale (uint8_t * padded_input, uint8_t * output, unsigned int *in_col, unsigned int *in_line, int16_t *cspline_w, uint16_t width_neighbors, uint8_t zero_width_neighbors, int16_t *cspline_h, uint16_t height_neighbors, uint8_t zero_height_neighbors, unsigned int half) { // Warning: because cubic-spline values may be <0 or >1.0, a range test on value is mandatory unsigned int local_output_active_width = output_active_width >> half; unsigned int local_output_active_height = output_active_height >> half; unsigned int local_output_width = output_width >> half; unsigned int local_input_useful_height = input_useful_height >> half; unsigned int local_input_useful_width = input_useful_width >> half; unsigned int local_padded_height = local_input_useful_height + height_neighbors -1; unsigned int local_padded_width = local_input_useful_width + width_neighbors -1; unsigned int out_line, out_col,w,h; unsigned int *in_line_p,*in_col_p; int16_t output_offset; uint8_t *output_p,*line,*line_begin,*line_0; int16_t *cspline_wp,*cspline_hp,*cspline_hp0; int32_t value=0,value1=0,*intermediate_p,*inter_begin; // mjpeg_debug ("Start of cubic_scale "); output_p = output; output_offset = local_output_width-local_output_active_width; /* *INDENT-OFF* */ switch(specific) { case 0: { // First scale along the Width, not the height width_neighbors-=zero_width_neighbors; height_neighbors-=zero_height_neighbors; intermediate_p=intermediate; line_0 = padded_input; for (out_line = 0; out_line < local_padded_height; out_line++) { cspline_wp=cspline_w; in_col_p=in_col; for (out_col = 0; out_col < local_output_active_width; out_col++) { line = line_0 + *(in_col_p++); value1=*(line++)*(*(cspline_wp++)); for (w=1;w> DBLEFLOAT2INT; if (value > 255) *(output_p++) = 255; else *(output_p++) = (uint8_t) value; } } // last out_col to be treated => cspline_hp0 incremented => we use the C "++" facility value1 = *(inter_begin)*(*(cspline_hp0++)); for (h=1;h> DBLEFLOAT2INT; if (value > 255) *(output_p++) = 255; else *(output_p++) = (uint8_t) value; } // a line on output is now finished. We jump to the beginning of the next line output_p+=output_offset; } } break; case 1: /* #ifdef HAVE_ASM_MMX if (mmx==1) { // We only downscale on width, not height emms(); pxor_r2r(mm7,mm7); // only zeros in mm7 line_0=padded_input; for (out_line = 0; out_line < local_output_active_height; out_line++) { cspline_wp=cspline_w; in_col_p=in_col; for (out_col = 0; out_col < local_output_active_width; out_col++) { line = line_0 + *(in_col_p++); switch(width_neighbors) { // NB : c'est l'opération movq_r2m qui coute le plus en temps, seulement pour la première !!! case 4: movq_m2r(*cspline_wp,mm0); movq_m2r(*(line),mm6); punpcklbw_r2r(mm7,mm6); pmaddwd_r2r(mm0,mm6); movq_r2m(mm6,*(mmx_t *)mmx_res); value1=mmx_res[0]+mmx_res[1]; break; case 6: // cspline_w in mm0 and mm1 movq_m2r(*cspline_wp,mm0); movq_m2r(*(cspline_wp+4),mm1); // 4 pixels in mm6 and next 4 in mm5 movq_m2r(*(line),mm6); // __m64 mm6= _mm_unpacklo_pi16(mm6, mm7); punpcklbw_r2r(mm7,mm6); movq_m2r(*(line+4),mm5); punpcklbw_r2r(mm7,mm5); // multiply and add => these take more than one cycle and may be done in parallel pmaddwd_r2r(mm0,mm6); movq_r2m(mm6,*(mmx_t *)mmx_res); // movntq_r2m(mm6,*(mmx_t *)mmx_res); value1=mmx_res[0]+mmx_res[1]; pmaddwd_r2r(mm1,mm5); movq_r2m(mm5,*(mmx_t *)mmx_res); // movntq_r2m(mm5,*(mmx_t *)mmx_res); value1+=mmx_res[0]; break; case 8: movq_m2r(*cspline_wp,mm0); movq_m2r(*(cspline_wp+4),mm1); movq_m2r(*(line),mm6); punpcklbw_r2r(mm7,mm6); pmaddwd_r2r(mm0,mm6); movq_r2m(mm6,*(mmx_t *)mmx_res); value1=mmx_res[0]+mmx_res[1]; movq_m2r(*(line+4),mm6); punpcklbw_r2r(mm7,mm6); pmaddwd_r2r(mm1,mm6); movq_r2m(mm6,*(mmx_t *)mmx_res); value1+=mmx_res[0]+mmx_res[1]; break; case 10: movq_m2r(*cspline_wp,mm0); movq_m2r(*(cspline_wp+4),mm1); movq_m2r(*(cspline_wp+8),mm2); movq_m2r(*(line),mm6); punpcklbw_r2r(mm7,mm6); pmaddwd_r2r(mm0,mm6); movq_r2m(mm6,*(mmx_t *)mmx_res); value1=mmx_res[0]+mmx_res[1]; movq_m2r(*(line+4),mm6); punpcklbw_r2r(mm7,mm6); pmaddwd_r2r(mm1,mm6); movq_r2m(mm6,*(mmx_t *)mmx_res); value1+=mmx_res[0]+mmx_res[1]; movq_m2r(*(line+8),mm6); punpcklbw_r2r(mm7,mm6); pmaddwd_r2r(mm2,mm6); movq_r2m(mm6,*(mmx_t *)mmx_res); value1+=mmx_res[0]; break; case 12: movq_m2r(*cspline_wp,mm0); movq_m2r(*(cspline_wp+4),mm1); movq_m2r(*(cspline_wp+8),mm2); movq_m2r(*(line),mm6); punpcklbw_r2r(mm7,mm6); pmaddwd_r2r(mm0,mm6); movq_r2m(mm6,*(mmx_t *)mmx_res); value1=mmx_res[0]+mmx_res[1]; movq_m2r(*(line+4),mm6); punpcklbw_r2r(mm7,mm6); pmaddwd_r2r(mm1,mm6); movq_r2m(mm6,*(mmx_t *)mmx_res); value1+=mmx_res[0]+mmx_res[1]; movq_m2r(*(line+8),mm6); punpcklbw_r2r(mm7,mm6); pmaddwd_r2r(mm2,mm6); movq_r2m(mm6,*(mmx_t *)mmx_res); value1+=mmx_res[0]+mmx_res[1]; break; case 14: movq_m2r(*cspline_wp,mm0); movq_m2r(*(cspline_wp+4),mm1); movq_m2r(*(cspline_wp+8),mm2); movq_m2r(*(cspline_wp+12),mm3); movq_m2r(*(line),mm6); punpcklbw_r2r(mm7,mm6); pmaddwd_r2r(mm0,mm6); movq_r2m(mm6,*(mmx_t *)mmx_res); value1=mmx_res[0]+mmx_res[1]; movq_m2r(*(line+4),mm6); punpcklbw_r2r(mm7,mm6); pmaddwd_r2r(mm1,mm6); movq_r2m(mm6,*(mmx_t *)mmx_res); value1+=mmx_res[0]+mmx_res[1]; movq_m2r(*(line+8),mm6); punpcklbw_r2r(mm7,mm6); pmaddwd_r2r(mm2,mm6); movq_r2m(mm6,*(mmx_t *)mmx_res); value1+=mmx_res[0]+mmx_res[1]; movq_m2r(*(line+12),mm6); punpcklbw_r2r(mm7,mm6); pmaddwd_r2r(mm3,mm6); movq_r2m(mm6,*(mmx_t *)mmx_res); value1+=mmx_res[0]; break; case 16: movq_m2r(*cspline_wp,mm0); movq_m2r(*(cspline_wp+4),mm1); movq_m2r(*(cspline_wp+8),mm2); movq_m2r(*(cspline_wp+12),mm3); movq_m2r(*(line),mm6); punpcklbw_r2r(mm7,mm6); pmaddwd_r2r(mm0,mm6); movq_r2m(mm6,*(mmx_t *)mmx_res); value1=mmx_res[0]+mmx_res[1]; movq_m2r(*(line+4),mm6); punpcklbw_r2r(mm7,mm6); pmaddwd_r2r(mm1,mm6); movq_r2m(mm6,*(mmx_t *)mmx_res); value1+=mmx_res[0]+mmx_res[1]; movq_m2r(*(line+8),mm6); punpcklbw_r2r(mm7,mm6); pmaddwd_r2r(mm2,mm6); movq_r2m(mm6,*(mmx_t *)mmx_res); value1+=mmx_res[0]+mmx_res[1]; movq_m2r(*(line+12),mm6); punpcklbw_r2r(mm7,mm6); pmaddwd_r2r(mm3,mm6); movq_r2m(mm6,*(mmx_t *)mmx_res); value1+=mmx_res[0]+mmx_res[1]; break; default: mjpeg_error_exit1("width neighbors = %d, is not supported inside cubic-scale function",width_neighbors); break; } cspline_wp+=width_neighbors; if (value1 < 0) *(output_p++) = 0; else { value = (value1 + FLOAT2INTOFFSET) >> FLOAT2INTEGERPOWER; if (value > 255) *(output_p++) = 255; else *(output_p++) = (uint8_t) value; } } // a line on output is now finished. We jump to the beginning of the next line output_p+=output_offset; line_0+=local_padded_width; } } else #endif */ { // We only scale on width, not height width_neighbors-=zero_width_neighbors; height_neighbors-=zero_height_neighbors; line_0=padded_input; for (out_line = 0; out_line < local_output_active_height; out_line++) { cspline_wp=cspline_w; in_col_p=in_col; for (out_col = 0; out_col < local_output_active_width; out_col++) { line = line_0 + *(in_col_p++); value1=*(line++)*(*(cspline_wp++)); for (w=1;w> FLOAT2INTEGERPOWER; if (value > 255) *(output_p++) = 255; else *(output_p++) = (uint8_t) value; } } // a line on output is now finished. We jump to the beginning of the next line output_p+=output_offset; line_0+=local_padded_width; } } break; case 5: // We only scale on height, not width { width_neighbors-=zero_width_neighbors; height_neighbors-=zero_height_neighbors; cspline_hp0=cspline_h; in_line_p=in_line; for (out_line = 0; out_line < local_output_active_height; out_line++) { line_begin=padded_input + *(in_line_p++) * local_padded_width; for (out_col = 0; out_col < local_output_active_width-1; out_col++) { cspline_hp=cspline_hp0; value1 = *(line_begin)*(*(cspline_hp++)); for (h=1;h> FLOAT2INTEGERPOWER; if (value > 255) *(output_p++) = 255; else *(output_p++) = (uint8_t) value; } } // last out_col to be treated => cspline_hp0 incremented => we use the C "++" facility value1 = *(line_begin)*(*(cspline_hp0++)); for (h=1;h> FLOAT2INTEGERPOWER; if (value > 255) *(output_p++) = 255; else *(output_p++) = (uint8_t) value; } // a line on output is now finished. We jump to the beginning of the next line output_p+=output_offset; } } break; } /* *INDENT-ON* */ // mjpeg_debug ("End of cubic_scale"); return (0); } // ************************************************************************************* // ************************************************************************************* int cubic_scale_interlaced (uint8_t * padded_top, uint8_t * padded_bottom, uint8_t * output, unsigned int *in_col, unsigned int *in_line, int16_t * cspline_w, uint16_t width_neighbors, uint8_t zero_width_neighbors, int16_t * cspline_h, uint16_t height_neighbors, uint8_t zero_height_neighbors, unsigned int half) { // Warning: because cubic-spline values may be <0 or >1.0, a range test on value is mandatory unsigned int local_output_active_width = output_active_width >> half; unsigned int local_output_active_height = output_active_height >> half; unsigned int local_output_width = output_width >> half; unsigned int local_input_useful_height = input_useful_height >> half; unsigned int local_input_useful_width = input_useful_width >> half; unsigned int local_padded_height = local_input_useful_height + height_neighbors -1; unsigned int local_padded_width = local_input_useful_width + width_neighbors -1; unsigned int out_line, out_col,w,h; unsigned int *in_line_p,*in_col_p; int16_t output_offset; uint8_t *output_p,*line,*line_begin,*line_top,*line_bot; int16_t *cspline_wp,*cspline_hp,*cspline_hp0; int32_t value=0,value1=0,*inter_begin,*intermediate_p,*intermediate_top_p,*intermediate_bot_p;; // mjpeg_debug ("Start of cubic_scale "); output_p = output; output_offset = local_output_width-local_output_active_width; width_neighbors-=zero_width_neighbors; height_neighbors-=zero_height_neighbors; /* *INDENT-OFF* */ switch(specific) { case 0: { // First scale along the Width, not the height // TOP, then BOTTOM intermediate_p=intermediate; line_top = padded_top; for (out_line = 0; out_line < (local_padded_height>>1); out_line++) { cspline_wp=cspline_w; in_col_p=in_col; for (out_col = 0; out_col < local_output_active_width; out_col++) { line = line_top + *(in_col_p++); value1=*(line++)*(*(cspline_wp++)); for (w=1;w>1); out_line++) { cspline_wp=cspline_w; in_col_p=in_col; for (out_col = 0; out_col < local_output_active_width; out_col++) { line = line_bot + *(in_col_p++); value1=*(line++)*(*(cspline_wp++)); for (w=1;w>1)*local_output_active_width; cspline_hp0=cspline_h; in_line_p=in_line; for (out_line = 0; out_line < (local_output_active_height>>1); out_line++) { // TOP line inter_begin=intermediate_top_p + *(in_line_p) * local_output_active_width; for (out_col = 0; out_col < local_output_active_width; out_col++) { cspline_hp=cspline_hp0; value1 = *(inter_begin)*(*(cspline_hp++)); for (h=1;h> DBLEFLOAT2INT; if (value > 255) *(output_p++) = 255; else *(output_p++) = (uint8_t) value; } } // a top line on output is now finished. We jump to the beginning of the next bottom line output_p+=output_offset; // BOTTOM line inter_begin=intermediate_bot_p + *(in_line_p++) * local_output_active_width; for (out_col = 0; out_col < local_output_active_width-1; out_col++) { cspline_hp=cspline_hp0; value1 = *(inter_begin)*(*(cspline_hp++)); for (h=1;h> DBLEFLOAT2INT; if (value > 255) *(output_p++) = 255; else *(output_p++) = (uint8_t) value; } } // last out_col to be treated => cspline_hp0 incremented => we use the C "++" facility value1 = *(inter_begin)*(*(cspline_hp0++)); for (h=1;h> DBLEFLOAT2INT; if (value > 255) *(output_p++) = 255; else *(output_p++) = (uint8_t) value; } // a bottom line on output is now finished. We jump to the beginning of the next top line output_p+=output_offset; } } break; case 1: // We only scale on width, not height { line_top=padded_top; line_bot=padded_bottom; for (out_line = 0; out_line < (local_output_active_height>>1); out_line++) { // TOP LINE cspline_wp=cspline_w; in_col_p=in_col; for (out_col = 0; out_col < local_output_active_width; out_col++) { line = line_top + *(in_col_p++); value1=*(line++)*(*(cspline_wp++)); for (w=1;w> FLOAT2INTEGERPOWER; if (value > 255) *(output_p++) = 255; else *(output_p++) = (uint8_t) value; } } // a top line on output is now finished. We jump to the beginning of the next bottom line output_p+=output_offset; line_top+=local_padded_width; // BOTTOM LINE cspline_wp=cspline_w; in_col_p=in_col; for (out_col = 0; out_col < local_output_active_width; out_col++) { line = line_bot + *(in_col_p++); value1=*(line++)*(*(cspline_wp++)); for (w=1;w> FLOAT2INTEGERPOWER; if (value > 255) *(output_p++) = 255; else *(output_p++) = (uint8_t) value; } } // a bottom line on output is now finished. We jump to the beginning of the next top line output_p+=output_offset; line_bot+=local_padded_width; } } break; case 5: // We only scale on height, not width { cspline_hp0=cspline_h; in_line_p=in_line; for (out_line = 0; out_line < (local_output_active_height>>1); out_line++) { // TOP LINE line_begin=padded_top + *(in_line_p) * local_padded_width; for (out_col = 0; out_col < local_output_active_width; out_col++) { cspline_hp=cspline_hp0; value1 = *(line_begin)*(*(cspline_hp++)); for (h=1;h> FLOAT2INTEGERPOWER; if (value > 255) *(output_p++) = 255; else *(output_p++) = (uint8_t) value; } } // a top line on output is now finished. We jump to the beginning of the next bottom line output_p+=output_offset; // BOTTTOM LINE line_begin=padded_bottom + *(in_line_p++) * local_padded_width; for (out_col = 0; out_col < local_output_active_width-1; out_col++) { cspline_hp=cspline_hp0; value1 = *(line_begin)*(*(cspline_hp++)); for (h=1;h> FLOAT2INTEGERPOWER; if (value > 255) *(output_p++) = 255; else *(output_p++) = (uint8_t) value; } } // last out_col to be treated => cspline_hp0 incremented => we use the C "++" facility value1 = *(line_begin)*(*(cspline_hp0++)); for (h=1;h> FLOAT2INTEGERPOWER; if (value > 255) *(output_p++) = 255; else *(output_p++) = (uint8_t) value; } // a bottom line on output is now finished. We jump to the beginning of the next top line output_p+=output_offset; } } break; } /* *INDENT-ON* */ // mjpeg_debug ("End of cubic_scale"); return (0); } // ************************************************************************************* // // ************************************************************************************* int16_t cubic_spline (float x, unsigned int multiplicative) { // Implementation of the Mitchell-Netravalli cubic spline, with recommended parameters B and C // [after Reconstruction filters in Computer Graphics by P. Mitchel and N. Netravali : Computer Graphics, Volume 22, Number 4, pp 221-228] // Normally, coefficiants are float, but they are transformed into integer with 1/FLOAT2INTEGER = 1/2"11 precision for speed reasons. // Please note that these coefficient may over and under shoot in the sense that they may be <0.0 and >1.0 // Given out values of B and C, maximum value is (x=0) 8/9 and undeshoot is bigger than -0.04 (x#1.5) const float B = 1.0 / 3.0; const float C = 1.0 / 3.0; if (fabs (x) < 1) return ((int16_t) floor (0.5 + (((12.0 - 9.0 * B - 6.0 * C) * fabs (x) * fabs (x) * fabs (x) + (-18.0 + 12.0 * B + 6.0 * C) * fabs (x) * fabs (x) + (6.0 - 2.0 * B)) / 6.0 ) * multiplicative)); if (fabs (x) <= 2) return ((int16_t) floor (0.5 + (((-B - 6.0 * C) * fabs (x) * fabs (x) * fabs (x) + (6.0 * B + 30.0 * C) * fabs (x) * fabs (x) + (-12.0 * B - 48.0 * C) * fabs (x) + (8.0 * B + 24.0 * C)) / 6.0) * multiplicative)); if (fabs (x) <= 3) return (0); mjpeg_info("In function cubic_spline: x=%f >3",x); return (0); } // ************************************************************************************* // ************************************************************************************* int padding (uint8_t * padded_input, uint8_t * input, unsigned int half, uint16_t left_offset, uint16_t top_offset, uint16_t right_offset, uint16_t bottom_offset, uint16_t width_pad) { // In cubic interpolation, output pixel are evaluated from the 4*4 to 12*12 nearest neigbors. // For border pixels, this requires that input datas along the edge to be padded. // We choose to pad border pixel with black pixel, since border pixel along width are much of the time non-visible // (TV set for example) and along the height they are either non-visible or black borders are displayed // This padding functions requires output_interlaced==0 unsigned int local_input_useful_width = input_useful_width >> half; unsigned int local_input_useful_height = input_useful_height >> half; unsigned int local_padded_width = local_input_useful_width + width_pad; unsigned int local_input_width = input_width >> half; unsigned int line; uint8_t black,*uint8_pad,*uint8_inp; unsigned long int nb_top=top_offset*local_padded_width; // mjpeg_debug ("Start of padding, left_offset=%d,top_offset=%d,right_offset=%d,bottom_offset=%d,width_pad=%d", // left_offset,top_offset,right_offset,bottom_offset,width_pad); if (half) black=128; else black=16; // PADDING // vertical offset of top_offset lines // Black pixel on the left_offset left pixels // Content Copy with left_offset pixels offset on the left and right_offset pixels of the right // Black pixel on the right_offset right pixels // vertical offset of the last bottom_offset lines memset(padded_input,black,nb_top); uint8_inp=input; uint8_pad=padded_input+nb_top; for (line = 0; line < local_input_useful_height; line++) { memset(uint8_pad,black,left_offset); uint8_pad+=left_offset; memcpy (uint8_pad, uint8_inp, local_input_useful_width); uint8_pad+=local_input_useful_width; uint8_inp+=local_input_width; // it is local_input_width, not local_input_useful_width, see yuvscaler_implementation.txt memset(uint8_pad,black,right_offset); uint8_pad+=right_offset; } memset(uint8_pad,black,bottom_offset*local_padded_width); // mjpeg_debug ("End of padding"); return (0); } // ************************************************************************************* // ************************************************************************************* int padding_interlaced (uint8_t * padded_top, uint8_t * padded_bottom, uint8_t * input, unsigned int half, uint16_t left_offset, uint16_t top_offset, uint16_t right_offset, uint16_t bottom_offset, uint16_t width_pad) { unsigned int local_input_useful_width = input_useful_width >> half; unsigned int local_input_useful_height = input_useful_height >> half; unsigned int local_padded_width = local_input_useful_width + width_pad; unsigned int local_input_width = input_width >> half; unsigned int line; uint8_t black, * uint8_ptop, * uint8_pbot, * uint8_inp; unsigned long int nb_top=top_offset*local_padded_width; unsigned long int nb_bot=bottom_offset*local_padded_width; // mjpeg_debug ("Start of padding_interlaced, left_offset=%d,top_offset=%d,right_offset=%d,bottom_offset=%d,width_pad=%d", // left_offset,top_offset,right_offset,bottom_offset,width_pad); if (half) black=128; else black=16; // PADDING // vertical offset of top_offset lines // Black pixel on the left_offset left pixels // Content Copy with left_offset pixels offset on the left and right_offset pixels of the right // Black pixel on the right_offset right pixels // vertical offset of the last bottom_offset lines memset(padded_top,black,nb_top); memset(padded_bottom,black,nb_top); uint8_inp=input; uint8_ptop=padded_top+nb_top; uint8_pbot=padded_bottom+nb_top; for (line = 0; line < (local_input_useful_height >> 1); line++) { memset(uint8_ptop,black,left_offset); uint8_ptop+=left_offset; memset(uint8_pbot,black,left_offset); uint8_pbot+=left_offset; memcpy (uint8_ptop, uint8_inp, local_input_useful_width); uint8_ptop+=local_input_useful_width; uint8_inp +=local_input_width; // it is local_input_width, not local_input_useful_width, see yuvscaler_implementation.txt memcpy (uint8_pbot, uint8_inp, local_input_useful_width); uint8_pbot+=local_input_useful_width; uint8_inp +=local_input_width; // it is local_input_width, not local_input_useful_width, see yuvscaler_implementation.txt memset(uint8_ptop,black,right_offset); uint8_ptop+=right_offset; memset(uint8_pbot,black,right_offset); uint8_pbot+=right_offset; } memset(uint8_ptop,black,nb_bot); memset(uint8_pbot,black,nb_bot); // mjpeg_debug ("End of padding_interlaced"); return (0); } // ************************************************************************************* // THE FOLLOWING LINE "if (!mmx) mmx=0;" DOES NO USEFUL CALCULATION BUT // it is necessary when gcc compilation with -O2 flag // to calculate correct values for value1+=(mmx_res[0]+mmx_res[1])*(*csplineh[h]); // I know this sounds incredible, but believe me, it is true ! // On the other hand, using only gcc -O1, this line is no more necessary. // And in both case, mmx_res[0],mmx_res[1] and *csplineh[h] have the same values // Indeed, the corresponding machine code is totally different with or without // this line with gcc -O2. // The line value1+=(mmx_res[0]+mmx_res[1])*(*csplineh[h]) is compiled into // (From DDD): // Right calculation, that is including the "if (!mmx) mmx=0;" line // --> 0x804f07f :pmaddwd %mm0,%mm6 // --> 0x804f082 :movq %mm6,(%ecx) // 0x804f085 :mov (%ecx),%edx // 0x804f087 :mov 0x4(%ecx),%eax // 0x804f08a :mov 0xffffffbc(%ebp),%ebx // 0x804f08d :add %edx,%eax // 0x804f08f :mov (%ebx,%edi,4),%edx // --> 0x804f092 :inc %edi // Wrong calculation, that is not including the "if (!mmx) mmx=0;" line // --> 0x804f062 :pmaddwd %mm0,%mm6 // --> 0x804f065 :movq %mm6,(%ecx) // 0x804f068 :mov 0xffffffbc(%ebp),%ebx // 0x804f06b :mov (%ecx),%eax // 0x804f06d :mov (%ebx,%edi,4),%edx // 0x804f070 :add %esi,%eax // --> 0x804f072 :inc %edi // if (!mmx) // mmx=0; mjpegtools-2.1.0/yuvscaler/Makefile.in0000644000175000017500000006101412217306411020272 0ustar glowwormglowworm# Makefile.in generated by automake 1.12.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Makefile for yuvscaler VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @HAVE_ALTIVEC_TRUE@am__append_1 = $(top_builddir)/mpeg2enc/libmpeg2encpp.la bin_PROGRAMS = yuvscaler$(EXEEXT) subdir = yuvscaler DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_yuvscaler_OBJECTS = yuvscaler-yuvscaler.$(OBJEXT) \ yuvscaler-yuvscaler_resample.$(OBJEXT) \ yuvscaler-yuvscaler_bicubic.$(OBJEXT) yuvscaler_OBJECTS = $(am_yuvscaler_OBJECTS) am__DEPENDENCIES_1 = yuvscaler_DEPENDENCIES = $(LIBMJPEGUTILS) $(am__DEPENDENCIES_1) yuvscaler_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(yuvscaler_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(yuvscaler_SOURCES) DIST_SOURCES = $(yuvscaler_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALTIVEC_EXTRA_LIBS = @ALTIVEC_EXTRA_LIBS@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDV_CFLAGS = @LIBDV_CFLAGS@ LIBDV_LIBS = @LIBDV_LIBS@ LIBGETOPT_LIB = @LIBGETOPT_LIB@ LIBM_LIBS = @LIBM_LIBS@ LIBOBJS = @LIBOBJS@ LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ LIBPNG_LIBS = @LIBPNG_LIBS@ LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@ LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ LT_STATIC = @LT_STATIC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROGRAM_NOPIC = @PROGRAM_NOPIC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ SDLgfx_LIBS = @SDLgfx_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ V4LCONF_LIBS = @V4LCONF_LIBS@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAINTAINERCLEANFILES = Makefile.in AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/utils LIBMJPEGUTILS = $(top_builddir)/utils/libmjpegutils.la $(am__append_1) noinst_HEADERS = \ yuvscaler.h EXTRA_DIST = yuvscaler_implementation.txt yuvscaler_CFLAGS = @PROGRAM_NOPIC@ yuvscaler_SOURCES = yuvscaler.c yuvscaler_resample.c yuvscaler_bicubic.c yuvscaler_LDADD = $(LIBMJPEGUTILS) $(LIBM_LIBS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu yuvscaler/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu yuvscaler/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list yuvscaler$(EXEEXT): $(yuvscaler_OBJECTS) $(yuvscaler_DEPENDENCIES) $(EXTRA_yuvscaler_DEPENDENCIES) @rm -f yuvscaler$(EXEEXT) $(yuvscaler_LINK) $(yuvscaler_OBJECTS) $(yuvscaler_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuvscaler-yuvscaler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuvscaler-yuvscaler_bicubic.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuvscaler-yuvscaler_resample.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< yuvscaler-yuvscaler.o: yuvscaler.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvscaler_CFLAGS) $(CFLAGS) -MT yuvscaler-yuvscaler.o -MD -MP -MF $(DEPDIR)/yuvscaler-yuvscaler.Tpo -c -o yuvscaler-yuvscaler.o `test -f 'yuvscaler.c' || echo '$(srcdir)/'`yuvscaler.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/yuvscaler-yuvscaler.Tpo $(DEPDIR)/yuvscaler-yuvscaler.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='yuvscaler.c' object='yuvscaler-yuvscaler.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvscaler_CFLAGS) $(CFLAGS) -c -o yuvscaler-yuvscaler.o `test -f 'yuvscaler.c' || echo '$(srcdir)/'`yuvscaler.c yuvscaler-yuvscaler.obj: yuvscaler.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvscaler_CFLAGS) $(CFLAGS) -MT yuvscaler-yuvscaler.obj -MD -MP -MF $(DEPDIR)/yuvscaler-yuvscaler.Tpo -c -o yuvscaler-yuvscaler.obj `if test -f 'yuvscaler.c'; then $(CYGPATH_W) 'yuvscaler.c'; else $(CYGPATH_W) '$(srcdir)/yuvscaler.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/yuvscaler-yuvscaler.Tpo $(DEPDIR)/yuvscaler-yuvscaler.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='yuvscaler.c' object='yuvscaler-yuvscaler.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvscaler_CFLAGS) $(CFLAGS) -c -o yuvscaler-yuvscaler.obj `if test -f 'yuvscaler.c'; then $(CYGPATH_W) 'yuvscaler.c'; else $(CYGPATH_W) '$(srcdir)/yuvscaler.c'; fi` yuvscaler-yuvscaler_resample.o: yuvscaler_resample.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvscaler_CFLAGS) $(CFLAGS) -MT yuvscaler-yuvscaler_resample.o -MD -MP -MF $(DEPDIR)/yuvscaler-yuvscaler_resample.Tpo -c -o yuvscaler-yuvscaler_resample.o `test -f 'yuvscaler_resample.c' || echo '$(srcdir)/'`yuvscaler_resample.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/yuvscaler-yuvscaler_resample.Tpo $(DEPDIR)/yuvscaler-yuvscaler_resample.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='yuvscaler_resample.c' object='yuvscaler-yuvscaler_resample.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvscaler_CFLAGS) $(CFLAGS) -c -o yuvscaler-yuvscaler_resample.o `test -f 'yuvscaler_resample.c' || echo '$(srcdir)/'`yuvscaler_resample.c yuvscaler-yuvscaler_resample.obj: yuvscaler_resample.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvscaler_CFLAGS) $(CFLAGS) -MT yuvscaler-yuvscaler_resample.obj -MD -MP -MF $(DEPDIR)/yuvscaler-yuvscaler_resample.Tpo -c -o yuvscaler-yuvscaler_resample.obj `if test -f 'yuvscaler_resample.c'; then $(CYGPATH_W) 'yuvscaler_resample.c'; else $(CYGPATH_W) '$(srcdir)/yuvscaler_resample.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/yuvscaler-yuvscaler_resample.Tpo $(DEPDIR)/yuvscaler-yuvscaler_resample.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='yuvscaler_resample.c' object='yuvscaler-yuvscaler_resample.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvscaler_CFLAGS) $(CFLAGS) -c -o yuvscaler-yuvscaler_resample.obj `if test -f 'yuvscaler_resample.c'; then $(CYGPATH_W) 'yuvscaler_resample.c'; else $(CYGPATH_W) '$(srcdir)/yuvscaler_resample.c'; fi` yuvscaler-yuvscaler_bicubic.o: yuvscaler_bicubic.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvscaler_CFLAGS) $(CFLAGS) -MT yuvscaler-yuvscaler_bicubic.o -MD -MP -MF $(DEPDIR)/yuvscaler-yuvscaler_bicubic.Tpo -c -o yuvscaler-yuvscaler_bicubic.o `test -f 'yuvscaler_bicubic.c' || echo '$(srcdir)/'`yuvscaler_bicubic.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/yuvscaler-yuvscaler_bicubic.Tpo $(DEPDIR)/yuvscaler-yuvscaler_bicubic.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='yuvscaler_bicubic.c' object='yuvscaler-yuvscaler_bicubic.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvscaler_CFLAGS) $(CFLAGS) -c -o yuvscaler-yuvscaler_bicubic.o `test -f 'yuvscaler_bicubic.c' || echo '$(srcdir)/'`yuvscaler_bicubic.c yuvscaler-yuvscaler_bicubic.obj: yuvscaler_bicubic.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvscaler_CFLAGS) $(CFLAGS) -MT yuvscaler-yuvscaler_bicubic.obj -MD -MP -MF $(DEPDIR)/yuvscaler-yuvscaler_bicubic.Tpo -c -o yuvscaler-yuvscaler_bicubic.obj `if test -f 'yuvscaler_bicubic.c'; then $(CYGPATH_W) 'yuvscaler_bicubic.c'; else $(CYGPATH_W) '$(srcdir)/yuvscaler_bicubic.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/yuvscaler-yuvscaler_bicubic.Tpo $(DEPDIR)/yuvscaler-yuvscaler_bicubic.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='yuvscaler_bicubic.c' object='yuvscaler-yuvscaler_bicubic.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvscaler_CFLAGS) $(CFLAGS) -c -o yuvscaler-yuvscaler_bicubic.obj `if test -f 'yuvscaler_bicubic.c'; then $(CYGPATH_W) 'yuvscaler_bicubic.c'; else $(CYGPATH_W) '$(srcdir)/yuvscaler_bicubic.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool cscopelist ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mjpegtools-2.1.0/yuvscaler/yuvscaler_implementation.txt0000644000175000017500000003650510323630014024112 0ustar glowwormglowwormThis file describes the internal implementation of yuvscaler. Variable name are between $$ like $$Variabel_name$$ ******** OVERVIEW ******** Basically, yuvscaler is a scaling program that works sequentially on the video stream to be treated, that is single frame by single frame. An input frame is read, it is then scaled, and the resulting frame is written on output. Frame number is $$frame_num$$. Frames are interleaved and they have the three components YUV with U and V at quarter resolution. Input frame Y component is of width $$input_width$$ and of height $$input_height$$, therefore U and V components are of size $$input_width$$/2*$$input_heith$$/2. When they are read, full input frame are stored under the pointer $$input$$ which points to 3/2*$$input_width$$*$$input_height$$ unsigned integer stored on 8bit (uint8_t). Input frames are then prerocessed acording to the needs (line-switching, filed time reordering, blackout, color saturation, brightness control). Once preprocessed, input frames are scaled. To do that, we make exclusively use three specific pointers: $$input_y$$, $$input_u$$ and $$input_v$$ (see after, the Input useful area paragraph for definition). So, in fact, yuvscaler only scales the useful area of input frames. Once scaled, the useful input area become the output frame frame accessed exclusively through $$frame_y$$, $$frame_u$$ and $$frame_v$$ pointer. The output active area that results from scaling the input useful area might be different from the display area (specified using the -O KEYWORD syntax). In that case, yuvscaler will automatically generate necessary black lines and columns and/or skip necessary lines and columns to get an active output centered within the display size. The Y component of the display is of size $$output_width$$*$$output_height$$. ***** INPUT => all variable names concerning INPUT begin with input_ ***** Two areas might be defined inside Input frame. First area is the useful area and second area is the active area. Input useful area (-I USE_WWxHH+x+y argument) ----------------- Everything outside the useful area is discarded. This area (Y component) is of size $$input_useful_width$$*$$input_useful_height$$. And as it is not necesseraly centered, we also define $$input_discard_col_left$$ (number of columns discard on the left side of the input frame), $$input_discard_col_right$$, $$input_discard_line_above$$ and $$input_discard_line_under$$. So, we have the relations: input_width=input_useful_width+input_discard_col_left+input_discard_col_right input_height=input_useful_height+input_discard_line_above+input_discard_line_under Illustration: input frame --------------------------------------------------------------------------- ^ ^ | | input_discard_line_above| | | input_discard --------------------------------------- input_discard | _col_left | ^ | _col_right | <------------->| | input_useful_width |<------------------>| |<----------------------------------->| | | | | | | | | | | | | | | | | | | |input_useful_height | | | | | | | | | | | | USEFUL AREA | | | | | | | | | | | | | | | | | | | | | | | \ | | --------------------------------------- | ^ ^ | | input_discard_line_under| | --------------------------------------------------------------------------| As a consequence, we must take into account ONLY what is inside the useful area. So, we define three new pointers: $$input_y$$, $$input_u$$ and $$input_v$$ that points respectively on the first USEFUL element of the Y (resp. U and V) component. So, BEWARE, data scaling (for Y) will only take into account lines that are $$input_useful_width$$ elements long BUT are spaced one to another by $$input_width$$ elements, and that starts at $$input_y$$, not $$input$$. The same stands for U and V components. Input active area: ------------------ Everything outside the active area is considered to be black pixels. Similarly to the useful area, we define six variables: $$input_active_width$$ and $$input_active_height$$ $$input_black_line_above$$ and $$input_black_line_under$$ $$input_black_col_left$$ and $$input_black_col_right$$ ******** SCALING ******** yuvscaler uses two different algorithms to scale an image: - the resample algorithm used to DOWNscale an image - the bicubic algorithm used to DOWNsclae or UPScale an image Moreover, there is a subdivision in each algorithm: interlaced or not-interlaced algorithm BEWARE: Let us first remind you: scaling uses exclusively $$input_y$$, $$input_u$$ and $$input_v$$ pointers. So, Data scaling (for Y) will only take into account lines that are $$input_useful_width$$ elements long BUT are spaced one to another by $$input_width$$ elements, and that starts at $$input_y$$, not $$input$$. The same stands for U and V components. Scaling factors --------------- As scaling factors may not be the same along width and height, we defined two scaling factors. For [width|height], $$input_[width|height]_slice$$ input pixels will be scaled to $$output_[width|height]_slice$$ pixels. Moreover, $$input_[width|height]_slice$$ and $$output_[width|height]_slice$$ are taken as irreductible (thanks to the pgcd function). RESAMPLE ALGORITHM (see file yuvscaler_resample.c) ------------------ The resample algorithm is, in fact, the natural way you will average (downscale) a certain number of input pixels into a smaller number of output pixels. For example, let us average 11 pixels into 5 pixels. If each input pixels is drawn as 5 units long and each output pixels as 11 units long, then input pixels contributes to the corresponding output pixels of the amount they intersect with it. -------------------------------------------------------- | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | input -------------------------------------------------------- | 1 | 2 | 3 | 4 | 5 | output -------------------------------------------------------- Thus, for example, output pixel number 4 will be equal to (2/5*input_pixel7+5/5*input_pixel8+4/5input_pixel9)/11, which may be rewritten as (2*input_pixel7+5*input_pixel8+4input_pixel9)/(5*11). It is the function average_coeff that calculates the multiplicative coefficents, here 2, 5 and 4. For the resample scaling of one image may be decomposed into the scaling a certain number of sub-pictures called slice. Each slice is of dimensions $$input_width_slice$$*$$input_height_slice$$ on input and $$output_width_slice$$*$$output_height_slice$$ on output. There are $$out_nb_line_slice$$ slices along the width and $$out_nb_col_slice$$ slices along the height. So, for both scaling algorithm implementation, we "just" have to implement scaling of a single slice and repeat the same process on all the slices. Thus, resample function is implemented as: for (out_line_slice = 0; out_line_slice < out_nb_line_slice; out_line_slice++) { for (out_col_slice = 0; out_col_slice < out_nb_col_slice; out_col_slice++) { *****SINGLE SLICE RESAMPLE SCALING******** } } For speed sake, we may note that all calculations end up by dividing a (non-constant) integer by a constant integer called $$diviseur$$, 5*11=55 in the preceding example. As integer division takes classically 5-7 cycles, it is worth tabulating all possible results, so that the final integer division is replaced by "just" a data recall in a vector, that we call $$divide$$. But division of integers by integers in C always made by smaller value => this results in a abnormal systematic drift towards smaller values for new pixels. To avoid that, we will add 1/2 of $$diviseur$$ to the value to be divided by $$diviseur$$ BICUBIC ALGORITHM (see file yuvscaler_bicubic.c) ----------------- // Given the scaling factor S, to an output pixel of coordinates (out_col,out_line) corresponds an input pixel of coordinates (in_col,in_line), // where in_col = out_col/S and in_line = out_line/S. As pixel coordinates are integer values, we take for in_col and out_col the nearest smaller integer // value: in_col = floor(out_col/S) and in_line = floor(out_line/S). Thus, we make an error conventionnally named "b" for columns and "a" for lines // with b = out_col/S - floor(out_col/S) and a = out_line/S - floor(out_line/S). a and b are inside range [0,1[. // Finally, the scaling ratio may be different for width and height and may be smaller or **larger** than 1.0. // // In the bicubic algorithm, the output pixel value depends on its 4x4 nearest neighbors in the input image. // Therefore, output pixel (out_col,out_line) depends on the 16 input pixels (in_col+n,in_line+m) with n=-1,0,1,2 and m=-1,0,1,2. // As a consequence, on the border of the image, the bicubic algorithm will try to find values outside the input image => to avoid this, we pad the input // image 1 pixel on the top and on the left, and 2 pixels on the right and on the bottom. The padded image is stored inside either padded_input vector if the input image is not-interlaced/progressive // or inside two vectors named padded_top and padded_bottom if input image is interlaced. // // The bicubic formula giving the value of the output pixel as a function of the 4x4 input pixels is: // OutputPixel(out_col,out_line)=Sum(m=-1,0,1,2)Sum(n=-1,0,1,2)InputPixel(in_col+n,in_line+m)*BicubicCoefficient(m-a)*BicubicCoefficient(b-n) // For calculation of the BicubicCoefficient function, see file yuvscaler_bicubic.c // // We will call cubic_spline_n, the various possible values of BicubicCoefficient(b-n) and cubic_spline_m the various possible values of BicubicCoefficient(m-a) // Now, let us speak about implementation and speed. A padded input image is stored in either padded_input (not-interlaced/progressive video) or the couple padded_top/padded_bottom (interlaced video). As the input frames are padded 1 pixel on the top and on the left, we have InputPixel(in_col+n,in_line+m)=padded(in_col+n+1,in_line+m+1). Thus, the bicubic formula may be rewritten with n=0,1,2,3 and m=0,1,2,3 as OutputPixel(out_col,out_line)=Sum(m=0,1,2,3)Sum(n=0,1,2,3)PaddedPixel(in_col+n,in_line+m)*BicubicCoefficient((m-1)-a)*BicubicCoefficient(b-(n-1)) For speed sake, it is vital to tabulate every values that do not depend on pixel values. So, we will tabulate values of in_col, in_line, b, a, BicubicCoefficient((m-1)-a) for m=0,1,2,3 and BicubicCoefficient(b-(n-1)) for n=0,1,2,3. We choose to tabulate these values as a function of the coordinates of the OutputPixel, that is as a function of either out_col or out_line. Therefore, we define: cubic_spline_n_0[out_col] = BicubicCoefficient(b[out_col]-(n-1)) for n=0 and every possible out_col values cubic_spline_n_1[out_col] = BicubicCoefficient(b[out_col]-(n-1)) for n=1 and every possible out_col values cubic_spline_n_2[out_col] = BicubicCoefficient(b[out_col]-(n-1)) for n=2 and every possible out_col values cubic_spline_n_3[out_col] = BicubicCoefficient(b[out_col]-(n-1)) for n=3 and every possible out_col values cubic_spline_m_0[out_line] = BicubicCoefficient((m-1)-a[out_line]) for m=0 and every possible out_line values cubic_spline_m_1[out_line] = BicubicCoefficient((m-1)-a[out_line]) for m=1 and every possible out_line values cubic_spline_m_2[out_line] = BicubicCoefficient((m-1)-a[out_line]) for m=2 and every possible out_line values cubic_spline_m_3[out_line] = BicubicCoefficient((m-1)-a[out_line]) for m=3 and every possible out_line values All these values are float ... as operations with float are notibly slower than operations with integer, we will work under fixed-point precision, that is these floats will be transformed into integer by multiplying them by a fixed integer value and round them off. The chosen fixed value here is 2048, that is a power of 2 to allow for multiplication and division operation to become simple and fast bit shifts. 2048 is also a sufficiently large value as compared to maximal pixel value to allow for calculations to have a sufficient precision. ********* OUTPUT => variables names begin with output_ or display_ ********* It is a bit more complicated than input in the sense that part of the output frame (resulting from scaling from the input frame) may not be displayed, or, on the contrary, output frame may be smaller than the display size. Display: -------- The display size is $$display_width$$*$$display_height$$ and is usually defined on the command line (-O [VCD|SVCD|SIZE_WWxHH] argument). This is the size of the frame that will be outputted by yuvscaler. Output size: ------------ By multipling input USEFUL size by the (irreductible) scaling ratios $$input_width_slice$$/$$output_width_slice$$ and $$input_height_slice$$/$$output_height_slice$$, output size $$output_width$$*$$output_height$$ is determined. If we now compare $$output_width$$ and $$display_width$$: - if $$display_width$$ is the smaller, then part of the output frame will not be displayed => we define $$output_skip_col_[left|right]$$ so that display is centered relative to output. - if $$display_width$$ is the bigger, then the output frame is too small and it will be completed by black borders => we define $$output_black_col_[left|right]$$ so that output frame is centered inside display frame Doing the same thing with height, we define $$output_skip_line_[above|under]$$ and $$output_black_line_[above|under]$$ *********** FRAME PREPROCESSING *********** line switching -------------- The line_switch function switches lines two by two inside the input frame. blackout -------- The blackout function makes input borders pixels become black time reordering of fields ------------------------- The idea here is to move either the bottom field or the top field one frame forward to compensate for wrong video capture. This is implemented by using sequentially two functions: either bottom_field_storage and then bottom_field_replace or top_field_storage and then top_field_replace. For even (resp. odd) frame numbers, the bottom_field_storage function will store inside field1 (resp. filed2) the bottom field of the current frame. And then, the function bottom_field_replace will replace the current bottom field that was just stored, by the bottom field of the preceding frame. The same stands for top field reordering mjpegtools-2.1.0/yuvscaler/yuvscaler.h0000644000175000017500000000351510323630014020410 0ustar glowwormglowworm// yuvscaler.c void yuvscaler_print_usage (char *argv[]); void yuvscaler_print_information (y4m_stream_info_t in_streaminfo, y4m_ratio_t frame_rate); uint8_t yuvscaler_nearest_integer_division (unsigned long int, unsigned long int); //static y4m_ratio_t yuvscaler_calculate_output_sar (int out_w, int out_h, // int in_w, int in_h, y4m_ratio_t in_sar); int yuvscaler_y4m_read_frame (int fd, y4m_stream_info_t *, y4m_frame_info_t * frameinfo,unsigned long int buflen, uint8_t * buf); int blackout(uint8_t *input_y,uint8_t *input_u,uint8_t *input_v); void handle_args_global (int argc, char *argv[]); void handle_args_dependent (int argc, char *argv[]); int main (int argc, char *argv[]); unsigned int pgcd(unsigned int,unsigned int); // yuvscaler_resample.c int average_coeff(unsigned int,unsigned int,unsigned int *); int average(unsigned char *,unsigned char *, unsigned int *, unsigned int *,unsigned int); int average_specific(unsigned char *,unsigned char *, unsigned int *, unsigned int *, unsigned int); // yuvscaler_bicubic.c int16_t cubic_spline(float,unsigned int); int padding_interlaced (uint8_t * padded_top, uint8_t * padded_bottom, uint8_t * input, unsigned int half, uint16_t left_offset, uint16_t top_offset, uint16_t right_offset, uint16_t bottom_offset, uint16_t width_pad); int padding (uint8_t * padded_input, uint8_t * input, unsigned int half, uint16_t left_offset, uint16_t top_offset, uint16_t right_offset, uint16_t bottom_offset, uint16_t width_pad); int cubic_scale_interlaced (uint8_t *, uint8_t *, uint8_t *, unsigned int *, unsigned int *, int16_t *, uint16_t, uint8_t, int16_t *, uint16_t, uint8_t, unsigned int); int cubic_scale (uint8_t *, uint8_t *, unsigned int *, unsigned int *, int16_t *, uint16_t, uint8_t, int16_t *, uint16_t, uint8_t, unsigned int); mjpegtools-2.1.0/README.glav0000644000175000017500000000276607430024743016037 0ustar glowwormglowwormYou should be able to just "make" there are some hacks so I didn't have to include anything from the mjpeg utils directory. I hope to get it into the build tree sometime (soon...). seconds are NTSC seconds (30 frames) Key Bindings: (loosely based on vi key bindings) ( set Selection Start Home " ) set Selection End End " 0 go to beginning h,<- + CTRL " 9 go to end l,-> + CTRL " l,-> forward single frame l,-> + SHIFT forward 10 frames l,-> + ALT forward 50 frames w forward 1/2 second (15 frames) W forward 1 second (30 frames) h,<- reverse single frame h,<- + SHIFT reverse 10 frames h,<- + ALT reverse 50 frames 1 forward 5 seconds 2 forward 10 seconds 3 forward 15 seconds 4 forward 20 seconds 5 forward 25 seconds 6 forward 30 seconds b reverse 1/2 second (15 frames) B reverse 1 second (30 frames) ! reverse 5 seconds @ reverse 10 seconds # reverse 15 seconds $ forward 20 seconds % forward 25 seconds ^ forward 30 seconds x,del cut selection y yank (copy) selection p,ins paste selection s,S stop, pause f play (forward) F fast forward r reverse R fast reverse mjpegtools-2.1.0/config.guess0000755000175000017500000013014512217306406016536 0ustar glowwormglowworm#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 Free Software Foundation, Inc. timestamp='2012-02-10' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner. Please send patches (context # diff format) to and include a ChangeLog # entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_MACHINE}" in i?86) test -z "$VENDOR" && VENDOR=pc ;; *) test -z "$VENDOR" && VENDOR=unknown ;; esac test -f /etc/SuSE-release -o -f /.buildenv && VENDOR=suse # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-${VENDOR}-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-${VENDOR}-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-${VENDOR}-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-${VENDOR}-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-${VENDOR}-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-${VENDOR}-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-${VENDOR}-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-${VENDOR}-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm:riscos:*:*|arm:RISCOS:*:*) echo arm-${VENDOR}-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-${VENDOR}-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-${VENDOR}-osf1mk else echo ${UNAME_MACHINE}-${VENDOR}-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-${VENDOR}-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-${VENDOR}-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-${VENDOR}-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-${VENDOR}-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-${VENDOR}-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-${VENDOR}-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-${VENDOR}-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-${VENDOR}-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-${VENDOR}-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-${VENDOR}-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-${VENDOR}-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-${VENDOR}-linux-gnueabi else echo ${UNAME_MACHINE}-${VENDOR}-linux-gnueabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-gnu exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-gnu exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; i*86:Linux:*:*) LIBC=gnu eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __dietlibc__ LIBC=dietlibc #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` echo "${UNAME_MACHINE}-pc-linux-${LIBC}" exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-${VENDOR}-linux-gnu"; exit; } ;; or32:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; padre:Linux:*:*) echo sparc-${VENDOR}-linux-gnu exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-${VENDOR}-linux-gnu exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-${VENDOR}-linux-gnu ;; PA8*) echo hppa2.0-${VENDOR}-linux-gnu ;; *) echo hppa-${VENDOR}-linux-gnu ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-${VENDOR}-linux-gnu exit ;; ppc:Linux:*:*) echo powerpc-${VENDOR}-linux-gnu exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-gnu exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-${VENDOR}-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-${VENDOR}-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-${VENODR}-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-${VENDOR}-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-${VENODR}-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-${VENDOR}-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-${VENDOR}-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-${VENDOR}-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-${VENDOR}-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-${VENDOR}-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in i386) eval $set_cc_for_build if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then UNAME_PROCESSOR="x86_64" fi fi ;; unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-?:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-${VENDOR}-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-${VENDOR}-tops10 exit ;; *:TENEX:*:*) echo pdp10-${VENDOR}-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-${VENDOR}-tops20 exit ;; *:ITS:*:*) echo pdp10-${VENDOR}-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-${VENDOR}-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-${VENDOR}-esx exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: mjpegtools-2.1.0/missing0000755000175000017500000002370312217306406015616 0ustar glowwormglowworm#! /bin/sh # Common stub for a few missing GNU programs while installing. scriptversion=2012-01-06.18; # UTC # Copyright (C) 1996-2012 Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi run=: sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' sed_minuso='s/.* -o \([^ ]*\).*/\1/p' # In the cases where this matters, 'missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi msg="missing on your system" case $1 in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 # Exit code 63 means version mismatch. This often happens # when the user try to use an ancient version of a tool on # a file that requires a minimum version. In this case we # we should proceed has if the program had been absent, or # if --run hadn't been passed. if test $? = 63; then run=: msg="probably too old" fi ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle 'PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file 'aclocal.m4' autoconf touch file 'configure' autoheader touch file 'config.h.in' autom4te touch the output file, or create a stub one automake touch all 'Makefile.in' files bison create 'y.tab.[ch]', if possible, from existing .[ch] flex create 'lex.yy.c', if possible, from existing .c help2man touch the output file lex create 'lex.yy.c', if possible, from existing .c makeinfo touch the output file yacc create 'y.tab.[ch]', if possible, from existing .[ch] Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: Unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # normalize program name to check for. program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect # the program). This is about non-GNU programs, so use $1 not # $program. case $1 in lex*|yacc*) # Not GNU programs, they don't have --version. ;; *) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then # Could not run --version or --help. This is probably someone # running '$TOOL --version' or '$TOOL --help' to check whether # $TOOL exists and not knowing $TOOL uses missing. exit 1 fi ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case $program in aclocal*) echo 1>&2 "\ WARNING: '$1' is $msg. You should only need it if you modified 'acinclude.m4' or '${configure_ac}'. You might want to install the Automake and Perl packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf*) echo 1>&2 "\ WARNING: '$1' is $msg. You should only need it if you modified '${configure_ac}'. You might want to install the Autoconf and GNU m4 packages. Grab them from any GNU archive site." touch configure ;; autoheader*) echo 1>&2 "\ WARNING: '$1' is $msg. You should only need it if you modified 'acconfig.h' or '${configure_ac}'. You might want to install the Autoconf and GNU m4 packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case $f in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) echo 1>&2 "\ WARNING: '$1' is $msg. You should only need it if you modified 'Makefile.am', 'acinclude.m4' or '${configure_ac}'. You might want to install the Automake and Perl packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te*) echo 1>&2 "\ WARNING: '$1' is needed, but is $msg. You might have modified some files without having the proper tools for further handling them. You can get '$1' as part of Autoconf from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison*|yacc*) echo 1>&2 "\ WARNING: '$1' $msg. You should only need it if you modified a '.y' file. You may need the Bison package in order for those modifications to take effect. You can get Bison from any GNU archive site." rm -f y.tab.c y.tab.h if test $# -ne 1; then eval LASTARG=\${$#} case $LASTARG in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.h fi ;; esac fi if test ! -f y.tab.h; then echo >y.tab.h fi if test ! -f y.tab.c; then echo 'main() { return 0; }' >y.tab.c fi ;; lex*|flex*) echo 1>&2 "\ WARNING: '$1' is $msg. You should only need it if you modified a '.l' file. You may need the Flex package in order for those modifications to take effect. You can get Flex from any GNU archive site." rm -f lex.yy.c if test $# -ne 1; then eval LASTARG=\${$#} case $LASTARG in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if test ! -f lex.yy.c; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man*) echo 1>&2 "\ WARNING: '$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the Help2man package in order for those modifications to take effect. You can get Help2man from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit $? fi ;; makeinfo*) echo 1>&2 "\ WARNING: '$1' is $msg. You should only need it if you modified a '.texi' or '.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy 'make' (AIX, DU, IRIX). You might want to install the Texinfo package or the GNU make package. Grab either from any GNU archive site." # The file to touch is that specified with -o ... file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -z "$file"; then # ... or it is the one specified with @setfilename ... infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n ' /^@setfilename/{ s/.* \([^ ]*\) *$/\1/ p q }' $infile` # ... or it is derived from the source name (dir/f.texi becomes f.info) test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info fi # If the file does not exist, the user really needs makeinfo; # let's fail without touching anything. test -f $file || exit 1 touch $file ;; *) echo 1>&2 "\ WARNING: '$1' is needed, and is $msg. You might have modified some files without having the proper tools for further handling them. Check the 'README' file, it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing '$1' program." exit 1 ;; esac exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: mjpegtools-2.1.0/INSTALL.real0000644000175000017500000000602310462546274016177 0ustar glowwormglowworm This file is NOT called INSTALL because 'autoreconf -f -i' overwrites INSTALL. The original INSTALL file (this file) is now called INSTALL.real which autoconf will leave alone. Linux MPEG/MJPEG Audio/Video tools - MJPEG TOOLS ================================================ The mjpegtools are a set of utilities for video-decoding, -recording, -playback, -editing and -encoding. Most parts of this software are distributed under the terms of the Gnu Public License (GPL). See the individual source files for the exact terms. Mjpegtools is known to build and install on Linux, BSD and OS/X. On other systems you are on yor own - maybe you'll be lucky. REQUIRED/RECOMMENDED SOFTWARE ============================= For compiling the mjpegtools you will at least need the following pieces of software: glib : http://www.gtk.org/ (g)cc/g++/c++ : http://gcc.gnu.org/ libjpeg : http://www.ijg.org/ XFree86 : http://www.xfree86.org/ These are almost always included with every distribution. However, with this, many of the tools and many features of the tools will not be compiled by default. The following software is advised for getting the extra features of the mjpegtools: Gtk+ : http://www.gtk.org/ libDV : http://libdv.sourceforge.net/ SDL : http://www.libsdl.org/ Some of these are not installed by default with some distributions. If any of them are not found this will be logged during the ./configure process. COMPILING SUPPORT LIBRARIES =========================== The following library is highly recommended for compiling the mjpegtools: libquicktime : http://libquicktime.sourceforge.net/ Lastly unpack libquicktime and run './configure', 'make' and 'make install'. As usual when installing new libraries it may be necessary to run 'ldconfig' after 'make install'. COMPILING THE MJPEGTOOLS ======================== Unpack the tarball and run './autogen.sh' to create the configure script. In the simplest form the configure script is run like this: ./configure If you do NOT want to include quicktime support you may specify '--with-quicktime=no', otherwise the presence of libquicktime will be autodetected. This is not recommended since Quicktime is a very useful format. You can possibly use other options, such as '--enable-large-file' to enable support for > 2GB file support. This is NOT needed by default since autoconf automatically generates the checks for largefile support. Binaries compiled with large file support will *not* run on systems lacking large file support! Next, run 'make' and 'make install'. You're now ready to use the mjpegtools! The MJPEG HOWTO (mjpeg_howto.txt or 'man mjpegtools') is a good place to start. HELP ==== For problems, bugs or questions, please send your e-mails to the mjpegtools malinglist (mjpeg-users@lists.sourceforge.net), or to one of the developers individually. Have fun, /Andrew /Gernot /Ronald /Bernhard /many others (see AUTHORS) mjpegtools-2.1.0/yuvfilters/0000755000175000017500000000000012217306501016422 5ustar glowwormglowwormmjpegtools-2.1.0/yuvfilters/ChangeLog0000644000175000017500000000652507343205352020212 0ustar glowwormglowworm2001-08-29 Kawamata/Hitoshi * README.2-3pulldown: added. 2001-08-28 Kawamata/Hitoshi * timecode.c, timecode.h: moved to ../utils/mpegtimecode.[ch]. * yuvkineco.c: use mpegtimecode.h. * all: add copyright(GPL) comment, use config.h, use mjpeg_logging.h. 2001-08-02 Kawamata/Hitoshi * yuvycsnoise: chroma noise detection case increased. 2001-07-31 Kawamata/Hitoshi * yuvycsnoise: reduce noise detection miss. Chroma noise reduction added. New luma noise reduction method 'triframe' added. Methods called 'interfield', 'intrafield' are now called 'biframe', 'infield'. Some options changed. Options(new/changed): -m tbi: Select method (default: tbic). t: 'triframe' method. b: 'biframe' method (replace old option '-x'). i: 'infield' method (replace old option '-i'). c: chroma noise reduction. -S min: -T errt,maxt: -B errb,maxb: -I erri,maxi: -C errc,maxc: error and max difference of each method. 2001-07-29 Kawamata/Hitoshi * timecode.c: Name of environment variable fixed. To use drop frame timecode, set MJPEG_DROP_FRAME_TIME_CODE=1. 2001-07-28 Kawamata/Hitoshi * yuvkineco: Always drop frame#0 fixed. Now frame#0 will always output. * yuvycsnoise: Abort at last frame fixed. 2001-07-27 Kawamata/Hitoshi * yuvycsnoise: Almost rewrote. Options: -t: test (unchanged). -i: disable 'intrafield' method. -x: disable 'interfield' method. -S min,maxi,maxx: threshold of luma difference is noise or not. min: minimum (unchagend). maxi: maximum in 'intrafiled' method. maxx: maximum in 'interfiled' method. * yuvkineco: Bug when -N CycleList and InputFPSCODE < 4 fixed. 2001-07-24 Kawamata/Hitoshi * addtask.c: Wrong parent after initialize task fixed. * putframe.c: remove cast which need not. 2001-07-23 Kawamata/Hitoshi * addtask.c: Wrong parent of initializing task fixed. * timecode.h: Added. Separated from yuvfilters.h. * all: Names of types and functions changed and clarified. files renamed: addfilter.c -> addtask.c allochandle.c -> alloctask.c 2001-07-22 Kawamata/Hitoshi * allochandle.c: Added. * all filters: replace malloc()/free() with allochandle()/freehandle(). * main.c: Now chained filter can be used. * addfilter.c: Added. * yuvycsnoise.c: Added. * yuvkineco.c: New option -S to insert filter yuvycsnoise. * yuvtemplate.c: Added. 2001-07-20 Kawamata/Hitoshi * main.c: Pass argv[0] to filter. (OLD: pass argv+1 to filter as argv) * all filters: Skip argv[0] * timecode.c: Added. mpeg_timecode() supports NTSC drop frame timecode. To use drop frame timecode, set environment variable: MJPEG_DROP_FRAME_TIME_CODE=1 * yuvctrlbytty: Use mpeg_timecode(). * yuvkineco: Use mpeg_timecode(). * yuvkineco: Add cycle list read / write. Command line arguments completely changed. * TODO: Added. 2001-07-17 Kawamata/Hitoshi * GNUmakefile: Deleted. * Makefile.am: Added. Automake only do about install and dist. Building binaries almost done by GNU make. 2001-07-12 Kawamata/Hitoshi * yuvkineco: Fix U,V merge when interlaced. mjpegtools-2.1.0/yuvfilters/Makefile.am0000644000175000017500000000132210254331123020451 0ustar glowwormglowwormEXTRA_DIST = README.2-3pulldown MAINTAINERCLEANFILES = Makefile.in bin_PROGRAMS = yuvycsnoise yuvkineco noinst_LTLIBRARIES = libyuvfilters.la AM_CPPFLAGS = -I$(top_srcdir)/utils MJPEGLIB = $(top_builddir)/utils/libmjpegutils.la if HAVE_ALTIVEC MJPEGLIB += $(top_builddir)/mpeg2enc/libmpeg2encpp.la endif libyuvfilters_la_SOURCES = \ addtask.c \ alloctask.c \ initframe.c \ putframe.c \ yuvkineco.c \ yuvstdin.c \ yuvstdout.c \ yuvycsnoise.c noinst_HEADERS = \ yuvfilters.h yuvkineco_SOURCES = main.c yuvkineco_CFLAGS = -DFILTER=yuvkineco yuvkineco_LDADD = libyuvfilters.la $(MJPEGLIB) yuvycsnoise_SOURCES = main.c yuvycsnoise_CFLAGS = -DFILTER=yuvycsnoise yuvycsnoise_LDADD = libyuvfilters.la $(MJPEGLIB) mjpegtools-2.1.0/yuvfilters/putframe.c0000644000175000017500000000175707342747141020437 0ustar glowwormglowworm/* * Copyright (C) 2001 Kawamata/Hitoshi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include "yuvfilters.h" int YfPutFrame(const YfTaskCore_t *handle, const YfFrame_t *frame) { return (*handle->handle_outgoing->method->frame)(handle->handle_outgoing, handle, frame); } mjpegtools-2.1.0/yuvfilters/yuvstdout.c0000644000175000017500000000360410210446740020660 0ustar glowwormglowworm/* * Copyright (C) 2001 Kawamata/Hitoshi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include "yuvfilters.h" DEFINE_STD_YFTASKCLASS(yuvstdout); static const char * do_usage(void) { return ""; } static YfTaskCore_t * do_init(int argc, char **argv, const YfTaskCore_t *h0) { YfTaskCore_t *h; --argc; ++argv; if (!(h = YfAllocateTask(&yuvstdout, sizeof *h, h0))) return NULL; y4m_si_set_width(&h->si, h0->width); y4m_si_set_height(&h->si, h0->height); y4m_si_set_framerate(&h->si, mpeg_framerate(h0->fpscode)); if (y4m_write_stream_header(1, &h->si) != Y4M_OK) { YfFreeTask(h); h = NULL; } return h; } static void do_fini(YfTaskCore_t *handle) { YfFreeTask(handle); } static int do_frame(YfTaskCore_t *handle, const YfTaskCore_t *h0, const YfFrame_t * frame0) { uint8_t * yuv[3]; yuv[0] = (uint8_t*)frame0->data; yuv[1] = yuv[0] + (handle->width * handle->height); yuv[2] = yuv[1] + ((handle->width / CWDIV(y4m_si_get_chroma(&handle->si))) * (handle->height / CHDIV(y4m_si_get_chroma(&handle->si)))); return y4m_write_frame(1, &handle->si, &frame0->fi, yuv); } mjpegtools-2.1.0/yuvfilters/addtask.c0000644000175000017500000000240707342747141020220 0ustar glowwormglowworm/* * Copyright (C) 2001 Kawamata/Hitoshi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include "yuvfilters.h" YfTaskCore_t * YfAddNewTask(const YfTaskClass_t *filter, int argc, char **argv, const YfTaskCore_t *h0) { YfTaskCore_t *h; if (h0) { while (h0->handle_outgoing) h0 = h0->handle_outgoing; h = (*filter->init)(argc, argv, h0); if (!h) return NULL; while (h0->handle_outgoing) h0 = h0->handle_outgoing; *(YfTaskCore_t **)&h0->handle_outgoing = h; } else h = (*filter->init)(argc, argv, h0); return h; } mjpegtools-2.1.0/yuvfilters/README.2-3pulldown0000644000175000017500000000440407427561372021411 0ustar glowwormglowwormWhat is 2-3 pulldown? Frame rate of FILM is 24fps. PAL video is 25fps. When we play FILM thru PAL video, 25fps. So motion is quicker and playing time is shorter 96% (24/25). NTSC video is 30fps (to be exact, 30/1.001fps). If we play FILM thru NTSC video as PAL (1 frame on FILM is 1 frame on video), motion will be quicker and playing time be shorter 80% (24/30). It is too quick so it will not seem natural motion, when we play FILM thru NTSC video, 1 frame on FILM is played 2 or 3 fields on video, so motion and playing time is same as FILM. FILM frames 0--. 1--.--. 2--. 3--.--. | | | | | | | | | | NTSC fields 0T | 1T | 2T | 3T | 4T | 0B 1B 2B 3B 4B In analog video world, this process is called 2-3 pulldown, because NTSC video is repeating of 2 fields from original 1 frame and 3 fields from original 1 frame. What is 3:2 pulldown? FILM is recorded in MPEG2 / DVD video for NTSC at 24fps (to be exact, 24/1.001fps). Some flags are also recorded on each frame. DVD video player use top_field_first flag and repeat_first_field flag to play 30fps (to be exact, 30/1.001fps) for NTSC monitor. FILM frames 0 1 2 3 top_field_first 1 1 0 0 repeat_first_field 0 1 0 1 FILM fields 0T 1T----. 2T 3T | 0B | 1B | 2B | 3B-+--. | | | | | | | | | | NTSC fields 0T | 1T | 2T | 3T | 4T | 0B 1B 2B 3B 4B This process is called 3:2 pulldown. What is different 2-3 pulldown and 3:2 pulldown? Results seem same. Difference of name is maybe where to start counting: 2 fields or 3 fields. 2-3 pulldown is processed before recording and recorded at 30fps. 3:2 pulldown is processed at playing and recorded at 24fps. If we play with progressive (60 frames/seconds) monitor, 2-3 pulldown video need rather complex process at progressive monitor to display beautifully. This process isn't reliable perfectly. When we play DVD 24fps video for 3:2 pulldown with progressive monitor, if player and monitor connected with cable which support progressive, player may directly generate progressive frames instead of normal 3:2 pulldown process. This is simple and reliable perfectly. mjpegtools-2.1.0/yuvfilters/Makefile.in0000644000175000017500000006011312217306411020470 0ustar glowwormglowworm# Makefile.in generated by automake 1.12.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = yuvycsnoise$(EXEEXT) yuvkineco$(EXEEXT) @HAVE_ALTIVEC_TRUE@am__append_1 = $(top_builddir)/mpeg2enc/libmpeg2encpp.la subdir = yuvfilters DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(top_srcdir)/depcomp ChangeLog TODO ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libyuvfilters_la_LIBADD = am_libyuvfilters_la_OBJECTS = addtask.lo alloctask.lo initframe.lo \ putframe.lo yuvkineco.lo yuvstdin.lo yuvstdout.lo \ yuvycsnoise.lo libyuvfilters_la_OBJECTS = $(am_libyuvfilters_la_OBJECTS) am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_yuvkineco_OBJECTS = yuvkineco-main.$(OBJEXT) yuvkineco_OBJECTS = $(am_yuvkineco_OBJECTS) yuvkineco_DEPENDENCIES = libyuvfilters.la $(MJPEGLIB) yuvkineco_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(yuvkineco_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_yuvycsnoise_OBJECTS = yuvycsnoise-main.$(OBJEXT) yuvycsnoise_OBJECTS = $(am_yuvycsnoise_OBJECTS) yuvycsnoise_DEPENDENCIES = libyuvfilters.la $(MJPEGLIB) yuvycsnoise_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(yuvycsnoise_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libyuvfilters_la_SOURCES) $(yuvkineco_SOURCES) \ $(yuvycsnoise_SOURCES) DIST_SOURCES = $(libyuvfilters_la_SOURCES) $(yuvkineco_SOURCES) \ $(yuvycsnoise_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALTIVEC_EXTRA_LIBS = @ALTIVEC_EXTRA_LIBS@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDV_CFLAGS = @LIBDV_CFLAGS@ LIBDV_LIBS = @LIBDV_LIBS@ LIBGETOPT_LIB = @LIBGETOPT_LIB@ LIBM_LIBS = @LIBM_LIBS@ LIBOBJS = @LIBOBJS@ LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ LIBPNG_LIBS = @LIBPNG_LIBS@ LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@ LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ LT_STATIC = @LT_STATIC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROGRAM_NOPIC = @PROGRAM_NOPIC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ SDLgfx_LIBS = @SDLgfx_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ V4LCONF_LIBS = @V4LCONF_LIBS@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = README.2-3pulldown MAINTAINERCLEANFILES = Makefile.in noinst_LTLIBRARIES = libyuvfilters.la AM_CPPFLAGS = -I$(top_srcdir)/utils MJPEGLIB = $(top_builddir)/utils/libmjpegutils.la $(am__append_1) libyuvfilters_la_SOURCES = \ addtask.c \ alloctask.c \ initframe.c \ putframe.c \ yuvkineco.c \ yuvstdin.c \ yuvstdout.c \ yuvycsnoise.c noinst_HEADERS = \ yuvfilters.h yuvkineco_SOURCES = main.c yuvkineco_CFLAGS = -DFILTER=yuvkineco yuvkineco_LDADD = libyuvfilters.la $(MJPEGLIB) yuvycsnoise_SOURCES = main.c yuvycsnoise_CFLAGS = -DFILTER=yuvycsnoise yuvycsnoise_LDADD = libyuvfilters.la $(MJPEGLIB) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu yuvfilters/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu yuvfilters/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libyuvfilters.la: $(libyuvfilters_la_OBJECTS) $(libyuvfilters_la_DEPENDENCIES) $(EXTRA_libyuvfilters_la_DEPENDENCIES) $(LINK) $(libyuvfilters_la_OBJECTS) $(libyuvfilters_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list yuvkineco$(EXEEXT): $(yuvkineco_OBJECTS) $(yuvkineco_DEPENDENCIES) $(EXTRA_yuvkineco_DEPENDENCIES) @rm -f yuvkineco$(EXEEXT) $(yuvkineco_LINK) $(yuvkineco_OBJECTS) $(yuvkineco_LDADD) $(LIBS) yuvycsnoise$(EXEEXT): $(yuvycsnoise_OBJECTS) $(yuvycsnoise_DEPENDENCIES) $(EXTRA_yuvycsnoise_DEPENDENCIES) @rm -f yuvycsnoise$(EXEEXT) $(yuvycsnoise_LINK) $(yuvycsnoise_OBJECTS) $(yuvycsnoise_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addtask.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloctask.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initframe.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/putframe.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuvkineco-main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuvkineco.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuvstdin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuvstdout.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuvycsnoise-main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yuvycsnoise.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< yuvkineco-main.o: main.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvkineco_CFLAGS) $(CFLAGS) -MT yuvkineco-main.o -MD -MP -MF $(DEPDIR)/yuvkineco-main.Tpo -c -o yuvkineco-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/yuvkineco-main.Tpo $(DEPDIR)/yuvkineco-main.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='main.c' object='yuvkineco-main.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvkineco_CFLAGS) $(CFLAGS) -c -o yuvkineco-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c yuvkineco-main.obj: main.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvkineco_CFLAGS) $(CFLAGS) -MT yuvkineco-main.obj -MD -MP -MF $(DEPDIR)/yuvkineco-main.Tpo -c -o yuvkineco-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/yuvkineco-main.Tpo $(DEPDIR)/yuvkineco-main.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='main.c' object='yuvkineco-main.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvkineco_CFLAGS) $(CFLAGS) -c -o yuvkineco-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` yuvycsnoise-main.o: main.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvycsnoise_CFLAGS) $(CFLAGS) -MT yuvycsnoise-main.o -MD -MP -MF $(DEPDIR)/yuvycsnoise-main.Tpo -c -o yuvycsnoise-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/yuvycsnoise-main.Tpo $(DEPDIR)/yuvycsnoise-main.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='main.c' object='yuvycsnoise-main.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvycsnoise_CFLAGS) $(CFLAGS) -c -o yuvycsnoise-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c yuvycsnoise-main.obj: main.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvycsnoise_CFLAGS) $(CFLAGS) -MT yuvycsnoise-main.obj -MD -MP -MF $(DEPDIR)/yuvycsnoise-main.Tpo -c -o yuvycsnoise-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/yuvycsnoise-main.Tpo $(DEPDIR)/yuvycsnoise-main.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='main.c' object='yuvycsnoise-main.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(yuvycsnoise_CFLAGS) $(CFLAGS) -c -o yuvycsnoise-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool clean-noinstLTLIBRARIES cscopelist \ ctags distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mjpegtools-2.1.0/yuvfilters/yuvfilters.h0000644000175000017500000000663110210446740021016 0ustar glowwormglowworm/* -*- mode:C -*- */ /* * Copyright (C) 2001 Kawamata/Hitoshi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __YUVFILTERS_H__ #define __YUVFILTERS_H__ #include #ifdef MJPEGTOOLS # include # include # include #endif #include #ifdef __cplusplus extern "C" { #endif #ifdef MJPEGTOOLS # define perror(MSG) mjpeg_error("%s: %s", MSG, strerror(errno)) # define WERROR(MSG) mjpeg_error(MSG) # define WERRORL(MSG) mjpeg_error(MSG) # define WWARN(MSG) mjpeg_warn(MSG) #else # define WERROR(MSG) write(2, MSG "\n", sizeof MSG) # define WERRORL(MSG) do { write(2, MSG, strlen(MSG)); write(2, "\n", 1); } while (0) # define WWARN(MSG) WERROR("warning: " MSG) #endif typedef struct { y4m_frame_info_t fi; uint8_t data[0]; } YfFrame_t; #define CWDIV(C) (((C)==Y4M_CHROMA_444)?1:((C)==Y4M_CHROMA_411)?4:2) #define CHDIV(C) \ (((C)==Y4M_CHROMA_444||(C)==Y4M_CHROMA_422||(C)==Y4M_CHROMA_411)?1:2) #define DATABYTES(C,W,H) \ (((W)*(H))+(((C)==Y4M_CHROMA_MONO)?0:(((W)/CWDIV(C))*((H)/CHDIV(C))*2))) #define FRAMEBYTES(C,W,H) (sizeof ((YfFrame_t *)0)->fi + DATABYTES(C,W,H)) struct YfTaskClass_tag; typedef struct YfTaskCore_tag { /* private: filter may not touch */ const struct YfTaskClass_tag *method; struct YfTaskCore_tag *handle_outgoing; /* protected: filter must set */ y4m_stream_info_t si; int width, height, fpscode; } YfTaskCore_t; typedef struct YfTaskClass_tag { const char *(*usage)(void); YfTaskCore_t *(*init)(int argc, char **argv, const YfTaskCore_t *h0); void (*fini)(YfTaskCore_t *handle); int (*frame)(YfTaskCore_t *handle, const YfTaskCore_t *h0, const YfFrame_t *frame0); } YfTaskClass_t; #define DECLARE_YFTASKCLASS(name) \ extern const YfTaskClass_t name #define DEFINE_YFTASKCLASS(sclass, prefix, name) \ sclass const char *prefix##_usage(void); \ sclass YfTaskCore_t *prefix##_init(int argc, char **argv, const YfTaskCore_t *h0); \ sclass void prefix##_fini(YfTaskCore_t *handle); \ sclass int prefix##_frame(YfTaskCore_t *handle, const YfTaskCore_t *h0, const YfFrame_t * frame0); \ const YfTaskClass_t name = { prefix##_usage, prefix##_init, prefix##_fini, prefix##_frame, } #define DEFINE_STD_YFTASKCLASS(name) DEFINE_YFTASKCLASS(static,do,name) extern int verbose; extern YfTaskCore_t *YfAllocateTask(const YfTaskClass_t *filter, size_t size, const YfTaskCore_t *h0); extern void YfFreeTask(YfTaskCore_t *handle); extern YfFrame_t *YfInitFrame(YfFrame_t *frame, const YfTaskCore_t *h0); extern void YfFiniFrame(YfFrame_t *frame); extern int YfPutFrame(const YfTaskCore_t *handle, const YfFrame_t *frame); extern YfTaskCore_t *YfAddNewTask(const YfTaskClass_t *filter, int argc, char **argv, const YfTaskCore_t *h0); #ifdef __cplusplus } #endif #endif mjpegtools-2.1.0/yuvfilters/yuvstdin.c0000644000175000017500000000443410210446740020461 0ustar glowwormglowworm/* * Copyright (C) 2001 Kawamata/Hitoshi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include "yuvfilters.h" DEFINE_STD_YFTASKCLASS(yuvstdin); static const char * do_usage(void) { return ""; } static YfTaskCore_t * do_init(int argc, char **argv, const YfTaskCore_t *h0) { int framebytes; YfTaskCore_t *h; y4m_stream_info_t si; --argc; ++argv; h = NULL; y4m_init_stream_info(&si); if (y4m_read_stream_header(0, &si) != Y4M_OK) goto FINI_SI; framebytes = FRAMEBYTES(y4m_si_get_chroma(&si), y4m_si_get_width(&si), y4m_si_get_height(&si)); h = YfAllocateTask(&yuvstdin, sizeof *h + framebytes, h0); if (!h) goto FINI_SI; y4m_copy_stream_info(&h->si, &si); h->width = y4m_si_get_width(&si); h->height = y4m_si_get_height(&si); h->fpscode = mpeg_framerate_code(y4m_si_get_framerate(&si)); FINI_SI: y4m_fini_stream_info(&si); return h; } static void do_fini(YfTaskCore_t *handle) { YfFreeTask(handle); } static int do_frame(YfTaskCore_t *handle, const YfTaskCore_t *h0, const YfFrame_t * frame) { YfTaskCore_t *h = handle; YfFrame_t *f = (YfFrame_t *)(h + 1); int ret; unsigned char * yuv[3]; YfInitFrame(f, h); yuv[0] = f->data; yuv[1] = yuv[0] + (h->width * h->height); yuv[2] = yuv[1] + ((h->width / CWDIV(y4m_si_get_chroma(&h->si))) * (h->height / CHDIV(y4m_si_get_chroma(&h->si)))); while ((ret = y4m_read_frame(0, &h->si, &f->fi, yuv)) == Y4M_OK) { if ((ret = YfPutFrame(h, f)) != Y4M_OK) break; } YfFiniFrame(f); return ret; } mjpegtools-2.1.0/yuvfilters/yuvkineco.c0000644000175000017500000006511610344745276020632 0ustar glowwormglowworm/* * Copyright (C) 2001,2002 Kawamata/Hitoshi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include "yuvfilters.h" #define NOISERATIO(N) (((N)+63)/64*63) #define MAXHALFHEIGHT 288 #define NOISEMAX 31 #define DEINTLRESO 1000 #define DEFAULTDTHR16 4 #define DEFAULTNOISE 10 #define DEFAULTDEINTL 10 static void buf_debug(char *buf, FILE *fp, const char *format, ...) { size_t n; va_list ap; va_start(ap, format); vsprintf(buf + strlen(buf), format, ap); va_end(ap); if (buf[(n = strlen(buf) - 1)] == '\n') { if (fp) { fputs(buf, fp); } else { #ifdef MJPEGTOOLS buf[n] = '\0'; mjpeg_debug(buf); #else fputs(buf, stderr); #endif } buf[0] = '\0'; } } typedef struct { YfTaskCore_t _; int fpscode0; FILE *cyfp; int cytype; int nfields; int nframes; int iget; int iuse; int iput; YfFrame_t *frame; int dthr16; int deintl; int nointlmax, deintlmin; unsigned int deintlframes; unsigned int deintldist[100]; union { struct { /* use in 1st try */ unsigned long dist[NOISEMAX+1]; unsigned long total; unsigned int level0, level; } noise; struct { /* use in retry */ char buff[32]; char *p; } cy; } u; struct { unsigned long odiff; /* odd field (or non-intarlaced frame) diff */ unsigned long ediff; /* even field diff (only when interlaced) */ long eoediff; /* previous even - odd - even diff */ unsigned long diffdist[NOISEMAX+1]; } framestat[0]; } YfTask_t; DEFINE_STD_YFTASKCLASS(yuvkineco); DECLARE_YFTASKCLASS(yuvycsnoise); static const char * do_usage(void) { return "[-{u|s}] [-F OutputFPSCODE] [-S YCSNoiseThreashold] [-n NoiseLevel] " "[-c CycleSearchThreashold] [-i DeinterlacePixelsPermil] " "{[-C OutputCycleListName] | -[ON] InputCycleListName}"; } static YfTaskCore_t * do_init(int argc, char **argv, const YfTaskCore_t *h0) { int fpscode; int nframes, nfields; YfTask_t *h; int c; int cytype = 0; char *cyname = NULL; char *ycsthres = NULL; YfTaskCore_t *hycs = NULL; int dthr16 = DEFAULTDTHR16; int noiselevel = DEFAULTNOISE; int deintlval = DEFAULTDEINTL; int output_interlace = 0; fpscode = h0->fpscode; while ((c = getopt(argc, argv, "usF:S:n:c:i:C:O:N:")) != -1) { switch (c) { case 'u': output_interlace = 1; break; case 's': output_interlace = 2; break; case 'F': fpscode = atoi(optarg); break; case 'S': ycsthres = optarg; break; case 'n': noiselevel = atoi(optarg); break; case 'c': dthr16 = atoi(optarg); break; case 'i': deintlval = atoi(optarg); break; case 'C': case 'O': case 'N': cytype = c; cyname = optarg; break; default: return NULL; } } if (cytype != 'N' && (h0->fpscode < 3 || 5 < h0->fpscode)) { WERROR("unsupported input fps"); return NULL; } if (fpscode < 1 || h0->fpscode < fpscode) { WERROR("illegal output fpscode"); return NULL; } if (y4m_si_get_interlace(&h0->si) == Y4M_ILACE_BOTTOM_FIRST) { WERROR("unsupported field order"); return NULL; } if (ycsthres) { char ycssopt[] = "-S"; char *ycsargv[] = { argv[0], ycssopt, ycsthres, NULL, }; optind = 1; if (!(hycs = YfAddNewTask(&yuvycsnoise, (sizeof ycsargv / sizeof ycsargv[0]) - 1, ycsargv, h0))) return NULL; } nframes = ((cytype && cytype != 'C')? 2: (h0->fpscode == 3)? 49: 9); nfields = ((y4m_si_get_interlace(&h0->si) == Y4M_UNKNOWN)? (MAXHALFHEIGHT < h0->height): y4m_si_get_interlace(&h0->si)) + 1; if (deintlval < 0 || nfields == 1 || (cytype && cytype != 'C')) deintlval = -1; else if (2 * DEINTLRESO < deintlval) deintlval = 2 * DEINTLRESO; if (dthr16 < 0) dthr16 = 0; else if (32 < dthr16) dthr16 = 32; if (noiselevel < 0) noiselevel = 0; else if (255 < noiselevel) noiselevel = 255; h = (YfTask_t *) YfAllocateTask(&yuvkineco, (sizeof *h + ((((!cytype || cytype == 'C')? (sizeof h->framestat[0]): 0) + FRAMEBYTES(y4m_si_get_chroma(&h0->si), h0->width, h0->height)) * nframes) + ((0 <= deintlval)? FRAMEBYTES(y4m_si_get_chroma(&h0->si), h0->width, h0->height): 0)), (hycs? hycs: h0)); if (!h) return NULL; if (output_interlace == 2 && (y4m_si_get_interlace(&h0->si) != Y4M_ILACE_TOP_FIRST || CHDIV(y4m_si_get_chroma(&h0->si)) != 2)) output_interlace = 3; y4m_si_set_interlace(&h->_.si, ((output_interlace == 1)? Y4M_UNKNOWN: (output_interlace == 2)? Y4M_ILACE_TOP_FIRST: Y4M_ILACE_NONE)); h->_.fpscode = fpscode; h->fpscode0 = h0->fpscode; h->cytype = cytype; h->nfields = nfields; h->nframes = nframes; h->frame = (YfFrame_t *)(h->framestat + (nframes * (!cytype || cytype == 'C'))); h->dthr16 = dthr16; h->deintl = deintlval * DATABYTES(y4m_si_get_chroma(&h0->si), h0->width, h0->height) / (2*DEINTLRESO); h->nointlmax = -1; h->deintlmin = 0x7fffffff; h->u.noise.level0 = h->u.noise.level = noiselevel; if (0 <= h->deintl) nframes++; while (0 <= --nframes) YfInitFrame((YfFrame_t *)((char *)h->frame + (nframes * FRAMEBYTES(y4m_si_get_chroma(&h0->si), h0->width, h0->height))), &h->_); if (!cytype) goto RETURN; if ((h->cyfp = fopen(cyname, ((cytype == 'C')? "w": "r"))) == NULL) { perror(cyname); goto ERROR_RETURN; } if (cytype == 'C') { fprintf(h->cyfp, "# 2-3 pull down cycle list\n" "# Generated by 'yuvkineco%s -F%d%s%s -n%d -c%d -i%d -C %s'\n" "#\n" "# Each character in list mean how each frame processed:\n" "# O,o: output\n" "# D,d: deinterlaced and output\n" "# X,x: bottom field replaced by previous one and output\n" "# M,m: bottom field replaced by previous one and deinterlaced and output\n" "# _: dropped\n" "# Lower case characters mean output but might drop if framerate was lower.\n" "#\n" "# You can edit this list by hand and retry yuvkineco.\n" "# When edit, you can use characters in addition to above:\n" "# E,e: always deinterlace\n" "# Y,y: always replace bottom field by previous one\n" "# N,n: always replace bottom field by previous one and deinterlace\n" "# T,t: duplicate top field\n" "# B,b: duplicate bottom field\n" "# Upper case characters mean always output.\n" "# Lower case characters mean output or drop according to framerate.\n" "#\n" "# Use this list with old input to generator yuvkineco,\n" "# do 'yuvkineco -F fpscode -O %s',\n" "# with output new,\n" "# do 'yuvkineco -F fpscode -N %s'.\n" "#\n" "# When used as '-O %s':\n" "# O,o: output\n" "# D,d,E,e: deinterlace and output\n" "# X,x,Y,y: replace bottom field by previous one and output\n" "# M,m,N,n: replace bottom field by previous one and deinterlace and output\n" "# T,t: duplicate top field and output\n" "# B,b: duplicate bottom field and output\n" "# _: drop\n" "#\n" "# When used as '-N %s':\n" "# O,o,X,x,D,d,M,m: output\n" "# E,e: deinterlace and output\n" "# Y,y: replace bottom field by previous one and output\n" "# N,n: replace bottom field by previous one and deinterlace and output\n" "# T,t: duplicate top field and output\n" "# B,b: duplicate bottom field and output\n" "# _: ignore\n" "#\n" "SIZE:%dx%d OLD_FPS:%d NEW_FPS:%d # DON'T CHANGE THIS LINE!!!", ((output_interlace == 1)? " -u": (2 <= output_interlace)? " -s": ""), fpscode, (ycsthres? " -S": ""), (ycsthres? ycsthres: ""), noiselevel, dthr16, deintlval, cyname, cyname, cyname, cyname, cyname, h0->width, h0->height, h0->fpscode, fpscode); } else { int width, height, oldfps, newfps; char buff[128]; h->u.cy.p = h->u.cy.buff; buff[sizeof buff - 1] = buff[sizeof buff - 2] = '\0'; while (fgets(buff, sizeof buff, h->cyfp)) { if (sscanf(buff, "SIZE:%dx%d OLD_FPS:%d NEW_FPS:%d ", &width, &height, &oldfps, &newfps) == 4) { if (width != h0->width || height != h0->height || ((h->cytype == 'O')? oldfps: newfps) != h0->fpscode) { WERROR("input and cycle list not match."); goto ERROR; } if (h->cytype == 'O' && newfps < fpscode) { WERROR("output fpscode greater than specified at 1st try."); goto ERROR; } goto RETURN; } } WERROR("broken cycle list."); ERROR: fclose(h->cyfp); goto ERROR_RETURN; } RETURN: return (YfTaskCore_t *)h; ERROR_RETURN: if (0 <= h->deintl) h->nframes++; while (0 <= --h->nframes) YfFiniFrame((YfFrame_t *)((char *)h->frame + (h->nframes * FRAMEBYTES(y4m_si_get_chroma(&h0->si), h0->width, h0->height)))); YfFreeTask((YfTaskCore_t *)h); return NULL; } static void dumpnoise(YfTask_t *h, FILE *fp) { int i; char buf[256]; if (!h->u.noise.total) return; buf[0] = '\0'; buf_debug(buf, fp, "#\n"); buf_debug(buf, fp, "# noise level: %u (# of sample: %lu); noise distribution:\n", h->u.noise.level, h->u.noise.total); buf_debug(buf, fp, "#"); for (i = 0; i <= NOISEMAX; i++) buf_debug(buf, fp, " %lu", (unsigned long)((((uint64_t)h->u.noise.dist[i] * 1000) + h->u.noise.total - 1) / h->u.noise.total)); buf_debug(buf, fp, "\n"); if (0 <= h->deintl) { int bytes = DATABYTES(y4m_si_get_chroma(&h->_.si), h->_.width, h->_.height); buf_debug(buf, fp, "# deinterlaced frames: %u; pixels/frame distribution:", h->deintlframes); for (i = 0; i < sizeof h->deintldist / sizeof h->deintldist[0]; i++) { if (!(i % 10)) { buf_debug(buf, fp, "\n"); buf_debug(buf, fp, "# %3d:", i); } buf_debug(buf, fp, "%7u", h->deintldist[i]); } buf_debug(buf, fp, "\n"); buf_debug(buf, fp, "# maximum permil of non-interlaced frames: %3d\n", h->nointlmax * (2 * DEINTLRESO) / bytes); buf_debug(buf, fp, "# minimum permil of deinterlaced frames: %3d\n", ((h->deintlmin == 0x7fffffff)? -1: (h->deintlmin * (2 * DEINTLRESO) / bytes))); } } static void do_fini(YfTaskCore_t *handle) { YfTask_t *h = (YfTask_t *)handle; while (h->iuse < h->iget) do_frame((YfTaskCore_t *)h, NULL, NULL); if (1 < verbose) dumpnoise(h, NULL); if (h->cytype == 'C') { putc('\n', h->cyfp); dumpnoise(h, h->cyfp); fclose(h->cyfp); } if (0 <= h->deintl) h->nframes++; while (0 <= --h->nframes) YfFiniFrame((YfFrame_t *)((char *)h->frame + (h->nframes * FRAMEBYTES(y4m_si_get_chroma(&h->_.si), h->_.width, h->_.height)))); YfFreeTask((YfTaskCore_t *)h); } static void putcy(YfTask_t *h, int c) { MPEG_timecode_t tc; int f; f = mpeg_timecode(&tc, h->iuse, h->fpscode0, 0.); if (f <= 0) { putc('\n', h->cyfp); if (tc.s == 0) { if (tc.m % 10 == 0) dumpnoise(h, h->cyfp); fputs("#\n" "# OLD NEW 0.... 5.... 10....15.... 20....25....\n", h->cyfp); } fprintf(h->cyfp, "%06d/%02d:%02d:%02d:%02d ", h->iuse, tc.h, tc.m, tc.s, tc.f); mpeg_timecode(&tc, h->iput, h->_.fpscode, 0.); fprintf(h->cyfp, "%06d/%02d:%02d:%02d:%02d", h->iput, tc.h, tc.m, tc.s, tc.f); } if (f < 0) { int i; f = -f; for (i = -1; i <= f; i++) putc(' ', h->cyfp); } if (f % 10 == 0) putc(' ', h->cyfp); if (f % 5 == 0) putc(' ', h->cyfp); if (c != '_' && h->framestat[h->iuse % h->nframes].eoediff == -9999999) c += 'X' - 'O'; putc(c, h->cyfp); } static int deinterlace(YfTask_t *h, unsigned char *data, int width, int height, int noise) { int pln, i, j, n = 0; for (pln = 0; pln < 3; pln++) { for (i = 1; i < height - 1; i += 2) { for (j = 0; j < width; j++) { int ymin = data[((i - 1) * width) + j]; int ynow = data[((i ) * width) + j]; int ymax = data[((i + 1) * width) + j]; int ynxt = data[((i + 2) * width) + j]; if (ymax < ymin) { int ytmp = ymax; ymax = ymin; ymin = ytmp; } ymin -= noise; ymax += noise; if ((ynow < ymin && ynxt < ymin ) || (ymax < ynow && ymax < ynxt )) n++; else if (!(ynow < ymin || ymax < ynow)) continue; #if 0 if (i < height - 3) { int ynx2 = data[((i + 3) * width) + j]; if ((ynx2 < ynxt && ynxt < ymin) || (ymax < ynxt && ynxt < ynx2)) continue; } #endif ynow = (ymin + ymax) / 2; data[((i ) * width) + j] = ynow; if (i < height - 3) { #if 0 int ynx2 = data[((i + 4) * width) + j]; if ((ynx2 < ymin && ynxt < ymin) || (ymax < ynx2 && ymax < ynxt)) #endif continue; } data[((i + 2) * width) + j] = ynow; } } data += width * height; if (pln == 0) { width /= CWDIV(y4m_si_get_chroma(&h->_.si)); height /= CHDIV(y4m_si_get_chroma(&h->_.si)); } } return n; } static int putframe(YfTask_t *h, int c, YfFrame_t *frame) { if (c <= 1) { if (c) deinterlace(h, frame->data, h->_.width, h->_.height, h->u.noise.level0); } else { if (0 <= h->deintl) { int n; int bytes = FRAMEBYTES(y4m_si_get_chroma(&h->_.si), h->_.width, h->_.height); YfFrame_t *fdst = (YfFrame_t *)((char *)h->frame + (h->nframes * bytes)); y4m_copy_frame_info(&fdst->fi, &frame->fi); memcpy(fdst->data, frame->data, bytes - sizeof frame->fi); n = deinterlace(h, fdst->data, h->_.width, h->_.height, h->u.noise.level0); if (h->deintl < n) { frame = fdst; c -= 'O' - 'D'; h->deintlframes++; if (n < h->deintlmin) h->deintlmin = n; } else { if (h->nointlmax < n) h->nointlmax = n; } n *= (2 * DEINTLRESO); n /= (bytes - sizeof frame->fi); if (sizeof h->deintldist / sizeof h->deintldist[0] <= n) n = (sizeof h->deintldist / sizeof h->deintldist[0]) - 1; h->deintldist[n]++; } if (h->cytype == 'C') putcy(h, c); } return YfPutFrame(&h->_, frame); } static int do_frame(YfTaskCore_t *handle, const YfTaskCore_t *h0, const YfFrame_t *frame0) { static const unsigned long fp1001s[] = { 0, 24000, 24024, 25025, 30000, 30030, 50050, 60000, 60060, }; YfTask_t *h = (YfTask_t *)handle; int framebytes = FRAMEBYTES(y4m_si_get_chroma(&h->_.si), h->_.width, h->_.height); int iadjust = ((h->_.fpscode == h->fpscode0)? 1: (((int64_t)h->iuse * fp1001s[h->_.fpscode] / fp1001s[h->fpscode0]) - h->iput)); int wdiv = CWDIV(y4m_si_get_chroma(&h->_.si)); int hdiv = CHDIV(y4m_si_get_chroma(&h->_.si)); /* copy frame to buffer */ if (frame0) { int b = h->iget % h->nframes; YfFrame_t *fget = (YfFrame_t *)((char *)h->frame + (b * framebytes)); y4m_copy_frame_info(&fget->fi, &frame0->fi); memcpy(fget->data, frame0->data, framebytes - sizeof frame0->fi); /* get frame summary */ if (h->cytype == 'O' || h->cytype =='N') { /* do nothing */ } else if (!h->iget) { h->framestat[b].odiff = 0 /* 9999999 */; h->framestat[b].ediff = 0 /* 9999999 */; } else { int i, j, d; unsigned int ypre, yget; unsigned int noise; int ipre = (h->iget - 1) % h->nframes; YfFrame_t *fpre = (YfFrame_t *)((char *)h->frame + (ipre * framebytes)); memset(&h->framestat[b], 0, sizeof h->framestat[b]); for (i = h->nfields; i < h->_.height; i += h->nfields) { for (j = 0; j < h->_.width; j++) { ypre = fpre->data[(i * h->_.width) + j]; yget = fget->data[(i * h->_.width) + j]; noise = h->u.noise.level0; if (yget < noise) noise = yget; else if (256 - yget < noise) noise = 256 - yget; d = abs(ypre - yget); h->framestat[b].diffdist[(d < NOISEMAX)? d: NOISEMAX]++; if (noise < d) { d -= noise; h->framestat[b].odiff += (((d * d) + 8) >> 4); } if (1 < h->nfields) { unsigned int ygte; ypre = fpre->data[((i - 1) * h->_.width) + j]; ygte = fget->data[((i - 1) * h->_.width) + j]; d = abs(yget - ygte); if (noise < d) { d -= noise; h->framestat[b].eoediff -= (((d * d) + 16) >> 5); } d = abs(yget - ypre); if (noise < d) { d -= noise; h->framestat[b].eoediff += (((d * d) + 16) >> 5); } ypre = fpre->data[((i + 1) * h->_.width) + j]; ygte = fget->data[((i + 1) * h->_.width) + j]; d = abs(yget - ygte); if (noise < d) { d -= noise; h->framestat[b].eoediff -= (((d * d) + 16) >> 5); } d = abs(yget - ypre); if (noise < d) { d -= noise; h->framestat[b].eoediff += (((d * d) + 16) >> 5); } d = abs(ypre - ygte); if (noise < d) { d -= noise; h->framestat[b].ediff += (((d * d) + 8) >> 4); } } } } #define PER1024PIXEL(p,h,w) (((p)/=(w)), ((p)<<=10), ((p)/=(h))) PER1024PIXEL(h->framestat[b].odiff, ((h->_.height / h->nfields) - 1), h->_.width); if (1 < h->nfields) { PER1024PIXEL(h->framestat[b].ediff, ((h->_.height / 2) - 1), h->_.width); PER1024PIXEL(h->framestat[b].eoediff, ((h->_.height / 2) - 1), h->_.width); } } h->iget++; } if (!h->cytype || h->cytype =='C') { /* 1st try */ /* process frames in buffer */ if (h->iget - h->iuse == h->nframes || !frame0) { int b = h->iuse % h->nframes; int i, idrp; unsigned long dthr = 0; char notdrop[48]; char debugbuf[1024]; debugbuf[0] = '\0'; if (1 < verbose) { MPEG_timecode_t tc; mpeg_timecode(&tc, h->iput, h->_.fpscode, 0.); buf_debug(debugbuf, NULL, "%02d:%02d:%02d ", tc.m, tc.s, tc.f); } { /* get threshold */ unsigned long dmin = 0xffffffffUL, dmax = 0; int imin = -1, imax = -1; for (i = 0; i < h->iget - h->iuse - 1; i++) { unsigned long odiff = h->framestat[(b + i) % h->nframes].odiff; if (1 < verbose) buf_debug(debugbuf, NULL, "%8ld:%-7lu", h->framestat[(b + i) % h->nframes].eoediff, odiff); if (odiff < dmin) { dmin = odiff; imin = i; /* maybe repeated field */ } if (dmax < odiff) { dmax = odiff; imax = i; /* maybe cut changed */ } } for (i = 0; i < h->iget - h->iuse - 1; i++) if (i != imin && i != imax) dthr += h->framestat[(b + i) % h->nframes].odiff; /* sum */ if (0 < i - 2) { dthr /= (i - 2); /* average */ dthr -= dmin; dthr *= h->dthr16; dthr += 15; /* round up */ dthr >>= 4; /* /= 16 */ dthr += dmin; dthr += h->u.noise.level0; } } /* search frame to drop */ memset(notdrop, ((1 < h->nfields)? '2': '0'), sizeof notdrop); notdrop[h->iget - h->iuse - 1] = '\0'; /* check motion top field (or frame of non-interlaced) */ for (i = 0; i < h->iget - h->iuse - 1; i++) if (dthr < h->framestat[(b + i) % h->nframes].odiff) notdrop[i] |= 1; if (1 < h->nfields) { /* check field merged */ int merged = 0; #if 0 /* codes for video editing fade-in/out */ long dmax = -0x7fffffffL, d2nd = -0x7fffffffL, d3rd = -0x7fffffffL; for (i = 1; i < (h->nframes / 2) + 2 && i < h->iget - h->iuse; i++) { long eoediff = h->framestat[(b + i) % h->nframes].eoediff; if (eoediff == -9999999) continue; if (dmax < eoediff) { d3rd = d2nd; d2nd = dmax; dmax = eoediff; } else if (d2nd < eoediff) { d3rd = d2nd; d2nd = eoediff; } else if (d3rd < eoediff) { d3rd = eoediff; } } if (d3rd == -0x7fffffffL) d3rd = 0; if (1 < verbose) buf_debug(debugbuf, NULL, "%6ld", d3rd); for (i = 1; i < (h->nframes / 2) + 2 && i < h->iget - h->iuse; i++) if (h->framestat[(b + i) % h->nframes].eoediff < d3rd - (long)dthr) #else for (i = 1; i < h->iget - h->iuse - 1; i++) if (h->framestat[(b + i) % h->nframes].eoediff < -(long)dthr) #endif { merged = 1; notdrop[i - 1] &= ~2; notdrop[i ] &= ~2; } if (!merged) for (i = 0; i < h->iget - h->iuse - 1; i++) notdrop[i] &= ~2; } idrp = h->nframes / 2; if (h->iget - h->iuse - 1 < idrp) idrp = h->iget - h->iuse - 1; while (0 <= idrp && notdrop[idrp] != '0') idrp--; if (idrp < 0) { idrp = h->nframes / 2; if (h->iget - h->iuse - 1 < idrp) idrp = h->iget - h->iuse - 1; while (0 <= idrp && (notdrop[idrp] & 1)) idrp--; } if (idrp < 0 && (h->nframes / 2) + 1 < h->iget - h->iuse - 1) { idrp = (h->nframes / 2) + 1; while (idrp < h->iget - h->iuse - 1 && (notdrop[idrp] & 1)) idrp++; if (idrp == h->iget - h->iuse - 1) { idrp = h->nframes / 2; goto DONE; } } if (idrp == h->nframes / 2) { unsigned long noisetotal; int bdrp; #if 0 int diff1024; #endif for (i = 0; i < idrp; i++) if (notdrop[i] == '0') goto DONE; /* calculate noise level */ while ((noisetotal = (h->u.noise.total + (((h->_.height / h->nfields) - 1) * h->_.width))) < h->u.noise.total) /* overflow */ for (h->u.noise.total = 0, i = 0; i <= NOISEMAX; i++) h->u.noise.total += (h->u.noise.dist[i] >>= 1); h->u.noise.total = noisetotal; bdrp = (b + idrp) % h->nframes; for (i = 0; i <= NOISEMAX; i++) h->u.noise.dist[i] += h->framestat[bdrp].diffdist[i]; noisetotal = NOISERATIO(noisetotal); for (i = 0; i <= NOISEMAX; i++) { if (noisetotal < h->u.noise.dist[i]) break; noisetotal -= h->u.noise.dist[i]; } #if 0 diff1024 = (i - h->u.noise.level) * 1024; #endif h->u.noise.level = i; #if 0 if (diff1024) { for (i = 0; i < h->nframes; i++) { if (diff1024 < -(int)h->framestat[i].odiff) h->framestat[i].odiff = 0; else h->framestat[i].odiff += diff1024; } if (1 < h->nfields) for (i = 0; i < h->nframes; i++) { if (diff1024 < -(int)h->framestat[i].ediff) h->framestat[i].ediff = 0; else h->framestat[i].ediff += diff1024; } } #endif } DONE: if (1 < verbose) buf_debug(debugbuf, NULL, "%3d%7lu %s%3d%3u", iadjust, dthr, notdrop, idrp, h->u.noise.level); /* reconstruct frame field merged */ if (1 < h->nfields) { int isrc, isrc0; isrc0 = ((0 < iadjust && 0 < idrp)? (idrp - 1): idrp); isrc = idrp + (h->nframes / 4) - 1; if (h->iget - h->iuse - 2 < isrc) isrc = h->iget - h->iuse - 2; for (; isrc0 <= isrc; --isrc) { int bsrc = (b + isrc) % h->nframes; int bdst = (bsrc + 1) % h->nframes; if ((isrc < idrp + (h->nframes / 4) - 1 || dthr < h->framestat[bdst].ediff) && h->framestat[bdst].eoediff <= 0 && h->framestat[bdst].eoediff != -9999999) { YfFrame_t *fsrc = (YfFrame_t *)((char *)h->frame + (bsrc * framebytes)); YfFrame_t *fdst = (YfFrame_t *)((char *)h->frame + (bdst * framebytes)); for (i = 1; i < h->_.height; i += 2) /* copy bottom field Y */ memcpy(&fdst->data[i * h->_.width], &fsrc->data[i * h->_.width], h->_.width); for (i = (h->_.height * wdiv) + 1; i < h->_.height * (wdiv + (2 / hdiv)); i += 2) /* UV */ memcpy(&fdst->data[i * h->_.width / wdiv], &fsrc->data[i * h->_.width / wdiv], h->_.width / wdiv); if (1 < verbose) buf_debug(debugbuf, NULL, "%2d", isrc + 1); h->framestat[bdst].eoediff = -9999999; } else { if (1 < verbose) buf_debug(debugbuf, NULL, " -"); } } } if (1 < verbose) buf_debug(debugbuf, NULL, "\n"); /* output frames */ for (i = 0; i < idrp; i++) { int ret; YfFrame_t *fout = (YfFrame_t *)((char *)h->frame + (b * framebytes)); if ((ret = putframe(h, 'O', fout))) return ret; h->iput++; h->iuse++; b = h->iuse % h->nframes; } if (h->iuse < h->iget) { YfFrame_t *fout = (YfFrame_t *)((char *)h->frame + (b * framebytes)); if (iadjust <= 0) { if (h->cytype == 'C') putcy(h, '_'); } else { int ret; if ((ret = putframe(h, 'o', fout))) return ret; h->iput++; } h->iuse++; } } } else { /* retry */ int i, c; YfFrame_t *fsrc, *fdst; int deintl = 0; while (!*h->u.cy.p) { char *s, *d; char buff[128]; d = h->u.cy.p = h->u.cy.buff; if (!fgets(buff, sizeof buff, h->cyfp)) { perror("cycle list"); return 1; } for (s = buff; (c = *s); s++) { /* FIXME: frame# should be checked */ if (c == '#') break; if (isalpha(c) || (c == '_' && h->cytype == 'O')) { if (h->u.cy.buff + 30 <= d) { WWARN("too long line in cycle list."); break; } *d++ = c; } } *d = '\0'; } fsrc = (YfFrame_t *)((char *)h->frame + (((h->iuse - 1) % h->nframes) * framebytes)); fdst = (YfFrame_t *)((char *)h->frame + (((h->iuse) % h->nframes) * framebytes)); h->iuse++; c = *h->u.cy.p++; if (c == '_') return 0; if (islower(c)) { if (iadjust <= 0) return 0; c += 'A' - 'a'; } switch (c) { case 'D': case 'M': if (h->cytype == 'N') goto DEINTLDECIDED; /* else do as E, N */ case 'E': case 'N': deintl = 1; DEINTLDECIDED: c += 'O' - 'D'; /* D->O, M->X, E->P(do as O), N->Y */ break; } i = 0; switch (c) { case 'X': if (h->cytype == 'N') break; /* else do as Y */ case 'Y': for (i = 1; i < h->_.height; i += 2) /* copy bottom field Y */ memcpy(&fdst->data[i * h->_.width], &fsrc->data[i * h->_.width], h->_.width); for (i = (h->_.height * wdiv) + 1; i < h->_.height * (wdiv + (2 / hdiv)); i += 2) /* UV */ memcpy(&fdst->data[i * h->_.width / wdiv], &fsrc->data[i * h->_.width / wdiv], h->_.width / wdiv); break; case 'T': for (i = 0; i < h->_.height; i += 2) /* duplicate top field Y */ memcpy(&fdst->data[(i + 1) * h->_.width], &fdst->data[(i) * h->_.width], h->_.width); for (i = (h->_.height * wdiv); i < h->_.height * (wdiv + (2 / hdiv)); i += 2) /* UV */ memcpy(&fdst->data[(i + 1) * h->_.width / wdiv], &fsrc->data[(i) * h->_.width / wdiv], h->_.width / wdiv); break; case 'B': for (i = 0; i < h->_.height; i += 2) /* duplicate bottom field Y */ memcpy(&fdst->data[(i) * h->_.width], &fdst->data[(i + 1) * h->_.width], h->_.width); for (i = (h->_.height * wdiv); i < h->_.height * (wdiv + (2 / hdiv)); i += 2) /* UV */ memcpy(&fdst->data[(i) * h->_.width / wdiv], &fsrc->data[(i + 1) * h->_.width / wdiv], h->_.width / wdiv); break; } if ((c = putframe(h, deintl, fdst))) return c; h->iput++; if (i || deintl) memcpy(fdst->data, frame0->data, framebytes - sizeof frame0->fi); } return 0; } mjpegtools-2.1.0/yuvfilters/yuvycsnoise.c0000644000175000017500000003321510210446740021173 0ustar glowwormglowworm/* * Copyright (C) 2001 Kawamata/Hitoshi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include "yuvfilters.h" typedef struct { YfTaskCore_t _; unsigned int iframe; unsigned char flags; unsigned char min; unsigned char maxt, maxb, maxi, maxc; unsigned char errt, errb, erri, errc; YfFrame_t frame; } YfTask_t; /* bits of flags */ #define TESTNOISE 1 #define TRIFRAME 2 #define BIFRAME 4 #define INFIELD 8 #define CHROMA 16 #define ALLMETHODS (TRIFRAME|BIFRAME|INFIELD|CHROMA) DEFINE_STD_YFTASKCLASS(yuvycsnoise); static const char * do_usage(void) { return "[-t] [-m {tbic}] [-S min] [-T errt,maxt] [-B errb,maxb] [-I erri,maxi] [-C errc,maxc]"; } static YfTaskCore_t * do_init(int argc, char **argv, const YfTaskCore_t *h0) { YfTask_t *h; int c; unsigned int flags = ALLMETHODS; int min = 4; int maxt = 255, maxb = 255, maxi = 255, maxc = 255; int errt = 32, errb = 32, erri = 16, errc = 12; while ((c = getopt(argc, argv, "tm:S:T:B:I:C:")) != -1) { switch (c) { case 't': flags |= TESTNOISE; break; case 'm': flags &= ~ALLMETHODS; for (; *optarg; optarg++) switch (*optarg) { case 't': flags |= TRIFRAME; break; case 'b': flags |= BIFRAME; break; case 'i': flags |= INFIELD; break; case 'c': flags |= CHROMA; break; } break; case 'S': sscanf(optarg, "%d", &min); case 'T': switch (sscanf(optarg, "%d,%d", &errt, &maxt)) { case 0: sscanf(optarg, ",%d", &maxt); break; } break; case 'B': switch (sscanf(optarg, "%d,%d", &errb, &maxb)) { case 0: sscanf(optarg, ",%d", &maxb); break; } break; case 'I': switch (sscanf(optarg, "%d,%d", &erri, &maxi)) { case 0: sscanf(optarg, ",%d", &maxi); break; } break; case 'C': switch (sscanf(optarg, "%d,%d", &errc, &maxc)) { case 0: sscanf(optarg, ",%d", &maxc); break; } break; } } if (min < 1 || maxt < min || 255 < maxt || maxb < min || 255 < maxb || maxi < min || 255 < maxi || maxc < min || 255 < maxi) { WERROR("illeagal threshold"); return NULL; } if (errt < 1 || 255 < errt || errb < 1 || 255 < errb || erri < 1 || 255 < erri || errc < 1 || 255 < errc) { WERROR("illeagal error"); return NULL; } if (y4m_si_get_interlace(&h0->si) == Y4M_ILACE_BOTTOM_FIRST) { WERROR("unsupported field order"); return NULL; } if (h0->height != 480 || h0->fpscode != 4) WWARN("input doesn't seem NTSC full height / full motion video"); h = (YfTask_t *) YfAllocateTask(&yuvycsnoise, (sizeof *h + DATABYTES(y4m_si_get_chroma(&h0->si), h0->width, h0->height) + /* frame */ (DATABYTES(y4m_si_get_chroma(&h0->si), h0->width, h0->height) * 4) + /* frprv, frnow, dfprv, dfnow */ ((h0->width / CWDIV(y4m_si_get_chroma(&h0->si))) * (h0->height / CHDIV(y4m_si_get_chroma(&h0->si))) * 2) + /* dfpr2 */ (h0->width * h0->height * 2) + (h0->width * 2)), /* dlprv, dlnow */ h0); if (!h) return NULL; h->flags = flags; h->min = min; h->maxt = maxt; h->maxb = maxb; h->maxi = maxi; h->maxc = maxc; h->errt = errt; h->errb = errb; h->erri = erri; h->errc = errc; YfInitFrame(&h->frame, &h->_); return (YfTaskCore_t *)h; } static void do_fini(YfTaskCore_t *handle) { YfTask_t *h = (YfTask_t *)handle; do_frame(handle, NULL, NULL); YfFiniFrame(&h->frame); YfFreeTask(handle); } static void uvnoise(YfTask_t *h, char *dfpr2_u, char *dfprv, char *dfnow, unsigned char *frprv, unsigned char *frnow, const unsigned char *frnxt) { int uw, uh, x, y; char *dfpr2_v, *dfprv_u, *dfprv_v, *dfnow_u, *dfnow_v; unsigned char *frprv_u, *frprv_v, *frnow_u, *frnow_v; const unsigned char *frnxt_u, *frnxt_v; unsigned char *frout_u, *frout_v; if (!(h->flags & CHROMA)) return; uw = h->_.width / CWDIV(y4m_si_get_chroma(&h->_.si)); uh = h->_.height / CHDIV(y4m_si_get_chroma(&h->_.si)); dfpr2_v = dfpr2_u + (uw * uh); dfprv_u = dfprv + (h->_.width * h->_.height); dfprv_v = dfprv_u + (uw * uh); dfnow_u = dfnow + (h->_.width * h->_.height); dfnow_v = dfnow_u + (uw * uh); frprv_u = frprv + (h->_.width * h->_.height); frprv_v = frprv_u + (uw * uh); frnow_u = frnow + (h->_.width * h->_.height); frnow_v = frnow_u + (uw * uh); frnxt_u = frnxt + (h->_.width * h->_.height); frnxt_v = frnxt_u + (uw * uh); frout_u = h->frame.data + (h->_.width * h->_.height); frout_v = frout_u + (uw * uh); for (y = 0; y < uh; y++) { int i, i0, i1; i = (uw * y); if (y & 1) { i0 = h->_.width * ((y * 2) - 1); i1 = h->_.width * ((y * 2) + 1); } else { i0 = h->_.width * ((y * 2)); i1 = h->_.width * ((y * 2) + 2); } for (x = 0; x < uw; x++, i++, i0 +=2, i1 += 2) { int d0; if ((((d0 = dfnow_u[i]) && dfprv_u[i] && dfprv_u[i] != d0 && dfpr2_u[i] && dfpr2_u[i] == d0) || ((d0 = dfnow_v[i]) && dfprv_v[i] && dfprv_v[i] != d0 && dfpr2_v[i] && dfpr2_v[i] == d0)) && frprv_u[i] - h->errc < frnxt_u[i] && frnxt_u[i] < frprv_u[i] + h->errc && frprv_v[i] - h->errc < frnxt_v[i] && frnxt_v[i] < frprv_v[i] + h->errc && frnow[i0] - (h->errc + h->min) < frprv[i0] && frprv[i0] < frnow[i0] + (h->errc + h->min) && frnxt[i0] - (h->errc) < frprv[i0] && frprv[i0] < frnxt[i0] + (h->errc) && frnow[i1] - (h->errc + h->min) < frprv[i1] && frprv[i1] < frnow[i1] + (h->errc + h->min) && frnxt[i1] - (h->errc) < frprv[i1] && frprv[i1] < frnxt[i1] + (h->errc) && frnow[i0+1] - (h->errc + h->min) < frprv[i0+1] && frprv[i0+1] < frnow[i0+1] + (h->errc + h->min) && frnxt[i0+1] - (h->errc) < frprv[i0+1] && frprv[i0+1] < frnxt[i0+1] + (h->errc) && frnow[i1+1] - (h->errc + h->min) < frprv[i1+1] && frprv[i1+1] < frnow[i1+1] + (h->errc + h->min) && frnxt[i1+1] - (h->errc) < frprv[i1+1] && frprv[i1+1] < frnxt[i1+1] + (h->errc)) { d0 = (frprv_u[i] + frnxt_u[i]) / 2; d0 -= frnow_u[i]; d0 /= 2; if (-h->maxc <= d0 && d0 <= h->maxc) frout_u[i] = ((h->flags & TESTNOISE)? 0: (frnow_u[i] + d0)); d0 = (frprv_v[i] + frnxt_v[i]) / 2; d0 -= frnow_v[i]; d0 /= 2; if (-h->maxc <= d0 && d0 <= h->maxc) frout_v[i] = ((h->flags & TESTNOISE)? 0: (frnow_v[i] + d0)); } } } } static void ynoise(YfTask_t *h, int btmfld, char *dnow, char *daux, char *dfprv, char *dfnow, unsigned char *frprv, unsigned char *frnow, const unsigned char *frnxt) { char *dprv, *dnxt, *dffld, *dfaux; const unsigned char *fraux; int x, y; if (!btmfld) { /* top field */ dprv = daux; dnxt = dnow; dffld = dfprv; dfaux = dfnow; fraux = frprv; } else { /* bottom field */ dprv = dnow; dnxt = daux; dffld = dfnow; dfaux = dfprv; fraux = frnxt; } for (y = btmfld; y < h->_.height; y += 2) { for (x = 0; x < h->_.width; x++) { int max; int i0 = (h->_.width * (y)) + x; int i1 = (h->_.width * (y + 1)) + x; int j1 = (h->_.width * (y - 1)) + x; int i2 = (h->_.width * (y + 2)) + x; int d0 = dfprv[i0]; if ((h->flags & TRIFRAME) && d0 && dfnow[i0] && dfnow[i0] != d0 && (!dffld[j1] || dffld[j1] == d0) && (!dffld[i1] || dffld[i1] != d0) && (!dfaux[j1] || dfaux[j1] != d0) && (!dfaux[i1] || dfaux[i1] == d0) && frprv[i0] - h->errt < frnxt[i0] && frnxt[i0] < frprv[i0] + h->errt && frprv[j1] - h->errt < frnxt[j1] && frnxt[j1] < frprv[j1] + h->errt && frprv[i1] - h->errt < frnxt[i1] && frnxt[i1] < frprv[i1] + h->errt) { max = h->maxt; d0 = (frprv[i0] + frnxt[i0]) / 2; goto YNOISE; } d0 = dnow[i0]; if (d0 && dnow[i2] && dnow[i2] != d0) { int j2 = (h->_.width * (y - 2)) + x; if ((h->flags & BIFRAME) && dprv[i1] && dprv[i1] == d0 && dnxt[i1] && dnxt[i1] != d0 && daux[i0] && daux[i0] != d0 && daux[i2] && daux[i2] == d0 && frnow[i0] - h->errb < fraux[j2] && fraux[j2] < frnow[i0] + h->errb && frnow[i0] - h->errb < fraux[i2] && fraux[i2] < frnow[i0] + h->errb && frnow[i1] - h->errb < fraux[j1] && fraux[j1] < frnow[i1] + h->errb && fraux[i1] - h->errb < frnow[j1] && frnow[j1] < fraux[i1] + h->errb && fraux[i0] - h->errb < frnow[j2] && frnow[j2] < fraux[i0] + h->errb && fraux[i0] - h->errb < frnow[i2] && frnow[i2] < fraux[i0] + h->errb) { max = h->maxb; goto YNOISE_XI; } else { int i4 = (h->_.width * (y + 4)) + x; int j4 = (h->_.width * (y - 4)) + x; int i6 = (h->_.width * (y + 6)) + x; int j6 = (h->_.width * (y - 6)) + x; if ((h->flags & INFIELD) && dnow[j2] && dnow[j2] != d0 && dnow[i4] && dnow[i4] == d0 && dnow[j4] && dnow[j4] == d0 && dnow[i6] && dnow[i6] != d0 && !(daux[i0] && daux[i0] == d0 && daux[i2] && daux[i2] != d0 && daux[j2] && daux[j2] != d0 && daux[i4] && daux[i4] == d0 && daux[j4] && daux[j4] == d0 && daux[i6] && daux[i6] != d0) && frnow[i0] - h->erri < frnow[j4] && frnow[j4] < frnow[i0] + h->erri && frnow[i0] - h->erri < frnow[i4] && frnow[i4] < frnow[i0] + h->erri && frnow[j2] - h->erri < frnow[j6] && frnow[j6] < frnow[j2] + h->erri && frnow[j2] - h->erri < frnow[i2] && frnow[i2] < frnow[j2] + h->erri && frnow[i2] - h->erri < frnow[i6] && frnow[i6] < frnow[i2] + h->erri) { max = h->maxi; goto YNOISE_XI; } } continue; YNOISE_XI: d0 = (frnow[j2] + frnow[i2]) / 2; goto YNOISE; } continue; YNOISE: d0 -= frnow[i0]; d0 /= 2; if (-max <= d0 && d0 <= max) h->frame.data[i0] = ((h->flags & TESTNOISE)? 0: (frnow[i0] + d0)); } } } /* * triframe biframe infield * prv now nxt prv now nxt now * T B T B T B T B T B T B T B T B T B * -4 - + - + - + - + t * -3 + - + - + - + - | b * -2 + - + - t t + - t | * -1 - t-----t-----t | t | t - + | b * 0 - t-----T-----t t | T | - + t | * 1 + t-----t-----t | t | t + - | b * 2 + - + - t t + - T | * -2 - + - + - b b + | B * -1 - b-----b-----b - b | b | + t | * 0 + b-----B-----b + | B | b - | b * 1 + b-----b-----b + b | b | - t | * 2 - + - + - b b + | b * 3 - + - + - + - + t | * 4 + - + - + - + - b */ static int do_frame(YfTaskCore_t *handle, const YfTaskCore_t *h0, const YfFrame_t *frame0) { YfTask_t *h = (YfTask_t *)handle; int databytes = DATABYTES(y4m_si_get_chroma(&h->_.si), h->_.width, h->_.height); const unsigned char *frnxt = frame0->data; unsigned char *frprv = h->frame.data + databytes; unsigned char *frnow = frprv + databytes; char *dfprv = (char *)frnow + databytes; char *dfnow = dfprv + databytes; char *dfpr2 = dfnow + databytes; char *dlprv = dfpr2 + ((h->_.width / CWDIV(y4m_si_get_chroma(&h->_.si))) * (h->_.height / CHDIV(y4m_si_get_chroma(&h->_.si))) * 2); char *dlnow = dlprv + (h->_.width * h->_.height); #define dlnxt dlprv if (h->iframe & 1) { char *tmp; tmp = (char *)frprv; frprv = frnow; frnow = (unsigned char *)tmp; tmp = dfprv; dfprv = dfnow; dfnow = tmp; tmp = dlprv; dlprv = dlnow; dlnow = tmp; } if (h->flags & CHROMA) memcpy(dfpr2, dfnow + (h->_.width * h->_.height), (h->_.width / CWDIV(y4m_si_get_chroma(&h->_.si))) * (h->_.height / CHDIV(y4m_si_get_chroma(&h->_.si))) * 2); /* dfnow: 2 frames ago */ if (!frame0) frnxt = frnow; if (h->flags & (CHROMA|TRIFRAME)) { if (!frame0) { memset(dfnow, 0, databytes); } else { int i; for (i = 0; i < databytes; i++) { int d = frnow[i] - frnxt[i]; dfnow[i] = ((d <= -h->min)? -1: (h->min <= d)? 1: 0); } } } if (h->iframe) { memcpy(h->frame.data, frnow, databytes); uvnoise(h, dfpr2, dfprv, dfnow, frprv, frnow, frnxt); ynoise(h, 0, dlnow, dlprv, dfprv, dfnow, frprv, frnow, frnxt); /* top field */ } if (h->flags & (BIFRAME|INFIELD)) { if (!frame0) { memset(dlnxt, 0, h->_.width * h->_.height); } else { int x, y; for (y = 2; y < h->_.height; y++) { for (x = 0; x < h->_.width; x++) { int j2 = (h->_.width * (y - 2)) + x; int i0 = (h->_.width * (y)) + x; int d = frnxt[j2] - frnxt[i0]; dlnxt[i0] = ((d <= -h->min)? -1: (h->min <= d)? 1: 0); } } } } if (h->iframe) { int ret; ynoise(h, 1, dlnow, dlnxt, dfprv, dfnow, frprv, frnow, frnxt); /* bottom field */ if ((ret = YfPutFrame(&h->_, &h->frame))) return ret; } if (!frame0) return 0; memcpy(frprv, frnxt, databytes); /* frprv: frnow at next */ h->iframe++; return 0; } mjpegtools-2.1.0/yuvfilters/TODO0000644000175000017500000000250007331566600017120 0ustar glowwormglowworm# -*- mode:Outline -*- (DONE) * yuvycsnoise Noise filter specialized for NTSC Y/C separation noise. Only Y noise reduced because UV noise should be removed when convert to 4:2:0 from 4:2:2. ** add method don't use previous frame but compare more pixels ** UV noise * yuvkineco ** insert yuvycsnoise ** BUG: when "-N CycleList", permit InputFPSCODE < 4 * yuvfilter Replace main.c. All filter statically linked (or dynamically load filter), from command line arguments, generate pipeline of filters. * yuvycsnoise ** speed up * yuvkineco ** add munual command *** W?: replace whole frame by previous *** Y?: replace top field by previous ** ditect cut change Use different field compare threshold at after cut changed from after new cycle detected. *** cut changed at bottom field in a frame: deinterlace? ** add options *** deinterlace (line double) *** not output yuv for only create cycle list (needed?) *** field compare threshold [3/2] *** field compare threshold after cut changed *** noise level threshold [7/8] *** initial noise level [5] *** ? ** speed up ** gstreamer plugin? * lavkineco ** only do 2nd try ** replace MJPEG fields without decode/encode ** implement as gstreamer plugin? * gkineco interactive kineco with GUI ** implement as gstreamer plugin? * wrapper for yuvfilters to be gstreamer filter mjpegtools-2.1.0/yuvfilters/alloctask.c0000644000175000017500000000261607437714622020567 0ustar glowwormglowworm/* * Copyright (C) 2001 Kawamata/Hitoshi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include "yuvfilters.h" YfTaskCore_t * YfAllocateTask(const YfTaskClass_t *filter, size_t size, const YfTaskCore_t *h0) { YfTaskCore_t *h = malloc(size); if (!h) { perror("malloc"); return NULL; } memset(h, 0, size); h->method = filter; h->handle_outgoing = NULL; y4m_init_stream_info(&h->si); if (h0) { y4m_copy_stream_info(&h->si, &h0->si); h->width = h0->width; h->height = h0->height; h->fpscode = h0->fpscode; } return h; } void YfFreeTask(YfTaskCore_t *handle) { y4m_fini_stream_info(&handle->si); free(handle); } mjpegtools-2.1.0/yuvfilters/main.c0000644000175000017500000000442410210446740017517 0ustar glowwormglowworm/* * Copyright (C) 2001 Kawamata/Hitoshi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include "yuvfilters.h" #ifdef FILTER # define MODULE FILTER #else # ifdef READER # define MODULE READER # else # define MODULE WRITER # endif #endif #ifndef READER #define READER yuvstdin #endif #ifndef WRITER #define WRITER yuvstdout #endif DECLARE_YFTASKCLASS(READER); DECLARE_YFTASKCLASS(WRITER); #ifdef FILTER DECLARE_YFTASKCLASS(FILTER); #endif int verbose = 1; static void usage(char **argv) { char buf[1024]; sprintf(buf, "Usage: %s %s", argv[0], (*MODULE.usage)()); WERRORL(buf); } int main(int argc, char **argv) { YfTaskCore_t *h, *hreader; int ret; char *p; if (1 < argc && (!strcmp(argv[1], "-?") || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) { usage(argv); return 0; } if ((p = getenv("MJPEG_VERBOSITY"))) verbose = atoi(p); y4m_accept_extensions(1); ret = 1; #ifndef FILTER if (!(hreader = YfAddNewTask(&READER, argc, argv, NULL))) goto RETURN; #else if (!(hreader = YfAddNewTask(&READER, argc, argv, NULL))) goto RETURN; if (!YfAddNewTask(&FILTER, argc, argv, hreader)) goto FINI; #endif if (!YfAddNewTask(&WRITER, argc, argv, hreader)) goto FINI; ret = (*READER.frame)(hreader, NULL, NULL); if (ret == Y4M_ERR_EOF) ret = Y4M_OK; if (ret != Y4M_OK) WERRORL(y4m_strerr(ret)); FINI: for (h = hreader; h; h = hreader) { hreader = h->handle_outgoing; (*h->method->fini)(h); } RETURN: return ret; } mjpegtools-2.1.0/yuvfilters/initframe.c0000644000175000017500000000234310210446740020547 0ustar glowwormglowworm/* * Copyright (C) 2001 Kawamata/Hitoshi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include "yuvfilters.h" YfFrame_t * YfInitFrame(YfFrame_t *frame, const YfTaskCore_t *h0) { if (!frame) { if (!(frame = malloc(FRAMEBYTES(y4m_si_get_chroma(&h0->si), h0->width, h0->height)))) { perror("malloc"); return NULL; } } y4m_init_frame_info(&frame->fi); return frame; } void YfFiniFrame(YfFrame_t *frame) { y4m_fini_frame_info(&frame->fi); } mjpegtools-2.1.0/y4munsharp/0000755000175000017500000000000012217306501016320 5ustar glowwormglowwormmjpegtools-2.1.0/y4munsharp/Makefile.am0000644000175000017500000000056710254331122020360 0ustar glowwormglowworm# Makefile.am for y4munsharp MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I $(top_srcdir)/utils -I $(top_srcdir) y4munharp_CFLAGS=@PROGRAM_NOPIC@ bin_PROGRAMS = y4munsharp y4munsharp_SOURCES = y4munsharp.c y4munsharp_LDADD = \ $(top_builddir)/utils/libmjpegutils.la \ @LIBM_LIBS@ if HAVE_ALTIVEC y4munsharp_LDADD += $(top_builddir)/mpeg2enc/libmpeg2encpp.la endif mjpegtools-2.1.0/y4munsharp/y4munsharp.c0000644000175000017500000004413011255225227020606 0ustar glowwormglowworm/* * $Id: y4munsharp.c,v 1.11 2009/09/19 19:01:43 sms00 Exp $ * * Constructed using: * unsharp.c 0.10 -- This is a plug-in for the GIMP 1.0 * Copyright (C) 1999 Winston Chang / * * * Rewritten/modified from the GIMP unsharp plugin into y4munsharp by * Steven Schultz * * 2004/11/10 - used the core functions of the unsharp plugin and wrote a * y4m filter program. The original plugin was allocated/deallocated * memory for each picture/frame and of course that had to be done in a * more efficient manner. Additional work involved handling interlaced * input for the column blur function. * * By default only the LUMA (Y') is processed. Processing the CHROMA * (CbCr) can, in some cases, result in color shifts where the edge * enhancement is done. If it is desired to process the CHROMA planes * -C option must be given explicitly. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" #include #include #include #include #include #include #define MAX(a,b) ((a) >= (b) ? (a) : (b)) #define ROUND(x) ((int) ((x) + 0.5)) void usage(char *); void y4munsharp(void); static void get_column(u_char *, u_char *, int, int); static void put_column(u_char *, u_char *, int, int); static void blur_line (double *, double *, int, u_char *, u_char *, int ); static double *gen_lookup_table (double *, int); static int gen_convolve_matrix(double, double **); u_char *i_yuv[3], *o_yuv[3], *cur_col, *dest_col, *cur_row, *dest_row; double y_radius = 2.0, y_amount = 0.30; double uv_radius = -1.0, uv_amount; int y_threshold = 4, uv_threshold, frameno; int interlaced, ywidth, uvwidth, yheight, uvheight, ylen, uvlen; int cmatrix_y_len, cmatrix_uv_len; double *cmatrix_y, *cmatrix_uv, *ctable_y, *ctable_uv; int lowy = 16, highy = 235, lowuv = 16, highuv = 240; int main(int argc, char **argv) { int fdin, fdout, err, c, i, verbose = 1; y4m_stream_info_t istream, ostream; y4m_frame_info_t iframe; fdin = fileno(stdin); fdout = fileno(stdout); y4m_accept_extensions(1); y4m_init_stream_info(&istream); y4m_init_frame_info(&iframe); while ((c = getopt(argc, argv, "L:C:hv:N")) != EOF) { switch (c) { case 'N': lowuv = lowy = 0; lowuv = highy = 255; break; case 'L': i = sscanf(optarg, "%lf,%lf,%d", &y_radius, &y_amount, &y_threshold); if (i != 3) { mjpeg_error("-L r,a,t"); usage(argv[0]); } break; case 'C': i = sscanf(optarg, "%lf,%lf,%d", &uv_radius, &uv_amount, &uv_threshold); if (i != 3) { mjpeg_error("-C r,a,t"); usage(argv[0]); } break; case 'v': verbose = atoi(optarg); if (verbose < 0 || verbose > 2) mjpeg_error_exit1("-v 0|1|2"); break; case 'h': default: usage(argv[0]); break; } } if (isatty(fdout)) mjpeg_error_exit1("stdout must not be a terminal"); mjpeg_default_handler_verbosity(verbose); err = y4m_read_stream_header(fdin, &istream); if (err != Y4M_OK) mjpeg_error_exit1("Couldn't read input stream header"); switch (y4m_si_get_interlace(&istream)) { case Y4M_ILACE_NONE: interlaced = 0; break; case Y4M_ILACE_BOTTOM_FIRST: case Y4M_ILACE_TOP_FIRST: interlaced = 1; break; default: mjpeg_error_exit1("Unsupported/unknown interlacing"); } if (y4m_si_get_plane_count(&istream) != 3) mjpeg_error_exit1("Only 3 plane formats supported"); yheight = y4m_si_get_plane_height(&istream, 0); uvheight = y4m_si_get_plane_height(&istream, 1); ywidth = y4m_si_get_plane_width(&istream, 0); uvwidth = y4m_si_get_plane_width(&istream, 1); ylen = y4m_si_get_plane_length(&istream, 0); uvlen = y4m_si_get_plane_length(&istream, 1); /* Input and output frame buffers */ i_yuv[0] = (u_char *)malloc(ylen); i_yuv[1] = (u_char *)malloc(uvlen); i_yuv[2] = (u_char *)malloc(uvlen); o_yuv[0] = (u_char *)malloc(ylen); o_yuv[1] = (u_char *)malloc(uvlen); o_yuv[2] = (u_char *)malloc(uvlen); /* * general purpose row/column scratch buffers. Slightly over allocated to * simplify life. */ cur_col = (u_char *)malloc(MAX(ywidth, yheight)); dest_col = (u_char *)malloc(MAX(ywidth, yheight)); cur_row = (u_char *)malloc(MAX(ywidth, yheight)); dest_row = (u_char *)malloc(MAX(ywidth, yheight)); /* * Generate the convolution matrices. The generation routine allocates the * memory and returns the length. */ cmatrix_y_len = gen_convolve_matrix(y_radius, &cmatrix_y); cmatrix_uv_len = gen_convolve_matrix(uv_radius, &cmatrix_uv); ctable_y = gen_lookup_table(cmatrix_y, cmatrix_y_len); ctable_uv = gen_lookup_table(cmatrix_uv, cmatrix_uv_len); y4m_init_stream_info(&ostream); y4m_copy_stream_info(&ostream, &istream); y4m_write_stream_header(fileno(stdout), &ostream); mjpeg_info("Luma radius: %f", y_radius); mjpeg_info("Luma amount: %f", y_amount); mjpeg_info("Luma threshold: %d", y_threshold); if (uv_radius != -1.0) { mjpeg_info("Chroma radius: %f", uv_radius); mjpeg_info("Chroma amount: %f", uv_amount); mjpeg_info("Chroma threshold: %d", uv_threshold); } for (frameno = 0; y4m_read_frame(fdin, &istream, &iframe, i_yuv) == Y4M_OK; frameno++) { y4munsharp(); err = y4m_write_frame(fdout, &ostream, &iframe, o_yuv); if (err != Y4M_OK) { mjpeg_error("y4m_write_frame err at frame %d", frameno); break; } } y4m_fini_frame_info(&iframe); y4m_fini_stream_info(&istream); y4m_fini_stream_info(&ostream); exit(0); } /* * Uses the globals defined above - probably not the best practice in the world * but beats passing a jillion arguments or going to the effort of * encapsulation. */ void y4munsharp(void) { int i, row, col, diff, value; u_char *i_ptr, *o_ptr; mjpeg_debug("Blurring Luma rows frame %d", frameno); for (row = 0; row < yheight; row++) { blur_line(ctable_y, cmatrix_y, cmatrix_y_len, &i_yuv[0][row * ywidth], &o_yuv[0][row * ywidth], ywidth); } if (uv_radius != -1.0) { mjpeg_debug("Blurring Chroma rows frame %d", frameno); for (row = 0; row < uvheight; row++) { blur_line(ctable_uv, cmatrix_uv, cmatrix_uv_len, &i_yuv[1][row * uvwidth], &o_yuv[1][row * uvwidth], uvwidth); blur_line(ctable_uv, cmatrix_uv, cmatrix_uv_len, &i_yuv[2][row * uvwidth], &o_yuv[2][row * uvwidth], uvwidth); } } else { memcpy(o_yuv[1], i_yuv[1], uvlen); memcpy(o_yuv[2], i_yuv[2], uvlen); } mjpeg_debug("Blurring Luma columns frame %d", frameno); for (col = 0; col < ywidth; col++) { /* * Do the entire frame if progressive, otherwise this does the only * the first field. */ get_column(&o_yuv[0][col], cur_col, interlaced ? 2 * ywidth : ywidth, interlaced ? yheight / 2 : yheight); blur_line(ctable_y, cmatrix_y, cmatrix_y_len, cur_col, dest_col, interlaced ? yheight / 2 : yheight); put_column(dest_col, &o_yuv[0][col], interlaced ? 2 * ywidth : ywidth, interlaced ? yheight / 2 : yheight); /* * If interlaced now process the second field (data source is offset * by 'ywidth'). */ if (interlaced) { get_column(&o_yuv[0][col + ywidth], cur_col, 2 * ywidth, yheight / 2); blur_line(ctable_y, cmatrix_y, cmatrix_y_len, cur_col, dest_col, interlaced ? yheight / 2 : yheight); put_column(dest_col, &o_yuv[0][col + ywidth], 2 * ywidth, yheight / 2); } } if (uv_radius == -1) goto merging; mjpeg_debug("Blurring chroma columns frame %d", frameno); for (col = 0; col < uvwidth; col++) { /* U */ get_column(&o_yuv[1][col], cur_col, interlaced ? 2 * uvwidth : uvwidth, interlaced ? uvheight / 2 : uvheight); blur_line(ctable_uv, cmatrix_uv, cmatrix_uv_len, cur_col, dest_col, interlaced ? uvheight / 2 : uvheight); put_column(dest_col, &o_yuv[1][col], interlaced ? 2 * uvwidth : uvwidth, interlaced ? uvheight / 2 : uvheight); if (interlaced) { get_column(&o_yuv[1][col + uvwidth], cur_col, 2 * uvwidth, uvheight / 2); blur_line(ctable_uv, cmatrix_uv, cmatrix_uv_len, cur_col, dest_col, interlaced ? uvheight / 2 : uvheight); put_column(dest_col, &o_yuv[1][col + uvwidth], 2 * uvwidth, uvheight / 2); } /* V */ get_column(&o_yuv[2][col], cur_col, interlaced ? 2 * uvwidth : uvwidth, interlaced ? uvheight / 2 : uvheight); blur_line(ctable_uv, cmatrix_uv, cmatrix_uv_len, cur_col, dest_col, interlaced ? uvheight / 2 : uvheight); put_column(dest_col, &o_yuv[2][col], interlaced ? 2 * uvwidth : uvwidth, interlaced ? uvheight / 2 : uvheight); if (interlaced) { get_column(&o_yuv[2][col + uvwidth], cur_col, 2 * uvwidth, uvheight / 2); blur_line(ctable_uv, cmatrix_uv, cmatrix_uv_len, cur_col, dest_col, interlaced ? uvheight / 2 : uvheight); put_column(dest_col, &o_yuv[2][col + uvwidth], 2 * uvwidth, uvheight / 2); } } merging: mjpeg_debug("Merging luma frame %d", frameno); for (row = 0, i_ptr = i_yuv[0], o_ptr = o_yuv[0]; row < yheight; row++) { for (i = 0; i < ywidth; i++, i_ptr++, o_ptr++) { diff = *i_ptr - *o_ptr; if (abs(2 * diff) < y_threshold) diff = 0; value = *i_ptr + (y_amount * diff); /* * For video the limits are 16 and 235 for the luma rather than 0 and 255! */ if (value < lowy) value = lowy; else if (value > highy) value = highy; *o_ptr = value; } } if (uv_radius == -1.0) goto done; mjpeg_debug("Merging chroma frame %d", frameno); for (row = 0, i_ptr = i_yuv[1], o_ptr = o_yuv[1]; row < uvheight; row++) { for (i = 0; i < uvwidth; i++, i_ptr++, o_ptr++) { diff = *i_ptr - *o_ptr; if (abs(2 * diff) < uv_threshold) diff = 0; value = *i_ptr + (uv_amount * diff); /* * For video the limits are 16 and 240 for the chroma rather than 0 and 255! */ if (value < lowuv) value = lowuv; else if (value > highuv) value = highuv; *o_ptr = value; } } for (row = 0, i_ptr = i_yuv[2], o_ptr = o_yuv[2]; row < uvheight; row++) { for (i = 0; i < uvwidth; i++, i_ptr++, o_ptr++) { diff = *i_ptr - *o_ptr; if (abs(2 * diff) < uv_threshold) diff = 0; value = *i_ptr + (uv_amount * diff); /* * For video the limits are 16 and 240 for the chroma rather than 0 and 255! */ if (value < 16) value = 16; else if (value > highuv) value = highuv; *o_ptr = value; } } done: return; } void get_column(u_char *in, u_char *out, int stride, int numrows) { int i; for (i = 0; i < numrows; i++) { *out++ = *in; in += stride; } } void put_column(u_char *in, u_char *out, int stride, int numrows) { int i; for (i = 0; i < numrows; i++) { *out = *in++; out += stride; } } /* * The blur_line(), gen_convolve_matrix() and gen_lookup_table() functions * were lifted almost intact from the GIMP unsharp plugin. malloc was used * instead of g_new() and the style was cleaned up a little but the logic * was left untouched. */ /* this function is written as if it is blurring a column at a time, * even though it can operate on rows, too. There is no difference * in the processing of the lines, at least to the blur_line function. */ static void blur_line (double *ctable, double *cmatrix, int cmatrix_length, u_char *cur_col, u_char *dest_col, int y) { double scale, sum, *cmatrix_p, *ctable_p; int i=0, j=0, row, cmatrix_middle = cmatrix_length/2; u_char *cur_col_p, *cur_col_p1, *dest_col_p; /* this first block is the same as the non-optimized version -- * it is only used for very small pictures, so speed isn't a * big concern. */ if (cmatrix_length > y) { for (row = 0; row < y ; row++) { scale=0; /* find the scale factor */ for (j = 0; j < y ; j++) { /* if the index is in bounds, add it to the scale counter */ if ((j + cmatrix_length/2 - row >= 0) && (j + cmatrix_length/2 - row < cmatrix_length)) scale += cmatrix[j + cmatrix_length/2 - row]; } for (i = 0; i< 1; i++) { sum = 0; for (j = 0; j < y; j++) { if ((j >= row - cmatrix_length/2) && (j <= row + cmatrix_length/2)) sum += cur_col[j + i] * cmatrix[j]; } dest_col[row + i] = (u_char) ROUND (sum / scale); } } } else { /* for the edge condition, we only use available info and scale to one */ for (row = 0; row < cmatrix_middle; row++) { /* find scale factor */ scale=0; for (j = cmatrix_middle - row; j0; j--) { sum += *(ctable_p + *cur_col_p1); cur_col_p1 += 1; ctable_p += 256; } cur_col_p++; *(dest_col_p++) = ROUND (sum); } } /* for the edge condition, we only use available info, and scale to one */ for (; row < y; row++) { /* find scale factor */ scale=0; for (j = 0; j< y-row + cmatrix_middle; j++) scale += cmatrix[j]; for (i = 0; i < 1; i++) { sum = 0; for (j = 0; j/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = y4munsharp$(EXEEXT) @HAVE_ALTIVEC_TRUE@am__append_1 = $(top_builddir)/mpeg2enc/libmpeg2encpp.la subdir = y4munsharp DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_y4munsharp_OBJECTS = y4munsharp.$(OBJEXT) y4munsharp_OBJECTS = $(am_y4munsharp_OBJECTS) y4munsharp_DEPENDENCIES = $(top_builddir)/utils/libmjpegutils.la \ $(am__append_1) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(y4munsharp_SOURCES) DIST_SOURCES = $(y4munsharp_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALTIVEC_EXTRA_LIBS = @ALTIVEC_EXTRA_LIBS@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDV_CFLAGS = @LIBDV_CFLAGS@ LIBDV_LIBS = @LIBDV_LIBS@ LIBGETOPT_LIB = @LIBGETOPT_LIB@ LIBM_LIBS = @LIBM_LIBS@ LIBOBJS = @LIBOBJS@ LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ LIBPNG_LIBS = @LIBPNG_LIBS@ LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@ LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ LT_STATIC = @LT_STATIC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROGRAM_NOPIC = @PROGRAM_NOPIC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ SDLgfx_LIBS = @SDLgfx_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ V4LCONF_LIBS = @V4LCONF_LIBS@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I $(top_srcdir)/utils -I $(top_srcdir) y4munharp_CFLAGS = @PROGRAM_NOPIC@ y4munsharp_SOURCES = y4munsharp.c y4munsharp_LDADD = $(top_builddir)/utils/libmjpegutils.la @LIBM_LIBS@ \ $(am__append_1) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu y4munsharp/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu y4munsharp/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list y4munsharp$(EXEEXT): $(y4munsharp_OBJECTS) $(y4munsharp_DEPENDENCIES) $(EXTRA_y4munsharp_DEPENDENCIES) @rm -f y4munsharp$(EXEEXT) $(LINK) $(y4munsharp_OBJECTS) $(y4munsharp_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/y4munsharp.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool cscopelist ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mjpegtools-2.1.0/cpuinfo.sh0000755000175000017500000001764111247043711016224 0ustar glowwormglowworm#!/bin/sh if test x"$CC" = x; then CC=gcc fi if test $# -ne 1; then echo "Please give the arch (ppc or x86) as an argument!" 1>&2 exit 1 fi if test `uname -s` = Darwin; then IsDarwin=yes else IsDarwin=no fi target=$1 cc_version=`$CC -dumpversion` _cc_major=`echo $cc_version | cut -d'.' -f1` _cc_minor=`echo $cc_version | cut -d'.' -f2` if test $_cc_major -ge 4; then _opt_mcpu="-mtune" else _opt_mcpu="-mcpu" fi do_cc() { $CC -o conftest conftest.c $@ >/dev/null 2>&1 } extcheck() { cat > conftest.c < void catch() { exit(1); } int main(void){ signal(SIGILL, catch); __asm__ __volatile__ ("$1":::"memory"); exit(0); } EOF do_cc if test -x ./conftest; then ./conftest if test $? -ne 0; then return 1 fi return 0 else return 1 fi } do_x86() { CFLAGS=-O if test $IsDarwin = yes; then CFLAGS="$CFLAGS -fno-pic -Wl,-read_only_relocs -Wl,suppress" fi if test -r /proc/cpuinfo; then _cpuinfo="cat /proc/cpuinfo" else $CC $CFLAGS -o cpuinfo utils/cpuinfo.c _cpuinfo="./cpuinfo" fi # Cpu determination logic adapted from the MPlayer configure script. pname=`$_cpuinfo | grep 'model name' | cut -d ':' -f 2 | head -n 1` pvendor=`$_cpuinfo | grep 'vendor_id' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` pfamily=`$_cpuinfo | grep 'cpu family' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` pmodel=`$_cpuinfo | grep -v 'model name' | grep 'model' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` pstep=`$_cpuinfo | grep 'stepping' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` pparam=`$_cpuinfo | grep 'features' | cut -d':' -f2 | head -n 1` if test -z "$pparam" ; then pparam=`$_cpuinfo | grep 'flags' | cut -d ':' -f 2 | head -n 1` fi _mmx=no _3dnow=no _3dnowex=no _mmx2=no _sse=no _sse2=no _mtrr=no for i in $pparam ; do case "$i" in 3dnow) _3dnow=yes ;; 3dnowext) _3dnow=yes _3dnowex=yes ;; mmx) _mmx=yes ;; mmxext) _mmx2=yes ;; mtrr|k6_mtrr|cyrix_arr) _mtrr=yes ;; xmm|sse|kni) _sse=yes _mmx2=yes ;; sse2) _sse2=yes ;; esac done case "$pvendor" in AuthenticAMD) case "$pfamily" in 3)proc=i386 ;; 4) proc=i486 ;; 5) iproc=586 # models are: K5/SSA5 K5 K5 K5 ? ? K6 K6 K6-2 K6-3 # K6 model 13 are the K6-2+ and K6-III+ if test "$pmodel" -eq 9 -o "$pmodel" -eq 13; then proc=k6-3 elif test "$pmodel" -ge 8; then proc=k6-2 elif test "$pmodel" -ge 6; then proc=k6 else proc=i586 fi ;; 6) iproc=686 if test "$pmodel" -ge 7; then proc=athlon-4 elif test "$pmodel" -ge 6; then if test "$_sse" = yes && test "$pstep" -ge 2; then proc=athlon-xp else proc=athlon-4 fi elif test "$pmodel" -ge 4; then proc=athlon-tbird else proc=athlon fi ;; 15) # Despite what the gcc into says 'athlon64' is not accepted as # synonym for 'k8' proc=k8 ;; 16) proc=barcelona ;; *) proc=athlon-xp ;; esac ;; GenuineIntel) case "$pfamily" in 3) proc=i386 ;; 4) proc=i486 ;; 5) iproc=586 if test "$pmodel" -eq 4 || test "$pmodel" -eq 8; then proc=pentium-mmx # 4 is desktop, 8 is mobile else proc=i586 fi ;; 6) iproc=686 if test "$pmodel" -ge 23; then proc=core2 elif test "$pmodel" -ge 15; then proc=nocona elif test "$pmodel" -ge 13; then proc=pentium-m elif test "$pmodel" -ge 7; then proc=pentium3 elif test "$pmodel" -ge 3; then proc=pentium2 else proc=i686 fi ;; 15) proc=pentium4 ;; *) proc=pentium4 ;; esac ;; unknown) case "$pfamily" in 3) proc=i386 ;; 4) proc=i486 ;; *) proc=i586 ;; esac ;; *) proc=i586 ;; esac # check that gcc supports our CPU, if not, fall back to earlier ones cat > conftest.c << EOF int main(void) { return 0; } EOF if test "$proc" = "athlon64" ; then do_cc -march=$proc $_opt_mcpu=$proc || proc=athlon-xp fi if test "$proc" = "athlon-xp" || test "$proc" = "athlon-4" || test "$proc" = "athlon-tbird"; then do_cc -march=$proc $_opt_mcpu=$proc || proc=athlon fi if test "$proc" = "k6-3" || test "$proc" = "k6-2"; then do_cc -march=$proc $_opt_mcpu=$proc || proc=k6 fi if test "$proc" = "k6"; then do_cc -march=$proc $_opt_mcpu=$proc if test $? -ne 0; then if do_cc -march=i586 $_opt_mcpu=i686; then proc=i586-i686 else proc=i586 fi fi fi # Seems some variants of gcc accept 'core2' instead of 'nocona'. if test "$proc" = "core2"; then do_cc -march=$proc $_opt_mcpu=$proc || proc=nocona fi if test "$proc" = "pentium4" || test "$proc" = "pentium3" || test "$proc" = "pentium2" || test "$proc" = "athlon"; then do_cc -march=$proc $_opt_mcpu=$proc || proc=i686 fi if test "$proc" = "i686" || test "$proc" = "pentium-mmx"; then do_cc -march=$proc $_opt_mcpu=$proc || proc=i586 fi if test "$proc" = "i586" ; then do_cc -march=$proc $_opt_mcpu=$proc || proc=i486 fi if test "$proc" = "i486" ; then do_cc -march=$proc $_opt_mcpu=$proc || proc=i386 fi if test "$proc" = "i386" ; then do_cc -march=$proc $_opt_mcpu=$proc || proc=error fi if test "$proc" = "error" ; then echo "Your $CC does not even support \"i386\" for '-march' and $_opt_mcpu." _mcpu="" _march="" elif test "$proc" = "i586-i686"; then _march="-march=i586" _mcpu="$_opt_mcpu=i686" else _march="-march=$proc" _mcpu="$_opt_mcpu=$proc" fi if test $_cc_major -ge 3; then extcheck "xorps %%xmm0, %%xmm0" || _gcc3_ext="$_gcc3_ext -mno-sse" extcheck "xorpd %%xmm0, %%xmm0" || _gcc3_ext="$_gcc3_ext -mno-sse2" if test x"$_gcc3_ext" != "x"; then # if we had to disable sse/sse2 because the active kernel does not # support this instruction set extension, we also have to tell # gcc3 to not generate sse/sse2 instructions for normal C code cat > conftest.c << EOF int main(void) { return 0; } EOF do_cc $_march $_gcc3_ext && _march="$_march $_gcc3_ext" fi fi echo $_march $_mcpu rm -f conftest.c conftest cpuinfo return 0 } do_ppc() { # Linux on a PPC has /proc/info # Darwin (OS/X) has the hostinfo command # If neither of those we have no idea what to do - so do nothing. if test -r /proc/cpuinfo; then proc=`grep cpu /proc/cpuinfo | cut -d':' -f2 | cut -d',' -f1 | cut -b 2- | head -n 1` elif test $IsDarwin = yes; then proc=`hostinfo | grep "Processor type" | cut -f3 -d' ' | sed 's/ppc//'` else return 0 fi case "$proc" in 601) _march="$_opt_mcpu=601" _mcpu='-mtune=601' ;; 603) _march="$_opt_mcpu=603" _mcpu='-mtune=603' ;; 603e|603ev) _march="$_opt_mcpu=603e" _mcpu='-mtune=603e' ;; 604|604e|604r|604ev) _march="$_opt_mcpu=604" _mcpu='-mtune=604' ;; 740|740/750|745/755) _march="$_opt_mcpu=740" _mcpu='-mtune=740' ;; 750|750CX) _march="$_opt_mcpu=750" _mcpu='-mtune=750' ;; *) ;; esac # gcc 3.1(.1) and up supports 7400 and 7450 if test "$_cc_major" -ge "3" && test "$_cc_minor" -ge "1" || test "$_cc_major" -ge "4"; then case "$proc" in 7400*|7410*) _march="$_opt_mcpu=7400" _mcpu='-mtune=7400' ;; 7450*|7455*) _march="$_opt_mcpu=7450" _mcpu='-mtune=7450' ;; *) ;; esac fi # gcc 3.2 and up supports 970 if test "$_cc_major" -ge "3" && test "$_cc_minor" -ge "3" || test "$_cc_major" -ge "4"; then case "$proc" in 970*) if test $IsDarwin = yes; then _march="$_opt_mcpu=G5 -mpowerpc64 -mpowerpc-gpopt -falign-loops=16 -force_cpusubtype_ALL" _mcpu='-mtune=G5' else _march="$_opt_mcpu=970" _mcpu='-mtune=970' fi ;; *) ;; esac fi echo $_march $_mcpu return 0 } # # The script that runs the various functions above # if test $target = x86; then do_x86 elif test $target = ppc; then do_ppc fi mjpegtools-2.1.0/BUGS0000644000175000017500000000343411563465013014704 0ustar glowwormglowworm 1. MPEG2 support for progressive sequences frame (-F 0) and field-interlaced (-F 3) is now well tested. Field sequences (-F 1 and -F 2) appear to be working but aren't yet thoroughly tested and lack some recent optimisations available for progressive sequences. 2. Currently the VCD HR Stills muxing stuff assumes *all* HR stills are the same size which is given in the initial vbv_buffer_size... This will work with mpeg2enc (which does this) but will fail fail fail with other streams. 3. The VBVbuffer delay code in the MPEG encoder is hopeless broken. It is currently turned off and needs re-implementing from scratch. Not urgent though since no decoder ever seems to take any notice of it. Certainly I never figured out the the damn thing would be useful for once your mux-er has checked for /ensured video buffer size bounding. 4. mpeg2enc is currently broken for 422 and 444 video. The problem is that the calculations for checking chrominance in the the motion compensation search assume 2-pel sub-sampled U and V in X and Y. 5. lavplay, lavrec seek problem when you have movies that are longer than 2:30, they play back well but the slider in glav does not work proper when about 2:30 is reached 6. zoran card/lavrec problem on modern machines. It works only if you don't have more than 2GB of Ram. A patch exists but didn't make into the kernel. The Patch does not apply well on a newer Kernel thatn 2.6.20 7. mjpegtools do not compile when you have X11 an SDL installed. And disable SDL with a configure option. 8. 2.6.38 Kernels don't have v4l(1) any more. So lavrec does not work any more. Actually you can't compile lavrec. the configure script detects that and disables lavrec if the kernel headers for v4l are not found. lavrec should be updated to us v4l2 mjpegtools-2.1.0/ltmain.sh0000644000175000017500000105152212217306375016045 0ustar glowwormglowworm # libtool (GNU libtool) 2.4.2 # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, # 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, # or obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Usage: $progname [OPTION]... [MODE-ARG]... # # Provide generalized library-building support services. # # --config show all configuration variables # --debug enable verbose shell tracing # -n, --dry-run display commands without modifying any files # --features display basic configuration information and exit # --mode=MODE use operation mode MODE # --preserve-dup-deps don't remove duplicate dependency libraries # --quiet, --silent don't print informational messages # --no-quiet, --no-silent # print informational messages (default) # --no-warn don't display warning messages # --tag=TAG use configuration variables from tag TAG # -v, --verbose print more informational messages than default # --no-verbose don't print the extra informational messages # --version print version information # -h, --help, --help-all print short, long, or detailed help message # # MODE must be one of the following: # # clean remove files from the build directory # compile compile a source file into a libtool object # execute automatically set library path, then run a program # finish complete the installation of libtool libraries # install install libraries or executables # link create a library or an executable # uninstall remove libraries from an installed directory # # MODE-ARGS vary depending on the MODE. When passed as first option, # `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. # Try `$progname --help --mode=MODE' for a more detailed description of MODE. # # When reporting a bug, please describe a test case to reproduce it and # include the following information: # # host-triplet: $host # shell: $SHELL # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) # $progname: (GNU libtool) 2.4.2 # automake: $automake_version # autoconf: $autoconf_version # # Report bugs to . # GNU libtool home page: . # General help using GNU software: . PROGRAM=libtool PACKAGE=libtool VERSION=2.4.2 TIMESTAMP="" package_revision=1.3337 # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # NLS nuisances: We save the old values to restore during execute mode. lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${$lt_var+set}\" = set; then save_$lt_var=\$$lt_var $lt_var=C export $lt_var lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done LC_ALL=C LANGUAGE=C export LANGUAGE LC_ALL $lt_unset CDPATH # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath="$0" : ${CP="cp -f"} test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} # Global variables: EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. exit_status=$EXIT_SUCCESS # Make sure IFS has a sensible default lt_nl=' ' IFS=" $lt_nl" dirname="s,/[^/]*$,," basename="s,^.*/,," # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_dirname may be replaced by extended shell implementation # func_basename file func_basename () { func_basename_result=`$ECHO "${1}" | $SED "$basename"` } # func_basename may be replaced by extended shell implementation # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` } # func_dirname_and_basename may be replaced by extended shell implementation # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname may be replaced by extended shell implementation # These SED scripts presuppose an absolute path with a trailing slash. pathcar='s,^/\([^/]*\).*$,\1,' pathcdr='s,^/[^/]*,,' removedotparts=':dotsl s@/\./@/@g t dotsl s,/\.$,/,' collapseslashes='s@/\{1,\}@/@g' finalslash='s,/*$,/,' # func_normal_abspath PATH # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. # value returned in "$func_normal_abspath_result" func_normal_abspath () { # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` while :; do # Processed it all yet? if test "$func_normal_abspath_tpath" = / ; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result" ; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_relative_path SRCDIR DSTDIR # generates a relative path from SRCDIR to DSTDIR, with a trailing # slash if non-empty, suitable for immediately appending a filename # without needing to append a separator. # value returned in "$func_relative_path_result" func_relative_path () { func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=${func_dirname_result} if test "x$func_relative_path_tlibdir" = x ; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test "x$func_stripname_result" != x ; then func_relative_path_result=${func_relative_path_result}/${func_stripname_result} fi # Normalisation. If bindir is libdir, return empty string, # else relative path ending with a slash; either way, target # file name can be directly appended. if test ! -z "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result/" func_relative_path_result=$func_stripname_result fi } # The name of this program: func_dirname_and_basename "$progpath" progname=$func_basename_result # Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=$func_dirname_result progdir=`cd "$progdir" && pwd` progpath="$progdir/$progname" ;; *) save_IFS="$IFS" IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS="$save_IFS" test -x "$progdir/$progname" && break done IFS="$save_IFS" test -n "$progdir" || progdir=`pwd` progpath="$progdir/$progname" ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([`"$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' # Sed substitution that converts a w32 file name or path # which contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-`\' parameter expansions in output of double_quote_subst that were # `\'-ed in input to the same. If an odd number of `\' preceded a '$' # in input to double_quote_subst, that '$' was protected from expansion. # Since each input `\' is now two `\'s, look for any number of runs of # four `\'s followed by two `\'s and then a '$'. `\' that '$'. bs='\\' bs2='\\\\' bs4='\\\\\\\\' dollar='\$' sed_double_backslash="\ s/$bs4/&\\ /g s/^$bs2$dollar/$bs&/ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g s/\n//g" # Standard options: opt_dry_run=false opt_help=false opt_quiet=false opt_verbose=false opt_warning=: # func_echo arg... # Echo program name prefixed message, along with the current mode # name if it has been set yet. func_echo () { $ECHO "$progname: ${opt_mode+$opt_mode: }$*" } # func_verbose arg... # Echo program name prefixed message in verbose mode only. func_verbose () { $opt_verbose && func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_error arg... # Echo program name prefixed message to standard error. func_error () { $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 } # func_warning arg... # Echo program name prefixed warning message to standard error. func_warning () { $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 # bash bug again: : } # func_fatal_error arg... # Echo program name prefixed message to standard error, and exit. func_fatal_error () { func_error ${1+"$@"} exit $EXIT_FAILURE } # func_fatal_help arg... # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { func_error ${1+"$@"} func_fatal_error "$help" } help="Try \`$progname --help' for more information." ## default # func_grep expression filename # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $GREP "$1" "$2" >/dev/null 2>&1 } # func_mkdir_p directory-path # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { my_directory_path="$1" my_dir_list= if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then # Protect directory names starting with `-' case $my_directory_path in -*) my_directory_path="./$my_directory_path" ;; esac # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` done my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do IFS="$save_mkdir_p_IFS" # mkdir can fail with a `File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$my_dir" 2>/dev/null || : done IFS="$save_mkdir_p_IFS" # Bail out if we (or some other process) failed to create a directory. test -d "$my_directory_path" || \ func_fatal_error "Failed to create \`$1'" fi } # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$opt_dry_run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $MKDIR "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || \ func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi $ECHO "$my_tmpdir" } # func_quote_for_eval arg # Aesthetically quote ARG to be evaled later. # This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT # is double-quoted, suitable for a subsequent eval, whereas # FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters # which are still active within double quotes backslashified. func_quote_for_eval () { case $1 in *[\\\`\"\$]*) func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac case $func_quote_for_eval_unquoted_result in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and and variable # expansion for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" ;; *) func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" esac } # func_quote_for_expand arg # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { case $1 in *[\\\`\"]*) my_arg=`$ECHO "$1" | $SED \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; esac case $my_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") my_arg="\"$my_arg\"" ;; esac func_quote_for_expand_result="$my_arg" } # func_show_eval cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$my_cmd" my_status=$? if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_show_eval_locale cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$lt_user_locale $my_cmd" my_status=$? eval "$lt_safe_locale" if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_tr_sh # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_version # Echo version message to standard output and exit. func_version () { $opt_debug $SED -n '/(C)/!b go :more /\./!{ N s/\n# / / b more } :go /^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ p }' < "$progpath" exit $? } # func_usage # Echo short help message to standard output and exit. func_usage () { $opt_debug $SED -n '/^# Usage:/,/^# *.*--help/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" echo $ECHO "run \`$progname --help | more' for full usage" exit $? } # func_help [NOEXIT] # Echo long help message to standard output and exit, # unless 'noexit' is passed as argument. func_help () { $opt_debug $SED -n '/^# Usage:/,/# Report bugs to/ { :print s/^# // s/^# *$// s*\$progname*'$progname'* s*\$host*'"$host"'* s*\$SHELL*'"$SHELL"'* s*\$LTCC*'"$LTCC"'* s*\$LTCFLAGS*'"$LTCFLAGS"'* s*\$LD*'"$LD"'* s/\$with_gnu_ld/'"$with_gnu_ld"'/ s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ p d } /^# .* home page:/b print /^# General help using/b print ' < "$progpath" ret=$? if test -z "$1"; then exit $ret fi } # func_missing_arg argname # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $opt_debug func_error "missing argument for $1." exit_cmd=exit } # func_split_short_opt shortopt # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. func_split_short_opt () { my_sed_short_opt='1s/^\(..\).*$/\1/;q' my_sed_short_rest='1s/^..\(.*\)$/\1/;q' func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` } # func_split_short_opt may be replaced by extended shell implementation # func_split_long_opt longopt # Set func_split_long_opt_name and func_split_long_opt_arg shell # variables after splitting LONGOPT at the `=' sign. func_split_long_opt () { my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' my_sed_long_arg='1s/^--[^=]*=//' func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` } # func_split_long_opt may be replaced by extended shell implementation exit_cmd=: magic="%%%MAGIC variable%%%" magic_exe="%%%MAGIC EXE variable%%%" # Global variables. nonopt= preserve_args= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "${1}=\$${1}\${2}" } # func_append may be replaced by extended shell implementation # func_append_quoted var value # Quote VALUE and append to the end of shell variable VAR, separated # by a space. func_append_quoted () { func_quote_for_eval "${2}" eval "${1}=\$${1}\\ \$func_quote_for_eval_result" } # func_append_quoted may be replaced by extended shell implementation # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "${@}"` } # func_arith may be replaced by extended shell implementation # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` } # func_len may be replaced by extended shell implementation # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` } # func_lo2o may be replaced by extended shell implementation # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` } # func_xform may be replaced by extended shell implementation # func_fatal_configuration arg... # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func_error ${1+"$@"} func_error "See the $PACKAGE documentation for more information." func_fatal_error "Fatal configuration error." } # func_config # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # Display the features supported by this script. func_features () { echo "host: $host" if test "$build_libtool_libs" = yes; then echo "enable shared libraries" else echo "disable shared libraries" fi if test "$build_old_libs" = yes; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag tagname # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname="$1" re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf="/$re_begincf/,/$re_endcf/p" # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Option defaults: opt_debug=: opt_dry_run=false opt_config=false opt_preserve_dup_deps=false opt_features=false opt_finish=false opt_help=false opt_help_all=false opt_silent=: opt_warning=: opt_verbose=: opt_silent=false opt_verbose=false # Parse options once, thoroughly. This comes as soon as possible in the # script to make things like `--version' happen as quickly as we can. { # this just eases exit handling while test $# -gt 0; do opt="$1" shift case $opt in --debug|-x) opt_debug='set -x' func_echo "enabling shell trace mode" $opt_debug ;; --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) opt_config=: func_config ;; --dlopen|-dlopen) optarg="$1" opt_dlopen="${opt_dlopen+$opt_dlopen }$optarg" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) opt_features=: func_features ;; --finish) opt_finish=: set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help_all=: opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_mode="$optarg" case $optarg in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_silent=false func_append preserve_args " $opt" ;; --no-warning|--no-warn) opt_warning=false func_append preserve_args " $opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $opt" ;; --silent|--quiet) opt_silent=: func_append preserve_args " $opt" opt_verbose=false ;; --verbose|-v) opt_verbose=: func_append preserve_args " $opt" opt_silent=false ;; --tag) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_tag="$optarg" func_append preserve_args " $opt $optarg" func_enable_tag "$optarg" shift ;; -\?|-h) func_usage ;; --help) func_help ;; --version) func_version ;; # Separate optargs to long options: --*=*) func_split_long_opt "$opt" set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-n*|-v*) func_split_short_opt "$opt" set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) break ;; -*) func_fatal_help "unrecognized option \`$opt'" ;; *) set dummy "$opt" ${1+"$@"}; shift; break ;; esac done # Validate options: # save first non-option argument if test "$#" -gt 0; then nonopt="$opt" shift fi # preserve --debug test "$opt_debug" = : || func_append preserve_args " --debug" case $host in *cygwin* | *mingw* | *pw32* | *cegcc*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then func_fatal_configuration "not configured to build any kind of library" fi # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test "$opt_mode" != execute; then func_error "unrecognized option \`-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$progname --help --mode=$opt_mode' for more information." } # Bail if the options were screwed $exit_cmd $EXIT_FAILURE } ## ----------- ## ## Main. ## ## ----------- ## # func_lalib_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null \ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_unsafe_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if `file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case "$lalib_p_line" in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test "$lalib_p" = yes } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { func_lalib_p "$1" } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $opt_debug save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$save_ifs eval cmd=\"$cmd\" func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. func_source () { $opt_debug case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case "$lt_sysroot:$1" in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result="=$func_stripname_result" ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $opt_debug if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with \`--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=${1} if test "$build_libtool_libs" = yes; then write_lobj=\'${2}\' else write_lobj=none fi if test "$build_old_libs" = yes; then write_oldobj=\'${3}\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$lt_sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $opt_debug # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result="" if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result" ; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $opt_debug if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $opt_debug # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $opt_debug if test -z "$2" && test -n "$1" ; then func_error "Could not determine host file name corresponding to" func_error " \`$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result="$1" fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $opt_debug if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " \`$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result="$3" fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $opt_debug case $4 in $1 ) func_to_host_path_result="$3$func_to_host_path_result" ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via `$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $opt_debug $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $opt_debug case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result="$1" } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result="$func_convert_core_msys_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via `$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $opt_debug if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd="func_convert_path_${func_stripname_result}" fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $opt_debug func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result="$1" } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_msys_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_mode_compile arg... func_mode_compile () { $opt_debug # Get the compilation command and the source file. base_compile= srcfile="$nonopt" # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg="$arg" arg_mode=normal ;; target ) libobj="$arg" arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify \`-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" func_append_quoted lastarg "$arg" done IFS="$save_ifs" func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg="$srcfile" srcfile="$arg" ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with \`-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj="$func_basename_result" } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from \`$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name \`$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname="$func_basename_result" xdir="$func_dirname_result" lobj=${xdir}$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test "$suppress_opt" = yes; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test "$need_locks" != no; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test "$opt_mode" = compile && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a \`.o' file suitable for static linking -static only build a \`.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode \`$opt_mode'" ;; esac echo $ECHO "Try \`$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test "$opt_help" = :; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | sed -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | sed '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $opt_debug # The first argument is the command name. cmd="$nonopt" test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "\`$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "\`$file' was not linked with \`-export-dynamic'" continue fi func_dirname "$file" "" "." dir="$func_dirname_result" if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir="$func_dirname_result" ;; *) func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file="$progdir/$program" elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if test "X$opt_dry_run" = Xfalse; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS fi } test "$opt_mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $opt_debug libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "\`$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument \`$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and \`=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_silent && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the \`-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the \`$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the \`$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test "$opt_mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $opt_debug # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" func_append install_prog "$func_quote_for_eval_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test "x$prev" = x-m && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the \`$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else func_dirname_and_basename "$dest" "" "." destdir="$func_dirname_result" destname="$func_basename_result" # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "\`$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "\`$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir="$func_dirname_result" func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking \`$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname="$1" shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme="" ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib="$destdir/$realname" func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name="$func_basename_result" instname="$dir/$name"i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest="$destfile" destfile= ;; *) func_fatal_help "cannot copy a libtool object to \`$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script \`$wrapper'" finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no fi done relink_command= func_source "$wrapper" outputname= if test "$fast_install" = no && test -n "$relink_command"; then $opt_dry_run || { if test "$finalize" = yes; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file="$func_basename_result" outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_silent || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink \`$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file="$outputname" else func_warning "cannot relink \`$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name="$func_basename_result" # Set up the ranlib parameters. oldlib="$destdir/$name" func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run \`$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test "$opt_mode" = install && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $opt_debug my_outputname="$1" my_originator="$2" my_pic_p="${3-no}" my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms="${my_outputname}S.c" else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${my_outputname}.nm" func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then func_verbose "generating symbol list for \`$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $opt_dry_run || { $RM $export_symbols eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" name="$func_basename_result" case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename="" if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname" ; then func_basename "$dlprefile_dlname" dlprefile_dlbasename="$func_basename_result" else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename" ; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = {\ { \"$my_originator\", (void *) 0 }," case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) if test "X$my_pic_p" != Xno; then pic_flag_for_symtable=" $pic_flag" fi ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' # Transform the symbol file into the correct name. symfileobj="$output_objdir/${my_outputname}S.$objext" case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for \`$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $opt_debug win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s,.*,import, p q } }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $opt_debug sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $opt_debug match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive which possess that section. Heuristic: eliminate # all those which have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $opt_debug if func_cygming_gnu_implib_p "$1" ; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1" ; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result="" fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" if test "$lock_old_archive_extraction" = yes; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test "$lock_old_archive_extraction" = yes; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $opt_debug my_gentop="$1"; shift my_oldlibs=${1+"$@"} my_oldobjs="" my_xlib="" my_xabs="" my_xdir="" for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib="$func_basename_result" my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir="$my_gentop/$my_xlib_u" func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` darwin_base_archive=`basename "$darwin_archive"` darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches ; do func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result="$my_oldobjs" } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory in which it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ which is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options which match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include /* declarations of non-ANSI functions */ #if defined(__MINGW32__) # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined(__CYGWIN__) # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined (other platforms) ... */ #endif /* portability defines, excluding path handling macros */ #if defined(_MSC_VER) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC # ifndef _INTPTR_T_DEFINED # define _INTPTR_T_DEFINED # define intptr_t int # endif #elif defined(__MINGW32__) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined(__CYGWIN__) # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined (other platforms) ... */ #endif #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) #if defined(LT_DEBUGWRAPPER) static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; int tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined (HAVE_DOS_BASED_FILE_SYSTEM) } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = q - p; p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (strcmp (str, pat) == 0) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else int len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { int orig_value_len = strlen (orig_value); int add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ int len = strlen (new_value); while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[len-1] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $opt_debug case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_mode_link arg... func_mode_link () { $opt_debug case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module="${wl}-single_module" func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir="$arg" prev= continue ;; dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" test -f "$arg" \ || func_fatal_error "symbol file \`$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file \`$arg' does not exist" fi arg=$save_arg prev= continue ;; precious_regex) precious_files_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds="$arg" prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "\`-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between \`-L' and \`$1'" else func_fatal_error "need path for \`-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of \`$dir'" dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module="${wl}-multi_module" continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "\`-no-install' is ignored for $host" func_warning "assuming \`-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-flto*|-fwhopr*|-fuse-linker-plugin) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test "$prev" = dlfiles; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the \`$prevarg' option requires an argument" if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname="$func_basename_result" libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" func_dirname "$output" "/" "" output_objdir="$func_dirname_result$objdir" func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps ; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test "$linkmode,$pass" = "lib,link"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs="$tmp_deplibs" fi if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test "$linkmode,$pass" = "lib,dlpreopen"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs="$dlprefiles" fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then func_warning "\`-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test "$linkmode" = lib; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no func_dirname "$lib" "" "." ladir="$func_dirname_result" lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l *.ltframework) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "\`-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." else echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" fi # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "\`$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir="$func_dirname_result" dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" elif test "$linkmode" != prog && test "$linkmode" != lib; then func_fatal_error "\`$lib' is not a convenience library" fi tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test "$prefer_static_libs" = yes || test "$prefer_static_libs,$installed" = "built,no"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib="$l" done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then func_fatal_error "cannot -dlopen a convenience library: \`$lib'" fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of \`$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir="$ladir" fi ;; esac func_basename "$lib" laname="$func_basename_result" # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library \`$lib' was moved." dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$lt_sysroot$libdir" absdir="$lt_sysroot$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir="$ladir" absdir="$abs_ladir" # Remove this search path later func_append notinst_path " $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir" && test "$linkmode" = prog; then func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi case "$host" in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { { test "$prefer_static_libs" = no || test "$prefer_static_libs,$installed" = "built,yes"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath:" in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test "$use_static_libs" = built && test "$installed" = yes; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test "$installed" = no; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule="" for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule="$dlpremoduletest" break fi done if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then echo if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname="$1" shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc*) func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" func_basename "$soroot" soname="$func_basename_result" func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from \`$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for \`$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$opt_mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we can not # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null ; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library" ; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add="$dir/$old_library" fi elif test -n "$old_library"; then add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$absdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && test "$hardcode_minus_L" != yes && test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$opt_mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system can not link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs="$temp_deplibs" fi func_append newlib_search_path " $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path="$deplib" ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of \`$dir'" absdir="$dir" fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl" ; then depdepl="$absdir/$objdir/$depdepl" darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" path= fi fi ;; *) path="-L$absdir/$objdir" ;; esac else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "\`$deplib' seems to be moved" path="-L$absdir" fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test "$pass" = link; then if test "$linkmode" = "prog"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" fi if test "$linkmode" = prog || test "$linkmode" = lib; then dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "\`-R' is ignored for archives" test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "\`-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "\`-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test "$module" = no && \ func_fatal_help "libtool library \`$output' must begin with \`lib'" if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test "$dlself" != no && \ func_warning "\`-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test "$#" -gt 1 && \ func_warning "ignoring multiple \`-rpath's for a libtool library" install_libdir="$1" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "\`-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 shift IFS="$save_ifs" test -n "$7" && \ func_fatal_help "too many parameters to \`-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$1" number_minor="$2" number_revision="$3" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|qnx|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_minor" lt_irix_increment=no ;; esac ;; no) current="$1" revision="$2" age="$3" ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT \`$current' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION \`$revision' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE \`$age' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE \`$age' is greater than the current interface number \`$current'" func_fatal_error "\`$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current" ;; irix | nonstopux) if test "X$lt_irix_increment" = "Xno"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring:${iface}.0" done # Make executables depend on our current version. func_append verstring ":${current}.0" ;; qnx) major=".$current" versuffix=".$current" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; *) func_fatal_configuration "unknown library version type \`$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then func_warning "undefined symbols not allowed in $host shared libraries" build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi func_generate_dlsyms "$libname" "$libname" "yes" func_append libobjs " $symfileobj" test "X$libobjs" = "X " && libobjs= if test "$opt_mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test "X$deplibs_check_method" = "Xnone"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then # Remove ${wl} instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$opt_mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname="$1" shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols="$output_objdir/$libname.uexp" func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile if test "x`$SED 1q $export_symbols`" != xEXPORTS; then # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols="$export_symbols" export_symbols= always_export_symbols=yes fi fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' for cmd1 in $cmds; do IFS="$save_ifs" # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test "$try_normal_branch" = yes \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=${output_objdir}/${output_la}.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS="$save_ifs" if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test "$compiler_needs_object" = yes && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test "X$skipped_export" != "X:" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test "$compiler_needs_object" = yes; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-${k}.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test "X$objlist" = X || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-${k}.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\${concat_cmds}$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi if ${skipped_export-false}; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi fi test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi if ${skipped_export-false}; then if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi fi libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "\`-R' is ignored for objects" test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for objects" test -n "$release" && \ func_warning "\`-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object \`$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec and hope we can get by with # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` else gentop="$output_objdir/${obj}x" func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" # Create the old-style object. reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for programs" test -n "$release" && \ func_warning "\`-release' is ignored for programs" test "$preload" = yes \ && test "$dlopen_support" = unknown \ && test "$dlopen_self" = unknown \ && test "$dlopen_self_static" = unknown && \ func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test "$tagname" = CXX ; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " ${wl}-bind_at_load" func_append finalize_command " ${wl}-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs="$new_libs" func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" "no" # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=yes case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=no ;; *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; *) if test "$need_relink" = no || test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; esac if test "$wrappers_required" = no; then # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.${objext}"; then func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' fi exit $exit_status fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" func_warning "this platform does not like uninstalled shared libraries" func_warning "\`$output' will be relinked during installation" else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource="$output_path/$objdir/lt-$output_name.c" cwrapper="$output_path/$output_name.exe" $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host" ; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save $symfileobj" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" if test "$preload" = yes && test -f "$symfileobj"; then func_append oldobjs " $symfileobj" fi fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase="$func_basename_result" case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name="$func_basename_result" func_resolve_sysroot "$deplib" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles="$newdlprefiles" fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test "x$bindir" != x ; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that can not go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } { test "$opt_mode" = link || test "$opt_mode" = relink; } && func_mode_link ${1+"$@"} # func_mode_uninstall arg... func_mode_uninstall () { $opt_debug RM="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) func_append RM " $arg"; rmforce=yes ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir="$func_dirname_result" if test "X$dir" = X.; then odir="$objdir" else odir="$dir/$objdir" fi func_basename "$file" name="$func_basename_result" test "$opt_mode" = uninstall && odir="$dir" # Remember odir for removal later, being careful to avoid duplicates if test "$opt_mode" = clean; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case "$opt_mode" in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test "$pic_object" != none; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test "$non_pic_object" != none; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test "$opt_mode" = clean ; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name" ; then func_append rmfiles " $odir/lt-${noexename}.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } { test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && func_mode_uninstall ${1+"$@"} test -z "$opt_mode" && { help="$generic_help" func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode \`$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: # vi:sw=2 mjpegtools-2.1.0/config.h.in0000644000175000017500000001247212217306406016243 0ustar glowwormglowworm/* config.h.in. Generated from configure.ac by autoheader. */ /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD /* Inline PPC Altivec primitives available */ #undef HAVE_ALTIVEC /* Inline MMX assembly accepted by C compiler */ #undef HAVE_ASM_MMX /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the `fmax' function. */ #undef HAVE_FMAX /* Define to 1 if you have the `fmin' function. */ #undef HAVE_FMIN /* Define to 1 if you have the header file. */ #undef HAVE_GETOPT_H /* long getopt support */ #undef HAVE_GETOPT_LONG /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* libdv is present */ #undef HAVE_LIBDV /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM /* libquicktime > 0.9.7 present */ #undef HAVE_LIBQUICKTIME /* libxf86dga is present */ #undef HAVE_LIBXXF86DGA /* Define to 1 if you have the `lround' function. */ #undef HAVE_LROUND /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H /* Define to 1 if you have the `memalign' function. */ #undef HAVE_MEMALIGN /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `posix_memalign' function. */ #undef HAVE_POSIX_MEMALIGN /* Compiling for PowerPC CPU */ #undef HAVE_PPCCPU /* Define if you have POSIX threads libraries and header files. */ #undef HAVE_PTHREAD /* pthread stack sizes accesible */ #undef HAVE_PTHREADSTACKSIZE /* libsdl > 1.1.3 present */ #undef HAVE_SDL /* SDL_gfx library present */ #undef HAVE_SDLgfx /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOUNDCARD_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Building for Linux - using the video4linux API */ #undef HAVE_V4L /* Compiling for x86-64 architecture CPU */ #undef HAVE_X86CPU /* Is __progname defined by system? */ #undef HAVE___PROGNAME /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Building mjpegtools */ #undef MJPEGTOOLS /* Optimised no DEBUG build, assertions disabled */ #undef NDEBUG /* Define to 1 if your C compiler doesn't accept -c and -o together. */ #undef NO_MINUS_C_MINUS_O /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to the necessary symbol if this constant uses a non-standard name on your system. */ #undef PTHREAD_CREATE_JOINABLE /* Define as the return type of signal handlers (`int' or `void'). */ #undef RETSIGTYPE /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # undef _ALL_SOURCE #endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # undef _GNU_SOURCE #endif /* Enable threading extensions on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # undef _POSIX_PTHREAD_SEMANTICS #endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # undef _TANDEM_SOURCE #endif /* Enable general extensions on Solaris. */ #ifndef __EXTENSIONS__ # undef __EXTENSIONS__ #endif /* Version number of package */ #undef VERSION /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN # undef WORDS_BIGENDIAN # endif #endif /* Define to 1 if the X Window System is missing or not being used. */ #undef X_DISPLAY_MISSING /* Enable large inode numbers on Mac OS X 10.5. */ #ifndef _DARWIN_USE_64_BIT_INODE # define _DARWIN_USE_64_BIT_INODE 1 #endif /* Number of bits in a file offset, on hosts where this is settable. */ #undef _FILE_OFFSET_BITS /* Define for large files, on AIX-style hosts. */ #undef _LARGE_FILES /* Define to 1 if on MINIX. */ #undef _MINIX /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ #undef _POSIX_1_SOURCE /* Define to 1 if you need to in order for `stat' and other things to work. */ #undef _POSIX_SOURCE /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif mjpegtools-2.1.0/docs/0000755000175000017500000000000012217306501015136 5ustar glowwormglowwormmjpegtools-2.1.0/docs/lav2yuv.10000755000175000017500000000552012216627207016645 0ustar glowwormglowworm.\" .TH "lav2yuv" "1" "6 March 2002" "MJPEG Tools Team" "MJPEG tools manual" .SH "NAME" lav2yuv \- Convert a MJPEG file to raw yuv .SH "SYNOPSIS" .B lav2yuv .RI [ options ] .I lavfile1 \fP[\fIlavfile2 \fP...\fI lavfileN\fP] .SH "DESCRIPTION" \fBlav2yuv\fP converts an MJPEG video sequence described by a sequence of MJPEG video files and/or edit lists pointing to such files into the simple uncompressed planar 4:2:0 Y'CbCr format, as used by \fBmpeg2enc\fP(1) MPEG encoder and image processing filters like \fByuvscaler\fP(1) or \fByuv2dfilter\fP(1) or \fByuvdenoise\fP(1). Output is to stdout so that by piping the output of lav2yuv into a suitable pipeline it is possible to process and then encode or play back video recorded in any of the mjpegtools MJPEG container formats: AVI, quicktime or edit lists describing editted versions of video held in such files. Mixing different files with different video formats is currently not possible. The \fB\-S \-T \-D\fP options are used for scene detection which is used by linux video studio. .SH "OPTIONS" \fBlav2yuv\fP accepts the following options: .TP 5 .BI \-m Force mono\-chrome .TP 5 .BI \-c Conceal frames containing corrupt MJPEG data by repeating the preceeding good frame. .TP 5 .BI \-S " list.el" Output a scene list with scene detection .TP 5 .BI \-T " num" Set scene detection threshold to num (default: 4) .TP 5 .BI \-D " num" Width decimation to use for scene detection (default: 2) .TP 5 .BI \-o " num" Frame offset \- skip \fInum\fP frames at the beginning. if \fInum\fP is negative all but the last \fInum\fP frames are skipped .TP 5 .BI \-f " num" Only \fInum\fP frames are written to stdout. 0 means that all frames are processed. .TP 5 .BI \-A \ width:height Set/override the sample aspect ratio (SAR) emitted in the output stream header. Currently, the SAR is only auto-detected for DV files, and guessed otherwise. .TP 5 .BI \-P \ width:height Set the intended/approximate display aspect ratio (DAR) for the stream. This value is only used to guess the SAR when it cannot be detected from the input stream. The default DAR is '4:3' (corresponding to a standard TV screen); another useful value is '16:9' (corresponding to widescreen TV). .TP 5 .BI \-C \ chroma Set output chroma (default: '420jpeg'). Currently, '420jpeg', '420mpeg2', '420paldv', '422' are available. .TP 5 .BI \-x Exchange fields. Useful if the field order was reversed during editing. .SH "AUTHOR" This man page was originally written by Bernhard Praschinger. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP .TP For more info, see our website at .I http://mjpeg.sourceforge.net .SH "SEE ALSO" .BR mjpegtools (1), .BR mpeg2enc (1), .BR yuvscaler (1), .BR yuv2lav (1), .BR yuvdenoise (1), .BR yuvplay (1) mjpegtools-2.1.0/docs/yuvdenoise.10000644000175000017500000000650712216627211017425 0ustar glowwormglowworm.TH "yuvdenoise" "1" "11th August 2005" "MJPEG Tools Team" "MJPEG tools manual" .SH NAME yuvdenoise \- Motion-Compensating-YUV4MPEG2-frame-denoiser .SH SYNOPSIS .B yuvdenoise .RI [ options ] .RI "/dev/stdout" .SH DESCRIPTION \fByuvdenoise\fP is a spatio\-temporal noise\-filter for YUV4MPEG2 streams. This is useful to reduce the bitrate needed to encode your captured movies for VCD and SVCD creation. .SH OPTIONS \fByuvdenoise\fP accepts the following options: .TP 4 .BI \-g " y,u,v [0..255] Gaussian filter thresholds" This sets the thresholds for the gaussian filter. A value of 0 disables filtering for a specific component and 0,0,0 completely disables/bypasses the filter. This filter is applied \fBbefore\fP the temporal (\-t) filter. .br (default=0,0,0) .TP 4 .BI \-m " y,u,v [0..255] Pre 3D Median filter thresholds" This sets the thresholds for the pre-processing 3D median filter. A value of 0 disables median filtering for a specific component and 0,0,0 completely disables/bypasses the filter. This filter is applied \fBbefore\fP the temporal (\-t) filter. .br (default=0,0,0) .TP 4 .BI \-r " y,u,v [0..255] Renoising filter thresholds" This sets the thresholds for adding random "noise" back into the video stream. Default is disabled (not adding random noise). This filter, if enabled, is run as the \fPBlast\fP filter (after the median and temporal filters). Reasonable value is 4,8,8 but if you are working with monochrome (black and white movie) then 4,0,0 will speed things up by not processing the chroma planes. .br (default=0,0,0) .TP 4 .BI \-t " y,u,v [0..255] Temporal noise\-filter thresholds" This sets the thresholds for the temporal noise\-filter. Values above 12 may introduce ghosting. The default value for Y' (y) is often a little high and reducing it to 4 or 5 may be necessary. If the chroma smears or ghosts try using values of 5 or 6 instead of the default (12). A value of 0 disables temporal filtering for the specified component (0,0,0 disables/bypasses all temporal filtering). Thus for black and white movies 4,0,0 will be faster by not denoising the chroma planes. .br (default=4,8,8) .TP 4 .BI \-M " y,u,v [0..255] Post 3D Median filter thresholds" This sets the thresholds for the post-processing 3D median filter. A value of 0 disables median filtering for a specific component and 0,0,0 completely disables/bypasses the filter. This filter is applied \fBafter\fP the temporal (\-t) filter. Reasonable value is 4,8,8 but if you are working with monochrome (black and white movie) then 4,0,0 will speed things up by not processing the chroma planes. .br (default=0,0,0) .SH HOW IT WORKS To Be Written (maybe) in the future. .SH TYPICAL USAGE AND TIPS As it is self-adapting to the noise-situation found in the stream you normally just can go without any options set: lav2yuv my-video.avi | yuvdenoise | mpeg2enc -t 1 -o my-video.m1v .SH AUTHOR This man page was written by Stefan Fendt and revised by Steven Schultz. .SH ADDITIONAL INFO If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: .BR \fImjpeg\-users@lists.sourceforge.net\fP For more info, see our website at .BR \fIhttp://mjpeg.sourceforge.net/\fP .SH SEE ALSO .BR mjpegtools (1), .BR mpeg2enc (1) .BR lavrec (1) .BR lav2yuv (1) mjpegtools-2.1.0/docs/y4munsharp.10000644000175000017500000000537012216627211017342 0ustar glowwormglowworm.TH "y4munsharp" "1" "11 November 2004" "MJPEG Tools Team" "MJPEG tools manual" .SH "NAME" y4munsharp \- Unsharp filter for YUV4MPEG2 streams .SH "SYNOPSIS" .B y4munsharp .RI [ options ] .SH "DESCRIPTION" \fBy4munsharp\fP is an implementation of the GIMP unsharp filter for YUV4MPEG2 streams. The usual 3 parameters for unshap mask processing (radius, amount and threshold) are specified on the command line. By default only the Y' (luma) component is processed although processing of the CbCr (chroma) may be requested by a commandline option. Output must be either to a pipe or a file, leaving stdout as a terminal will elicit an error and the program will exit. .SH "OPTIONS" \fBy4munsharp\fP accepts the following options: .TP 5 .BI \-v " num" Set verbosity level (0 = quiet, 1 = normal, 2 = debug) (default: 1) .TP 5 .BI \-h Print a suage summary and exit .TP 5 .BI \-L " radius,amount,threshold" Y' (luma) unsharp parameters. The \fIradius\fP and \fIamount" arguments are floating point numbers. The \fIthreshold\fP argument is an integer. (default: 3.0,0.3,4) .BI \-C " radius,amount,threshold" CbCr (chroma) unsharp parameters. The chroma is not processed unless this option is given. Arguments are the same type as for the -L option above. (default: none) .TP 5 .BI \-N Filtering can produce output outside the 16 to 240 range for Y' and 16 to 235 for CbCr. By default values outside the legal range are clipped/cored (values over 240 for Y' are set to 240 for example). Using \fB-N\fP the limits 0 and 255 are used instead. .SH "EXAMPLES" A mild setting: .nf y4munsharp -L 2.0,0.3,0 .sp An aggressive setting: y4munsharp -L 5.0,0.5,0 .SH "NOTES" The radius, amount, threshold parameters have the same meaning as the GIMP's unsharp plugin. This means you can use the GIMP on selected frame still images to determine suitable settings for \fBy4munsharp\fP. The key thing to remember is to be subtle - you just barely want to notice the sharpening effect. If the effect is obvious ("jumps out at you") then the parameters are set too aggressively. .PP The chroma is not processed for a several reasons: 1) The eye is much more sensitive to changes in brightness, 2) the chroma is usually subsampled and doesn't contribute much to the perceived sharpness of an image \- so not processing the chroma provides a boost in speed of processing the image, and 3) possible artifacting - changes in Y' just make an image brighter/darker but changes in Cb or Cr can change colors and possibly lead to shifts in hue. Use the \fB-C\fP option to enable processing of the chroma planes. .SH "BUGS" Only the 3 plane YUV4MPEG2 formats are supported. .PP Only progressive, top field first or bottom field first interlaced streams are handled. The mixed interlaced stream format is not supported. mjpegtools-2.1.0/docs/y4mcolorbars.10000755000175000017500000000730512216627211017653 0ustar glowwormglowworm.\" .TH "y4mcolorbars" "1" "28 April 2004" "MJPEG Tools Team" "MJPEG tools manual" .SH "NAME" y4mcolorbars \- Create a YUV4MPEG2 stream containing a colorbar test pattern .SH "SYNOPSIS" .B y4mcolorbars .RI [ options ] .SH "DESCRIPTION" \fBy4mcolorbars\fP creates a YUV4MPEG2 stream consisting entirely of frames containing a colorbar test pattern. The pattern attempts to reproduce the standard SMPTE EG-1-1990 colorbar test signal as faithfully as possible, given the constraints of the Y'CbCr colorspace. Output is to stdout to facilitate piping to other MJPEG tools. .SH "OPTIONS" \fBy4mcolorbars\fP accepts the following options: .TP 5 .BI \-n " num" Output a total of 'num' output frames. [default: 1] .TP 5 .BI \-F " n:d" Set framerate encoded in output stream, as an exact integer ratio. Common rates are: 24000:1001 - NTSC 3:2 pulldown converted film 24:1 - native film 25:1 - PAL/SECAM 30000:1001 - NTSC video [default] 50:1 - PAL field rate 60000:1001 - NTSC field rate .TP 5 .BI \-W " w" Set frame width. [default: 720] .TP 5 .BI \-H " h" Set frame height. [default: 480] .TP 5 .BI \-A " n:d" Set pixel aspect ratio encoded in output stream, as an exact integer ratio. Common ratios are: 1:1 - square pixels (e.g. computer graphics) 10:11 - CCIR-601 NTSC [default] 59:54 - CCIR-601 PAL .TP 5 .BI \-I " x" Set interlacing mode, used to interpret the PPM image(s), and also encoded in output stream. p - progressive, non-interlaced [default] t - top/upper-field-first interlaced b - bottom/lower-field-first interlaced .TP 5 .BI \-Q " n" Data to place in the "-I/+Q" patches in the bottom row of the pattern: 0 - -I and +Q at 20% (20IRE) [default] 1 - -I and +Q at 50% (50IRE) 2 - +Cb and +Cr at 100% .TP 5 .BI \-S " mode" Set chroma subsampling mode. 444 - 4:4:4 (no subsampling) [default] 420jpeg - 4:2:0 JPEG/MPEG-1, interstitial cositing 420mpeg2 - 4:2:0 MPEG-2, horizontal cositing The supported subsampled modes use a lousy subsampling filter; better results will be achieved by passing the default 4:4:4 output to a scaler which supports subsampling, such as \fBy4mscaler\fP(1). .TP 5 .BI \-v " [0,1,2]" Set verbosity level. 0 - warnings and errors only. 1 - add informative messages, too. [default] 2 - add chatty debugging message, too. .SH "EXAMPLES" .hw y4mcolorbars yuvplay tgatoppm To create and display 200 frames of colorbars corresponding to a top-field-first interlaced 4:3 NTSC source: .RS 5 y4mcolorbars -n 200 -It -S 420jpeg | yuvplay .RE To create and display 200 frames of colorbars corresponding to a bottom-field-first interlaced 4:3 PAL source: .RS 5 y4mcolorbars -n 200 -H 576 -F 25:1 -A 59:54 -Ib | yuvplay .RE .SH "BUGS" First, it's not clear to the author (who hasn't actually ever seen the SMPTE EG-1-1990 document itself) what the absolute excursion of the -I and +Q regions is supposed to be; however, the phase is correct, and that should be the critical feature. Second, the PLUGE bars, of -4 and +4 IRE, can never be precisely synthesized --- the Y' digital space maps [16,235] over the full luma excursion, but the full luma excursion in analog space depends on whether or not 7.5 IRE NTSC setup is being used by whatever device eventually produces the analog output. However, the difference is within 1-bit of Y' accuracy anyway. .SH "AUTHOR" This man page was written by Matt Marjanovic. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP .TP For more info, see our website at .I http://mjpeg.sourceforge.net .SH "SEE ALSO" .BR mjpegtools (1), .BR mpeg2enc (1), .BR y4mscaler (1), .BR yuv2lav (1), .BR yuvplay (1) mjpegtools-2.1.0/docs/lav2wav.10000755000175000017500000000503112216627207016614 0ustar glowwormglowworm.TH "lav2wav" "1" "2 June 2001" "MJPEG Tools Team" "MJPEG tools manual" .SH "NAME" lav2wav \- Extract the audio out of MJPEG container files to stdout .SH "SYNOPSIS" .B lav2wav .RB [ \-s .IR num ] .RB [ \-c .IR num ] .RB [ \-v .IR num ] .RB [ \-I ] .RB [ \-R ] .RB [ \-r .IR samplerate, .IR bitesize, .IR channels ] .I lavfile1 \fP[\fIlavfile2 \fP...\fI lavfileN\fP] .SH "DESCRIPTION" \fBlav2wav\fP can be used to extract the audio to stdout. This output goes to stdout and can be saved as a wav file or piped to another sound processing tool that is able to handle the wav format. This can be mp2enc and toolame for mpeg layer 2 audio, or for example lame for mpeg layer 3 audio. .LP The input files may be any combination of AVI (.avi), Quicktime (.qt) or editlist files so long as they are all lavtools\- readable (e.g. MJPEG-encoded AVI/Quicktime or DV type 2 AVI). .SH "OPTIONS" \fBlav2wav\fP accepts the following options: .TP 5 .BI \-s " num" Start extracting at video frame (num) .TP 5 .BI \-c " num" Extract (num) frames of audio .TP 5 .BI \-v " num" Verbosity level (0, 1 or 2) .TP 5 .BI \-I Ignore unsupported bitrates/bits per sample .TP 5 .BI \-R If the file does not contain any sound. lav2wav will create silence with 44100kHz Sampelrate, 16 Bit audio bitsize and 2 Chanels .TP 5 .BI \-r " sr,bs,ch" If the file does not contain any sound lav2wav will generate silence with the values you supply the samplerate (sr), audio-bitsize (bs) and channel (ch). .SH BUGS The "WAV" file format (technically: RIFF) is really very much less than ideal for a tool intended to be used in pipelines as lav2wav is. The problem is that the header includes a field specifying the length of the file. This can't be filled in except by seeking back to the begining and over-writing. If the output is unseekable (e.g. pipe) lav2wav simply writes a large length into the header and leaves it at that. Most tools like sox(1) or mp2enc(1) either ignore the length field anyway or only give a warning. .br The audio length is inacurate calculated when lav2wav generates silence. This happens only if you have NTSC framerate and than it creates for every hour of video 1.1498sec too less of silence. .SH "AUTHOR" This man page was written by Bernhard Praschinger. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP .TP For more info, see our website at .I http://mjpeg.sourceforge.net .SH "SEE ALSO" .BR mjpegtools (1), .BR mp2enc (1), .BR sox(1) mjpegtools-2.1.0/docs/Makefile.am0000644000175000017500000000765412052075212017205 0ustar glowwormglowworm# If the installation of man pages by you (e.g. you're a package builder) # You may want to disable it man_MANS = lavplay.1 lavrec.1 mjpegtools.1 mpeg2enc.1 mplex.1 \ yuvplay.1 lav2wav.1 lav2yuv.1 lavtrans.1 mp2enc.1 \ yuvscaler.1 lavpipe.1 yuv2lav.1 yuvdenoise.1 jpeg2yuv.1 \ png2yuv.1 \ pgmtoy4m.1 ppmtoy4m.1 y4mtoppm.1 y4mcolorbars.1 \ y4mtopnm.1 pnmtoy4m.1 \ yuvkineco.1 yuvycsnoise.1 yuvmedianfilter.1 \ y4munsharp.1 y4mscaler.1 \ lav2mpeg.1 yuv4mpeg.5 yuvfps.1 yuvinactive.1 y4mdenoise.1 info_INFO = mjpeg-howto.info EXTRA_DIST = \ $(man_MANS) \ FAQ.txt \ authors.sgml \ lavtools.sgml MAINTAINERCLEANFILES = Makefile.in # (Ronald) this stuff comes from texinfos.am on my # installation. We need it for proper in-auto-build # installation of info pages. # It's adapted to handle the debian install-info case # too... INSTALL_INFO = /sbin/install-info INFO_ENTRY = "* mjpeg-howto: (mjpeg-howto). How to use the mjpeg tools" INFO_DESCRIPTION = "mjpeg tools documentation" install-exec-hook: install-info dist-hook: dist-info ## Look in both . and srcdir because the info pages might have been ## rebuilt in the build directory. Can't cd to srcdir; that might ## break a possible install-sh reference. ## Funny name due to --cygnus influence; we want to reserve ## `install-info' for the user. install-info-am: $(info_INFO) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(infodir) @list='$(info_INFO)'; \ for file in $$list; do \ d=$(srcdir); \ ## We use these strange circumlocutions because we want the "ifile" to ## be relative, for the install. for ifile in `cd $$d && echo $$file $$file-[0-9] $$file-[0-9][0-9]`; do \ if test -f $$d/$$ifile; then \ echo " $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile"; \ $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile; \ else : ; fi; \ done; \ done @$(POST_INSTALL) @if test x$(INSTALL_INFO) != x && test -f $(INSTALL_INFO); then \ list='$(info_INFO)'; \ for file in $$list; do \ ## Run `:' after install-info in case install-info fails. We really ## don't care about failures here, because they can be spurious. For ## instance if you don't have a dir file, install-info will fail. I ## think instead it should create a new dir file for you. This bug ## causes the `make distcheck' target to fail reliably. echo " install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file";\ ## Use `|| :' here because Sun make passes -e to sh; if install-info ## fails then we'd fail if we used `;'. if $(SHELL) -c '$(INSTALL_INFO) --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \ $(INSTALL_INFO) --entry=$(INFO_ENTRY) --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file || :;\ else \ ## Special Debian case $(INSTALL_INFO) --infodir=$(DESTDIR)$(infodir) --menuentry=$(INFO_ENTRY) --description=$(INFO_DESCRPITION) $(DESTDIR)$(infodir)/$$file || :; \ fi; \ done; \ fi uninstall-info-am: $(PRE_UNINSTALL) ## Run two loops here so that we can handle PRE_UNINSTALL and ## NORMAL_UNINSTALL correctly. if test x$(INSTALL_INFO) != x && test -f $(INSTALL_INFO); then \ list='$(info_INFO)'; \ for file in $$list; do \ if $(SHELL) -c '$(INSTALL_INFO) --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \ ## GNU case $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) --remove $$file; \ else \ ## Debian case $(INSTALL_INFO) --infodir=$(DESTDIR)$(infodir) --delete $$file; \ fi; \ done; \ fi @$(NORMAL_UNINSTALL) list='$(info_INFO)'; \ for file in $$list; do \ (cd $(DESTDIR)$(infodir) && rm -f $$file $$file-[0-9] $$file-[0-9][0-9]); \ done dist-info: $(info_INFO) list='$(info_INFO)'; \ for base in $$list; do \ d=$(srcdir); \ for file in `cd $$d && eval echo $$base*`; do \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ || cp -p $$d/$$file $(distdir)/$$file; \ done; \ done mjpegtools-2.1.0/docs/yuvplay.10000755000175000017500000000337312216627211016745 0ustar glowwormglowworm.TH "yuvplay" "1" "8 April 2002" "MJPEG Tools Team" "MJPEG tools manual" .SH NAME yuvplay \- Display YUV4MPEG2 streams (using SDL) .SH SYNOPSIS .B yuvplay .RB [ options ] .SH DESCRIPTION \fByuvplay\fP produces on-screen playback of a YUV4MPEG2 stream which is provided to stdin, typically through piping from the stdout of \fBlavpipe\fP(1), \fBlav2yuv\fP(1), \fBmpeg2dec\fP(1) or a similar program. It should be noted that for pure playback lavplay should be a superior option. yuvplay is intended primarily as a debugging or diagnostic utility when setting up video processing pipelines. .SH OPTIONS \fByuvplay\fP accepts the following options: .TP 8 .BI \-s \ WxH The size of the SDL window. By default, it uses the size of the input video stream scaled to yield 1:1 pixels (using the sample aspect ratio encoded in the stream header). However, you can specify any size you want. WxH is the width x height of the scaled window. .TP 8 .BI \-t title Set the window title. .TP 8 .BI \-f " num" Override the framerate specified in the input stream header. .TP 8 .BI \-c By default, yuvplay will try to play at the framerate of the input movie. With this option, yuvplay will just play all the frames as fast as it can. .TP 8 .BI \-v \ [0, 1, 2] Set the verbosity of user feedback. Default is "1": errors, warnings, and info messages. .SH AUTHOR This man page was originally written by Ronald Bultje (and since edited by Matt Marjanovic). .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP .TP For more info, see our website at .I http://mjpeg.sourceforge.net/ .SH SEE ALSO .BR mjpegtools (1), .BR lavpipe (1), .BR lav2yuv (1) .BR lavplay (1) mjpegtools-2.1.0/docs/mp2enc.10000644000175000017500000000750112216627211016412 0ustar glowwormglowworm.TH "mp2enc" "1" "2 June 2001" "MJPEG Tools Team" "MJPEG tools manual" .SH "NAME" .LP .br mp2enc \- Simple MPEG-1 layer-II audio encoder .br .SH "SYNOPSIS" .B mp2enc .RB [ -v .IR num ] .RB [ -b .IR bitrate_kbps ] .RB [ -r .IR output_sampling_rate_hz ] .RB [ -R .IR rate,chans,bits ] .RB [ -s ] .RB [ -m ] .RB [ -e ] .RB [ -V ] .RB [ -? ] .BI -o \ output_filename .SH "DESCRIPTION" Mp2enc is a simple MPEG-1 layer-I/II audio encoder. It is actually a very mildly warmed over version of the MPEG Software Simulation Group's reference encoder. It accepts a WAV file or stream on stdin and ouputs an a layer-I/II elementary audio stream. It is included in the \fBmjpegtools\fP(1) primarily for reasons of completeness and because it is able to perform sampling rate conversion. .PP Those seeking a faster (and probably higher quality) layer II encoder are recommended to use \fBtoolame\fP(1) which can be obtained from: .IP \fIhttp://www.planckenergy.com\fP .SH "GENERAL FUNCTION LETTERS" .TP .BI -o \ output_filename Specifies the name for the output file. An integer format code (e.g. %d) in the name is replaced the number of the file generated (see printf(3)). .TP .BI -v \ num Set verbosity level to num. 0 = warnings and errors only, 1 = information as well, 2=really verbose. .B -? Display a synopsis of the command syntax. .TP .BI -R \ rate,chans,bits Indicate, that the input is raw PCM without header. You must specify 3 numbers: rate is the samplerate in Hz, chans is the number of channels (1 or 2) and bits is the number of bits per sample. 8 bits are unsigned, 16 bits are signed in machine native byte order. .br .SH "FUNCTION LETTERS CONTROLLING OUTPUT STREAM STRUCTURE" .TP .BI -b \ bitrate This sets the bit-rate of the output stream in kBit/sec. Typical values for layer II might be 224kbps for good-quality audio suitable for capturing Dolby pro-logic signals. A rate of 192kbps or 128kbps is reasonable for low quality audio (e.g. mono TV audio). Really high compression is, of course, better achieved using MPEG-1 layer III ("MP3") audio encoding or AAC. A more appropriate value for layer I might be 384kbps. .TP .BI -r \ sampling_rate Sets the audio sampling rate of the reconstructed output signal in Hz. Legal values are 32000, 44100 and 48000Hz. mp2enc will automatically sample-rate convert the input signal if necessary. .TP .BI -l \ layer Sets the audio layer. Legal values are 1 and 2. The default is layer II. .TP .BI -s Force stereo output. A mono input signal is channel doubled before encoding to make it stereo. This is useful for players which simply can't handle a non-stero signal. .TP .BI -m Force mono output. A stereo input signal is down-mixed before encoding. Useful if you've captured a mono signal in stereo and your player can handle mono MPEG-1 Layer 2 audio. .TP .BI -e Use CRC error protection. .TP .BI -V Force VCD compatible output. The primary effect of this is to make certain that the sampling rate is set to 44100 (-r 44100). The VCD2.0 specifications permit mono audio at 64, 96 and 192 kbits/sec and stereo at 128, 192, 224, and 384 kbits/sec. Using \fB-V\fP checks that the bitrate is valid for the number of channels. The defaults (unless -m or -b are used) are stereo at 224 kbits/sec. .TP .BI -o \ outputpathname The name of the output file to generate. If '-' is given as the pathname output is written to standard output. .SH "BUGS" Mono output does not work for layer I. .SH AUTHOR This man page was written by Andrew Stevens. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP .TP For more info, see our website at .I http://mjpeg.sourceforge.net .SH "SEE ALSO" .BR mpeg2enc "(1), " mp2enc "(1), " lavrec "(1), " lavplay "(1), " .BR lav2yuv "(1), " lav2wav "(1), " yuvscaler "(1)" mjpegtools-2.1.0/docs/pgmtoy4m.10000644000175000017500000000410312216627211017001 0ustar glowwormglowworm.TH "pgmtoy4m" "1" "16 December 2003" "y4mutils" "MJPEG tools manual" .SH "NAME" pgmtoy4m \- Convert mpeg2dec pgm and pgmpipe output to YUV4MPEG2 .SH "SYNOPSIS" .B pgmtoy4m .RI [ options ] .SH "DESCRIPTION" \fBpgmtoy4m\fP repacks the PGM output from \fBmpeg2dec\fP into YUV4MPEG2 4:2:0p. No actual changes to the data are made. The data is unpacked from the quasi-PGM format and placed in YUV4MPEG2 format with the specified sample aspect, frame rate and field order. Output must be either to a pipe or a file, leaving stdout as a terminal will elicit an error and the program will exit. .SH "OPTIONS" \fBpgmtoy4m\fP accepts the following options: .TP 5 .BI \-v " num" Set verbosity level. (default: 0) .TP 5 .BI \-h Print a usage summary and exit. .TP 5 .BI \-i " t|b|p" Set the interlacing mode. Top field first (t), bottom field first (b) or progressive/none (p). (default: t) .TP 5 .BI \-a " sar" Set the sample aspect ratio. (default: 10:11) .TP 5 .BI \-r " frame rate" Set the frame rate. (default: 30000:1001) .SH "EXAMPLES" .nf mpeg2dec -s -o pgmpipe file.mpg | pgmtoy4m -a 10:11 -r 24000:1001 -i b | yuvplay .sp mpeg2dec -s -o pgm file.mpg cat *.pgm | pgmtoy4m -r 30000:1001 -i t | yuvplay .fi .SH "NOTES" This program is specifically designed to work with the output of mpeg2dec and is \fBNOT\fP a general PGM (NetPBM) tool! .sp From the introduction in the source file: .sp .nf * Note: mpeg2dec uses a variation of the PGM format - they're really not * "Grey Maps" but rather a catenation of the 420P data (commonly called * "YUV"). The type is P5 ("raw") and the number of rows is really * the total of the Y', Cb and Cr heights. The Cb and Cr data is "joined" * together. After the Y' rows you have 1 row of Cb and 1 row of Cr per * "row" of PGM data. * NOTE: You MAY need to know the field order (top/bottom field first), * sample aspect ratio and frame rate because the PGM format makes * none of that information available! .fi .SH "AUTHOR" This manpage was written by Steven Schultz (sms at 2bsd dot com). .SH "BUGS" Possible but none known at the present time. mjpegtools-2.1.0/docs/png2yuv.10000644000175000017500000000566712216627211016653 0ustar glowwormglowworm.TH "png2yuv" "1" "2 February 2003" "MJPEG Tools Team" "MJPEG tools manual" .SH "NAME" png2yuv \- Convert PNG images to the YUV4MPEG stream format. .SH "SYNOPSIS" .B png2yuv .RB [ \-b .IR num ] .RB [ \-f .IR num ] .RB [ \-I .IR num ] .RB [ \-L .IR num ] .RB [ \-n .RB num ] .RB [ \-l .IR num ] .RB [ \-j .IR filename ] .SH "DESCRIPTION" \fBpng2yuv\fP decompresses a sequence of PNG files and pipes the image data to stdout as a YUV4MPEG2 stream. Any 8bit/pixel PNG format supported by libpng can be read. stdout will be filled with the YUV4MPEG movie data stream, so be prepared to pipe it on to mpeg2enc or to write it into a file. \fBThis tool is incomplete.\fP The alternative utility you are probably looking for is \fBppmtoy4m\fP(1), which is also included in MJPEGtools. .SH "OPTIONS" \fBpng2yuv\fP accepts the following options: .TP 5 .BI \-b " num" Frame offset: skip output of the first 'num' frames. (default: 0) .TP 5 .BI \-f " num" Set the frame rate of stream accepts the same numbers. Not default, this option has to be specified. .TP 5 .BI \-I " num" interlacing mode: p = none / progressive .br t = top field first .br b = bottom field first .br No default, this option has to be specified. .TP 5 .BI \-L " num" 0 = non-interleaved (two successive fields per PNG file) .br 1 = interleaved fields .TP 5 .BI \-l " num" Specifies the number of loops (default: 0 loops ) .TP 5 .BI \-S " samp_mode" chroma subsampling mode, only for professionals, for more info see ppmtoy4m and the YUV guide on http://www.mir.com/DMG/. .br default: 420_jpeg .br When this option is not used the given range of images is only processed once. If you use this option and as number 1, jpeg2yv will loop forever writing the image to stdout. When you use n > 1 it will loop. n-time till it finishes. .TP 5 .BI \-n " num" Specifies the nummber of frames to process. (default: all = -1) .TP 5 .BI \-j " {1}%{2}d{3}" Read PNG frames with the name components as follows: {1} PNG filename prefix (e g: picture_ ) {2} Counting placeholder (like in C, printf, eg 06 )) {3} File extension. Something like this: .png A correct description of the files could look like this: picture_%06d.png .TP 5 .BI \-v " num" Verbosity level (0, 1 or 2) .SH BUGS The frame rate description does not seem to be up to date. The NTSC integer ratios are not supported (use floating point instead). As workaround specify a PAL (25) or native FILM (24) and set the right frame rate in mpeg2enc with the -F option. Interlaced handling is not implemented yet. .SH "AUTHOR" This man page was written by Gernot Ziegler. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP .TP For more info, see our website at .I http://mjpeg.sourceforge.net .SH "SEE ALSO" .BR mjpegtools (1), .BR mpeg2enc (1), .BR ppmtoy4m (1), .BR yuv2lav (1), .BR yuvdenoise (1), .BR yuvmedianfilter (1), .BR yuvscaler (1) mjpegtools-2.1.0/docs/yuvkineco.10000644000175000017500000000755112216627211017247 0ustar glowwormglowworm.TH "yuvkineco" "1" "5 February 2002" "MJPEG Tools Team" "MJPEG tools manual" .SH NAME yuvkineco \- revert 2\-3 pulldown movie .SH SYNOPSIS .br .B yuvkineco .RI [ options ] .RB [ \-C .IR PATH ] .br .B yuvkineco .RI [ options ] .BR \-O | N .I PATH .SH DESCRIPTION .br \fByuvkineco\fP reverts to original non\-interlaced frames, from NTSC video which was film sourced and 2\-3 pulled down. Input fps code must be 4(29.97fps), output fps code can be selected from 1(23.97fps) to 4(29.97fps). If 2, 3 or 4 selected, duplicated frames remain but they are reverted to non\-interlaced. If input was non\-interlaced only remove duplicate frames. Interlaced frame detection may fail in conditions like: Pull down cycle changed (video editing). Low quality pull down. Motionless scene. .br If \fB\-C\fP \fIPATH\fP was specified, \fByuvkineco\fP outputs 2\-3 pull down cycle list to the file. You can edit this file by hand and feed it to \fByuvkineco\fP with \fB\-O\fP or \fB\-N\fP option to correct mistake of 1st \fByuvkineco\fP. Try \fB\-C\fP and see cycle list. EXAMPLE #1: for 24p movie / automatically \fBlav2yuv 60i.eli | \\ yuvkineco \-F 1 | yuv2lav \-f a \-I 0 \-o 24p.avi\fP EXAMPLE #2: for 30p/24p mix / automatically \fBlav2yuv 60i.eli | \\ yuvkineco \-F 4 | yuv2lav \-f a \-I 0 \-o 30p.avi\fP EXAMPLE #3: for 24p movie / check and repair \fBlav2yuv 60i.eli | \\ yuvkineco \-F 1 \-C 60i.23c | \\ yuv2lav \-f a \-I 1 \-o take1.avi glav \-F +n take1.avi\fP \ # check and edit 60i.23c \fBlav2yuv take1.avi | \\ yuvkineco \-F 1 \-N 60i.23c | \\ yuv2lav \-f a \-I 0 \-o take2.avi\fP EXAMPLE #4: for 24p movie / check and retry \fBlav2yuv 60i.eli | \\ yuvkineco \-F 1 \-C 60i.23c | \\ yuv2lav \-f a \-I 0 \-o take1.avi glav \-F +n take1.avi\fP \ # check and edit 60i.23c \fBlav2yuv 60i.eli | \\ yuvkineco \-F 1 \-O 60i.23c | \\ yuv2lav \-f a \-I 0 \-o take2.avi\fP .SH OPTIONS \fByuvkineco\fP accepts the following options: .TP 8 .BI \-F \ FPSCODE Set output fps code (default: same as input). .TP 8 .BI \-C \ PATH Specify 2-3 pull down cycle list file name to write. .TP 8 .BI \-O \ PATH Specify cycle list name to read with old yuv stream to retry. .TP 8 .BI \-N \ PATH Specify cycle list name to read with new yuv stream to repair. .TP 8 .BI \-S \ MIN Use \fByuvycsnoise\fP(1) as preprocessor and specify minimum threshold. .TP 8 .BI \-n \ LEVEL Specify noise level of input (default: 10). This affects both pulldown cycle detection and deinterlacing. .TP 8 .BI \-c \ THRESHOLD Specify threshold to decide pictures in 2 frames are same (default: 4). \fByuvkineco\fP compares several frames, searches pair of frame they contain same pictures, to decide which frame should be dropped. If \fITHRESHOLD\fP is 0, pair which has smallest difference will be selected. If 16, selected from pairs those have differences smaller than average. .TP 8 .BI \-i \ PERMIL \fByuvkineco\fP deinterlaces each frame after 2\-3 pulldown reverting process, specify how much pixels deinterlaced to decide to use or not use deinterlacing result (default: 10). If \fIPERMIL\fP is 10 and 1% or more of pixels deinterlaced, deinterlacing result will be used. If 0, always deinterlacing result will be used. If 1000, deinterlacing result will not be used, but deinterlacing process will run on all of frames. To disable deinterlacing process, specify negative value. .TP 8 .BI \-u Set interlace information in header of output to unknown (default: non\-interlaced). .SH AUTHOR \fByuvkineco\fP was written by Kawamata/Hitoshi. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP .TP For more info, see our website at .I http://mjpeg.sourceforge.net/ .SH SEE ALSO .BR mjpegtools (1), .BR yuvycsnoise (1). mjpegtools-2.1.0/docs/lavtrans.10000755000175000017500000000405212216627207017066 0ustar glowwormglowworm.TH "lavtrans" "1" "2 June 2001" "MJPEG Tools Team" "MJPEG tools manual" .SH "NAME" lavtrans \- Convert MJPEG videos to other MJPEG video formats .SH "SYNOPSIS" .B lavtrans \-o .I outputfile .BR \-f\ a | q | i | w .RB [ \-i .IR num ] .I lavfile1 \fP[\fIlavfile2 \fP...\fI lavfileN\fP] .SH "DESCRIPTION" \fBlavtrans\fP can be used to convert the recorded videos from one MJPEG "container" format to another one. It can also be used to split the streams, or do destructive edits. Like all the other \fBmjpegtools\fP(1) lavtrans also accept a edit list file in place of actual video files. This allows it to be used to construct a stand-alone copy of the editted video sequence described in the editlist. Note that lavtrans can only change the container type of MJPEG video, not the format. As such it is not possible to use it combine streams of different format. .SH "OPTIONS" \fBlavtrans\fP accepts the following options: .TP 5 .BR \-f " [" a | q | m | i | w ] Specifies the output format that should be saved. a \- output to AVI file q \- output to Qicktime file i \- output single JPEG images, w \- output WAV file (sound only!) .TP 5 .BI \-i " num" Convert a single frame to a JPEG file. .TP 5 .BI \-o " outputfile" Specifies the name of the output file If you want as output single JPEG images the output file string must be a valid format string .TP 5 .I filename Multiple filenames as input are acceped, also mixing of edit list files and other in video files. .SH BUGS There seem to be problems with the transoding of large Quicktime movies. One other thing is that with interlaced movies only one field is extracted. So you get pictures with the full horizontal size and half vertical size. .SH "AUTHOR" This man page was written by Bernhard Praschinger. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP .TP For more info, see our website at .I http://mjpeg.sourceforge.net .SH "SEE ALSO" .BR mjpegtools (1), .BR lavplay (1) mjpegtools-2.1.0/docs/mpeg2enc.10000644000175000017500000006710010772065733016741 0ustar glowwormglowworm.TH "mpeg2enc" "1" "25 Aug 2002" "MJPEG Tools Team" "MJPEG tools manual" .SH "NAME" mpeg2enc \- MPEG-1/2 encoder .SH "SYNOPSIS" .B mpeg2enc .RB [ -v | --verbose .IR num ] .RB [ -M | --multi-thread .IR num_CPU ] .RB [ -f | --format .IR mpeg_profile ] .RB [ -l | --level ] h | high | m | main .RB [ -b | --video-bitrate .IR bitrate_kbps ] .RB [ -V | --video-buffer .IR video_buf_size_kB ] .RB [ -T | --target-still-size .IR still_size_kB ] .RB [ -q | --quantisation .IR quantisation ] .RB [ -r | --motion-search-radius .IR motion_search_radius ] .RB [ -Q | --quantisation-reduction .IR \-4.0..5.0 ] .RB [ -X | --quant-reduction-max-var .IR 0.0 .. 2500.0] .RB [ -p | --3-2-pulldown ] .RB [ -I | --interlace-mode .IR 0|1|2 ] .RB [ -s | --sequence-header-every-gop ] .RB [ -g | --min-gop-size .IR min_gop_size ] .RB [ -G | --max-gop-size .IR max_gop_size ] .RB [ -P | --force-b-b-p ] .RB [ -n | --video-norm .IR n|p|s ] .RB [ -F | --frame-rate .IR frame_rate_code ] .RB [ -x | --display-hsize] .IR 32 .. 38383 ] .RB [ -y | --display-vsize] .IR 32 .. 38383 ] .RB [ -a | --aspect .IR aspect_ratio_code ] .RB [ -z | --playback-field-order .IR b|t ] .RB [ -4 | --reduction-4x4 .IR 1..4 ] .RB [ -2 | --reduction-2x2 .IR 1..4 ] .RB [ -S | --sequence-length .IR size_MB ] .RB [ -B | --nonvideo-bitrate .IR bitrate_kbps ] .RB [ -N | --reduce-hf .IR 0.0..2.0 ] .RB [ -D | --intra_dc_prec .IR 8..11 ] .RB [ -H | --keep-hf ] .RB [ -d | --no-dummy-svcd-SOF ] .RB [ -C | --correct-svcd-hds ] .RB [ --no-constraints ] .RB [ -K | --custom-quant-matrices .IR kvcd|tmpgenc|default|hi-res|file=inputfile|help ] .RB [ -E | --unit-coeff-elim .IR -40..40 ] .RB [ -R | --b-per-refframe .IR 0..2 ] .RB [ --no-altscan-mpeg2 ] .RB [ --dualprime-mpeg2 ] .RB [ -A | --ratecontroller .IR 0..1 ] .RB [ -u | --cbr ] .RB [ --chapters .IR frame,... ] .RB [ -? | --help ] .B -o|--output .I filename .SH "DESCRIPTION" mpeg2enc is heavily enhanced derivative of the MPEG Software Simulation Group's MPEG-2 reference encoder. It accepts streams in a simple planar YUV format "YUV4MPEG" produced by the \fBlav2yuv\fP and related filters (e.g. \fByuvscaler\fP(1)) from the \fBmjpegtools\fP(1) package. An output plug-in to the \fBmpeg2dec\fP(1) MPEG decoder is available to permit its use in transcoding applications. The encoder currently fully supports the generation of elementary MPEG-1, progressive and interlaced frame MPEG-2 streams. Field encoded MPEG-2 is also possible but is not currently maintained or supported. For most purposes this elementary stream output will need to be multiplexed with one or more audio streams into a program/systems stream using the .BR mplex (1) tool. Note that although this manual page aims to explain how mpeg2enc can be used effectively it is not intended as an introduction to MPEG-1/2 video which is a fairly complex topic in its own right. The MPEG video format is a somewhat baroque standard with many many options, not all of which necessarily easy to explain or even particular useful in the context of a software encoder. Much useful practical information for novices can be found in the mjpeg-HOWTO document that should have been installed with \fBmjpegtools\fP(1) package. Further information and useful supporting software can be found on the mjpegtools web-site: .br .IP \fBhttp://mjpeg.sourceforge.net\fP .SH "SELECTING THE MPEG PROFILE" .PP Set the MPEG profile to use. The MPEG standards support a vast number of options. In practice, different applications of the MPEG format place additional constraints of the form the MPEG stream. Setting this flag selects the kind of stream to produce. .PP .BR -f|--format \ 0 - Generic MPEG1. .PP A basic MPEG-1 profile that lets most parameters be adjusted for particular applications using the other flags. Typical applications would be to produce a variable bitrate MPEG-1 stream with big buffers and a high data-rate software playback on a computer. .PP .BR -f|--format \ 1 - Standard VCD. .PP An MPEG1 profile exactly to the VCD2.0 specification. Flag settings that would result in a non-standard stream structure are simply ignored. .PP .BR -f|--format \ 2 - User VCD. .PP As for profile 2 but bitrate and video buffer size can be set to non-standard values. Frame size may also be non-standard. Bit-rate and buffer sizes default to those for standard VCD. .PP .BR -f|--format \ 3 - Generic MPEG2. .PP A basic MPEG-2 profile that lets most parameters be adjusted for particular applications using the other flags. Typical applications would be to produce a MPEG-2 stream with big buffers and long GOP's for software playback on a computer. .PP .BR -f|--format \ 4 - Standard SVCD. .PP An MPEG-2 profile exactly to the SVCD2.0 specification. Flag settings that would result in a non-standard stream structure are simply ignored. .PP .BR -f|--format \ 5 - Non-standard SVCD. .PP As for profile 4 but bitrate, video buffer size, GOP sizes and structure can be set to non-standard values. Frame size may also be non-standard. Bit-rate and buffer sizes default to those for standard SVCD. .PP .BR -f|--format \ 6 - VCD Stills sequence. .PP Encodes the special style of MPEG stream used for still images on VCDs. To use this profile you must set the target size you wish to compress the images to using the -T flag. Reasonable values are around 35KB for standard resolution stills (352 wide) and 120KB for high resolution stills (704 wide). .PP .BR -f|--format \ 7 - SVCD Stills sequence. .PP Encodes the special style of MPEG stream used for still images on SVCDs. Both standard (480 wide) and high resolution (704 wide) images are supported. As with VCD stills you select how big each compressed still should be using the -T flag. .PP .BR -f|--format \ 8 - DVD MPEG-2 for 'dvdauthor' .PP This version adds special dummy navigation packets into the output stream that the dvdauthor tool fills in to make a proper .VOB for authoring. Bit-rate defaults to 7500kbps, buffer sizes to the maximum permitted by the DVD specification. .PP .BR -f|--format \ 9 - DVD MPEG-2. .PP Just a very basic implementation. Useful with DXR2 board and similar hardware that can decode MPEG-2 only if it is presented in a DVD like form. Bit-rate defaults to 7500kbps, buffer sizes to the maximum permitted by the DVD specification. .PP .BR -f|--format \ 10 - ATSC 480i .PP .BR -f|--format \ 11 - ATSC 480p .PP .BR -f|--format \ 12 - ATSC 720p .PP .BR -f|--format \ 13 - ATSC 1080i .SH "GENERAL FUNCTION LETTERS" .PP .BR -v|--verbose \ num .PP Set verbosity level to num. 0 = warnings and errors only, 1 = information as well, 2=really verbose. .PP .BR -K|--custom-quant-matrices \fBkvcd\fP | \fBtmpgenc\fP | \fBdefault\fP | \fBhi-res\fP | \fBfile=\fPinputfile | \fBhelp\fP .PP Specify which quantisation matrices to use instead of the defaults (which can be specified by using "-K default"). Using "-K hi-res" is identical to using the -H option. The value kvcd uses the Kvcd.Net matrices from http://www.kvcd.net/; the value tmpgenc invokes the TMPGEnc matrices from http://www.tmpgenc.net/e_main.html. On average (this depends on the source material), the tmpgenc tables reduce the average bitrate by about 10% and the kvcd tables reduce bitrate by about 16% (compared to the default tables). .PP .BR -E|--unit-coeff-elim \ -40..40 .PP Specify when a special 'unit coefficient elimination' algorithm should be applied to the encoded picture blocks. Basically, this procedure forces blocks of a type that don't carry much information but are expensive to encode to be simply skipped. The larger the number the more potentially visible this skipping is likely to be but the more compression is boosted. A negative value means that all coefficients are zeroed, positive means only texture but not base intensity coefficients are zeroed. Values of around 10 or -10 seem to work well with high quality source material. For noisier material it might be worth trying 20 or -20. .PP Note: if B frames are being encoded this only applies to B frames. .BR -R|--b-per-refframe \ 0..2 .PP Specify how many bi-directionally (B type) difference-encoded frames should be encoded between reference (I or P) frames. The default is 0 except for VCD encoding where it is 2 B frames as required by the standard. Experts differ on how much using B frames improves compression. In practice unless you have really clean material they tend to be fairly useless and sometimes even harmful. Encoding is significantly faster and uses less memory if no B frames are encoded and compression is rarely more than marginally worse. .PP .BR -?|--help .PP Display a synopsis of the command syntax. .SH "FUNCTION LETTERS ADJUSTING THE SELECTED PROFILE" N.b. If the profile you have selected sets particular values for these parameters it will over-ride these adjustment flags. In particular, there is almost \fInothing\fP that can be adjusted for the standard VCD and SVCD profiles. .PP .BR -b|--video-bitrate \ num .PP The bitrate of the output video stream in kBits/sec. The default is exactly the bitrate required for VCD streams. If variable bitrate (VBR) mode has been selected (see the -q option) this is the .I maximum bitrate of the stream. \fBNOTE:\fP By default MPEG-2 streams (\fB-f\fP 3, 4, 5, 8 and 9 are VBR. Use the \fB--cbr\fP option for generating CBR (Constant Bit Rate) streams. .PP .BR -A|--ratecontroller \ 0..1 .PP Specify which of the rate control algorithms to use. Default is 0. .PP .BR -V|--video-buffer \ num .PP The maximum video buffer usage required to decode the stream in KBytes. The default is 46KB the (tiny) size specified for VCD. The size to use for SVCD is the (more reasonable) 230KB. If you are encoding for a half-decent software decoder it makes sense to push this up to 500K or more. .PP .BR -T|--target-still-size \ num .PP Set the target size for (S)VCD still images in KB. .PP .BR -s|--sequence-header-every-gop .PP This flag forces the encoder to generate a "sequence header" at the start of every group-of-pictures. This is needed by some player hardware to support fast forward/rewind/random access functions but is a waste of bits otherwise. .PP .BR -d|--no-dummy-svcd-SOF .PP The SVCD MPEG-2 profile demands that special "Scan OFfset" which are (in effect) pointers to the place on the final SVCD disk where the video for 0.5 and around 5-10 seconds behind and ahead in the stream is located. The intended use of this information is to support"Fast forward/Rewind" functions. Unfortunately, at the time mpeg2enc encodes the video it doesn't know where the video is going to finally end up. So special dummy "Scan OFfset" values are written which are intended to be filled in during the creation of the SVCD image. Currently the GNU vcdimager tool handles this task. However, in some circumstances the dummy offsets can cause problems. This flags stops mpeg2enc generating them. .PP .BR --correct-svcd-hds .PP In the official SVCD standards the field in the MPEG-2 header information that passes on the encoders "recommended" horizontal resolution to decode the stream to is supposed to take the values 540 (for 4:3 sequences) or 720 (for 16:9 sequences). In practice many players don't work unless the value is 480. This flag, forces mpeg2enc to follow the official standard. It is worth trying if 16:9 sequences play at 4:3 aspect ratio. .PP .BR --no-constraints .PP This flag deactivates all constraints for the maximum video samplerate or video resolution. Its purpose is to allow the encoding of unusual resolutions of MPEG-video (e.g. 2200 x 576, 160 degrees FOV VR-theatre MPEG movies), but should be used with care: It can possible circumvent a number of other security checks, and untested settings can cause mpeg2enc to crash in this mode. .BR -l |--level\ h|high|m|main .PP This flag allows the MPEG-2 implementation level against which the coding parameters are checked to be set. You may need to set this to 'high' if you're encoding HDTV material. .PP .BR --no-altscan-mpeg2 .PP This flag deactivates the use of the 'alternate' macroblock scan pattern for MPEG2 encoding. Normally this pattern is used but a few elderly software decoders had bugs relating to this feature. You should never need to use this flag. .PP .BR --dualprime-mpeg2 .PP MPEG-2 supports a special motion estimation mode (DPME, Dual Prime Motion Estimation) for I/P-frame only streams that can somewhat improve compression. A number of players (both hardware and software) do not support this mode. Those players may or may not be MPEG-2 compliant depending if DPME is an option or not in the MPEG-2 specs. If you need to generate content for such players (e.g. Ogle or Apple's DVD player application) you should NOT turn on dualprime-mpeg2! Surprisingly at least one hardware/set-top player is known to be allergic to DPME being used. .PP .BR -z|--playback-field-order \ b|t .PP This flag overrides the field-order specified in the interlacing tag of the input stream header. (If you need this option, it indicates a problem in the capturing/encoding process where the temporal order of the two fields in each frame has been mislabeled. The effect of this is weird "juddering" when playing back the stream on a TV. Check the mjpeg-howto for more information about interlacing problems.) .PP .SH "OPTION LETTERS CONTROLLING VIDEO PARAMETERS" .PP .BR -n|--video-norm \ n|p|s .PP Force the input stream to be treated as NTSC|PAL|SECAM regardless of what the stream header might suggest. Basically this just sets the defaults for a bunch of other options. .PP .BR -F|--frame-rate \ num .PP Set the frame-rate of the output-stream. By default, this value is inferred from the input header. Currently only the standard MPEG rates are supported. Eventually more-or-less arbitrary rates will be possible. .br 0 - illegal .br 1 - 24000.0/1001.0 (NTSC 3:2 pulldown converted FILM) .br 2 - 24.0 (NATIVE FILM) .br 3 - 25.0 (PAL/SECAM VIDEO / converted FILM) .br 4 - 30000.0/1001.0 (NTSC VIDEO) .br 5 - 30.0 .br 6 - 50.0 (PAL FIELD RATE) .br 7 - 60000.0/1001.0 (NTSC FIELD RATE) .br 8 - 60.0 .br .PP .BR -a|--aspect \ num .PP Set the playback aspect ratio code of the encoded video. By default, this value is inferred from the input header. .br 1 - 1 - 1:1 display .br 2 - 2 - 4:3 display .br 3 - 3 - 16:9 display .br 4 - 4 - 2.21:1 display .IP For MPEG-2 the specified aspect ratios are used directly. For MPEG-1 mpeg2enc infers the MPEG-1 pixel aspect code from the video norm specified and the specified playback aspect ratio. .PP .BR -x|--display-hsize \ num .PP .BR -y|--display-vsize \ num .PP These set the display-horizontal-size and display-vertical-size hints in the MPEG-2. By default these are simply the encode frame dimensions. However, if they are set to different values the player gets a hint that the appropriate 'black bars' or cropping/scaling should be performed. The main use for these parameters is to set a display-vertical-size of 1080 for HDTV 1080i or 1080p material. Here, since the frame height has to be a multiple of 16, the encoded frame height is forced to be 1088, even though HDTV standards specify only 1080 lines of picture content. Standards committees ... love' em. .BR -p|--3-2-pulldown .PP Setting -p only makes sense for 24frame/sec Movie source material. It sets flags in the output stream that tell the decoder to play the movie as NTSC 60field/sec video using "3:2 pulldown". This is vastly more efficient than encoding as 60field/sec video. The classic application is to transcode a PAL-encoded movie (24fps played too fast at 25 fps!) into NTSC (see the -f flag). .SH "OPTION LETTERS FOR CONTROLLING COMPRESSION AND SPEED" .PP .BR -M|--multi-thread \ num_CPU .PP MPEG encoding is a task that can be split over a small number of CPU's quite efficiently. Mpeg2enc can be internally set to split major processing tasks between a number of concurrent threads. This flag adjusts the multi-threading to the optimum to utilise the specified number of CPU's. .PP It should be noted that even with 1 CPU present \fIsome\fR multi-threading is performed: frame input takes place in parallel with encoding. The default -M value is 1. This allows good performance to be achieved when when a seperate machine is being used for pre-processing (decoding from MJPEG, scaling, denoising etc) with the final result pipe to mpeg2enc (e.g. using rsh or ssh). .PP Setting -M 0 disables all multithreading. This is sometimes useful for debugging or to achieve maximum CPU efficiency on a shared machine. Setting -M 3 on a dual-CPU machine will produce slightly faster results than -M 2 at the price of slightly less CPU efficiency. This is useful if nothing else needs to be done on the encoding machine. In practice there is little point setting -M greater than 4 even if the CPU's are available due to the fairly coarse-grained parallelism used. Indeed there is a hardcoded limit of 4 worker threads. .PP The default has been changed to be 0 instead of 1 to avoid the crash at end of encoding: .nf INFO: [mpeg2enc] Signaling last frame = 499 mpeg2enc: seqencoder.cc:433: void SeqEncoder::EncodeStream(): Assertion `pass1coded.size() == 0' failed. Abort .fi .PP .BR -q|--quantisation \ 1 .. 31 .PP Minimum quantisation of the output stream. Quantisation controls the precision with which image information is encoded. The lower the number the higher the quality but the greater the required data-rate. \fBNOTE:\fP on IA32 systems it is possible to cause artifacting by setting the value too low (3 or less) due to arithmetic overflow/truncation in the DCT/iDCT routines. If this option is set a .I variable bitrate stream is produced. This is more efficient but variable bitrate MPEG-1 cannot be played by some hardware decoders and is rejected by some DVD authoring packages. If you intend to use a software decoder you'd be insane not to use variable bitrate. .sp If this option is set without a maximum bitrate being specified then quantisation is fixed at the specified value. It should be noted that not specifying a bitrate is probably an error and may produce unexpected results. .sp For MPEG-2 streams a default of 8 is used if \fB-q\fP is not explicitly given. To force constant bitrate streams use \fB--cbr\fP and \fB-b NOT -q\fP! .PP .BR -I|--interlace-mode \ 0|1|2 .PP Set the sequence picture structure and block encoding type for MPEG-2 streams. By default, this value is inferred from the interlacing tag of the input stream. Setting 0 encodes frame-by-frame with support for interlaced video turned off, and specifies that progressive chroma subsampling has been used. Setting 1 encodes frame-by-frame with interlace-adapted motion compensation and block encoding, and specifies that interlaced chroma subsampling has been used. Setting 2 encodes interlaced material field-by-field, which will produce more accurate results for highly textured interlaced material with lots of motion, at the expense of generally less efficiency. .IP This setting should match the interlaced-ness of the input stream, otherwise chroma artifacts may be generated when the MPEG stream is played back. .PP .BR -g|--min-gop-size \ num .PP .BR -G|--max-gop-size \ num .PP These flags set the minimum and maximum group-of-picture (GOP) size for the output MPEG stream. The default values depend on the output format. .sp For MPEG-1 (for example VCD) the default is a fixed GOP size of 12 (-g and -G are both set to 12). .sp For MPEG-2 the default value of -G (max) is set according to the video system: -G 15 for 625 line (PAL) and 18 for 525 line (NTSC). If -g (min) has not been specified then the minimum GOP size is set to be one half of the maximum (-G). .sp To force a fixed GOP size specify both -g and -G with the same value. .sp If the minimum and maximum GOP sizes are \fBnot\fP identical then mpeg2enc will start a \fBnew\fP GOP if more than 60% of the macroblocks in a P or B frame are Intra encoded. This ensure big changes of image coincide with a fully-encoded I-frame by starting a new GOP. This can help prevent transient "blockiness". .sp Reasonable minimum GOP sizes are 6 or 9. If a minimum is not specified but a maximum is given then the minimum will be set to one half the maximum. A larger GOP size can help reduce the bitrate required for a given quality. However, this really only applies to \fBhigh-quality\fP source material with \fBlittle noise\fP (e.g. digital video). For broadcast material there is little point setting GOP size much beyond 21 or 24. Even with good source material diminishing returns set in quite rapidly. Also it must be noted that specific MPEG-2 formats (such as for DVD) are constrained in the maximum allowable GOP size. .sp Note: mpeg2enc is currently hard-wired to produce 2 B frames between each I/P frame unless the GOP size forces less. This is reasonable for medium to high bitrates (>= 1Mbps) but probably sub-optimal for low-bitrate encoding. .PP .BR -c|--closed-GOPs .PP Setting this flag causes the encoder to generate only "closed" GOPs (Groups of Pictures) that can be decoded without reference to their predecessor. This is useful for streams that are supposed to be used in multi-angle DVD's and applications where more easily edittable MPEG is required. .PP .BR -P|--force-b-b-p .PP This flag forces the GOP size selection to choose sizes that ensure 2 B frames appear between adjacent I/P frames. Several common MPEG-1 decoders can't handle streams where less than 2 B-frames appear between I/P frames. .PP .BR -Q|--quantisation-reduction \ -4.0..5.0 .PP This flag sets the amount quantisation is reduced for blocks containing large amounts of sharp image detail. Large values produces efficient use of bits but may cause visible artifacting around detailed sections. With noisy source material this option may cause a "swimming" effect on textured backgrounds as the noise cause the quantisation of blocks to be boosted at random. The default is 0.0 (off). See also the \-X option. .PP .BR -X|--quant-reduction-max-var \ 0.0..2500.0 .PP Luma variance below which quantisation boost (-Q) is activated. .PP .BR -r|--motion-search-radius \ num .PP This flag sets the motion estimation search radius. For most purposes the default (16) should be just fine. For high-resolution MPEG-2 and active scenes it may be worth bumping it up. However, this will make encoding significantly slower. There is little point reducing the radius. Speed gains are not huge and the impact on quality can be marked. .PP .BR -4|--reduction-4x4 \ 1..4 .PP .BR -2|--reduction-2x2 \ 1..4 .PP These options control how radical the encoder is in throwing away apparently poor candidate estimates during motion estimation. A setting of 1 means very few blocks are discarded early which makes for slow encoding but quality as good as it gets. A setting of 4 makes for fast encoding but can impact quality. The -4 flag controls discarding during the initial 4*4 sub-sampled search stage, the -2 flag controls discarding during the secondary 2*2 sub-sampled stage. .IP These flags are useful as the speed quality trade-off is markedly different depending on which CPU you have. On modern machines the impact on speed is around a factor 2 on older machines a factor 3. The impact on quality is around 10% quantisation (0.2 of a bit of precision in encoding textures). For most purposes the default settings will be fine. However on P-III Katmai etc -4 2 -2 1 gives a good near-optimum quality setting with reasonably speed. .PP .BR -N|--reduce-hf \ num .PP Setting this flag adjusts the way texture detail is quantised to reduce the precision with which of high-frequency information encoded. This is very useful for .I mildly noisy sources. If you have really noisy material the filtering tools available in mjpegtools are a much better bet. The specified number must be in the range 0.0 to 2.0 gives the maxium quantisation boost. A useful number to use would be 1.5 or 1.0. .PP .BR -H|--keep-hf .PP Setting this flag makes the encoder encode as much high-frequency information as possible. This is a good setting for maximising quality at VCD resolution with good quality low-noise source material. It can also help with "swimmy" material if you can spare the bitrate! .PP .BR -D| --intra_dc_prec \ num .PP Specifies the precision of the DC component. The default is 9. Most commercial DVDs use 10. Using 9 instead saves a few bits. Using 10 might help to avoid looking larger areas of nearly the same color blocky. A value of 11 is only valid at the next MPEG-2 profile/level so it's not a currently meaningful value to use. .SH "OPTION LETTERS FOR CHUNKING THE OUTPUT STREAM" .PP .BR -S|--sequence-length \ num .PP This flag allows the target size of individual sequences in the final multiplexed stream to be set in MBytes. If set mpeg2enc keeps track of how large the eventual stream is getting and inserts a sequence split (actually: sequence end / sequence start) into the output stream each time it reaches the specified limit. The multiplexer \fBmplex\fP(1) can recognise these splits and start a new multiplexed output file each time it encounters one. In this way it is easy to automatically ensure each component sequence file can be burnt onto a CD-R and still be played as a stand-alone MPEG sequence. For the SVCD and VCD profiles the default target sequence length is 700M bytes. For other profiles the default is that sequence length is unlimited. .PP .BR -B|--nonvideo-bitrate \ num .PP Since mpeg2enc can't read minds it cannot know in advance what other material will be multiplexed with the output video stream. Thus to get its calculations of where to insert split point right it needs to be told the combined data-rate of the other material that is eventually to be multiplexed with the video. This flag allows this rate to be specified in K bits/sec. A good rule of thumb is to use the total rate of all the other streams plus 1% of the total rate including video. .PP .BR -u|--cbr .PP Force the use of Constant Bit Rate encoding. Less than optimal (and inefficient in almost all cases) but some folks insist on it. \fBNOTE:\fP this \fBdisables\fP (overrides) the use of the \fB-q\fP option! .sp It is an error to use this option and not specify a bitrate using \fB-b\fP since a constant bitrate of 0 makes no sense. .PP .BR --chapters \ frame,... .PP This flag allows you to define chapter points within the mpeg stream. This is most useful when generating DVD video. Each chapter point is specified by frame number, with the first frame being number 0. Every chapter point defined will end up at the beginning of a closed GOP as an I frame. .SH "SSE, 3D-Now!, MMX"! mpeg2enc makes extensive use of these SIMD instruction set extension on x86 family CPU's. The routines used are determined dynamically at run-time. It should be noted that using SSE requires operating system support. Old 2.2.x Linux kernels (unless patched ones like RedHat) do not have this and so SSE, although physically present, won't be activated. .SH "BUGS" There should be an option to force GOP sizes that permit 2 B frames between I/P frames. Some decoders (even software) can't handle the case where I/P frames come back to back or with only 1 B frame between them. There needs to be a facility for writing dummy user-data fields so that the multiplexer/imager can insert forward/backward pointers when muxing/imaging an SVCD. .SH AUTHOR This man page was written by Andrew Stevens. If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG-tools is: \fImjpeg\-users@lists.sourceforge.net\fP For more info, see our website at \fIhttp://mjpeg.sourceforge.net .SH "SEE ALSO" .BR mplex "(1), " mp2enc "(1), " lavrec "(1), " lavplay "(1), " .BR lav2yuv "(1), " lav2wav "(1), " yuvscaler "(1), " yuvdenoise "(1), " y4mdenoise "(1), " mjpegtools "(1)" mjpegtools-2.1.0/docs/mjpeg-howto.info0000644000175000017500000035724312217255472020303 0ustar glowwormglowwormSTART-INFO-DIR-ENTRY * mjpegtools: (mjpeg-howto). command line tools for MPEG audio and video. END-INFO-DIR-ENTRY  File: mjpeg-howto.info, Node: Top, Next: Introduction, Up: (dir) MJPEG HOWTO - An introduction to the MJPEG-tools ************************************************ Praschinger Bernhard v2.00 MJPEG capture/editting/replay and MPEG encoding toolset description * Menu: * Introduction:: * Unsorted list of useful Hints:: * Recording videos:: * Creating videos from other sources:: * Checking if recording was successful:: * Edit the video:: * Converting the stream to MPEG or DIVx videos:: * Optimizing the stream:: * Transcoding of existing MPEG-2:: * Trading Quality/Speed:: * SMP and distributed Encoding:: * Interoperability::  File: mjpeg-howto.info, Node: Introduction, Next: Unsorted list of useful Hints, Prev: Top, Up: Top 1 Introduction ************** I wrote this things down, because I had many sheets with notes on them. This should be some kind of summary of collected knowledge over a long period of time. Andrew Stevens helped with encoding and VCD knowledge and hints. Mjpegtools is a set of programs that can do recording, playback, editing and eventual MPEG compression of audio and video under Linux. Although primarily intended for use with capture / playback boards based on the Zoran ZR36067 MJPEG codec chip mjpegtools can easily be used to process and compress MJPEG video streams captured using xawtv using simple frame-buffer devices. The HOWTO for the tools intended to give an an introduction to the MJPEG-tools and the creation of MPEG 1/2 videos. VCD, SVCD and DVD and the transcoding of existing mpeg streams. For more information about the programs read the corresponding man-page. Achtung es gibt auch eine deutsche Version bei: `http://sourceforge.net/projects/mjpeg' There is also a manpage of this text. You can read it with "man mjpegtools" if installed. We also have a info version you should be able to read it with info The text version of this text is available via cvs. You should get it with the tarball or the precompiled package (RPM and deb). In the following picture you see the typical workflow when you record a video, cut it afterwards and encode it. In the picture you also see the connections to other programs. These parts are in grey. The parts in blue can be done with the mjpegtools. Video encoding workflow  File: mjpeg-howto.info, Node: Unsorted list of useful Hints, Next: Recording videos, Prev: Introduction, Up: Top 2 Unsorted list of useful Hints ******************************* You have to compile and install the mjpeg_play package, for this read the README & INSTALL.real an follow the hints from the configure script. If you do not want to compile it, you can download the mjpeg .RPM or .DEB package at Sourceforge, or if available use the one that comes with your distribution. There is a script in the scripts/ directory. This script is something that shows you a way it can be done. It also creates (under certain circumstances) videos that look quite good. Better videos you will only get by tuning the parameters. If you use a Linux kernel from the 2.4 series you will usually have to load the drivers for the Buz or DC10 or LML33 cards. You have to run the update script providing as option the name of your card you have. The script is usually in /usr/src/driver-zoran/. The zoran kernel driver below the kernel 2.4.4 do not work. You have to use the driver available from: `http://mjpeg.sourceforge.net/driver-zoran' In the 2.6. Linux kernel is the driver for the zoran cards included, you just need to make sure that it is loaded correct. If you have a x64 machine and an kernel that is newer than 2.6.30 we'd be happy to hear that you are able to record from the zoran based card. I'm not soure if that combination works. The driver for the Matrox Marvel card also works, more information about it: `http://marvel.sourceforge.net' If you compile the tools on a P6 based computer (PPro, P-II, P-III, P-4, Athlon,Duron) then never try to let them run on a P5 based computer (Pentium, Pentium-MMX, K6, K6-x, Cyrix, Via, Winchip). You'll get a "illegal instruction" and the program won't work. That is the same for the newer CPU as well. If you use specific optimizations be aware of them. If lav2yuv dumps core then one possible cause is no dv support was included. To enable it make sure that libdv is installed on the system. This will be necessary if you are using a digital camera (or analog to DV converter such as the Canopus ADVC100 and converting the dv avi format into the MPEG format. Start xawtv to see if you get an picture. If you want to use HW-playback of the recorded streams you have to start xawtv (any TV application works) once to get the streams played back. You should also check the settings of your mixer in the sound card. If you use v4l2 you should give mplayer a try to watch the picture If you compile the tools on a platform other than Linux not all tools will work. Mjpegtools on a OS/X system for example will not have V4L (video4linux) capability. Never try to stop or start the TV application when lavrec runs. If you start or stop the TV application lavrec will stop recording, or your computer could get "frozen". This is a problem of v4l (video4linux). This problem is solved with v4l2. If you use v4l2 you can record the video and stop and start the tv application whenever you want. But v4l2 is currently (7. Jan. 2003) only supported for the zoran based cards (BUZ, DC10, DC10+, LML33) if you use the CVS driver from mjpeg.sf.net tagged with ZORAN_VIDEODEV_2. And this driver only works with the 2.4.20 kernel and the 2.5.* development kernel. One last thing about the data you get before we start: Audio: ( Samplerate * Channels * Bitsize ) / (8 * 1024) CD Quality:(44100 Samples/sec * 2 Chanels * 16 Bit) / (8 * 1024)=172,2 kB/sec The 8 * 1024 convert the value from bit/sec to kByte/sec Video: (width * height * framerate * quality ) / (200 * 1024) PAL HALF Size : (352 * 288 * 25 * 80) / (200 * 1024) = 990 kB/sec PAL FULL size : (720 * 576 * 25 * 80) / (200 * 1024) = 4050 kB/sec NTSC HALF size: (352 * 240 * 30 * 80) / (200 * 1024) = 990 kB/sec NTSC FULL size: (720 * 480 * 30 * 80) / (200 * 1024) = 4050 kB/sec The 1024 converts the Bytes to kBytes. Not every card can record the size mentioned. The Buz and Marvel G400 for example can only record a size of 720x576 when using -d 1, the DC10 records a size of 384x288 when using -d 2. When you add audio and video datarate this is what your hard disk has to be able to write constantly streaming, else you will have lost frames. If you want to play with the *-mjpeg-buffer-size*. Remember the value should be at least big enough that one frame fits in it. The size of one frame is: (width * height * quality ) / (200 * 1024) = kB If the buffer is too small the rate calculation doesn't match any more and buffer overflows can happen. The maximum value is 512kB. How video works and the difference between the video types is explained here: `http://www.mir.com/DMG/' There you also find how to create MPEG Still Images for VCD/SVCD. A good description of DV (Digital Video) can be found here: `http://www.uwasa.fi/~f76998/video/conversion/' * Menu: * Some books we found usefull::  File: mjpeg-howto.info, Node: Some books we found usefull, Up: Unsorted list of useful Hints 2.1 Some books we found usefull =============================== written in English: * Digital Video and HDTV by Charles Poyton (ISBN 1-55860-792-7) * Digital Video Compression by Peter Symes (ISBN 0-07-142487-3) * Video Demystified by Keith Jack (ISBN 1-878707-56-6) written in German: * Fernsehtechnik von Rudolf Maeusl (ISBN 3-7785-2374-0) * Professionelle Videotechnik - analoge und digitale Grundlagen von U. Schmidt (ISBN 3-540-43974-9) * Digitale Film- und Videotechnik von U. Schmidt (ISBN 3-446-21827-0) If you know some other really good book about that, write us!  File: mjpeg-howto.info, Node: Recording videos, Next: Creating videos from other sources, Prev: Unsorted list of useful Hints, Up: Top 3 Recording videos ****************** * Menu: * lavrec examples:: * Other recording hints:: * Some information about the typical lavrec output while recording:: * Notes about "interlace field order - what can go wrong and how to fix it"::  File: mjpeg-howto.info, Node: lavrec examples, Next: Other recording hints, Up: Recording videos 3.1 lavrec examples =================== Recording with lavrec looks like this: `> lavrec -f a -i P -d 2 record.avi' `' Should start recording now, `-f a' use AVI as output format, `-i P' use as input source the SVHS-In with PAL format, `-d 2' the size of the pictures are half size (352x288) `record.avi' name of the created file. Recording is finished by pressing Ctrl-C (on German Keyboards: Strg-C). Sometimes using *-f A* instead of *-f a* might be necessary Other example: `> lavrec -f q -i n -d 1 -q 80 -s -l 80 -R l -U record.avi ' `' Should start recording now, `-f q' use Quicktime as output format, `-i n' use Composite-In with NTSC format, `-d 1' record pictures with full size (640x480) `-q 80' set the quality to 80% of the captured image `-s' use stereo mode (default mono) `-l 80' set the recording level to 80% of the max during recording `-R l' set the recording source to Line-In `-U' With this lavrec uses the read instead of mmap for recording this is needed if your sound card does not support the mmap for recording. Setting the mixer does not work with every sound card. If you record with 2 different settings and both recordings are equally loud you should setup the mixer with a mixer program. After that you should use the *-l -1* option when you record using lavrec The size of the image depends on the card you use. At full size (-d 1) you get these image sizes: BUZ and LML33: 720x576, the DC10 and DC30: 768x576 Other example: `> lavrec -w -f a -i S -d 2 -l -1 record%02d.avi' `' Should start recording, `-w' Waits for user confirmation to start (press enter) `-f a' use AVI as output format, `-i S' use SECAM SVHS-Input (SECAM Composite recording is also possible: -i s) `-d 2' the size of the pictures are half size `-l -1' do not touch the mixer settings `record%02d.avi' Here lavrec creates the first file named record00.avi after the file has reached a size of 1.6GB (after about 20 Minutes recording) it starts a new sequence named record01.avi and so on till the recording is stopped or the disk is full. With the release of the 1.9.0 Version mjpegtools is able to handle AVI files larger than 2GB. So that option is present for compatibility. Other example: `> lavrec -f a -i t -q 80 -d 2 -C europe-west:SE20 test.avi' `' Should start recording now, `-f a' use AVI as output format, `-i t' use tuner input, `-q 80' set the quality to 80% of the captured image `-d 2' the size of the pictures are half size (352x288) `-C' choose TV channels, and the corresponding -it and -iT (video source: TV tuner) can currently be used on the Marvel G200/G400 and the Matrox Millenium G200/G400 with Rainbow Runner extension (BTTV-Support is under construction). For more information on how to make the TV tuner parts of these cards work, see the Marvel/Linux project on: `http://marvel.sourceforge.net' Last example: `> lavrec -f a -i p -g 352x288 -q 80 -s -l 70 -R l -software-encoding test03.avi' The two new options are *-g 352x288*, which sets the size of the video to be recorded when using *-software-encoding*, this enables the software encoding of the recorded images. With this option you can also record from a bttv based card. The processor load is high. This option only works for generic video4linux cards (such as the brooktree-848/878 based cards), it doesn't work for zoran-based cards.  File: mjpeg-howto.info, Node: Other recording hints, Next: Some information about the typical lavrec output while recording, Prev: lavrec examples, Up: Recording videos 3.2 Other recording hints ========================= All lavtools accept a file description like file*.avi so you do not have to name each file but that is a posibility. Note: More options are described in the man-page, but with this you should be able to get started. Here are some hints for sensible settings. Turn the quality to 80% or more for -d 2 capture. At full resolution as low as 40% seems to be visually "perfect". -d 2 is already better than VHS video (a *lot*!). For a Marvel you should not set the quality higher than 50 when you record at full size (-d 1). If you use higher settings (-q 60) it is more likely that you will encounter problems. Higher settings will result in framedrops. If you're aiming to create VCD's then there is little to be gained recording at full resolution as you need to reduce to -d 2 resolution later anyway. you can record at other sizes than the obvious -d 1/2/4. You can use combinations where you use halve horizontal size and full vertical size: -d 21. This would record for NTSC at a size of 352x480. This helps if you want to create SVCDs, scaling the 352 Pixles put to 480 is not that visible for the eye as if you would use the other combination -d 12. Where you have the full horzontal resolution and half vertical this Version will have a size of 720x288 for NTSC  File: mjpeg-howto.info, Node: Some information about the typical lavrec output while recording, Next: Notes about "interlace field order - what can go wrong and how to fix it", Prev: Other recording hints, Up: Recording videos 3.3 Some information about the typical lavrec output while recording ==================================================================== 0.06.14:22 int: 00040 lst:0 ins:0 del:0 ae:0 td1=0.014 td2=0.029 The first part shows the time lavrec is recording. *int:* the interval between two frames. *lst:* the number of lost frames. *ins and del:* are the number of frames inserted and deleted for sync correction. *ae:* number of audio errors. *td1 and td2* are the audio/video time-difference. * *[int] frame interval* should be around 33 (NTSC) or 40 (PAL/SECAM). If it is very different, you'll likely get a bad recording and/or many lost frames * *[lst] lost frames* are bad and mean that something is not working very well during recording (too slow HD, too high CPU usage, ...) Try recording with a greater decimation and possibly a lower quality. * *[ins, del] inserted OR deleted frames* of them are normal -> sync. If you have many lost AND inserted frames, you're asking too much of your machine. Use less demanding options or try a different sound card. * *[ae] audio errors* are never good. Should be 0 * *[td1, td2] time difference*is always floating around 0, unless sync correction is disabled (-synchronization!=2, 2 is default).  File: mjpeg-howto.info, Node: Notes about "interlace field order - what can go wrong and how to fix it", Prev: Some information about the typical lavrec output while recording, Up: Recording videos 3.4 Notes about "interlace field order - what can go wrong and how to fix it" ============================================================================= Firstly, what does it mean for interlace field order to be wrong? The mjpegtools image processing chain is frame-oriented. Since it is video material that is captured each frame comprised of a top field (the 0th, 2nd, 4th and so lines) and a bottom field (the 1st, 3rd, 5th and so on lines). * Menu: * There are three bad things that can happen with fields:: * How can I recognize if I have one of these Problems ?:: * How can you fix it?:: * Hey what about NTSC movies ?::  File: mjpeg-howto.info, Node: There are three bad things that can happen with fields, Next: How can I recognize if I have one of these Problems ?, Up: Notes about "interlace field order - what can go wrong and how to fix it" 3.4.1 There are three bad things that can happen with fields ------------------------------------------------------------ 1. This is really only an issue for movies in PAL video where each film frame is sent as a pair of fields. These can be sent top or bottom field first and sadly it's not always the same, though bottom-first appears to be usual. If you capture with the wrong field order (you start capturing each frame with a bottom rather than a top or vice versa) the frames of the movie get split *between* frames in the stream. Played back on a TV where each field is displayed on its own this is harmless. The sequence of fields played back is exactly the same as the sequence of fields broadcast. Unfortunately, playing back on a Computer monitor where both fields of a frame appear at once it looks *terrible* because each frame is effectively mixing two moments 1/25sec apart in time. 2. The two fields can simply be swapped somehow so that top gets treat as bottom and bottom treat as top. Juddering and "slicing" is the result. This occasionally seems to happen due to hardware glitches in the capture card. 3. Somewhere in capturing/processing the *order* in time of the two fields in each frame can get mislabeled somehow. This is not good as it means that when playback eventually takes place a field containing an image sampled earlier in time comes after an image sampled later. Weird "juddering" effects are the results.  File: mjpeg-howto.info, Node: How can I recognize if I have one of these Problems ?, Next: How can you fix it?, Prev: There are three bad things that can happen with fields, Up: Notes about "interlace field order - what can go wrong and how to fix it" 3.4.2 How can I recognize if I have one of these Problems ? ----------------------------------------------------------- 1. This can be hard to spot. If you have mysteriously flickery pictures during playback try encoding a snippet with the reverse field-order forced (see below). If things improve you know what the problem was and what the solution is! 2. The two fields can simply be swapped somehow so that top gets treat as bottom and bottom treat as top. Juddering and "slicing" is the result. This occasionally seems to happen due to hardware glitches in the capture card. That problem looks like that: Interlacing problem 3. Somewhere in capturing/processing the *order* in time of the two fields in each frame can get mislabeled somehow. This is not good as it means that when playback eventually takes place a field containing an image sampled earlier in time comes after an image sampled later. Weird "juddering" effects are the result. If you use glav or lavplay be sure that you also use the *-F/-flicker* option. This disables some things that improve the picture. If you want to look at the video you can also use yuvplay: `> lav2yuv | ... | yuvplay' If there is a field order problem you should see it with yuvplay.  File: mjpeg-howto.info, Node: How can you fix it?, Next: Hey what about NTSC movies ?, Prev: How can I recognize if I have one of these Problems ?, Up: Notes about "interlace field order - what can go wrong and how to fix it" 3.4.3 How can you fix it? ------------------------- 1. To fix this one the fields need to be "shifted" through the frames. Use yuvcorrect's *-T BOTT_FORWARD/TOP_FORWARD* to shift the way fields are allocated to frames. You can find out the current field order for an MJPEG file by looking at the first few lines of debug output from: *> lav2yuv -v 2 the_mjpeg_file > /dev/null* Or re-record exchanging *-f a* for *-F A* or vice-versa. 2. This isn't too bad either. Use a tool that simply swaps the top and bottom fields a second time. yuvcorrect can do this use the *-T LINE_SWITCH*. 3. Is easy to fix. Either tell a tool someplace to relabel the fields or simply tell the player to play back in swapped order (the latter can be done "indirectly" by telling mpeg2enc when encoding to *reverse the flag (-z b|t)* that tells the decoder which field order to use. *In order to determine exactly what type of interlacing problem you have, you need to extract some frames from the recorded stream and take a look at them:* > mkdir pnm > lav2yuv -f 40 video.avi | y4mtoppm | pnmsplit - pnm/image%d.pnm > rm pnm/image?.pnm > cd pnm > xv First we create a directory where we store the images. The lav2yuv -f 40 writes only the first 40 frames to stdout. The program y4mtoppm converts the frames to pnm images and the pnmsplit splits the picture into two frames in the picture to two single pictures. Then we remove the first 10 images because pnmsplit does not support the %0xd numbering. Without a leading zero in the number, the files will be sorted in the wrong order, leading to confusing playback. Use your favorite graphic program (xv for example) to view the pictures. As each picture only contain one field out of two they will appear scaled vertically. If you look at the pictures you should see the movie slowly advancing. If you have a film you should always see 2 pictures that are nearly the same (because the film frame is split into two field for broadcasting) after each other. You can observe this easily if you have comb effects when you pause the film because both fields will be displayed at the same time. The two pictures that belong together should have an even number and the following odd number. So if you take a look on pictures: 4 and 5 are nearly identical, 5 and 6 differ (have movement), 6 and 7 identical, 7 and 8 differ , .... To fix this problem you have to use yuvcorrect's *-T BOTT_FORWARD or TOP_FORWARD*. You can also have the problem that the field order (top/bottom) is still wrong. You may have to use yuvcorrect a second time with *-M LINE_SWITCH*, or use the mpeg2enc *-z (b|t)* option. To see if you guessed correctly extract the frames again and reorder them using yuvcorrect: `> lav2yuv -f 40 video.avi | yuvcorrect -T OPTION | y4mtoppm | pnmsplit - pnm/image%d.pnm ' Where "OPTION" is what you think will correct the problem. This is for material converted from film. Material produced directly for TV is addressed below.  File: mjpeg-howto.info, Node: Hey what about NTSC movies ?, Prev: How can you fix it?, Up: Notes about "interlace field order - what can go wrong and how to fix it" 3.4.4 Hey what about NTSC movies ? ---------------------------------- Movies are broadcast in NTSC using "3:2" pulldown which means that half the capture frames contain fields from 1 movie frame and half fields from 2 frames. To undo this effect for efficient MPEG encoding you need to use yuvkineco. If you have an interlaced source like a TV camera you have a frame consists of two fields that are recorded at different points in time. Spotting the problem here is harder. You need to find something moving horizontally from the left to the right. When you extract the fields, the thing should move in small steps from the left to the right, not one large step forward, small step back, large forward, small back...... You have to use the same options mentioned aboth to correct the problem. Do not expect that the field order is always the same (top- or bottom-first) It may change between the channels, between the films, and it may even change within a film. If it changes constant you may have to encode with the mpeg2enc -I 1 or even -I 2. You can only have this problems if you record at full size !!!  File: mjpeg-howto.info, Node: Creating videos from other sources, Next: Checking if recording was successful, Prev: Recording videos, Up: Top 4 Creating videos from other sources ************************************ Here are some hints and descriptions of how to create the videos from other sources like images and other video types. You might also be interested in taking a look at the *Transcoding of existing MPEG-2* section. * Menu: * Creating videos from images:: * Decoding streams with mplayer:: * Decoding MPEG-2 streams with mpeg2dec:: * Other things to know::  File: mjpeg-howto.info, Node: Creating videos from images, Next: Decoding streams with mplayer, Up: Creating videos from other sources 4.1 Creating videos from images =============================== You can use jpeg2yuv to create a yuv stream from separate JPEG images. This stream is sent to stdout, so that it can either be saved into a file, encoded directly to a mpeg video using mpeg2enc or used for anything else. Saving an yuv stream can be done like this: `> jpeg2yuv -f 25 -I p -j image%05d.jpg > result.yuv' Creates the file result.yuv containing the yuv video data with 25 FPS. The -f option is used to set the frame rate. Note that image%05d.jpg means that the jpeg files are named image00000.jpg, image00001.jpg and so on. (05 means five digits, 04 means four digits, etc.) The -I p is needed for specifing the interlacing. You have to check which type you have. If you don't have interlacing just choose p for progressive If you want to encode a mpeg video directly from jpeg images without saving a separate video file type: `> jpeg2yuv -f 25 -I p -j image%05d.jpg | mpeg2enc -o mpegfile.m1v' Does the same as above but saves a mpeg video rather than a yuv video. See mpeg2enc section for details on how to use mpeg2enc. You can also use yuvscaler between jpeg2yuv and mpeg2enc. If you want to create a SVCD from your source images: `> jpeg2yuv -f 25 -I p -j image%05d.jpg | yuvscaler -O SVCD | mpeg2enc -f 4 -o video.m2v' You can use the -b option to set the number of the image to start with. The number of images to be processed can be specified with the -n number. For example, if your first image is image01.jpg rather than image00.jpg and you only want 60 images to be processed type: `>jpeg2yuv -b 1 -f 25 -I p -n 60 -j image*.jpg | yuv2lav -o stream_without_sound.avi' Adding the sound to the stream then: `> lavaddwav stream_without_sound.avi sound.wav stream_with_sound.avi' For ppm input there is the ppmtoy4m util. There is a manpage for ppmtoy4m that should be consulted for additional information. To create a mpeg video try this: `>cat *.ppm | ppmtoy4m -o 75 -n 60 -F 25:1 | mpeg2enc -o output.m1v' cat each *.ppm file to ppmtoy4m. There the first 75 frames (pictures) are ignored and next 60 are encoded by mpeg2enc to output.m1v. You can run it without the -o and -n option. The -F options sets the frame rate, default is NTSC (30000:1001), for PAL you have to use -F 25:1. Other picture formats can also be used if there is a converter to ppm. `>ls *.tga | xargs -n1 tgatoppm | ppmtoy4m | yuvplay' A list of filenames (ls *.tga) is given to xargs that executes the tgatoppm with one (-n 1) argument per call, and feeds the output into ppmtoy4m. This time the video is only shown on the screen. The xargs is only needed if the converter (tgatoppm) can only operate on a single image at a time. If you want to use the ImageMagick 'convert' tool (a Swiss Army Knife) try: `>convert *.gif ppm:- | ppmtoy4m | yuvplay' That means take all '.jpg' images in directory, convert to PPM format, pipe to stdout, then to ppmtoy4m for conversion to y4m ....  File: mjpeg-howto.info, Node: Decoding streams with mplayer, Next: Decoding MPEG-2 streams with mpeg2dec, Prev: Creating videos from images, Up: Creating videos from other sources 4.2 Decoding streams with mplayer ================================= Decoding the streams with mplayer is a nice way of bringing every video that mplayer can play back to something you can edit or encode to mpeg with mjpegtools. This method has been tested with mplayer 1.0rc2 and should work with newer versions `>mkfifo stream.yuv' `>cat stream.yuv | yuv2lav -o mjpeg_wo.avi &' `>mplayer -nosound -noframedrop -vo yuv4mpeg anyfile.mpg' `>mplayer -vo null -ao pcm:file=anyfile.wav anyfile.mpg' Now you have an example of a mjpeg encoded AVI without sound. The sound will be in anyfile.wav. You can choose if you want to add the sound to the AVI with `lavaddwav' and edit the file before encoding. You can also use instead of yuv2lav, mpeg2enc or any other tool from the mjpeg tools so your command might also look like that: `> cat stream.yuv | yuvdenoise | yuvscaler -O SVCD | mpeg2enc -f 4 -o video_svcd.m2v' cat the wav file into `mp2enc' to encode it to MP2 audio. The *-vo yuv4mpeg* option works well with other input types mentioned in the mplayer documentation.  File: mjpeg-howto.info, Node: Decoding MPEG-2 streams with mpeg2dec, Next: Other things to know, Prev: Decoding streams with mplayer, Up: Creating videos from other sources 4.3 Decoding MPEG-2 streams with mpeg2dec ========================================= You can decode mpeg2 streams with the patched mpeg2dec version which creates yuv streams. You can pipe that into any other mjpegtools program. Or you use a mpeg2dec version directly from the libmpeg2 project and use the output mode pgmpipe. With the `pgmtoy4m' program you can convert that pgm output back to yuv. If you ask yourself why there is a patched version and pgmtoy4m. The answer is that the patch for yuv output was sent several times to the libmpeg2 developers but was never included. Now we have two ways around that problem. Decoding looks like this: `> mpeg2dec -s -o pgmpipe ANYTS.VOB | pgmtoy4m -i t -a 10:11 -r 30000:1001 | mpeg2enc -f 8 newvideo.m2v' You can decode the audio as described in the *Transcoding of existing MPEG-2* Section.  File: mjpeg-howto.info, Node: Other things to know, Prev: Decoding MPEG-2 streams with mpeg2dec, Up: Creating videos from other sources 4.4 Other things to know ======================== If you have Transport streams from your DVB card, or Satelite Receiver you might want to demultiplex or cut them. A nice tool for that is *Project X* available from: `http://www.lucike.info/page_projectx.htm' You can process the streams afterwards as you would do with any mpeg movie or demultiplexed audio video. So the *Transcoding of existing MPEG-2* section of this document will be of interest.  File: mjpeg-howto.info, Node: Checking if recording was successful, Next: Edit the video, Prev: Creating videos from other sources, Up: Top 5 Checking if recording was successful ************************************** You can use lavplay or glav. *IMPORTANT: NEVER* try to run xawtv and lavplay or glav with hardware playback, it will not work. For software playback it works fine. `>lavplay -p S record.avi' You should see the recorded video and hear the sound. But the decoding of the video is done by the CPU which will place a heavy load on the system. The advantage of this method is you don't need xawtv. The better way: `>lavplay -p H record.avi' The video is decoded and played by the hardware. The system load is very low. This will play it back on-screen using the hardware rather than software decoding. You might also try: `> lavply -p C record.avi' Which will play it back using the hardware but to the video output of the card. `> glav record.avi' Does the same as lavplay but you have an nice GUI. The options for glav and lavplay are nearly the same. Using no option SW playback is used. Using hardware playback a signal for the Composite and SVHS OUT is generated so you can view the movie on your TV. `> lav2yuv test.eli | yuvplay' Is a other way to get the video without sound. You can use yuvplay once in the encoding command. When you use yuvplay in the encoding command you see the changes made by filters and scaling. You can also use it for slow-motion debugging. *NOTE_* After loading the driver's you have to start xawtv to set up some things lavplay and glav do not, but they are needed for HW-Playback. Don't forget to close xawtv !! *NOTE2:* Do not try to send glav an lavplay into background, wont work correct !!! *NOTE3:* SECAM playback is now (12.3.2001) only in monochrome but the recording and encoding is done right. *NOTE4:*Bad cables may reduce the quality of the image. Normally you can't see this but when there is text you might notice a small shadow. When you see this you should change the cable. *Coming soon:* There is a tool which makes recoding videos very simple: Linux Studio. You can download it at: `http://ronald.bitfreak.net'  File: mjpeg-howto.info, Node: Edit the video, Next: Converting the stream to MPEG or DIVx videos, Prev: Checking if recording was successful, Up: Top 6 Edit the video **************** * Menu: * Edit with glav:: * Unify videos:: * Separate sound:: * Separate images:: * Creating movie transitions::  File: mjpeg-howto.info, Node: Edit with glav, Next: Unify videos, Up: Edit the video 6.1 Edit with glav ================== Most tasks can be easily done by glav. Like deleting parts of the video, cut paste and copy parts of the videos. glav button description The modifications should be saved because glav does not destructively edit the video. This means that the original video is left untouched and the modifications are kept in an extra "Edit List" file readable with a text editor. These files can be used as an input to the other lavtools programs such as lav2wav, lav2yuv, lavtrans. If you want to cut off the beginning and the end of the stream mark the beginning and the and, and use the "save select" button. The edit list file is than used as input for the lavtools. If you want to split a recorded video to some smaller parts simply select the parts and then save each part to a different listfile. You can see all changes to the video and sound NOW and you do not need to recalculate anything. If you want to get a "destructive" version of your edited video use: `> lavtrans -o short_version.avi -f a editlist.eli' `-o' specifies the output name `-f a' specifies the output format (AVI for example) `editlist.eli' is the list file where the modifications are described. You generate the list file with the "save all" or "save select" buttons in glav.  File: mjpeg-howto.info, Node: Unify videos, Next: Separate sound, Prev: Edit with glav, Up: Edit the video 6.2 Unify videos ================ `> lavtrans -o stream.qt -f q record_1.avi record_2.avi ... record_n.avi' `-o' specifies the outputfile name `-f q' specifies the output format, quicktime in this case This is usually not needed. Keep in your mind that there is a 2GB file-size-limit on 32Bit systems with an older glibc. Usually not a problem these days  File: mjpeg-howto.info, Node: Separate sound, Next: Separate images, Prev: Unify videos, Up: Edit the video 6.3 Separate sound ================== `> lavtrans -o sound.wav -f w stream.avi' Creates a wav file with the sound of the stream.avi Maybe needed if you want to remove noise or if you want to convert it to another sound format. Another way to split the sound is: `> lav2wav editlist.eli >sound.wav'  File: mjpeg-howto.info, Node: Separate images, Next: Creating movie transitions, Prev: Separate sound, Up: Edit the video 6.4 Separate images =================== `>mkdir jpg; lavtrans -o jpg/image%05d.jpg -f i stream.avi' First create the directory "jpg". Then lavtrans will create single JPG images in the jpg directory from the stream.avi file. The files will be named: image00000.jpg, image00001.jpg .... The jpg images created contain the whole picture. But if you have recorded at full size the images are stored interlaced. Usually the picture viewers show only the first field in the jpg file. If you want to have the image in a single file you can use that version `> lav2yuv -f 1 stream.avi | y4mtoppm -L >file.pnm' If you want to split the fields into single files use that: `> lav2yuv -f 5 ../stream.avi | y4mtoppm | pnmsplit - image%d.pnm' Maybe interesting if you need sample images and do not want to play around with grabbing a single image.  File: mjpeg-howto.info, Node: Creating movie transitions, Prev: Separate images, Up: Edit the video 6.5 Creating movie transitions ============================== Thanks to Philipp Zabel's lavpipe we can now make simple transitions between movies or combine multiple layers of movies. Philipp wrote this HOWTO on how to make transitions: Let's assume simple this scene: We have two input videos intro.avi and epilogue.mov and want to make intro.avi transition into epilogue.mov with a duration of one second (that is 25 frames for PAL or 30 frames for NTSC). Intro.avi and epiloque.mov have to be of the same format (the same frame rate and resolution). In this example they are both 352x288 PAL files. intro.avi contains 250 frames and epilogue.mov is 1000 frames long. Therefore our output file will contain: `' the first 225 frames of intro.avi `' a 25 frame transition containing the last 25 frames of intro.avi and the first 25 frames of epilogue.mov `' the last 975 frames of epilogue.mov We could get the last 25 frames of intro.avi by calling: `>lav2yuv -o 225 -f 25 intro.avi' *-o 255*, the offset, tells lav2yuv to begin with frame # 225 and * -f 25* makes it output 25 frames from there on. Another possibility (because negative offsets are counted from the end)is: `> lav2yuv -o -25 intro.avi' And the first 25 frames of epilogue.mov: `> lav2yuv -f 25 epilogue.mov' *-o* defaults to an offset of zero But we need to combine the two streams with lavpipe. So the call would be: `> lavpipe "lav2yuv -o 255 -f 25 intro.avi" "lav2yuv -f 25 epilogue.mov" ' The output of this is a raw yuv stream that can be fed into transist.flt. transist.flt needs to be informed about the duration of the transition and the opacity of the second stream at the beginning and at the end of the transition: `-o num' opacity of second input at the beginning [0-255] `-O num' opacity of second input at the end [0-255] `-d num' duration of transition in frames An opacity of 0 means that the second stream is fully transparent (only stream one visible), at 255 stream two is fully opaque. In our case the correct call (transition from stream 1 to stream 2) would be: `> transist.flt -o 0 -O 255 -d 25' The -s and -n parameters equate to the -o and -f parameters of lav2yuv and are only needed if anybody wants to render only a portion of the transition for whatever reason. Please note that this only affects the weighting calculations - none of the input is really skipped. If you use the skip parameter (-s 30, for example) you also need to skip the first 30 frames in lav2yuv (-o 30) in order to get the expected result. If you didn't understand this send an email to the authors or simply ignore -s and -n. The whole procedure will eventually be automated. Now we want to compress the yuv stream with yuv2lav: `> yuv2lav -f a -q 80 -o transition.avi' Reads the yuv stream from stdin and outputs an avi file (-f a) with compressed jpeg frames of quality 80. Now we have the whole command for creating a transition: `> ypipe "lav2yuv -o 255 -f 25 intro.avi" "lav2yuv -f 25 epilogue.mov" | transist.flt -o 0 -O 255 -d 25 | yuv2lav -f a -q 80 -o transition.avi' The resulting video can be written as a LAV Edit List (a plain text file) containing the following lines: LAV Edit List PAL 3 intro.avi transition.avi epilogue.mov 0 0 224 1 0 24 2 25 999 This file can be fed into glav or lavplay, or you can pipe it into mpeg2enc with lav2yuv or combine the whole stuff into one single mjpeg file with lavtrans or lav2yuv|yuv2lav.  File: mjpeg-howto.info, Node: Converting the stream to MPEG or DIVx videos, Next: Optimizing the stream, Prev: Edit the video, Up: Top 7 Converting the stream to MPEG or DIVx videos ********************************************** First there is some general description in the encoding process and afterwards there is a detailed description of some commonly used output formats. If you want a one command conversation to mpeg videos try lav2mpeg in the scripts directory The encoding with the lav2mpeg script looks like this for mpeg1 output: `>lav2mpeg -a 160 -b 2110 -d 320x240 -m mpeg1 -o output.mpg file.eli' * Will create a mpeg1 with videobitrate of 2110kBit/sec and audiobitrate of 160 kBit/sec * at a resolution of 320x240 Or for the generation of mpeg2 output: `lav2mpeg -o mpeg2 -O output.mpg file.eli' * Will create a mpeg2 with default bitrate in same resolution as the input resolution Better results can be accomplished, however, by trying various options and find out which ones work best for you. These are discussed below. The creation of MPEG-1 movies is explained with more examples and in greater detail because most of the things that can be used for MPEG-1 also work for the other output formats For the creation of of VCD/SVCD Stills sequences (-f 6 / -f 7 in mpeg2enc) you should see: `http://www.mir.com/DMG/' Still sequences are needed for the creation of menus in VCD/SVCD. The creation of menus is described in the doku of vcdimager. * Menu: * Creating sound:: * Converting video:: * Putting the streams together:: * Creating MPEG-1 Videos:: * Creating MPEG-2 Videos:: * Creating Video CDs (VCDs):: * Creating SVCD:: * Creating DVD's:: * Creating DIVX Videos::  File: mjpeg-howto.info, Node: Creating sound, Next: Converting video, Up: Converting the stream to MPEG or DIVx videos 7.1 Creating sound ================== MPEG-1 videos need MPEG-1-Layer2 (MP2) sound files. For MPEG-2 videos you can use MPEG-1-Layer2 and MPEG1-Layer3 (MP3). MP3 audio is not an offically valid audio format but many VCD players will recognize it. MP3 audio is not valid for DVDs. You should stick to MP2 because many of the MPEG-2 players (DVD Player for example, usually the Windows Versions have great problems with this too) are not able to play MPEG2-Video and MP3 sound. mp2enc is a MP2 Audio encoder. The toolame encoder is also able to produce an MP2 file. Toolame is much faster than mp2enc but toolame does not peform resampling (48000 to 44100 samples/second). Many hardware players will play SVCDs using 48000 rate audio. For MP3 creation I'm be sure you have an encoder. Example: `> lav2wav stream.avi | mp2enc -o sound.mp2' This creates a mpeg sound file out of the stream.avi with 224kBit/sec bitrate and a sample rate of 48kHz. If you audio file has 44.1kHz mp2enc resamples the audio to create a 48kHz output. If you want a 44.1kHz output sample rate you have to add -r 44100 to the mp2enc command Example `> cat sound.wav | mp2enc -v 2 -V -o sound.mp2' This creates a VCD (-V bitrate=224, stereo, sampling rate:44100) compatible output from the wav file. With -v 2 mp2enc is more verbose, while encoding you see the number of sec of audio already encoded. You can test the output with: `> plaympeg sound.mp2' *NOTE_* plaympeg is a MPEG-1 Player for Linux, you can use other players as wellr. For audio testing you can also use mpg123. For both audio and video playing there are the universal player like VLC mplayer and others.  File: mjpeg-howto.info, Node: Converting video, Next: Putting the streams together, Prev: Creating sound, Up: Converting the stream to MPEG or DIVx videos 7.2 Converting video ==================== Creating MPEG-1 and MPEG-2 videos. Normally the first video you create is not the best. For optimal quality/size you need to play with the bitrate, search radius, noise filter .... The options of mpeg2enc are described in the manpage of mpeg2enc. Example: `lav2yuv stream.avi stream1.avi | mpeg2enc -o video.m1v' This creates an video file with the default constant bitrate of 1152kBit/sec. This is the bitrate you need if you want to create VCDs. You can specify more files and also use the placeholder %nd. Where *n* describes the number. By default mpeg2enc assumes that you want to encode a not interlaced video to Mpeg-1. If you want to encode a full size video with interlacing that command above will fail. Example: `> lav2yuv streami%02d.avi | mpeg2enc -b 1500 -r 16 -o video.m1v' mpeg2enc creates a video with a bitrate of 1500kBit/s uses an search radius of 16. That means when trying to find similar 16*16 macroblocks of pixels between frames the encoder looks up to 16 pixels away from the current position of each block. It looks twice as far when comparing frames 1 frame apart and so on. Reasonable values are 16 or 24. The default is 16 so adding the option here is useless. Lower values (0, 8), improve the encoding speed but you get lower quality (more visible artifacts) while higher values (24, 32) improve the quality at the cost of the speed. With the file description of stream%02d.avi all files are processed that match this pattern with 00, 01.... * Menu: * Scaling:: * High quality scaling y4mscaler::  File: mjpeg-howto.info, Node: Scaling, Next: High quality scaling y4mscaler, Up: Converting video 7.2.1 Scaling ------------- Using yuvscaler one can now also scale the video before encoding it. This can be useful for users with a DC10 or DC10+ cards which captures at -d 1 768x576 or -d 2 384x288 (PAL/SECAM) or -d 1 640x480 (NTSC). You get a full description of all commands by reading the manpage or running: `>yuvscaler -h' Example: `> lav2yuv stream.avi | yuvscaler -O VCD | mpeg2enc -o video.m1v' This will scale the stream to VCD size which for PAL/SECAM is 352x288 and for NTSC is 352x240. The scaled yuvstream is encoded to MPEG-1. It can also do SVCD scaling to 480x480 (NTSC) or 480x576 (PAL/SECAM): `> lav2yuv stream.avi | yuvscaler -O SVCD -M BICUBIC | mpeg2enc -o video.m1v' The mode keyword (-M) forces yuvscaler to use the higher quality bicubic algorithms for downscaling and not the default resample algorithms. Upscaling is always done using the bicubic algorithm. Example: `> lav2yuv stream.avi | yuvscaler -I USE_450x340+20+30 -O SIZE_320x200 | mpeg2enc -o video.m1v ' Here we only use a part of the input and specify a nonstandard output resolution. *NOTE_* yuvscaler can set a active area, and set everything else to black using: -I ACTIVE_WidthxHeight+WidthOffset+HeightOffset  File: mjpeg-howto.info, Node: High quality scaling y4mscaler, Prev: Scaling, Up: Converting video 7.2.2 High quality scaling: y4mscaler ------------------------------------- y4mscaler has been arround for quite some time. But it was for a quite long time a extra tool you needed to compile. There is a comprehensive manpage explaining all the details, there also a lot fo helpful information on the website: `Digital Media Group: Video Library http://www.mir.com/DMG/' One unique feature is that is it able to change the subsampling, and Choma Modes. And you can choose the scaler kernels, depending on the source that can help a lot. Example: `> cat raw.yuv | y4mscaler -O infer=CLIP -O preset=DVD -O sar=PAL_Wide | mpeg2enc video.m1v ' In this example y4mscaler will take the input stream and scale it to the coresponding PAL size. The sar option tell to scale is to a wide format (16:9). The `infer=clip' option will tells y4mscaler that it can clip the top and bottom bars away to scale it to the resulting size. Example: `> mpeg2dec -o pgmpipe deluxe.m2v | pgmtoy4m -x 420jpeg -r 25:1 -i t | y4mscaler -I sar=64:36 -I active=344x476+100+48 -O preset=DVD | mpeg2enc -f 8 video.m1v ' This is a more the job for y4mscaler. We have a weird PAL MPEG source format with 544x576 pixels in a wide screen 16:9 format, that makes black bars all around the original 4:3 image. This command scales the image up to a original 4:3 size, and takes just the interesting center. The SAR is the sample aspect ratio get lost somewhere so we specify it in the beginning. So it is specified again, than you tell y4mscaller the active size of the picture it shall use to scale up. The active keyword is treated different in y4mscaler and yuvscaler. The DVD is a preset for the output format you want. From the stream parameters y4mscaler knows that it is a PAL stream and the output parameters. If you wanted a 16:9 output you would have to use the keyword: DVD_WIDE. Testing is done by: `> mplayer video.m1v' *NOTE_*These are only examples. There are more options you can use. You can use most of them together to create high quality videos with the lowest possible bitrate. *NOTE2:*The higher you set the search radius the longer the conversion will take. In general the more options used the longer encoding takes. *NOTE3:*MPEG-1 was not designed to be a VBR (variable bitrate stream) !! So if you encode with -q 15 mpeg2enc sets the maximal bitrate -b to 1152. If you want a VBR MPEG-1 you have to set -b very high (2500). *NOTE4:*Maybe you should give better names than video.mpg. A good idea is to use the options as part of the filename (for example: `video_b1500_r16_41_21.m1v'). Another possibility is to call all the layer 2 audio files ".mp2" all the MPEG-1 video files ".m1v" and all MPEG-2 video files ".m2v" Easy to see what's happening then. Reserve .mpg for multiplexed MPEG-1/2 streams.  File: mjpeg-howto.info, Node: Putting the streams together, Next: Creating MPEG-1 Videos, Prev: Converting video, Up: Converting the stream to MPEG or DIVx videos 7.3 Putting the streams together ================================ Example: `> mplex sound.mp2 video.m1v -o my_video.m1v' Puts the sound.mp2 and the video.m1v stream together to my_video.mpg Now you can use your preferred MPEG player and watch it. All players (gtv for example) based on the SMPEG library work well for MPEG-1. Other players (which can play MPEG-2 as well as MPEG-1 movies) are: xmovie, xine, and MPlayer VLC, to name some. *NOTE_* If you have specified the *-S* option for mpeg2enc mplex will automatically split the files if there is in the output filename a %d (looks like: -o test%d.mpg) The files generated this way are separate stand-alone MPEG steams! *NOTE2:* xine might have a problem with seeking through videos. mplayer has a problem with the "seek backward/forward" with variable bitrate streams because it goes forward in the file the amount of data for a constant bitrate stream. That amount might be significantly more than 10 seconds or one minute (those are the amount mplayer seeks for each press of the arrow keys). So don't wonder if it seeks much more time forward or backward than you expect. *Variable bit-rate multiplexing:* Remember to tell mplex you're encoding VBR (-V option) as well as mpeg2enc (see the example scripts). It *could* auto-detect but it is not working yet. You should tell mplex a video buffer size at least as large as the one you specified to "mpeg2enc" Sensible numbers for MPEG-1 might be a ceiling bit-rate of 2800Kbps, a quality ceiling (quantization floor) of 6 and a buffer size of 400K. Example: `> mplex -V -r 1740 audio.mp2 video_vbr.m1v -o vbr_stream.mpg' Here we multiplex a variable bitrate stream. mplex is a single pass multiplexer so it can't detect the maximal bitrate and we have to specify it. The data rate for the output stream is: audio bitrate + peak videobitrate + 1-2% for mplex information. If audio (-b 224) is 224kBit and the video is 1500kBit (encoded with -b 1500 -q 9) then we have 1724 * 1.01 or about 1740kBit. Example: `> plaympeg my_video.mpg' or `> mplayer my_video.mpg'  File: mjpeg-howto.info, Node: Creating MPEG-1 Videos, Next: Creating MPEG-2 Videos, Prev: Putting the streams together, Up: Converting the stream to MPEG or DIVx videos 7.4 Creating MPEG-1 Videos ========================== For MPEG-1 videos you can use MP2 audio and MPEG-1 video. A subset of MPEG-1 movies are VCD's. You can use VBR (Variable BitRate) for the Video (although VCDs are almost always use CBR video) but the Audio has to be CBR (Constant BitRate). MPEG-1 is recommended for picture sizes up to 352x288 for PAL and 352x240 for NTSC for larger sizes MPEG-2 is the better choice. There is no exact resolution where MPEG-1 is better than MPEG-2. Just to make soure, MPEG-1 can't handle interlaced sources. If you video is interlaced you need MPEG-2 to get it proper encoded. * Menu: * MPEG-1 Audio creation Example:: * MPEG-1 Video creation example:: * MPEG-1 Multiplexing Example::  File: mjpeg-howto.info, Node: MPEG-1 Audio creation Example, Next: MPEG-1 Video creation example, Up: Creating MPEG-1 Videos 7.4.1 MPEG-1 Audio creation Example ----------------------------------- `> lav2wav editlist.eli | mp2enc -r 44100 -o sound.mp2' You can save some bits by telling mp2enc to use a lower bitrate (-b option) like 160 or 192 kBit/s. The -r 44100 option forces mp2enc to generate a 44.1kHz audio file. `> lav2wav editlist.eli | mp2enc -b 128 -m -o sound.mp2' This creates a mono output with an bitrate of 128kBit/sec bitrate. The input this time is the editlistfile (can have any name) created with glav so all changes you made in glav are direct processed and handed over to mp2enc. You do NOT have to create an edited stream with lavtrans to get it converted properly.  File: mjpeg-howto.info, Node: MPEG-1 Video creation example, Next: MPEG-1 Multiplexing Example, Prev: MPEG-1 Audio creation Example, Up: Creating MPEG-1 Videos 7.4.2 MPEG-1 Video creation example ----------------------------------- `> lav2yuv editlist.eli | mpeg2enc -b 2000 -r 24 -q 6 -o video.m1v' mpeg2enc creates an video with an bitrate of 2000kBit/s (or 2048000Bit/s) but the -q flag activates the variable bitrate and a quality factor of 6. It uses a search radius of 24. *Explanation:*when mpeg2enc is invoked without the 'q' flag it creates "constantbit-rate" MPEG streams. Where (loosely speaking) the strength of compression (and hence picture quality) is adjusted to ensure that on average each frame of video has exactly the specified number of bits. Such constant bit-rate streams are needed for broadcasting and for low-cost hardware like DVD and VCD players which use slow fixed-speed player hardware. Obviously this is fairly inefficient as it means inactive scenes use up bits that could better be "spent" on rapidly changing scenes. Setting the 'q' flag tells mpeg2enc to generate variable bit-rate streams. For such streams the bit-rate specified is simply the maximum permissible. The 'q' parameter specifies the minimum degree of compression to be applied by specifying how exactly picture information is recorded. Typically 'q' would be set so that quiet scenes would use less than the specified maximum (around 6 or 8) but fast moving scenes would still be bit-rate limited. For archival purposes setting a maximum bit-rate high enough never to be reached (e.g. 10Mbps) and a q of 2 or 3 are reasonable choices. Example: `> lav2yuv stream.avi | yuvscaler -I ACTIVE_352x240+0+24 | mpeg2enc -b 1152 -r 16 -4 1 -2 1 -o video.m1v' Usually there is at the top and at the bottom a nearly black border and a lot of bandwidth is used for something you do not like. The yuvscaler -I ACTIVE option sets everything that is not in the described area to black but the imagesize (352x288) is not changed. So you have a real black border the encoder only uses a few bits for encoding them. You are still compatible with the VCD's format in this example. To determine the active window extract one frame to the jpeg format: `> lavtrans -f i -i 100 -o frame.jpg test.avi' Than use your favorite graphic display program to determine the active size. The -4 1 and -2 1 options improves the quality about 10% but conversion is slower. At the size of 352x288 (1/2 PAL size created when using the -d 2 option when recording) the needed bitrate is/should be between 1000 - 1500kBit/s. For NTSC it should be about the same, because the image is smaller but there are more frames per second than in PAL. Anyways, the major factor is quality of the original and the degree of filtering. Poor quality unfiltered material typically needs a higher rate to avoid visible artifacts. If you want to reduce bit-rate without annoying artifacts when compressing broadcast material you should try one (or more) of the noise filters. Example: `> lav2yuv stream.avi | mpeg2enc -b 1500 -n s -g 6 -G 20 -P -o video.m1v' Here the stream.avi will be encoded with: `-b 1500' a Bitrate of 1500kBit/sec `-n s' the input Video norm is forced to SECAM `-P' This ensures that 2 B frames appear between adjacent I/P frames. Several common MPEG-1 decoders can't handle streams that do not have 2 B-frames between I/P frames `-g 6 -G 20' the encoder can dynamically change the group-of-pictures size to reflect scene changes. This is done by setting a maximum GOP (-G flag) size larger than the minimum (-g flag). For VCDs sensible values might be a minimum of 9 and a maximum of 15. For SVCD 9 and 15 would be good values. If you only want to play it back on SW player you can use other min-max values. Example: `> lav2yuv stream*.avi | mpeg2enc -b 1500 -r 16 -4 1 -2 1 -S 630 -B 260 -o video_n1_1500_r16_41_21_S630_B240.m1v' lav2yuv processes all the stream files. Then mpeg2enc is given some options that make the encoded stream look nicer. Using *-S 630* means that mpeg2enc marks the stream so that mplex generates a new stream every 630MB. One important thing is the use of the *-B* option which specifies the non-video (audio and mplex information) bitrate. The *-B* value of 260 should be fine for audio with 224kBit and mplex information. For further information take a look at the encoding scripts in the scripts directory.  File: mjpeg-howto.info, Node: MPEG-1 Multiplexing Example, Prev: MPEG-1 Video creation example, Up: Creating MPEG-1 Videos 7.4.3 MPEG-1 Multiplexing Example --------------------------------- Example: ` >mplex sound.mp2 video.m1v -o my_video.mpg' Puts the sound.mp2 and the video.m1v stream together to my_video.mpg. It only works that easy if you have CBR (the -q option was not used with mpeg2enc). Example: `mplex -V -r 1740 audio.mp2 video_vbr.m1v -o vbr_stream.mpg' Here we multiplex a variable bitrate stream. mplex is now a single pass multiplexer so it can't detect the maximal bitrate and we have to specify it. The data rate for the output stream is: *audio bitrate + peak videobitrate + 1-2% for mplex information*. If audio (-b 224) has 224kBit, video has 1500kBit (was encoded with -b 1500 -q 9) then we have 1724 * 1.01 or about 1740kBit.  File: mjpeg-howto.info, Node: Creating MPEG-2 Videos, Next: Creating Video CDs (VCDs), Prev: Creating MPEG-1 Videos, Up: Converting the stream to MPEG or DIVx videos 7.5 Creating MPEG-2 Videos ========================== MPEG-2 is recommended for sources with a greater picture than 352x240 for NTSC and 352x288 for PAL. MPEG-2 can also handle interlaced sources like recording from TV at full resolution. MPEG-2 allows the usage of mpeg layer 3 (mp3) sound. So you can use your favorite mp3encoder for the creation of the sound. However, MP3 audio is not valid for DVDs. It is best to use MP2 (Layer 2) audio. The audio can also be a VBR stream. MPEG-2 is usually a VBR stream. MPEG-2 creation with optimization requires a lot of CPU power. A film with the double resolution is NOT 4 times larger than an MPEG-1 stream. Depending on your quality settings it will be about 1.5 up to 3 times larger than the MPEG-1 stream at its lower resolution. * Menu: * MPEG-2 audio creation example:: * MPEG-2 Video creation example:: * MPEG-2 Multiplexing example::  File: mjpeg-howto.info, Node: MPEG-2 audio creation example, Next: MPEG-2 Video creation example, Up: Creating MPEG-2 Videos 7.5.1 MPEG-2 audio creation example ----------------------------------- `> lav2wav editlist.eli | mp2enc -o sound.mp2' You can save some bits by telling mp2enc to use a lower bitrate (-b option) like 160 or 192 kBit/s. You might want to add -r 44100 so that mpeg2enc generates 44.1kHz sampling rate audio. I hope I don't need to explain the usage of an MP3 Encoder. But you should not use all the fancy options that are available.  File: mjpeg-howto.info, Node: MPEG-2 Video creation example, Next: MPEG-2 Multiplexing example, Prev: MPEG-2 audio creation example, Up: Creating MPEG-2 Videos 7.5.2 MPEG-2 Video creation example ----------------------------------- `> lav2yuv editlist.eli | mpeg2enc -f 3 -b 3000 -q 9 -o video.m2v' A very simple example for MPEG-2 Video. The most important option is the -f 3. That tells mpeg2enc that it should create a MPEG-2 stream. Because it is a generic MPEG-2 you have to use the -b bitrate options. And should use the -q option because you usually want a space saving VBR stream. When using VBR streams the -b option tells mpeg2enc the maximum bitrate that can be used. The -q option tell mpeg2enc what quality the streams should have. The bitrate has an upper bound of the value specified by -b. `> lav2yuv editlist.eli | mpeg2enc -f 3 -4 1 -2 1 -q7 -b 4500 -V 300 -P -g 6 -G 18 -I 1 -o video.m2v' This will generate a higher quality MPEG-2 stream because the -4 1 and -2 1 options were used. With -b 4500 -q 7 you tell mpeg2enc the maximal bitrate and the quality factor. -V is the video buffer size used for decoding the stream. For SW playback it can be much higher than the default. Dynamic GOP is set with -g and -G. A larger GOP size can help reduce the bit-rate required for a given quality but very large sizes can introduce artifacts due to DCT/iDCT accumulated rounding errors. The -P option also ensures that 2 B frames appear between adjacent I/P frames. The -I 1 option tells mpeg2enc that the source is a interlaced material like videos. There is (time consuming) interlaced motion compensation logic present in mpeg2enc. Mpeg2enc will use that logic if the size of the frames you encode is larger than the VCD size for your TV Norm. If you deinterlacing the movie with yuvdeinterlace you should tell mpeg2enc that it does not need to do motion estimation for interlaced material. You have to use the -I 0 option of mpeg2enc to say that the frames are already deinterlaced. This will save a lot of time when encoding. If you don't use -I 0 it will not cause problems, the encoding will just take longer. You can also use scaling an options that optimize (denoise) the images to get smaller streams. These options are explained in detail in the following sections. * Menu: * Which values should be used for VBR Encoding?:: * Encoding destination TV (interlaced) or Monitor (progressive)::  File: mjpeg-howto.info, Node: Which values should be used for VBR Encoding?, Next: Encoding destination TV (interlaced) or Monitor (progressive), Up: MPEG-2 Video creation example 7.5.2.1 Which values should be used for VBR Encoding? ..................................................... The -q option controls the minimum quantization of the output stream. Quantization controls the precision with which image information is encoded. The lower the value the better the image quality. Values below 4 are extremes and should only be used if you know what you are doing Usually you have to set up a maximum bitrate with the -b option. The tricky task is to set a value for the -q option and the -b option that produces a nice movie without using too much bandwidth and does not introduce too many artifacts. A quality factor should be chosen that way that the mplex output of Peak bit-rate and average bit-rate differ by about 20-25%. If the difference is very small (less than < 10%) it is likely that you will begin to see artifacts in high motion scenes. The most common cause of the average rate being too close (or equal) to the maximum rate is wrong value for the maximal bitrate or a quality factor that is too high. A combination that will produce more artifacts than you can count is a SVCD with a maximal video bitrate of 2500kBit and a quality factor of 1 or 2. For SVCD with a video limit of 2500kBit a quality factor of 7-11 fits quite good (8 is the default). If you use filter programs or have a very good source like digital TV, DVD like material or rendered pictures you can use a quality factor of 6 when creating SVCDs. If your SVCD/DVD player supports non-standard bitrates you can increase the bitrate above the standard maximum of 2788 kBit/sec (video plus audio). When using a higher bitrate and quality factor action scenes will look much better but of course the playing time of the disc will be less. The same (7-11) quality factor for a full size picture and a top bitrate of 3500 to 4000 kBit will produce few artifacts. For SVCD/DVD you can expect a result like the one described if the maximal bitrate is not set too low: q <= 6 real sharp pictures, and good quality q <= 8 good quality q >= 10 average quality q >= 11 not that good q >= 13 here even still sequences might look blocky  File: mjpeg-howto.info, Node: Encoding destination TV (interlaced) or Monitor (progressive), Prev: Which values should be used for VBR Encoding?, Up: MPEG-2 Video creation example 7.5.2.2 Encoding destination TV (interlaced) or Monitor (progressive) ..................................................................... MPEG-2 supports interlaced data in addition to the progressive format. A MPEG-2 movie can be interlaced or progressive. It depends on the source (film or broadcast) and on the viewing device. If you encode a film both fields should be the same. Deinterlace the stream with yuvdeinterlace, or if you have a high quality source, and don't need to use the denoiser with yuvcorrect -T NOT_INTERLACED. Also set the mpeg2enc interlace-mode (-I) option to 0. This means that there is no interlacing. We do not really need deinterlacing here because there is no motion between the fields of the frame. We only need to unite the two fields into a single progressive frame. This movie should play back an any device (TV or Monitor) without problems. If you have an interlaced source (broadcast) you can encode it as interlaced stream. Or deinterlace the stream and encode it as progressive stream. If you deinterlace it with yuvdeinterlace you will lose details. But if you plan to play the recorded stream on your DVD player and your TV it would not be wise to perform deinterlacing. If you only want to play it back on the Monitor (progressive display) the picture looks better when playing it back if it is deinterlaced. If the player you use can do deinterlacing it does not matter if your encoded video has interlaced frames or progressive frames. If you plan to deinterlace the stream you can only do this with yuvdeinterlace and set the mpeg2enc -I 0. If you do not want to deinterlace the stream you do not need to set any special option (do not use yuvdeinterlace and mpeg2enc -I 0) If you like to pause the stream and look on the still you should deinterlace. Because then the image is flicker free when pausing. If you have a film (progressive) with parts from a broadcast (interlaced) mixed together (like in a documentary where some parts from a speaker are recorded interlaced and other parts are filmed) you have to choose between good film sequences with average still images or average looking film sequences with good still images. For good film with average stills do not deinterlace. For average film sequences with good stills then deinterlace (using yuvdeinterlace and mpeg2enc -I 0).  File: mjpeg-howto.info, Node: MPEG-2 Multiplexing example, Prev: MPEG-2 Video creation example, Up: Creating MPEG-2 Videos 7.5.3 MPEG-2 Multiplexing example --------------------------------- `> mplex -f 3 -b 300 -r 4750 -V audio.mp3 video.m2v -o final.mpg' Now both streams (a mp3 audio and a mpeg2 video) are multiplex into a single stream (final.mpg). You have to use the *-f 3* option to tell mplex the output format. You also have to add the *-b* decoder buffers size option with the same value used when encoding the video. -*r* is that rate of video + audio +1-2% of mplex information. The *-V*option tells that your source for mplexing is a VBR stream. If you don't use this option mplex creates something like a CBR stream with the bitrate you have told it with the *-r* option. These streams are usually get BIG.  File: mjpeg-howto.info, Node: Creating Video CDs (VCDs), Next: Creating SVCD, Prev: Creating MPEG-2 Videos, Up: Converting the stream to MPEG or DIVx videos 7.6 Creating Video CDs (VCDs) ============================= VCD is a constrained version of MPEG-1 video. VCD format was defined by Philips. The goal was to use a single speed CD-drive and other cheap hardware (not flexible) to have a cheap HW-Player. Because of that there are limitations for video and audio used to make a VCD. The bitrate for video is 1152kBit and 224kBit/sec MP2 audio. You are not allowed to use the -q option, dynamic GOP sizes and the video buffer is limited to 46kB. The image size is limited to 352x240 for NTSC, an to 352x288 for PAL. If you have no VCD (only) player and you plan to use your DVD player then it is quite possible that the DVD player will be flexible enough to allow higher bitrates, dynamic GOP sizes, larger video buffer and so on * Menu: * VCD Audio creation Example:: * VCD Video creation Example:: * VCD Multiplexing Example:: * Creating the CD:: * Notes:: * Storing MPEGs::  File: mjpeg-howto.info, Node: VCD Audio creation Example, Next: VCD Video creation Example, Up: Creating Video CDs (VCDs) 7.6.1 VCD Audio creation Example -------------------------------- `> lav2wav stream.avi | mp2enc -V -o sound.mp2' *-V* force VCD 2.0 compatible output. There the audio samplerate is fixed to 44.1kHz. And you can choose the audio bitrate for mono audio to be 64, 96 or 192kBit/sec. If you have stereo audio you can choose 128, 192, 224 or 384kBit/sec. For hardware players, you should stick to 44.1 224kBps Stereo layer 2 Audio.  File: mjpeg-howto.info, Node: VCD Video creation Example, Next: VCD Multiplexing Example, Prev: VCD Audio creation Example, Up: Creating Video CDs (VCDs) 7.6.2 VCD Video creation Example -------------------------------- `> lav2yuv stream.avi | yuvscaler -O VCD | mpeg2enc -f 1 -r 16 -o video.mpg' For VCD compatible output the -f 1 sets all options in mpeg2enc as needed. It seems that many VCD players (Avex for example) are not able to play MPEG streams that are encoded with a search radius greater than 16 so do not use the -r option to override the default of 16. `> lav2yuv streams.eli | mpeg2enc -f 1 -4 1 -2 1 -S 630 -B 260 -P -o video.m1v' Using *'-S 630'* means that mpeg2enc marks the stream so that mplex generates a new stream every 630MB. One important thing is the use of the *-B* option which specifies the non-video (audio and mplex information) bitrate. The -B value of 260 should be fine for audio with 224kBit and mplex information. For further information take a look at the encoding scripts in the scripts directory. The multiplexed streams should easily fit on a 650MB CD. The default value (-B) is 700MB for the video. mpeg2enc marks automatically every stream at that size if the -B option is not used to set a different value. If you have a CD where you can write more data (perhaps as much as 800MB) you have to set the -S option or otherwise mpeg2enc will mark the stream at 700 MB, and mplex will split the stream there. Which is almost certainly not what you want.  File: mjpeg-howto.info, Node: VCD Multiplexing Example, Next: Creating the CD, Prev: VCD Video creation Example, Up: Creating Video CDs (VCDs) 7.6.3 VCD Multiplexing Example ------------------------------ `> mplex -f 1 sound.mp2 video.mpg -o vcd_out.mpg' The -f 1 option turns on a lot of weird stuff that otherwise has no place in a respectable multiplexer!  File: mjpeg-howto.info, Node: Creating the CD, Next: Notes, Prev: VCD Multiplexing Example, Up: Creating Video CDs (VCDs) 7.6.4 Creating the CD --------------------- The multiplexed streams have to be converted to an VCD compatible. This is done by vcdimager `http://www.vcdimager.org/' `> vcdimager testvideo.mpg' Creates a *videocd.bin*, the data file, and a *videocd.cue* which is used as control file for cdrdao. You use cdrdao to burn the image. Cdrdao is yet another fine Sourceforge project which is found at: `http://cdrdao.sourceforge.net/'  File: mjpeg-howto.info, Node: Notes, Next: Storing MPEGs, Prev: Creating the CD, Up: Creating Video CDs (VCDs) 7.6.5 Notes ----------- For MPEG-1 encoding a typical (45 minute running time) show or 90 odd minute movie from an analog broadcast a constant bit-rate of around 1800 kBit/sec should be ideal. The resulting files are around 700M for 45 minutes which fits nicely as a raw XA MODE2 data track on a CD-R. For pure digital sources (DTV or DVD streams and similar) VCD 1152 works fine. *Note_* If you encode VBR MPEG-1 (-q) remember the Hardware was probably not designed to do the playback because it is not in the specifications. If it works be very happy. I've noticed that it helps when you have an MPEG-1 stream to tell vcdimager that it is an SVCD. vcdimager complains (but only with a warning and not a fatal error) but you should be able to burn it. This could convince the player to use different routines in its firmware and play it back correct but there is no guarantee of that.  File: mjpeg-howto.info, Node: Storing MPEGs, Prev: Notes, Up: Creating Video CDs (VCDs) 7.6.6 Storing MPEGs ------------------- If you record the data as XA mode 2 tracks you can fit appreciably more on a CD (at the expense of error correction/detection). You can use vcdimager to do this and vcdxrip (part of the vcdimager package) to extract ("rip") the resulting files. For better Quality there are SVCD and XVCD and DVD. Currently SVCD is fully supported with a pre-set format in mplex and tools to create disks. MPEG streams that can be played by DVD player hardware and software can readily produced using mpeg2enc/mplex If your player doesn't support SVCD you may well find it can handle VCD streams that have much higher than standard bit-rates. Often as much as 2500kBit/sec is possible. The several brands of DVD players can also play wildly out of spec SVCD and VCD discs. With higher bit-rates and good quality source material it is worth trying mpeg2enc's -h flag which produce a stream that is as sharp as the limits of the VCD standard permits. However, if your player supports it and you have the patience for the longer encoding times SVCD is a much better alternative. Using a more efficient MPEG format SVCD more than doubles VCD's resolution while typically producing files that are less than twice as big.  File: mjpeg-howto.info, Node: Creating SVCD, Next: Creating DVD's, Prev: Creating Video CDs (VCDs), Up: Converting the stream to MPEG or DIVx videos 7.7 Creating SVCD ================= Super Video CD (SVCD) is an enhancement to Video CD that was developed by a Chinese government-backed committee of manufacturers and researchers. The final SVCD spec was announced in September 1998. A good explanation of the SVCD format from Philips can be found here: `http://lipas.uwasa.fi/~f76998/video/svcd/overview/'. Record at full TV resolution (means: -d 1 for PAL this is 720x576) The resolution is for NTSC is 480x480 of PAL 480x576, so you know why you should record at full size. * Menu: * SVCD Audio creation Example:: * SVCD Video creation example:: * SVCD multiplexing example:: * SVCD creating the CD::  File: mjpeg-howto.info, Node: SVCD Audio creation Example, Next: SVCD Video creation example, Up: Creating SVCD 7.7.1 SVCD Audio creation Example --------------------------------- `> lav2wav stream.avi | mp2enc -V -e -o sound.mp2' The SVCD specifications permit a much wider choice of audio rates, it is not necessary to use 224 kBit/sec. Any audio rate between 32 and 384 kBit/sec is permitted. The audio may be VBR (Variable Bit Rate). The -e enables the CRC error protection for the audio. The CRC has to be enabled to be SVCD standard compliant but it seems that most players don't pay attention to the CRC information. The CRC information need 2 bytes per Audio frame The approximate frame length formula for MPEG-1 layer-II is: [frame length in bytes) = 144 * (byte rate) / (sample rate] If you have the typical VCD settings the CRC data needs about 0,27% of the whole data. In the worst case where you have a MONO 32k Bitrate stream the CRC data needs 1,92%.  File: mjpeg-howto.info, Node: SVCD Video creation example, Next: SVCD multiplexing example, Prev: SVCD Audio creation Example, Up: Creating SVCD 7.7.2 SVCD Video creation example --------------------------------- `> lav2yuv stream.avi | yuvscaler -O SVCD | mpeg2enc -f 4 -q 7 -I 1 -V 200 -o video.m2v' `-f 4' sets the options for mpeg2enc to SVCD `-q 7' tell mpeg2enc to generate a variable bitrate stream `-I 1' tell mpeg2enc to assume that the original signal is field interlaced video where the odd rows of pixels are sampled a half frame interval after the even ones in each frame. The -I 0 (progressive output (no field pictures)) option will also work for PAL You can use lower bitrates but the SVCD standard limits *total bit-rate (audio and video) to 2788800 Bit/sec*. So with 224Kbps audio and overhead 2550 may already be marginally too tight. Since the SVCD format permits any audio rate between 32 and 384 kBit/sec you can save a few bits/sec by using 192k audio (or for non-musical material 160k). SVCD supports variable bitrate (VBR), because MPEG-2 is usually VBR, but with the top video bitrate limit of 2500kBit/sec. With the -f 4 flag the encoder also sets dynamic GOP with a low limit of -g 6 and a high limit of -G 18. This saves a few bits/sec and improves the picture quality during scene changes. When encoding with -f 4 mpeg2enc ignores the video bitrate (-b) and search radius (-r) options. If you use -f 5 you have to specify the bitrate and other options to mpeg2enc. Another possibility for movies in PAL (European style 25 frames/50 fields per sec) video is: `> lav2yuv stream.avi | yuvscaler -O SVCD | mpeg2enc -f 4 -I 0 -V 300 -o video.m2v' Movies are shot on film at 24 frames/sec. For PAL broadcast the film is simply shown slightly "too fast" at 25 frame/sec (much to the pain of people with an absolute pitch sense of pitch). The -I 0 flag turns off the tedious calculations needed to compensate for field interlacing giving much faster encoding. Unfortunately, movies broadcast in NTSC (US style 30 frames/60 fields sec) video this will produce very poor compression. The "pulldown" sampling used to produce 60 fields a second from a 24 frame a second movie means half the frames in an NTSC *are* field interlaced. Don't forget the -S and -B options mentioned above. You want the stream to fit on a CD don't you ?  File: mjpeg-howto.info, Node: SVCD multiplexing example, Next: SVCD creating the CD, Prev: SVCD Video creation example, Up: Creating SVCD 7.7.3 SVCD multiplexing example ------------------------------- `> mplex -f 4 -b 300 -r 2750 sound.mp2 video.m2v -o svcd_out.mpg' `-f 4' tells mplex to mplex a SVCD `-r 2750' is the calculated Audio + Video Bitrate + 1-2% multiplex information `-b 300' is the buffer available on the playback device (the same value as used for the video encoding (mpeg2enc's -V option).  File: mjpeg-howto.info, Node: SVCD creating the CD, Prev: SVCD multiplexing example, Up: Creating SVCD 7.7.4 SVCD creating the CD -------------------------- Example: `> vcdimager -t svcd testvideo.mpg' Creates a *videocd.bin*, the data file, and a *videocd.cue* which is used as control file for cdrdao. Use cdrdao to burn the image as mentioned earlier. *NOTE_*If you want to build "custom" VCD/SVCD you will need to use the mplex -f 2 and -f 5 switches. *NOTE_*The VCD and SVCD stuff may work on your HW player or not. There are many reports that it works quite well. Don't be worried if it does not work. Nor am I responsible for unusable CDs. ("coasters")  File: mjpeg-howto.info, Node: Creating DVD's, Next: Creating DIVX Videos, Prev: Creating SVCD, Up: Converting the stream to MPEG or DIVx videos 7.8 Creating DVD's ================== This statement was correct a few years ago: Everything in this section is new. The limitations I mention here might not exist in the current version. Currently (Dec. 2007) DVD creating is working. You need obviously a DVD writer. I did own a Ricoh DVD+RW that works, and I know of a DVD-RAM writer that is able to to burn DVD-R. That disks also work with a DVD-Player. Now most DVD writers ar able to burn both media + and -, so that should not be a problem any more. Which programs you use for burning depends on the DVD writer drive. For the creation and writing of the VOB, IFO and BUP files we use dvdauthor. Aviable from Sourceforge (you might have guessed it) `http://dvdauthor.sourceforge.net'. * Menu: * DVD Audio creation example:: * DVD Video creation example:: * DVD multiplexing example:: * DVD creation example::  File: mjpeg-howto.info, Node: DVD Audio creation example, Next: DVD Video creation example, Up: Creating DVD's 7.8.1 DVD Audio creation example -------------------------------- `> lav2wav stream.eli | mp2enc -o sound.mp2' The sample rate has to be 48kHz. The mp2enc does create by default a sample rate of 48kHz. If it is not a 48kHz mp2enc will resample the audio to get the sample rate. If the audio is recorded at 48kHz then no resampling is needed and toolame can be used for the encoding (it is faster than mp2enc).  File: mjpeg-howto.info, Node: DVD Video creation example, Next: DVD multiplexing example, Prev: DVD Audio creation example, Up: Creating DVD's 7.8.2 DVD Video creation example -------------------------------- `> lav2yuv stream.eli | mpeg2enc -f 8 -o video.m2v' `-f 8' This sets the options correctly for a MPEG-2 video that is compliant with the DVD standard. The maximum bitrate is set to 7500kBps and the video buffer size is set to 230KB. The default quality factor is set to 8. mpeg2enc sets currenty no automatic sequence length as it does for VCD/SVCD. The other options to get a low bitrate and high quality stream can also be used to override the default settings mentioned above. You can also use yuvdenoise to increase the picture quality if the input data is noisy (from a VHS tape for example). A typical command will look like this: `lav2yuv moby.eli | yuvdenoise | mpeg2enc -f 8 -q 7 -4 1 -2 1 -P -I 0 -N -o video_DVD.m2v'  File: mjpeg-howto.info, Node: DVD multiplexing example, Next: DVD creation example, Prev: DVD Video creation example, Up: Creating DVD's 7.8.3 DVD multiplexing example ------------------------------ `> mplex -f 8 sound.mp2 video.m2v -o my_dvdlikestream.mpg' `-f 8' Here again we specify that we want to have DVD like MPEG stream. mplex cannot do all the fancy things allowed for a DVD, but it is close enough that the HW-DVD players accept it. `-o' there we specify the output filename.  File: mjpeg-howto.info, Node: DVD creation example, Prev: DVD multiplexing example, Up: Creating DVD's 7.8.4 DVD creation example -------------------------- This topic will be covered by the documentation of the dvdauthor program. For questions please see `dvdauthor' In general it will work like this: `> dvdauthor -o output/ stream1.mpg stream2.mpg ... my_dvdlikestream.mpg; dvdauthor -T -o output/ ' You will get a directory with AUDIO_TS and VIDEO_TS directories. Burning the data from the disk to a DVD+-R/+-RW writer would be done like this: `growisofs -Z /dev/scd2 -dvd-video mydvd/' If you own a DVD+RW/+R drive a good place for more information is: `DVD+RW/+R for Linux http://fy.chalmers.se/~appro/linux/DVD+RW/' page. You also need a version of the cdrtools with *dvd-video* support. The cdrtools 1.11a27 is known to work but newer versions already exist. For other writers the commands to write a DVD will be different. You can get some more information in the dvdauthor package. There is no guarantee that it will work at all !!!  File: mjpeg-howto.info, Node: Creating DIVX Videos, Prev: Creating DVD's, Up: Converting the stream to MPEG or DIVx videos 7.9 Creating DIVX Videos ======================== * Menu: * lav2avi-sh::  File: mjpeg-howto.info, Node: lav2avi-sh, Up: Creating DIVX Videos 7.9.1 lav2avi-sh ---------------- Another way of creating DIVX is the program *mencoder* which is from the mplayer project. `http://www.mplayer.hu/'. For more information about mencoder please read mencoder/mplayer help and documents. A first and a second pass give at the end of pass hints for bitrate which can be used for encoding to specific size (650 MB, 700 MB and 800 MB). The script lav2avi.sh uses this information if provided (for short streams it is omitted by mencoder). Look for parameter `preferedSize' in the script. You can also specify other parameters used for encoding with `encoderParam' option in the script. For a description of the usable parameters take a look in the mplayer/mencoder manual. The outputfilename is that name of your input file (first option) but with the extension avi. If the size of file is less then specified by `preferedSize' it's because the source was of very high quality (no noise) and the specified bitrate was higher than required. You usually get 700MB for 1.5 hour film at half image size with bitrate around 900 that means for divx good quality (assuming good quality source material of course). The script does a 3 step encoding: * 1st step - audio encoding * 2nd step - first video pass * 3rd step - second video pass The mplayer/mencoder documentation deprecates the use of the 3 pass encoding method (it can cause A/V sync problems) and recommends the use of the 2 pass method. The mencoder/mplayer documentation is extensive and has many helpful hints (and a bitrate calculator in the TOOLS/ directory). For encoding use the fast ffmpeg (lavc) codec. It gives nice results together with high good performance. For audio encoding mp3 is used. For encoding of all parts it uses unix pipes. This mean that you DO NOT need additional space on your hard drive where all glav manipulations will be done. For audio encoding the script uses a FIFO queue. If you want to tweak the script for your own needs use these hints: * Output of 1st step is file called *frameno.avi* with encoded audio * 2nd step is using *frameno.avi* and output is text file called `lavc_stats.txt' with timing informations * 3rd step is using *frameno.avi* and `lavc_stats.txt' for encoding the stream to the output file *movie2.avi* * If you want change only video bitrate keep the file *frameno.avi* comment out the 1st step encoding and repeate 2nd and 3rd step. Dont forget to remove the line where the *frameno.avi* is removed.  File: mjpeg-howto.info, Node: Optimizing the stream, Next: Transcoding of existing MPEG-2, Prev: Converting the stream to MPEG or DIVx videos, Up: Top 8 Optimizing the stream *********************** Using filters helps to increase the image quality of constant bitrate (CBR) video streams. With VBR (variable bit rate) video the filesize is reduced. Example: `> lav2yuv stream.avi | yuvmedianfilter | mpeg2enc -o video.m1v' Here the yuvmedianfilter program is used to improve the image. This removes some of low frequence noise in the images. It also softens the image a little. It takes a center pointer and averages the pixels around it that fall within the specified threshold. It then replaces the center pixel with this new value. You can also use the -r (radius) option for an other search radius. *NOTE_*a radius greater than the default value of 2 is horrendously slow! yuvmedianfilter has separate settings for luma and chroma. You can control the search radius and the trigger threshold independently. If you use a threshold of 0 then filtering is disabled (-t 0 disables luma filtering, -T 0 disables chroma filtering). `> lav2yuv stream.avi | yuvmedianfilter -r 3 -t 4 -T 0 | mpeg2enc -o video.m1v' This example uses a search radius of 3 pixels for the luma, a threshold of 4 (the default is 2), and disables filtering for the chroma components. Sometimes, depending on the source material, median filtering of the chroma can cause a slight color shift towards green. Filtering on the luma component (disabling the chroma filtering) is the solution to that problem. Example: `> lav2yuv stream.avi | yuvdenoise | mpeg2enc -o video.m1v' Now we are using yuvdenoise to improve the image. The filter mainly reduces color and luminance-noise and flickering due to phase errors but is also effective at removing speckles. yuvdenoise denoises interlaced if the input is interlaced. You can of course change the denoiser threshold (-g/t). Creating a black border can lower the bitrate of the encoded stream because pure black areas compress much better than noise (captures from analog sources such as VHS and 8mm usually have several lines at the time and bottom that are very noisy). For this you can use the scaler. yuvdenoise uses a different approach to filter the noise. More information about how yuvdenoise works as well as descriptions of its options are found in the manpage. If you have a high quality source you should lower the filter to levels like that: -g 0,255,255 -t 2,2,2. You might also use the mpeg2enc *-h/-keep-hf* option. That option tells mpeg2enc to keep as much high frequency information as possible. Using -h will greatly increase the bitrate (filesize). If the bitrate is too close to the maximum (set with -b) the encoder will have to decrease the quality to avoid exceeding the maximum bitrate. A builtin filter in mpeg2enc is the -N/-reduce-HF option. This option is not really filter in the usual sense. Rather it changes how exactly the high frequency information is encoded. Often the high frequency is noise. You also have high frequencies on sharp borders or transitions. The -N option can have values between 0.0 and 2.0 where 0.0 does nothing (disables the high frequency quantizer boost) and 2.0 gives the maximum quantization boost. The value to use depends on the desired output quality and filesize. Values of -N less than 0.5 are very subtle while a value of 1.0 will achieve a good balance between bitrate reduction and output quality. Using -N values above 1.5 will noticeably reduce the sharpness of the output picture and are normally used only for poor quality sources (VHS tapes for example). Using yuvmedianfilter's capability to only filter the chroma (-T) is moderately effective at reducing noise in dark scenes without softening the image during normal (brighter) scenes. Median filtering of the luma (-t) will produce a lower bitrate but can cause loss of detail (softening). Chroma only medianfiltering is less agressive and is a good choice to use in combination with yuvdenoise. Combining the filters yuvdenoise, yuvmedianfilter and the mpeg2enc -N option gives a very fine degree of control over the bitrate (filesize). The reduction (or increase) in the bitrate depends on the source material and the exact encoding/filter options used. So we can give no exact numbers how much each option and combination will reduce the filesize, only guidelines. Usually you should use the -N option in a range from 0.5 to 1.5. Below 0.5 it does not reduce the bitrate very much (but does preserve sharpness). At 1.5 and higher you will notice a softening in the video and possibly artifacts (halo/ringing) around edges of objects (text/subtitles especially). If you combine the filters you should use yuvdenoise and maybe afterwards yuvmedianfilter. Maybe yuvmedianfilter even after scaling. Having yuvmedianfilter in the chain does not reduce the bitrate that much. Often the use of yuvdenoise is enough. The yuvmedianfilter helps much if you have low quality sources, and not that much if you already have a rather good quality. When you combine the filter and option you will very likely reduce the filesize to about the half of the filesize without using the options and programs. In general aggressive filtering will produce smaller files (lower bitrate) but reduce the quality (details) of the picture. Less aggressive filtering/processing will preserve more detail but result in larger files. Example: `> lav2yuv stream.avi | yuvkineco -F 1 | mpeg2enc -o video.m1v' yuvkineco is used for NTSC sources. It does the conversation from 30000.0/1001.0 (about 29.97) fps to 24000.0/1001.0 (about 23.976) fps, you can call it "reverse 2-3 pulldown" more info about this in the README.2-3pulldown. yuvkineco does only remove NTSC specific problems. If you want to improve the image you should also use yuvdenoise: `> lav2yuv stream.avi | yuvkineco | yuvdenoise | mpeg2enc -o video.m1v' Example `> lav2yuv stream.avi | yuvycsnoise | mpeg2enc -o video.m1v' yuvycsnoise is also used for NTSC and is specialized for NTSC Y/C separation noise. If video capture hardware has only a poor Y/C separator then at vertical stripes (especially red/blue) noises appear which seem checker flag and bright/dark invert per 1 frame. yuvycsnoise reduces noises of this type. You can also use different thresholds for luma/chroma and the optimizing method. This filter is not needed with working with DV (Digital Video) data. yuvycsnoise works only correct when we have NTSC with: * full height (480 lines) * full motion captured (29.97 fps) * captured with poor Y/C separator hardware For more information about the yuvkineco and yuvycsnoise read the README in the yuvfilters directory. If you want to experiment to determine the optimal settings for the denoiser, scaler and so on replace the mpeg2enc with yuvplay. yuvplay plays back the yuv frames so you can see if the options you have chosen are making the thing better or worse. A command would look like this: `> lav2yuv stream.eli | yuvdenoise -options | yuvscaler -options | yuvplay' If you want to know how much each tool lowers the average bitrate. You can use this table to see what you can expect if you have a full size video and want to create a DVD with a qality factor of 5 and the allowed maximal bitrate of 8500kb/sec. * no denoising : 8300 kb/s (mostly hitting the upper bound) * yuvenoise : 7700 kb/s * mpeg2enc -reduce-hf : 7400 kb/s * yuvdenoise + yuvmedianfilter : 6000 kb/s * yuvdenoise + mpeg2enc -reduce-hf : 4900 kb/s * all of the above : 3600 kb/s While *-N|-reduce-hf* or yuvdenoise alone is only a modest improvement, together they reduce the bitrate substantially. There is not really much visible difference between using yuvdenoise alone and yuvdenoise with mpeg2enc -reduce-hf. The usefull values are between 0.0 and 1.5. Where you can say that the higher the quality factor you want, the less this option improves. At a quality factor 4 you save using -N 1.0 about 1%. If you want a quality factor of 9 and use the -N 1.0 you might save up to 40%. But you might save less, that depends on the video you encode!!! If you ask yourself why not alyways use all of the above filters? The answers are that the image softens (loss of detail) and the encoding time increases. Most of the filters each require about the same amount of time as mpeg2enc needs for encoding the video. If you have very high quality material and want to keep every detail you should try to use the mpeg2enc -keep-hf|-h on the other hand. *Note_* The bitrate reduction you have depends on the material and on the noise of the images. A other interresting mpeg2enc option is the *-E|-unit-coeff-elim* option. This option is disabled by default. If you enable it, a special "unit coefficient elimination" algorithm, is applied to the encoded picture blocks. Basically this proceedure forces blocks of a type that do not carry much information (but use many bits to encode) to be skipped. A negative value examines the base (DC) as well as the AC coefficients. A positive value means that only texture (AC) coefficients are examined and possibly zeroed. The recommended values lies between -20 and +20. You usually can expect that you have a 5% decreased filesize. The amount the bitrate is reduced can vary considerably, the range spans from not really noticable up to 20%. If you think a other quantization matrice will help use the *-K|-custom-quant-matrices* option. You can try out your own quanitsation matrice or use another builtin than the default. You can choose between kvcd, tmpgenc, hi-res, and your own. Using -K usually makes the file smaller except the hi-res option (that makes files considerably larger). Exact guidelines are hard to give, sometime a other quanitsation matrix saves almost nothing, and the next time up to 20%. More than 20% is very unlikely, 10-15% at a moderate qualityfactor (-q 8-10) are likely. The higher the qualiy the less it saves, at a quality factor of 4-6 the reduction in bitrate may only be 5% One thing to keep in mind is that the unit coefficient elimination and the quantization matrix option are decreasing the bitrate while maintaining the same visual quality. At this point you can chose to use the smaller file to increase the amount of video that will fit on the disc media or you could chose to increase the quality even more by lowering the -q value by 1 and make a larger (but higher quality) file. * Menu: * Scaling and offset correction:: * Frame rate conversion::  File: mjpeg-howto.info, Node: Scaling and offset correction, Next: Frame rate conversion, Up: Optimizing the stream 8.1 Scaling and offset correction ================================= The basic scaling is described in the *Converting video* section The scaling takes a part of the picture and scales it to a larger or smaller size. The scaling is done by yuvscaler: `lav2yuv test.eli | yuvscaler -I USE_400x400+50+100 | yuvplay' Here we only take part of the picture and scale it up to the size of the original frame. But yuvscaler also changes the pixel aspect ratio. That means when you look at the stream using yuvplay it looks like a square in our example. After scaling, if the sample (pixel) aspect ratio were not changed, the video would not display with the proper aspect ratio. Yuvscaler compensates by adjusting the sample aspect ratio. If you have a interlaced video, the height and HeightOffset have to be a multiple by 4 if the video is interlaced. Else the values (width, height, widthoffset, heightoffset) have to be a multiple of 2. A problem that cannot be solved easily with scaling is when the picture is not centered horizontal. On one side you have no black pixels and on the other you have 30 for example. Scaling is here is the wrong solution. y4mshift is the perfect solution because it can shift the image to the left or right. `lav2yuv test.eli | y4mshift -n 20 | mpeg2enc -f 3 -b 4000 -q 10 -o video.m2v' That will shift the image 20 pixels to the right. If you use a negative the image is shift to the left. You have to use a even number. The inserted pixels are set to black. Some might wonder why the image is not centered and there is a black border around the image when you view what you have recorded. The reason for the black border is in history of the CRT (Cathode Ray Tube) TV technology. The history of the TV standard s a very interesting story but that topic is described in other (large) books. The TV does not show the full picture. A part of the picture is not shown because the TV sets overscan (sometimes as much as 10% but more common today is 5%). But when you capture the video with a card you see the whole image including the border that TVs lose due to overscanning. A horizontal offset is usually not a problem of the capture card. It is a problem when the film is broadcast and not well synchronized with the image. This means that the scan of the source not exactly synchronized with the carrier signal, you wont see that on TV.  File: mjpeg-howto.info, Node: Frame rate conversion, Prev: Scaling and offset correction, Up: Optimizing the stream 8.2 Frame rate conversion ========================= Ever needed to convert the framerate from PAL to NTSC or the other direction around ? Or something much simpler like converting the framerate from 24FPS to 24000:1001 for conversation from a film frame rate to a valid NTSC frame rate. Than *yuvfps* is your program. It can lower the framerate by dropping frames or create a higher framerate by replicating frames. If you have a wrong framerate in the header you can only change the header of the YUV stream and not modify the stream. Because the frames are only replicated (copied) you should denoise first and then change the framerate and scale at als last step. If you have a interlaced source you should also deinterlace before changeing the framerate. If you create a higher frame rate it is very likely that you will have weird flickers when you play it back. If you convert PAL to NTSC (30000:1001 FPS about 29,97 FPS) the frame rate will lower by about the factor 480/576 (NTSC lines / PAL lines). If you lower the frame rate from PAL to NTSC (at 24000:1001) or NTSC FILM (24FPS) the bitrate will be about (480 Lines * 24 FPS) / (576 Lines * 25FPS). If you change the frame rate before denoising the yuvdenoise will have problems finding the noise across the frames and the needed bandwith will slightly increase. Example `> lav2yuv video.eli | yuvfps -r 30000:1001 | yuvscaler -O SVCD | mpeg2enc -f 4 -o video_ntsc_svcd.m2v' This is a example to convert the source video to a NTSC video running at 30000:1001 FPS (or about 29,97FPS) at SVCD size. Example `> lav2yuv video.eli | yuvdenoise | yuvfps -r 24000:1001 | yuvscaler -O SIZE_720x480 | mpeg2enc -f 3 -b 4000 -q 7 -o video_ntsc.m2v' This example shows how you should use the tools. Denoise first and than change the framerate and in the last step change the image size. It can happen that yuvscaler or mpeg2enc do not detect the TV norm correct. If that happens you have to add the norm option *-n n/p/s* to the program that chooses the wrong norm. If you know that the header tells the wrong framerate, you can simply change the framerate of the yuv header this way: `> lav2yuv video.eli | yuvfps -r 25:1 -c | mpeg2enc -f 3 -b 4000 -q 7 -o video_pal.m2v' You need the *-c* option. To tell yuvfps that it only should change the header of the stream. With the *-r 25:1* you tell yuvfps the frame rate it should write into the header. In your example the PAL frame rate of 25 FPS. You always have to use the fractional form. If you know that the header is wrong, and you need a different output bitrate you can do this in a single step: `> lav2yuv video.eli | yuvfps -s 24:1 -r 25:1 | mpeg2enc -o video.m1v'  File: mjpeg-howto.info, Node: Transcoding of existing MPEG-2, Next: Trading Quality/Speed, Prev: Optimizing the stream, Up: Top 9 Transcoding of existing MPEG-2 ******************************** For transcoding existing MPEG-2 streams from digital TV cards or DVD a lower data-rate than for broadcast will give good results. Standard VCD 1152 kbps typically works just fine for MPEG-1. The difference is in the Signal/Noise ratio of the original. The noise in the analog stuff makes it much harder to compress. You will also need to manually adjust the audio delay offset relative to video when multiplexing. Very often around 150ms delay seems to do the trick. You have to download the ac3dec and mpeg2dec packages. You can find them at their homepage: mpeg2dec ( `http://libmpeg2.sourceforge.net/' ) and ac3dec. For decoding the audio streams mpg123 and mplayer can be very helpfull. You also need sox and toolame. In the scripts directory there is a *mpegtranscode* script that does most of the work. So transcoding looks like this: `> mjpegtranscode -V -o vcd_stream mpeg2src.mpg' `-V' set's the options so that a VCD compatible stream is generated `-o vcd_stream' a vcd_stream.m1v (video) and vcd_stream.mp2 (audio) is created `mpeg2src.mpg' specifies the source stream The script prints also something like this: `> SYNC 234 mSec' You will need to adjust the audio/video startup delays when multiplexing to ensure audio and video are synchronized. The exact delay (in milliseconds) that you need to pass to mplex to synchronize audio and video using the "-v"" is printed by the extract_a52 tool labeled "SYNC" when run with the "s" flag. This is the value th mjpegtranscode script prints out after the *SYNC* word. Then you need to multiplex them like this: `> mplex -f 1 -O 234 vcd_stream.mp2 vcd_stream.m1v -o lowrate.mpg' `-f 1' Mux format is set to VCD `-O 234' Video timestamp offset in mSec, generated by the mjpegtranscoding script, there negative values are allowed `vcd_stream.mp2 & vcd_stream.m1v' generated files by the script `lowrate.mpg' the VCD compatible output stream Here we have a SVCD (MPEG-2 video) example: `> mjpegtranscode -S -o svcd_stream mpeg2src.mpg' You have to multiplex it with: `> mplex -f 4 -O 234 svcd_stream.mp2 svcd_stream.m2v -o lowrate.mpg' *Problem:* There is sometimes a problem with NTSC and VCD playback because movies may be recoded with 3:2 pulldown NTSC with 60 fields/sec. mpeg2dec is designed for playback on computers and generates the original 24frames/sec bitrate. If you encode the video now 30frames/sec video is created. This video is now much too short for the encoded audio. The transcoding can be made to work but it must be done manually: `> mpeg2dec -s -o pgmpipe mpeg2src.mpg | pgmtoy4m -a 59:54 -r 25:1 -i t | mpeg2enc -I 0 -f 4 -q 9 -V 230 -p -P -o svcd_stream.m2v' The -p tells mpeg2enc to generate header flags for 3:2 pull down of 24fps movie. It may also work if you do not add the -p flag. You do not need the -p flag when transcoding to VCD format because it is not supported in mpeg1. * Menu: * If you want to do every step on your own it will look something like this::  File: mjpeg-howto.info, Node: If you want to do every step on your own it will look something like this, Up: Transcoding of existing MPEG-2 9.1 If you want to do every step on your own it will look something like this ============================================================================= Extracting Audio: `> cat test2.mpg | extract_a52 - -s | ac3dec -o wav -p sound.wav 2>/dev/null' One of the first lines showed contains the label "SYNC" you have to use this time later when multiplexing. The 2>/dev/null redirects the output of ac3dec to /dev/null. In the next step you generate the mpeg audio file: `> cat sound.wav | mp2enc -V -v 2 -o audio.mp2' `-V' forces VCD format, the sampling rate is converted to 44.1kHz from 48kHz `-v 2' unnecessary but if you use it mp2enc tells you how many seconds of the audio file are already encoded. `-o' Specifies the output file. `cat test2.mpg | extract_a52 - -s | ac3dec -o wav | sox -t wav /dev/stdin -t wav -r 44100 /dev/stdout | toolame -p 2 -b 224 /dev/stdin audio.mp2' One of the first lines again output contains the label "SYNC". You have to use this time (referred to as "SYNC_value" below) when doing the multiplexing. For VCD creation use: `> mpeg2dec -s -o pgmpipe test2.mpg | pgmtoy4m -a 59:54 -r 25:1 -i t | mpeg2enc -s -o video_vcd.m1v' `' mpeg2dec: `-s' tells mpeg2dec to use program stream demultiplexer `-o pgmpipe' the output format of the pictures, suitable for pgmtoy4m Mplex with: `> mplex -f 1 -O SYNC_value audio.mp2 video_vcd.m1v -o vcd_stream.mpg' `-f 1' generates an VCD stream `-O SYNC_value' the value mentioned above For SVCD creation use: `> mpeg2dec -s -o mpeg2src.mpg | pgmtoy4m -a 59:54 -r 25:1 -i t | mpeg2enc -f 4 -q 9 -V 230 -o video_svcd.mpg' `-q 9' Quality factor for the stream (VBR stream) (default q: 12) `-V 230' Target video buffer size in KB `-o' Output file Mplex with: `> mplex -f 4 -b 230 audio.mp2 video_svcd -o svcd_stream.mpg' `-f 4' generate an SVCD stream `-b 200' Specify the video buffer size by the playback device. For other video output formats this might work: `> mpeg2dec -s -o pgmpipe test2.mpg | pgmtoy4m -a 59:54 -r 25:1 -i t | yuvscaler -O SIZE_320x200 -O NOT_INTERLACED | mpeg2enc -o strange_video.m1v' If you want to edit mpeg streams this also works but in a slightly different way. For demultiplexing you can use bbdmux from the bbtools package. Splits out either video or audio very cleanly. You can't get it any more from the homepage from Brent Beyler, it can still be found when you search for it using that keywords " bbtools linux -suse -blackbox". Currenty it can be found at: `http://www.nop.org/inkling/' First run: `> bbdmux myvideo.mpg' You should get something like this: Found stream id 0xE0 = Video Stream 0 Found stream id 0xC0 = MPEG Audio Stream 0 Found stream id 0xBE = Padding Stream Extract audio with: `> bbdmux myvideo.mpg 0xC0 audio.mp1' Convert it to wav: `> mpg123 -w audio.wav audio.m1v' Extract video with: `> bbdmux myvideo.mpg 0xE0 video.m1v' Converting video to an mjpeg avi stream: `> mpeg2dec -o pgmpipe video.m1v | pgmtoy4m -a 59:54 -r 25:1 -i t | yuv2lav -f a -o test.avi' Then adding the sound to the avi: `> lavaddwav test.avi audio.wav final.avi' If the source video has already the size of the target video use -o YUV. Using YUVh makes the video the half size! The rest can be done just like editing and encoding other streams. If you have videos with ac3 sound you only have to adapt the commands above. Extracting Audio: `> cat test2.mpg | extract_a52 - -s | ac3dec -o wav 2>dev/null >sound.wav' Extract video and adding the audio in a single step : `> mpeg2dec -s -o pgmpipe | pgmtoy4m -a 59:54 -r 25:1 -i t | yuvscaler -O VCD | yuv2lav -f a -q 85 -w sound.wav -o test.avi' *NOTE_*You need much disk space. 1GB of video has a size of about 2GB at SVCD format and of course disk space is needed for some temp files. Converting the video to mjpeg also takes some time. On my Athlon 500 I never get more than 6-7 Frames a second. You loose quality each time you convert a stream into an other format!  File: mjpeg-howto.info, Node: Trading Quality/Speed, Next: SMP and distributed Encoding, Prev: Transcoding of existing MPEG-2, Up: Top 10 Trading Quality/Speed ************************ If absolute quality is your objective a modest improvement can be achieved using the -4 and -2 flags. These control how ruthlessly mpeg2enc discards bad looking matches between sections of adjacent frames during the early stages of the search when it is working with 4*4 and 2*2 clusters of pixels rather than individual pixels. Setting -4 1 -2 1 maximizes quality. -4 4 -2 4 maximizes speed. Note that because the statistical criteria mpeg2enc uses for discarding bad looking matches are usually fairly reliable the increase/decrease in quality is modest (but noticeable). Reducing the radius of the search for matching sections of images also increases speed. However due to the way the search algorithm works the search radius is in effect rounded to the nearest multiple of 8. Furthermore on modern CPU's the speed gained by reducing the radius below 16 is not large enough to make the marked quality reduction worthwhile for most applications. * Menu: * Creating streams to be played from disk using Software players::  File: mjpeg-howto.info, Node: Creating streams to be played from disk using Software players, Up: Trading Quality/Speed 10.1 Creating streams to be played from disk using Software players =================================================================== Usually MPEG player software is much more flexible than the hardware built into DVD and VCD players. This flexibility allows for significantly better compression to be achieved for the same quality. The trick is to generate video streams that use big video buffers (500KB or more) and variable bitrate encoding (the -f / -q flag to mpeg2enc). Software players will often also correctly play back the more efficient MPEG layer 3 (yes, "MP3" audio format. A good MP3 encoder like lame will produce results comparable to layer 2 at 224Kbps at 128Kbps or 160Kbps.  File: mjpeg-howto.info, Node: SMP and distributed Encoding, Next: Interoperability, Prev: Trading Quality/Speed, Up: Top 11 SMP and distributed Encoding ******************************* Distributed encoding is a quite dark theory for the typical Machine in 2013. So most users can safely skip that point. SMP Encoding is more interresting for the average computer The degree to which mpeg2enc tries to split work between concurrently executing threads is controlled by the -M or -multi-thread [0..32] option. This optimizes mpeg2enc for the specified number of CPUs. By default (-M 1) mpeg2enc runs with just a little multi-threading: reading of frames happens concurrently with compression. This is done to allow encoding pipelines that are split across several machines (see below) to work efficiently without the need for special buffering programs. If you are encoding on a single-CPU machine where RAM is tight you may find turning off multithreading altogether by setting -M 0 works slightly more efficiently. For SMP machines with two ore more processors you can speed up mpeg2enc by setting the number of concurrently executing encoding threads's you wish to utilize (e.g. -M 2). Setting -M 2 or -M 3 on a 2-way machine should allow you to speed up encoding by around 80%. Values above 3 are accepted but have very little effect even on 4 cpu systems. If you have a real fast SMP machine (currently 1.Aug.03) like a dual Athlon MP 2600 or something similar the -M 2 and the filtering might not keep both (or more) CPU's busy. The use of the buffer or bfr program with a 10-20MB buffer helps to keep both CPUs busy. Obviously if your encoding pipeline contains several filtering stages it is likely that you can keep two or more CPU's busy simultaneously even without using -M. Denoising using yuvdenoise or yuvmedianfilter is particular demanding and uses almost as much processing power as MPEG encoding. It you more than one computer you can also split the encoding pipeline between computers using the standard 'rsh' or 'rcmd' remote shell execution commands. For example, if you have two computers: `> rsh machine1 lav2yuv "mycapture.eli | yuvscaler -O SVCD | yuvdenoise" | mpeg2enc -f 4 -o mycapture.m2vi' Here the computer where you execute the command is doing the MPEG encoding and "machine1" is the machine that is decoding scaling and denoising the captured video. Obviously, for this to work "machine1" has to be able to access the video and the computer where the command is executed has to have space for the encoded video. In practice, it is usually well worth setting up network file-storage using "NFS" or other packages if you are going to do stuff like this. If you have three computers you can take this a stage further, one computer could do the decoding and scaling, the next could do denoising and the third could do MPEG encoding: `> rsh machine1 "lav2yuv mycapture.eli | yuvscaler -O SVCD" | yuvdenoise | rsh machine3 mpeg2enc -f 4 -o mycapture.m2v' *NOTE_*How the remote command executions are set up so that the data is sent direct from the machine that produces it to the machine that consumes it. In practice for this to be worthwhile the network you are using must be fast enough to avoid becoming a bottleneck. For Pentium-III class machines or above you will need a 100Mbps Ethernet. For really fast machines a switched 100MBps Ethernet (or better!) may be needed.Setting up the rshd ("Remote Shell Daemon" needed for rsh to do its work and configuring "rsh" is beyond the scope of this document, but its a standard package and should be easily installed and activated on any Linux or BSD distribution. Be aware that this is potentially a security issue so use with care on machines that are visible to outside networks!  File: mjpeg-howto.info, Node: Interoperability, Prev: SMP and distributed Encoding, Up: Top 12 Interoperability ******************* Quicktime files capturing using lavrec can be edited using Broadcast2000. But Broadcast2000 is not available any more on heroinewarrior. mjpeg AVI files captured using the streamer tool from the xawtv package can be edited and compressed and played back using software. Hardware playback is not possible for such files due to limitations in the Zoran hardware currently supported. Videos recorded with NuppelVideo can also be processed with the mjpeg tools. If you have a Macintosh (MAC) and want to use the mjpeg tools look there: `http://www.sjoki.uta.fi/~shmhav/SVCD_on_a_Macintosh.html' MPEG files produced using the tools are know to play back correctly on: * dxr2 (hardware decoder card) * xine `http://xine.sourceforge.net/' * xmovie `http://heroinewarrior.com/xmovie.php' * mplayer `http://www.mplayerhq.hu/' * vlc `http://www.videolan.org/' * MPEG-1 only: gtv `http://packages.debian.org/stable/graphics/smpeg-gtv' * MS Media player version 6 and 7 and later version * severals Software based DVD Player To find out what you HW-player (most of the time DVD player) can do take a look at: `http://www.videohelp.com' It seems that the MS Media player likes MPEG-1 streams more if you have used -f 1 when multiplexing. If you have any problems or suggestions feel free to mail me (Bernhard Praschinger): `waldviertler@users.sourceforge.net' There is a lot of stuff added from the HINTS which Andrew Stevens created. Wolfgang Goeller and Steven M. Schultz checked the document for bugs and spelling mistakes. And to the people who have helped me with program descriptions and hints, *thanks*  Tag Table: Node: Top141 Node: Introduction792 Node: Unsorted list of useful Hints2492 Node: Some books we found usefull7475 Node: Recording videos8186 Node: lavrec examples8570 Node: Other recording hints12292 Node: Some information about the typical lavrec output while recording13804 Node: Notes about "interlace field order - what can go wrong and how to fix it"15359 Node: There are three bad things that can happen with fields16201 Node: How can I recognize if I have one of these Problems ?17978 Node: How can you fix it?19573 Node: Hey what about NTSC movies ?22870 Node: Creating videos from other sources24165 Node: Creating videos from images24751 Node: Decoding streams with mplayer27926 Node: Decoding MPEG-2 streams with mpeg2dec29216 Node: Other things to know30253 Node: Checking if recording was successful30851 Node: Edit the video33113 Node: Edit with glav33421 Node: Unify videos34869 Node: Separate sound35357 Node: Separate images35784 Node: Creating movie transitions36779 Node: Converting the stream to MPEG or DIVx videos40498 Node: Creating sound42251 Node: Converting video44070 Node: Scaling45836 Node: High quality scaling y4mscaler47193 Node: Putting the streams together50145 Node: Creating MPEG-1 Videos52436 Node: MPEG-1 Audio creation Example53347 Node: MPEG-1 Video creation example54159 Node: MPEG-1 Multiplexing Example58705 Node: Creating MPEG-2 Videos59585 Node: MPEG-2 audio creation example60660 Node: MPEG-2 Video creation example61230 Node: Which values should be used for VBR Encoding?63682 Node: Encoding destination TV (interlaced) or Monitor (progressive)66044 Node: MPEG-2 Multiplexing example68601 Node: Creating Video CDs (VCDs)69440 Node: VCD Audio creation Example70538 Node: VCD Video creation Example71103 Node: VCD Multiplexing Example72625 Node: Creating the CD72997 Node: Notes73568 Node: Storing MPEGs74578 Node: Creating SVCD75926 Node: SVCD Audio creation Example76747 Node: SVCD Video creation example77737 Node: SVCD multiplexing example80164 Node: SVCD creating the CD80711 Node: Creating DVD's81399 Node: DVD Audio creation example82428 Node: DVD Video creation example82985 Node: DVD multiplexing example83970 Node: DVD creation example84489 Node: Creating DIVX Videos85562 Node: lav2avi-sh85767 Node: Optimizing the stream88376 Node: Scaling and offset correction99135 Node: Frame rate conversion101668 Node: Transcoding of existing MPEG-2104522 Node: If you want to do every step on your own it will look something like this107803 Node: Trading Quality/Speed112111 Node: Creating streams to be played from disk using Software players113336 Node: SMP and distributed Encoding114160 Node: Interoperability117984  End Tag Table mjpegtools-2.1.0/docs/lav2mpeg.10000644000175000017500000001213412216627207016746 0ustar glowwormglowworm.\" Process this file with .\" groff -man -Tascii foo.1 .\" .TH lav2mpeg 1 "JANUARY 2002" "MJPEG Tools Team" "MJPEG tools manual" .SH NAME lav2mpeg \- easy conversion of lav files to mpeg .SH SYNOPSIS .B lav2mpeg [ options ] .I lavfile1 [lavfile2 ... lavfileN] .SH DESCRIPTION .B lav2mpeg is a shell script to ease the use of the mjpeg utilities, providing a convenient way to convert from MJPEG files to popular MPEG file formats. It supports output in VCD, medium and high rate VCD, SVCD, high rate SVCD, and generic mpeg1 and mpeg2 .LP The input files may be any combination of AVI (.avi), Quicktime (.qt) or editlist files so long as they are all lavtools\- readable (e.g. MJPEG-encoded AVI/Quicktime or DV type 2 AVI). .SH OPTIONS .IP -s/S Turn stereo off/on (default auto) .IP -k/K Turn keeping of raw files off/on (default off) .IP -f/F Turn use of fifos off/on (default off) .IP -l/L Turn logging of entire process off/on (default off) .IP -n/N Turn "noisy logging" off/on (default off) .IP -y/Y Turn use of yuvdenoise off/on (default off) .IP -m one of MODES (see below) (default vcd) .IP -e encoding quality : 0, 1, or 2 (default 2) .IP -o output file ( defaults to firstInputFileName.mpg ) .IP -b video bitrate in kbps ( only used when -o is "mpeg1" or "mpeg2" ) .IP -a audio bitrate in kpbs ( only used when -o is not "vcd*" ) .IP -q quality for mpeg2enc ( only used when -o is "mpeg1" or "mpeg2" ) .IP -d dimensions XxY ( only used when -o is "mpeg1" or "mpeg2" ) defaults to same as input .SH MODES .B vcd .ft R -- standard VCD (352x240 or 352x288) .B vcd_medium -- 1550kbps video VCD (352x240 or 352x288) .B vcd_high -- 1800kbps video VCD (352x240 or 352x288) .B svcd -- standard SVCD (480x480 or 480x576) .B svcd_high -- 3000kbps(max) vbr @qual=5 (480x480 or 480x576) .B mpeg1 -- honor -a -b -q -d flags default resolution same as input .B mpeg2 -- honor -a -b -q -d flags default resolution same as input .SH FILES .I ~/.lav2mpegrc .RS user configuration file. It is bash sourceable, and can modify any of the environment variables mentioned in the ENVIRONMENT section, or set the LAV2MPEG_OPTIONS variable to add default options. .SH ENVIRONMENT .IP NICEVAL the nice value of each command, set using 'nice -n command' .IP YUVSCALER modify which command is called for yuvscaler .IP LAV2WAV modify which command is called for lav2wav .IP MPLEX modify which command is called for mplex .IP YUVDENOISE modify which command is called for yuvdenoise .IP MPEG2ENC modify which command is called for mpeg2enC .IP AUDIOENC audioenc is similar to those above, however, if it is set to 'mp2enc' it will use mp2enc rather than toolame, and set flags appropriotely. .IP NOISYLOGFILE set the file used for noisy logging (-N) defaults to outputfile.log .IP QUIETLOG set the file used for quiet logging. defaults to lav2mpeg.log if set to "" it will log only to screen .IP LOGDATE defaults to 1, set to 0 to not have the date logged in log or output (see man date for more info) .IP LOGDATESTR will pass this on to 'date' to describe what time format to use. Only used if LOGDATE is not 0 .IP LOGCOMMANDS if set to non-zero, will log to the quite log the commands used. Commands are always logged to NOISYLOGFILE if used .IP LOGONLY if set to non-zero, will only log the commands it would use but not actually run any commands .IP LAV2MPEGRC the lav2mpegrc file. Only beneficial if set from environment variable. .IP VCD_MEDIUM_BR video bitrate for mode=vcd_medium .IP VCD_HIGH_BR video bitrate for mode=vcd_high .IP SVCD_HIGH_BR video bitrate for mode=svcd_high .IP SVCD_HIGH_QUAL quality used (-q 0-30 to mpeg2enc) for SVCD_HIGH .IP SVCD_HIGH_BUFFSIZE buffsize (-V to mpeg2enc) used for svcd_high defaults to 100 .IP EXTRA_LAV2YUV set extra command line arguments to lav2yuv, which will be added on the end .IP EXTRA_YUVSCALER set extra command line arguments to yuvscaler, which will be added on the end .IP EXTRA_MPEG2ENC set extra command line arguments to mpeg2enc, which will be added on the end .IP EXTRA_LAV2WAV set extra command line arguments to lav2wav, which will be added on the end .IP EXTRA_AUDIOENC set extra command line arguments to mp2enc or toolame (depending on AUDIOENC), which will be added on the end .IP EXTRA_MPLEX set extra command line arguments to mplex, which will be added on the end .IP EXTRA_YUVDENOISE set extra command line arguments to yuvdenoise, which will be added on the end .SH DIAGNOSTICS To simply see the commands that lav2mpeg would have called, run 'LOGONLY=1 lav2mpeg ...' .SH BUGS Possibly. Please let the author know. .SH AUTHOR Scott Moser .SH EXAMPLES .nf create a VCD compliant mpeg regardless of input named file.mpg .ft B lav2mpeg file.avi .ft R create a SVCD high rate mpeg from input named out.mpg .ft B lav2mpeg -o out.mpg -m svcd_high file.avi .ft R use lav2yuv.new for instead of lav2yuv, and add the '-M MMX' flag to yuvscaler: .ft B LAV2YUV="lav2yuv.new" EXTRA_YUVSCALER="-M MMX" lav2mpeg file.avi .ft R Please read other examples included in documentation for .lav2mpegrc usage mjpegtools-2.1.0/docs/Makefile.in0000644000175000017500000004734712217306407017227 0ustar glowwormglowworm# Makefile.in generated by automake 1.12.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = docs DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man1dir = $(mandir)/man1 am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" man5dir = $(mandir)/man5 NROFF = nroff MANS = $(man_MANS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALTIVEC_EXTRA_LIBS = @ALTIVEC_EXTRA_LIBS@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDV_CFLAGS = @LIBDV_CFLAGS@ LIBDV_LIBS = @LIBDV_LIBS@ LIBGETOPT_LIB = @LIBGETOPT_LIB@ LIBM_LIBS = @LIBM_LIBS@ LIBOBJS = @LIBOBJS@ LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ LIBPNG_LIBS = @LIBPNG_LIBS@ LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@ LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ LT_STATIC = @LT_STATIC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROGRAM_NOPIC = @PROGRAM_NOPIC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ SDLgfx_LIBS = @SDLgfx_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ V4LCONF_LIBS = @V4LCONF_LIBS@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # If the installation of man pages by you (e.g. you're a package builder) # You may want to disable it man_MANS = lavplay.1 lavrec.1 mjpegtools.1 mpeg2enc.1 mplex.1 \ yuvplay.1 lav2wav.1 lav2yuv.1 lavtrans.1 mp2enc.1 \ yuvscaler.1 lavpipe.1 yuv2lav.1 yuvdenoise.1 jpeg2yuv.1 \ png2yuv.1 \ pgmtoy4m.1 ppmtoy4m.1 y4mtoppm.1 y4mcolorbars.1 \ y4mtopnm.1 pnmtoy4m.1 \ yuvkineco.1 yuvycsnoise.1 yuvmedianfilter.1 \ y4munsharp.1 y4mscaler.1 \ lav2mpeg.1 yuv4mpeg.5 yuvfps.1 yuvinactive.1 y4mdenoise.1 info_INFO = mjpeg-howto.info EXTRA_DIST = \ $(man_MANS) \ FAQ.txt \ authors.sgml \ lavtools.sgml MAINTAINERCLEANFILES = Makefile.in # (Ronald) this stuff comes from texinfos.am on my # installation. We need it for proper in-auto-build # installation of info pages. # It's adapted to handle the debian install-info case # too... INSTALL_INFO = /sbin/install-info INFO_ENTRY = "* mjpeg-howto: (mjpeg-howto). How to use the mjpeg tools" INFO_DESCRIPTION = "mjpeg tools documentation" all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu docs/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-man1: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) install-man5: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man5dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.5[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \ done; } uninstall-man5: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man5dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.5[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir) tags: TAGS TAGS: ctags: CTAGS CTAGS: cscope cscopelist: distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically 'make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am all-am: Makefile $(MANS) installdirs: for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-am install-html-am: install-info: install-info-am install-man: install-man1 install-man5 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-man uninstall-man: uninstall-man1 uninstall-man5 .MAKE: install-am install-exec-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ dist-hook distclean distclean-generic distclean-libtool \ distdir dvi dvi-am html html-am info info-am install \ install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-exec-hook \ install-html install-html-am install-info install-info-am \ install-man install-man1 install-man5 install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \ uninstall-man uninstall-man1 uninstall-man5 install-exec-hook: install-info dist-hook: dist-info install-info-am: $(info_INFO) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(infodir) @list='$(info_INFO)'; \ for file in $$list; do \ d=$(srcdir); \ for ifile in `cd $$d && echo $$file $$file-[0-9] $$file-[0-9][0-9]`; do \ if test -f $$d/$$ifile; then \ echo " $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile"; \ $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile; \ else : ; fi; \ done; \ done @$(POST_INSTALL) @if test x$(INSTALL_INFO) != x && test -f $(INSTALL_INFO); then \ list='$(info_INFO)'; \ for file in $$list; do \ echo " install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file";\ if $(SHELL) -c '$(INSTALL_INFO) --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \ $(INSTALL_INFO) --entry=$(INFO_ENTRY) --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file || :;\ else \ $(INSTALL_INFO) --infodir=$(DESTDIR)$(infodir) --menuentry=$(INFO_ENTRY) --description=$(INFO_DESCRPITION) $(DESTDIR)$(infodir)/$$file || :; \ fi; \ done; \ fi uninstall-info-am: $(PRE_UNINSTALL) if test x$(INSTALL_INFO) != x && test -f $(INSTALL_INFO); then \ list='$(info_INFO)'; \ for file in $$list; do \ if $(SHELL) -c '$(INSTALL_INFO) --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \ $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) --remove $$file; \ else \ $(INSTALL_INFO) --infodir=$(DESTDIR)$(infodir) --delete $$file; \ fi; \ done; \ fi @$(NORMAL_UNINSTALL) list='$(info_INFO)'; \ for file in $$list; do \ (cd $(DESTDIR)$(infodir) && rm -f $$file $$file-[0-9] $$file-[0-9][0-9]); \ done dist-info: $(info_INFO) list='$(info_INFO)'; \ for base in $$list; do \ d=$(srcdir); \ for file in `cd $$d && eval echo $$base*`; do \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ || cp -p $$d/$$file $(distdir)/$$file; \ done; \ done # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mjpegtools-2.1.0/docs/y4mdenoise.10000644000175000017500000002310312216627211017302 0ustar glowwormglowworm.TH "y4mdenoise" "1" "27 Apr 2004" "MJPEG Tools Team" "MJPEG tools manual" .SH NAME y4mdenoise \- Motion-compensating YUV4MPEG-frame denoiser .SH SYNOPSIS .B y4mdenoise .RB [ -v .IR verbosity ] .RB [ -p .IR parallelism ] .RB [ -r .IR motion-search_radius ] .RB [ -R .IR color_motion-search_radius ] .RB [ -t .IR error_tolerance ] .RB [ -T .IR color_error_tolerance ] .RB [ -z .IR zero_motion_error_tolerance ] .RB [ -Z .IR color_zero_motion_error_tolerance ] .RB [ -m .IR match-count_throttle ] .RB [ -M .IR match-size_throttle ] .RB [ -f .IR reference_frames ] .RB [ -B ] .RB [ -I .IR interlacing_type ] .RI "< /dev/stdin > /dev/stdout" .SH DESCRIPTION \fBy4mdenoise\fP can be used to remove noise from images in a YUV4MPEG2 stream. This is useful for cleaning old sources to increase video quality, and to reduce the bitrate needed to encode your video (e.g. for VCD and SVCD creation). .SH HOW IT WORKS It maintains a list of the last several frames, called reference frames. Each reference frame is composed of reference pixels. Every time a pixel in one frame is proven to be a moved instance of a pixel in another frame, the reference-pixel incorporates its value, and produces an average value for all instances of the pixel. The oldest reference frame, therefore, gets a pretty good idea of the real value of every pixel, but of course output is delayed by the number of reference frames. The search is not actually done one pixel at a time; it's done in terms of pixel groups. An entire pixel-group has to match for any match to be found, but all possible pixel-groups are tested (i.e. all possible overlapping combinations are checked). Using pixel-groups helps to establish a minimum standard for what may be considered a match, in order to avoid finding lots of really small (and really useless) matches. Presently, intensity pixel-groups are 4x2 (i.e. 4 across and 2 down), and color pixel-groups are 2x2. It compares every pixel-group in the current frame with all pixel-groups in the previous frame, within a given search-radius, and sorts them based on how close the match was, keeping the top contenders. It then flood-fills each found pixel-group in turn, to determine the full size of the match. The first match found to be big enough is applied to the image. The number of contenders to consider, and the minimum size of a match, can be specified on the command line. At the end of the frame, any new-frame pixels not resolved yet are considered to be new information, and a new reference-pixel is generated for each one. A "zero-motion pass" happens each frame, before motion-detection, in an attempt to resolve most of the frame cheaply. Its error-tolerance can be set separately. .SH OPTIONS \fBy4mdenoise\fP accepts the following options: .TP 4 .BI \-v " [0..2] verbosity" 0 = none, 1 = normal (per-frame pixel-detection totals), 2=debug. .TP 4 .BI \-p " num" Controls the level of parallelism. Since intensity and color are denoised separately by design, it's very easy to do each in parallel on a multiple-processor machine. The default value is 1; that reads and writes video frames in parallel with denoising. A value of 2 causes intensity and color to be denoised in parallel. A value of 3 does both types of concurrency. A value of 0 turns off all concurrency. .TP 4 .BI \-r " [4..] search radius" The search radius, i.e. the maximum distance that a pixel can move and still be found by motion-detection. The default is 16. There are no particular restrictions on the search radius, e.g. it doesn't have to be an even multiple of 4. .TP 4 .BI \-R " [4..] color search radius" The search radius to use for color. Default is whatever the main search-radius was set to. Note that this value ends up getting scaled by the relative size of intensity & color planes in your YUV4MPEG2 stream. .TP 4 .BI \-t " [0..255] Error tolerance" The largest difference between two pixels that's accepted for the two pixels to be considered equal. The default is 3, which is good for medium-noise material like analog cable TV. (This value will have to be changed to whatever is appropriate for your YUV4MPEG2 stream in order to avoid undesirable results. See the instructions below.) .TP 4 .BI \-T " [0..255] Error tolerance for color" The default is whatever the main error-tolerance was set to. .TP 4 .BI \-z " [0..255] Error tolerance for zero-motion pass" The error-tolerance used on pixels that haven't moved. Usually equal to the main error-tolerance or one less than that. Default is 2. .TP 4 .BI \-Z " [0..255] Error tolerance for color's zero-motion pass" The default is whatever the main zero-motion error-tolerance was set to. .TP 4 .BI \-m " [num] Match-count throttle" The maximum number of pixel-group matches (within the search radius) to consider. If more are found, only the closest matches are kept. Default is 15. .TP 4 .BI \-M " [num] Match-size throttle" The minimum size of the flood-filled region generated from a match. Matches smaller than this are thrown away. Specified in terms of pixel-groups. Default is 3. .TP 4 .BI \-f " num" The number of reference frames to keep. Pixel values are averaged over this many frames before they're written to standard output; this also implies that output is delayed by this many frames. Default is 10. .TP 4 .BI \-B Black-and-white mode. Denoise only the intensity plane, and set the color plane to all white. .TP 4 .BI \-I " num" Set interlacing type. Default is taken from the YUV4MPEG2 stream. 0 means not interlaced, 1 means top-field interlaced, 2 means bottom-field interlaced. This is useful when the signal is more naturally of some other interlacing type than its current representation (e.g. if the original was shot on film and then later it was transferred to interlaced video, it will denoise better if treated as film, i.e. non-interlaced). .SH TYPICAL USAGE AND TIPS Keep in mind that all of this advice was gained through experience. (Just because one writes a tool doesn't mean one understands how it should be used, for the same reason that car designers aren't necessarily professional drivers.) The error-threshold must be determined for every individual YUV4MPEG2 stream. If the threshold is set too low, it'll leave noise in the video, and the denoiser will run a lot slower than it has to. If it's set too high, the denoiser will start to remove detail: the video will get blurrier, you may see topographical-like bands in the relatively flat areas of the video, and small parts of the video that should be moving will be stuck in place. It may also run a little slower. Additionally, just because the video came to you from a clean source (digital cable TV, LaserDisc, etc.) doesn't mean the video itself is clean; \fBy4mdenoise\fP is capable of picking up on noise in the original recording as well as sampling error from the video-capture device. You will have to generate small clips of representative parts of your video, denoise them with various error thresholds, and see what looks the best. As you gain experience with the tool, you may know what error threshold generally works with various types of sources, but you'll still want to double-check your assumptions. Flat, shiny surfaces, like gloss-painted walls, or the polished wood floor of an indoor gymnasium, seem to require a lower error threshold than other types of video. Here is the author's experience: -t 1 : Digital cable TV, most LaserDiscs, DV camcorder video -t 2 : VHS camcorder video, commercially-produced videotapes -t 3 : Analog cable TV, VHS videotape (at the 2-hour speed) -t 4 : VHS videotape (at the 6-hour speed) Interlaced video that was made from non-interlaced video (e.g. a videotape or LaserDisc of a film) must be denoised as non-interlaced. Otherwise the result tends to be grainy. \fBy4mdenoise\fP only removes temporal noise, i.e. noise that occurs over time. And it tends to do such a good job of this, that the spatial noise (i.e. noise that occurs in nearby areas of the same frame) tends to become very distinct. Therefore, always pipe the output of \fBy4mdenoise\fP through a spatial filter such as \fBy4mspatialfilter\fP or \fByuvmedianfilter\fP. When producing very low bitrate video (e.g. VCD-compatible video less than 900 kbps), denoise at the output frame size, e.g. don't denoise at DVD frame size then downscale to VCD size. That will denoise as well as condition the video for the motion-detection part of \fBmpeg2enc\fP. Not doing this will produce video where the less complex scenes will look really good, but high-motion scenes will blur significantly. JPEG compression of your video frames, even 100% compression, seems to be inaccurate enough to affect MPEG encoding. Therefore, if you're using motion-JPEG files as your intermediary video format, you may want to use the denoiser in your MPEG-encoding pipeline, i.e. after \fBlav2yuv\fP and before \fBmpeg2enc\fP. If you're generating multiple resolutions of the same video, e.g. DVD and VCD, experience shows that it's acceptable to run \fBy4mdenoise\fP before \fByuv2lav\fP, but you should still use the spatial-filter (e.g. \fBy4mspatialfilter\fP, \fByuvmedianfilter\fP) in the MPEG-encoding pipeline, to try to smooth away JPEG encoding artifacts. .SH AUTHOR The bulk of the \fBy4mdenoise\fP code, and this manual page, was written by Steven Boswell . .SH FURTHER INFO If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: .BR \fImjpeg\-users@lists.sourceforge.net\fP For more info, see our website at .BR \fIhttp://mjpeg.sourceforge.net/\fP .SH SEE ALSO .BR mjpegtools (1), .BR mpeg2enc (1), .BR yuvdenoise (1), .BR yuvmedianfilter (1) mjpegtools-2.1.0/docs/pnmtoy4m.10000755000175000017500000001160312216627211017016 0ustar glowwormglowworm.\" .TH "pnmtoy4m" "1" "28 April 2004" "MJPEG Tools Team" "MJPEG tools manual" .SH "NAME" pnmtoy4m \- Convert PNM/PAM images to YUV4MPEG2 stream .SH "SYNOPSIS" .B pnmtoy4m .RI [ options ] .I [ filename ] .SH "DESCRIPTION" \fBpnmtoy4m\fP converts one or more raw PPM, PGM, PBM, or PAM images into a YUV4MPEG2 stream ready for further processing by other video tools. These three (or four) image formats are collectively referred to as "PNM images". Output is to stdout to facilitate piping to other MJPEG tools. The size of the output frame(s) is determined from the (first) input image. Input is a 'raw' format PNM image, read from stdin or from the optional filename. The input may contain multiple PNM images concatenated together; \fBpnmtoy4m\fP will read and process them sequentially. All images must have identical size and format. Input images can be interpreted as whole progressive frames, pairs of interleaved fields, or as sequential fields (read in pairs of images) to be output as either interlaced or progressive frames. PPM and PGM images must have 8 bits per channel (i.e. 'maxval' must be 255). PPM input images should be in the usual R'G'B' colorspace. They are converted to the Y'CbCr colorspace (ITU-R BT.601) before being output to a "4:4:4" (non-subsampled) YUV4MPEG2 stream. If chroma subsampling is required (e.g. to 4:2:0 for MPEG), the output should be further piped through a program such as \fBy4mscaler\fP. PGM images should be in the standard full-range ([0,255]) grayscale colorspace. PGM and PBM images will be converted to BT.601 luma and output as "MONO" (luma-only) YUV4MPEG2 streams. The PAM format is a newer superset of the PNM formats; the precise contents of a PAM image is defined by the TUPLTYPE header tag. \fBpnmtoy4m\fP handles TUPLTYPE "GRAYSCALE" as PGM, "RGB" as PPM, and "RGB_ALPHA" as PPM with an 8-bit alpha channel. (The alpha channel is converted to BT.601 luma as is appropriate for YUV4MPEG2 streams.) \fBpnmtoy4m\fP and \fBy4mtopnm\fP are inverses of each other; you can pipe the output of one into the other, and vice-versa. Note that the colorspace operations are lossy in both directions. And, when converting to PNM, information on interlacing and sample aspect ratio is lost (but can be reconstructed by supplying command-line arguments to \fBpnmtoy4m\fP). .SH "OPTIONS" \fBpnmtoy4m\fP accepts the following options: .TP 5 .BI \-o " num" Frame offset: skip output of the first 'num' frames. (default: 0) .TP 5 .BI \-n " num" Output a total of 'num' output frames. Use '0' to specify all frames. (default: 0) .TP 5 .BI \-B Interpret data as being BGR rather than RGB. .TP 5 .BI \-r Repeat last input frame until output is complete. If '-n 0' is also specified, last input frame will be repeated forever. .TP 5 .BI \-D " x" Treat each PNM image as a single (de-interleaved) field instead of a full frame. The argument specifies the interpretation: t - the first image is a top-field b - the first image is a bottom-field With this option, two input images will be required per output frame. Be careful: mismatched "-I" and "-D" options can invert the temporal or spatial order of the fields (or both). .TP 5 .BI \-F " n:d" Set framerate encoded in output stream, as an exact integer ratio. (default: 30000:1001) Common rates are: 24000:1001 - NTSC 3:2 pulldown converted film 24:1 - native film 25:1 - PAL/SECAM 30000:1001 - NTSC video 50:1 - PAL field rate 60000:1001 - NTSC field rate .TP 5 .BI \-A " n:d" Set pixel aspect ratio encoded in output stream, as an exact integer ratio. (default: 1:1) Common ratios are: 1:1 - square pixels (computer graphics) 10:11 - CCIR-601 NTSC 59:54 - CCIR-601 PAL .TP 5 .BI \-I " x" Set the output interlacing mode, encoded in the output stream. (Default is to match "-D" if given, or 'p' if not.) p - progressive, non-interlaced t - top/upper-field-first interlaced b - bottom/lower-field-first interlaced .TP 5 .BI \-v " [0,1,2]" Set verbosity level. 0 = warnings and errors only. 1 = add informative messages, too. 2 = add chatty debugging message, too. .SH "EXAMPLES" .hw pnmtoy4m yuvplay tgatoppm To convert a file containing a single PPM file into a stream of 15 (identical) frames: .RS 5 pnmtoy4m -n 15 -r some-image.ppm .RE To convert a series of Targa format images (in the current directory) to a YUV4MPEG2 stream displayed by yuvplay: .RS 5 ls *.tga | xargs -n1 tgatoppm | pnmtoy4m | yuvplay .RE .SH "AUTHOR" This manual page was written by Matt Marjanovic. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP .TP For more info, see our website at .I http://mjpeg.sourceforge.net/ .SH "SEE ALSO" .BR pam (5), .BR pbm (5), .BR pgm (5), .BR pnm (5), .BR ppm (5), .BR y4mtopnm (1), .BR mjpegtools (1), .BR mpeg2enc (1), .BR y4mscaler (1), .BR yuv2lav (1), .BR yuvplay (1) mjpegtools-2.1.0/docs/lavrec.10000755000175000017500000002415712216627207016520 0ustar glowwormglowworm.TH "lavrec" "1" "27 August 2003" "MJPEG Tools Team" "MJPEG tools manual" .SH NAME lavrec \- Record MJPEG-video from a zoran/video4linux-device .SH SYNOPSIS .B lavrec .RI [ options ] .IR filename(s) .SH DESCRIPTION \fBlavrec\fP can be used to record video in MJPEG format (either quicktime or AVI) from a zoran video-capture device, such as the Miro/Pinnacle DC10(+), the Iomega Buz or Linux Media Labs' LML33, or from a generic video4linux device, such as the cheap Bt848 or Bt878 based TV-cards that are being sold in every computer shop around the corner. .SH OPTIONS \fBlavrec\fP accepts the following options: .TP 8 .B filename The file to record to (*.avi, *.qt). Use a % to record to multiple files (using file%02d.avi will record to file00.avi, file01.avi, etc). You can also give more than one filename, which will have the same effect. This will avoid problems resulting from filetype or filesystem size limits. AVI, for example, has a 2 GB limit, as does ext2fs in 2.2.x kernels. .TP 8 .BR \-\-software\-encoding By default, lavrec will capture in a mode that is only suitable for recording from hardware MJPEG devices. Using this option will make lavrec use software\-JPEG\-encoding (using libjpeg) which enables MJPEG\-video\-capture from many generic video4linux devices (such as Bt848/Bt878\-based ones). .TP 8 .BR \-\-software\-encoding\-yuvp This option adds support for the EM28XX USB driver. As this driver is V4L2. As the original BTTV software implementation assumes that the driver supports V4L it will not work with the EM28XX driver, not even with the V4L1 emulation layer. This option enables two things: It enables the V4L2 calls to make interaction with this driver possible It select the cards YUV Packed format and converts this in software to YUV Planar The process is after this the same as for the BTTV driver. ome things of note are the fact that the EM28XX driver expects 48KHz audio recording. If you choose slower things will work, but a lot of deleted/inserted frames will occur. The lower the sample rate, the worse this problem gets. Recording at 48KHz is therefore recommended. This code was tested and found working with a DVC100 Pinnacle Dazzle. This option should work with any EM28XX, but this hasnt been tested. It might work for any other V4L2 device that outputs YUV packed format, this has however not been tested. Feedback would be appreciated. .TP 8 .BR \-f/\-\-format " [" a | A | q | m ] The format in which the video should be saved to the harddisk. a - MJPEG AVI A - MJPEG AVI with fields exchanged q - Quicktime .br By default, lavrec will look at the extension of the first file (*.avi, *.qt) and choose a format based on that. .TP 8 .BR \-i/\-\-input " [" p | P | n | N | s | S | t | T | f | a ] or .TP 8 .BR \-i/\-\-input " input[:norm] The recording source and the video source standard format. p - PAL through Composite or 1st Bt8x8 input P - PAL through SVHS- or 2nd Bt8x8 input t - PAL through TV-tuner- or 3rd Bt8x8 input n - NTSC through Composite or 1st Bt8x8 input N - NTSC through SVHS- or 2nd Bt8x8 input T - NTSC through TV-tuner- or 3rd Bt8x8 input s - SECAM through Composite or 1st Bt8x8 input S - SECAM through SVHS- or 2nd Bt8x8 input f - SECAM through TV-tuner- or 3rd Bt8x8 input a - (or every other letter) Autosense (default) .br The input can be specified using either single letters or an input number with an optional norm, where the number specifies the n'th input of the card, ranging from 1 to 10. Using a numerical input is necessary when using input four or higher with a card that has more than three inputs, for instance the AverMedia 6 Eyes. When using numeric input with the norm it must contain the whole norm name; valid names are pal, ntsc and secam. You can use numeric input selection for cards with only three inputs, too, which most Zoran based cards has. "-i\ 2:pal" used with a Buz would be equivalent to "-i\ P", recording from the S-Video input in PAL format. .TP 8 .BI \-d/\-\-decimation " num" Recording decimation, either 1, 2 or 4. This will decimate the size of the recorded video horizontally and vertically. To use different horizontal and vertical decimations, use two numbers, the first one being the horizontal and the second one being the vertical (-d 12). \fBNote:\fP this option can only be used during hardware recording. .TP 8 .BI \-g/\-\-geometry " WxH(+X+Y)" \fBFor hardware recording:\fP An X\-style geometry string, giving the geometry of the undecimated subframe to record. The default is the full frame, so 720x576/480+0+0 for Buz/LML33\-users and 640x480+0+0 or 768x576+0+0 for DC10(+)-users. \fBFor software recording:\fP The size of the video to be captured. Currently, width and height need to be a multiple of 16. You always capture the full frame since most video4linux devices don\'t support subframe capture. .TP 8 .BI \-q/\-\-quality " num" Quality of the JPEG\-video to be recorded (in percent). This must be a number between 0 and 100. Lower quality should generally mean lower filesize, higher quality will take more diskspace but will give more detailed perfectness in the resulting recorded video. Default is 50%. .TP 8 .BI \-C/\-\-channel " LIST:CHAN" Choose the channel to record from (xawtv-style). By default, lavrec will just use the current TV channel. .TP 8 .BI \-t/\-\-time " num" Recording time in seconds. The default is unlimited. To stop capturing video while recording, use Ctrl-C. .TP 8 .B \-S/\-\-single\-frame Single-frame capture mode. This means that one can capture individual frames from the capture device. .TP 8 .BI \-T/\-\-time\-lapse " num" time-lapse factor, which means that only every th frame is saved to the recording file. .TP 8 .B \-w/\-\-wait If this option is given, lavrec will wait for the user to press enter before starting to record. .TP 8 .B \-B/\-\-batch This option turns off all possible interactivity options and limits console output as much as possible. Useful for cron/scheduled recordings. .TP 8 .BI \-a/\-\-audio\-bitsize " num" Audio size in bits, either 0, 8 or 16 (default). 0 means no audio. .TP 8 .BI \-r/\-\-audio\-bitrate " num" Audio sampling rate in Hz. This must be a sampling rate which is supported by the soundcard. Often-supported audio sampling rate values are 11025, 22050 or 44100 (default). .TP 8 .B \-s/\-\-stereo Capture in stereo. By default, lavrec captures in mono. .TP 8 .BI \-l/\-\-audio\-volume " num" Recording level. This must be a value between 0 (no sound) and 100 (loud recording). \-1 (default) means to not touch the mixer settings at all. .TP 8 .B \-m/\-\-mute Mute sound output while recording. This can be useful when recording sound from the microphone to disable echos. This option is disabled by default. .TP 8 .BR \-R/\-\-audio\-source " [" l | m | c ] Recording source, either (l)ine-in, (m)icrophone or (c)d-rom. The default is to record from line-in (l). .TP 8 .BR \-U/\-\-use\-read Use the read() system call rather than the mmap() system call for audio recording. This may fix many audio recording problems. .TP 8 .BR \-c/\-\-synchronization " [" 0 | 1 | 2 ] Audio/video synchronization level efforts. (0) means no synchronization, (1) means that lavrec will replicate frames for lost frames. (2) means that lavrec will replicate frames for lost frames and do sync correction. Default is 2. .TP 8 .BI \-n/\-\-mjpeg-buffers " num" Number of MJPEG-buffers. Default is 32. Try changing this number if you have many lost frames. .TP 8 .BI \-b/\-\-mjpeg-buffer-size " num" MJPEG buffersize in kilobytes. The default is 256 kB. .TP 8 .BI \-\-max\-file\-size " num" The maximum file size per JPEG file. By default, lavrec uses the maximum possible size for that specific recording format. .TP 8 .BI \-\-max\-file\-frames " num" The maximum number of frames per per JPEG file. By default, the number of frames is only limited by other factors, such as maximum file size. .TP 8 .BI \-\-file\-flush " num" Flush the file to disk after every num frames captured. .TP 8 .BI \-v/\-\-verbose " num" Verbosity level (0, 1 or 2). Default is 0. .SH ENVIRONMENT The following environment variables can be recognized by lavrec: .TP 8 .B LAV_VIDEO_DEV The video device. Default is /dev/video .TP 8 .B LAV_AUDIO_DEV The audio device. Default is /dev/dsp .TP 8 .B LAV_MIXER_DEV The mixer device. Default is /dev/mixer .SH OUTPUT Lavrec will output the current recording state. Typically, this looks like: .br 0.06.14:22 int: 00040 lst:0 ins:0 del:0 ae:0 td1=0.014 td2=0.029 .br The first part is the time that has been spent recording (hours \- minutes \- seconds \- frames). .B int is the interval (in milliseconds) between two captured frames (this should be around 40 for PAL/SECAM and 33 for NTSC). .B lst is the number of lost frames. .B ins and .B del are the number of frames inserted and deleted for sync correction. .B ae is the number of audio errors. .B td1 and .B td2 are the audio/video time-difference (out\-of\-sync'ness). .SH TYPICAL RECORDING SESSIONS Okay, that's a lot of options. Now how would I normally record video? Let's assume you want to record at VCD resolution (352x288) from PAL source. You might want some higher quality than default (80%). You use default audio options and record to an AVI file. That having said, your recording command line would look like: .TP 8 .B From hardware MJPEG devices (S\-video input) lavrec --format=a --input=P --quality=80 --decimation=2 /path/to/file.avi .TP 8 .B From normal video4linux devices lavrec --software-encoding --format=a --input=p --quality=80 --geometry=352x288 /path/to/file.avi .SH BUGS lavrec should be able to detect automatically whether to use software JPEG encoding or whether to use the card's hardware JPEG encoding features (if available). Besides that, software JPEG encoding seems, for some people, to cause small out-of-sync'ness. SMP support for JPEG encoding is currently work-in-progress. .SH AUTHOR This man page was written by Ronald Bultje. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: .br \fImjpeg\-users@lists.sourceforge.net\fP .br .br For more info, see our website at .br \fIhttp://mjpeg.sourceforge.net/\fP .SH SEE ALSO .BR mjpegtools (1), .BR lavplay (1) mjpegtools-2.1.0/docs/yuvmedianfilter.10000755000175000017500000000602012216627211020433 0ustar glowwormglowworm.TH "yuvmedianfilter" "1" "24 February 2003" "y4mutils" "MJPEG tools manual" .SH "NAME" yuvmedianfilter \- A filter for yuv images produced by the mjpeg tools .SH "SYNOPSIS" .B yuvmedianfilter .RB [ \-r .IR num ] .RB [ \-R .IR num ] .RB [ \-t .IR num ] .RB [ \-T .IR num ] .RB [ \-I .IR num ] .RB [ \-f ] .RB [ \-w .IR num ] .RB [ \-s .IR num ] .RB [ \-v .IR num ] .RB [ \-h ] .SH "DESCRIPTION" \fByuvmedianfilter\fP is designed to enhance/filter images. It takes the input from STDIN and writes output to STDOUT. .br This filter looks around the current point for a radius and averages the values that fall inside a threshold. So the image is softened and the edges become more sharp. If the input material is noisy (it is always noisy but you do not always see it) the output images are improved and the encoder spends less bandwidth encoding noise. The more sophisticated version of image filtering is yuvdenoise. But you can use both programs in the encoding procces. It cannot process a recorded file and write the improved version to another file. .SH "OPTIONS" \fByuvmedianfilter\fP accepts the following options: .TP 5 .BI \-r " num" Radius for luma median (default: 2 pixels) .TP 5 .BI \-R " num" Radius for chroma median (default: 2 pixels) .TP 5 .BI \-t " num" Trigger threshold for luma (default: 2 [0=disable]) .TP 5 .BI \-T " num" Trigger threshold for chroma (default: 2 [0=disable]) .TP 5 .BI \-I " num" Interlacing type (0=no, 1=yes, default: taken from yuv stream) .TP 5 .BI \-f Fast mode, i.e. the threshold is ignored, and a simple mean of the surrounding values is calculated. .TP 5 .BI \-w " num" In fast mode, the weight given to the current value versus the surrounding values. Default is 8. .br Note that certain combinations of radii and weights have been optimized to be even faster -- radius 1 and weight 2.667, radius 1 and weight 8, and radius 2 and weight 8. .TP 5 .BI \-c " num" In slow mode, more than this fraction of the pixels must be within the threshold; otherwise the pixel is simply the weighted mean of pixels within a radius of 1. Default is 0.33333. .TP 5 .BI \-s " num" Number of beginning frames to skip. The first num frames are written to stdout unfiltered. This is useful for resuming an interrupted job without having to duplicate work. .TP 5 .BI \-v " num" Verbosity level (0, 1 or 2) .TP 5 .BI \-h Print out a help message .SH BUGS It is slow. Using a radius greater than the default of 2 is painfully slow. .SH "AUTHOR" This man page was written by Bernhard Praschinger. .br The yuvmedianfilter program was written by Mike Bernson, and adapted to the yuv4mpeg2 stream header format by Steven M. Schultz. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP .TP For more info, see our website at .I http://mjpeg.sourceforge.net .SH "SEE ALSO" .BR mjpegtools (1), .BR jpeg2yuv (1), .BR lav2yuv (1), .BR mpeg2enc (1), .BR ppmtoy4m (1), .BR yuv2lav (1), .BR yuvdenoise (1), .BR yuvscaler (1) mjpegtools-2.1.0/docs/yuvfps.10000644000175000017500000001023112216627211016554 0ustar glowwormglowworm.TH "yuvfps" "1" "8 Jan 2006" "MJPEG Tools Team" "MJPEG tools manual" .SH NAME yuvfps \- Converts to a different frame rate .SH SYNOPSIS .B yuvfps .RB [ -r .IR Num:Den ] .RB [ -s .IR Num:Den ] .RB [ -i .IR Interlacing ] .RB [ -I .IR Interlacing ] .RB [ -c ] .RB [ -n ] .RB [ -w ] .RB [ -v\ 0 - 2 ] .RB [ -h ] .SH DESCRIPTION \fByuvfps\fP is a general (UP or DOWN) resampling utility that is provided to allow the generation of video streams with the frame rates required for each standard video format. \fByuvfps\fP reads a YUV4MPEG stream from the standard input and outputs a YUV4MPEG stream to the standard output in which frames from the original ones are skipped (downsampling) or duplicated (upsampling). This allows for other mjpegtools that require a specific frame rate to process the stream. \fByuvfps\fP uses by default Bresenham's algorithm to do the resampling so that the new video stream is similar to the original one. Note, however, that downscaling is a non-reversible operation because frames are dropped. Moreover, the resulting video stream may not have the exact same duration as the original one if the new frame rate is not a whole multiple of the original rate. As an alternative to simply dropping or duplicating frames each output frame/field can be produced as a weighted average of the two temporally closest input frames/fields. In this mode, \fByuvfps\fP can also change the interlacing mode of the stream. \fByuvfps\fP also can "fix" the framerate specified in the YUV4MPEG header. This allows for the generation of effects (fast-forwarding, slow motion) and also when the source stream has some framerate that is very close, but not exactly, the rate required for some standard video (for example, 24.9 vs 25). .SH OPTIONS .TP .B -r \fBNum:Den\fP .IP Specifies the resulting stream frame rate. .TP .B -s \fBNum:Den\fP .IP Ignores the frame rate in the input stream and assumes this frame rate for the input stream. .TP .B -i \fBInterlacing\fP .IP Specifies the interlacing mode of the resulting stream. The interlacing mode can be changed only when using the weighted average resampling mode (the -w option). .IP p - progressive (non-interlaced) .br t - top-field first .br b - bottom-field first .TP .B -I \fBInterlacing\fP .IP Ignores the interlacing mode information in the input stream and assumes this interlacing mode for the input stream. The possible values are the same as for the -i option. .TP .B -c .IP Changes the stream header frame rate and interlacing mode in the output stream but copies frames from the original stream without changes. The -r and -i options specify the frame rate and interlacing mode for the output stream header. .TP .B -n .IP By default yuvfps tries to find a normalized framerate. Some programs create framerates like: 29969909:1000000 which is actually th typical NTSC framerate of 30000:1001. yuvfps prints out the normalizes values and the original when it starts. If you think the normalized value is not correct and want yuvfps to use the original given number you have to add that option. So yuvfps does not try to normalize the values. .TP .B -w .IP Produce each output frame/field as a weighted average of the two temporally closest input frames/fields instead of simply dropping or duplicating frames. The blending of two adjacent frames/fields reduces visible stepping compared to the default drop/duplicate algorithm but as a drawback it makes fast moving objects appear blurred and is much slower. .TP .B \-v " [0,1,2]" .IP Set verbosity level. 0 = warnings and error messages only. 1 = add informative messages, like the framerate conversation information. 2 = add chatty debugging message, too. .SH AUTHOR This man page was written by Alfonso García-Patiño Barbolani. .br Johannes Lehtinen added information about the weighted average resampling mode and the related options. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP .TP For more info, see our website at .I http://mjpeg.sourceforge.net/ .SH SEE ALSO .BR yuvscaler (1), .BR mjpegtools (1), .BR lavpipe (1), .BR lav2yuv (1) .BR mpeg2enc (1) mjpegtools-2.1.0/docs/lavplay.10000755000175000017500000001751712216627207016716 0ustar glowwormglowworm.TH "lavplay" "1" "6 December 2001" "MJPEG Tools Team" "MJPEG tools manual" .SH NAME lavplay \- Playback and edit MJPEG video .SH SYNOPSIS .B lavplay .RI [ options ] .I lavfile1 [lavfile2 ... lavfileN] .SH DESCRIPTION \fBlavplay\fP can be used to playback video in MJPEG format (either quicktime or AVI) on a zoran video-capture device, such as the Miro/Pinnacle DC10(+), the Iomega Buz or Linux Media Labs' LML33, or in software mode (using SDL). It also provides mechanisms for non-destructive editting video using an interactive front-end such as \fBglav\fP(1). See .B SEARCHING AND EDITING below for details. .SH OPTIONS \fBlavplay\fP accepts the following options: .TP 8 .BR \-p/\-\-playback " [" S | C | H ] The playback mode to be used. 'S' means software\-playback using SDL. 'H' means hardware\-playback on the monitor (on\-screen). 'C' means hardware\-playback to the video-out of the zoran video-capture device. Obviously, 'C' and 'H' only work on computers with zoran video\-capture devices. .TP 8 .B \-Z/\-\-full\-screen Full-screen playback. This works if SDL- or onscreen-playback is chosen. .TP 8 .BI \-\-size " NxN" Size of the video window (default: size of the input video) when using software (SDL) or hardware onscreen playback .TP 8 .BI \-a/\-\-audio " num" When play audio, 0 means never, or sum of 1: while playing forward, 2: while playing reverse, 4: even fast playing, 8: while pausing .br (default: 7: forward/reverse/fast). If 8(pausing) was contained, lavplay will be very noisy, but useful when you want to edit by sound. .TP 8 .B \-z/\-\-zoom Zooms the video to fit the screen as good as possible. .TP 8 .B \-x Exchange fields of an interlaced video. Try this if the video looks weird. It shouldn't be necessary with stuff captured using lavrec(1) but could be needed for other sources. .TP 8 .BI \-s/\-\-skip " num" Skip seconds of video at the beginning. .TP 8 .B \-x/\-\-exchange\-fields Invert field order (for videos which are recorded with wrong field order interlacing settings) .TP 8 .B \-F/\-\-flicker Disable stills flicker reduction. This is useful if you want to see stills exactly as they were recorded rather than flicker-free! .TP 8 .BR \-c/\-\-synchronization " [" 0 | 1 ] Enables (1) or disables (0) the use of sync corrections. Basically, you almost certainly want this. Disabling is really there for diagnostic purposes and not much else. .TP 8 .BI \-H/\-\-H\-offset " num, " \-V/\-\-V-offset " num" Horizontal (-H) and vertical (-V) offset when using hardware-playback. Offset plus width or height should be smaller than or equal to the playback device's maximum allowed size (DC10+: 640x480 or 768x576, LML33/Marvel/Buz: 720x480/576). .TP 8 .BI \-\-s\-x\-offset " num, " \-\-s\-y\-offset " num" Offset for the video window (from top left screen corner) when using hardware onscreen playback in non\-fullscreen mode. .TP 8 .BI \-\-display " :x.x" When using hardware fullsreen video playback (\-pH), this setting can be used to specify the video display (default: :0.0) to use for video display. .TP 8 .B \-q/\-\-no\-quit Makes lavplay stay alive at the end of the video (lavplay won't quit). Use 'q' on the command line to quit (see below, \fBSEARCHING AND EDITING\fP). .TP 8 .B \-g/\-\-gui\-mode Enables GUI-mode. This is used by glav and Linux Video Studio. It will output the current position in the video each frame, so that the glav or LVS can keep track of where we are in the video which is being played back. .TP 8 .B \-P/\-\-preserve-pathnames This is used by glav and Linux Video Studio. When editlists are created the original pathnames for files are used and not the canonicalised pathnames from the root directory. Useful if you've got things like automounters active that make directories with the same non-canonical name have different canonical names on different machines. .TP 8 .BI \-U/\-\-use-write Use the write() system call rather than the mmap() system call for audio writing to the sound device. This may fix some audio playback problems. .TP 8 .BI \-n/\-\-mjpeg\-buffers " num" Number of MJPEG-buffers. Default is 32. Try changing this number if you have many lost frames. .TP 8 .BI \-v/\-\-verbose " num" Verbosity level (0, 1 or 2) .SH ENVIRONMENT VARIABLES The following environment variables can be recognized by lavrec: .TP 8 .B LAV_VIDEO_DEV The video device. Default is /dev/video .TP 8 .B LAV_AUDIO_DEV The audio device. Default is /dev/dsp .SH SEARCHING AND EDITING \fBlavplay\fP can do more than simple plain playback. It is also intended to be controlled using commands sent via stdin from a front-end like .BR glav(1) or similar, more sophisticated tools. The most significant aspect of this functionality is the ability to create \fIedit list\fP files giving the playback sequence of an editted version of the input video. The edit list file can be read by any of the mjpegtools(1) (including lavplay!) wherever an actual video file would be acceptable. Such edit lists record only the original source file and start and stop frames of the components of the editted video editting rather than the video itself. As such editting leaves the original files unchanged and requires only tiny amounts of data-movement. The drawback is that for the edit list to work the original files must remain unchanged, and that interactive play may be jumpy due to the playback sequence "skipping about" between different parts of the original video sequence. If a stand-alone consolidated versions of editted video is required it can be produced by running the lavtrans(1) utility on the edit list. Edit list files are plain text with a very simple syntax to allow easy manual editting using a text-editor or writing of scripted editting tools. .SH "STDIN COMMANDS" The commands accepted on standard input sre as follows (and can of course be entered directly by command-line junkies): .TP 8 .B +, \- Goes to next/previous frame. Only makes sense when the video is paused. .TP 8 .B pN Sets playback speed to N (N=..., -1, 0, 1, ...) .TP 8 .B a[01] Enables/disables audio playback .TP 8 .B sN if N is a number, this means to go to frame N. if N is prefixed by a + or -, this means to go N frames back- or forward. .TP 8 .B om editlist [N1 N2 [N3 N4]] Opens a movie or editlist. A second and third argument can specify to only open a specific range of frames from this video (N1=-1 means whole video). N3 and N4 can specify to show only a specific range of frames from the frames which were just opened (useful for trimming). .TP 8 .B w[as] file Save the current editlist (a) or the current selection (s) to a file. .TP 8 .B q Quit lavplay. .TP 8 .B e[ou] N1 N2 Cuts (u) or copies (o) frames N1-N2 from the current editlist into an internal selection. .TP 8 .B ep Pastes the contents of the selection into the current position in the editlist. .TP 8 .B em N1 N2 N3 Moves frames N1-N2 to position N3 in the video. .TP 8 .B ed N1 N2 Deletes frames N1-N2 from the editlist. .TP 8 .B ea video N1 N2 N3 Adds frames N1-N2 of the video into position N3 within the editlist. N1=-1 means to add the whole video. .TP 8 .B es N1 N2 Sets the current viewable frames within the whole video to N1-N2. This is useful for trimming. .SH BUGS Editlists record absolute pathnames. This more or less forces manual editting of the pathnames in them if it is desired to move editlists and source video files. lavplay really ought to make a decent job of detecting what playback options are feasible (on-screen hardware, video-out port hardware, software) and set the default playback mode appropriately. Alas, it does not. .SH AUTHOR This man page was written by Ronald Bultje. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: .br \fImjpeg\-users@lists.sourceforge.net\fP .br .br For more info, see our website at .br \fIhttp://mjpeg.sourceforge.net/\fP .SH SEE ALSO .BR mjpegtools (1), .BR lavrec (1), .BR glav (1) mjpegtools-2.1.0/docs/y4mscaler.10000644000175000017500000005775512051575455017162 0ustar glowwormglowworm.\" .TH "y4mscaler" "1" "February 14, 2003" "y4mtools" "y4mtools manual" .hw y4mscaler .SH "NAME" y4mscaler \- Scale/crop/translate a YUV4MPEG2 stream .SH "SYNOPSIS" .B y4mscaler .RI [ options ] .I < Y4Mstream > Y4Mstream .SH "DESCRIPTION" \fBy4mscaler\fP is a general-purpose video scaler which operates on YUV4MPEG2 streams, as produced and consumed by the MJPEGtools such as \fBlav2yuv\fP and \fBmpeg2enc\fP(1). \fBy4mscaler\fP is meant to be used in a pipeline. Thus, input is from stdin, and output is to stdout. The essential function of \fBy4mscaler\fP is to scale a specified "active" region of the input stream (the source) into a specified active region of the output stream (the target). Pixels outside of the active region of the source are ignored; pixels outside of the active region of the target are filled with a background color. The source may additionally have a matte applied to it; pixels outside the source matte are set to a separately specified background color. \fBy4mscaler\fP correctly handles chroma subsampling, and thus it can also perform chroma subsampling conversions. The YUV4MPEG2 stream format supports three varieties of 4:2:0 subsampling, as well as 4:1:1, 4:2:2, 4:4:4, a 4:4:4 modes with an alpha channel, and a monochrome luma-only mode. (See "NOTES ON CHROMA MODES AND SUBSAMPLING".) \fBy4mscaler\fP can perform simple interlacing conversions: switching from top-field-first to bottom-field-first and vice-versa (by lossily discarding the first field), and creating a progressive stream from interlaced by discarding every other field (effectively halving the vertical resolution). The source and target are defined by many, many parameters, but \fBy4mscaler\fP has many, many heuristics built-in to automagically set them appropriately. Most source parameters are taken from the input stream header. Remaining source and target parameters which are not specified by the user are guessed in a sane manner. \fBy4mscaler\fP includes preset parameters for a number of common target streams: DVD, VideoCD (VCD), SuperVCD (SVCD), associated still image formats, and DV. .SH "EXAMPLES" To create a stream appropriate for use in an SVCD: .RS 5 y4mscaler -O preset=svcd .RE To create a stream for a VideoCD (a non-interlaced format), from a DV source (an interlaced format), shifting the input frame 4 pixels to the left: .RS 5 y4mscaler -I ilace=bottom-only -I active=-4+0cc -O preset=vcd .RE To take a widescreen NTSC DV source, and convert it to a letterboxed stream, with blue bars on the top and bottom: .RS 5 y4mscaler -O sar=ntsc -O bg=RGB:0,0,255 .RE To take a widescreen NTSC DV source, and convert it to a "fullscreen" stream (i.e. the sides are clipped, just like on TV): .RS 5 y4mscaler -O sar=ntsc -O infer=clip .RE To take a centered, letterboxed NTSC source, and convert it to a widescreen (16:9) format stream for DVD, with the black bars removed: .RS 5 y4mscaler -O preset=dvd -O sar=ntsc_wide -O infer=clip .RE To take the center 100x100 pixel chunk of an NTSC DV stream, surround it with a 20-pixel blue border, and blow that up to a full-screen SuperVCD stream: .RS 5 y4mscaler -I active=140x140+0+0cc -I matte=100x100+0+0cc -I bg=RGB:0,0,255 -O preset=svcd .RE .SH "OPTIONS" The first three options, -v, -V, and -h, are simple straightforward options which take either no arguments or one numeric argument. .TP 5 .BI \-v " [0,1,2]" Set verbosity level. 0 = warnings and errors only. 1 = add informative messages, too (default). 2 = add chatty debugging message, too. .TP 5 .BI \-V Show version information and exit. .TP 5 .BI \-h Show a help message (synopsis of options). .P The -I, -O, and -S options each take one argument of the form .I parameter=value, which specify parameters for the input, output, and scaling, respectively. These options can be used repeatedly to specify multiple parameters. The parameter names and values are not case-sensitive. Definitions of the form "parameter=[AAA|BBB|CCC]" mean that only one of the listed keywords AAA, BBB, or CCC may be chosen. Succeeding options will override earlier ones. .TP 5 .BI \-I " input_parameter" .RS Specify parameters for the source/input stream. All '-I' arguments are evaluated in order, and later arguments on the command-line will override earlier ones. All '-I' arguments are evaluated before any '-O' arguments. .TP 3 .BI active= WxH+X+Yaa Specify the active region of the source frame, which is scaled to fit the active region of the target frame. The default is the full frame. (The "WxH" may be omitted, and the region size defaults to the size of of the source frame.) W and H are width and height. X and Y are the offset of the anchor point. "aa" is the anchor mode (default: TL); see "NOTES ON REGION GEOMETRY" for details. .br Example: active=200x180+30+24cc .TP 3 .BI matte= WxH+X+Y Specify a matte region for the source frame. All pixels outside of this region are set to the source background color. The default matte is the full frame. (The "WxH" may be omitted, and the region size defaults to the size of of the source frame.) W and H are width and height. X and Y are the offset of the anchor point. "aa" is the anchor mode (default: TL); see "NOTES ON REGION GEOMETRY" for details. .br Example: matte=200x180+30+24cc .PP .BI bg= RGB:r,g,b .br .BI bg= YCBCR:y,cb,cr .br .BI bg= RGBA:r,g,b,a .br .BI bg= YCBCRA:y,cb,cr,a .RS 3 Set the source background color. Pixels outside of the source's matte region are set to this color. One can specify the color as either a R'G'B' or Y'CbCr triplet. For example, the default color is black, specified as "bg=YCBCR:16,128,128" or "bg=RGB:0,0,0". The 'A' versions will set the alpha (transparency) value of the color. The alpha range is [0,255] for RGBA and [16,235] for YCBCRA. The default is fully-opaque (255 for RGBA, 235 for YCBCRA). .RE .TP 3 .BR norm= [ NTSC | PAL | SECAM ] Specify the "norm" of the source stream. This is normally inferred from the stream header. .TP 3 .BR ilace= [ NONE | TOP_FIRST | BOTTOM_FIRST | TOP_ONLY | BOTTOM_ONLY ] Specify the interlacing used by the source stream. NONE, TOP_FIRST, and BOTTOM_FIRST correspond to non-interlaced, top-field-first, and bottom-field-first. These values are normally inferred from the stream header; specifying them will override the stream header. .br TOP_ONLY and BOTTOM_ONLY specify that only the top or bottom field of each frame should be used; the other field is discarded. These options can only be used with an interlaced input, and cause the interlaced stream to be treated as a progressive stream with half the height. (This is particularly useful in creating a VCD from a full-size interlaced input stream.) These two special options can only be used when the source is a pure progressive stream (as opposed to a YUV4MPEG2 "mixed-mode" stream). .TP 3 .BR chromass= [ 420JPEG | 420MPEG2 | 420PALDV | 444 | 422 | 411 | mono | 444alpha ] Specify the chroma subsampling mode used in the source stream. This parameter is inferred from the stream header, so this keyword should almost never be used in a source specification. The only useful reason to specify this keyword is to override one variety of 4:2:0 with another. Any other use will cause processing to fail. .PP .BI sar= N:D .br .BR sar= [ NTSC | PAL | NTSC_WIDE | PAL_WIDE ] .RS 3 Specify the sample-aspect-ratio of the source stream. The value can either be or numeric ratio (such as "10:11") or one of the keywords, which correspond to the CCIR-601 values for 4:3 or 16:9 displays, respectively. This parameter is usually inferred from the stream header. .RE .RE .TP 5 .BI \-O " output_parameter" .RS Specify parameters for the destination/output stream. All '-O' arguments are evaluated in order, and later arguments on the command-line will override earlier ones. All '-O' arguments are evaluated after any '-I' arguments. .PP .BI size= WxH .br .B size=SRC .RS 3 Set the output/target frame size, as width W and height H in pixels. Use the keyword \fBSRC\fP to specify that the target frame size should match the source frame size. .RE .TP 3 .BI active= WxH+X+Yaa Specify the active region of the target frame, into which the active region of the source frame is scaled. The default is the full target frame. (The "WxH" may be omitted, and the region size defaults to the size of of the target frame.) W and H are width and height. X and Y are the offset of the anchor point. "aa" is the anchor mode (default: TL); see "NOTES ON REGION GEOMETRY" for details. .br Example: active=200x180+30+24cc .PP .BI bg= RGB:r,g,b .br .BI bg= YCBCR:y,cb,cr .br .BI bg= RGBA:r,g,b,a .br .BI bg= YCBCRA:y,cb,cr,a .RS 3 Set the target background color. Pixels outside of the target's active region are set to this color. One can specify the color as either a R'G'B' or Y'CbCr triplet. For example, the default color is black, specified as "bg=YCBCR:16,128,128" or "bg=RGB:0,0,0". The 'A' versions will set the alpha (transparency) value of the color. The alpha range is [0,255] for RGBA and [16,235] for YCBCRA. The default is fully-opaque (255 for RGBA, 235 for YCBCRA). .RE .TP 3 .BR ilace= [ NONE | TOP_FIRST | BOTTOM_FIRST ] Specify the interlacing used by the target stream. NONE, TOP_FIRST, and BOTTOM_FIRST correspond to non-interlaced, top-field-first, and bottom-field-first. The default if to match the source stream. .br If the source and target are both interlaced, but with different modes (i.e. one is bottom-first, and the other is top-first), then \fBy4mscaler\fP will convert one mode to the other by dropping the first source field. .TP 3 .BR chromass= [ 420JPEG | 420MPEG2 | 420PALDV | 444 | 422 | 411 | mono | 444alpha ] Specify the chroma subsampling mode to be used in the target stream. The default is to match the source mode. See "NOTES ON CHROMA MODES AND SUBSAMPLING" for more information. .PP .BI sar= N:D .br .BR sar= [ SRC | NTSC | PAL | NTSC_WIDE | PAL_WIDE ] .RS 3 Specify the sample-aspect-ratio of the source stream. The value can either be or numeric ratio (such as "10:11") or one of the keywords, which correspond to the CCIR-601 values for 4:3 or 16:9 displays, respectively. The keyword \fBSRC\fP specifies that the target SAR should match the source. .RE .PP .BI scale= N/D .br .BI Xscale= N/D .br .BI Yscale= N/D .RS 3 Set the scaling ratios, as a fraction; for example, scale=1/2. "scale=" sets both X and Y factors simultaneously. "Xscale=" and "Yscale=" can be used to set them independently. .RE .TP 3 .BR infer= [ PAD | CLIP | PRESERVE_X | PRESERVE_Y ] Set the mode used to infer scaling ratios from active regions and SAR's. The keywords are mutually exclusive. The default is PAD. .TP 3 .BR infer= [ SIMPLIFY | EXACT ] Set whether the above heuristic uses exact ratios, or whether it is allowed to slightly adjust active regions to simplify the scaling ratios. The keywords are mutually exclusive. The default is SIMPLIFY. .TP 3 .BR align= [ TL | TC | TR | CL | CC | CR | BL | BC | BR ] Set the alignment point between the source and target active regions. The keywords specify "top-left", "top-center", "top-right", etc. The specified corner or point from the source region will be mapped to the same spot in the target region; and cropping or padding which is applied to the active regions will preserve this mapping. The default is CC, for "center-center", i.e. the source and target regions are mutually centered. The keywords are mutually exclusive. The default is CC. See "NOTES ON SOURCE AND TARGET ALIGNMENT" for details. .PP .BR preset= [ VCD | CVD | SVCD | DVD | DVD_WIDE | DV | DV_WIDE | .br .BR " " " " SVCD_STILL_HI | SVCD_STILL_LO | VCD_STILL_HI | VCD_STILL_LO | .br .BR " " " " ATSC_720P | ATSC_1080I | ATSC_1080P ] .br .RS 3 Use preset target parameters for several common output formats. Individual parameters can be overridden by following with more "-O" settings. These keywords are mutually exclusive. For the details of what settings these preset keywords imply, see "NOTES ON TARGET PRESETS". .TP 3 .BR VCD " - 352-wide VideoCD, progressive" .TP 3 .BR CVD " - 352-wide (full-height) ChinaVideoDisc" .TP 3 .BR SVCD " - 480-wide SuperVCD" .TP 3 .BR DVD " - 720-wide DVD" .TP 3 .BR DVD_WIDE " - 720-wide DVD, anamorphic pixels" .TP 3 .BR DV " - 720-wide DV (bottom-field-first, 4:1:1)" .TP 3 .BR DV_WIDE " - 720-wide DV, anamorphic pixels" .TP 3 .BR SVCD_STILL_HI " - high-resolution SVCD still image" .TP 3 .BR SVCD_STILL_LO " - low-resolution SVCD still image" .TP 3 .BR VCD_STILL_HI " - high-resolution VCD still image" .TP 3 .BR VCD_STILL_LO " - low-resolution SVCD still image" .TP 3 .BR ATSC_720P " - ATSC 720p (progressive HDTV)" .TP 3 .BR ATSC_1080I " - ATSC 1080i (interlaced HDTV)" .TP 3 .BR ATSC_1080P " - ATSC 1080p (HDTV)" .RE .RE .TP 5 .BI \-S " scaling_parameter" .RS Specify parameters for the scaling engine. All '-S' arguments are evaluated in order, and later arguments on the command-line will override earlier ones. .TP 3 .B mode=MONO Request monochrome scaling. The source is treated as monochrome and its chroma channels are ignored. The chroma channels of the output stream will be zeroed to yield a grayscale output. .TP 3 .B mode=LINESWITCH Request line swapping. Effectively, the top and bottom fields within each frame will be swapped. This may help with malformed streams that have a messed up spatial order. This option is only effective on interlaced streams. .TP 3 .BI scaler= scaler-name Use a particular scaling engine. The available engines are: .RS 'default' \- Matto's Generic Scaler (the default) .RE .TP 3 .BI option= scaler-option Specify an option for the chosen scaling engine. To see all the available options, use "option=help". .RS 3 .PP For the default engine, the available \fIscaler-option\fPs select the filter kernel: .RS 3 .TP 3 .BR box " - box filter" .TP 3 .BR linear " - linear interpolation" .TP 3 .BR quadratic " - quadratic interpolation" .TP 3 .BR cubic " - cubic interpolation, Mitchell-Netravali spline" .TP 3 .BR cubicCR " - cubic interpolation, Catmull-Rom spline" .TP 3 .BR cubicB " - cubic interpolation, B-spline" .TP 3 .BR cubicK4 " - Keys 4th-order cubic" .TP 3 .BR sinc:N " - sinc with Lanczos window, N cycles" .RE .PP To select kernels for the x and y scaling directions independently, use two kernel names separated by a comma, e.g. \fIoption=box,quadratic\fP. .PP \fBsinc:N\fP will give the best quality results (least aliasing), but is the slowest. The quality improves with larger values of N, as does processing time. \fBcubic\fP is generally regarded in the graphics world as the 3rd-order cubic spline with the best trade-off between smoothing and aliasing. \fBbox\fP yields the worst quality results (most aliasing), but is the fastest. The default kernel is \fBcubicK4\fP, which has a flatter passband and sharper cutoff than \fBcubic\fP. (It requires the same computational power as \fBsinc:4\fP, but produces less ringing artifacts.) .RE .RE .SH "NOTES ON TARGET PRESETS" The following table details the settings provided by the various target "preset=" keywords. When two values are given the primary is for NTSC streams; the value in {braces} is for PAL streams. If interlace value is unspecified, it is inherited from the source, otherwise the indicated target interlacing is required. .nf Preset Frame Size Interlace SAR Subsampling ----------------------------------------------------------------------- VCD 352x240{288} none 10:11{59:54} 4:2:0-JPEG CVD 352x480{576} --- 20:11{59:27} 4:2:0-MPEG2 SVCD 480x480{576} --- 15:11{59:36} 4:2:0-MPEG2 DVD 720x480{576} --- 10:11{59:54} 4:2:0-MPEG2 DVD_WIDE 720x480{576} --- 40:33{118:81} 4:2:0-MPEG2 DV 720x480{576} bottom-first 10:11{59:54} 4:1:1 DV_WIDE 720x480{576} bottom-first 40:33{118:81} 4:1:1 SVCD_STILL_HI 704x480{576} none 10:11{59:54} 4:2:0-MPEG2 SVCD_STILL_LO 480x480{576} none 15:11{59:36} 4:2:0-MPEG2 VCD_STILL_HI 704x480{576} none 10:11{59:54} 4:2:0-JPEG VCD_STILL_LO 352x240{288} none 10:11{59:54} 4:2:0-JPEG ATSC_720p 1280x720 none 1:1 4:2:0-MPEG2 ATSC_1080i 1920x1080 (required) 1:1 4:2:0-MPEG2 ATSC_1080p 1920x1080 none 1:1 4:2:0-MPEG2 .fi .SH "NOTES ON REGION GEOMETRY" Active and matte regions are specified using a geometry string of the form "WxH+X+Yaa". The "WxH" part specifies the size of the region, as a Width and Height in pixels. (In some cases, the "WxH" may be omitted, and the region size defaults to the full frame size.) The "+X+Y" specifies the position of the region, as an offset relative to the anchor point specified by "aa". The "aa" code can be one of .BR TL ", " TC ", " TR ", " CL ", " CC ", " CR ", " BL ", " BC ", or " BR . These stand for "top-left", "top-center", ..., "bottom-center", "bottom-right". These codes are not case-sensitive. The "+X+Y" specifies the offset of the region's anchor point from the frame's anchor point. For example, "+20+30TL" means that the top-left corner of the region will be offset 20 pixels to the right and 30 pixels down from the top-left corner of the frame. The offset values can also be negative. For example, "-4+0CC" means that the center (vertical and horizontal) of the region is offset 4 pixels to the left of the center of the frame. The default anchoring point for geometry strings is \fBTL\fP, i.e. the top-left corner. .SH "NOTES ON SOURCE AND TARGET ALIGNMENT" Often, the source and target active regions do not match exactly. This happens when, using the given or calculated scaling ratios, the source region scales to a different size or shape than the target region. In this case, the source and target regions are mutually clipped, so that only the portion of the source which fits will be scaled into the target. Before any clipping or padding, the source and target regions are aligned so that the points specified via the "align=aa" parameter coincide. The "aa" code specifies an anchor point as described above. For example, "align=BC" specifies that the bottom-center of the source region should get mapped to the bottom-center of the target region. In other words, the source region will be horizontally centered and vertically aligned to the bottom of the target region before clipping: .nf ---------------- source |abcdefghijklmn| ---|opqrstuvwxyz01|--- target ---------------- | |234567890ABCDE| | |234567890ABCDE| | |FGHIJKLMNOPQRS| | |FGHIJKLMNOPQRS| | |TUVWXYZabcdefg| | |TUVWXYZabcdefg| ---------------------- ---------------- Before Mutually Clipped .fi If instead "align=TR" were centered, the source would be clipped in a different place, and scaled into a different region of the target frame: .nf ---------------------- ---------------- | |abcdefghijklmn| |abcdefghijklmn| | |opqrstuvwxyz01| |opqrstuvwxyz01| | |234567890ABCDE| |234567890ABCDE| ------|FGHIJKLMNOPQRS| ---------------- target |TUVWXYZabcdefg| source ---------------- Before Mutually Clipped .fi The default alignment mode is "CC", that is, the source and target are mutually centered. .SH "NOTES ON SCALE FACTOR INFERENCE" If the X and Y scaling factors are not explicitly provided, \fBy4mscaler\fP will infer the factors from the source and target active regions and sample aspect ratios (SAR's). If the active regions are not compatible shape-wise (given the SAR's), the source and target regions will be clipped or padded according to one of four policies. The policy is selected using the "infer=" parameter and one of the keywords .BR PAD ", " CLIP ", " PRESERVE_X ", or " PRESERVE_Y . (The default is \fBPAD\fP.) .RS 3 .TP 3 .B PAD Pick scaling factors which will pad the source, but ensure that all of the source image content ends up in the target. .TP 3 .B CLIP Pick scaling factors which will clip the source, but which will fill the target region as much as possible. .TP 3 .B PRESERVE_X Pick scaling factors which preserve as much of the horizontal source content as possible. .TP 3 .B PRESERVE_Y Pick scaling factors which preserve as much of the vertical source content as possible. .RE .PP The policy is further affected by a choice of two other keywords, .BR SIMPLIFY ", or " EXACT . (The default is \fBSIMPLIFY\fP.) .RS 3 .TP 3 .B EXACT Calculate exact scaling factors. .TP 3 .B SIMPLIFY Adjust the active regions and scaling factors (within 10% or so), to simplify the ratios as much as possible. (For example, crop or pad slightly to achieve a ratio of 2/1 rather than 45/22.) .RE .SH "NOTES ON CHROMA MODES AND SUBSAMPLING" \fBy4mscaler\fP can convert streams from one chroma subsampling mode to another. Such conversions are always lossy operations, even if the overall frame is undergoing 1/1 scaling. \fBy4mscaler\fP will infer the source's subsampling mode from tags in the input stream header. The target presets ("preset=XXX") will attempt to set the target subsampling mode appropriately. Otherwise, by default the target subsampling mode will match the source. One can explicitly set the subsampling mode for the source and/or the target by using the "chromass=" parameter. \fBy4mscaler\fP is capable of reading and writing streams in the 4:4:4, 4:2:2, 4:1:1, and 4:2:0 (all three varieties) subsampling modes. The first three, however, are a relatively new addition to the YUV4MPEG2 standard, and many MJPEGtools will fail to process them correctly, if at all. smil2yuv and raw2yuv can produce native 4:1:1 streams from NTSC DV video, which can then be converted to 4:2:0 by \fBy4mscaler\fP before further processing by other tools. If the source has an alpha-channel (i.e. 444ALPHA mode) and the target does not, the alpha channel will simply be discarded. On the other hand, if the target has an alpha-channel but the source does not, a constant alpha-channel will be created using the alpha-value of the target's background color (as set by "-O bg="). The default is fully-opaque. Similarly, if the target has chroma channels but the source does not (i.e. a luma-only MONO stream), then the chroma channels in the output will be set according to the background color. .RE .SH "NOTES ON ANOMALOUS INTERLACE MIXTURES" The YUV4MPEG2 format allows for "mixed-mode interlacing" streams, which may contain a mixture of progressive and interlaced frames. Each frame is tagged as temporally interlaced or progressive, and vertically-subsampled frames (4:2:0 formats) are further tagged as spatially interlaced or not. Unfortunately, this allows for the possibility of \fBanomalous\fP frames, which happen to be temporally interlaced (fields sampled at different times) but spatially progressive (subsampling performed across entire frame), or vice-versa. The only reasonable thing to do with such anomalous frames is to vertically-upsample the chroma, essentially making to problem go away as quickly as possible. \fBy4mscaler\fP will only process such frames if the target output format is non-vertically-subsampled (e.g. 4:4:4, 4:2:2, etc.) and no other vertical processing is required. Otherwise \fBy4mscaler\fP will bail on processing in midstream when it encounters an anomalous frame. If there is any possibility of encountering such an error, \fBy4mscaler\fP will print a warning when processing begins. .RE .PP .SH "EXIT STATUS" .IP 0 Successful program execution. .IP 1 Usage, syntax, or operational error. .SH "AUTHOR" This manual page is copyright 2005 by Matthew Marjanovic. .br Feel free to direct any questions, remarks, problems, or bug reports concerning this tool to \fI.\fP .TP For more info, see our website at: .UR http://www.mir.com/DMG/ .UE .TP For more information on MJPEGtools, consult: .UR http://mjpeg.sourceforge.net/ .UE .hw mjpegtools yuv2lav mpeg2enc ppmtoy4m yuvplay yuvscaler .SH "SEE ALSO" .BR mjpegtools (1), .BR yuv2lav (1), .BR mpeg2enc (1), .BR ppmtoy4m (1), .BR raw2yuv (1), .BR smil2yuv (1), .BR yuvplay (1), .BR yuvscaler (1) mjpegtools-2.1.0/docs/yuvycsnoise.10000644000175000017500000000410612216627211017624 0ustar glowwormglowworm.TH "yuvycsnoise" "1" "5 February 2002" "MJPEG Tools Team" "MJPEG tools manual" .SH NAME yuvycsnoise \- Noise filter specialized for NTSC Y/C separation noise .SH SYNOPSIS .B yuvycsnoise .RB [ \-t ] .RB [ \-m\ t | b | i | c ] .RB [ \-S .IR MIN ] .RB [ \-T .IR ERRT [\fB,\fP MAXT ]] .RB [ \-B .IR ERRB [\fB,\fP MAXB ]] .RB [ \-I .IR ERRI [\fB,\fP MAXI ]] .RB [ \-C .IR ERRC [\fB,\fP MAXC ]] .SH DESCRIPTION If video capture hardware has only a poor Y/C separator, at vertical stripe (especially red/blue), noises appear which seem checker flag and bright/dark invert per 1 frame. \fByuvycsnoise\fP reduces noises of this type. .SH OPTIONS \fByuvycsnoise\fP accepts the following options: .TP 8 .BI \-t test. Instead of noise reduction, noises will be marked as black pixel. .TP 8 .BI \-m \ METHOD (default: \fBtbic\fP). .br Select method. \fIMETHOD\fP is string in which each character mean method. \fBt\fP: 'triframe' method of luma noise reduction. \fBb\fP: 'biframe' method of luma noise reduction. \fBi\fP: 'infield' method of luma noise reduction. \fBc\fP: chroma noise reduction. use 3 frames as 'triframe'. .TP 8 .BI \-S \ MIN (default: 4). .br Set minimum threshold of luma/chroma difference which is treated as noise. .TP 8 .BI \-T \ ERRT \fR[\fP, MAXT\fR]\fP (default: 32,255). .TP 8 .BI \-B \ ERRB \fR[\fP, MAXB\fR]\fP (default: 32,255). .TP 8 .BI \-I \ ERRI \fR[\fP, MAXI\fR]\fP (default: 16,255). .TP 8 .BI \-C \ ERRC \fR[\fP, MAXC\fR]\fP (default: 12,255). .br Set threshold of luma/chroma difference of each methods. \fIERRx\fP is maximum error of luma/chroma of pixels around target pixel, which should be same if target contain noise. \fIMAXx\fP is maximum threshold of luma/chroma difference of target pixel from luma/chroma after noise reduced. .SH AUTHOR \fByuvycsnoise\fP was written by Kawamata/Hitoshi. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP .TP For more info, see our website at .I http://mjpeg.sourceforge.net/ .SH SEE ALSO .BR mjpegtools (1) mjpegtools-2.1.0/docs/y4mtoppm.10000755000175000017500000000563112216627211017024 0ustar glowwormglowworm.\" .TH "y4mtoppm" "1" "28 April 2004" "MJPEG Tools Team" "MJPEG tools manual" .SH "NAME" y4mtoppm \- Convert YUV4MPEG2 stream to PPM images .SH "SYNOPSIS" .B y4mtoppm .RI [ options ] .SH "DESCRIPTION" \fBy4mtoppm\fP converts a YUV4MPEG2 stream into a sequence of raw PPM images. Output is to stdout (but feel free to have the shell redirect to a file). Input is read from stdin, like all other YUV4MPEG2 filters and tools. YUV4MPEG2 streams contain frames using the Y'CbCr colorspace (ITU-R BT.601). \fBy4mtoppm\fP will convert each pixel to the usual R'G'B' colorspace used for computer graphics. YUV4MPEG2 streams may (often!) have subsampled chroma planes. \fBy4mtoppm\fP can upsample "4:2:0 JPEG" streams using a simple, lousy algorithm. Better results will be obtained using a filters such as \fBy4mscaler\fP(1) which are capable of general-purpose subsampling operations. \fBy4mtoppm\fP will fail on streams which have chroma subsampling modes other than 4:4:4 or 4:2:0-JPEG. For interlaced streams, these operations are performed on each field individually. Fields can be output as separate PPM images in time-order (default), or interleaved into full-frame images. If multiple PPM images are generated, they are simply output one after another. If you want to turn such a "multi-image" PPM stream/file into individual files, use \fBpnmsplit\fP. (Some PNM filters can process multi-image files/streams; however, many written before June 2000 will only process the first image.) \fBy4mtoppm\fP and \fBppmtoy4m\fP are inverses of each other; you can pipe the output of one into the other, and vice-versa. Note that the colorspace (and subsampling) operations are lossy in both directions. And, when converting to PPM, information on interlacing and sample aspect ratio is lost (but can be reconstructed by supplying command-line arguments to \fBppmtoy4m\fP). .SH "OPTIONS" \fBy4mtoppm\fP accepts the following options: .TP 5 .BI \-L For interlaced streams, output a single PPM image for each frame, containing two interleaved fields. (Otherwise, two PPM images will be generated for each frame; one per field.) .TP 5 .BI \-v " [0,1,2]" Set verbosity level. 0 = warnings and errors only. 1 = add informative messages, too. 2 = add chatty debugging message, too. .SH "EXAMPLES" .hw y4mtoppm pnmsplit lav2yuv To turn the first 15 frames of an (MJPEG or DV) AVI file into individual PPM files: .RS 5 lav2yuv -f 15 your-video.avi | y4mtoppm | pnmsplit - "your-video-%d.ppm" .RE .SH "AUTHOR" This man page was written by Matt Marjanovic. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP .TP For more info, see our website at .I http://mjpeg.sourceforge.net/ .SH "SEE ALSO" .BR ppm (5), .BR pnm (5), .BR ppmtoy4m (1), .BR mjpegtools (1), .BR mpeg2enc (1), .BR lav2yuv (1), .BR pnmsplit (1), .BR y4mscaler (1) mjpegtools-2.1.0/docs/lavpipe.10000644000175000017500000001562112216627207016675 0ustar glowwormglowworm.TH "lavpipe" "1" "2 June 2001" "MJPEG Tools Team" "MJPEG tools manual" .SH "NAME" lavpipe \- creates raw YUV streams from pipe list scripts .SH "SYNOPSIS" .B lavpipe .RB [ -o .IR num ] .RB [ -n .IR num ] .I pipe-list .SH "DESCRIPTION" lavpipe reads a script file called 'pipe list' that is of a similar structure as the edit lists that can be fed into lav2yuv. For info about the pipe list format see below. The pipe list defines several video sources and filters that are combined by lavpipe to produce a single output YUV stream on stdout (which for example can be compressed and stored to disk via .BR mpeg2enc "(1) or " yuv2lav "(1))." .SH "OPTIONS" The command line options are used to output a specific part of the resulting video stream. That means you can tell lavpipe how many frames to skip and how many frames to deliver from that point on. .TP .BI "-o " num This is the frame offset of the output video. The first .I num frames of the resulting video simply are neither calculated nor written to stdout. This value defaults to 0. .TP .BI "-n " num This is the frame count. If the input files or streams defined in the pipe list script are long enough, the output will be of exactly .I num frames length. A value of 0 means that all frames until the last one as defined in the pipe list will be written out, as long as there's some input (0 is the default). .TP .I pipe-list This is name of the pipe list file that lavpipe will 'execute'. For information about this file's format see below. .TP .B -? Display a synopsis of the command syntax. .SH "EXAMPLES" .TP lavpipe -o 100 -n 25 film.pli would calculate and output to stdout frames 100 to 124 as defined in film.pli (in PAL this would be the 5th second of the film). .TP lavpipe input.pli | yuv2lav -q80 output.avi would save the movie assembled by lavpipe as a single AVI file. .SH "USAGE" In this section the format of lavpipe's input files the pipe list scripts is explained. If you need some examples or a more detailed tutorial, please read the .BR mjpegtools "(1) manpage's section about" .BR "CREATING MOVIE TRANSITIONS" ". and the file" .I README.lavpipe that should be included in the distribution. Also feel free to contact us via the mailing list (see below). A pipe list contains of two parts: the YUV .B source list and after this, as many .B sequence descriptions as wanted. It always begins with the following two lines: .TP .B LAV Pipe List This is the first line in every pipe list script. It is used as a simple test if lavpipe really was given a pipe list script and not your PhD thesis as input. .TP .BR NTSC | PAL This is the second line in every pipe list and can be either PAL or NTSC, depending on what video standard you use. I don't remember if this is used at the moment. .PP Now follows the .BR "source list" : .TP .I num This is the number of input commands. lavpipe will read the next .I num lines and interpret them as input stream commands. .TP .IR command \ ( num \ times) This is a valid command line with two variables $o and $n that will be replaced by lavpipe with the offset and number of frames that the program has to output. Example: .br .B lav2yuv -o $o -f $n input.avi .PP .RB "Thus, an example " "source list" " could look like this:" .br .B 2 .br .B lav2yuv -o $o -f $n scene1.avi .br .B lav2yuv -o $o -f $n scene2.avi after this you can append as many .B sequence descriptions as needed. Each of them is built up as follows: .TP .I num The number of frames that this sequence will last. .TP .I num The number of inputs that will be used in this sequence. This number must of course be less than or equal to the number of inputs that are defined above. .TP .IR idx " [" ofs "] (" num " times)" These are the indices to the sources that are defined at the beginning of the file (first source is 0) with an optional frame offset (i.e. sequence starts with .RI "frame number " ofs " of this input.) - this value" defaults to 0. Example: .br .B 0 150 .TP .I command This is a valid command line to a YUV filter tool that reads .IR num " input streams and writes one output stream, combining" its inputs. Optionally, the filter tool can be given the two $o and $n variables that will be replaced by lavpipe as in the source commands (see above). For further info read .IR README.lavpipe " or the documentation for the filter" programs (if available). An example filter could look like this: .br .B transist.flt -o 0 -O 255 -s $o -n $n -d 50 .br And if the sequence only has one input that simply should be copied to the output, you can use a dash instead of a command line: .br .B - .PP And here's an example for a complete pipe list that implements a transistion from scene1.avi to scene2.avi .sp .B REMOVE THE COMMENTS AFTER The # .sp .B LAV Pipe List .br .B PAL .br .B 2 .br .B lav2yuv -o $o -f $n scene1.avi .br .B lav2yuv -o $o -f $n scene2.avi .br .BR 50 " # first sequence: 50 frames" .br .BR 1 " # contains one input:" .br .BR "0 0" " # scene1.avi, offset 0" .br .BR - " # simple output" .br .BR 25 " # second sequence: 25 frames" .br .BR 2 " # contains two inputs:" .br .BR "0 50" " # scene1.avi, offset 50" .br .BR 1 " # scene2.avi, offset 0" .br .BR "transist.flt -o 0 -O 255 -s $o -n $n -d 50" " # transistion" .br .BR 50 " # third sequence: 50 frames" .br .BR 1 " # contains one input:" .br .BR "1 25" " # scene2.avi, offset 25" .br .BR - " # simple output" .SH "BUGS" I'm sure there are enough of them. lavpipe often accepts malformed pipe lists and then writes out a video that was all but intended - without warning. .sp .B The mention of $n above is wrong. At one time there were two parameters but now a program is allowed to produce as many frames as it wants. THe author of the program hard coded, for reasons unknown, $n to be 0. .SH "NOTES" There are also some serious limitations in the system, such as frame-by-frame processing. But as the goal when writing lavpipe was the simplicity of the pipeline, other tools will have to be written to do more interesting tasks. .br But I want to note that it is very well possible to write a pipe list that combines several files, and then use that pipe list as an input for another pipe list by simply using the lavpipe command in the source list (see above) - this can be already used to do some nice things, if you have some nice filters. .sp .B Comments are NOT allowed in pipelist files. The comments (text after #) above are for illustration only. .SH AUTHOR This man page was written by Philipp Zabel. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP .TP For more info, see our website at .I http://mjpeg.sourceforge.net .SH "SEE ALSO" .BR lav2yuv (1), .BR lavplay (1), .BR lavrec (1), .BR mpeg2enc (1), .BR yuv2lav (1), .BR yuvscaler (1) mjpegtools-2.1.0/docs/lavtools.sgml0000644000175000017500000000462707423032505017701 0ustar glowwormglowworm ]> MJPEG Tools' user manual This is release 0.1 of the MJPEG Tools' user's guide. 2001 Gregory McLean This documentation is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Linux Audio and Video Tools The lavtools suite of programs are for MJPEG recording and playback with simple cut and paste editing of the recorded files. Also supported is MPEG compression of the recorded files to various standards. Only the "lav" programs have been written from scratch, the rest of the tools are from diverse free software originals. They have been modified to work with the lav tools edit lists and AVI/Quicktime files. Some have had more major performance and functionality enhancements. Whats included ... Authors &authors; mjpegtools-2.1.0/docs/y4mtopnm.10000755000175000017500000001302012216627211017011 0ustar glowwormglowworm.\" .TH "y4mtopnm" "1" "28 April 2004" "MJPEG Tools Team" "MJPEG tools manual" .SH "NAME" y4mtopnm \- Convert a YUV4MPEG2 stream to PNM images .SH "SYNOPSIS" .B y4mtopnm .RI [ options ] .SH "DESCRIPTION" \fBy4mtopnm\fP converts a YUV4MPEG2 stream into a sequence of raw PPM, PGM, or PAM images. (Technically, "pnm" comprises the PPM, PGM and PBM formats. PAM is a fourth format, which can effectively contain any of the other three, and more.) Output is to stdout (but feel free to have the shell redirect to a file). Input is read from stdin, like all other YUV4MPEG2 filters and tools. YUV4MPEG2 streams contain frames using the Y'CbCr colorspace (ITU-R BT.601). For 4:4:4 (color) streams, \fBy4mtopnm\fP will convert each pixel to the usual R'G'B' colorspace used for computer graphics, and produce PPM images. "MONO" (luma-only) streams will be converted to full-range [0,255] grayscale and output as PGM images. YUV4MPEG2 streams may (often!) have subsampled chroma planes, but \fBy4mtopnm\fP will not process them (except in the special 'flatten' mode; see below). Subsampled streams will need to be converted to 4:4:4 using a tool such as \fBy4mscaler\fP. If \fBy4mtopnm\fP is given a "444ALPHA" stream (4:4:4 video with an 8-bit alpha channel), the results depend on whether or not the "-P" option is specified. With "-P", it will produce PAM images with a TUPLTYPE of RGB_ALPHA, containing both color and alpha channel data. Without "-P", it will produce pairs of PPM and PGM images: a PPM for the color pixels followed by a PGM for the alpha channel data. (Such a sequence of interspersed PPM and PGM images cannot be later re-processed by \fBpnmtoy4m\fP. This feature is mostly for quick and easy stream debugging.) If multiple output images are generated, they are simply output one after another. If you want to turn such a "multi-image" stream/file into individual files, use \fBpnmsplit\fP. (Some PNM filters can process multi-image files/streams; however, many written before June 2000 will only process the first image.) \fBy4mtopnm\fP and \fBpnmtoy4m\fP are inverses of each other; you can typically pipe the output of one into the other, and vice-versa (except for the "444ALPHA" case noted above and the "mixed-mode" case noted below). Note that the colorspace operations can be lossy in both directions (due to range-compression and/or quantization). And, when converting to PNM, information on interlacing and sample aspect ratio of a stream is lost (but can be reconstructed by supplying command-line arguments to \fBpnmtoy4m\fP). .SH "OPTIONS" \fBy4mtopnm\fP accepts the following options: .TP 5 .BI \-P Produce PAM format output, instead of PPM and/or PGM. PAM can encode a superset of PNM, but is not yet understood by as many graphics programs. (Indeed, surprisingly few of the NetPBM tools seem to understand it.) .TP 5 .BI \-D Produce a separate output image for each field of each frame. (Otherwise, a single image per frame, containing two interleaved fields, is created.) If the input stream is interlaced, the field-images are output in temporal order, i.e. the first image of a bottom-field-first stream will be the bottom-field. If the stream is progressive or has "mixed-mode" interlacing, then the temporal order is ambiguous, and the top-field will always be output first. Note that it will \fInot\fP be possible to later use \fBpnmtoy4m\fP to reconstruct a "mixed-mode" stream from a sequence of PNM/PAM images. .TP 5 .BI \-f Produce a special 'flattened' output, most useful for analyzing and debugging streams. All the planes of a frame/field are tiled together into an enlarged PGM (or grayscale PAM) output image as follows: .nf +-----+ +-----+ 4:4:4 | Y | 4:4:4 w/alpha | Y | +-----+ +-----+ | Cb | | Cb | +-----+ +-----+ | Cr | | Cr | +-----+ +-----+ | A | +-----+ +-----+ 4:2:2, | Y | 4:2:0 +--+--+ +-----+--+--+ |Cb|Cr| 4:1:1 | Y |Cb|Cr| +--+--+ +-----+--+--+ +-----+ MONO | Y | +-----+ .fi In this mode, any YUV4MPEG2 chroma format is accepted, but no upsampling or colorspace conversion is performed. This is essentially just a reformatting/permutation of the original data from the input stream into a PGM image container. All the other command-line flags continue to have the same effect on output. .TP 5 .BI \-v " [0,1,2]" Set verbosity level. 0 = warnings and errors only. 1 = add informative messages, too. 2 = add chatty debugging message, too. .SH "EXAMPLES" .hw y4mtopnm pnmsplit lav2yuv To turn the first 15 frames of an (MJPEG or DV) AVI file into individual PPM files: .RS 5 lav2yuv -f 15 your-video.avi | y4mscaler -O chromass=444 | y4mtopnm | pnmsplit - "your-video-%d.ppm" .RE .SH "AUTHOR" This manual page was written by Matt Marjanovic. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP .TP For more info, see our website at .I http://mjpeg.sourceforge.net/ .SH "SEE ALSO" .BR pam (5), .BR pgm (5), .BR pnm (5), .BR ppm (5), .BR pnmtoy4m (1), .BR mjpegtools (1), .BR mpeg2enc (1), .BR lav2yuv (1), .BR pnmsplit (1), .BR y4mscaler (1) mjpegtools-2.1.0/docs/mplex.10000644000175000017500000002446511624123571016365 0ustar glowwormglowworm.TH "mplex" "1" "2 June 2001" "MJPEG Tools Team" "MJPEG tools manual" .SH "NAME" .LP .br mplex \- MPEG 1/2 program/system stream multiplexer .br .SH "SYNOPSIS" .B mplex .RB [ -f|--format .IR format_code ] .RB [ -i|--vdr-index] .IR index_pathname .RB [ -v|--verbose .IR num ] .RB [ -b|--video-buffer .IR video_buffer_size_kB [, .IR video_buffer_size_kB ...] ] .RB [ -L|--lpcm-params .IR params [, .IR params ... ] ] .RB [ -r|--mux-bitrate .IR muxed_bitrate_kbps ] .RB [ -l|--mux-limit .IR num ] .RB [ -O|--sync-offset .IR num[\fBms\fP|\fBs\fP|\fBmpt\fP] ] .RB [ -d|--subpicture-delay .IR [\fBms\fP|\fBs\fP|\fBmpt|\fBc\fP] [:stream-id] [, delay[:stream-id] ] .RB [ -R|--run-in .IR num ] .RB [ -V|--vbr] .RB [ -C|--cbr] .RB [ -s|--sector-size .IR sector_size_B ] .RB [ -p|--packets-per-pack .IR num ] .RB [ -h|--system-headers ] .RB [ -S|--max-segment-size .IR output_filesize_limit_MB ] .RB [ -M|--split-segment] .RB [ -?|--help ] .BI -o|--output \ output_pathname_pattern \ input_file... .SH "DESCRIPTION" Mplex is a general-purpose audio/video multiplexer for MPEG-1/MPEG-2. It accepts one or more MPEG-1/2 video stream, MPEG layer I/II/III, DTS, AC3 and LPCM audio streams and multiplexes them into a combined program/system stream according to the constraints specified. Many different types of output structure are supported along with presets for standard VCD and SVCD streams. These latter can be burned to CD using tools such as \fBvcdimager\fP(1) and played in stand-alone players. It is also capable of automatically splitting the output stream into chunks of a specified size either independently or at sequence end/start points in the input video stream. .SH "GENERAL FUNCTION LETTERS" .TP .BI -o|--output \ output_filename_pattern This mandatory option sets the pattern for the name(s) of output files. An integer format code (e.g. %d) in the name is replaced by the number of the file generated (see \fBprintf\fP(3)). .TP .BI -v|--verbose \ num Set verbosity level to \fInum\fP: 0 - warnings and errors only, 1 - information as well, 2 - really verbose. .TP .B -?|--help Display a synopsis of the command syntax. .br .SH "FUNCTION LETTERS" .TP .BI -f|--format \ format_code This command allows one of a number of convenient preset output formats or generic MPEG1 or MPEG2 output to be selected. For the generic formats other function letters can be used to control many aspects of the multiplexed stream. For VCD/SVCD/DVD compliant output the corresponding formats \fImust\fR be used as the standards require the multiplexer to enforce a variety of special constraints on the structure of the output stream. .IP 0 - Generic MPEG1. A simple general-purpose MPEG1 format primarily suitable for software decoders. Buffer sizes and VBR must be specified. Bit-rate can be auto-detected. 1 - VCD. Standard VCD. Overrides other option settings. 2 - User VCD. VCD format but buffer size, bit rate and VBR can be set manually. 3 - Generic MPEG2. Like 0 except MPEG2. 4 - SVCD. Standard SVCD. Overrides other option settings. 5 - User-rate SVCD. SVCD format but buffer size bit rate and VBR can be set. 6 - VCD Stills stream (mixed mode with hi-res and standard-res image streams multiplexed are supported). 7 - SVCD Stills stream. 8 - DVD (with NAV sectors). Don't get too excited. This is really a very minimal mux format. It includes empty versions of the peculiar VOBU start sectors DVD VOB's include. This is enough to persuade some hardware players to play the stream but is a long way from full DVD authoring. 9 - DVD. As above but without the empty VOBU sectors. .TP .BI -W|--workarounds \ workaround_flag\ \fR [, \fIworkaround_flag\fR ...] .br A comma-seperated list of flags that set special work-arounds for what are suspected to be parser Bugs in widely used players. No workarounds are (currently) implemented but history suggests this may change quickly ;-) .BI -i|--vdr-index \ index_pathname This tells mplex to generate an index file for the output in the format used by the 'vdr' (video disk recorder package). Useful if you want to write output into vdr's recordings directory for playback on your video recorder PC. This probably only useful in combination with -f 9. .TP .BI -r|--mux-bitrate \ num The total (non VBR) / peak (VBR) bit-rate of the output stream in k Bits/sec. If unspecified and not set by a preset it is automatically calculated from the input stream. .TP .BI -b|--video-buffer \ numlist A comma-seperateed list of video decoder buffer sizes in KB for the video streams (given in the order the video streams appear on the command line). The default is 46KB the (tiny) size specified for VCD. The size to use for SVCD is the (more reasonable) 230KB. If you are encoding for a half-decent software decoder it makes sense to push this up to 500K or more. .TP .BI -L|--lpcm-params .I samples_per_sec:channels:bits_per_sample .br [, .I samples_per_sec:channels:bits_per_sample ...] .br A comma-seperated list of paramter sets for the lpcm audio streams (given in the order the lpcm streams appear on the command line). Each parameter set comprises the sampling rate in Hz, the number of channels, and the number of bits per sample seperated by colons. For example, the default 48kHz two-channel 16-bit audio would be specified as 48000:2:16. .IP Note: these parameters are necessary because mplex expects raw LPCM audio data without any headers. That is: for each sample point a group of 16,20, or 24 bit amplitude values, one for each channel. Amplitude values are signed with the constituent bytes in big-endian (most significant bytes first) order. For 20 bit samples I am not sure but what documentation I have suggests such samples are padded at the lsb end so that they byte-align at the most significant bits. .TP .BI -l|--mux-limit \ num Multiplex limit. Multiplex only the specified number of seconds. Useful for tuning and debugging. .TP .BI -O|--sync-offset \ num[\fBms\fP|\fBs\fP|\fBmpt\fP|\fBc\fP] Set the presentation timestamp offset of video stream w.r.t. audio stream (video-audio) in mSec. This flag is used to produce a stream with synchronised audio/video when one stream started before/after the other. This is common when transcoding as the synchronisation information is typically lost during the (seperate) decoding/encoding of audio and video. .IP By appending 's', 'ms' or 'mpt' the offset can given in seconds, milliseconds or MPEG clock ticks (1/90000th of a second) respectively. If no suffix is given milliseconds are assumed. .TP .BI -d|--subpicture-delay \ num [\fBms\fP|\fBs|\fBmpt\fP|\fBc\fP] [:stream-id] [, delay[:stream-id]] Specify offset of timestamps (video-subpicture) in msec sec, mpt or clock-ticks. If no suffix is given milliseconds are assumed. .IP The intention of the adding subtitle support was to enable mplex to mux all streams necessary for a DVD so that the mpeg2 stream created can be used directly for further dvd creation. Currently only ps1 streams (like created by tcextract) are supported .IP Valid subtitle stream are in a range of 32-63 (including). You may want to specify each stream you mplex, use "," to delimit each stream. .IP \fBExample:\fP If you want to mux one video, one audio and two subtitle streams having delays of 500 and 1000 ms, the first shall have id 32, the second is 33 (Subtitle streams 0 and 1): .IP $ mplex -f 8 -o my_mpeg.mpeg -d 500:32,1000:33 video_in.mpv audio_in.m2a subtitle_0.ps1 subtitle_1.ps1 .TP .BI -R|--run-in \ num Set a non-default run-in (the time data is preloaded into buffers before decoding is scheduled) at the start of each sequence in video frame intervals. By default a run-in matching the specified size of the video and audio buffers in the decoder and the type of multiplexing (constant or variable bit-rate) is selected automatically. .TP .B -V|--vbr Force variable bit rate multiplexing even if selected profile defaults to constant-bit-rate. .TP .B -C||-cbr Force constant bit rate multiplexing even if selected profile defaults to variable bit-rate. .TP .BI -s|--sector-size \ num This option specifies the sector size of the output stream in bytes. .TP .BI -p|--packets-per-pack \ num This option specifies the number of packets per pack in the output stream. .TP .BI -S|--max-segment-size \ num This option specifies the maximum size of output files in MBytes (2^10) When the limit is reached a new file is started. The default is (0) unlimited. .IP Note: This option is .I not for splitting a long video across multiple VCD's or SVCD's. It simply splits a single long sequence into in a way that prevents bits of a video GOP(group of pictures) or audio frame being split between chunks. This is fine for formats like that used for DVDs where all stream parameters appear every GOP. However, for VCD / SVCD it won't work as the players expect each file to start a new MPEG sequence. For VCD / SVCD a different technique is used. If mplex encounters a sequence break (sequence end followed by start) in the input video stream it starts a new output stream and file at the sequence start. Thus to split a long video across VCD's/SVCD's you have to get the MPEG video encoder to introduce sequence splits at the right points (see mpeg2enc(1) for details of how to do this). .TP .B -M|--ignore-seqend-markers This flag makes mplex ignore sequence end markers embedded in the first video stream instead of switching to a new output file. This is sometimes useful splitting a long stream in files based on a -S limit that doesn't need a run-in/run-out like (S)VCD. .TP .B -h|--system-headers A system header is generated in every pack rather than just in the first. .SH "DIAGNOSTIC OUTPUT" When multiplexing using mplex you may get warning or error messages complaining about buffer underflow. This means that the bit-rate you have specified is simply too low to permit the video and audio to be played back without skipping. The fix is to either reduce the data-rate of the input material or increased the output stream bit-rate. .SH "BUGS" The multiplexer should handle MPEG(5.1) audio. .SH AUTHOR This man page was written by Andrew Stevens. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP For more info, see our website at \fIhttp://mjpeg.sourceforge.net\fP .SH "SEE ALSO" .BR mpeg2enc "(1), " mp2enc "(1), " lavrec "(1), " lavplay "(1), " .BR lav2yuv "(1), " lav2wav "(1), " yuvscaler "(1)" mjpegtools-2.1.0/docs/mjpegtools.10000644000175000017500000032747212217255472017434 0ustar glowwormglowworm.\" .TH "MJPEG tools" "MJPEG Linux Square" "MJPEG tools manual" .LP MJPEG HOWTO - An introduction to the MJPEG-toolsPraschinger Bernhardv2.00MJPEG capture/editting/replay and MPEG encoding toolset description .PP Introduction .PP I wrote this things down, because I had many sheets with notes on them. This should be some kind of summary of collected knowledge over a long period of time. Andrew Stevens helped with encoding and VCD knowledge and hints. .PP Mjpegtools is a set of programs that can do recording, playback, editing and eventual MPEG compression of audio and video under Linux. .PP Although primarily intended for use with capture / playback boards based on the Zoran ZR36067 MJPEG codec chip mjpegtools can easily be used to process and compress MJPEG video streams captured using xawtv using simple frame-buffer devices. .PP The HOWTO for the tools intended to give an an introduction to the MJPEG-tools and the creation of MPEG 1/2 videos. VCD, SVCD and DVD and the transcoding of existing mpeg streams. .PP For more information about the programs read the corresponding man-page. .PP Achtung es gibt auch eine deutsche Version bei: .PP There is also a manpage of this text. You can read it with \(rqman mjpegtools\(rq if installed. We also have a info version you should be able to read it with info .PP The text version of this text is available via cvs. You should get it with the tarball or the precompiled package (RPM and deb). .PP In the following picture you see the typical workflow when you record a video, cut it afterwards and encode it. In the picture you also see the connections to other programs. These parts are in grey. The parts in blue can be done with the mjpegtools. .PP Video encoding workflow .PP Unsorted list of useful Hints .PP You have to compile and install the mjpeg_play package, for this read the README & INSTALL.real an follow the hints from the configure script. If you do not want to compile it, you can download the mjpeg .RPM or .DEB package at Sourceforge, or if available use the one that comes with your distribution. .PP There is a script in the scripts/ directory. This script is something that shows you a way it can be done. It also creates (under certain circumstances) videos that look quite good. Better videos you will only get by tuning the parameters. .PP If you use a Linux kernel from the 2.4 series you will usually have to load the drivers for the Buz or DC10 or LML33 cards. You have to run the update script providing as option the name of your card you have. The script is usually in /usr/src/driver-zoran/. The zoran kernel driver below the kernel 2.4.4 do not work. You have to use the driver available from: .PP In the 2.6. Linux kernel is the driver for the zoran cards included, you just need to make sure that it is loaded correct. If you have a x64 machine and an kernel that is newer than 2.6.30 we'd be happy to hear that you are able to record from the zoran based card. I'm not soure if that combination works. .PP The driver for the Matrox Marvel card also works, more information about it: .PP If you compile the tools on a P6 based computer (PPro, P-II, P-III, P-4, Athlon,Duron) then never try to let them run on a P5 based computer (Pentium, Pentium-MMX, K6, K6-x, Cyrix, Via, Winchip). You'll get a \(rqillegal instruction\(rq and the program won't work. That is the same for the newer CPU as well. If you use specific optimizations be aware of them. .PP If lav2yuv dumps core then one possible cause is no dv support was included. To enable it make sure that libdv is installed on the system. This will be necessary if you are using a digital camera (or analog to DV converter such as the Canopus ADVC100 and converting the dv avi format into the MPEG format. .PP Start xawtv to see if you get an picture. If you want to use HW-playback of the recorded streams you have to start xawtv (any TV application works) once to get the streams played back. You should also check the settings of your mixer in the sound card. If you use v4l2 you should give mplayer a try to watch the picture .PP If you compile the tools on a platform other than Linux not all tools will work. Mjpegtools on a OS/X system for example will not have V4L (video4linux) capability. .PP Never try to stop or start the TV application when lavrec runs. If you start or stop the TV application lavrec will stop recording, or your computer could get \(rqfrozen\(rq\&. This is a problem of v4l (video4linux). .PP This problem is solved with v4l2. If you use v4l2 you can record the video and stop and start the tv application whenever you want. But v4l2 is currently (7. Jan. 2003) only supported for the zoran based cards (BUZ, DC10, DC10+, LML33) if you use the CVS driver from mjpeg.sf.net tagged with ZORAN_VIDEODEV_2. And this driver only works with the 2.4.20 kernel and the 2.5.* development kernel. .PP One last thing about the data you get before we start: .PP .DS .sp .ft RR .nf Audio: ( Samplerate * Channels * Bitsize ) / (8 * 1024) CD Quality:(44100 Samples/sec * 2 Chanels * 16 Bit) / (8 * 1024)=172,2 kB/sec The 8 * 1024 convert the value from bit/sec to kByte/sec Video: (width * height * framerate * quality ) / (200 * 1024) PAL HALF Size : (352 * 288 * 25 * 80) / (200 * 1024) = 990 kB/sec PAL FULL size : (720 * 576 * 25 * 80) / (200 * 1024) = 4050 kB/sec NTSC HALF size: (352 * 240 * 30 * 80) / (200 * 1024) = 990 kB/sec NTSC FULL size: (720 * 480 * 30 * 80) / (200 * 1024) = 4050 kB/sec .DE .fi .ec .ft P .sp .PP The 1024 converts the Bytes to kBytes. Not every card can record the size mentioned. The Buz and Marvel G400 for example can only record a size of 720x576 when using -d 1, the DC10 records a size of 384x288 when using -d 2. .PP When you add audio and video datarate this is what your hard disk has to be able to write constantly streaming, else you will have lost frames. .PP If you want to play with the \fB--mjpeg-buffer-size\fP\&. Remember the value should be at least big enough that one frame fits in it. The size of one frame is: (width * height * quality ) / (200 * 1024) = kB If the buffer is too small the rate calculation doesn't match any more and buffer overflows can happen. The maximum value is 512kB. .PP How video works and the difference between the video types is explained here: .PP There you also find how to create MPEG Still Images for VCD/SVCD. .PP A good description of DV (Digital Video) can be found here: .PP .SH Some books we found usefull .PP written in English: .nr ll +1 .nr t\n(ll 0 .if \n(ll>1 .RS .nr bi 1 .PP Digital Video and HDTV by Charles Poyton (ISBN 1-55860-792-7) .nr bi 1 .PP Digital Video Compression by Peter Symes (ISBN 0-07-142487-3) .nr bi 1 .PP Video Demystified by Keith Jack (ISBN 1-878707-56-6) .if \n(ll>1 .RE .nr ll -1 .PP written in German: .nr ll +1 .nr t\n(ll 0 .if \n(ll>1 .RS .nr bi 1 .PP Fernsehtechnik von Rudolf Maeusl (ISBN 3-7785-2374-0) .nr bi 1 .PP Professionelle Videotechnik - analoge und digitale Grundlagen von U. Schmidt (ISBN 3-540-43974-9) .nr bi 1 .PP Digitale Film- und Videotechnik von U. Schmidt (ISBN 3-446-21827-0) .if \n(ll>1 .RE .nr ll -1 .PP If you know some other really good book about that, write us! .PP Recording videos .PP .SH lavrec examples .PP Recording with lavrec looks like this: .PP \fB> lavrec -f a -i P -d 2 record.avi\fP .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "" .nr bi 1 .PP Should start recording now, .IP "-f a" .nr bi 1 .PP use AVI as output format, .IP "-i P" .nr bi 1 .PP use as input source the SVHS-In with PAL format, .IP "-d 2" .nr bi 1 .PP the size of the pictures are half size (352x288) .IP "record.avi" .nr bi 1 .PP name of the created file. .if \n(ll>1 .RE .nr ll -1 .PP Recording is finished by pressing Ctrl-C (on German Keyboards: Strg-C). Sometimes using \fB-f A\fP instead of \fB-f a\fP might be necessary .PP Other example: .PP \fB> lavrec -f q -i n -d 1 -q 80 -s -l 80 -R l -U record.avi \fP .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "" .nr bi 1 .PP Should start recording now, .IP "-f q" .nr bi 1 .PP use Quicktime as output format, .IP "-i n" .nr bi 1 .PP use Composite-In with NTSC format, .IP "-d 1" .nr bi 1 .PP record pictures with full size (640x480) .IP "-q 80" .nr bi 1 .PP set the quality to 80% of the captured image .IP "-s" .nr bi 1 .PP use stereo mode (default mono) .IP "-l 80" .nr bi 1 .PP set the recording level to 80% of the max during recording .IP "-R l" .nr bi 1 .PP set the recording source to Line-In .IP "-U" .nr bi 1 .PP With this lavrec uses the read instead of mmap for recording this is needed if your sound card does not support the mmap for recording. .if \n(ll>1 .RE .nr ll -1 .PP Setting the mixer does not work with every sound card. If you record with 2 different settings and both recordings are equally loud you should setup the mixer with a mixer program. After that you should use the \fB-l -1\fP option when you record using lavrec .PP The size of the image depends on the card you use. At full size (-d 1) you get these image sizes: BUZ and LML33: 720x576, the DC10 and DC30: 768x576 .PP Other example: .PP \fB> lavrec -w -f a -i S -d 2 -l -1 record%02d.avi\fP .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "" .nr bi 1 .PP Should start recording, .IP "-w" .nr bi 1 .PP Waits for user confirmation to start (press enter) .IP "-f a" .nr bi 1 .PP use AVI as output format, .IP "-i S" .nr bi 1 .PP use SECAM SVHS-Input (SECAM Composite recording is also possible: -i s) .IP "-d 2" .nr bi 1 .PP the size of the pictures are half size .IP "-l -1" .nr bi 1 .PP do not touch the mixer settings .IP "record%02d.avi" .nr bi 1 .PP Here lavrec creates the first file named record00.avi after the file has reached a size of 1.6GB (after about 20 Minutes recording) it starts a new sequence named record01.avi and so on till the recording is stopped or the disk is full. With the release of the 1.9.0 Version mjpegtools is able to handle AVI files larger than 2GB. So that option is present for compatibility. .if \n(ll>1 .RE .nr ll -1 .PP Other example: .PP \fB> lavrec -f a -i t -q 80 -d 2 -C europe-west:SE20 test.avi\fP .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "" .nr bi 1 .PP Should start recording now, .IP "-f a" .nr bi 1 .PP use AVI as output format, .IP "-i t" .nr bi 1 .PP use tuner input, .IP "-q 80" .nr bi 1 .PP set the quality to 80% of the captured image .IP "-d 2" .nr bi 1 .PP the size of the pictures are half size (352x288) .IP "-C" .nr bi 1 .PP choose TV channels, and the corresponding -it and -iT (video source: TV tuner) can currently be used on the Marvel G200/G400 and the Matrox Millenium G200/G400 with Rainbow Runner extension (BTTV-Support is under construction). For more information on how to make the TV tuner parts of these cards work, see the Marvel/Linux project on: .if \n(ll>1 .RE .nr ll -1 .PP Last example: .PP \fB> lavrec -f a -i p -g 352x288 -q 80 -s -l 70 -R l --software-encoding test03.avi\fP .PP The two new options are \fB-g 352x288\fP, which sets the size of the video to be recorded when using \fB--software-encoding\fP, this enables the software encoding of the recorded images. With this option you can also record from a bttv based card. The processor load is high. This option only works for generic video4linux cards (such as the brooktree-848/878 based cards), it doesn't work for zoran-based cards. .PP .SH Other recording hints .PP All lavtools accept a file description like file*.avi so you do not have to name each file but that is a posibility. .PP Note: More options are described in the man-page, but with this you should be able to get started. .PP Here are some hints for sensible settings. Turn the quality to 80% or more for -d 2 capture. At full resolution as low as 40% seems to be visually \(rqperfect\(rq\&. -d 2 is already better than VHS video (a *lot*!). For a Marvel you should not set the quality higher than 50 when you record at full size (-d 1). If you use higher settings (-q 60) it is more likely that you will encounter problems. Higher settings will result in framedrops. If you're aiming to create VCD's then there is little to be gained recording at full resolution as you need to reduce to -d 2 resolution later anyway. .PP you can record at other sizes than the obvious -d 1/2/4. You can use combinations where you use halve horizontal size and full vertical size: -d 21. This would record for NTSC at a size of 352x480. This helps if you want to create SVCDs, scaling the 352 Pixles put to 480 is not that visible for the eye as if you would use the other combination -d 12. Where you have the full horzontal resolution and half vertical this Version will have a size of 720x288 for NTSC .PP .SH Some information about the typical lavrec output while recording .PP 0.06.14:22 int: 00040 lst:0 ins:0 del:0 ae:0 td1=0.014 td2=0.029 .PP The first part shows the time lavrec is recording. \fBint:\fP the interval between two frames. \fBlst:\fP the number of lost frames. \fBins and del:\fP are the number of frames inserted and deleted for sync correction. \fBae:\fP number of audio errors. \fBtd1 and td2\fP are the audio/video time-difference. .PP .nr ll +1 .nr t\n(ll 0 .if \n(ll>1 .RS .nr bi 1 .PP \fB(int) frame interval\fP should be around 33 (NTSC) or 40 (PAL/SECAM). If it is very different, you'll likely get a bad recording and/or many lost frames .nr bi 1 .PP \fB(lst) lost frames\fP are bad and mean that something is not working very well during recording (too slow HD, too high CPU usage, ...) Try recording with a greater decimation and possibly a lower quality. .nr bi 1 .PP \fB(ins, del) inserted OR deleted frames\fP of them are normal \(-> sync. If you have many lost AND inserted frames, you're asking too much of your machine. Use less demanding options or try a different sound card. .nr bi 1 .PP \fB(ae) audio errors\fP are never good. Should be 0 .nr bi 1 .PP \fB(td1, td2) time difference\fPis always floating around 0, unless sync correction is disabled (--synchronization!=2, 2 is default). .if \n(ll>1 .RE .nr ll -1 .PP .SH Notes about \(rqinterlace field order - what can go wrong and how to fix it\(rq .PP Firstly, what does it mean for interlace field order to be wrong? .PP The mjpegtools image processing chain is frame-oriented. Since it is video material that is captured each frame comprised of a top field (the 0th, 2nd, 4th and so lines) and a bottom field (the 1st, 3rd, 5th and so on lines). .PP There are three bad things that can happen with fields .PP .nr ll +1 .nr el +1 .nr t\n(ll 1 .nr e\n(el 0 1 .af e\n(el \*(f\n(el .if \n(ll>1 .RS .nr bi 1 .PP This is really only an issue for movies in PAL video where each film frame is sent as a pair of fields. These can be sent top or bottom field first and sadly it's not always the same, though bottom-first appears to be usual. If you capture with the wrong field order (you start capturing each frame with a bottom rather than a top or vice versa) the frames of the movie get split *between* frames in the stream. Played back on a TV where each field is displayed on its own this is harmless. The sequence of fields played back is exactly the same as the sequence of fields broadcast. Unfortunately, playing back on a Computer monitor where both fields of a frame appear at once it looks *terrible* because each frame is effectively mixing two moments 1/25sec apart in time. .nr bi 1 .PP The two fields can simply be swapped somehow so that top gets treat as bottom and bottom treat as top. Juddering and \(rqslicing\(rq is the result. This occasionally seems to happen due to hardware glitches in the capture card. .nr bi 1 .PP Somewhere in capturing/processing the *order* in time of the two fields in each frame can get mislabeled somehow. This is not good as it means that when playback eventually takes place a field containing an image sampled earlier in time comes after an image sampled later. Weird \(rqjuddering\(rq effects are the results. .if \n(ll>1 .RE .nr el -1 .nr ll -1 .PP How can I recognize if I have one of these Problems ? .PP .nr ll +1 .nr el +1 .nr t\n(ll 1 .nr e\n(el 0 1 .af e\n(el \*(f\n(el .if \n(ll>1 .RS .nr bi 1 .PP This can be hard to spot. If you have mysteriously flickery pictures during playback try encoding a snippet with the reverse field-order forced (see below). If things improve you know what the problem was and what the solution is! .nr bi 1 .PP The two fields can simply be swapped somehow so that top gets treat as bottom and bottom treat as top. Juddering and \(rqslicing\(rq is the result. This occasionally seems to happen due to hardware glitches in the capture card. That problem looks like that: .PP Interlacing problem .PP .nr bi 1 .PP Somewhere in capturing/processing the *order* in time of the two fields in each frame can get mislabeled somehow. This is not good as it means that when playback eventually takes place a field containing an image sampled earlier in time comes after an image sampled later. Weird \(rqjuddering\(rq effects are the result. .if \n(ll>1 .RE .nr el -1 .nr ll -1 .PP If you use glav or lavplay be sure that you also use the \fB-F/--flicker\fP option. This disables some things that improve the picture. .PP If you want to look at the video you can also use yuvplay: .PP \fB> lav2yuv \(br ... \(br yuvplay\fP .PP If there is a field order problem you should see it with yuvplay. .PP How can you fix it? .PP .nr ll +1 .nr el +1 .nr t\n(ll 1 .nr e\n(el 0 1 .af e\n(el \*(f\n(el .if \n(ll>1 .RS .nr bi 1 .PP To fix this one the fields need to be \(rqshifted\(rq through the frames. Use yuvcorrect's \fB-T BOTT_FORWARD/TOP_FORWARD\fP to shift the way fields are allocated to frames. You can find out the current field order for an MJPEG file by looking at the first few lines of debug output from: \fB> lav2yuv -v 2 the_mjpeg_file > /dev/null\fP Or re-record exchanging \fB-f a\fP for \fB-F A\fP or vice-versa. .nr bi 1 .PP This isn't too bad either. Use a tool that simply swaps the top and bottom fields a second time. yuvcorrect can do this use the \fB-T LINE_SWITCH\fP\&. .nr bi 1 .PP Is easy to fix. Either tell a tool someplace to relabel the fields or simply tell the player to play back in swapped order (the latter can be done \(rqindirectly\(rq by telling mpeg2enc when encoding to \fBreverse the flag (-z b\(brt)\fP that tells the decoder which field order to use. .if \n(ll>1 .RE .nr el -1 .nr ll -1 .PP \fBIn order to determine exactly what type of interlacing problem you have, you need to extract some frames from the recorded stream and take a look at them:\fP .PP .DS .sp .ft RR .nf > mkdir pnm > lav2yuv -f 40 video.avi \(br y4mtoppm \(br pnmsplit - pnm/image%d.pnm > rm pnm/image?.pnm > cd pnm > xv .DE .fi .ec .ft P .sp .PP First we create a directory where we store the images. The lav2yuv -f 40 writes only the first 40 frames to stdout. The program y4mtoppm converts the frames to pnm images and the pnmsplit splits the picture into two frames in the picture to two single pictures. Then we remove the first 10 images because pnmsplit does not support the %0xd numbering. Without a leading zero in the number, the files will be sorted in the wrong order, leading to confusing playback. .PP Use your favorite graphic program (xv for example) to view the pictures. As each picture only contain one field out of two they will appear scaled vertically. If you look at the pictures you should see the movie slowly advancing. .PP If you have a film you should always see 2 pictures that are nearly the same (because the film frame is split into two field for broadcasting) after each other. You can observe this easily if you have comb effects when you pause the film because both fields will be displayed at the same time. The two pictures that belong together should have an even number and the following odd number. So if you take a look on pictures: 4 and 5 are nearly identical, 5 and 6 differ (have movement), 6 and 7 identical, 7 and 8 differ , .... .PP To fix this problem you have to use yuvcorrect's \fB-T BOTT_FORWARD or TOP_FORWARD\fP\&. You can also have the problem that the field order (top/bottom) is still wrong. You may have to use yuvcorrect a second time with \fB-M LINE_SWITCH\fP, or use the mpeg2enc \fB-z (b\(brt)\fP option. .PP To see if you guessed correctly extract the frames again and reorder them using yuvcorrect: .PP \fB> lav2yuv -f 40 video.avi \(br yuvcorrect -T OPTION \(br y4mtoppm \(br pnmsplit - pnm/image%d.pnm \fP .PP Where \(rqOPTION\(rq is what you think will correct the problem. This is for material converted from film. Material produced directly for TV is addressed below. .PP Hey, what about NTSC movies ? .PP Movies are broadcast in NTSC using \(rq3:2\(rq pulldown which means that half the capture frames contain fields from 1 movie frame and half fields from 2 frames. To undo this effect for efficient MPEG encoding you need to use yuvkineco. .PP If you have an interlaced source like a TV camera you have a frame consists of two fields that are recorded at different points in time. Spotting the problem here is harder. You need to find something moving horizontally from the left to the right. When you extract the fields, the thing should move in small steps from the left to the right, not one large step forward, small step back, large forward, small back...... You have to use the same options mentioned aboth to correct the problem. .PP Do not expect that the field order is always the same (top- or bottom-first) It may change between the channels, between the films, and it may even change within a film. If it changes constant you may have to encode with the mpeg2enc -I 1 or even -I 2. .PP You can only have this problems if you record at full size !!! .PP Creating videos from other sources .PP Here are some hints and descriptions of how to create the videos from other sources like images and other video types. .PP You might also be interested in taking a look at the \fBTranscoding of existing MPEG-2\fP section. .PP .SH Creating videos from images .PP You can use jpeg2yuv to create a yuv stream from separate JPEG images. This stream is sent to stdout, so that it can either be saved into a file, encoded directly to a mpeg video using mpeg2enc or used for anything else. .PP Saving an yuv stream can be done like this: .PP \fB> jpeg2yuv -f 25 -I p -j image%05d.jpg > result.yuv\fP .PP Creates the file result.yuv containing the yuv video data with 25 FPS. The -f option is used to set the frame rate. Note that image%05d.jpg means that the jpeg files are named image00000.jpg, image00001.jpg and so on. (05 means five digits, 04 means four digits, etc.) The -I p is needed for specifing the interlacing. You have to check which type you have. If you don't have interlacing just choose p for progressive .PP If you want to encode a mpeg video directly from jpeg images without saving a separate video file type: .PP \fB> jpeg2yuv -f 25 -I p -j image%05d.jpg \(br mpeg2enc -o mpegfile.m1v\fP .PP Does the same as above but saves a mpeg video rather than a yuv video. See mpeg2enc section for details on how to use mpeg2enc. .PP You can also use yuvscaler between jpeg2yuv and mpeg2enc. If you want to create a SVCD from your source images: .PP \fB> jpeg2yuv -f 25 -I p -j image%05d.jpg \(br yuvscaler -O SVCD \(br mpeg2enc -f 4 -o video.m2v\fP .PP You can use the -b option to set the number of the image to start with. The number of images to be processed can be specified with the -n number. For example, if your first image is image01.jpg rather than image00.jpg and you only want 60 images to be processed type: .PP \fB>jpeg2yuv -b 1 -f 25 -I p -n 60 -j image*.jpg \(br yuv2lav -o stream_without_sound.avi\fP .PP Adding the sound to the stream then: .PP \fB> lavaddwav stream_without_sound.avi sound.wav stream_with_sound.avi\fP .PP For ppm input there is the ppmtoy4m util. There is a manpage for ppmtoy4m that should be consulted for additional information. .PP To create a mpeg video try this: .PP \fB>cat *.ppm \(br ppmtoy4m -o 75 -n 60 -F 25:1 \(br mpeg2enc -o output.m1v\fP .PP cat each *.ppm file to ppmtoy4m. There the first 75 frames (pictures) are ignored and next 60 are encoded by mpeg2enc to output.m1v. You can run it without the -o and -n option. The -F options sets the frame rate, default is NTSC (30000:1001), for PAL you have to use -F 25:1. .PP Other picture formats can also be used if there is a converter to ppm. .PP \fB>ls *.tga \(br xargs -n1 tgatoppm \(br ppmtoy4m \(br yuvplay\fP .PP A list of filenames (ls *.tga) is given to xargs that executes the tgatoppm with one (-n 1) argument per call, and feeds the output into ppmtoy4m. This time the video is only shown on the screen. The xargs is only needed if the converter (tgatoppm) can only operate on a single image at a time. .PP If you want to use the ImageMagick 'convert' tool (a Swiss Army Knife) try: .PP \fB>convert *.gif ppm:- \(br ppmtoy4m \(br yuvplay\fP .PP That means take all '.jpg' images in directory, convert to PPM format, pipe to stdout, then to ppmtoy4m for conversion to y4m .... .PP .SH Decoding streams with mplayer .PP Decoding the streams with mplayer is a nice way of bringing every video that mplayer can play back to something you can edit or encode to mpeg with mjpegtools. This method has been tested with mplayer 1.0rc2 and should work with newer versions .PP \fB>mkfifo stream.yuv\fP .PP \fB>cat stream.yuv \(br yuv2lav -o mjpeg_wo.avi &\fP .PP \fB>mplayer -nosound -noframedrop -vo yuv4mpeg anyfile.mpg\fP .PP \fB>mplayer -vo null -ao pcm:file=anyfile.wav anyfile.mpg\fP .PP Now you have an example of a mjpeg encoded AVI without sound. The sound will be in anyfile.wav. You can choose if you want to add the sound to the AVI with \fBlavaddwav\fP and edit the file before encoding. .PP You can also use instead of yuv2lav, mpeg2enc or any other tool from the mjpeg tools so your command might also look like that: .PP \fB> cat stream.yuv \(br yuvdenoise \(br yuvscaler -O SVCD \(br mpeg2enc -f 4 -o video_svcd.m2v\fP .PP cat the wav file into \fBmp2enc\fP to encode it to MP2 audio. The \fB-vo yuv4mpeg\fP option works well with other input types mentioned in the mplayer documentation. .SH Decoding MPEG-2 streams with mpeg2dec .PP You can decode mpeg2 streams with the patched mpeg2dec version which creates yuv streams. You can pipe that into any other mjpegtools program. Or you use a mpeg2dec version directly from the libmpeg2 project and use the output mode pgmpipe. With the \fBpgmtoy4m\fP program you can convert that pgm output back to yuv. .PP If you ask yourself why there is a patched version and pgmtoy4m. The answer is that the patch for yuv output was sent several times to the libmpeg2 developers but was never included. Now we have two ways around that problem. Decoding looks like this: .PP \fB> mpeg2dec -s -o pgmpipe ANYTS.VOB \(br pgmtoy4m -i t -a 10:11 -r 30000:1001 \(br mpeg2enc -f 8 newvideo.m2v\fP .PP You can decode the audio as described in the \fBTranscoding of existing MPEG-2\fP Section. .PP .SH Other things to know .PP If you have Transport streams from your DVB card, or Satelite Receiver you might want to demultiplex or cut them. A nice tool for that is \fBProject X\fP available from: .PP You can process the streams afterwards as you would do with any mpeg movie or demultiplexed audio video. So the \fBTranscoding of existing MPEG-2\fP section of this document will be of interest.Checking if recording was successful .PP You can use lavplay or glav. \fBIMPORTANT: NEVER\fP try to run xawtv and lavplay or glav with hardware playback, it will not work. For software playback it works fine. .PP \fB>lavplay -p S record.avi\fP .PP You should see the recorded video and hear the sound. But the decoding of the video is done by the CPU which will place a heavy load on the system. The advantage of this method is you don't need xawtv. .PP The better way: .PP \fB>lavplay -p H record.avi\fP .PP The video is decoded and played by the hardware. The system load is very low. This will play it back on-screen using the hardware rather than software decoding. .PP You might also try: .PP \fB> lavply -p C record.avi\fP .PP Which will play it back using the hardware but to the video output of the card. .PP \fB> glav record.avi\fP .PP Does the same as lavplay but you have an nice GUI. The options for glav and lavplay are nearly the same. Using no option SW playback is used. .PP Using hardware playback a signal for the Composite and SVHS OUT is generated so you can view the movie on your TV. .PP \fB> lav2yuv test.eli \(br yuvplay\fP .PP Is a other way to get the video without sound. You can use yuvplay once in the encoding command. When you use yuvplay in the encoding command you see the changes made by filters and scaling. You can also use it for slow-motion debugging. .PP \fBNOTE:\fP After loading the driver's you have to start xawtv to set up some things lavplay and glav do not, but they are needed for HW-Playback. Don't forget to close xawtv !! .PP \fBNOTE2:\fP Do not try to send glav an lavplay into background, wont work correct !!! .PP \fBNOTE3:\fP SECAM playback is now (12.3.2001) only in monochrome but the recording and encoding is done right. .PP \fBNOTE4:\fPBad cables may reduce the quality of the image. Normally you can't see this but when there is text you might notice a small shadow. When you see this you should change the cable. .PP \fBComing soon:\fP There is a tool which makes recoding videos very simple: Linux Studio. You can download it at: .PP Edit the video .PP .SH Edit with glav .PP Most tasks can be easily done by glav. Like deleting parts of the video, cut paste and copy parts of the videos. .PP glav button description .PP The modifications should be saved because glav does not destructively edit the video. This means that the original video is left untouched and the modifications are kept in an extra \(rqEdit List\(rq file readable with a text editor. These files can be used as an input to the other lavtools programs such as lav2wav, lav2yuv, lavtrans. .PP If you want to cut off the beginning and the end of the stream mark the beginning and the and, and use the \(rqsave select\(rq button. The edit list file is than used as input for the lavtools. If you want to split a recorded video to some smaller parts simply select the parts and then save each part to a different listfile. .PP You can see all changes to the video and sound NOW and you do not need to recalculate anything. .PP If you want to get a \&"destructive\&" version of your edited video use: .PP \fB> lavtrans -o short_version.avi -f a editlist.eli\fP .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "-o" .nr bi 1 .PP specifies the output name .IP "-f a" .nr bi 1 .PP specifies the output format (AVI for example) .IP "editlist.eli" .nr bi 1 .PP is the list file where the modifications are described. You generate the list file with the \&"save all\&" or \(rqsave select\(rq buttons in glav. .if \n(ll>1 .RE .nr ll -1 .PP .SH Unify videos .PP \fB> lavtrans -o stream.qt -f q record_1.avi record_2.avi ... record_n.avi\fP .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "-o" .nr bi 1 .PP specifies the outputfile name .IP "-f q" .nr bi 1 .PP specifies the output format, quicktime in this case .if \n(ll>1 .RE .nr ll -1 .PP This is usually not needed. Keep in your mind that there is a 2GB file-size-limit on 32Bit systems with an older glibc. Usually not a problem these days .PP .SH Separate sound .PP \fB> lavtrans -o sound.wav -f w stream.avi\fP .PP Creates a wav file with the sound of the stream.avi Maybe needed if you want to remove noise or if you want to convert it to another sound format. .PP Another way to split the sound is: .PP \fB> lav2wav editlist.eli >sound.wav\fP .PP .SH Separate images .PP \fB>mkdir jpg; lavtrans -o jpg/image%05d.jpg -f i stream.avi\fP .PP First create the directory \(rqjpg\(rq\&. Then lavtrans will create single JPG images in the jpg directory from the stream.avi file. The files will be named: image00000.jpg, image00001.jpg .... .PP The jpg images created contain the whole picture. But if you have recorded at full size the images are stored interlaced. Usually the picture viewers show only the first field in the jpg file. .PP .PP If you want to have the image in a single file you can use that version .PP \fB> lav2yuv -f 1 stream.avi \(br y4mtoppm -L >file.pnm\fP .PP If you want to split the fields into single files use that: .PP \fB> lav2yuv -f 5 ../stream.avi \(br y4mtoppm \(br pnmsplit - image%d.pnm\fP .PP Maybe interesting if you need sample images and do not want to play around with grabbing a single image. .PP .SH Creating movie transitions .PP Thanks to Philipp Zabel's lavpipe we can now make simple transitions between movies or combine multiple layers of movies. .PP Philipp wrote this HOWTO on how to make transitions: .PP Let's assume simple this scene: We have two input videos intro.avi and epilogue.mov and want to make intro.avi transition into epilogue.mov with a duration of one second (that is 25 frames for PAL or 30 frames for NTSC). .PP Intro.avi and epiloque.mov have to be of the same format (the same frame rate and resolution). In this example they are both 352x288 PAL files. intro.avi contains 250 frames and epilogue.mov is 1000 frames long. .PP Therefore our output file will contain: .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "" .nr bi 1 .PP the first 225 frames of intro.avi .IP "" .nr bi 1 .PP a 25 frame transition containing the last 25 frames of intro.avi and the first 25 frames of epilogue.mov .IP "" .nr bi 1 .PP the last 975 frames of epilogue.mov .if \n(ll>1 .RE .nr ll -1 .PP We could get the last 25 frames of intro.avi by calling: .PP \fB>lav2yuv -o 225 -f 25 intro.avi\fP .PP \fB-o 255\fP, the offset, tells lav2yuv to begin with frame # 225 and \fB -f 25\fP makes it output 25 frames from there on. .PP Another possibility (because negative offsets are counted from the end)is: .PP \fB> lav2yuv -o -25 intro.avi\fP .PP And the first 25 frames of epilogue.mov: .PP \fB> lav2yuv -f 25 epilogue.mov\fP .PP \fB-o\fP defaults to an offset of zero .PP But we need to combine the two streams with lavpipe. So the call would be: .PP \fB> lavpipe \(rqlav2yuv -o 255 -f 25 intro.avi\(rq \(rqlav2yuv -f 25 epilogue.mov\(rq \fP .PP The output of this is a raw yuv stream that can be fed into transist.flt. .PP transist.flt needs to be informed about the duration of the transition and the opacity of the second stream at the beginning and at the end of the transition: .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "-o num" .nr bi 1 .PP opacity of second input at the beginning [0-255] .IP "-O num" .nr bi 1 .PP opacity of second input at the end [0-255] .IP "-d num" .nr bi 1 .PP duration of transition in frames .if \n(ll>1 .RE .nr ll -1 .PP An opacity of 0 means that the second stream is fully transparent (only stream one visible), at 255 stream two is fully opaque. .PP In our case the correct call (transition from stream 1 to stream 2) would be: .PP \fB> transist.flt -o 0 -O 255 -d 25\fP .PP The -s and -n parameters equate to the -o and -f parameters of lav2yuv and are only needed if anybody wants to render only a portion of the transition for whatever reason. Please note that this only affects the weighting calculations - none of the input is really skipped. If you use the skip parameter (-s 30, for example) you also need to skip the first 30 frames in lav2yuv (-o 30) in order to get the expected result. If you didn't understand this send an email to the authors or simply ignore -s and -n. The whole procedure will eventually be automated. .PP Now we want to compress the yuv stream with yuv2lav: .PP \fB> yuv2lav -f a -q 80 -o transition.avi\fP .PP Reads the yuv stream from stdin and outputs an avi file (-f a) with compressed jpeg frames of quality 80. .PP Now we have the whole command for creating a transition: .PP \fB> ypipe \(rqlav2yuv -o 255 -f 25 intro.avi\(rq \(rqlav2yuv -f 25 epilogue.mov\(rq \(br transist.flt -o 0 -O 255 -d 25 \(br yuv2lav -f a -q 80 -o transition.avi\fP .PP The resulting video can be written as a LAV Edit List (a plain text file) containing the following lines: .PP .DS .sp .ft RR .nf LAV Edit List PAL 3 intro.avi transition.avi epilogue.mov 0 0 224 1 0 24 2 25 999 .DE .fi .ec .ft P .sp .PP This file can be fed into glav or lavplay, or you can pipe it into mpeg2enc with lav2yuv or combine the whole stuff into one single mjpeg file with lavtrans or lav2yuv\(bryuv2lav. .PP Converting the stream to MPEG or DIVx videos .PP First there is some general description in the encoding process and afterwards there is a detailed description of some commonly used output formats. .PP If you want a one command conversation to mpeg videos try lav2mpeg in the scripts directory .PP The encoding with the lav2mpeg script looks like this for mpeg1 output: .PP \fB>lav2mpeg -a 160 -b 2110 -d 320x240 -m mpeg1 -o output.mpg file.eli\fP .PP .nr ll +1 .nr t\n(ll 0 .if \n(ll>1 .RS .nr bi 1 .PP Will create a mpeg1 with videobitrate of 2110kBit/sec and audiobitrate of 160 kBit/sec .nr bi 1 .PP at a resolution of 320x240 .if \n(ll>1 .RE .nr ll -1 .PP Or for the generation of mpeg2 output: .PP \fBlav2mpeg -o mpeg2 -O output.mpg file.eli\fP .PP .nr ll +1 .nr t\n(ll 0 .if \n(ll>1 .RS .nr bi 1 .PP Will create a mpeg2 with default bitrate in same resolution as the input resolution .if \n(ll>1 .RE .nr ll -1 .PP Better results can be accomplished, however, by trying various options and find out which ones work best for you. These are discussed below. .PP The creation of MPEG-1 movies is explained with more examples and in greater detail because most of the things that can be used for MPEG-1 also work for the other output formats .PP For the creation of of VCD/SVCD Stills sequences (-f 6 / -f 7 in mpeg2enc) you should see: Still sequences are needed for the creation of menus in VCD/SVCD. The creation of menus is described in the doku of vcdimager. .PP .SH Creating sound .PP MPEG-1 videos need MPEG-1-Layer2 (MP2) sound files. For MPEG-2 videos you can use MPEG-1-Layer2 and MPEG1-Layer3 (MP3). MP3 audio is not an offically valid audio format but many VCD players will recognize it. MP3 audio is not valid for DVDs. You should stick to MP2 because many of the MPEG-2 players (DVD Player for example, usually the Windows Versions have great problems with this too) are not able to play MPEG2-Video and MP3 sound. .PP mp2enc is a MP2 Audio encoder. The toolame encoder is also able to produce an MP2 file. Toolame is much faster than mp2enc but toolame does not peform resampling (48000 to 44100 samples/second). Many hardware players will play SVCDs using 48000 rate audio. For MP3 creation I'm be sure you have an encoder. .PP Example: .PP \fB> lav2wav stream.avi \(br mp2enc -o sound.mp2\fP .PP This creates a mpeg sound file out of the stream.avi with 224kBit/sec bitrate and a sample rate of 48kHz. If you audio file has 44.1kHz mp2enc resamples the audio to create a 48kHz output. If you want a 44.1kHz output sample rate you have to add -r 44100 to the mp2enc command .PP Example .PP \fB> cat sound.wav \(br mp2enc -v 2 -V -o sound.mp2\fP .PP This creates a VCD (-V bitrate=224, stereo, sampling rate:44100) compatible output from the wav file. .PP With -v 2 mp2enc is more verbose, while encoding you see the number of sec of audio already encoded. .PP You can test the output with: .PP \fB> plaympeg sound.mp2\fP .PP \fBNOTE:\fP plaympeg is a MPEG-1 Player for Linux, you can use other players as wellr. For audio testing you can also use mpg123. For both audio and video playing there are the universal player like VLC mplayer and others. .PP .SH Converting video .PP Creating MPEG-1 and MPEG-2 videos. .PP Normally the first video you create is not the best. For optimal quality/size you need to play with the bitrate, search radius, noise filter .... The options of mpeg2enc are described in the manpage of mpeg2enc. .PP Example: .PP \fBlav2yuv stream.avi stream1.avi \(br mpeg2enc -o video.m1v\fP .PP This creates an video file with the default constant bitrate of 1152kBit/sec. This is the bitrate you need if you want to create VCDs. You can specify more files and also use the placeholder %nd. Where \fBn\fP describes the number. By default mpeg2enc assumes that you want to encode a not interlaced video to Mpeg-1. If you want to encode a full size video with interlacing that command above will fail. .PP Example: .PP \fB> lav2yuv streami%02d.avi \(br mpeg2enc -b 1500 -r 16 -o video.m1v\fP .PP mpeg2enc creates a video with a bitrate of 1500kBit/s uses an search radius of 16. That means when trying to find similar 16*16 macroblocks of pixels between frames the encoder looks up to 16 pixels away from the current position of each block. It looks twice as far when comparing frames 1 frame apart and so on. Reasonable values are 16 or 24. The default is 16 so adding the option here is useless. Lower values (0, 8), improve the encoding speed but you get lower quality (more visible artifacts) while higher values (24, 32) improve the quality at the cost of the speed. With the file description of stream%02d.avi all files are processed that match this pattern with 00, 01.... .PP Scaling .PP Using yuvscaler one can now also scale the video before encoding it. This can be useful for users with a DC10 or DC10+ cards which captures at -d 1 768x576 or -d 2 384x288 (PAL/SECAM) or -d 1 640x480 (NTSC). .PP You get a full description of all commands by reading the manpage or running: .PP \fB>yuvscaler -h\fP .PP Example: .PP \fB> lav2yuv stream.avi \(br yuvscaler -O VCD \(br mpeg2enc -o video.m1v\fP .PP This will scale the stream to VCD size which for PAL/SECAM is 352x288 and for NTSC is 352x240. The scaled yuvstream is encoded to MPEG-1. .PP It can also do SVCD scaling to 480x480 (NTSC) or 480x576 (PAL/SECAM): .PP \fB> lav2yuv stream.avi \(br yuvscaler -O SVCD -M BICUBIC \(br mpeg2enc -o video.m1v\fP .PP The mode keyword (-M) forces yuvscaler to use the higher quality bicubic algorithms for downscaling and not the default resample algorithms. Upscaling is always done using the bicubic algorithm. .PP Example: .PP \fB> lav2yuv stream.avi \(br yuvscaler -I USE_450x340+20+30 -O SIZE_320x200 \(br mpeg2enc -o video.m1v \fP .PP Here we only use a part of the input and specify a nonstandard output resolution. .PP \fBNOTE:\fP yuvscaler can set a active area, and set everything else to black using: -I ACTIVE_WidthxHeight+WidthOffset+HeightOffset High quality scaling: y4mscaler .PP y4mscaler has been arround for quite some time. But it was for a quite long time a extra tool you needed to compile. There is a comprehensive manpage explaining all the details, there also a lot fo helpful information on the website: One unique feature is that is it able to change the subsampling, and Choma Modes. And you can choose the scaler kernels, depending on the source that can help a lot. .PP Example: .PP \fB> cat raw.yuv \(br y4mscaler -O infer=CLIP -O preset=DVD -O sar=PAL_Wide \(br mpeg2enc video.m1v \fP .PP In this example y4mscaler will take the input stream and scale it to the coresponding PAL size. The sar option tell to scale is to a wide format (16:9). The \fBinfer=clip\fP option will tells y4mscaler that it can clip the top and bottom bars away to scale it to the resulting size. .PP Example: .PP \fB> mpeg2dec -o pgmpipe deluxe.m2v \(br pgmtoy4m -x 420jpeg -r 25:1 -i t \(br y4mscaler -I sar=64:36 -I active=344x476+100+48 -O preset=DVD \(br mpeg2enc -f 8 video.m1v \fP .PP This is a more the job for y4mscaler. We have a weird PAL MPEG source format with 544x576 pixels in a wide screen 16:9 format, that makes black bars all around the original 4:3 image. This command scales the image up to a original 4:3 size, and takes just the interesting center. The SAR is the sample aspect ratio get lost somewhere so we specify it in the beginning. So it is specified again, than you tell y4mscaller the active size of the picture it shall use to scale up. The active keyword is treated different in y4mscaler and yuvscaler. The DVD is a preset for the output format you want. From the stream parameters y4mscaler knows that it is a PAL stream and the output parameters. If you wanted a 16:9 output you would have to use the keyword: DVD_WIDE. .PP Testing is done by: .PP \fB> mplayer video.m1v\fP .PP \fBNOTE:\fPThese are only examples. There are more options you can use. You can use most of them together to create high quality videos with the lowest possible bitrate. .PP \fBNOTE2:\fPThe higher you set the search radius the longer the conversion will take. In general the more options used the longer encoding takes. .PP \fBNOTE3:\fPMPEG-1 was not designed to be a VBR (variable bitrate stream) !! So if you encode with -q 15 mpeg2enc sets the maximal bitrate -b to 1152. If you want a VBR MPEG-1 you have to set -b very high (2500). .PP \fBNOTE4:\fPMaybe you should give better names than video.mpg. A good idea is to use the options as part of the filename (for example: \fBvideo_b1500_r16_41_21.m1v\fP). Another possibility is to call all the layer 2 audio files \(rq\&.mp2\(rq all the MPEG-1 video files \(rq\&.m1v\(rq and all MPEG-2 video files \(rq\&.m2v\(rq Easy to see what's happening then. Reserve .mpg for multiplexed MPEG-1/2 streams. .PP .SH Putting the streams together .PP Example: .PP \fB> mplex sound.mp2 video.m1v -o my_video.m1v\fP .PP Puts the sound.mp2 and the video.m1v stream together to my_video.mpg .PP Now you can use your preferred MPEG player and watch it. All players (gtv for example) based on the SMPEG library work well for MPEG-1. Other players (which can play MPEG-2 as well as MPEG-1 movies) are: xmovie, xine, and MPlayer VLC, to name some. .PP \fBNOTE:\fP If you have specified the \fB-S\fP option for mpeg2enc mplex will automatically split the files if there is in the output filename a %d (looks like: -o test%d.mpg) The files generated this way are separate stand-alone MPEG steams! .PP \fBNOTE2:\fP xine might have a problem with seeking through videos. mplayer has a problem with the \(rqseek backward/forward\(rq with variable bitrate streams because it goes forward in the file the amount of data for a constant bitrate stream. That amount might be significantly more than 10 seconds or one minute (those are the amount mplayer seeks for each press of the arrow keys). So don't wonder if it seeks much more time forward or backward than you expect. .PP \fBVariable bit-rate multiplexing:\fP Remember to tell mplex you're encoding VBR (-V option) as well as mpeg2enc (see the example scripts). It *could* auto-detect but it is not working yet. You should tell mplex a video buffer size at least as large as the one you specified to \(rqmpeg2enc\(rq Sensible numbers for MPEG-1 might be a ceiling bit-rate of 2800Kbps, a quality ceiling (quantization floor) of 6 and a buffer size of 400K. .PP Example: .PP \fB> mplex -V -r 1740 audio.mp2 video_vbr.m1v -o vbr_stream.mpg\fP .PP Here we multiplex a variable bitrate stream. mplex is a single pass multiplexer so it can't detect the maximal bitrate and we have to specify it. The data rate for the output stream is: audio bitrate + peak videobitrate + 1-2% for mplex information. If audio (-b 224) is 224kBit and the video is 1500kBit (encoded with -b 1500 -q 9) then we have 1724 * 1.01 or about 1740kBit. .PP Example: .PP \fB> plaympeg my_video.mpg\fP .PP or .PP \fB> mplayer my_video.mpg\fP .SH Creating MPEG-1 Videos .PP For MPEG-1 videos you can use MP2 audio and MPEG-1 video. A subset of MPEG-1 movies are VCD's. You can use VBR (Variable BitRate) for the Video (although VCDs are almost always use CBR video) but the Audio has to be CBR (Constant BitRate). .PP MPEG-1 is recommended for picture sizes up to 352x288 for PAL and 352x240 for NTSC for larger sizes MPEG-2 is the better choice. There is no exact resolution where MPEG-1 is better than MPEG-2. Just to make soure, MPEG-1 can't handle interlaced sources. If you video is interlaced you need MPEG-2 to get it proper encoded. .PP MPEG-1 Audio creation Example .PP \fB> lav2wav editlist.eli \(br mp2enc -r 44100 -o sound.mp2\fP .PP You can save some bits by telling mp2enc to use a lower bitrate (-b option) like 160 or 192 kBit/s. The -r 44100 option forces mp2enc to generate a 44.1kHz audio file. .PP \fB> lav2wav editlist.eli \(br mp2enc -b 128 -m -o sound.mp2\fP .PP This creates a mono output with an bitrate of 128kBit/sec bitrate. The input this time is the editlistfile (can have any name) created with glav so all changes you made in glav are direct processed and handed over to mp2enc. You do NOT have to create an edited stream with lavtrans to get it converted properly. .PP MPEG-1 Video creation example .PP \fB> lav2yuv editlist.eli \(br mpeg2enc -b 2000 -r 24 -q 6 -o video.m1v\fP .PP mpeg2enc creates an video with an bitrate of 2000kBit/s (or 2048000Bit/s) but the -q flag activates the variable bitrate and a quality factor of 6. It uses a search radius of 24. .PP \fBExplanation:\fPwhen mpeg2enc is invoked without the 'q' flag it creates \(rqconstantbit-rate\(rq MPEG streams. Where (loosely speaking) the strength of compression (and hence picture quality) is adjusted to ensure that on average each frame of video has exactly the specified number of bits. Such constant bit-rate streams are needed for broadcasting and for low-cost hardware like DVD and VCD players which use slow fixed-speed player hardware. .PP Obviously this is fairly inefficient as it means inactive scenes use up bits that could better be \(rqspent\(rq on rapidly changing scenes. Setting the 'q' flag tells mpeg2enc to generate variable bit-rate streams. For such streams the bit-rate specified is simply the maximum permissible. The 'q' parameter specifies the minimum degree of compression to be applied by specifying how exactly picture information is recorded. Typically 'q' would be set so that quiet scenes would use less than the specified maximum (around 6 or 8) but fast moving scenes would still be bit-rate limited. For archival purposes setting a maximum bit-rate high enough never to be reached (e.g. 10Mbps) and a q of 2 or 3 are reasonable choices. .PP Example: .PP \fB> lav2yuv stream.avi \(br yuvscaler -I ACTIVE_352x240+0+24 \(br mpeg2enc -b 1152 -r 16 -4 1 -2 1 -o video.m1v\fP .PP Usually there is at the top and at the bottom a nearly black border and a lot of bandwidth is used for something you do not like. The yuvscaler -I ACTIVE option sets everything that is not in the described area to black but the imagesize (352x288) is not changed. So you have a real black border the encoder only uses a few bits for encoding them. You are still compatible with the VCD's format in this example. To determine the active window extract one frame to the jpeg format: .PP \fB> lavtrans -f i -i 100 -o frame.jpg test.avi\fP .PP Than use your favorite graphic display program to determine the active size. The -4 1 and -2 1 options improves the quality about 10% but conversion is slower. .PP At the size of 352x288 (1/2 PAL size created when using the -d 2 option when recording) the needed bitrate is/should be between 1000 - 1500kBit/s. For NTSC it should be about the same, because the image is smaller but there are more frames per second than in PAL. .PP Anyways, the major factor is quality of the original and the degree of filtering. Poor quality unfiltered material typically needs a higher rate to avoid visible artifacts. If you want to reduce bit-rate without annoying artifacts when compressing broadcast material you should try one (or more) of the noise filters. .PP Example: .PP \fB> lav2yuv stream.avi \(br mpeg2enc -b 1500 -n s -g 6 -G 20 -P -o video.m1v\fP .PP Here the stream.avi will be encoded with: .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "-b 1500" .nr bi 1 .PP a Bitrate of 1500kBit/sec .IP "-n s" .nr bi 1 .PP the input Video norm is forced to SECAM .IP "-P" .nr bi 1 .PP This ensures that 2 B frames appear between adjacent I/P frames. Several common MPEG-1 decoders can't handle streams that do not have 2 B-frames between I/P frames .IP "-g 6 -G 20" .nr bi 1 .PP the encoder can dynamically change the group-of-pictures size to reflect scene changes. This is done by setting a maximum GOP (-G flag) size larger than the minimum (-g flag). For VCDs sensible values might be a minimum of 9 and a maximum of 15. For SVCD 9 and 15 would be good values. If you only want to play it back on SW player you can use other min-max values. .if \n(ll>1 .RE .nr ll -1 .PP Example: .PP \fB> lav2yuv stream*.avi \(br mpeg2enc -b 1500 -r 16 -4 1 -2 1 -S 630 -B 260 -o video_n1_1500_r16_41_21_S630_B240.m1v\fP .PP lav2yuv processes all the stream files. Then mpeg2enc is given some options that make the encoded stream look nicer. Using \fB-S 630\fP means that mpeg2enc marks the stream so that mplex generates a new stream every 630MB. One important thing is the use of the \fB-B\fP option which specifies the non-video (audio and mplex information) bitrate. The \fB-B\fP value of 260 should be fine for audio with 224kBit and mplex information. For further information take a look at the encoding scripts in the scripts directory. .PP MPEG-1 Multiplexing Example .PP Example: .PP \fB >mplex sound.mp2 video.m1v -o my_video.mpg\fP .PP Puts the sound.mp2 and the video.m1v stream together to my_video.mpg. It only works that easy if you have CBR (the -q option was not used with mpeg2enc). .PP Example: .PP \fBmplex -V -r 1740 audio.mp2 video_vbr.m1v -o vbr_stream.mpg\fP .PP Here we multiplex a variable bitrate stream. mplex is now a single pass multiplexer so it can't detect the maximal bitrate and we have to specify it. The data rate for the output stream is: \fBaudio bitrate + peak videobitrate + 1-2% for mplex information\fP\&. If audio (-b 224) has 224kBit, video has 1500kBit (was encoded with -b 1500 -q 9) then we have 1724 * 1.01 or about 1740kBit. .PP .SH Creating MPEG-2 Videos .PP MPEG-2 is recommended for sources with a greater picture than 352x240 for NTSC and 352x288 for PAL. MPEG-2 can also handle interlaced sources like recording from TV at full resolution. .PP MPEG-2 allows the usage of mpeg layer 3 (mp3) sound. So you can use your favorite mp3encoder for the creation of the sound. However, MP3 audio is not valid for DVDs. It is best to use MP2 (Layer 2) audio. The audio can also be a VBR stream. .PP MPEG-2 is usually a VBR stream. MPEG-2 creation with optimization requires a lot of CPU power. A film with the double resolution is NOT 4 times larger than an MPEG-1 stream. Depending on your quality settings it will be about 1.5 up to 3 times larger than the MPEG-1 stream at its lower resolution.MPEG-2 audio creation example .PP \fB> lav2wav editlist.eli \(br mp2enc -o sound.mp2\fP .PP You can save some bits by telling mp2enc to use a lower bitrate (-b option) like 160 or 192 kBit/s. You might want to add -r 44100 so that mpeg2enc generates 44.1kHz sampling rate audio. I hope I don't need to explain the usage of an MP3 Encoder. But you should not use all the fancy options that are available.MPEG-2 Video creation example .PP \fB> lav2yuv editlist.eli \(br mpeg2enc -f 3 -b 3000 -q 9 -o video.m2v\fP .PP A very simple example for MPEG-2 Video. The most important option is the -f 3. That tells mpeg2enc that it should create a MPEG-2 stream. Because it is a generic MPEG-2 you have to use the -b bitrate options. And should use the -q option because you usually want a space saving VBR stream. When using VBR streams the -b option tells mpeg2enc the maximum bitrate that can be used. The -q option tell mpeg2enc what quality the streams should have. The bitrate has an upper bound of the value specified by -b. .PP \fB> lav2yuv editlist.eli \(br mpeg2enc -f 3 -4 1 -2 1 -q7 -b 4500 -V 300 -P -g 6 -G 18 -I 1 -o video.m2v\fP .PP This will generate a higher quality MPEG-2 stream because the -4 1 and -2 1 options were used. With -b 4500 -q 7 you tell mpeg2enc the maximal bitrate and the quality factor. -V is the video buffer size used for decoding the stream. For SW playback it can be much higher than the default. Dynamic GOP is set with -g and -G. A larger GOP size can help reduce the bit-rate required for a given quality but very large sizes can introduce artifacts due to DCT/iDCT accumulated rounding errors. The -P option also ensures that 2 B frames appear between adjacent I/P frames. The -I 1 option tells mpeg2enc that the source is a interlaced material like videos. There is (time consuming) interlaced motion compensation logic present in mpeg2enc. Mpeg2enc will use that logic if the size of the frames you encode is larger than the VCD size for your TV Norm. .PP If you deinterlacing the movie with yuvdeinterlace you should tell mpeg2enc that it does not need to do motion estimation for interlaced material. You have to use the -I 0 option of mpeg2enc to say that the frames are already deinterlaced. This will save a lot of time when encoding. If you don't use -I 0 it will not cause problems, the encoding will just take longer. .PP You can also use scaling an options that optimize (denoise) the images to get smaller streams. These options are explained in detail in the following sections.Which values should be used for VBR Encoding? .PP The -q option controls the minimum quantization of the output stream. Quantization controls the precision with which image information is encoded. The lower the value the better the image quality. Values below 4 are extremes and should only be used if you know what you are doing .PP Usually you have to set up a maximum bitrate with the -b option. The tricky task is to set a value for the -q option and the -b option that produces a nice movie without using too much bandwidth and does not introduce too many artifacts. .PP A quality factor should be chosen that way that the mplex output of Peak bit-rate and average bit-rate differ by about 20-25%\&. If the difference is very small (less than < 10%) it is likely that you will begin to see artifacts in high motion scenes. The most common cause of the average rate being too close (or equal) to the maximum rate is wrong value for the maximal bitrate or a quality factor that is too high. .PP A combination that will produce more artifacts than you can count is a SVCD with a maximal video bitrate of 2500kBit and a quality factor of 1 or 2. For SVCD with a video limit of 2500kBit a quality factor of 7-11 fits quite good (8 is the default). If you use filter programs or have a very good source like digital TV, DVD like material or rendered pictures you can use a quality factor of 6 when creating SVCDs. If your SVCD/DVD player supports non-standard bitrates you can increase the bitrate above the standard maximum of 2788 kBit/sec (video plus audio). When using a higher bitrate and quality factor action scenes will look much better but of course the playing time of the disc will be less. .PP The same (7-11) quality factor for a full size picture and a top bitrate of 3500 to 4000 kBit will produce few artifacts. .PP For SVCD/DVD you can expect a result like the one described if the maximal bitrate is not set too low: .PP .DS .sp .ft RR .nf q <= 6 real sharp pictures, and good quality q <= 8 good quality q >= 10 average quality q >= 11 not that good q >= 13 here even still sequences might look blocky .DE .fi .ec .ft P .sp Encoding destination TV (interlaced) or Monitor (progressive) .PP MPEG-2 supports interlaced data in addition to the progressive format. A MPEG-2 movie can be interlaced or progressive. It depends on the source (film or broadcast) and on the viewing device. .PP If you encode a film both fields should be the same. Deinterlace the stream with yuvdeinterlace, or if you have a high quality source, and don't need to use the denoiser with yuvcorrect -T NOT_INTERLACED. Also set the mpeg2enc interlace-mode (-I) option to 0. This means that there is no interlacing. We do not really need deinterlacing here because there is no motion between the fields of the frame. We only need to unite the two fields into a single progressive frame. .PP This movie should play back an any device (TV or Monitor) without problems. .PP If you have an interlaced source (broadcast) you can encode it as interlaced stream. Or deinterlace the stream and encode it as progressive stream. If you deinterlace it with yuvdeinterlace you will lose details. But if you plan to play the recorded stream on your DVD player and your TV it would not be wise to perform deinterlacing. If you only want to play it back on the Monitor (progressive display) the picture looks better when playing it back if it is deinterlaced. If the player you use can do deinterlacing it does not matter if your encoded video has interlaced frames or progressive frames. .PP If you plan to deinterlace the stream you can only do this with yuvdeinterlace and set the mpeg2enc -I 0. If you do not want to deinterlace the stream you do not need to set any special option (do not use yuvdeinterlace and mpeg2enc -I 0) .PP If you like to pause the stream and look on the still you should deinterlace. Because then the image is flicker free when pausing. .PP If you have a film (progressive) with parts from a broadcast (interlaced) mixed together (like in a documentary where some parts from a speaker are recorded interlaced and other parts are filmed) you have to choose between good film sequences with average still images or average looking film sequences with good still images. .PP For good film with average stills do not deinterlace. For average film sequences with good stills then deinterlace (using yuvdeinterlace and mpeg2enc -I 0).MPEG-2 Multiplexing example .PP \fB> mplex -f 3 -b 300 -r 4750 -V audio.mp3 video.m2v -o final.mpg\fP .PP Now both streams (a mp3 audio and a mpeg2 video) are multiplex into a single stream (final.mpg). You have to use the \fB-f 3\fP option to tell mplex the output format. You also have to add the \fB-b\fP decoder buffers size option with the same value used when encoding the video. -\fBr\fP is that rate of video + audio +1-2% of mplex information. .PP The \fB-V\fPoption tells that your source for mplexing is a VBR stream. If you don't use this option mplex creates something like a CBR stream with the bitrate you have told it with the \fB-r\fP option. These streams are usually get BIG. .PP .SH Creating Video CDs (VCDs) .PP VCD is a constrained version of MPEG-1 video. VCD format was defined by Philips. The goal was to use a single speed CD-drive and other cheap hardware (not flexible) to have a cheap HW-Player. Because of that there are limitations for video and audio used to make a VCD. The bitrate for video is 1152kBit and 224kBit/sec MP2 audio. You are not allowed to use the -q option, dynamic GOP sizes and the video buffer is limited to 46kB. The image size is limited to 352x240 for NTSC, an to 352x288 for PAL. .PP If you have no VCD (only) player and you plan to use your DVD player then it is quite possible that the DVD player will be flexible enough to allow higher bitrates, dynamic GOP sizes, larger video buffer and so onVCD Audio creation Example .PP \fB> lav2wav stream.avi \(br mp2enc -V -o sound.mp2\fP .PP \fB-V\fP force VCD 2.0 compatible output. There the audio samplerate is fixed to 44.1kHz. And you can choose the audio bitrate for mono audio to be 64, 96 or 192kBit/sec. If you have stereo audio you can choose 128, 192, 224 or 384kBit/sec. For hardware players, you should stick to 44.1 224kBps Stereo layer 2 Audio.VCD Video creation Example .PP \fB> lav2yuv stream.avi \(br yuvscaler -O VCD \(br mpeg2enc -f 1 -r 16 -o video.mpg\fP .PP For VCD compatible output the -f 1 sets all options in mpeg2enc as needed. It seems that many VCD players (Avex for example) are not able to play MPEG streams that are encoded with a search radius greater than 16 so do not use the -r option to override the default of 16. .PP \fB> lav2yuv streams.eli \(br mpeg2enc -f 1 -4 1 -2 1 -S 630 -B 260 -P -o video.m1v\fP .PP Using \fB\&'-S 630'\fP means that mpeg2enc marks the stream so that mplex generates a new stream every 630MB. One important thing is the use of the \fB-B\fP option which specifies the non-video (audio and mplex information) bitrate. The -B value of 260 should be fine for audio with 224kBit and mplex information. For further information take a look at the encoding scripts in the scripts directory. The multiplexed streams should easily fit on a 650MB CD. .PP The default value (-B) is 700MB for the video. mpeg2enc marks automatically every stream at that size if the -B option is not used to set a different value. If you have a CD where you can write more data (perhaps as much as 800MB) you have to set the -S option or otherwise mpeg2enc will mark the stream at 700 MB, and mplex will split the stream there. Which is almost certainly not what you want. .PP VCD Multiplexing Example .PP \fB> mplex -f 1 sound.mp2 video.mpg -o vcd_out.mpg\fP .PP The -f 1 option turns on a lot of weird stuff that otherwise has no place in a respectable multiplexer!Creating the CD .PP The multiplexed streams have to be converted to an VCD compatible. This is done by vcdimager .PP \fB> vcdimager testvideo.mpg\fP .PP Creates a \fBvideocd.bin\fP, the data file, and a \fBvideocd.cue\fP which is used as control file for cdrdao. .PP You use cdrdao to burn the image. Cdrdao is yet another fine Sourceforge project which is found at: Notes .PP For MPEG-1 encoding a typical (45 minute running time) show or 90 odd minute movie from an analog broadcast a constant bit-rate of around 1800 kBit/sec should be ideal. The resulting files are around 700M for 45 minutes which fits nicely as a raw XA MODE2 data track on a CD-R. For pure digital sources (DTV or DVD streams and similar) VCD 1152 works fine. .PP \fBNote:\fP If you encode VBR MPEG-1 (-q) remember the Hardware was probably not designed to do the playback because it is not in the specifications. If it works be very happy. I've noticed that it helps when you have an MPEG-1 stream to tell vcdimager that it is an SVCD. vcdimager complains (but only with a warning and not a fatal error) but you should be able to burn it. This could convince the player to use different routines in its firmware and play it back correct but there is no guarantee of that.Storing MPEGs .PP If you record the data as XA mode 2 tracks you can fit appreciably more on a CD (at the expense of error correction/detection). You can use vcdimager to do this and vcdxrip (part of the vcdimager package) to extract (\(rqrip\(rq) the resulting files. For better Quality there are SVCD and XVCD and DVD. .PP Currently SVCD is fully supported with a pre-set format in mplex and tools to create disks. MPEG streams that can be played by DVD player hardware and software can readily produced using mpeg2enc/mplex .PP If your player doesn't support SVCD you may well find it can handle VCD streams that have much higher than standard bit-rates. Often as much as 2500kBit/sec is possible. The several brands of DVD players can also play wildly out of spec SVCD and VCD discs. With higher bit-rates and good quality source material it is worth trying mpeg2enc's -h flag which produce a stream that is as sharp as the limits of the VCD standard permits. .PP However, if your player supports it and you have the patience for the longer encoding times SVCD is a much better alternative. Using a more efficient MPEG format SVCD more than doubles VCD's resolution while typically producing files that are less than twice as big. .SH Creating SVCD .PP Super Video CD (SVCD) is an enhancement to Video CD that was developed by a Chinese government-backed committee of manufacturers and researchers. The final SVCD spec was announced in September 1998. A good explanation of the SVCD format from Philips can be found here: \&. .PP Record at full TV resolution (means: -d 1 for PAL this is 720x576) The resolution is for NTSC is 480x480 of PAL 480x576, so you know why you should record at full size.SVCD Audio creation Example .PP \fB> lav2wav stream.avi \(br mp2enc -V -e -o sound.mp2\fP .PP The SVCD specifications permit a much wider choice of audio rates, it is not necessary to use 224 kBit/sec. Any audio rate between 32 and 384 kBit/sec is permitted. The audio may be VBR (Variable Bit Rate). The -e enables the CRC error protection for the audio. The CRC has to be enabled to be SVCD standard compliant but it seems that most players don't pay attention to the CRC information. The CRC information need 2 bytes per Audio frame .PP The approximate frame length formula for MPEG-1 layer-II is: .PP .DS .sp .ft RR .nf (frame length in bytes) = 144 * (byte rate) / (sample rate) .DE .fi .ec .ft P .sp .PP If you have the typical VCD settings the CRC data needs about 0,27% of the whole data. In the worst case where you have a MONO 32k Bitrate stream the CRC data needs 1,92%\&.SVCD Video creation example .PP \fB> lav2yuv stream.avi \(br yuvscaler -O SVCD \(br mpeg2enc -f 4 -q 7 -I 1 -V 200 -o video.m2v\fP .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "-f 4" .nr bi 1 .PP sets the options for mpeg2enc to SVCD .IP "-q 7" .nr bi 1 .PP tell mpeg2enc to generate a variable bitrate stream .IP "-I 1" .nr bi 1 .PP tell mpeg2enc to assume that the original signal is field interlaced video where the odd rows of pixels are sampled a half frame interval after the even ones in each frame. The -I 0 (progressive output (no field pictures)) option will also work for PAL .if \n(ll>1 .RE .nr ll -1 .PP You can use lower bitrates but the SVCD standard limits \fBtotal bit-rate (audio and video) to 2788800 Bit/sec\fP\&. So with 224Kbps audio and overhead 2550 may already be marginally too tight. Since the SVCD format permits any audio rate between 32 and 384 kBit/sec you can save a few bits/sec by using 192k audio (or for non-musical material 160k). .PP SVCD supports variable bitrate (VBR), because MPEG-2 is usually VBR, but with the top video bitrate limit of 2500kBit/sec. With the -f 4 flag the encoder also sets dynamic GOP with a low limit of -g 6 and a high limit of -G 18. This saves a few bits/sec and improves the picture quality during scene changes. When encoding with -f 4 mpeg2enc ignores the video bitrate (-b) and search radius (-r) options. If you use -f 5 you have to specify the bitrate and other options to mpeg2enc. .PP Another possibility for movies in PAL (European style 25 frames/50 fields per sec) video is: .PP \fB> lav2yuv stream.avi \(br yuvscaler -O SVCD \(br mpeg2enc -f 4 -I 0 -V 300 -o video.m2v\fP .PP Movies are shot on film at 24 frames/sec. For PAL broadcast the film is simply shown slightly \(rqtoo fast\(rq at 25 frame/sec (much to the pain of people with an absolute pitch sense of pitch). The -I 0 flag turns off the tedious calculations needed to compensate for field interlacing giving much faster encoding. .PP Unfortunately, movies broadcast in NTSC (US style 30 frames/60 fields sec) video this will produce very poor compression. The \(rqpulldown\(rq sampling used to produce 60 fields a second from a 24 frame a second movie means half the frames in an NTSC *are* field interlaced. .PP Don't forget the -S and -B options mentioned above. You want the stream to fit on a CD don't you ?SVCD multiplexing example .PP \fB> mplex -f 4 -b 300 -r 2750 sound.mp2 video.m2v -o svcd_out.mpg\fP .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "-f 4" .nr bi 1 .PP tells mplex to mplex a SVCD .IP "-r 2750" .nr bi 1 .PP is the calculated Audio + Video Bitrate + 1-2% multiplex information .IP "-b 300" .nr bi 1 .PP is the buffer available on the playback device (the same value as used for the video encoding (mpeg2enc's -V option). .if \n(ll>1 .RE .nr ll -1 SVCD creating the CD .PP Example: .PP \fB> vcdimager -t svcd testvideo.mpg\fP .PP Creates a \fBvideocd.bin\fP, the data file, and a \fBvideocd.cue\fP which is used as control file for cdrdao. .PP Use cdrdao to burn the image as mentioned earlier. .PP \fBNOTE:\fPIf you want to build \(rqcustom\(rq VCD/SVCD you will need to use the mplex -f 2 and -f 5 switches. .PP \fBNOTE:\fPThe VCD and SVCD stuff may work on your HW player or not. There are many reports that it works quite well. Don't be worried if it does not work. Nor am I responsible for unusable CDs. (\(rqcoasters\(rq) .SH Creating DVD's .PP This statement was correct a few years ago: Everything in this section is new. The limitations I mention here might not exist in the current version. Currently (Dec. 2007) DVD creating is working. .PP You need obviously a DVD writer. I did own a Ricoh DVD+RW that works, and I know of a DVD-RAM writer that is able to to burn DVD-R. That disks also work with a DVD-Player. Now most DVD writers ar able to burn both media + and -, so that should not be a problem any more. Which programs you use for burning depends on the DVD writer drive. .PP For the creation and writing of the VOB, IFO and BUP files we use dvdauthor. Aviable from Sourceforge (you might have guessed it) \&.DVD Audio creation example .PP \fB> lav2wav stream.eli \(br mp2enc -o sound.mp2\fP .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .PP The sample rate has to be 48kHz. The mp2enc does create by default a sample rate of 48kHz. If it is not a 48kHz mp2enc will resample the audio to get the sample rate. If the audio is recorded at 48kHz then no resampling is needed and toolame can be used for the encoding (it is faster than mp2enc). .if \n(ll>1 .RE .nr ll -1 DVD Video creation example .PP \fB> lav2yuv stream.eli \(br mpeg2enc -f 8 -o video.m2v\fP .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "-f 8" .nr bi 1 .PP This sets the options correctly for a MPEG-2 video that is compliant with the DVD standard. The maximum bitrate is set to 7500kBps and the video buffer size is set to 230KB. The default quality factor is set to 8. mpeg2enc sets currenty no automatic sequence length as it does for VCD/SVCD. .if \n(ll>1 .RE .nr ll -1 .PP The other options to get a low bitrate and high quality stream can also be used to override the default settings mentioned above. You can also use yuvdenoise to increase the picture quality if the input data is noisy (from a VHS tape for example). A typical command will look like this: .PP \fBlav2yuv moby.eli \(br yuvdenoise \(br mpeg2enc -f 8 -q 7 -4 1 -2 1 -P -I 0 -N -o video_DVD.m2v\fPDVD multiplexing example .PP \fB> mplex -f 8 sound.mp2 video.m2v -o my_dvdlikestream.mpg\fP .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "-f 8" .nr bi 1 .PP Here again we specify that we want to have DVD like MPEG stream. mplex cannot do all the fancy things allowed for a DVD, but it is close enough that the HW-DVD players accept it. .IP "-o" .nr bi 1 .PP there we specify the output filename. .if \n(ll>1 .RE .nr ll -1 DVD creation example .PP This topic will be covered by the documentation of the dvdauthor program. For questions please see In general it will work like this: .PP \fB> dvdauthor -o output/ stream1.mpg stream2.mpg ... my_dvdlikestream.mpg; dvdauthor -T -o output/ \fP .PP You will get a directory with AUDIO_TS and VIDEO_TS directories. Burning the data from the disk to a DVD+-R/+-RW writer would be done like this: .PP \fBgrowisofs -Z /dev/scd2 -dvd-video mydvd/\fP .PP If you own a DVD+RW/+R drive a good place for more information is: page. You also need a version of the cdrtools with \fBdvd-video\fP support. The cdrtools 1.11a27 is known to work but newer versions already exist. .PP For other writers the commands to write a DVD will be different. You can get some more information in the dvdauthor package. There is no guarantee that it will work at all !!! .SH Creating DIVX Videos lav2avi.sh .PP Another way of creating DIVX is the program \fBmencoder\fP which is from the mplayer project. \&. For more information about mencoder please read mencoder/mplayer help and documents. A first and a second pass give at the end of pass hints for bitrate which can be used for encoding to specific size (650 MB, 700 MB and 800 MB). The script lav2avi.sh uses this information if provided (for short streams it is omitted by mencoder). Look for parameter \fIpreferedSize\fP in the script. You can also specify other parameters used for encoding with \fIencoderParam\fP option in the script. For a description of the usable parameters take a look in the mplayer/mencoder manual. .PP The outputfilename is that name of your input file (first option) but with the extension avi. If the size of file is less then specified by \fIpreferedSize\fP it's because the source was of very high quality (no noise) and the specified bitrate was higher than required. You usually get 700MB for 1.5 hour film at half image size with bitrate around 900 that means for divx good quality (assuming good quality source material of course). .PP The script does a 3 step encoding: .PP .nr ll +1 .nr t\n(ll 0 .if \n(ll>1 .RS .nr bi 1 .PP 1st step - audio encoding .nr bi 1 .PP 2nd step - first video pass .nr bi 1 .PP 3rd step - second video pass .if \n(ll>1 .RE .nr ll -1 .PP The mplayer/mencoder documentation deprecates the use of the 3 pass encoding method (it can cause A/V sync problems) and recommends the use of the 2 pass method. The mencoder/mplayer documentation is extensive and has many helpful hints (and a bitrate calculator in the TOOLS/ directory). .PP For encoding use the fast ffmpeg (lavc) codec. It gives nice results together with high good performance. For audio encoding mp3 is used. For encoding of all parts it uses unix pipes. This mean that you DO NOT need additional space on your hard drive where all glav manipulations will be done. For audio encoding the script uses a FIFO queue. .PP If you want to tweak the script for your own needs use these hints: .nr ll +1 .nr t\n(ll 0 .if \n(ll>1 .RS .nr bi 1 .PP Output of 1st step is file called \fBframeno.avi\fP with encoded audio .nr bi 1 .PP 2nd step is using \fBframeno.avi\fP and output is text file called \fIlavc_stats.txt\fP with timing informations .nr bi 1 .PP 3rd step is using \fBframeno.avi\fP and \fIlavc_stats.txt\fP for encoding the stream to the output file \fBmovie2.avi\fP .nr bi 1 .PP If you want change only video bitrate keep the file \fBframeno.avi\fP comment out the 1st step encoding and repeate 2nd and 3rd step. Dont forget to remove the line where the \fBframeno.avi\fP is removed. .if \n(ll>1 .RE .nr ll -1 .PP Optimizing the stream .PP Using filters helps to increase the image quality of constant bitrate (CBR) video streams. With VBR (variable bit rate) video the filesize is reduced. .PP Example: .PP \fB> lav2yuv stream.avi \(br yuvmedianfilter \(br mpeg2enc -o video.m1v\fP .PP Here the yuvmedianfilter program is used to improve the image. This removes some of low frequence noise in the images. It also softens the image a little. It takes a center pointer and averages the pixels around it that fall within the specified threshold. It then replaces the center pixel with this new value. You can also use the -r (radius) option for an other search radius. .PP \fBNOTE:\fPa radius greater than the default value of 2 is horrendously slow! .PP yuvmedianfilter has separate settings for luma and chroma. You can control the search radius and the trigger threshold independently. If you use a threshold of 0 then filtering is disabled (-t 0 disables luma filtering, -T 0 disables chroma filtering). .PP \fB> lav2yuv stream.avi \(br yuvmedianfilter -r 3 -t 4 -T 0 \(br mpeg2enc -o video.m1v\fP .PP This example uses a search radius of 3 pixels for the luma, a threshold of 4 (the default is 2), and disables filtering for the chroma components. Sometimes, depending on the source material, median filtering of the chroma can cause a slight color shift towards green. Filtering on the luma component (disabling the chroma filtering) is the solution to that problem. .PP Example: .PP \fB> lav2yuv stream.avi \(br yuvdenoise \(br mpeg2enc -o video.m1v\fP .PP Now we are using yuvdenoise to improve the image. The filter mainly reduces color and luminance-noise and flickering due to phase errors but is also effective at removing speckles. .PP yuvdenoise denoises interlaced if the input is interlaced. You can of course change the denoiser threshold (-g/t). Creating a black border can lower the bitrate of the encoded stream because pure black areas compress much better than noise (captures from analog sources such as VHS and 8mm usually have several lines at the time and bottom that are very noisy). For this you can use the scaler. .PP yuvdenoise uses a different approach to filter the noise. More information about how yuvdenoise works as well as descriptions of its options are found in the manpage. .PP If you have a high quality source you should lower the filter to levels like that: -g 0,255,255 -t 2,2,2. You might also use the mpeg2enc \fB-h/--keep-hf\fP option. That option tells mpeg2enc to keep as much high frequency information as possible. Using -h will greatly increase the bitrate (filesize). If the bitrate is too close to the maximum (set with -b) the encoder will have to decrease the quality to avoid exceeding the maximum bitrate. .PP A builtin filter in mpeg2enc is the -N/--reduce-HF option. This option is not really filter in the usual sense. Rather it changes how exactly the high frequency information is encoded. Often the high frequency is noise. You also have high frequencies on sharp borders or transitions. The -N option can have values between 0.0 and 2.0 where 0.0 does nothing (disables the high frequency quantizer boost) and 2.0 gives the maximum quantization boost. The value to use depends on the desired output quality and filesize. Values of -N less than 0.5 are very subtle while a value of 1.0 will achieve a good balance between bitrate reduction and output quality. Using -N values above 1.5 will noticeably reduce the sharpness of the output picture and are normally used only for poor quality sources (VHS tapes for example). .PP Using yuvmedianfilter's capability to only filter the chroma (-T) is moderately effective at reducing noise in dark scenes without softening the image during normal (brighter) scenes. Median filtering of the luma (-t) will produce a lower bitrate but can cause loss of detail (softening). Chroma only medianfiltering is less agressive and is a good choice to use in combination with yuvdenoise. .PP Combining the filters yuvdenoise, yuvmedianfilter and the mpeg2enc -N option gives a very fine degree of control over the bitrate (filesize). The reduction (or increase) in the bitrate depends on the source material and the exact encoding/filter options used. So we can give no exact numbers how much each option and combination will reduce the filesize, only guidelines. .PP Usually you should use the -N option in a range from 0.5 to 1.5. Below 0.5 it does not reduce the bitrate very much (but does preserve sharpness). At 1.5 and higher you will notice a softening in the video and possibly artifacts (halo/ringing) around edges of objects (text/subtitles especially). If you combine the filters you should use yuvdenoise and maybe afterwards yuvmedianfilter. Maybe yuvmedianfilter even after scaling. Having yuvmedianfilter in the chain does not reduce the bitrate that much. Often the use of yuvdenoise is enough. The yuvmedianfilter helps much if you have low quality sources, and not that much if you already have a rather good quality. When you combine the filter and option you will very likely reduce the filesize to about the half of the filesize without using the options and programs. .PP In general aggressive filtering will produce smaller files (lower bitrate) but reduce the quality (details) of the picture. Less aggressive filtering/processing will preserve more detail but result in larger files. .PP Example: .PP \fB> lav2yuv stream.avi \(br yuvkineco -F 1 \(br mpeg2enc -o video.m1v\fP .PP yuvkineco is used for NTSC sources. It does the conversation from 30000.0/1001.0 (about 29.97) fps to 24000.0/1001.0 (about 23.976) fps, you can call it \(rqreverse 2-3 pulldown\(rq more info about this in the README.2-3pulldown. yuvkineco does only remove NTSC specific problems. .PP If you want to improve the image you should also use yuvdenoise: .PP \fB> lav2yuv stream.avi \(br yuvkineco \(br yuvdenoise \(br mpeg2enc -o video.m1v\fP .PP Example .PP \fB> lav2yuv stream.avi \(br yuvycsnoise \(br mpeg2enc -o video.m1v\fP .PP yuvycsnoise is also used for NTSC and is specialized for NTSC Y/C separation noise. If video capture hardware has only a poor Y/C separator then at vertical stripes (especially red/blue) noises appear which seem checker flag and bright/dark invert per 1 frame. yuvycsnoise reduces noises of this type. You can also use different thresholds for luma/chroma and the optimizing method. This filter is not needed with working with DV (Digital Video) data. .PP yuvycsnoise works only correct when we have NTSC with: .PP .nr ll +1 .nr t\n(ll 0 .if \n(ll>1 .RS .nr bi 1 .PP full height (480 lines) .nr bi 1 .PP full motion captured (29.97 fps) .nr bi 1 .PP captured with poor Y/C separator hardware .if \n(ll>1 .RE .nr ll -1 .PP For more information about the yuvkineco and yuvycsnoise read the README in the yuvfilters directory. .PP If you want to experiment to determine the optimal settings for the denoiser, scaler and so on replace the mpeg2enc with yuvplay. yuvplay plays back the yuv frames so you can see if the options you have chosen are making the thing better or worse. .PP A command would look like this: .PP \fB> lav2yuv stream.eli \(br yuvdenoise -options \(br yuvscaler -options \(br yuvplay\fP .PP If you want to know how much each tool lowers the average bitrate. You can use this table to see what you can expect if you have a full size video and want to create a DVD with a qality factor of 5 and the allowed maximal bitrate of 8500kb/sec. .PP .nr ll +1 .nr t\n(ll 0 .if \n(ll>1 .RS .nr bi 1 .PP no denoising : 8300 kb/s (mostly hitting the upper bound) .nr bi 1 .PP yuvenoise : 7700 kb/s .nr bi 1 .PP mpeg2enc --reduce-hf : 7400 kb/s .nr bi 1 .PP yuvdenoise + yuvmedianfilter : 6000 kb/s .nr bi 1 .PP yuvdenoise + mpeg2enc --reduce-hf : 4900 kb/s .nr bi 1 .PP all of the above : 3600 kb/s .if \n(ll>1 .RE .nr ll -1 .PP While \fB-N\(br--reduce-hf\fP or yuvdenoise alone is only a modest improvement, together they reduce the bitrate substantially. There is not really much visible difference between using yuvdenoise alone and yuvdenoise with mpeg2enc --reduce-hf. The usefull values are between 0.0 and 1.5. Where you can say that the higher the quality factor you want, the less this option improves. At a quality factor 4 you save using -N 1.0 about 1%\&. If you want a quality factor of 9 and use the -N 1.0 you might save up to 40%\&. But you might save less, that depends on the video you encode!!! .PP If you ask yourself why not alyways use all of the above filters? The answers are that the image softens (loss of detail) and the encoding time increases. Most of the filters each require about the same amount of time as mpeg2enc needs for encoding the video. .PP If you have very high quality material and want to keep every detail you should try to use the mpeg2enc --keep-hf\(br-h on the other hand. .PP \fBNote:\fP The bitrate reduction you have depends on the material and on the noise of the images. .PP A other interresting mpeg2enc option is the \fB-E\(br--unit-coeff-elim\fP option. This option is disabled by default. If you enable it, a special \&"unit coefficient elimination\&" algorithm, is applied to the encoded picture blocks. Basically this proceedure forces blocks of a type that do not carry much information (but use many bits to encode) to be skipped. A negative value examines the base (DC) as well as the AC coefficients. A positive value means that only texture (AC) coefficients are examined and possibly zeroed. The recommended values lies between -20 and +20. You usually can expect that you have a 5% decreased filesize. The amount the bitrate is reduced can vary considerably, the range spans from not really noticable up to 20%\&. .PP If you think a other quantization matrice will help use the \fB-K\(br--custom-quant-matrices\fP option. You can try out your own quanitsation matrice or use another builtin than the default. You can choose between kvcd, tmpgenc, hi-res, and your own. Using -K usually makes the file smaller except the hi-res option (that makes files considerably larger). Exact guidelines are hard to give, sometime a other quanitsation matrix saves almost nothing, and the next time up to 20%\&. More than 20% is very unlikely, 10-15% at a moderate qualityfactor (-q 8-10) are likely. The higher the qualiy the less it saves, at a quality factor of 4-6 the reduction in bitrate may only be 5% .PP One thing to keep in mind is that the unit coefficient elimination and the quantization matrix option are decreasing the bitrate while maintaining the same visual quality. At this point you can chose to use the smaller file to increase the amount of video that will fit on the disc media or you could chose to increase the quality even more by lowering the -q value by 1 and make a larger (but higher quality) file. .SH Scaling and offset correction .PP The basic scaling is described in the \fBConverting video\fP section .PP The scaling takes a part of the picture and scales it to a larger or smaller size. The scaling is done by yuvscaler: .PP \fBlav2yuv test.eli \(br yuvscaler -I USE_400x400+50+100 \(br yuvplay\fP .PP Here we only take part of the picture and scale it up to the size of the original frame. But yuvscaler also changes the pixel aspect ratio. That means when you look at the stream using yuvplay it looks like a square in our example. After scaling, if the sample (pixel) aspect ratio were not changed, the video would not display with the proper aspect ratio. Yuvscaler compensates by adjusting the sample aspect ratio. If you have a interlaced video, the height and HeightOffset have to be a multiple by 4 if the video is interlaced. Else the values (width, height, widthoffset, heightoffset) have to be a multiple of 2. .PP A problem that cannot be solved easily with scaling is when the picture is not centered horizontal. On one side you have no black pixels and on the other you have 30 for example. Scaling is here is the wrong solution. y4mshift is the perfect solution because it can shift the image to the left or right. .PP \fBlav2yuv test.eli \(br y4mshift -n 20 \(br mpeg2enc -f 3 -b 4000 -q 10 -o video.m2v\fP .PP That will shift the image 20 pixels to the right. If you use a negative the image is shift to the left. You have to use a even number. The inserted pixels are set to black. .PP Some might wonder why the image is not centered and there is a black border around the image when you view what you have recorded. The reason for the black border is in history of the CRT (Cathode Ray Tube) TV technology. The history of the TV standard s a very interesting story but that topic is described in other (large) books. .PP The TV does not show the full picture. A part of the picture is not shown because the TV sets overscan (sometimes as much as 10% but more common today is 5%). But when you capture the video with a card you see the whole image including the border that TVs lose due to overscanning. A horizontal offset is usually not a problem of the capture card. It is a problem when the film is broadcast and not well synchronized with the image. This means that the scan of the source not exactly synchronized with the carrier signal, you wont see that on TV. .SH Frame rate conversion .PP Ever needed to convert the framerate from PAL to NTSC or the other direction around ? Or something much simpler like converting the framerate from 24FPS to 24000:1001 for conversation from a film frame rate to a valid NTSC frame rate. .PP Than \fByuvfps\fP is your program. It can lower the framerate by dropping frames or create a higher framerate by replicating frames. If you have a wrong framerate in the header you can only change the header of the YUV stream and not modify the stream. .PP Because the frames are only replicated (copied) you should denoise first and then change the framerate and scale at als last step. If you have a interlaced source you should also deinterlace before changeing the framerate. If you create a higher frame rate it is very likely that you will have weird flickers when you play it back. If you convert PAL to NTSC (30000:1001 FPS about 29,97 FPS) the frame rate will lower by about the factor 480/576 (NTSC lines / PAL lines). If you lower the frame rate from PAL to NTSC (at 24000:1001) or NTSC FILM (24FPS) the bitrate will be about (480 Lines * 24 FPS) / (576 Lines * 25FPS). If you change the frame rate before denoising the yuvdenoise will have problems finding the noise across the frames and the needed bandwith will slightly increase. .PP Example .PP \fB> lav2yuv video.eli \(br yuvfps -r 30000:1001 \(br yuvscaler -O SVCD \(br mpeg2enc -f 4 -o video_ntsc_svcd.m2v\fP .PP This is a example to convert the source video to a NTSC video running at 30000:1001 FPS (or about 29,97FPS) at SVCD size. .PP Example .PP \fB> lav2yuv video.eli \(br yuvdenoise \(br yuvfps -r 24000:1001 \(br yuvscaler -O SIZE_720x480 \(br mpeg2enc -f 3 -b 4000 -q 7 -o video_ntsc.m2v\fP .PP This example shows how you should use the tools. Denoise first and than change the framerate and in the last step change the image size. .PP It can happen that yuvscaler or mpeg2enc do not detect the TV norm correct. If that happens you have to add the norm option \fB-n n/p/s\fP to the program that chooses the wrong norm. .PP If you know that the header tells the wrong framerate, you can simply change the framerate of the yuv header this way: .PP \fB> lav2yuv video.eli \(br yuvfps -r 25:1 -c \(br mpeg2enc -f 3 -b 4000 -q 7 -o video_pal.m2v\fP .PP You need the \fB-c\fP option. To tell yuvfps that it only should change the header of the stream. With the \fB-r 25:1\fP you tell yuvfps the frame rate it should write into the header. In your example the PAL frame rate of 25 FPS. You always have to use the fractional form. .PP If you know that the header is wrong, and you need a different output bitrate you can do this in a single step: .PP \fB> lav2yuv video.eli \(br yuvfps -s 24:1 -r 25:1 \(br mpeg2enc -o video.m1v\fPTranscoding of existing MPEG-2 .PP For transcoding existing MPEG-2 streams from digital TV cards or DVD a lower data-rate than for broadcast will give good results. Standard VCD 1152 kbps typically works just fine for MPEG-1. The difference is in the Signal/Noise ratio of the original. The noise in the analog stuff makes it much harder to compress. .PP You will also need to manually adjust the audio delay offset relative to video when multiplexing. Very often around 150ms delay seems to do the trick. .PP You have to download the ac3dec and mpeg2dec packages. You can find them at their homepage: mpeg2dec ( ) and ac3dec. For decoding the audio streams mpg123 and mplayer can be very helpfull. You also need sox and toolame. .PP In the scripts directory there is a \fBmpegtranscode\fP script that does most of the work. .PP So transcoding looks like this: .PP \fB> mjpegtranscode -V -o vcd_stream mpeg2src.mpg\fP .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "-V" .nr bi 1 .PP set's the options so that a VCD compatible stream is generated .IP "-o vcd_stream" .nr bi 1 .PP a vcd_stream.m1v (video) and vcd_stream.mp2 (audio) is created .IP "mpeg2src.mpg" .nr bi 1 .PP specifies the source stream .if \n(ll>1 .RE .nr ll -1 .PP The script prints also something like this: .PP \fB> SYNC 234 mSec\fP .PP You will need to adjust the audio/video startup delays when multiplexing to ensure audio and video are synchronized. The exact delay (in milliseconds) that you need to pass to mplex to synchronize audio and video using the \(rq-v\(rq\&" is printed by the extract_a52 tool labeled \(rqSYNC\(rq when run with the \(rqs\(rq flag. This is the value th mjpegtranscode script prints out after the \fBSYNC\fP word. .PP Then you need to multiplex them like this: .PP \fB> mplex -f 1 -O 234 vcd_stream.mp2 vcd_stream.m1v -o lowrate.mpg\fP .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "-f 1" .nr bi 1 .PP Mux format is set to VCD .IP "-O 234" .nr bi 1 .PP Video timestamp offset in mSec, generated by the mjpegtranscoding script, there negative values are allowed .IP "vcd_stream.mp2 & vcd_stream.m1v" .nr bi 1 .PP generated files by the script .IP "lowrate.mpg" .nr bi 1 .PP the VCD compatible output stream .if \n(ll>1 .RE .nr ll -1 .PP Here we have a SVCD (MPEG-2 video) example: .PP \fB> mjpegtranscode -S -o svcd_stream mpeg2src.mpg\fP .PP You have to multiplex it with: .PP \fB> mplex -f 4 -O 234 svcd_stream.mp2 svcd_stream.m2v -o lowrate.mpg\fP .PP \fBProblem:\fP There is sometimes a problem with NTSC and VCD playback because movies may be recoded with 3:2 pulldown NTSC with 60 fields/sec. mpeg2dec is designed for playback on computers and generates the original 24frames/sec bitrate. If you encode the video now 30frames/sec video is created. This video is now much too short for the encoded audio. .PP The transcoding can be made to work but it must be done manually: .PP \fB> mpeg2dec -s -o pgmpipe mpeg2src.mpg \(br pgmtoy4m -a 59:54 -r 25:1 -i t \(br mpeg2enc -I 0 -f 4 -q 9 -V 230 -p -P -o svcd_stream.m2v\fP .PP The -p tells mpeg2enc to generate header flags for 3:2 pull down of 24fps movie. It may also work if you do not add the -p flag. You do not need the -p flag when transcoding to VCD format because it is not supported in mpeg1. .SH If you want to do every step on your own it will look something like this .PP Extracting Audio: .PP \fB> cat test2.mpg \(br extract_a52 - -s \(br ac3dec -o wav -p sound.wav 2>/dev/null\fP .PP One of the first lines showed contains the label \(rqSYNC\(rq you have to use this time later when multiplexing. The 2>/dev/null redirects the output of ac3dec to /dev/null. In the next step you generate the mpeg audio file: .PP \fB> cat sound.wav \(br mp2enc -V -v 2 -o audio.mp2\fP .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "-V" .nr bi 1 .PP forces VCD format, the sampling rate is converted to 44.1kHz from 48kHz .IP "-v 2" .nr bi 1 .PP unnecessary but if you use it mp2enc tells you how many seconds of the audio file are already encoded. .IP "-o" .nr bi 1 .PP Specifies the output file. .if \n(ll>1 .RE .nr ll -1 .PP \fBcat test2.mpg \(br extract_a52 - -s \(br ac3dec -o wav \(br sox -t wav /dev/stdin -t wav -r 44100 /dev/stdout \(br toolame -p 2 -b 224 /dev/stdin audio.mp2\fP .PP One of the first lines again output contains the label \(rqSYNC\(rq\&. You have to use this time (referred to as \&"SYNC_value\&" below) when doing the multiplexing. .PP For VCD creation use: .PP \fB> mpeg2dec -s -o pgmpipe test2.mpg \(br pgmtoy4m -a 59:54 -r 25:1 -i t \(br mpeg2enc -s -o video_vcd.m1v\fP .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "" .nr bi 1 .PP mpeg2dec: .IP "-s" .nr bi 1 .PP tells mpeg2dec to use program stream demultiplexer .IP "-o pgmpipe" .nr bi 1 .PP the output format of the pictures, suitable for pgmtoy4m .if \n(ll>1 .RE .nr ll -1 .PP Mplex with: .PP \fB> mplex -f 1 -O SYNC_value audio.mp2 video_vcd.m1v -o vcd_stream.mpg\fP .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "-f 1" .nr bi 1 .PP generates an VCD stream .IP "-O SYNC_value" .nr bi 1 .PP the value mentioned above .if \n(ll>1 .RE .nr ll -1 .PP For SVCD creation use: .PP \fB> mpeg2dec -s -o mpeg2src.mpg \(br pgmtoy4m -a 59:54 -r 25:1 -i t \(br mpeg2enc -f 4 -q 9 -V 230 -o video_svcd.mpg\fP .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "-q 9" .nr bi 1 .PP Quality factor for the stream (VBR stream) (default q: 12) .IP "-V 230" .nr bi 1 .PP Target video buffer size in KB .IP "-o" .nr bi 1 .PP Output file .if \n(ll>1 .RE .nr ll -1 .PP Mplex with: .PP \fB> mplex -f 4 -b 230 audio.mp2 video_svcd -o svcd_stream.mpg\fP .PP .nr ll +1 .nr t\n(ll 2 .if \n(ll>1 .RS .IP "-f 4" .nr bi 1 .PP generate an SVCD stream .IP "-b 200" .nr bi 1 .PP Specify the video buffer size by the playback device. .if \n(ll>1 .RE .nr ll -1 .PP For other video output formats this might work: .PP \fB> mpeg2dec -s -o pgmpipe test2.mpg \(br pgmtoy4m -a 59:54 -r 25:1 -i t \(br yuvscaler -O SIZE_320x200 -O NOT_INTERLACED \(br mpeg2enc -o strange_video.m1v\fP .PP If you want to edit mpeg streams this also works but in a slightly different way. For demultiplexing you can use bbdmux from the bbtools package. Splits out either video or audio very cleanly. You can't get it any more from the homepage from Brent Beyler, it can still be found when you search for it using that keywords \(rq bbtools linux -suse -blackbox\(rq\&. Currenty it can be found at: .PP First run: .PP \fB> bbdmux myvideo.mpg\fP .PP You should get something like this: .PP .DS .sp .ft RR .nf Found stream id 0xE0 = Video Stream 0 Found stream id 0xC0 = MPEG Audio Stream 0 Found stream id 0xBE = Padding Stream .DE .fi .ec .ft P .sp .PP Extract audio with: .PP \fB> bbdmux myvideo.mpg 0xC0 audio.mp1\fP .PP Convert it to wav: .PP \fB> mpg123 -w audio.wav audio.m1v\fP .PP Extract video with: .PP \fB> bbdmux myvideo.mpg 0xE0 video.m1v\fP .PP Converting video to an mjpeg avi stream: .PP \fB> mpeg2dec -o pgmpipe video.m1v \(br pgmtoy4m -a 59:54 -r 25:1 -i t \(br yuv2lav -f a -o test.avi\fP .PP Then adding the sound to the avi: .PP \fB> lavaddwav test.avi audio.wav final.avi\fP .PP If the source video has already the size of the target video use -o YUV. Using YUVh makes the video the half size! The rest can be done just like editing and encoding other streams. If you have videos with ac3 sound you only have to adapt the commands above. .PP Extracting Audio: .PP \fB> cat test2.mpg \(br extract_a52 - -s \(br ac3dec -o wav 2>dev/null >sound.wav\fP .PP Extract video and adding the audio in a single step : .PP \fB> mpeg2dec -s -o pgmpipe \(br pgmtoy4m -a 59:54 -r 25:1 -i t \(br yuvscaler -O VCD \(br yuv2lav -f a -q 85 -w sound.wav -o test.avi\fP .PP \fBNOTE:\fPYou need much disk space. 1GB of video has a size of about 2GB at SVCD format and of course disk space is needed for some temp files. Converting the video to mjpeg also takes some time. On my Athlon 500 I never get more than 6-7 Frames a second. You loose quality each time you convert a stream into an other format! Trading Quality/Speed .PP If absolute quality is your objective a modest improvement can be achieved using the -4 and -2 flags. These control how ruthlessly mpeg2enc discards bad looking matches between sections of adjacent frames during the early stages of the search when it is working with 4*4 and 2*2 clusters of pixels rather than individual pixels. Setting -4 1 -2 1 maximizes quality. -4 4 -2 4 maximizes speed. Note that because the statistical criteria mpeg2enc uses for discarding bad looking matches are usually fairly reliable the increase/decrease in quality is modest (but noticeable). .PP Reducing the radius of the search for matching sections of images also increases speed. However due to the way the search algorithm works the search radius is in effect rounded to the nearest multiple of 8. Furthermore on modern CPU's the speed gained by reducing the radius below 16 is not large enough to make the marked quality reduction worthwhile for most applications. .SH Creating streams to be played from disk using Software players .PP Usually MPEG player software is much more flexible than the hardware built into DVD and VCD players. This flexibility allows for significantly better compression to be achieved for the same quality. The trick is to generate video streams that use big video buffers (500KB or more) and variable bitrate encoding (the -f / -q flag to mpeg2enc). Software players will often also correctly play back the more efficient MPEG layer 3 (yes, \(rqMP3\(rq audio format. A good MP3 encoder like lame will produce results comparable to layer 2 at 224Kbps at 128Kbps or 160Kbps.SMP and distributed Encoding .PP Distributed encoding is a quite dark theory for the typical Machine in 2013. So most users can safely skip that point. SMP Encoding is more interresting for the average computer .PP The degree to which mpeg2enc tries to split work between concurrently executing threads is controlled by the -M or --multi-thread [0..32] option. This optimizes mpeg2enc for the specified number of CPUs. By default (-M 1) mpeg2enc runs with just a little multi-threading: reading of frames happens concurrently with compression. This is done to allow encoding pipelines that are split across several machines (see below) to work efficiently without the need for special buffering programs. If you are encoding on a single-CPU machine where RAM is tight you may find turning off multithreading altogether by setting -M 0 works slightly more efficiently. .PP For SMP machines with two ore more processors you can speed up mpeg2enc by setting the number of concurrently executing encoding threads's you wish to utilize (e.g. -M 2). Setting -M 2 or -M 3 on a 2-way machine should allow you to speed up encoding by around 80%\&. Values above 3 are accepted but have very little effect even on 4 cpu systems. .PP If you have a real fast SMP machine (currently 1.Aug.03) like a dual Athlon MP 2600 or something similar the -M 2 and the filtering might not keep both (or more) CPU's busy. The use of the buffer or bfr program with a 10-20MB buffer helps to keep both CPUs busy. .PP Obviously if your encoding pipeline contains several filtering stages it is likely that you can keep two or more CPU's busy simultaneously even without using -M. Denoising using yuvdenoise or yuvmedianfilter is particular demanding and uses almost as much processing power as MPEG encoding. .PP It you more than one computer you can also split the encoding pipeline between computers using the standard 'rsh' or 'rcmd' remote shell execution commands. For example, if you have two computers: .PP \fB> rsh machine1 lav2yuv \(rqmycapture.eli \(br yuvscaler -O SVCD \(br yuvdenoise\(rq \(br mpeg2enc -f 4 -o mycapture.m2vi\fP .PP Here the computer where you execute the command is doing the MPEG encoding and \(rqmachine1\(rq is the machine that is decoding scaling and denoising the captured video. .PP Obviously, for this to work \(rqmachine1\(rq has to be able to access the video and the computer where the command is executed has to have space for the encoded video. In practice, it is usually well worth setting up network file-storage using \(rqNFS\(rq or other packages if you are going to do stuff like this. If you have three computers you can take this a stage further, one computer could do the decoding and scaling, the next could do denoising and the third could do MPEG encoding: .PP \fB> rsh machine1 \(rqlav2yuv mycapture.eli \(br yuvscaler -O SVCD\(rq \(br yuvdenoise \(br rsh machine3 mpeg2enc -f 4 -o mycapture.m2v\fP .PP \fBNOTE:\fPHow the remote command executions are set up so that the data is sent direct from the machine that produces it to the machine that consumes it. .PP In practice for this to be worthwhile the network you are using must be fast enough to avoid becoming a bottleneck. For Pentium-III class machines or above you will need a 100Mbps Ethernet. .PP For really fast machines a switched 100MBps Ethernet (or better!) may be needed.Setting up the rshd (\(rqRemote Shell Daemon\(rq needed for rsh to do its work and configuring \(rqrsh\(rq is beyond the scope of this document, but its a standard package and should be easily installed and activated on any Linux or BSD distribution. .PP Be aware that this is potentially a security issue so use with care on machines that are visible to outside networks!Interoperability .PP Quicktime files capturing using lavrec can be edited using Broadcast2000. But Broadcast2000 is not available any more on heroinewarrior. mjpeg AVI files captured using the streamer tool from the xawtv package can be edited and compressed and played back using software. Hardware playback is not possible for such files due to limitations in the Zoran hardware currently supported. Videos recorded with NuppelVideo can also be processed with the mjpeg tools. .PP If you have a Macintosh (MAC) and want to use the mjpeg tools look there: .PP MPEG files produced using the tools are know to play back correctly on: .PP .nr ll +1 .nr t\n(ll 0 .if \n(ll>1 .RS .nr bi 1 .PP dxr2 (hardware decoder card) .nr bi 1 .PP xine .nr bi 1 .PP xmovie .nr bi 1 .PP mplayer .nr bi 1 .PP vlc .nr bi 1 .PP MPEG-1 only: gtv .nr bi 1 .PP MS Media player version 6 and 7 and later version .nr bi 1 .PP severals Software based DVD Player .if \n(ll>1 .RE .nr ll -1 .PP To find out what you HW-player (most of the time DVD player) can do take a look at: .PP It seems that the MS Media player likes MPEG-1 streams more if you have used -f 1 when multiplexing. .PP If you have any problems or suggestions feel free to mail me (Bernhard Praschinger): There is a lot of stuff added from the HINTS which Andrew Stevens created. Wolfgang Goeller and Steven M. Schultz checked the document for bugs and spelling mistakes. .PP And to the people who have helped me with program descriptions and hints, \fBthanks\fP .SH "SEE ALSO" .br .LP The mjpeg homepage is at: .br http://mjpeg.sourceforge.net/ .br http://sourceforge.net/projects/mjpeg vcdimager is aviable at: .br http://www.vcdimager.org/ .br cdrdao is aviable at: .br http://cdrdao.sourceforge.net/index.html .br Linux Video Studio is aviable at: .br http://ronald.bitfreak.net The lavtools: .br .BR jpeg2yuv(1), .BR lav2wav(1), .BR lav2yuv(1), .BR lavpipe(1), .BR lavplay(1), .BR lavrec(1), .BR lavtrans(1), .BR lavinfo(1), .BR mp2enc(1), .BR mpeg2enc(1), .BR mplex(1), .BR ppmtoy4m (1), .BR pnmtoy4m (1), .BR yuv2lav(1), .BR yuvdenoise(1), .BR yuvkineco(1), .BR yuvmedianfilter(1), .BR yuvplay(1), .BR yuvfps(1), .BR yuvscaler(1), .BR yuvycsnoise(1), .BR y4mblack(1), .BR y4mcolorbars(1), .BR y4mdenoise(1), .BR y4mhist(1), .BR y4minterlace(1), .BR y4mshift(1), .BR y4mstabilizer(1), .BR y4mtopnm(1). .BR y4mtoppm(1). .br Tools without a man page: lavaddwaw, glav mjpegtools-2.1.0/docs/yuv2lav.10000644000175000017500000000701412216627211016635 0ustar glowwormglowworm.TH "yuv2lav" "1" "2 June 2001" "MJPEG Tools Team" "MJPEG tools manual" .SH "NAME" yuv2lav \- encodes lavtool's raw YUV frame streams into MJPEG files .SH "SYNOPSIS" .B yuv2lav .RB [ -f \| \ a | A | q | m ] .RB [ -q .IR num ] .RB [ -b .IR num ] .RB [ -I .IR num ] .RB [ -m .IR num ] .RB [ -v .IR num ] .RB [ -w .IR file ] .B -o .I output-file .SH "DESCRIPTION" yuv2lav is a simple MJPEG encoder for raw YUV frame streams as they are emitted by .BR lav2yuv "(1) or " lavpipe "(1)," for example. It reads its input from stdin and is capable of writing AVI and Quicktime. .SH "OPTIONS" The command line options allow to specify the output file name, JPEG encoding quality and the amount of memory that will be allocated for JPEG compressed data. .TP .BI -o \ output-file This (compulsorary) option sets the name of the file that yuv2lav will write its output to. If the output file contains a % (e.g. file%02d.avi), the output will be written to multiple files in case this is necessary (file00.avi, file01.avi and so on). .TP .BR -f \| \ a | A | q This sets the output file format, which has to be one of .br .B \ a - for AVI file output, .br .B \ A - for AVI with reversed fields, .br .B \ q - for Quicktime output or .br AVI with reversed field of course only makes sense if yuv2lav's feed is an interlaced video source and should only be needed if you experience frame reversal problems in your output. If you don't use that option yuv2lav will set the output format to AVI if the last 3 char are avi, or to Quicktime if you use mov. If you use the -f option it overides the setting in the filename .TP .BI -q \ num This option specifies the JPEG encoding quality as passed through to libjpeg. The default value is 80, .I num must lie within 24...100 inclusive (think of it as percentage values, although with a lossy compression algorithm like JPEG, keeping 100% of the original quality is of course not really possible). .TP .BI -b \ num This option specifies the size of the buffer (in kBytes) that yuv2lav allocates in order to store the compressed JPEG data in it. The default value (256k) is perfectly enough for 100% quality full sized PAL/NTSC, but if you want to compress Super-Mega-HDTV or if you are low on memory, you can use this option to suit your needs. .TP .BI -m \ num This is the maximum size (in MB) per file. Normally this depends on the output file type. .TP .BI -I \ num Force a specific interlacing type. 0 means no interlacing, 1 means top-field-first, 2 means bottom-field-first. .TP .BI -w \ file This is the WAV file containing audio data to be combined with the video stream into the output file. .TP .BI -v \ num Verbosity level. 0 means only print error messages, 2 prints full debug output. .TP .B -? Display a synopsis of the command syntax. .SH "EXAMPLES" .TP lav2yuv movie.avi | yuv2lav -fq -q 30 lowbitrate.qt would recompress movie.avi as a low bit rate Quicktime file. .TP lavpipe input.pli | yuv2lav -q80 output.avi would save the movie assembled by lavpipe as a single AVI file. .SH "BUGS" If you experience any problems with this tool, please feel free to contact the developers (see below). .SH AUTHOR This man page was written by pHilipp Zabel. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: .br \fImjpeg\-users@lists.sourceforge.net\fP .br .br For more info, see our website at .br \fIhttp://mjpeg.sourceforge.net/\fP .SH "SEE ALSO" .BR lav2yuv "(1), " lavpipe "(1), " lavplay "(1)," .BR lavrec "(1), " mpeg2enc "(1), " yuvscaler "(1)" mjpegtools-2.1.0/docs/FAQ.txt0000644000175000017500000002453507755317461016341 0ustar glowwormglowworm 1. Questions about Motion JPEG (MJPEG) (and MJPEG AVI) 1.1 What is MJPEG? MJPEG stands for Motion JPEG and is basically video encoded as a series of JPEG compressed images. Unfortunately, it is not a proper rigorously defined standard like MPEG. For a start MJPEG really only says frames of video are encoded as JPEG. To package them together into a sequence with audio and synchronisation information a "carrier" format is needed. This is typically either Microsoft's "AVI" or Apple's Quicktime format. 1.2 I've created an MJPEG AVI or Quicktime file with mjpegtools but it won't play on my Windows/MacOS machine (or vice versa!). The Problem is that lack of rigorous definition of MJPEG. The JPEG format has a lot of options and, due to the need for speed, the JPEG encoders/decoders used in MJPEG codecs only support a small subset. Worse, the different codecs support different subsets. Its a pain! 1.3 Why is there a 2GB file-size restriction on individual AVI files created using mjpegtools? The original AVI format is inherently limited to files no larger than 2GB as certain internal pointers are only held as 32-bit values. The "OpenDML" extensiojns subsequently extended the format to support much larger files. Unfortunately, the mjpegtools do not currently support this format. 1.4 How do I get around the 2GB file-size restriction on individual AVI files created using mjpegtools? The work-around is to use Quicktime or multiple AVI files. All the mjpegtools will work with a seq of AVI's just as happily as they would with a single file. To create a sequence of AVI's using lavrec you use a pathname pattern rather than a pathname. A "%d" in the pathname you specify is replaced by a sequence number (1,2,3,4,5,6) and so on and files created as needed. 2. Questions about MPEG VCD, SVCD and DVD 2.1 What is the difference between MPEG-1 and MPEG-2. MPEG-2 is (basically) a superset of MPEG-1 that is much more flexible in terms of data-rates and formats and can handle interlaced video. There's more to it than that but most of the the other differences relate to support for digital TV broadcasting. 2.2 How does MPEG-1/MPEG-2 compare to MPEG-4 video (or "DivX") The MPEG-4 video compression standard provides somewhat better compression at low-to-medium bit-rates (up to around 1Mbps). Basically, MPEG-4 still gives useful pictures where MPEG-1 or MPEG-2 would start to break down. To do this it has special encoding modes for efficiently encoding subsampled (down-scaled) images and for masking the artefacts caused by very low data-rate encoding. At higher data-rates these features aren't really needed and bring relatively little. MPEG's own figures suggest MPEG-4 gains about 15% over MPEG-1/2 at around 1MBps, more at lower rates less and between 5-10% at datarates above 2Mbps. These figures are, however, for encoders working with comparable parameters. One reason why DivX seemed to be such a big leap over MPEG-1 was that most MPEG-1 encoders generated very conservative MPEG-1 like that used for standard VCD disks. When encoding for a Software decoder running on a computer lots of extra MPEG features can be used to improve compression. Top amoungst these is the use of variable bit rate encoding and assuming large buffers in the decoder. Basically, if you want to put an acceptable quality encoding of a Movie onto 1 CD MPEG-4 is the sensible choice. If you want higher quality and are willing to use 2 CD's or more MPEG-1/2 will work at least as well and will allow you to use VCD and SVCD formats that can be played on DVD players. If you need to encode interlaced material at high quality MPEG-2 is a sensible choice because MPEG-4 cannot encode interlaced video directly. It needs it to be deinterlaced first. 2.3 What is this "multiplexing" business? An MPEG video stream (as found say on a DVD) is actually one or more video streams proper interleaved with one or more audio streams in a special carrier format. The carrier format also holds the synchronisation and timing information needed to deliver the audio and video data to the decoder at just the right time to avoid glitches without overflowing its memory buffers. Multiplexing takes the video and audio streams specified and wraps them up in the carrier format (generating the synchronisation and timing information as it goes). The latest versions of the multiplexer "mplex" don't actually need intermediate files for the video and audio streams. You can feed them direct from the encoders via fifo's (named pipes - see the "mkfifo" command). See 4.3 2.4 Why do I need to use special settings to encode and multiplex MPEG for VCD, SVCD or DVD. The MPEG standards are *huge* with many rarely-used or even downright exotic options. For use in consumer disk players particular narrowly defined subsets of MPEG were specified that also added additional features (e.g. Dolby Digital and DTS audio for DTS) and special extensions for the disk application (e.g. subtitle images). Unfortunately, consumer electronics people being who they are the standards also specify some things that are very "unnatural". You have to tell the encoder 2.5 Can I capture video and compress it so that I can burn it to CD and play it in my DVD player? Your best bet is probably to compress it as an SVCD stream and use the "vcdimager" program to create the burnable CD image. Many current DVD players can play SVCD format CDs. Unfortunately, there's currently no free authoring software that would allow the same to be done for DVD-format MPEG. Hopefully, this will change someday. 2.6 I've just encoded a huge MPEG file on my P133 an it took *ages*. Is there any way I can split it to fit ontp VCD's without re-encoding? In theory this is sort-of possible. In practice there aren't any free tools around that can do the fine surgery on the synchronisation information and copying of headers that would be necessary. If you want to play back using a computer the best solution is simply to split the file for storage and join it again for playback. 3. Questions about the MJPEG and audio drivers. 3.1 I've got a Buz card and I just can get it to capture without lots of dropped frames. Unfortunately, some aspects of the Buz design make it very sensitive to devices that share or affect the computer's PCI bus that behave less-than-perfectly. The extent of the problems depend both on the quality of the BIOS and the mainboard chipset. VIA-based mainboards are generally particularly awkward in this respect. The DC10(+) and LML33 boards are much less sensitive than the Buz. 3.2 I can capture nicely if I disable audio (-a 0 to lavrec) but bad things happen if I enable it. Unfortunately, the quality of Linux audio drivers *recording* facilities can still be very patchy. Especially, the "mmap" programming interface that lavrec prefers to use. Often simply telling it to use the (slightly less accurate) "read" interface fixes the problem. Sometimes, the driver is just plain broken and the only solution is to wait for the problem to be fixed or to get another sound card. 4. Questions about MPEG encoding with mjpegtools 4.1 Damn! When I burn an SVCD my player plays trash. Unfortunately, the quality of the firmware for SVCD in many DVD players for markets outside Asia is rather poor. Various nasty little bugs can cause SVCD to fail to play back. To help the unfortunates with such players there some special bug fix flags. --correct-svcd-hds May help 16:9 streams to play back correctly on correct players. This is not on by default because it breaks all SVCD playback on many players --no-altscan-mpeg2 Some players seem not be able to cope with the "alternative" pattern for scanning pixel blocks that MPEG2 supports. This flag forces mpeg2enc to use only the less efficient "normal" pattern. 4.2 When I encode stuff it is just too damn slow how can speed things up? o If you're encoding MPEG2 (-f 3,4,5 and 8) and encoding non-interlaced video (e.g. movies) you then you can make big speed gains by switching off the special calculations needed for encoding moving interlaced scenes by setting '-I 0'. Note that even for interlaced material it is faster to deinterlace and encode deinterlaced video than encode with interlaced support. However, this can cause some quality loss (it depends a lot on the source material). o You can trade (very modest) reduction in compression for significant speed gains by using the -4 and -2 flags. o If you have a long processing pipeline with scaling and denoising then these tasks take about as much CPU as the MPEG encoding itself. If you split the work across several CPU's either in a multi-processor machine or using a fast network then things can go much faster. E.g. if you have the a remote shell login daemon running on machine1 rsh machine1 "lav2yuv blah.avi | yuvdenoise ... | yuvscale ..." \ | mpeg2enc ... will split the work between the machine you're working on machine1. The best way to split the work depends of course on the relative speeds of the machines. If you have more than two machines you can split the work even more. Later release of the mjpegtools will probably gain a special "network pipe" mode for maximising efficiency with this kind of setup. Even if you're only doing "lav2yuv | mpeg2enc" for MJPEG some gains may be possible using this approach as MJPEG decoding takes a not insignificant amount of time. o If you have a multi-processor machine and its not running at full load during encoding you can tell mpeg2enc to run multiple encoding threads using the -M flag. Here's what I do when encoding on a pair of dual P-III machines: rsh machine1 "lav2yuv ... | yuvdenoise ... " | mpeg2enc -M 2 ... 4.3 How can I avoid those space-hogging intermediate files generated by mpeg2enc and the MPEG audio encoder? The mplex multiplexer can accept data from fifo's (named pipes) as well as intermediate files. This means you can directly pipe the output of the MPEG audio and video encoders in mplex and generate the final multiplexed MPEG stream directly. The recipe if you're using "mp2enc" for audio encoding is as follows: mkfifo audio mkfifo video ... mpeg2enc ... -o video & ... mp2enc ... -o audio & mplex ... audio video -o audvid.mpg rm audio rm video Easy isn't it! 5. Question about Digital Video in General mjpegtools-2.1.0/docs/yuvscaler.10000644000175000017500000001543412216627211017247 0ustar glowwormglowworm.TH "yuvscaler" "1" "26 Septembre 2001" "MJPEG Tools Team" "MJPEG tools manual" .SH NAME yuvscaler \- UPscales or DOWNscales a YUV4MPEG2 stream to a specified format .SH SYNOPSIS .B yuvscaler .RB [ -I .IR input_keyword ] .RB [ -M .IR mode_keyword ] .RB [ -O .IR output_keyword ] .RB [ -n\ p | s | n ] .RB [ -v\ 0 - 2 ] .RB [ -h ] .SH DESCRIPTION \fByuvscaler\fP is a general (UP or DOWN) scaling utility that is provided to allow conversion between different video formats. It reads in a YUV4MPEG2 format stream from stdin (such as that produced by \fBlav2yuv\fP) and outputs such stream to stdout (e.g. to be consumed by \fBmpeg2enc\fP). The most common use of yuvscaler is to generate input suitable for MPEG encoding to VCD or SVCD formats using \fBmpeg2enc\fP(1). \fByuvscaler\fP will automatically take into account PAL/SECAM and NTSC format, as well as widescreen (16:9) format and interlacing. Use of yuvscaler was designed to be straightforward. .SH EXAMPLES \fBVCD encoding:\fP .br lav2yuv my-file.avi | yuvscaler -O VCD | mpeg2enc -f 1 -o vcd.%d.m1v \fBSVCD encoding:\fP .br lav2yuv my-file.qt | yuvscaler -O SVCD | mpeg2enc -f 4 -o svcd.%d.m2v \fBEncoding anamorphic 16:9 as letterboxed VCD:\fP .br lav2yuv my-ana16-9.eli | yuvscaler -M WIDE2VCD | mpeg2enc -f 1 -o letterbox_vcd.%d.m1v \fBEncoding anamorphic 16:9 as letterboxed SVCD:\fP .br lav2yuv my-ana16-9.eli | yuvscaler -M WIDE2STD -O SVCD | mpeg2enc -f 4 -o letterbox_svcd.%d.m2v \fBEncoding anamorphic 16:9 as letterboxed DVD:\fP .br lav2yuv my-ana16-9.eli | yuvscaler -M WIDE2STD -O DVD | mpeg2enc -f 8 -o letterbox_dvd.%d.m2v .SH OPTIONS .TP .B -I \fIinput_keyword\fP .IP Specifies input processing options. Input options may be combined by using multiple \fB-I\fP flags. Possible \fIinput_keyword\fPs are: .IP \fBUSE_WidthxHeight+WidthOffset+HeightOffset\fP to select a useful area of the input frame (all multiple of 2, Height and HeightOffset multiple of 4 if interlaced), the rest of the image being discarded .IP \fBACTIVE_WidthxHeight+WidthOffset+HeightOffset\fP to select an active area of the input frame (all multiple of 2, Height and HeightOffset multiple of 4 if interlaced), the rest of the image being made black .TP .B -M \fImode_keyword\fP .IP Sets the scaling mode options. Scaling mode options can be combined by giving several \fB-M\fP flags. Possible are: .IP \fBBICUBIC\fP - to use the (Mitchell-Netravalli) high-quality bicubic upsacling and/or downscaling algorithm .IP \fBRESAMPLE\fP - to use a classical resampling algorithm -only for downscaling- that goes much faster than bicubic. For coherence reason, \fByuvscaler\fP will use RESAMPLE if only downscaling is necessary, BICUBIC if not. .IP \fBWIDE2STD\fP - convert widescreen anamorphic (16:9) input video into letterboxed (4:3), generating necessary black lines. Note that for MPEG applications if your \fIplayer\fP can properly decode anamorphic video you may wish to leave the video unscaled and simply specify the approprate format during MPEG encoding (see \fBmpeg2enc\fP(1)). .IP \fBRATIO_WidthIn_WidthOut_HeightIn_HeightOut\fP to specified scaling ratios of WidthIn/WidthOut for width and HeightIN/HeightOut for height to be applied to the useful area. The output frames that result from scaling can have a different format than the output format specified using \fB-O\fP options(s). In this case, \fByuvscaler\fP automatically generate necessary black lines and columns and/or skips necessary lines and columns to center the scaled image in the output frame. .IP \fBWIDE2VCD\fP to scale anamorphic widescreen (16:9) frames into letterboxed VCD format (equivalent to -M WIDE2STD -O VCD). .IP \fBFASTVCD\fP to transcode full sized frames to VCD (equivalent to -M RATIO_2_1_2_1 -O VCD, see below). .IP \fBFAST_WIDE2VCD\fP to transcode full-sized anamorphic (16:9) frames to letter-boxed VCD (equivalent to -M WIDE2STD -M RATIO_2_1_2_1 -O VCD, see below). .IP \fBNO_HEADER\fP to suppress stream header generation on output .IP \fBMMX\fP to use MMX functions for BICUBIC scaling (experimental feature!!) .IP .TP .B -O \fIoutput_keyword\fP .IP Sets the output frame format options. Output format options can be combined by giving several \fB-O\fP flags. By default, output frames size will be the same as input frame sizes, as well as output frames interlacing if coherent with output keyword specification which prevails, top_first if not. .IP \fBMONOCHROME\fP to generate monochrome frames on output. Chrominance information for the scaled pixels is set neutral (white). MPEG encoding of black and white video will be both inefficient \fIand\fP show annonying chrominance artifacts unless this is done. .IP \fBVCD\fP to generate VCD compliant frames on output (taking care of PAL and NTSC standards). Non-interlaced output. .IP \fBSVCD\fP to generate SVCD compliant frames on output (taking care of PAL and NTSC standards). Top-field-first interlaced frames. .IP \fBDVD\fP to generate DVD compliant frames on output (taking care of PAL and NTSC standards). Top-field-first interlaced frames. .IP \fBSIZE_WidthxHeight\fP to generate frames of size WidthxHeight on output (multiple of 4) .IP If VCD, SVCD or DVD keywords are not used, output interlacing is taken of the same type as input. By default, output frames size will be the same as input frame size. .IP .TP .B -n p|s|n (usually not necessary) if norm could not be determined from data flux, specifies the OUTPUT norm for VCD/SVCD (p=pal,s=secam,n=ntsc). .TP .B -v 0|1|2 Specifies the degree of verbosity: 0=quiet, 1=normal, 2=verbose/debug .TP .B -h Prints a summary of command line syntax. .PP \fBNote:\fP The most useful downscaling ratios are handled using dedicated optimised scaling routines. They are: .IP RATIO_WidthIn_WidthOut_2_1 => Full-sized frame to VCD downscaling .IP RATIO_3_2_1_1 => Full-sized frame to SVCD downscaling .IP RATIO_1_1_4_3 => WIDE2STD downscaling mode .IP RATIO_WidthIn_WidthOut_1_1 => downscaling only concerns width, not height .IP RATIO_1_1_HeightIn_HeightOut => downscaling only concerns height, not width .IP RATIO_2_1_2_1 => FASTVCD, slightly width distorted (real ratio 45 to 22) but faster full-sized frame to VCD downscaling (-M RATIO_2_1_2_1 -O VCD) .IP RATIO_WidthIn_WidthOut_8_3 => specific to WIDE2VCD downscaling (-M WIDE2STD -O VCD) .IP RATIO_2_1_8_3 => specific to (slighly distorted) FAST_WIDE2VCD downscaling (-M WIDE2STD -M RATIO_2_1_2_1 -O VCD) .IP RATIO_1_1_1_1 => copy useful input part of possible several files into output frames .SH AUTHOR This man page was written by Xavier Biquard et al. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP .TP For more info, see our website at .I http://mjpeg.sourceforge.net/ .SH SEE ALSO .BR mjpegtools (1), .BR lavpipe (1), .BR lav2yuv (1) .BR mpeg2enc (1) mjpegtools-2.1.0/docs/authors.sgml0000644000175000017500000000111212216631403017503 0ustar glowwormglowworm Authors MJPEG Tools was written by Rainer Johanni Andrew Stevens Andrew.Stevens@comlab.ox.ac.uk, Gernot Ziegler gz@lysator.liu.se, Bernhard Praschinger shadowlord@utanet.at Xavier Biquard, Ronald Bultje, And many others . To find more information about MJPEG Tools, please visit the MJPEG Tools page. mjpegtools-2.1.0/docs/yuv4mpeg.50000644000175000017500000001415312216627211017013 0ustar glowwormglowworm.TH "yuv4mpeg" "5" "25 November 2002" "MJPEG Tools Team" "MJPEG Tools Manual" .SH "NAME" YUV4MPEG2 \- video stream format used by pipe-based MJPEGtools .hw libmjpegutils yuv4mpeg.h YUV4MPEG YUV4MPEG2 .SH "DESCRIPTION" .PP Many of the MJPEGtools communicate via pipes and act as filters (or sources or sinks). The format of video data used in the pipes is referred to as "YUV4MPEG", or, more precisely, "YUV4MPEG2". (The format was extended and codified during v1.5.x of the tools.) .PP The basic structure is a stream header followed by an unlimited number of frames. Each frame itself consists of a header followed by video data. The headers are vaguely human-readable ASCII, but the video data is simple byte-size binary. .PP The MJPEGtools distribution has a C library (libmjpegutils) which contains functions for manipulating YUV4MPEG2 streams. We recommend that you use this library rather than writing your own code if possible. See the header file "yuv4mpeg.h" for a description of these functions. .PP Design Goals: .IP o Easy to parse both via C or sh. .IP o Extensible; easy to add new parameters while maintaining backwards compatibility. .IP o Simple upgrade from original "YUV4MPEG" format. .PP Drawbacks: .IP o Frame headers do not have constant size, so streams are not seekable. .SH "GRAMMAR" The precise description of the the YUV4MPEG2 stream format is as follows: .PP \fISTREAM\fP consists of .IP - 3 one \fISTREAM-HEADER\fP .IP - 3 unlimited number of \fIFRAME\fPs .PP \fISTREAM-HEADER\fP consists of .IP - 3 magic string "YUV4MPEG2" .IP - 3 unlimited number of \fITAGGED-FIELD\fPs, each preceeded by a '\ ' (single space) separator .IP - 3 single '\en' line terminator .PP \fIFRAME\fP consists of .IP - 3 one \fIFRAME-HEADER\fP .IP - 3 "length" octets of planar YCbCr 4:2:0 image data (If the stream is interlaced, then the two fields per frame are interleaved, with proper spatial ordering.) .PP \fIFRAME-HEADER\fP consists of .IP - 3 magic string "FRAME" .IP - 3 unlimited number of \fITAGGED-FIELD\fPs, each preceeded by a '\ ' (single space) separator .IP - 3 single '\en' line terminator .PP .I \fITAGGED-FIELD\fP consists of .IP - 3 single ASCII character tag .IP - 3 \fIVALUE\fP (which does not contain whitespace) .PP \fIVALUE\fP consists of .IP - 3 \fIRATIO\fP, .B or .IP - 3 integer (base 10 ASCII representation), .B or .IP - 3 single ascii character, .B or .IP - 3 string (multiple ASCII characters) .PP \fIRATIO\fP consists of .IP - 3 numerator (base 10 ASCII integer) .IP - 3 \&':' (a colon) .IP - 3 denominator (base 10 ASCII integer) .PP Header tags fall into three categories: \fBoptional\fP, \fBrequired\fP and \fBhas-default\fP. Optional tags are completely optional and may be omitted from a header. Required tags must be present in a header. Has-Default tags have a default value which is implied if the tag is not present. Independent of these categories, some tags allow an "unknown" value and some do not. .PP The supported tags for the \fISTREAM-HEADER\fP: .RS .HP W[integer]\ \-\ frame width in pixels, must be > 0 (\fBrequired\fP) .HP H[integer]\ \-\ frame height in pixels, must be > 0 (\fBrequired\fP) .HP C[string]\ \-\ chroma subsampling, image data format (\fBhas default\fP) .RS 420jpeg\ \-\ 4:2:0 with JPEG/MPEG-1 siting (default) 420mpeg2\ \-\ 4:2:0 with MPEG-2 siting 420paldv\ \-\ 4:2:0 with PAL-DV siting 411\ \-\ 4:1:1, cosited 422\ \-\ 4:2:2, cosited 444\ \-\ 4:4:4 (no subsampling) 444alpha\ \-\ 4:4:4 with an alpha channel mono\ \-\ luma (Y') plane only .RE .HP I[char]\ \-\ interlacing specification: (\fBhas default\fP) .RS ?\ \-\ unknown (default) p\ \-\ progressive/none t\ \-\ top-field-first b\ \-\ bottom-field-first m\ \-\ mixed-mode: refer to 'I' tag in frame header .RE .HP F[ratio]\ \-\ frame-rate (\fBhas default\fP of 0:0 == unknown) .HP A[ratio]\ \-\ sample aspect ratio (\fBhas default\fP of 0:0 == unknown) .HP X[string]\ \-\ 'metadata' (\fBoptional\fP; unparsed, but passed around) .RE .PP The currently supported tags for the \fIFRAME-HEADER\fP: .RS .HP I[string]\ \-\ framing and sampling (\fBrequired if-and-only-if\fP Im is present in stream header). Value is a string of three characters "xyz" which have the following meanings: .RS x: frame presentation t\ \-\ top-field-first T\ \-\ top-field-first and repeat b\ \-\ bottom-field-first B\ \-\ bottom-field-first and repeat 1\ \-\ single progressive frame 2\ \-\ double progressive frame (repeat) 3\ \-\ triple progressive frame (repeat) y: frame temporal sampling p\ \-\ progressive (fields sampled at same time) i\ \-\ interlaced (fields sampled at different times) z: frame chroma-subsampling p\ \-\ progressive (subsampling over whole frame) i\ \-\ interlaced (each field subsampled independently) ?\ \-\ unknown (allowed only for non-4:2:0 subsampling) .RE .HP X[string]\ \-\ 'metadata' (\fBoptional\fP; unparsed, but passed around) .RE .PP Note that a filter application must faithfully forward all "X" tags from input pipe to output pipe (unless it uses one of those tags, of course). The supplied library will do this automatically if the functions y4m_copy_stream_info() and y4m_copy_frame_info() are used appropriately. .SH "NOTES ON IMAGE DATA" .PP All image data is in the CCIR-601 Y'CbCr colorspace, presented plane-by-plane in row-major order. Each sample within each plane is one octet (8-bits) in size. When all planes are present, they are transmitted in the order Y', Cb, Cr, potentially followed by an alpha/transparency mask plane (for the \fB444alpha\fP chroma format). The alpha channel data is follows the same range as the Y' luma channel: full transparency is at 16 and full opacity is at 235. All Y' and alpha planes consist of (height\ X\ width) octets. The size of the chroma planes depends on the subsampling mode: .IP - 3 4:4:4 - (height\ X\ width) octets .IP - 3 4:2:2 - (height\ X\ width)\ /\ 2 octets .IP - 3 4:1:1 - (height\ X\ width)\ /\ 4 octets .IP - 3 4:2:0 - (height\ X\ width)\ /\ 4 octets .SH "NOTES ON FRAMING" .PP (More to come here.) .SH "SEE ALSO" .BR mjpegtools (1), yuv4mpeg.h .SH "AUTHOR" This manual page Copyright 2004 Matthew J. Marjanovic. mjpegtools-2.1.0/docs/jpeg2yuv.10000755000175000017500000000552212216627207017012 0ustar glowwormglowworm.TH "jpeg2yuv" "1" "8 December 2001" "MJPEG Tools Team" "MJPEG tools manual" .SH "NAME" jpeg2yuv \- Convert jpeg images to the yuv format. .SH "SYNOPSIS" .B jpeg2yuv .RB [ \-b .IR num ] .RB [ \-f .IR num ] .RB [ \-I .IR num ] .RB [ \-A .IR ratio ] .RB [ \-L .IR num ] .RB [ \-n .RB num ] .RB [ \-l .IR num ] .RB [ \-j .IR filename ] .SH "DESCRIPTION" \fBjpeg2yuv\fP decompresses a sequence of JPEG files and pipes the image data to stdout as a YUV4MPEG2 stream. Any JPEG format supported by libjpeg can be read. stdout will be filled with the YUV4MPEG2 movie data stream, so be prepared to pipe it on to mpeg2enc or to write it into a file. .SH "OPTIONS" \fBjpeg2yuv\fP accepts the following options: .TP 5 .BI \-b " num" Frame offset: skip output of the first 'num' frames. (default: 0) .TP 5 .BI \-f " num" Set the frame rate of stream accepts the same numbers. No default, this option has to be specified. .TP 5 .BI \-A " ratio" Sample aspect ratio. Default is square pixels (1:1) .TP 5 .BI \-I " num" interlacing mode: p = none / progressive .br t = top field first .br b = bottom field first .br No default, this option has to be specified. .TP 5 .BI \-L " num" 0 = non-interlaced (two successive fields per JPEG file) .br 1 = interlaced fields .TP 5 .BI \-l " num" Specifies the number of loops (default: 0 loops ) .br When this option is not used the given range of images is only processed once. If you use this option with num of -1 jpeg2yuv will loop forever writing the image to stdout. When you use n > 0 it will loop n-times till it finishes. .TP 5 .BI \-n " num" Specifies the number of frames to process. (default: all = -1) .TP 5 .BI \-j " {1}%{2}d{3}" Read JPEG frames with the name components as follows: {1} JPEG filename prefix (e g: picture_ ) {2} Counting placeholder (like in C, printf, eg 06 )) {3} File extension. Something like this: .jpg A correct description of the files could look like this: picture_%06d.jpg If this option is omited, the filenames are read from stdin. For example: $ls *jpg | jpeg2yuv -f 25 -I p > result.yuv .TP 5 .BI \-R " 1 or 0" rescale YUV color values from 0-255 to 16-235 (default: 1) .TP 5 .BI \-v " num" Verbosity level (0, 1 or 2) .SH BUGS The frame rate description seems not to be up to date. The NTSC integer ratios seem not to be supported. As a workaround specify a PAL (25) or FILM (24) and set the right frame rate in mpeg2enc with the -F option. .SH "AUTHOR" This man page was written by Bernhard Praschinger. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP .TP For more info, see our website at .I http://mjpeg.sourceforge.net .SH "SEE ALSO" .BR mjpegtools (1), .BR mpeg2enc (1), .BR ppmtoy4m (1), .BR yuv2lav (1), .BR yuvdenoise (1), .BR yuvmedianfilter (1), .BR yuvscaler (1) mjpegtools-2.1.0/docs/ppmtoy4m.10000755000175000017500000001020612216627211017016 0ustar glowwormglowworm.\" .TH "ppmtoy4m" "1" "28 April 2004" "MJPEG Tools Team" "MJPEG tools manual" .SH "NAME" ppmtoy4m \- Convert PPM images to YUV4MPEG2 stream .SH "SYNOPSIS" .B ppmtoy4m .RI [ options ] .I [ filename ] .SH "DESCRIPTION" \fBppmtoy4m\fP converts one or more raw PPM images into a YUV4MPEG2 stream ready for further processing by other video tools. Output is to stdout to facilitate piping to other MJPEG tools. The size of the output frame(s) is determined from the (first) input image. Input is a 'raw' format PPM image, read from stdin or from the optional filename. The input may contain multiple PPM images concatenated together; \fBppmtoy4m\fP will read and process them sequentially. All images must have identical size and format. Input images can be interpreted as whole progressive frames, interleaved fields, or (in pairs) as sequential fields. The input images must have 8 bits per channel (i.e. 'maxval' must be 255). Input images should be in the usual R'G'B' colorspace. They are converted to the Y'CbCr colorspace (ITU-R BT.601) (and chroma subsampled, if desired) before output. \fBppmtoy4m\fP and \fBy4mtoppm\fP are inverses of each other; you can pipe the output of one into the other, and vice-versa. Note that the subsampling and colorspace operations are lossy in both directions. And, when converting to PPM, information on interlacing and sample aspect ratio is lost (but can be reconstructed by supplying command-line arguments to \fBppmtoy4m\fP). .SH "OPTIONS" \fBppmtoy4m\fP accepts the following options: .TP 5 .BI \-o " num" Frame offset: skip output of the first 'num' frames. (default: 0) .TP 5 .BI \-n " num" Output a total of 'num' output frames. Use '0' to specify all frames. (default: 0) .TP 5 .BI \-F " n:d" Set framerate encoded in output stream, as an exact integer ratio. (default: 30000:1001) Common rates are: 24000:1001 - NTSC 3:2 pulldown converted film 24:1 - native film 25:1 - PAL/SECAM 30000:1001 - NTSC video 50:1 - PAL field rate 60000:1001 - NTSC field rate .TP 5 .BI \-A " n:d" Set pixel aspect ratio encoded in output stream, as an exact integer ratio. (default: 1:1) Common ratios are: 1:1 - square pixels (computer graphics) 10:11 - CCIR-601 NTSC 59:54 - CCIR-601 PAL .TP 5 .BI \-B Interpret data as being BGR rather than RGB. .TP 5 .BI \-I " x" Set interlacing mode, used to interpret the PPM image(s), and also encoded in output stream. (default: 'p') p - progressive, non-interlaced t - top/upper-field-first interlaced b - bottom/lower-field-first interlaced .TP 5 .BI \-L For interlaced streams, treat each PPM image as two interleaved fields. (Otherwise, two PPM images will be read for each frame; one per field.) .TP 5 .BI \-r Repeat last input frame until output is complete. If '-n 0' is also specified, last input frame will be repeated forever. .TP 5 .BI \-S " mode" Set chroma subsampling mode. (default: 444) 444 - 4:4:4 (no subsampling) 420jpeg - 4:2:0 JPEG/MPEG-1, interstitial cositing 420mpeg2 - 4:2:0 MPEG-2, horizontal cositing The subsampled modes use a lousy subsampling filter; better results will be achieved by passing the default 4:4:4 output to a scaler which supports subsampling, such as \fBy4mscaler\fP(1). .TP 5 .BI \-v " [0,1,2]" Set verbosity level. 0 = warnings and errors only. 1 = add informative messages, too. 2 = add chatty debugging message, too. .SH "EXAMPLES" .hw ppmtoy4m yuvplay tgatoppm To convert a file containing a single PPM file into a stream of 15 (identical) frames: .RS 5 ppmtoy4m -n 15 -r some-image.ppm .RE To convert a series of Targa format images (in the current directory) to a YUV4MPEG2 stream displayed by yuvplay: .RS 5 ls *.tga | xargs -n1 tgatoppm | ppmtoy4m | yuvplay .RE .SH "AUTHOR" This man page was written by Matt Marjanovic. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP .TP For more info, see our website at .I http://mjpeg.sourceforge.net/ .SH "SEE ALSO" .BR ppm (5), .BR y4mtoppm (1), .BR mjpegtools (1), .BR mpeg2enc (1), .BR y4mscaler (1), .BR yuv2lav (1), .BR yuvplay (1) mjpegtools-2.1.0/docs/yuvinactive.10000755000175000017500000000526012216627211017577 0ustar glowwormglowworm.\" .TH "yuvinactive" "1" "30 October 2003" "MJPEG Tools Team" "MJPEG tools manual" .SH "NAME" yuvinactive \- Set a part of the video to a defined state .SH "SYNOPSIS" .B yuvinactive .RI [ options ] .I /dev/stdout .SH "DESCRIPTION" \fByuvinactive\fP operates with a area (rectangle) you define. By default is sets it to really black. But you can tell tell yuvinactive to darken the area, or fill it with a certain color. It can also make the content of the area unreadable, like extreme softening of the area. Or copy the surrounding area into the the specified area. You usually have to use the -i option which sets the area in which yuvinactive will work. If no additional option is given yuvinactive stet the area to black. But you can use the \fB-d -s -a -c options\fP to tell yuvinactive that it shall do something different with that area. You can only use one additional option. yuvinactive was built to remove unwanted things like a logo, from the movie. .SH "OPTIONS" \fBlav2yuv\fP accepts the following options: .TP 5 .BI \-h Some help output .TP 5 .BI \-i "XxY+XOFF+YOFF" Specifies the area yuvinactive shall work with. With this option the area is set to black. There are no restrictions because of interlacing. .TP 5 .BI \-d " num" How much darker the area should be compared to the original color. This is done by setting a lower value for the luma. The value is in percent from the original luma. .TP 5 .BI \-s " num" Here you specify a certain color in the yuv format. .TP 5 .BI \-a " num" With this option the program uses on pixel and averages the surrounding pixels with the same color to make the original less readable. The number tells the the program how much pixels around the original pixel should be overwritten with the same color. You have to use a even number here .TP 5 .BI \-c " num" Sets the number of surrounding pixels yuvinactive should use to copy them into the given area. You have to use a even number here. yuvinactive uses the lines above and below the specified area for copying them into the area. .SH "BUGS" Right, there are bugs hidden. The thing is not well tested, and not every option might work. yuvinactive is in the first state of becoming a useful program. .SH "AUTHOR" This man page was originally written by Bernhard Praschinger. .br If you have questions, remarks, problems or you just want to contact the developers, the main mailing list for the MJPEG\-tools is: \fImjpeg\-users@lists.sourceforge.net\fP .TP For more info, see our website at .I http://mjpeg.sourceforge.net .SH "SEE ALSO" .BR mjpegtools (1), .BR lav2yuv (1), .BR mpeg2enc (1), .BR yuvscaler (1), .BR yuv2lav (1), .BR yuvdenoise (1), .BR yuvplay (1), .BR yuvmedianfilter (1)