submux-dvd-0.5.2/CHANGES0000644000000000000000000000144511615561257013322 0ustar rootroot0.1: First release with DVD coding. 0.2: ... 0.3: Went all the way back to 0.1, started changing that. Subs are made even. Total rewrite DVD muxing, tried to make it more to DVD spec (finally got some data on that). 0.4: Not a release in the open... 0.5: Adapted so it will work right with xste-3.0 with the colors, the different fonts. NOTE the sequence of the extra commands has changed, see the FORMAT file in this release. Now pointers are used, and the correct colors come for background, pattern, emphasis1, and emphasis2. Use the new xste (from version 3.0) to make the .sub file and bitmaps, it supports full color and multiple fonts. xste is not released yet.... Still testing. 0.5.1 gcc fix for \ 0.5.2: Compiles clean with -Wall in gcc-4.0.3 Updated home page URL, and email address. submux-dvd-0.5.2/FORMAT0000644000000000000000000000355011615561257013241 0ustar rootrootHere is the submux-dvd latest interface spec (see the .sub for example too). bitmap_filename hh:mm:ss:dd hh:mm:ss:dd xsize ysize xpos ypos extra values1: set colors and contrast in this bitmap background_contrast pattern_contrast outline1_contrast outline2_contrast background_color pattern_color emphasis1_color emphasis2_color extra values 2: select special submux command handling (optional1 MUST then be present) submux_command_nr extra values3: if submux_command & 4, the COL_CON is executed, bitmap data is ignored, this allows to select a vertical area, with up to 16 horizontal start points in that area, each with its own color. It seems the not selected parts are then set to the default as in the original bitmap vertical_area_start vertical_area_end maximal 16 groups of: horizontal_area_start background_contrast pattern_contrast emphasis1_contrast emphasis2_contrast background_color pattern_color emphasis1_color emphasis2_color NOTE: the last 2 lines are reversed since -0.4 test release! so it is more consistent: contrast values always first, the color values. The submux-commands: USE BITMAP DATA 1 USE STOP 2 USE COL_CON 4 USE FORCED START 8 USE START 16 So: To display a bitmap that stays on the screen until the next bitmap shown 1 + 8 = 9 frame0500.bmp 00:00:10:00 00:05:30:00 656 480 38 83 0 15 15 0 0 13 2 3 9 To only change the colors and contrast in a bit bitmap on the screen 4 frame1000.bmp 00:00:20:00 00:00:21:00 296 36 218 125 0 15 15 0 0 5 2 3 4 10 400 30 0 15 15 0 0 1 2 3 200 0 15 15 0 0 5 2 3 400 0 15 15 0 0 9 2 3 To display a normal bitmap. leave out submux command (default will be used) 1 + 2 + 8 = 11 frame4000.bmp 00:02:08:00 00:02:57:00 296 36 218 425 0 15 15 0 0 1 2 3 11 submux-dvd-0.5.2/INSTALL0000644000000000000000000000005011615561257013347 0ustar rootrootmake make install should do it for you submux-dvd-0.5.2/LICENSE0000644000000000000000000004307011615561257013334 0ustar rootroot 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 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. submux-dvd-0.5.2/Makefile0000644000000000000000000000034311615561257013763 0ustar rootrootCC = gcc -Wall -O2 -fomit-frame-pointer all: submux-dvd vob2sub clean: rm -f vob2sub submux-dvd *.o *~ distclean: clean rm -f palette.txt *.bmp *.sub install: cp submux-dvd /usr/local/bin/ cp vob2sub /usr/local/bin/ submux-dvd-0.5.2/README0000644000000000000000000000357111615561257013211 0ustar rootroot This is submux with DVD coding and multiplexing routines added, and slightly modified (bitmap_read). It will add SPU subtitles to a .vob. Input format is .sub and .bmp, as produced by the Linux subtitle editor xste. No manual yet, this is an interim release (as always :-) ). This version has been tested on: Linux: mplayer (see note) xine Windows: PowerDVD InterActual Player Standalone players: Mustek 562 Cyberhome CH-DVD 405 Note mplayer: The current version of mplayer drops subs that have less then 3 bytes in the last SPU packet as data. You can fix this by commenting out the return in: libmpdemux/demux_mpg.c aid=stream_read_char(demux->stream);--len; if(len < 3) // CHANGE THIS to < 1, then compile and re-install { return -1; } ---------------------------------- Note InterActual Player: You cannot select a second title if more then one titles present it seems, unless there is some menu, nothing to do with subs, the subs are OK. dvdauthor: In dvdauthor a derivative version of submux is used, called spumux. I notice some top outlines re-appearing at the bottom in subtitles made with spumux. I personally use submux-dvd, and tested it with dvdauthor-0.7.0. Example of usage: echo "use xste to make and output vfactor .126 subs, then press ENTER" read user_reply submux-dvd -v 3 -s 0 -t .180 filename.vob ~/.subtitles/filename.sub filename-subbed.vob mkdir dvd rm -rf dvd/* dvdauthor -t -o dvd -a mp2+en+1ch,mp2+es+2ch,mp2+fr+2ch,mp2+it+2ch,mp2+de+2ch,ac3+5ch+de,ac3+5ch+iw,ac3+5ch+el -s nl,nl,nl,nl -p xste-palette.yuv filename-subbed.vob dvdauthor -T -o dvd mkisofs -dvd-video -publisher Panteltje_Press -p Panteltje_Productions dvd/ > dvd_image growisofs -speed 3 -dvd-compat -Z /dev/dvd=dvd_image dvdimagecmp -a /dev/dvd -b dvd_image Please report any problems to panteltje@yahoo.com. The submux-dvd homepage is at http://www.panteltje.com/panteltje/dvd/ Jan Panteltje submux-dvd-0.5.2/spu.html0000644000000000000000000001643111615561257014025 0ustar rootrootSub-Pictures

Sub-Pictures

The typical arrangement of data in the 53220 byte buffer for sub-pictures is
SPUHPXDtfPXDbfSP_DCSQT
However, the only requirement is that the header (SPUH) be first, all other areas are reached by pointers.

SPUH

Sub-Picture Unit Header
2 words (small endian - least significant byte last)
offsetnamecontents
0SPDSZthe size of the total sub-picture data (which may span packets)
2SP_DCSQTAoffset within the Sub-Picture Unit to the SP_DCSQT

PXDtf and PXDbf

PiXel Data
These are the rle compressed pixel data for the top field (lines 1, 3, 5, etc) and the bottom field (lines 2, 4, 6, etc) respectively
Individual pixels may have one of four values, commonly referred to as background (0), pattern (1), emphasis 1 (2), and emphasis 2 (3) Each coded value indicates the number of pixels having the same code value, and can be in one of four forms, depending on the number of identical pixels
rangebitsformat
1-34n n c c
4-1580 0 n n n n c c
16-63120 0 0 0 n n n n n n c c
64-255160 0 0 0 0 0 n n n n n n n n c c
One special case, encoding a count of zero using the 16-bit format indicates the same pixel value until the end of the line.
If, at the end of a line, the bit count is not a multiple of 8, four fill bits of 0 are added.

SP_DCSQT

Sub-Picture Display Control SeQuence Table
This area contains blocks (SP_DCSQ) of commands to the decoder. Each SP_DCSQ begins with a 2 word header
offsetnamecontents
0SP_DCSQ_STMdelay to wait before executing these commands.
The units are 90KHz clock (same as PTM) divided by 1024 - see conversion aids
2SP_NXT_DCSQ_SAoffset within the Sub-Picture Unit to the next SP_DCSQ. If this is the last SP_DCSQ, it points to itself.

Commands

There are eight commands available for Sub-Pictures. The first SP_DCSQ should contain, as a minimum, SET_COLOR, SET_CONTR, SET_DAREA, and SET_DSPXA.

FF - CMD_END - ends one SP_DCSQ

00 - FSTA_DSP - Forced Start Display, no arguments

01 - STA_DSP - Start Display, no arguments

02 - STP_DSP - Stop Display, no arguments

03 - SET_COLOR - provides four indices into the CLUT for the current PGC to associate with the four pixel values. One nibble per pixel value for a total of 2 bytes.
e2 e1   p b

04 - SET_CONTR - directly provides the four contrast (alpha blend) values to associate with the four pixel values. One nibble per pixel value for a total of 2 bytes. 0x0 = transparent, 0xF = opaque
e2 e1   p b

05 - SET_DAREA - defines the display area, each pair (X and Y) of values is 3 bytes wide, for a total of 6 bytes, and has the form
sx sx   sx ex   ex ex   sy sy   sy ey   ey ey
sx = starting X coordinate
ex = ending X coordinate
sy = starting Y coordinate
ey = ending Y coordinate

06 - SET_DSPXA - defines the pixel data addresses. First a 2-byte offset to the top field data, followed by a 2-byte offset to the bottom field data, for a total of 4 bytes.

07 - CHG_COLCON - allows for changing the COLor and CONtrast within one or more areas of the display. This command contains a series of parameters, arranged in a hierarchy.
Following the command byte is a 2-byte value for the total size of the parameter area, including the size word.
The parameter sequence begins with a LN_CTLI, which defines a vertically bounded area of the display. The LN_CTLI may include from one to fifteen PX_CTLI parameters, which define a starting horizontal position and new color and contrast value to apply from that column on towards the right to the next PX_CTLI or the right side of the display.

LN_CTLI, 4 bytes, special value of 0f ff ff ff signifies the end of the parameter area (this termination code MUST be present as the last parameter)
0 s   s s   n t   t t
sss = csln, the starting (top-most) line number for this area
n = number of PX_CTLI to follow
ttt = ctln, the terminating (bottom-most) line number for this area

PX_CTLI, 6 bytes, defines a starting column and new color and contrast values
bytes 0 and 1 - starting column number
bytes 2 and 3 - new color values, as per SET_COLOR
bytes 4 and 5 - new contrast values, as per SET_CONTR

Converting frames and time to SP_DCSQ_STM values

The direct method of converting time to delay values is to multiply time in seconds by 90000/1024 and truncate the value. Rounding up will cause the display to occur one frame late.
Framesvalue for NTSC (30fps)value for PAL/SECAM (25fps)
123
257
3810
41114
51417
61721
72024
82328
92631
102935
113238
123542
133845
144149
154352
164656
174959
185263
195566
205870
216173
226477
236780
247084
2573(87)
2676(91)
2779(94)
2882(98)
2984(101)
secondsvalue
187
2175
3263
4351
5439
6527
7615
8703
9791
10878
201757
302636
403515
504394
605273

DVD-Video home submux-dvd-0.5.2/submux-dvd-0.5.2.lsm0000644000000000000000000000173111615561257015600 0ustar rootrootBegin3 Title: submux-dvd Version: 0.5.2 Entered-date: 2011-07-01 Description: subtitle multiplexer for DVD .VOB files. Accepts .sub files output from xste To unpack: tar -zxvf submux-dvd-0.5.2.tgz cd submux-dvd-0.5.2 Then follow the instructions in README. Documentation is not complete yet. Changes 0.5.2: Compiles clean with -Wall in gcc-4.0.3 Updated home page URL, and email address. Keywords: subtitles, video, TV, satellite, SPU, xste, subtitler, ppml, language, DVD, mpeg2, mpeg2 multiplex, VOB. Author: "Jan Panteltje" Maintained-by: Jan Panteltje Primary-site: ftp sunsite.unc.edu/pub/linux/apps/video/ Alternate-site: http://panteltje.com/panteltje/dvd/ (homepage) Platforms: LINUX, UNIX Copying-policy: GPL End submux-dvd-0.5.2/submux-dvd.c0000644000000000000000000026502411615561257014576 0ustar rootroot/* * DVD code copyright (C) 2002, 2003, 20004, always Jan Panteltje , * original CVD and SVCD code by unknown author. * * 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 */ // prog for encoding DVD, CVD and SVCD subtitles and multiplexing them into an mpeg // available under GPL v2 #define _FILE_OFFSET_BITS 64 #define VERSION "0.5.2" #define SUB_BUFFER_MAX 53220 #define CVD_SUB_CHANNEL 0x0 #define SVCD_SUB_CHANNEL 0x70 #define DVD_SUB_CHANNEL 0x20 /* for mode */ #define DVD_SUB 0 #define CVD_SUB 1 #define SVCD_SUB 2 /* for header_mode */ #define FIRST_FIRST 0 #define NEXT_FIRST 1 #define NEXT_NEXT 2 #include #include #include #include #include #include #include #include #define psbufs 10 #define mintime 4 #ifndef O_BINARY #define O_BINARY 0 //for mingw #endif #define optimize 0 #define until_next_sub 1 //if 0 subs without length are made when subs are overlapping #define tbs 90 #define even_yofs 1 #define even_xd 1 int debug_flag; #define maxx 720 #define maxy 576 int dvd_encode(); int make_stop_packet(); int read_bmp(char *name); size_t cwrite(int fd, const void *buf, size_t count); size_t cread(int fd, void *buf, size_t count); int background_contrast; int pattern_contrast; int emphasis1_contrast; int emphasis2_contrast; int current_background_contrast; int current_pattern_contrast; int current_emphasis1_contrast; int current_emphasis2_contrast; int submux_command = 0; int current_submux_command; int c_start_line; int c_end_line; int c_h_start[16]; int c_background[16]; int c_pattern[16]; int c_emphasis1[16]; int c_emphasis2[16]; int c_contrast0[16]; int c_contrast1[16]; int c_contrast2[16]; int c_contrast3[16]; int c_h_blocks; int current_c_start_line; int current_c_end_line; int current_c_h_start[16]; int current_c_background[16]; int current_c_pattern[16]; int current_c_emphasis1[16]; int current_c_emphasis2[16]; int current_c_contrast0[16]; int current_c_contrast1[16]; int current_c_contrast2[16]; int current_c_contrast3[16]; int current_c_h_blocks; int colors_specified_flag; unsigned char *change_colcon_size; typedef struct { unsigned char r, g, b, t; } palt; palt pal_[4], pal[4]; palt epal[4]; typedef struct { unsigned short int BM; unsigned int size; unsigned int r0; unsigned int ofs; unsigned int hsize; unsigned int x; unsigned int y; unsigned short int bplanes; unsigned short int bpp; unsigned int comp; unsigned int imgsize; unsigned int xpm,ypm; unsigned int cused; unsigned int cimp; } __attribute__ ((packed)) bmpt; unsigned char bb, bc; unsigned char *sub, *cbuf; unsigned char *img, *fimg; //unsigned char nbuf[256]; char nbuf[256]; FILE *fds; static unsigned int subo, x0, y0, xd, yd, x0_, y0_, xd_, yd_; // -Wall, y0 is a build in function, static reduces its scope to this source file unsigned int iline, progr, skip; int sd, sd_; int tofs, spts, nspts, lvpts; int ofs, ofs1, io, debug, svcd; static int pattern, background, emphasis1, emphasis2; static int current_pattern, current_background, current_emphasis1, current_emphasis2; #define maxx 720 #define maxy 576 char header[32]; // msu hold enough space form max header size (15) plus max stuffing bytes (7) + svcd stuff void mkpackh(unsigned long int time, unsigned short int ext, unsigned int muxrate, unsigned char stuffing) { header[0] = 0x44 | ((time >> 27) & 0x38) | ((time >> 28) & 3); header[1] = (time >> 20); header[2] = 4 | ((time >> 12) & 0xf8) | ((time >> 13) & 3); header[3] = (time >> 5); header[4] = 4 | ((time & 31) << 3) | ((ext >> 7) & 2); header[5] = 1 | (ext << 1); header[6] = muxrate >> 14; header[7] = muxrate >> 6; header[8] = 3 | (muxrate << 2); header[9] = 0xF8 | stuffing; } void mkpesh0(unsigned long int pts, unsigned char id) { header[0] = 0x81; header[1] = 0x80; //pts flag header[2] = 5; header[3] = 0x21 | ((pts >> 29) & 6); header[4] = pts >> 22; header[5] = 1 | (pts >> 14); header[6] = (pts >> 7); header[7] = 1 | (pts << 1); header[8] = id; } void mkpesh1(unsigned long int pts, unsigned char id) { header[0] = 0x81; header[1] = 0x81; //pts flag + pes extension flag header[2] = 8; header[3] = 0x21 | ((pts >> 29)&6); header[4] = pts >> 22; header[5] = 1 | (pts >> 14); header[6] = (pts >> 7); header[7] = 1 | (pts << 1); header[8] = 0x1e; //P - STD_buffer_flag header[9] = 0x60; //buffer scale header[10] = 0x3a; //buffer size (wtf nu det är..) (svcdverifier tycker att 64 är ett bra tal här..) header[11] = id; } void mkpesh2 (unsigned char id) { header[0] = 0x81; header[1] = 0; header[2] = 0; header[3] = id; } unsigned long int getgts(unsigned char *buf) { if (((buf[8]&3) != 3) || ((buf[5]&1) != 1) || ((buf[4]&4) != 4)||((buf[2]&4) != 4)|| ((buf[0]&0xc4) != 0x44)) return -1; return (buf[4] >> 3) + (buf[3]*32) + ((buf[2]&3)*32*256) + ((buf[2]&0xf8)*32*128) + (buf[1]*1024*1024) + ((buf[0]&3)*1024*1024*256) + ((buf[0]&0x38)*1024*1024*256*2); } unsigned int getmuxr(unsigned char *buf) { return (buf[8] >> 2)|(buf[7]*64)|(buf[5]*16384); } unsigned int getpts(unsigned char *buf) { if (!(buf[1]&0xc0) || (buf[2]<4) | ((buf[3]&0xe1) != 0x21) || ((buf[5]&1) != 1) || ((buf[7]&1) != 1)) return -1; return (buf[7] >> 1) + buf[6]*128 + ((buf[5]&254)*16384) + buf[4]*16384*256 + ((buf[3]&14)*16384*256*128); } #define nco if (subo<65536) sub[subo++] #define a2b(b) do { bb = (bb << 2) + b; bc--; if (!bc) { bc = 4; nco = bb; }} while (0) int svcd_encode() { unsigned int x,y,c,l2o; double a; subo = 2; if (sd != -1) { nco = 0x2e; nco = 0; nco = sd >> 24; nco = sd >> 16; nco = sd >> 8; nco = sd; } else { nco = 0x26; nco = 0; } if (debug > 2) fprintf(stderr,\ "sd: %d xd: %d yd: %d x0: %d y0: %d\n", sd, xd, yd, x0, y0); nco = (x0 >> 8); nco = x0; nco = (y0 >> 8); nco = y0; nco = xd >> 8; nco = xd; nco = yd >> 8; nco = yd; for(c = 0;c<4;c++) { a = (0.257 * (double)epal[c].r) + (0.504*(double)epal[c].g) + (0.098*(double)epal[c].b) + 16; if (a>255) a = 255; if (a<0) a = 0; nco = a; a = (0.439 * (double)epal[c].r) - (0.368 * (double)epal[c].g) - (0.071 * (double)epal[c].b) + 128; if (a>255) a = 255; if (a<0) a = 0; nco = a; a = -(0.148 * (double)epal[c].r) - (0.291 * (double)epal[c].g) + (0.439 * (double)epal[c].b) + 128; if (a>255) a = 255; if (a<0) a = 0; nco = a; nco = epal[c].t; } nco = 0; //????? l2o = subo; subo += 2; y = 0; odd_row: for(; y4) { a2b(0); a2b(3); c -= 4; } a2b(0); a2b(c - 1); } } if (bc != 4) nco = bb << (2*bc); } if (!(y&1)) { if (!(subo&1)) { if (debug>3) fprintf(stderr,\ "padded betweed fields with 1 byte to %d\n",subo%4); nco = 0; } y = 1; sub[l2o] = (subo - l2o - 2) >> 8; sub[l2o+1] = (subo - l2o - 2); goto odd_row; } nco = 0;// no additional commands c = 0; while (subo%4) { nco = 0; c++; } if (debug>3) fprintf(stderr,"padded with %d byte\n",c); sub[0] = subo >> 8; sub[1] = subo; if (subo == 65536) return -1; else return subo; } /* end function svcd_encode */ #define an(b) do { bb = (bb << 4)+(b); bc--; if (!bc) { bc = 2; nco = bb; }} while (0) int cvd_encode() { unsigned int x, y, c, d; double a; subo = 4; ofs = 4; c = 0; for(y = 0; y < yd; y += 2) { odd_row_cvd: bc = 2; bb = 0; for(x = 0; x < xd;) { d = fimg[y * xd + x]; c = 1; while (((++x) < xd) && (fimg[y * xd + x] == d) ) c++; if(x == xd) { an(0); an(d); if (bc != 2) an(0); continue; } while(c > 3) { an(12 + d); c -= 3; } an((c << 2) + d); } } if(!(y & 1)) { y = 1; ofs1 = subo; goto odd_row_cvd; } sub[2] = subo >> 8; sub[3] = subo; /* setting this to all 0xff then no more subtitles */ nco = 0x0c; nco = 0; nco = 0; nco = 0; /* set pallette 0-3 */ for(c = 0; c < 4; c++) { //#define nco if (subo<65536) sub[subo++] nco = 0x24 + c; if(debug > 3) { fprintf(stderr, "c=%d R=%.2f G=%.2f B=%.2f\n",\ c, (double)epal[c].r, (double)epal[c].g, (double)epal[c].b); } /* Y */ a = (0.257 * (double)epal[c].r) + (0.504 * (double)epal[c].g) +\ (0.098 * (double)epal[c].b) + 16.0; if (a > 255) a = 255; if (a < 0) a = 0; nco = a; if(debug > 3) { fprintf(stderr, "Y=%.2f sub[subo]=%ud\n", a, sub[subo - 1]); } /* U */ a = (0.439 * (double)epal[c].r) - (0.368 * (double)epal[c].g) -\ (0.071 * (double)epal[c].b) + 128.0; if (a > 255) a = 255; if (a < 0) a = 0; nco = a; if(debug > 3) { fprintf(stderr, "U=%.2f sub[subo]=%ud\n", a, sub[subo - 1]); } /* V */ a = -(0.148 * (double)epal[c].r) - (0.291 * (double)epal[c].g) +\ (0.439 * (double)epal[c].b) + 128.0; if (a > 255) a = 255; if (a < 0) a = 0; nco = a; if(debug > 3) { fprintf(stderr, "V=%.2f sub[subo]=%ud (0x%0x)\n",\ a, sub[subo - 1], sub[subo - 1]); } } /* end for pallette 0-3 */ /* sethighlight pallette */ for(c = 0; c < 4; c++) { //#define nco if (subo<65536) sub[subo++] nco = 0x2c + c; if(debug > 3) { fprintf(stderr, "c=%d R=%.2f G=%.2f B=%.2f\n",\ c, (double)epal[c].r, (double)epal[c].g, (double)epal[c].b); } /* Y */ a = (0.257 * (double)epal[c].r) + (0.504 * (double)epal[c].g) +\ (0.098 * (double)epal[c].b) + 16; if (a > 255) a = 255; if (a < 0) a = 0; nco = a; if(debug > 3) { fprintf(stderr, "Y=%.2f sub[subo]=%d\n", a, sub[subo - 1]); } /* U */ a = (0.439 * (double)epal[c].r) - (0.368 * (double)epal[c].g) -\ (0.071 * (double)epal[c].b) + 128; if (a > 255) a = 255; if (a < 0) a = 0; nco = a; if(debug > 3) { fprintf(stderr, "U=%.2f sub[subo]=%d\n", a, sub[subo - 1]); } /* V */ a = -(0.148 * (double)epal[c].r) - (0.291 * (double)epal[c].g) +\ (0.439 * (double)epal[c].b) + 128; if (a > 255) a = 255; if (a < 0) a = 0; nco = a; if(debug > 3) { fprintf(stderr, "V=%.2f sub[subo]=%d\n", a, sub[subo - 1]); } } /* end for pallette 4-7 */ if(debug > 3) { fprintf(stderr,\ "epal[0].t=%d epal[1].t=%d epal[2].t=%d epal[3].t=%d\n",\ epal[0].t, epal[1].t, epal[2].t, epal[3].t); } /* x0, y0 */ nco = 0x17; nco = 0xf0 + (x0 >> 6); nco = (x0 << 2) + (y0 >> 8); nco = y0; /* xd, yd */ nco = 0x1f; nco = 0xf0 + ((x0 + xd - 1) >> 6); nco = ((x0 + xd - 1) << 2) + ((y0 + yd - 1) >> 8); nco = y0 + yd - 1; /* 0x37 is pallette.t 0-3 contrast */ nco = 0x37; nco = 0xff; //nco = 0x00; //nco = 0xff; nco = (epal[3].t & 0xf0) + (epal[2].t >> 4); nco = (epal[1].t & 0xf0) + (epal[0].t >> 4); if(debug > 3) { fprintf(stderr, "EPALS nco0(2 3h, 2l)=%02x nco1(2 1h,0l)=%02x\n",\ sub[subo - 1], sub[subo - 2]); } /* 0x3f is high light pallette.t 4-7 contrast */ nco = 0x3f; nco = 0xff; nco = 0xff; nco = 0xf0; /* ofs is 4 ? is offset in bitmap to first field data (interlace) */ nco = 0x47; nco = 0xff; nco = ofs >> 8; nco = ofs; /* ofs1 is offset to other field in bitmap (interlace) */ nco = 0x4f; nco = 0xff; nco = ofs1 >> 8; nco = ofs1; /* unknown!!! (in RX too!) setting all to 0xff keeps the pic on screen! */ nco = 0x0c; nco = 0; nco = 0; nco = 0; /* sd, time in display, duration */ nco = 0x04; nco = sd >> 16; nco = sd >> 8; nco = sd; // IA3 //0: 02 68 02 24 //1: 08 61 08 1d //2: 08 6b 08 27 //3: 07 6b 07 27 //4: 05 40 04 fc //5: 08 81 08 3d //6: 05 4f 15 40 sub[0] = subo >> 8; sub[1] = subo; nco = 4; nco = 8; nco = 12; nco = 16; if(subo == 65536) return -1; else return subo; } /* end function cvd_encode */ int h2d(char *ch) { int a; if ((ch[0] < 48) || ((ch[0] > 57) && (ch[0] < 97)) || (ch[0] > 102)) return 0; if ((ch[1] < 48) || ((ch[1] > 57) && (ch[1] < 97)) || (ch[1] > 102)) return 0; if (ch[0] > 57) a = ch[0] - 87; else a = ch[0] - 48; a = a << 4; if (ch[1] > 57) a += ch[1] - 87; else a += ch[1] - 48; return a; } /* end function svcd_encode */ void rns() { //unsigned char lbuf[256 + 80]; char lbuf[256 + 80]; int a,b, i; if(debug_flag) { fprintf(stdout, "rns(): arg none\n"); } colors_specified_flag = 0; lns: if (feof(fds) || (!fgets(lbuf, 256 + 80, fds)) ) { nspts = -1; return; } iline++; /* find start of line ? */ if (strlen(lbuf) == 256 + 80 - 1) while(getc(fds) != 10); /* scip comments and stuff ? */ if ((lbuf[0] == '#') || (lbuf[0] == ' ') || (lbuf[0] == 0)) goto lns; /* get bitmap filename */ a = 0; while(lbuf[a] && (lbuf[a] != 32) && (lbuf[a] != 9)) { nbuf[a] = lbuf[a]; a++; } /* string termination */ nbuf[a] = 0; /* get start time */ while((lbuf[a]) && !((lbuf[a] > 47) && (lbuf[a] < 58))) a++; nspts = atoi(lbuf + a) * 60 * 60 * 90000; a += 3; nspts += atoi(lbuf + a) * 60 * 90000; a += 3; nspts += atoi(lbuf + a) * 90000; a += 3; nspts += atoi(lbuf + a) * 900; a += 2; /* get stop time */ while((lbuf[a]) && !((lbuf[a] > 47) && (lbuf[a] < 58))) a++; sd_ = atoi(lbuf+a) * 60 * 60 * 90000; a += 3; sd_ += atoi(lbuf + a) * 60 * 90000; a += 3; sd_ += atoi(lbuf + a) * 90000; a += 3; sd_ += atoi(lbuf + a) * 900; a += 2; if(a > strlen(lbuf)) { skip++; if (debug > -1) fprintf(stderr,"warning, unable to parse line %d, skipping\n", iline); goto lns; } /* sanity test */ if (!sd_) sd_ = -1; else { if (sd_ <= nspts) { if (debug > -1) { fprintf(stderr, "warning: sub on line %d has end<=start, skipping\n", iline); } skip++; goto lns; } sd_ -= nspts; } nspts += tofs; /* h size */ while((lbuf[a]) && !((lbuf[a] > 47) && (lbuf[a] < 58))) a++; xd_ = atoi(lbuf + a); /* scip space */ while((lbuf[a]) && !((lbuf[a] < 48) || (lbuf[a] > 57))) a++; /* v size */ while((lbuf[a]) && !((lbuf[a] > 47) && (lbuf[a] < 58))) a++; yd_ = atoi(lbuf + a); /* scip space (did he never hear about scanf????? */ while((lbuf[a]) && !((lbuf[a] < 48) || (lbuf[a] > 57))) a++; /* x pos */ while((lbuf[a]) && !((lbuf[a] > 47) && (lbuf[a] < 58))) a++; x0_ = atoi(lbuf + a); /* scip space */ while((lbuf[a]) && !((lbuf[a] < 48) || (lbuf[a] > 57))) a++; /* y pos */ while((lbuf[a]) && !((lbuf[a] > 47) && (lbuf[a] < 58))) a++; if(!lbuf[a]) { skip++; if (debug>-1) { fprintf(stderr, "warning, unable to parse line %d, skipping\n",iline); } goto lns; } y0_ = atoi(lbuf + a); /* scip space */ while( (lbuf[a]) && !( (lbuf[a] < 48) || (lbuf[a] > 57) ) ) a++; /* 4 contrast values */ for(b = 0; b < 4; b++) { /* get value */ while( (lbuf[a]) && !( (lbuf[a] > 47) && (lbuf[a] < 58) ) ) a++; if (lbuf[a]) { pal_[b].t = atoi(lbuf + a); if(b == 0) background_contrast = atoi(lbuf + a); if(b == 1) pattern_contrast = atoi(lbuf + a); if(b == 2) emphasis1_contrast = atoi(lbuf + a); if(b == 3) emphasis2_contrast = atoi(lbuf + a); } /* scip space */ while( (lbuf[a]) && !( (lbuf[a] < 48) || (lbuf[a] > 57))) a++; if (debug > 3) { fprintf(stderr,\ "pal: %d #%.2x%.2x%.2x %d\n",\ b, pal_[b].r, pal_[b].g, pal_[b].b, pal_[b].t); } } /* Set pointers to the color lookup table in the IFO (CLUT) for each parameter. Range = 0 - 15 */ /* defaults */ background = 0; pattern = 1; emphasis1 = 2; emphasis2 = 3; /* get character background pointer in CLUT */ while( (lbuf[a]) && !( (lbuf[a] > 47) && (lbuf[a] < 58) ) ) a++; if (lbuf[a]) background = atoi(lbuf + a); background &= 15; /* scip space */ while( (lbuf[a]) && !( (lbuf[a] < 48) || (lbuf[a] > 57) ) ) a++; /* get character pattern pointer in CLUT */ while( (lbuf[a]) && !( (lbuf[a] > 47) && (lbuf[a] < 58) ) ) a++; if (lbuf[a]) pattern = atoi(lbuf + a); pattern &= 15; /* scip space */ while( (lbuf[a]) && !( (lbuf[a] < 48) || (lbuf[a] > 57) ) ) a++; /* get character emphasis1 pointer in CLUT */ while( (lbuf[a]) && !( (lbuf[a] > 47) && (lbuf[a] < 58) ) ) a++; if (lbuf[a]) emphasis1 = atoi(lbuf + a); emphasis1 &= 15; /* scip space */ while( (lbuf[a]) && !( (lbuf[a] < 48) || (lbuf[a] > 57) ) ) a++; /* get character emphasis2 pointer in CLUT */ while( (lbuf[a]) && !( (lbuf[a] > 47) && (lbuf[a] < 58) ) ) a++; if (lbuf[a]) emphasis2 = atoi(lbuf + a); emphasis2 &= 15; colors_specified_flag = 1; /* scip space */ while( (lbuf[a]) && !( (lbuf[a] < 48) || (lbuf[a] > 57) ) ) a++; /* get submux-dvd control command code */ /* for compatibility with old versions: PIXELS + FORCED START + STOP = 1 + 16 + 2 = 19 */ submux_command = 19; while( (lbuf[a]) && !( (lbuf[a] > 47) && (lbuf[a] < 58) ) ) a++; if (lbuf[a]) submux_command = atoi(lbuf + a); /* scip space */ while( (lbuf[a]) && !( (lbuf[a] < 48) || (lbuf[a] > 57) ) ) a++; /* in case of COL_CON read the values */ /* default */ c_h_blocks = 0; if(submux_command & 4) { /* read vertical region start */ while( (lbuf[a]) && !( (lbuf[a] > 47) && (lbuf[a] < 58) ) ) a++; if (lbuf[a]) c_start_line = atoi(lbuf + a); /* scip space */ while( (lbuf[a]) && !( (lbuf[a] < 48) || (lbuf[a] > 57) ) ) a++; /* read vertical region end */ while( (lbuf[a]) && !( (lbuf[a] > 47) && (lbuf[a] < 58) ) ) a++; if (lbuf[a]) c_end_line = atoi(lbuf + a); /* scip space */ while( (lbuf[a]) && !( (lbuf[a] < 48) || (lbuf[a] > 57) ) ) a++; /* read data for up to 16 horizontal regions */ while(1) { if( ! lbuf[a] ) break; /* read c_h_start[c_h_blocks] */ while( (lbuf[a]) && !( (lbuf[a] > 47) && (lbuf[a] < 58) ) ) a++; if (lbuf[a]) c_h_start[c_h_blocks] = atoi(lbuf + a); /* scip space */ while( (lbuf[a]) && !( (lbuf[a] < 48) || (lbuf[a] > 57) ) ) a++; /* read c_contrast0[c_h_blocks] */ while( (lbuf[a]) && !( (lbuf[a] > 47) && (lbuf[a] < 58) ) ) a++; if (lbuf[a]) c_contrast0[c_h_blocks] = atoi(lbuf + a); /* scip space */ while( (lbuf[a]) && !( (lbuf[a] < 48) || (lbuf[a] > 57) ) ) a++; /* read c_contrast1[c_h_blocks] */ while( (lbuf[a]) && !( (lbuf[a] > 47) && (lbuf[a] < 58) ) ) a++; if (lbuf[a]) c_contrast1[c_h_blocks] = atoi(lbuf + a); /* scip space */ while( (lbuf[a]) && !( (lbuf[a] < 48) || (lbuf[a] > 57) ) ) a++; /* read c_contrast2[c_h_blocks] */ while( (lbuf[a]) && !( (lbuf[a] > 47) && (lbuf[a] < 58) ) ) a++; if (lbuf[a]) c_contrast2[c_h_blocks] = atoi(lbuf + a); /* scip space */ while( (lbuf[a]) && !( (lbuf[a] < 48) || (lbuf[a] > 57) ) ) a++; /* read c_contrast3[c_h_blocks] */ while( (lbuf[a]) && !( (lbuf[a] > 47) && (lbuf[a] < 58) ) ) a++; if (lbuf[a]) c_contrast3[c_h_blocks] = atoi(lbuf + a); /* scip space */ while( (lbuf[a]) && !( (lbuf[a] < 48) || (lbuf[a] > 57) ) ) a++; /* read c_background[c_h_blocks] */ while( (lbuf[a]) && !( (lbuf[a] > 47) && (lbuf[a] < 58) ) ) a++; if (lbuf[a]) c_background[c_h_blocks] = atoi(lbuf + a); /* scip space */ while( (lbuf[a]) && !( (lbuf[a] < 48) || (lbuf[a] > 57) ) ) a++; /* read c_pattern[c_h_blocks] */ while( (lbuf[a]) && !( (lbuf[a] > 47) && (lbuf[a] < 58) ) ) a++; if (lbuf[a]) c_pattern[c_h_blocks] = atoi(lbuf + a); /* scip space */ while( (lbuf[a]) && !( (lbuf[a] < 48) || (lbuf[a] > 57) ) ) a++; /* read c_emphasis1[c_h_blocks] */ while( (lbuf[a]) && !( (lbuf[a] > 47) && (lbuf[a] < 58) ) ) a++; if (lbuf[a]) c_emphasis1[c_h_blocks] = atoi(lbuf + a); /* scip space */ while( (lbuf[a]) && !( (lbuf[a] < 48) || (lbuf[a] > 57) ) ) a++; /* read c_emphasis2[c_h_blocks] */ while( (lbuf[a]) && !( (lbuf[a] > 47) && (lbuf[a] < 58) ) ) a++; if (lbuf[a]) c_emphasis2[c_h_blocks] = atoi(lbuf + a); /* scip space */ while( (lbuf[a]) && !( (lbuf[a] < 48) || (lbuf[a] > 57) ) ) a++; c_h_blocks++; } /* end for all horizontal regions in this vertical region */ c_h_blocks--; if(debug_flag) { for(i = 0; i < c_h_blocks; i++) { fprintf(stdout,\ "rns(): c_h_start=%d\n\ c_background=%d c_pattern=%d c_emphasis1=%d c_emphasis2=%d\n\ c_contrast0=%d c_contrast1=%d c_contrast2=%d c_contrast3=%d\n",\ c_h_start[i],\ c_background[i], c_pattern[i], c_emphasis1[i], c_emphasis2[i],\ c_contrast0[i], c_contrast1[i], c_contrast2[i], c_contrast3[i]); } fprintf(stdout, "rns(): c_h_blocks=%d\n", c_h_blocks); } } /* end if submux_command & 4 */ if(debug_flag) { fprintf(stdout,\ "rns(): background=%d pattern=%d emphasis1=%d emphasis2=%d submux_command=%d\n",\ background, pattern, emphasis1, emphasis2, submux_command); } if(debug > 2) { fprintf(stderr,\ "img: %s, %d (%.2f) %d (%.2f) %d,%d %d,%d\n",\ nbuf, nspts, (double)nspts / 90000, sd_, (double)sd_ / 90000, x0_,\ y0_, xd_, yd_); } } /* end function rns */ int imgfix() { int a, b, i, x0_, y0_, xd_, yd_, x, y, j; int cst[4]; unsigned char c, r; if (!optimize) { for(c = 0; c < 4; c++) { epal[c].r = pal[c].r; epal[c].g = pal[c].g; epal[c].b = pal[c].b; epal[c].t = pal[c].t; } a = 0; for(y = 0; (y < yd) && (y < yd); y++) { for(x = 0; (x < xd) && (x < xd); x++) { fimg[a] = img[a]; a++; } } //#define P_TEST2 #ifdef P_TEST2 for(a = 0; a < 4; a++) { fprintf(stderr, "WAS P_TEST2 ORIGINAL setting\n\ epal[%d].r=%d\n\ epal[%d].g=%d\n\ epal[%d].b=%d\n\ epal[%d].t=%d\n",\ a, epal[a].r,\ a, epal[a].g,\ a, epal[a].b,\ a, epal[a].t); } #endif /* P_TEST2 */ return 1; } //xd and yd should be multiples of 4... a = 0; x0_ = maxx; xd_ = 0; y0_ = yd_ = -1; cst[0] = cst[1] = cst[2] = cst[3] = 0; for(y = 0; y < yd; y++) for(x = 0;x < xd; x++) { if (pal[img[a++]].t) { if (y0_ == -1) y0_ = y; if (x < x0_) x0_ = x; if (x > xd_) xd_ = x; yd_ = y; } } if(yd_ != -1) { r = 0; if(svcd) { for(y = y0_; y < yd_; y++) for(x =x0_ ;x < xd_; x++) cst[ img[a] ]++; a = cst[0]; for(i = 1; i < 4; i++) if (a < cst[i]) { a = cst[i]; r = i; } } else for(a = 3; a > 0;a--) if ( !pal[a].t) r = a; // if (debug>2) fprintf(stderr,"colors rotated %d steps\n", r); for(c = 0; c < 4; c++) { epal[c].r = pal[(c + r) % 4].r; epal[c].g = pal[(c + r) % 4].g; epal[c].b = pal[(c + r) % 4].b; epal[c].t = pal[(c + r) % 4].t; } //#define P_TEST2 #ifdef P_TEST2 for(a = 0; a < 4; a++) { fprintf(stderr, "WAS P_TEST2 ROTATE setting\n\ epal[%d].r=%d\n\ epal[%d].g=%d\n\ epal[%d].b=%d\n\ epal[%d].t=%d\n",\ a, epal[a].r,\ a, epal[a].g,\ a, epal[a].b,\ a, epal[a].t); } #endif /* P_TEST2 */ r = 4 - r; xd_ -= x0_ -1; yd_ -= y0_ -1; b = 0; c = 0; for(a = 3; a > 0; a--) if (!epal[a].t) c = a; y = 0; if( ( (y0 + y0_) & 1) && (even_yofs)) { if (y0_) y0_--; else { for (j = 0;j < xd_ + xd; j++) fimg[b++] = c; y++; yd_++; y0--; } } if (even_xd) if (xd_ & 1) xd_++; a = y0_ * xd + x0_; for(;(y < yd_) && (y < yd); y++) { for(x = 0; (x < xd_) && (x < xd); x++) fimg[b++] = (img[a++] + r) % 4; if(xd > xd_) a += xd - xd_; if(xd < xd_) for (j = 0; j < xd_ - xd; j++) fimg[b++] = c; } while (yd_ & 1) { for(x = 0; x < xd_; x++) fimg[b++] = c; yd_++; } x0 += x0_; y0 += y0_; xd = xd_; yd = yd_; if (debug > 2) { fprintf(stderr,\ "x0: %d y0: %d w: %d h: %d start: %fs len: %fs\n",\ x0, y0, xd, yd, (double)spts / 90000, (double)sd / 90000); } return 1; } return 0; } /* end function imgfix */ unsigned char *subtitle_image_buffer; unsigned char *subtitle_packet_buffer; unsigned char *even_buf, *odd_buf; int main(int argc,char **argv) { int fdi, fdo; unsigned int q, c, a, i, j, k, gts, pts, muxrate, sector_size, frame, lps; unsigned short int b, vss, subno; unsigned char cc, seq, psbuf[psbufs], substr; char *nptr[3]; int ncnt; int sub_size; int bytes_send; unsigned short int header_size; int mode; int last_pts; int max_sub_size; int bytes_to_sector; int stuffing_size; int padding_size; int bytes_left; int bytes_free; int available_space; int header_mode; int packet_length; int pack_extention_flag1; int pack_extention_flag2; int pack_stuffing_flag; int first_flag; int pes_scrambling_control; int pes_priority_flag; int data_alignment_indicator_flag; int copyright_flag; int original_flag; c_start_line = 2; c_end_line = 499; c_h_start[0] = 100; c_h_start[1] = 200; c_h_start[2] = 300; c_background[0] = 0; c_background[1] = 0; c_background[2] = 0; c_pattern[0] = 5; c_pattern[1] = 9; c_pattern[2] = 13; c_emphasis1[0] = 2; c_emphasis1[1] = 2; c_emphasis1[2] = 2; c_emphasis2[0] = 3; c_emphasis2[1] = 3; c_emphasis2[2] = 3; c_contrast0[0] = 0; c_contrast0[1] = 0; c_contrast0[2] = 0; c_contrast1[0] = 15; c_contrast1[1] = 15; c_contrast1[2] = 15; c_contrast2[0] = 15; c_contrast2[1] = 15; c_contrast2[2] = 15; c_contrast3[0] = 0; c_contrast3[1] = 0; c_contrast3[2] = 0; c_h_blocks = 3; mode = 0; /* default DVD */ odd_buf = malloc(maxx * maxy); if(! odd_buf) { fprintf(stderr, "submux-dvd(): could not allocate space for odd_buf, aborting.\n"); exit(1); } even_buf = malloc(maxx * maxy); if(! even_buf) { fprintf(stderr, "submux-dvd(): could not allocate space for even_buf, aborting.\n"); exit(1); } subtitle_image_buffer = malloc(maxx * maxy * 3); if(! subtitle_image_buffer) { fprintf(stderr, "submux-dvd(): could not allocate space for subtitle_image_buffer, aborting.\n"); exit(1); } subtitle_packet_buffer = malloc( SUB_BUFFER_MAX); //maxx * maxy * 3); //SUB_BUFFER_MAX); if(! subtitle_packet_buffer) { fprintf(stderr, "submux-dvd(): could not allocate space for subtitle_packet_buffer, aborting.\n"); exit(1); } //fprintf(stderr, "malloc subtitle_packet_buffer=%p\n", subtitle_packet_buffer); sub = subtitle_packet_buffer; cbuf = malloc(65536); img = malloc(maxx * maxy); fimg = malloc(maxx * maxy); fprintf(stderr, "submux-dvd-%s copyright 2002-always Jan Panteltje\n", VERSION); if (argc<4) { parse_err: fprintf(stderr, "submux-dvd [options] [in.mpg] [script.sub] [out.mpg]\n"); fprintf(stderr, "options:\n"); fprintf(stderr, "-c set copyright bit.\n"); fprintf(stderr, "-m 0 = DVD mode (default), 1 = CVD, 2 = SVCD.\n"); fprintf(stderr, "-s number of the substream to insert (default 0).\n"); fprintf(stderr, "-t