summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTORS33
-rw-r--r--COPYING340
-rw-r--r--HISTORY293
-rw-r--r--INSTALL22
-rw-r--r--Makefile101
-rw-r--r--README20
-rw-r--r--TODO43
-rw-r--r--dxr3.c241
-rw-r--r--dxr3.h97
-rw-r--r--dxr3audiodecoder.c316
-rw-r--r--dxr3audiodecoder.h97
-rw-r--r--dxr3blackframe.c1294
-rw-r--r--dxr3colormanager.c388
-rw-r--r--dxr3colormanager.h126
-rw-r--r--dxr3configdata.c47
-rw-r--r--dxr3configdata.h172
-rw-r--r--dxr3demuxdevice.c710
-rw-r--r--dxr3demuxdevice.h103
-rw-r--r--dxr3device.c467
-rw-r--r--dxr3device.h105
-rw-r--r--dxr3ffmpeg.c91
-rw-r--r--dxr3ffmpeg.h75
-rw-r--r--dxr3generaldefines.h54
-rw-r--r--dxr3i18n.c607
-rw-r--r--dxr3i18n.h36
-rw-r--r--dxr3interface.c1205
-rw-r--r--dxr3interface.h221
-rw-r--r--dxr3interface_spu_encoder.c688
-rw-r--r--dxr3interface_spu_encoder.h153
-rw-r--r--dxr3multichannelaudio.c784
-rw-r--r--dxr3multichannelaudio.h43
-rw-r--r--dxr3nextpts.c32
-rw-r--r--dxr3nextpts.h85
-rw-r--r--dxr3osd.c48
-rw-r--r--dxr3osd.h23
-rw-r--r--dxr3osd_subpicture.c265
-rw-r--r--dxr3osd_subpicture.h37
-rw-r--r--dxr3outputthread.c239
-rw-r--r--dxr3outputthread.h104
-rw-r--r--dxr3pesframe.c273
-rw-r--r--dxr3pesframe.h268
-rw-r--r--dxr3singleton.h59
-rw-r--r--dxr3spudecoder.c640
-rw-r--r--dxr3spudecoder.h190
-rw-r--r--dxr3syncbuffer.c496
-rw-r--r--dxr3syncbuffer.h198
-rw-r--r--dxr3sysclock.c77
-rw-r--r--dxr3sysclock.h66
-rw-r--r--dxr3tools.h109
-rw-r--r--dxr3vdrincludes.h58
50 files changed, 12239 insertions, 0 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
new file mode 100644
index 0000000..0da75f0
--- /dev/null
+++ b/CONTRIBUTORS
@@ -0,0 +1,33 @@
+The following people have contributed to the development of this plugin in
+one way or the another. Without their help, the plugin would not be as good
+as it is now.
+
+Jon Burgess
+Malcolm Caldwell
+Martin Cap
+Stuart Daines
+Martin Dauskardt
+Peter Dittmann
+Gavin Hamill
+Paavo Hartikainen
+Tobias Haustein
+Stefan Hülswitt
+Thomas Husterer
+Seppo Ingalsuo
+Antti Järvinen
+Atte Manninen
+Lars Neufurth (donated some money for Christian's DD 5.1 system)
+Andre Neumann
+Luca Olivetti
+Richard P.
+Miika Pekkarinen
+Teemu Rantanen
+Jarkko Santala
+Marco Schlüßler
+Stephan Skrodzki
+Ville Skyttä
+Mikko Tuumanen
+Sascha Volkenandt
+Kimmo Vuorinen
+
+Thank you very much :)
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..3912109
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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.
+
+ <signature of Ty Coon>, 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.
diff --git a/HISTORY b/HISTORY
new file mode 100644
index 0000000..04fb409
--- /dev/null
+++ b/HISTORY
@@ -0,0 +1,293 @@
+VDR Plugin 'dxr3' Revision History
+----------------------------------
+
+2002-08-04: Version 0.0.1
+
+- Initial revision.
+
+2002-11-10: Version 0.1.0
+
+- Rewritten Audio/Video-sync engine
+- Changed OSD colors (but still limited to four colors)
+
+2002-11-12: Version 0.1.1
+
+- Changed Makefile (needed for vdr 1.1.15)
+- The plugin should now work smoother under heavy system load (e.g. network traffic)
+
+2002-12-23: Version 0.1.2
+- Compiles now with gcc3.2.
+- Fixed unsigned / signed bug in output thread (dxr3outputthread.c) which led
+to sporadic resync (still frame and jump of about 1s).
+- OSD is now as colorful as vdr with DVB-s
+- OSD rescaling for channels with a lower horizontal resolution
+
+2002-12-29: Version 0.1.3
+- SPU write is now protected with a mutex by using the Dxr3AbstractionDevice.
+- Fixed horizontal size detection.
+- Added usleep call during still picture to reduce cpu load.
+- Removed calls to WaitForSysClock in dxr3outputthread.c which led to problems
+during replay on some systems (Thanks to Atte Manninen for reporting this).
+- Did some minor changes to dxr3outputthread.c which hopefully will increase
+reliability.
+- Changed osd scale rule. Scaling now only happens if the horizontal size is
+smaller than 700.
+
+2003-01-05: Version 0.1.4
+- Small bugfix in dxr3demuxdevice.c
+
+2003-02-19: Version 0.1.5
+- Support for MP3 plugin.
+- Support for radio channels. Requested by Richard P. (???) who send me a
+ sample code ... thanks.
+- Some fixes to get along with corrupt pes data (which should actually be
+ solved in a lower layer). Thanks to Teemu Rantanen.
+- Changed sync buffer size during replay to reduce "jumps" in cutted streams.
+ Thanks to Atte Manninen for the idea.
+- Support for still frame handling. Now it is possible to move the editing
+ marks with visible corresponding i-frames. Unfortunately this doesn't seem to
+ work with finish dvb streams.
+- Some tuning to reduce cpu load during replay.
+
+2003-02-25: Version 0.1.6
+- Added black frames between channel switches (which solves the frozen picture
+ 'problem' when using the mp3-plugin, too).
+- Increased thread priority of output threads which improves live stream
+ quality on my system (K6II 350).
+
+2003-03-23: Version 0.1.7
+- Added unix domain server interface to close and reopen dxr3 devices without
+ stopping vdr (see dxr3_ux_client.pl script on how to use this).
+ Requested by Atte Manninen.
+ Thanks to Atte Manninen and Teemu Rantanen for testing and fixing some problems.
+- Added support for external player mode.
+- Some cosmetic changes.
+- Some changes to reduce cpu load.
+- Added workaround handling for osd crash (driver patch necessary; patch with
+ em8300_patch.diff).
+ Thanks to Teemu Rantanen and Malcolm Caldwell for testing this.
+- Added buffered output for mp3-plugin audio data. This seems to improve audio
+ quality significantly.
+- Reduced count of audio errors (wrong data rate).
+- Changed channel switch behavior (to remove audio disturbances => channel switching
+ is a little bit slower now).
+- Added exception handling for defect pes streams.
+- Added more checks by introducing a new pes parsing class.
+- Fixed buffer overrun problem. Because of the missing pll control a buffer overrun
+ happens after staying for a long time on the same channel. In older version
+ the output stopped after a buffer overrun. Now the buffer will be cleared and
+ the output will continue after about a second.
+- New buffer handling in PlayVideo.
+
+2003-03-23: Version 0.1.7a
+- Bugfix in A/V-engine for audio output with less dropouts
+
+2003-04-28: Version 0.1.8
+- Added support for dvd-plugin (subtitles doesn't work properly so far).
+- Added setup parameter to define the dxr3-card which shall be used by vdr
+ (thanks to Tobias Haustein).
+- Added setup parameter to force letter box mode (for wrong aspect ratio coded
+ in pes-stream). This parameter is not saved.
+- Added support for video format setup parameter (no WSS support).
+- Fixed external player support (thanks to Seppo Ingalsuo).
+- Added volume support (thanks to Teemu Rantanen).
+- Fixed I-Frame display problem (cutting and fast forward/backwards in some streams).
+ Those who have problems with fast forward/backward might want to patch
+ vdr (use vdr_iframe_patch.diff / for vdr-1.1.29).
+- Reduced memory consumption.
+- Fixed problem with digital output setup parameter.
+- Fixed wrong bit error detection.
+- Changed bit error handling.
+
+2003-04-28: Version 0.1.8a
+- Second trial to fix external player support (thanks to Jarkko Santala)
+
+2003-05-07: Version 0.1.9
+- Added support for AC3 streams (based on classes of
+ the AC3overDVB Patch maintained by Stefan Huelswitt).
+- Added DXR3 main menu entry. It's now possible to:
+ - Reset DXR3-hardware.
+ - Toggle Force LetterBox.
+ - Switch to Digital Output.
+ - Switch to AC3 Output (when already listening to digital output).
+- Added short ac3 information text on channel switch.
+- Reduced analog audio disturbances.
+- Fixed audio initialization problem.
+
+2003-05-07: Version 0.2.0
+- Fixed compatibility problem with vdr version 1.1.31 and higher.
+- Fixed analog audio problem (spurious disturbances).
+- Added first cut mpeg1 support: It works quite good with vcd plugin. As far as I know
+ this doesn't work reliable together with analog plugin. Thanks to Gavin Hamill for
+ testing support and investigations with analog plugin.
+ No osd scaling for mpeg1 at the moment.
+- Changed channel switch behavior with respect to mpeg1 support (it doesn't seem
+ to be possible to switch between mpeg1 and mpeg2 without closing and reopening the
+ video device).
+- Improved lib sync.
+
+2003-08-10: Version 0.2.1
+- Added setup entry to switch between ntsc and pal. This setting becomes active
+ after restarting vdr and reseting the dxr3 card, respectively.
+- Fixed uninitialized variable m_audioMode in dxr3abstractiondevice.c. Thanks
+ to Jon Burgess.
+- Fixed incorrect ioctl-problem. Thanks to Jon Burgess.
+- Fixed wrong scaled osd problem when starting vdr without live stream.
+- Fixed external player problem when return to dxr3 output after using ac3 output.
+ Thanks to Jarkko Santala for reporting this one.
+- Fixed wrong assert-call. Thanks to Andre Neumann.
+
+2004-01-04: Version 0.2.2
+
+- Some initialization fixes. Thanks to Jon Burgess.
+- Added patch from Teemu Rantanen to emergency exit if
+ the plugin is not able to recover from dxr3 driver crash.
+- Fixed some osd problems (Elchi, Games, etc.).
+- Changed Makefile to support vdr-1.3.0.
+
+2004-06-22: Version 0.2.3-alpha1 (only for vdr-portal.de)
+
+- we are using now <linux/em8300.h> instead of "em8300.h"
+- updated multichannelaudio.h/c with newest AC3overDVB-Patch-Source (0.2.6)
+- switched to new osd routines for vdr-1.3.7
+- added dxr3singleton.h
+- new interface to work with ffmpeg (chagned include to <avcodec.h>)
+- added a lot of commments and cosmetic code cleanups
+- using everywhere std::string - makes life nicer
+- moved dxr3absdevice to dxr3interface
+- rewritten some parts of dxr3interface
+- added anti-glinsch-when-fast-forward-and-then-play-patch ;)
+- killed DIAG and added a global logger, which is used only in
+ a few functions and not in every like DIAG
+- removed cDxr3StatusMonitor - i dont know why we need this
+- cleaned out unneeded includes
+- fixed memory leak in cDxr3Interface::UploadMicroCode:
+ If uploading of the microcode failed, the allocated memory wasn't
+ freed.
+- If we are changing the audiooutput now the plugin will call an overworked
+ AudioRepoen function, which does not shutdown the whole card.
+- Things like VIDEOMODE and AUDIOMODE are now set only ONCE on plugin start!
+- added check if memory in cDxr3SyncBuffer is allocated correct
+- introced a 'ToDo-System'.
+ in every *.c file there can be something like this at the top of the file:
+ /*
+ ToDo:
+ - cDxr3SyncBuffer::Push: XXX This is only a workaround until a sufficient control algorithm is implemented
+ */
+
+ So it is easier to keep track of stuff, which needs more work.
+- some small changes in dxr3colormanger.h/c
+- some small changes in dxr3pesframe.h/c
+- some small changes in spuenc.h/c
+- killed spu_dump in spuenc.h/c
+- renamed spuenc.h/c to dxr3interface_spu_encoder.h/c
+- changed dxr3audiodecoder to support the new ffmpeg interface
+- renamed dxr3absspu/dxr3absspulist to dxr3interace_spu/dxr3interace_spu_list
+- volume control logarithmic instead of linear.
+ This is a more natural sounding way of controlling the
+ volume. Thanks to Jon Burgess <mplayer@jburgess.uklinux.net>
+- added patch for DVD subtitles. Thanks to Stuart Daines <s.daines@ntlworld.com>
+- fixed memory leak in dxr3osd.c - Thanks to Miika Pekkarinen <miipekk@ihme.org>
+- added Tools namespace, which has a fixed Rgb2YCrCb function in it (dxr3tools.h)
+- kicked out Cmd in dxr3osd.h/c
+- added dxr3i18n.h/c
+- added Portuguese language support - thanks to Paulo Lopes <pmml@netvita.pt>
+- added Finnish language support - thanks to Hannu Savolainen <hannu@opensound.com>
+- added Swedish language support - thanks to Tomas Prybil <tomas@prybil.se>
+NOTE: I havent found time to include all of the languages, will be done in pre2
+- kicked out - i hope - some unneeded usleeps
+- rewrote cSPUEncoder: Now we imitate the Cmd funtion form the dvb drivers. So
+ we can use now the normal osd functions form dvbosd.c :)
+- added support for vdr-1.3.11
+- added videomode pal 60
+
+
+2004-07-29: Version 0.2.3-pre2 (now aviable on SourceForge)
+
+- fixed audio and video problems
+- works now with vdr < 1.3.7
+- added YUV2Rgb int dxr3tools.h (for dxr3spudecoder)
+- added some more debug infos in dxr3outputthread.c
+- added const keyword in dxr3configdata.h
+- added EM8300 include define in Makefile
+- added debuglevels, so we can define how much we want to log
+- assimilated spudecoder from vdr's dvbspu.c/h -> nice nav in dvds
+- kicked out cDxr3InterfaceSpu from dxr3interface.c/h
+- a little fix for cDxr3Interface::ResampleVolume
+- kicked out dxr3interface_spu.c/h and dxr3interface_spu_list.c/h, because
+ the new spudecoder dont need it anymore.
+- added dxr3cpu.c/h to get some infos about the cpu
+- added dxr3memcpy.c/h to get a little speedup - i hope
+- maybe a little audiofix: lastHeader in cDxr3AudioDecoder will now set to 0
+ with the constr. and not via Init()-function. So there should be now some lesser
+ audio scratches.
+- osd works now on every resolution (viva, viva plus,...)
+- added main-menu-entry
+- added in some parts some memory allocation tests
+- added fix for Makefile from vdr-portal.de -> should compile on more machines :)
+- added Tools::WriteInfoToOsd(...) - now some infos like "Releasing devices" are show
+ now on the osd again
+- fixed dxr3osd_subpicutre.c - thanks to Paavo Hartikainen <pahartik@sci.fi>
+
+
+2005-08-07: Version 0.2.3
+
+- fixed output of anamorphic video when tv aspect is configured to 16:9 in
+ DVB setup menu (Seppo Ingalsuo)
+- rewrote i18n support, improved Finnish translation and other bits
+ (Christian Gmeiner, Ville Skyttä)
+- fixed void cDxr3Interface::SetAudioDigitalPCM() (Stephan Skrodzki)
+- added many comments into source (Christian Gmeiner)
+- using doxygen for docs (Christian Gmeiner)
+- made path to microcode configurable in Makefile (Sascha Volkenandt)
+- better default directories in Makefile (Christian Gmeiner, vdr-wiki.de folks)
+- use std:: instead of namespace std
+ (bug #1044069, Christian Gmeiner, Ville Skyttä)
+- fixed #includes: moved #include "dxr3osd.h" from dxr3interface.h to
+ dxr3interface.c, removed not needed #includes (Christian Gmeiner)
+- added support for VDR 1.3.13 and later (Luca Olivetti, Peter Dittmann)
+- fixed checking of return falues when opening the em8300-* fifos
+ (Christian Gmeiner, Ville Skyttä)
+- removed explicit linking with zlib (Christian Gmeiner)
+- compiles now with 3.4.x gcc's (Christian Gmeiner, Ville Skyttä)
+- use $CXX for generating dependencies instead of hardcoded g++ (Ville Skyttä)
+- added descriptions to audio and video output threads
+ (#1112673, Ville Skyttä)
+- fixed audio and video thread deletion in demux device destructor
+ (#1112674, Ville Skyttä)
+- made "all" the default target in Makefile (Ville Skyttä)
+- avoid hang in pause mode with VDR >= 1.3.18 (Luca Olivetti)
+- avoid high CPU usage in pause mode (Luca Olivetti, Klaus Schmidinger)
+- improved GetSTC(): fixes DVB subtitles sync problems (Mikko Tuumanen)
+- limit OSD flush rate: prevents OSD from going berserk due to being
+ refreshed too often, see plugin settings (Luca Olivetti, Ville Skyttä)
+- borrow better OSD scaling routines from the Xine plugin (Luca Olivetti)
+- improve original OSD scaler for small resolutions (#1014339, Luca Olivetti)
+- improve error checking, eliminate some compiler warnings (Ville Skyttä)
+- fix OSD going pink after returning from the MPlayer plugin; while at it,
+ remove dxr3palettemanager.* and use VDR's cPalette
+ (Ville Skyttä, Martin Cap, Luca Olivetti)
+- remove unused dxr3unixserversocket.* from 0.2.x (Ville Skyttä)
+- fix sound with the MP3 plugin and VDR >= 1.3.18 (Antti Järvinen)
+- set aspect ratio and audio mode to unknown when releasing devices, fixes
+ the setup eg. after returning from the MPlayer plugin
+ (Luca Olivetti, Kimmo Vuorinen)
+- rework OSD color management, fixes eg. color "bleeding"
+ (Luca Olivetti, Thomas Husterer)
+- sync SPU decoder with VDR 1.3.23 (Ville Skyttä)
+- register only needed ffmpeg codec(s) (Marco Schlüßler)
+- fix crash at exit (Marco Schlüßler)
+- add support for mandatory subtitles (Marco Schlüßler)
+- avoid crashing with some corrupted streams (Jon Burgess)
+- remove optimized memcpy routines and related stuff, just use the glibc
+ one (Ville Skyttä)
+- clean up dead code for old VDR versions that hasn't worked for some time
+ anyway, VDR >= 1.3.11 is now required (Ville Skyttä)
+- improve recovery and avoid lockups caused by bad streams (Jon Burgess)
+- use VDR's facilities for logging (no more dxr3plugin.log), make it less
+ noisy (Ville Skyttä, Christian Gmeiner)
+- add setup option for hiding the main menu entry (Ville Skyttä)
+- implement stereo/left/right audio channel switching (Malcolm Caldwell)
+- limit card number to sane values in config (Ville Skyttä)
+- added Italian, Spanish and Catalan translations (Luca Olivetti)
+- don't override OSD's {Save,Restore}Region with dummies (Luca Olivetti)
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..60637ee
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,22 @@
+Prerequisites:
+
+- Get the DXR3 drivers from http://sourceforge.net/projects/dxr3 ,
+ install, configure, test and verify the installation.
+- Install the (latest) VDR developer version, or at least >= 1.3.11.
+- The plugin needs the libavcodec library from http://ffmpeg.sourceforge.net/
+
+Installation:
+
+- Get the latest dxr3-plugin version from
+ http://sourceforge.net/projects/dxr3plugin/
+- Unpack the package into "PLUGINS/SRC" directory.
+- Make a symbolic link to this dxr3-plugin (ln -s vdr_dxr3_x.x.x dxr3).
+- Check FFMDIR and EM8300 in Makefile.
+- Check extra settings in Makefile: -DMICROCODE, -DUSE_XINE_SCALER
+- Call "make plugins" in the VDR root directory.
+- Make sure your DXR3 driver modules are loaded and ready to run.
+- Start VDR with "vdr -Pdxr3".
+
+Supplemental patches:
+
+- See the patches/ directory.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..3ab2e57
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,101 @@
+#
+# Makefile for a Video Disk Recorder plugin
+#
+# $Id: Makefile,v 1.19 2005/08/15 17:28:49 austriancoder Exp $
+
+# The official name of this plugin.
+# This name will be used in the '-P...' option of VDR to load the plugin.
+# By default the main source file also carries this name.
+#
+PLUGIN = dxr3
+
+### The version number of this plugin (taken from the main source file):
+
+VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ print $$6 }' | sed -e 's/[";]//g')
+
+### The C++ compiler and options:
+
+CXX = g++
+CXXFLAGS = -O2 -Wall -Woverloaded-virtual
+
+### The directory environment:
+
+DVBDIR = ../../../DVB
+VDRDIR = ../../..
+LIBDIR = ../../lib
+TMPDIR = /tmp
+FFMDIR = /usr/local/include/ffmpeg
+EM8300 = /usr/include
+
+### Allow user defined options to overwrite defaults:
+
+-include $(VDRDIR)/Make.config
+
+### The version number of VDR (taken from VDR's "config.h"):
+
+VDRVERSION = $(shell grep 'define VDRVERSION ' $(VDRDIR)/config.h | awk '{ print $$3 }' | sed -e 's/"//g')
+
+### The name of the distribution archive:
+
+ARCHIVE = $(PLUGIN)-$(VERSION)
+PACKAGE = $(shell echo vdr-$(ARCHIVE) | sed -e 's/cvs$$/cvs'`date +%Y%m%d`/)
+
+### Includes and Defines (add further entries here):
+
+INCLUDES += -I$(VDRDIR)/include -I$(DVBDIR)/include -I$(FFMDIR) -I$(EM8300)
+LIBS = -L$(FFMDIR)/libavcodec -lavcodec -ljpeg
+DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
+DEFINES += -D_GNU_SOURCE
+
+# where is the microcode for the dxr3 located?
+DEFINES += -DMICROCODE=\"/usr/share/misc/em8300.uc\"
+
+# use OSD scaler borrowed from the Xine plugin?
+# comment this out to use the traditional vdr-dxr3 scaler
+DEFINES += -DUSE_XINE_SCALER
+
+### The object files (add further files here):
+
+OBJS = $(PLUGIN).o dxr3multichannelaudio.o dxr3sysclock.o dxr3colormanager.o dxr3syncbuffer.o dxr3audiodecoder.o \
+dxr3blackframe.o dxr3nextpts.o dxr3pesframe.o dxr3demuxdevice.o dxr3configdata.o \
+dxr3ffmpeg.o dxr3interface_spu_encoder.o dxr3i18n.o \
+dxr3interface.o dxr3device.o dxr3outputthread.o dxr3osd.o dxr3osd_subpicture.o dxr3spudecoder.o
+
+### Default target:
+
+all: libvdr-$(PLUGIN).so
+
+### Implicit rules:
+
+%.o: %.c
+ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
+
+# Dependencies:
+
+MAKEDEP = $(CXX) -MM -MG
+DEPFILE = .dependencies
+$(DEPFILE): Makefile
+ @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
+
+-include $(DEPFILE)
+
+### Targets:
+
+libvdr-$(PLUGIN).so: $(OBJS)
+ $(CXX) $(CXXFLAGS) -shared $(OBJS) $(LIBS) -o $@
+ @cp $@ $(LIBDIR)/$@.$(VDRVERSION)
+
+dist: clean
+ @-rm -rf $(TMPDIR)/$(ARCHIVE)
+ @mkdir $(TMPDIR)/$(ARCHIVE)
+ @cp -a * $(TMPDIR)/$(ARCHIVE)
+ @tar czf $(PACKAGE).tgz -C $(TMPDIR) \
+ --owner=root --group=root --exclude CVS $(ARCHIVE)
+ @-rm -rf $(TMPDIR)/$(ARCHIVE)
+ @echo Distribution package created as $(PACKAGE).tgz
+
+clean:
+ @-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~ \#*
+
+#indent:
+# emacs -batch --eval '(dolist (file command-line-args-left) (progn (find-file file) (c-indent-region (point-min) (point-max)) (save-buffer)))' *.h *.c
diff --git a/README b/README
new file mode 100644
index 0000000..a736c7a
--- /dev/null
+++ b/README
@@ -0,0 +1,20 @@
+This is a "plugin" for the Video Disk Recorder (VDR).
+
+Written by: Kai Moeller <dxr3_av@schluenss.de>,
+ Stefan Schluenss <dxr3_osd@schluenss.de>,
+ Christian Gmeiner <christian at visual-page.de>,
+ ...and numerous others, see CONTRIBUTORS.
+
+Project's home page: http://sourceforge.net/projects/dxr3plugin/
+
+Mailing lists: http://sourceforge.net/mail/?group_id=112648
+
+Latest version available at: See project home page
+
+Description: DXR3/Hollywood+ MPEG decoder card plugin which
+ allows using such a card as primary interface
+ for VDR.
+
+See the file COPYING for license information.
+For installation instructions, see the file INSTALL.
+See TODO for a list of work in progress items, bugs and some workarounds.
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..a825b1b
--- /dev/null
+++ b/TODO
@@ -0,0 +1,43 @@
+Known problems, bugs, and workarounds for this driver:
+------------------------------------------------------
+
+* The MP3 plugin's "show live TV" option while playing stuff doesn't work.
+ Workaround: none known, but the black screen isn't that bad if you
+ make the MP3 progress stuff/playlist visible...
+
+* VCD plugin does not work.
+ Workaround: use the MPlayer plugin to play VCDs.
+
+* No sound with the DVD plugin with VDR >= 1.3.18.
+ Workaround: use the MPlayer plugin to play DVDs.
+ Workaround 2: use VDR < 1.3.18.
+
+* When cutting recordings from some channels, the still picture is stuck
+ and won't move when you press 4 or 6 to fine tune the cutmarks.
+ Workaround: see vdr-iframe.patch in the patches/ directory or Reinhard
+ Nißl's http://home.vr-web.de/~rnissl/vdr-1.3.28-dvbplayer.patch (better)
+
+* If the TV aspect ratio does not automatically adjust according to the
+ video stream, and you have a ADV7170-based DXR3 and a PAL system, see
+ em8300-adv7170-wss.patch and vdr-dxr3-wss.patch in the patches/ dir.
+
+Other TODOs:
+------------
+
+* set bcs
+* clean unneeded log entries
+* stillpicture
+* grab screenshot
+* add much more comments!
+* rewrite some parts of plugin like
+ - demuxer
+ - palettemanger
+ - colormanger
+ - spuencoder
+* osd via
+ - ffmpeg
+ - vga overlay
+
+* optimize (is it worth it?)
+ Rgb2YCrCb
+ YUV2Rgb
diff --git a/dxr3.c b/dxr3.c
new file mode 100644
index 0000000..66bb85f
--- /dev/null
+++ b/dxr3.c
@@ -0,0 +1,241 @@
+/*
+ * dxr3.c: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id: dxr3.c,v 1.9 2005/08/15 17:28:49 austriancoder Exp $
+ *
+ */
+
+#include "dxr3vdrincludes.h"
+#include "dxr3device.h"
+#include "dxr3syncbuffer.h"
+#include "dxr3configdata.h"
+#include "dxr3interface.h"
+#include "dxr3.h"
+#include "dxr3i18n.h"
+
+static const char *VERSION = "0.2.3";
+static const char *DESCRIPTION = "Hardware MPEG decoder";
+static const char *MAINMENUENTRY = "DXR3";
+
+#if VDRVERSNUM && VDRVERSNUM < 10311
+#error "This version of the DXR3 plugin needs VDR version >= 1.3.11"
+#endif
+
+#define DXR3_MAX_CARDS 4
+
+// ==================================
+// 'message-handler' for the main screen
+eOSState cDxr3OsdItem::ProcessKey(eKeys Key)
+{
+ if (Key == kOk)
+ {
+ switch (m_item)
+ {
+ case DXR3_RESET_HARDWARE:
+ cDxr3Interface::Instance().ResetHardware();
+ if (cDxr3Device::InstanceP())
+ cDxr3Device::InstanceP()->Reset();
+ break;
+
+ case DXR3_FORCE_LETTER_BOX:
+ cDxr3ConfigData::Instance().SetForceLetterBox(!cDxr3ConfigData::Instance().GetForceLetterBox());
+ break;
+
+ case DXR3_ANALOG_OUT:
+ cDxr3ConfigData::Instance().SetUseDigitalOut(0);
+ cDxr3ConfigData::Instance().SetAc3OutPut(0);
+ if (cDxr3Device::InstanceP())
+ cDxr3Device::InstanceP()->Reset();
+ break;
+
+ case DXR3_DIGITAL_OUT:
+ cDxr3ConfigData::Instance().SetUseDigitalOut(1);
+ cDxr3ConfigData::Instance().SetAc3OutPut(0);
+ if (cDxr3Device::InstanceP())
+ cDxr3Device::InstanceP()->Reset();
+ break;
+
+ case DXR3_AC3_OUT:
+ cDxr3ConfigData::Instance().SetAc3OutPut(!cDxr3ConfigData::Instance().GetAc3OutPut());
+ if (cDxr3Device::InstanceP())
+ cDxr3Device::InstanceP()->Reset();
+ break;
+ }
+ }
+
+ return Key == kOk ? osBack : cOsdItem::ProcessKey(Key);
+}
+
+// ==================================
+// setup menu
+cMenuSetupDxr3::cMenuSetupDxr3(void)
+{
+ newUseDigitalOut = cDxr3ConfigData::Instance().GetUseDigitalOut();
+ Add(new cMenuEditBoolItem(tr("Digital audio output"), &newUseDigitalOut));
+ newDxr3Card = cDxr3ConfigData::Instance().GetDxr3Card();
+ Add(new cMenuEditIntItem(tr("Card number"),
+ &newDxr3Card, 0, DXR3_MAX_CARDS - 1));
+ newVideoMode = (int) cDxr3ConfigData::Instance().GetVideoMode();
+ menuVideoModes[0] = tr("PAL");
+ menuVideoModes[1] = tr("PAL60");
+ menuVideoModes[2] = tr("NTSC");
+ Add(new cMenuEditStraItem(tr("Video mode"),
+ &newVideoMode, 3, menuVideoModes));
+ newHideMenu = cDxr3ConfigData::Instance().GetHideMenu();
+ Add(new cMenuEditBoolItem(tr("Hide main menu entry"), &newHideMenu));
+ newOsdFlushRate = cDxr3ConfigData::Instance().GetOsdFlushRate();
+ Add(new cMenuEditIntItem(tr("OSD flush rate (ms)"),
+ &newOsdFlushRate, 0, 255));
+}
+
+// ==================================
+// save menu values
+void cMenuSetupDxr3::Store(void)
+{
+ SetupStore("UseDigitalOut",
+ cDxr3ConfigData::Instance().SetUseDigitalOut(newUseDigitalOut));
+ SetupStore("Dxr3Card",
+ cDxr3ConfigData::Instance().SetDxr3Card(newDxr3Card));
+ SetupStore("Dxr3VideoMode",
+ cDxr3ConfigData::Instance().SetVideoMode((eVideoMode) newVideoMode));
+ SetupStore("HideMenu",
+ cDxr3ConfigData::Instance().SetHideMenu(newHideMenu));
+ SetupStore("OsdFlushRate",
+ cDxr3ConfigData::Instance().SetOsdFlushRate(newOsdFlushRate));
+}
+
+// ==================================
+class cPluginDxr3 : public cPlugin
+{
+private:
+ // Add any member variables or functions you may need here.
+public:
+ cPluginDxr3();
+ ~cPluginDxr3();
+ const char *Version()
+ {
+ return VERSION;
+ }
+ const char *Description()
+ {
+ return tr(DESCRIPTION);
+ }
+ const char *CommandLineHelp();
+ bool ProcessArgs(int argc, char *argv[]);
+ bool Initialize();
+ bool Start();
+ void Housekeeping();
+ cMenuSetupPage *SetupMenu();
+ bool SetupParse(const char *Name, const char *Value);
+ const char* MainMenuEntry();
+ cOsdObject* MainMenuAction();
+};
+
+// ==================================
+cPluginDxr3::cPluginDxr3()
+{
+ // Initialize any member varaiables here.
+ // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
+ // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
+ cDxr3ConfigData::Instance();
+}
+
+// ==================================
+cPluginDxr3::~cPluginDxr3()
+{
+}
+
+// ==================================
+const char *cPluginDxr3::CommandLineHelp()
+{
+ return NULL;
+}
+
+// ==================================
+bool cPluginDxr3::ProcessArgs(int argc, char *argv[])
+{
+ return true;
+}
+
+// ==================================
+bool cPluginDxr3::Start()
+{
+ return true;
+}
+
+// ==================================
+bool cPluginDxr3::Initialize()
+{
+ RegisterI18n(Phrases);
+
+ cDxr3Device::InstanceP();
+
+ return true;
+}
+
+// ==================================
+void cPluginDxr3::Housekeeping()
+{
+}
+
+// ==================================
+cMenuSetupPage* cPluginDxr3::SetupMenu()
+{
+ return new cMenuSetupDxr3();
+}
+
+// ==================================
+bool cPluginDxr3::SetupParse(const char *Name, const char *Value)
+{
+ if (!strcasecmp(Name, "UseDigitalOut"))
+ {
+ cDxr3ConfigData::Instance().SetUseDigitalOut(atoi(Value));
+ return true;
+ }
+ if (!strcasecmp(Name, "Dxr3Card"))
+ {
+ cDxr3ConfigData::Instance().SetDxr3Card(atoi(Value));
+ return true;
+ }
+ if (!strcasecmp(Name, "Dxr3VideoMode"))
+ {
+ cDxr3ConfigData::Instance().SetVideoMode((eVideoMode) atoi(Value));
+ return true;
+ }
+ if (!strcasecmp(Name, "HideMenu"))
+ {
+ cDxr3ConfigData::Instance().SetHideMenu(atoi(Value));
+ return true;
+ }
+ if (!strcasecmp(Name, "OsdFlushRate"))
+ {
+ cDxr3ConfigData::Instance().SetOsdFlushRate(atoi(Value));
+ return true;
+ }
+
+ return false;
+}
+
+// ==================================
+const char* cPluginDxr3::MainMenuEntry()
+{
+ return cDxr3ConfigData::Instance().GetHideMenu() ?
+ NULL : tr(MAINMENUENTRY);
+}
+
+// ==================================
+cOsdObject* cPluginDxr3::MainMenuAction()
+{
+ return new cDxr3OsdMenu;
+}
+
+VDRPLUGINCREATOR(cPluginDxr3); // Don't touch this!
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3.h b/dxr3.h
new file mode 100644
index 0000000..c3a1a04
--- /dev/null
+++ b/dxr3.h
@@ -0,0 +1,97 @@
+#ifndef _DXR3_H_
+#define _DXR3_H_
+
+// --- cMenuSetupDxr3 -------------------------------------------------------
+
+// ==================================
+// setup screen
+class cMenuSetupDxr3 : public cMenuSetupPage
+{
+public:
+ cMenuSetupDxr3();
+
+protected:
+ virtual void Store();
+
+private:
+ int newUseDigitalOut;
+ int newDxr3Card;
+ int newVideoMode;
+ const char *menuVideoModes[3];
+ int newHideMenu;
+ int newOsdFlushRate;
+};
+
+
+// ==================================
+enum eDxr3OsdItem
+{
+ DXR3_RESET_HARDWARE,
+ DXR3_FORCE_LETTER_BOX,
+ DXR3_DIGITAL_OUT,
+ DXR3_ANALOG_OUT,
+ DXR3_AC3_OUT
+};
+
+// ==================================
+// osd item
+class cDxr3OsdItem : public cOsdItem
+{
+public:
+ cDxr3OsdItem(const char* text, eDxr3OsdItem item) :
+ cOsdItem(text), m_item(item) {}
+
+ // process fb input
+ eOSState ProcessKey(eKeys Key);
+
+protected:
+ eDxr3OsdItem m_item;
+};
+
+// ==================================
+// main screen
+class cDxr3OsdMenu : public cOsdMenu
+{
+public:
+ cDxr3OsdMenu(): cOsdMenu(tr("DXR3 Adjustment"))
+ {
+ Clear();
+ SetHasHotkeys();
+ Add(new cDxr3OsdItem(hk(tr("Reset DXR3 hardware")),
+ DXR3_RESET_HARDWARE));
+ Add(new cDxr3OsdItem(hk(tr("Toggle force letterbox")),
+ DXR3_FORCE_LETTER_BOX));
+
+ if (cDxr3ConfigData::Instance().GetUseDigitalOut())
+ Add(new cDxr3OsdItem(hk(tr("Switch to analog audio output")),
+ DXR3_ANALOG_OUT));
+ else
+ Add(new cDxr3OsdItem(hk(tr("Switch to digital audio output")),
+ DXR3_DIGITAL_OUT));
+ /*
+ if (cDxr3ConfigData::Instance().GetUseDigitalOut())
+ {
+ Add(new cDxr3OsdItem(hk("Analog output"), DXR3_ANALOG_OUT));
+
+ if (cDxr3ConfigData::Instance().GetAc3OutPut())
+ Add(new cDxr3OsdItem(hk(tr("AC3 output off")), DXR3_AC3_OUT));
+ else if (cDxr3Interface::Instance().IsAc3Present())
+ Add(new cDxr3OsdItem(hk(tr("AC3 output on")), DXR3_AC3_OUT));
+ }
+ else
+ {
+ Add(new cDxr3OsdItem(hk(tr("Switch to digital audio output")),
+ DXR3_DIGITAL_OUT));
+ }
+ */
+ }
+};
+
+#endif /*_DXR3_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3audiodecoder.c b/dxr3audiodecoder.c
new file mode 100644
index 0000000..67238d2
--- /dev/null
+++ b/dxr3audiodecoder.c
@@ -0,0 +1,316 @@
+/*
+ * dxr3audiodecoder.c
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ * Copyright (C) 2004 Christian Gmeiner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+
+/*
+ ToDo:
+ - cDxr3AudioDecoder::Init: Why are we always reinit the codec?
+*/
+
+#include <stdio.h>
+#include "dxr3audiodecoder.h"
+#include "dxr3pesframe.h"
+
+// ==================================
+const int LPCM_HEADER_LENGTH = 7;
+
+// ==================================
+//! constructor
+cDxr3AudioDecoder::cDxr3AudioDecoder() : rbuf(50000), ac3dtsDecoder(&rbuf)
+{
+ decoderOpened = false;
+ audioSynched = false;
+ volume = 255;
+ Codec.id = CODEC_ID_MP2;
+
+ Init();
+
+ lastHeader[0] = 0xFF;
+ lastHeader[1] = lastHeader[2] = lastHeader[3] = 0;
+};
+
+// ==================================
+//! deconst.
+cDxr3AudioDecoder::~cDxr3AudioDecoder()
+{
+ // close codec, if it is open
+ cDxr3Ffmepg::Instance().CloseCodec(Codec);
+};
+
+// ==================================
+//! (re)init ffmpeg codec
+void cDxr3AudioDecoder::Init()
+{
+ // (re)init codec
+ cDxr3Ffmepg::Instance().CloseCodec(Codec);
+ if (cDxr3Ffmepg::Instance().FindCodec(Codec))
+ {
+ cDxr3Ffmepg::Instance().OpenCodec(Codec);
+ rate = channels = -1;
+ frameSize = Codec.codec_context.frame_size;
+ decoderOpened = true;
+ foundHeader = false;
+ decodeAudio = true;
+
+ //lastHeader[0] = 0xFF;
+ //lastHeader[1] = lastHeader[2] = lastHeader[3] = 0;
+ }
+ else
+ {
+ decoderOpened = false;
+ }
+}
+
+// ==================================
+//! decode given buffer
+void cDxr3AudioDecoder::Decode(const uint8_t* buf, int length, uint32_t pts,
+ cDxr3SyncBuffer &aBuf)
+{
+ if (!decoderOpened)
+ {
+ // No decoder is open, so it
+ // is better to stop here.
+ return;
+ }
+
+ int len;
+ int out_size;
+
+ enum audioException
+ {
+ WRONG_LENGTH,
+ UNEXPECTED_PARAMETER_CHANGE
+ };
+
+ int i = 0;
+ for (i = 0; i < length-4 && !foundHeader; i++)
+ {
+ unsigned int tempHead = *((unsigned int*)(buf+i));
+ if (HeadCheck(tempHead))
+ {
+ if ((buf[i+2] & 0xFC) != (lastHeader[2] & 0xFC))
+ {
+ dsyslog("dxr3: audiodecoder: found different audio header"
+ " (new: %#x, old: %#x), (re)initializing",
+ *((uint32_t*) lastHeader), *((uint32_t*) (buf+i)));
+
+ Init();
+ lastHeader[0] = buf[i];
+ lastHeader[1] = buf[i+1];
+ lastHeader[2] = buf[i+2];
+ lastHeader[3] = buf[i+3];
+ }
+ foundHeader = true;
+ }
+ }
+
+ if (audioSynched)
+ {
+ // no header found
+ decodeAudio = true;
+ }
+ else
+ {
+ if (foundHeader && pts)
+ {
+ decodeAudio = true;
+ audioSynched = true;
+ }
+ }
+
+ try
+ {
+ while (length > 0 && decodeAudio)
+ {
+ len = avcodec_decode_audio(&Codec.codec_context,
+ (short *)(&pcmbuf), &out_size,
+ const_cast<uint8_t *>(buf), length);
+ if (len < 0 || out_size < 0)
+ throw WRONG_LENGTH;
+
+ if (Codec.codec_context.sample_rate != rate)
+ {
+ dsyslog("dxr3: audiodecoder: sample rate=%d",
+ Codec.codec_context.sample_rate);
+ if (rate != -1) throw UNEXPECTED_PARAMETER_CHANGE;
+ rate = Codec.codec_context.sample_rate;
+ }
+ if (Codec.codec_context.channels != channels + 1)
+ {
+ dsyslog("dxr3: audiodecoder: channels=%d",
+ Codec.codec_context.channels);
+ if (channels != -1)
+ throw UNEXPECTED_PARAMETER_CHANGE;
+ channels = (Codec.codec_context.channels == 2) ? 1 : 0;
+ }
+ if (out_size)
+ {
+ cFixedLengthFrame* pTempFrame = aBuf.Push(pcmbuf,
+ out_size, pts);
+ pTempFrame->SetChannelCount(channels);
+ pTempFrame->SetDataRate(rate);
+ }
+ length -= len;
+ buf += len;
+ }
+ }
+ catch (audioException ex)
+ {
+ switch (ex)
+ {
+ case WRONG_LENGTH:
+ esyslog("dxr3: audiodecoder: wrong length");
+ break;
+
+ case UNEXPECTED_PARAMETER_CHANGE:
+ esyslog("dxr3: audiodecoder: unexpected parameter change");
+ break;
+
+ default:
+ esyslog("dxr3: audiodecoder: unexpected exception");
+ break;
+ }
+ esyslog("dxr3: audiodecoder: skipping %d broken data bytes", length);
+
+ Init();
+ }
+}
+
+// ==================================
+//! decode lpcm
+void cDxr3AudioDecoder::DecodeLpcm(const uint8_t* buf, int length,
+ uint32_t pts, cDxr3SyncBuffer &aBuf)
+{
+ if (length > (LPCM_HEADER_LENGTH + 2))
+ {
+ uint8_t* pFrame = new uint8_t[length - LPCM_HEADER_LENGTH];
+ // only even number of bytes are allowed
+ assert(!((length - LPCM_HEADER_LENGTH) % 2));
+
+ for (int i = LPCM_HEADER_LENGTH; i < length; i += 2)
+ {
+ pFrame[i - LPCM_HEADER_LENGTH] = buf[i + 1];
+ pFrame[i - LPCM_HEADER_LENGTH + 1] = buf[i];
+ }
+
+ int codedSpeed = (buf[5] >> 4) & 0x03;
+ int speed = 0;
+
+ switch (codedSpeed)
+ {
+ case 1:
+ speed = 96000;
+ break;
+
+ case 2:
+ speed = 44100;
+ break;
+
+ case 3:
+ speed = 32000;
+ break;
+
+ default:
+ speed = 48000;
+ break;
+ }
+
+ cFixedLengthFrame* pTempFrame = aBuf.Push(pFrame,
+ length - LPCM_HEADER_LENGTH,
+ pts);
+ pTempFrame->SetChannelCount(1);
+ pTempFrame->SetDataRate(speed);
+
+ delete[] pFrame;
+ }
+}
+
+// ==================================
+//! decode ac3
+void cDxr3AudioDecoder::DecodeAc3Dts(const uint8_t* pPes, const uint8_t* buf,
+ int length, uint32_t pts,
+ cDxr3SyncBuffer &aBuf)
+{
+ int headerLength = (int) (buf - pPes);
+
+ uint8_t* pBuf = (uint8_t*) pPes;
+ ac3dtsDecoder.Check(pBuf + headerLength, length, pBuf);
+ ac3dtsDecoder.Encapsulate(pBuf + headerLength, length);
+
+ cFrame* pFrame = 0;
+ while ((pFrame = rbuf.Get()))
+ {
+ if (pFrame && pFrame->Count())
+ {
+ cDxr3PesFrame tempPes;
+ tempPes.ExtractNextFrame(pFrame->Data(), pFrame->Count());
+ int pesHeaderLength = (int) (tempPes.GetEsStart() - tempPes.GetPesStart());
+ uint8_t* pData = pFrame->Data() + pesHeaderLength + LPCM_HEADER_LENGTH;
+
+ for (int i = 0; i < pFrame->Count() - pesHeaderLength - LPCM_HEADER_LENGTH; i += 2)
+ {
+ std::swap(pData[i], pData[i + 1]);
+ }
+
+ aBuf.Push(pFrame->Data() + pesHeaderLength + LPCM_HEADER_LENGTH, pFrame->Count() - pesHeaderLength - 7, tempPes.GetPts());
+ if (pFrame) rbuf.Drop(pFrame);
+ }
+ }
+}
+
+// ==================================
+//! checking routine
+bool cDxr3AudioDecoder::HeadCheck(unsigned long head)
+{
+ bool retval = false;
+
+ uint8_t* phead = (uint8_t*) (&head);
+ if (phead[0] != 0xFF)
+ {
+ retval = false;
+ }
+ else if (phead[1] != 0xFC && phead[1] != 0xFE)
+ {
+ retval = false;
+ }
+ else if ((phead[2] & 0xF0) == 0xF0)
+ {
+ retval = false;
+ }
+ else if ((phead[2] & 0xC) == 0xC)
+ {
+ retval = false;
+ }
+ else
+ {
+ retval = true;
+ }
+
+ return retval;
+}
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3audiodecoder.h b/dxr3audiodecoder.h
new file mode 100644
index 0000000..4f86c7d
--- /dev/null
+++ b/dxr3audiodecoder.h
@@ -0,0 +1,97 @@
+/*
+ * dxr3audiodecoder.h
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ * Copyright (C) 2004 Christian Gmeiner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _DXR3_AUDIODECODER_H_
+#define _DXR3_AUDIODECODER_H_
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "dxr3ffmpeg.h"
+#include "dxr3syncbuffer.h"
+#include "dxr3multichannelaudio.h"
+
+// ==================================
+// decode audio to mp2 or use DD :)
+class cDxr3AudioDecoder
+{
+public:
+ cDxr3AudioDecoder();
+ ~cDxr3AudioDecoder();
+
+ void Init(void); // init in const?
+
+ void Decode(const uint8_t* buf, int length, uint32_t pts,
+ cDxr3SyncBuffer &aBuf);
+ void DecodeLpcm(const uint8_t* buf, int length, uint32_t pts,
+ cDxr3SyncBuffer &aBuf);
+ void DecodeAc3Dts(const uint8_t* pPes, const uint8_t* buf, int length,
+ uint32_t pts, cDxr3SyncBuffer &aBuf);
+
+ int GetRate(void) const
+ {
+ return rate;
+ }
+ int GetChannelCount(void) const
+ {
+ return channels;
+ }
+ int GetFrameSize(void) const
+ {
+ return frameSize;
+ }
+ void Reset(void)
+ {
+ ac3dtsDecoder.Clear();
+ rbuf.Clear();
+ }
+
+private:
+ bool HeadCheck(unsigned long head);
+
+ struct Dxr3Codec Codec;
+
+ cRingBufferFrame rbuf;
+ cMultichannelAudio ac3dtsDecoder;
+
+ bool audioSynched;
+ bool decoderOpened;
+ uint8_t lastHeader[4];
+ int rate;
+ int channels;
+ uint32_t frameSize;
+ uint8_t pcmbuf[AVCODEC_MAX_AUDIO_FRAME_SIZE];
+ int volume;
+ bool foundHeader;
+ bool decodeAudio;
+
+ cDxr3AudioDecoder(cDxr3AudioDecoder&); // no copy constructor
+};
+
+#endif /*_DXR3_AUDIODECODER_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3blackframe.c b/dxr3blackframe.c
new file mode 100644
index 0000000..35c79bb
--- /dev/null
+++ b/dxr3blackframe.c
@@ -0,0 +1,1294 @@
+/*
+ * dxr3blackframe.c
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+// ==================================
+//! used when channel gets switched
+char blackframe[] =
+{
+0x0, 0x0, 0x1, 0xb3, 0x2d, 0x2, 0x40, 0x23, 0x24, 0x9f, 0x23, 0x82, 0x10, 0x20, 0x20, 0x26,
+0x20, 0x26, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x34, 0x30, 0x34, 0x36, 0x36, 0x36, 0x34,
+0x34, 0x34, 0x34, 0x36, 0x36, 0x36, 0x3a, 0x3a, 0x3a, 0x44, 0x44, 0x44, 0x3a, 0x3a, 0x3a,
+0x36, 0x36, 0x3a, 0x3a, 0x40, 0x40, 0x44, 0x44, 0x4a, 0x4c, 0x4a, 0x46, 0x46, 0x44, 0x46,
+0x4c, 0x4c, 0x50, 0x50, 0x50, 0x60, 0x60, 0x5c, 0x5c, 0x70, 0x70, 0x74, 0x8a, 0x8a, 0xa7,
+0x10, 0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 0x14, 0x14,
+0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17,
+0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x18, 0x18, 0x18, 0x19, 0x18, 0x18, 0x18, 0x19, 0x1a,
+0x1a, 0x1a, 0x1a, 0x19, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1c, 0x1c, 0x1c, 0x1c, 0x1e, 0x1e,
+0x1e, 0x1f, 0x1f, 0x21, 0x0, 0x0, 0x1, 0xb5, 0x14, 0x82, 0x0, 0x1, 0x0, 0x0, 0x0,
+0x0, 0x1, 0xb8, 0x5a, 0x9, 0xc4, 0x80, 0x0, 0x0, 0x1, 0x0, 0x0, 0x4b, 0x9, 0xb0,
+0x0, 0x0, 0x1, 0xb5, 0x8f, 0xff, 0xf7, 0x98, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0xb, 0x7e,
+0x1f, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c,
+0x30, 0xd4, 0x28, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46,
+0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1,
+0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3,
+0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18,
+0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46,
+0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1,
+0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4,
+0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30,
+0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46,
+0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d,
+0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc,
+0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1,
+0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34,
+0x68, 0xc3, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x2, 0x13, 0x7e, 0x1f, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d,
+0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc,
+0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1,
+0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34,
+0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d,
+0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b,
+0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3,
+0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34,
+0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d,
+0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3,
+0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86,
+0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30,
+0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d,
+0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3,
+0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1,
+0x3, 0x13, 0x7e, 0x1f, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1,
+0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3,
+0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18,
+0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46,
+0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1,
+0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4,
+0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30,
+0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46,
+0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d,
+0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc,
+0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1,
+0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34,
+0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xa8, 0x31, 0xa3, 0x46, 0x8c, 0x30, 0xda,
+0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18,
+0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x4, 0x13, 0x7e, 0x1f, 0x68, 0xd1, 0xa3,
+0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68,
+0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a,
+0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36,
+0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86,
+0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68,
+0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a,
+0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46,
+0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd,
+0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61,
+0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1a, 0x83, 0x1a, 0x34,
+0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d,
+0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b,
+0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3,
+0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34,
+0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d,
+0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xc, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x1, 0x5, 0x13, 0x7e, 0x1f, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d,
+0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b,
+0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3,
+0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34,
+0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d,
+0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3,
+0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x35, 0x6, 0x34, 0x68, 0xd1, 0x86,
+0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68,
+0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a,
+0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46,
+0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd,
+0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61,
+0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a,
+0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46,
+0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1,
+0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3,
+0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xc, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x6, 0x13, 0x7e, 0x1f, 0x68, 0xd1, 0xa3,
+0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68,
+0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a,
+0x34, 0x68, 0xc3, 0xd, 0x41, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30,
+0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46,
+0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d,
+0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc,
+0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1,
+0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34,
+0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d,
+0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b,
+0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3,
+0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34,
+0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d,
+0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x62, 0xb5, 0x4e, 0x81,
+0x2a, 0x5, 0x46, 0x18, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x1, 0x7, 0xb, 0xfe, 0x1f, 0x3, 0x4d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46,
+0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1,
+0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4,
+0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30,
+0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46,
+0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d,
+0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc,
+0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1,
+0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34,
+0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d,
+0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b,
+0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3,
+0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34,
+0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d,
+0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x8, 0xb,
+0x7e, 0x1f, 0x68, 0xd0, 0x94, 0x48, 0xf5, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61,
+0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c,
+0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3,
+0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68,
+0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda,
+0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18,
+0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3,
+0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68,
+0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a,
+0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36,
+0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86,
+0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68,
+0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a,
+0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46,
+0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd,
+0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61,
+0x86, 0xd1, 0xa3, 0x46, 0x21, 0xea, 0x31, 0x6, 0x97, 0x54, 0x85, 0x18, 0x61, 0x80, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x9,
+0xb, 0x7e, 0x1f, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3,
+0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68,
+0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61,
+0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c,
+0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3,
+0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68,
+0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda,
+0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18,
+0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3,
+0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68,
+0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a,
+0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36,
+0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86,
+0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68,
+0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a,
+0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46,
+0x8d, 0x1a, 0x30, 0xc3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xa, 0xb, 0xfe, 0x1f, 0x3, 0x4d, 0x1a,
+0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46,
+0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd,
+0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61,
+0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a,
+0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46,
+0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1,
+0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3,
+0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18,
+0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46,
+0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1,
+0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4,
+0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30,
+0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46,
+0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x60,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xb, 0xb, 0x7e,
+0x1f, 0x68, 0xd0, 0x94, 0x48, 0xf5, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4,
+0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30,
+0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46,
+0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d,
+0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc,
+0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1,
+0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34,
+0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d,
+0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b,
+0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3,
+0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34,
+0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d,
+0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3,
+0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86,
+0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xc, 0xb,
+0x7e, 0x1f, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46,
+0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1,
+0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4,
+0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30,
+0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46,
+0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d,
+0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc,
+0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1,
+0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34,
+0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d,
+0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b,
+0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3,
+0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34,
+0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d,
+0x1a, 0x30, 0xc3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x1, 0xd, 0xb, 0xfe, 0x1f, 0x3, 0x4d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c,
+0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3,
+0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68,
+0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda,
+0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18,
+0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3,
+0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68,
+0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a,
+0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36,
+0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86,
+0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68,
+0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a,
+0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46,
+0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd,
+0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61,
+0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a,
+0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xe, 0xb, 0x7e, 0x1f,
+0x68, 0xd0, 0x94, 0x48, 0xf5, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68,
+0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda,
+0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18,
+0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3,
+0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68,
+0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a,
+0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36,
+0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86,
+0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68,
+0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a,
+0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46,
+0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd,
+0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61,
+0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a,
+0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46,
+0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1,
+0xa3, 0x46, 0x8c, 0x30, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xf, 0xb, 0x7e, 0x1f,
+0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30,
+0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46,
+0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d,
+0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc,
+0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1,
+0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34,
+0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d,
+0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b,
+0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3,
+0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34,
+0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d,
+0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3,
+0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86,
+0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30,
+0xc3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1,
+0x10, 0xb, 0xfe, 0x1f, 0x3, 0x4d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30,
+0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46,
+0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d,
+0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc,
+0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1,
+0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34,
+0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d,
+0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b,
+0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3,
+0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34,
+0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d,
+0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3,
+0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86,
+0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30,
+0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x1, 0x11, 0xb, 0x7e, 0x1f, 0x68, 0xd0, 0x94, 0x48, 0xf5, 0x68, 0xc3,
+0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34,
+0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d,
+0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3,
+0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86,
+0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30,
+0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d,
+0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3,
+0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68,
+0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61,
+0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c,
+0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3,
+0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68,
+0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda,
+0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18,
+0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3,
+0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xc0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x1, 0x12, 0xb, 0x7e, 0x1f, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a,
+0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46,
+0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd,
+0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61,
+0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a,
+0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46,
+0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1,
+0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3,
+0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18,
+0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46,
+0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1,
+0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4,
+0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30,
+0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46,
+0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x13, 0xb,
+0x7e, 0x1f, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46,
+0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1,
+0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4,
+0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30,
+0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46,
+0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d,
+0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc,
+0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1,
+0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34,
+0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d,
+0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b,
+0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3,
+0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34,
+0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d,
+0x1a, 0x30, 0xc3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x1, 0x14, 0xb, 0x7e, 0x1f, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61,
+0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a,
+0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46,
+0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1,
+0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3,
+0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18,
+0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46,
+0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1,
+0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4,
+0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30,
+0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46,
+0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d,
+0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc,
+0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1,
+0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x1, 0x15, 0xb, 0x7e, 0x1f, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d,
+0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b,
+0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3,
+0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34,
+0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d,
+0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3,
+0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86,
+0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30,
+0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d,
+0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3,
+0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68,
+0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61,
+0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c,
+0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3,
+0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68,
+0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda,
+0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x1, 0x16, 0xb, 0x7e, 0x1f, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61,
+0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a,
+0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46,
+0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1,
+0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3,
+0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18,
+0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46,
+0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1,
+0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4,
+0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30,
+0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46,
+0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d,
+0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc,
+0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1,
+0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x17, 0xb, 0x7e, 0x1f, 0x68, 0xd1, 0xa3,
+0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68,
+0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a,
+0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36,
+0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86,
+0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68,
+0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a,
+0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46,
+0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd,
+0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61,
+0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a,
+0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46,
+0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1,
+0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3,
+0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18,
+0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46,
+0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x1, 0x18, 0xb, 0x7e, 0x1f, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34,
+0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d,
+0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3,
+0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86,
+0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30,
+0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d,
+0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3,
+0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68,
+0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61,
+0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c,
+0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3,
+0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68,
+0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda,
+0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18,
+0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3,
+0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68,
+0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x19, 0xb, 0x7e, 0x1f, 0x68, 0xd1, 0xa3, 0xc, 0x36,
+0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86,
+0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68,
+0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a,
+0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46,
+0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd,
+0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61,
+0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a,
+0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46,
+0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1,
+0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3,
+0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18,
+0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46,
+0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1,
+0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4,
+0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30,
+0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x1, 0x1a, 0xb, 0x7e, 0x1f, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34,
+0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d,
+0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3,
+0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86,
+0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30,
+0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d,
+0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3,
+0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68,
+0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61,
+0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c,
+0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3,
+0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68,
+0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda,
+0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18,
+0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3,
+0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68,
+0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1b, 0xb, 0x7e, 0x1f, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d,
+0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc,
+0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1,
+0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34,
+0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d,
+0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b,
+0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3,
+0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34,
+0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d,
+0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3,
+0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86,
+0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30,
+0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d,
+0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3,
+0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1c, 0xb,
+0x7e, 0x1f, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46,
+0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1,
+0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4,
+0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30,
+0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46,
+0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d,
+0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc,
+0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1,
+0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34,
+0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d,
+0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b,
+0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3,
+0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34,
+0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d,
+0x1a, 0x30, 0xc3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x1, 0x1d, 0xb, 0x7e, 0x1f, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a,
+0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46,
+0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd,
+0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61,
+0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a,
+0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46,
+0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1,
+0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3,
+0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18,
+0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46,
+0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1,
+0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4,
+0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30,
+0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46,
+0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x1, 0x1e, 0xb, 0x7e, 0x1f, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86,
+0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30,
+0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d,
+0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3,
+0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68,
+0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61,
+0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c,
+0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3,
+0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68,
+0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda,
+0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18,
+0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3,
+0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68,
+0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a,
+0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36,
+0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86,
+0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x1, 0x1f, 0xb, 0x7e, 0x1f, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a,
+0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46,
+0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd,
+0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61,
+0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a,
+0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46,
+0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1,
+0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3,
+0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18,
+0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46,
+0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1,
+0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4,
+0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30,
+0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46,
+0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20, 0xb, 0xfe, 0x1f, 0x68, 0xd1, 0xa3,
+0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68,
+0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a,
+0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36,
+0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86,
+0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68,
+0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a,
+0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46,
+0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd,
+0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61,
+0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a,
+0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46,
+0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1,
+0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3,
+0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18,
+0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46,
+0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x21, 0xb, 0x7e, 0x1f,
+0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30,
+0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46,
+0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d,
+0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc,
+0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1,
+0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34,
+0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d,
+0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b,
+0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3,
+0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34,
+0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d,
+0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3,
+0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86,
+0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30,
+0xc3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x22, 0xb, 0x7e, 0x1f, 0x68, 0xd1, 0xa3,
+0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68,
+0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a,
+0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36,
+0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86,
+0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68,
+0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a,
+0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46,
+0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd,
+0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61,
+0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a,
+0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46,
+0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1,
+0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3,
+0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18,
+0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46,
+0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x1, 0x23, 0xb, 0x7e, 0x1f, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d,
+0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b,
+0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3,
+0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34,
+0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d,
+0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3,
+0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86,
+0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30,
+0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d,
+0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3,
+0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68,
+0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61,
+0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c,
+0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3,
+0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68,
+0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda,
+0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x24, 0xb, 0x7e, 0x1f, 0x68, 0xd1,
+0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34,
+0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d,
+0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc,
+0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1,
+0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34,
+0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d,
+0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b,
+0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3,
+0xd, 0xa3, 0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34,
+0x61, 0x86, 0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d,
+0x1a, 0x30, 0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3,
+0x46, 0x8d, 0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86,
+0xd1, 0xa3, 0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30,
+0xc3, 0x68, 0xd1, 0xa3, 0x46, 0x18, 0x6d, 0x1a, 0x34, 0x68, 0xc3, 0xd, 0xa3, 0x46, 0x8d,
+0x18, 0x61, 0xb4, 0x68, 0xd1, 0xa3, 0xc, 0x36, 0x8d, 0x1a, 0x34, 0x61, 0x86, 0xd1, 0xa3,
+0x46, 0x8c, 0x30, 0xda, 0x34, 0x68, 0xd1, 0x86, 0x1b, 0x46, 0x8d, 0x1a, 0x30, 0xc3, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0
+};
+
+int blackframeLength = sizeof(blackframe);
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3colormanager.c b/dxr3colormanager.c
new file mode 100644
index 0000000..044d254
--- /dev/null
+++ b/dxr3colormanager.c
@@ -0,0 +1,388 @@
+/***************************************************************************
+ dxr3colormanager.c - description
+ -------------------
+ begin : Tue Oct 22 2002
+ copyright : (C) 2002 by Stefan Schluenss
+ email : vdr@schluenss.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+/**
+ * Background:
+ * Each encoded pixel in the SPU could have one of the values 0,1,2,3. *
+ * These values
+
+ Pixelvalue Maps
+ to index
+ 0 --> 4 -->
+
+
+ * The SPU data definition allows highlighting of rectangular areas. They *
+ * are defined by a starting and ending row. Whithin these rows one could *
+ * define a starting column for using a new color palette mapping. This *
+ * mapping will be used til the end of the line or up to the next column *
+ * defintion.
+ * Look at the picture below:
+ *
+ Row Col=5 Col=16
+ n-2 ...............................
+ n-1 ...............................
+ n .....-------------------------- <- Highligh region starts here
+ .....| 6,3,1,2 | 0,2,8,9
+ .....| 6,3,1,2 | 0,2,8,9
+ .....| 6,3,1,2 | 0,2,8,9
+ n+4 .....-------------------------- <- Highligh region ends here
+ n+5 ...............................
+ n+6 ...............................
+
+ In the above example one region (from n to n+4) is defined with two *
+ highlight sections - one from column 5 up to 15 and the second from 16 *
+ til the end of the line.
+**/
+
+
+#include <assert.h>
+
+#include "dxr3colormanager.h"
+#include <vdr/tools.h>
+#include <stdio.h>
+#include <string.h>
+
+// ==================================
+//! constructor
+cColorManager::cColorManager()
+{
+ NrOfRegions = -1;
+ for(int i = 0; i < MAX_NO_OF_REGIONS; i++)
+ hlr[i] = NULL;
+}
+
+// ==================================
+cColorManager::~cColorManager()
+{
+ for (int i = 0; i < NrOfRegions; i++)
+ {
+ if (hlr[i])
+ {
+ delete(hlr[i]);
+ }
+ }
+}
+
+// ==================================
+// Opens a new highlight region
+void cColorManager::OpenRegion(int y)
+{
+ // Calling method (cColorManager::EncodeColors)
+ // already checks MAX_NO_OF_REGIONS
+ curRegion = new yRegion();
+ curRegion->Y1 = y;
+ NrOfRegions++;
+ hlr[NrOfRegions] = curRegion;
+ NewSection(0); //there's always at least a section
+}
+
+// ==================================
+// Closes the spu-highlight region
+void cColorManager::CloseRegion(int y)
+{
+ curRegion->Y2 = y;
+}
+
+// ==================================
+void cColorManager::EncodeColors(int width, int height, unsigned char* map,
+ unsigned char* dmap)
+{
+ unsigned char color;
+ unsigned char oldcolor = 0xFF;
+ unsigned char ColorIndex;
+ int mapoffset = 0;
+
+ OpenRegion(0);
+ for (int y = 0; y < height; ++y)
+ {
+ oldcolor = 0xFF;
+ FirstSection();
+ for(int x = 0; x < width; ++x)
+ {
+ if (x > curSection->X2)
+ {
+ oldcolor = 0xFF;
+ NextSection();
+ }
+ color = map[mapoffset + x];
+ if (color == oldcolor)
+ dmap[mapoffset + x] = ColorIndex;
+ else
+ {
+ // try to map the color in the current region
+ if (AddColor(x, y, color, ColorIndex))
+ {
+ // store as the highlight region index
+ dmap[mapoffset + x] = ColorIndex;
+ }
+ else
+ {
+ CloseRegion(y - 1);
+ if (NrOfRegions <= MAX_NO_OF_REGIONS - 1)
+ {
+ // retry with another region
+ OpenRegion(y);
+ x = -1;
+ oldcolor = 0xFF;
+ }
+ else
+ {
+ esyslog("dxr3: colormanager: too many regions (%d)"
+ " - giving up", NrOfRegions);
+ return;
+ }
+ }
+ }
+ }
+ mapoffset += width;
+ }
+ // close the last highlight region
+ CloseRegion(height);
+
+//#define colordebug
+#ifdef colordebug
+ {
+ FILE *fp;
+ fp = fopen("OSD.dump","w+");
+ u_char *pippo = dmap;
+ u_char *pippo2 = map;
+ int curregion = 0;
+ int cursection = 0;
+
+
+ for (int dumpy = 0; dumpy < height; dumpy++)
+ {
+ if(curregion < NrOfRegions)
+ {
+ if(hlr[curregion]->Y1 == dumpy)
+ {
+ fprintf(fp, "%i", hlr[curregion]->N);
+ for (int sec = 0; sec < hlr[curregion]->N; sec++)
+ fprintf(fp, ",%i", hlr[curregion]->Section[sec]->X1);
+ for (int dumpx = 0; dumpx < width; dumpx++)
+ fprintf(fp, "=");
+ fprintf(fp, "\n");
+ curregion++;
+ }
+ }
+
+ cursection = 0;
+ for (int dumpx = 0; dumpx < width; dumpx++)
+ {
+ if (curregion < NrOfRegions)
+ {
+ if (cursection < hlr[curregion]->N)
+ {
+ if (hlr[curregion]->Section[cursection]->X1 == dumpx)
+ {
+ fprintf(fp, "|");
+ cursection++;
+ }
+ }
+ }
+ fprintf(fp, "%01X", *pippo2 & 0xF);
+ pippo2++;
+ }
+ fprintf(fp, "\n");
+
+ cursection = 0;
+ for (int dumpx = 0; dumpx < width; dumpx++)
+ {
+ if(curregion < NrOfRegions)
+ {
+ if (cursection < hlr[curregion]->N)
+ {
+ if (hlr[curregion]->Section[cursection]->X1 == dumpx)
+ {
+ fprintf(fp, "|");
+ cursection++;
+ }
+ }
+ }
+ fprintf(fp, "%01X", *pippo & 0xF);
+ pippo++;
+ }
+ fprintf(fp, "\n");
+ }
+ fclose(fp);
+ printf("**** dumped\n");
+ }
+#endif
+}
+
+// ==================================
+unsigned char cColorManager::AddColor(int x, int y, unsigned char color,
+ unsigned char &ColorIndex) {
+
+ if (!curSection->HasColor(color, ColorIndex))
+ {
+ // this color is new for this section
+ if (curSection->AllColorsUsed(curRegion->Y1==y))
+ {
+ // no more free colors
+ if (y != curRegion->Y1)
+ {
+ // terminate region
+ return(0);
+ }
+ NewSection(x);
+ }
+ // and add new color
+ ColorIndex = curSection->AddColor(color);
+ }
+ return(1);
+}
+
+// ==================================
+void cColorManager::FirstSection(void)
+{
+ curSectionIndex = 0;
+ curSection = curRegion->Section[0];
+}
+
+// ==================================
+void cColorManager::NextSection(void)
+{
+ curSectionIndex++;
+ if (curSectionIndex < curRegion->N)
+ curSection=curRegion->Section[curSectionIndex];
+ // it shouldn't happen
+ else esyslog("dxr3: colormanager: ran out of sections");
+}
+
+// ==================================
+// convert into SPU - hope is correct description
+unsigned char* cColorManager::GetSpuData(int& len)
+{
+ if (NrOfRegions >= 0)
+ {
+ int ptr = 0;
+ spudata[ptr++] = 0x07; // CHG_COLCON command
+ spudata[ptr++] = 0x00; // total size of parameter area
+ spudata[ptr++] = 0x00; // will be filled later
+
+
+ for(int i = 0; i <= NrOfRegions;i++)
+ {
+ spudata[ptr++] = (hlr[i]->Y1 >> 8) & 0x0f;
+ spudata[ptr++] = (hlr[i]->Y1 & 0xff);
+ spudata[ptr++] = (((hlr[i]->N) & 0x0f) << 4) | ((hlr[i]->Y2 >> 8) & 0x0f);
+ spudata[ptr++] = (hlr[i]->Y2 & 0xff);
+
+ for(int c = 0; c < hlr[i]->N; c++)
+ {
+ spudata[ptr++] = hlr[i]->Section[c]->X1 >> 8;
+ spudata[ptr++] = hlr[i]->Section[c]->X1 & 0xff;
+ spudata[ptr++] = (hlr[i]->Section[c]->Colors[3] << 4) | (hlr[i]->Section[c]->Colors[2] & 0x0F);
+ spudata[ptr++] = (hlr[i]->Section[c]->Colors[1] << 4) | (hlr[i]->Section[c]->Colors[0] & 0x0F);
+
+ spudata[ptr++] = (hlr[i]->Section[c]->Opac[3] << 4) | hlr[i]->Section[c]->Opac[2];
+ spudata[ptr++] = (hlr[i]->Section[c]->Opac[1] << 4) | hlr[i]->Section[c]->Opac[0];
+ }
+ }
+ spudata[ptr++] = 0x0f; // termination of parameter block
+ spudata[ptr++] = 0xff;
+ spudata[ptr++] = 0xff;
+ spudata[ptr++] = 0xff;
+ int size = ptr - 1;
+ spudata[1] = size >> 8;
+ spudata[2] = size & 0xff;
+
+ len = ptr;
+ }
+ else
+ {
+ len = 0;
+ }
+
+#if OSD_SPU_CM_DUMP
+ FILE *fp;
+ fp = fopen("CM.dump", "a+");
+ fprintf(fp, "len:%03d ", len);
+ for (int i = 0; i < len; i++)
+ fprintf(fp, "%02X", *(spudata + i));
+ fprintf(fp, "\n");
+ fclose(fp);
+#endif
+
+ return(spudata);
+}
+
+// ==================================
+void cColorManager::NewSection(int x)
+{
+ int N = curRegion->N;
+ if (N >= MAX_NO_OF_SECTIONS - 1) {
+ esyslog("dxr3: colormanager: bummer, too many sections (%d),"
+ " reusing last one", N);
+ return; // reuse last section, not optimal but there's no other way out
+ }
+ curSection = new xSection(x);
+ curRegion->Section[N] = curSection;
+ if (N > 0)
+ curRegion->Section[N-1]->X2 = x - 1;
+ (curRegion->N)++;
+ curSectionIndex = N;
+}
+
+// ==================================
+xSection::xSection(int x)
+{
+ X1 = x;
+ X2 = 32767;
+ NrOfColors = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ Opac[i] = 0xFF;
+ Colors[i] = 0;
+ }
+}
+
+// ==================================
+unsigned char xSection::AddColor(unsigned int color)
+{
+ unsigned char ColorIndex = 0;
+
+ if (NrOfColors <= 3)
+ {
+ Colors[NrOfColors] = color;
+ Opac[NrOfColors] = color >> 4;
+ ColorIndex = NrOfColors;
+ NrOfColors++;
+ }
+ return(ColorIndex);
+}
+
+// ==================================
+bool xSection::HasColor(unsigned int color, unsigned char &ColorIndex)
+{
+ for(int i = 0; i < NrOfColors; i++)
+ {
+ if (Colors[i] == color)
+ {
+ ColorIndex = i;
+ return (true);
+ }
+ }
+ return(false);
+}
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3colormanager.h b/dxr3colormanager.h
new file mode 100644
index 0000000..2a2553c
--- /dev/null
+++ b/dxr3colormanager.h
@@ -0,0 +1,126 @@
+/***************************************************************************
+ dxr3colormanager.h - description
+ -------------------
+ begin : Tue Oct 22 2002
+ copyright : (C) 2002 by Stefan Schluenss
+ email : vdr@schluenss.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef _DXR3COLORMANAGER_H_
+#define _DXR3COLORMANAGER_H_
+/*
+// ==================================
+struct rectangular_area
+{
+ rectangular_area() :
+ m_startrow(0), m_endrow(0), m_startcol(0), m_endcol(0) {}
+
+private:
+ size_t m_startrow;
+ size_t m_endrow;
+ size_t m_startcol;
+ size_t m_endcol;
+
+ unsigned int Colors[4];
+ unsigned int Opac[4];
+}
+*/
+
+/**SPU-ColorManager
+ *@author Stefan Schluenss
+ */
+
+#include <stdio.h>
+
+#define OSD_SPU_CM_DUMP 0
+
+#define MAX_NO_OF_SECTIONS 15
+#define MAX_NO_OF_REGIONS 100
+
+
+// ==================================
+class xSection
+{
+public:
+ xSection(int x);
+ bool HasColor(unsigned int color, unsigned char &ColorIndex);
+ unsigned char AddColor(unsigned int color);
+ bool AllColorsUsed(bool FirstLine) {
+ //DIAG("AllColorsUsed: %d\n",NrOfColors);
+ return(NrOfColors >= (FirstLine ? 3 : 4));
+ };
+ int X1;
+ int X2;
+ int NrOfColors;
+ unsigned int Colors[4];
+ unsigned int Opac[4];
+};
+
+// ==================================
+class yRegion
+{
+public:
+ yRegion() : Y1(0), Y2(0), N(0) {}
+
+ /** No descriptions */
+ void AddSection(int first, int last, unsigned int color,
+ unsigned int opac);
+ int Y1;
+ int Y2;
+ int N;
+
+ xSection* Section[MAX_NO_OF_SECTIONS];
+};
+
+// ==================================
+class cColorManager
+{
+public:
+ cColorManager();
+ ~cColorManager();
+
+ void EncodeColors(int width, int height, unsigned char* smap,
+ unsigned char* dmap);
+
+ /** Sets a new color on the OSD */
+ unsigned char AddColor(int x, int y, unsigned char color,
+ unsigned char &ColorIndex);
+
+ /** Encodes the color information as highlight spu data */
+ unsigned char* GetSpuData(int &len);
+
+private:
+ yRegion *hlr[MAX_NO_OF_REGIONS];
+ yRegion *curRegion;
+ int NrOfRegions;
+ unsigned char spudata[(4+6*MAX_NO_OF_SECTIONS)*MAX_NO_OF_REGIONS+7];
+ xSection *curSection;
+ int curSectionIndex;
+
+ /** Opens a new highlight region */
+ void OpenRegion(int y);
+ /** Closes the spu-highlight region */
+ void CloseRegion(int y);
+
+ void NewSection(int x);
+ void FirstSection(void);
+ void NextSection(void);
+};
+
+#endif /*_DXR3COLORMANAGER_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3configdata.c b/dxr3configdata.c
new file mode 100644
index 0000000..5b65ea4
--- /dev/null
+++ b/dxr3configdata.c
@@ -0,0 +1,47 @@
+/*
+ * dxr3configdata.c
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ * Copyright (C) 2004 Christian Gmeiner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "dxr3configdata.h"
+
+// ==================================
+//! constructor
+cDxr3ConfigData::cDxr3ConfigData()
+{
+ m_digitaloutput = 0;
+ m_ac3output = 0;
+ m_card = 0;
+ m_forceletterbox = 0;
+ m_videomode = PAL;
+ m_menumode = SUBPICTURE;
+ m_brightness = 500;
+ m_contrast = 500;
+ m_saturation = 500;
+ m_hidemenu = 0;
+ m_osdflushrate = 40;
+}
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3configdata.h b/dxr3configdata.h
new file mode 100644
index 0000000..07660e5
--- /dev/null
+++ b/dxr3configdata.h
@@ -0,0 +1,172 @@
+/*
+ * dxr3configdata.h
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ * Copyright (C) 2004 Christian Gmeiner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _DXR3_CONFIGDATA_H_
+#define _DXR3_CONFIGDATA_H_
+
+#include "dxr3singleton.h"
+
+// ==================================
+//! possible video modes
+enum eVideoMode
+{
+ PAL = 0, ///< use PAL as videomode
+ PAL60, ///< use PAL60 as videomode
+ NTSC ///< use NTSC as videomode
+};
+
+// ==================================
+// possible menu modes
+enum eMenuMode
+{
+ SUBPICTURE = 0,
+ MPEG
+};
+
+// ==================================
+//! global interface to access all config datas of this plugin
+/*
+ With this singleton you can access very easy all possible
+ config settings of the plugin.
+*/
+class cDxr3ConfigData : public Singleton<cDxr3ConfigData>
+{
+public:
+ cDxr3ConfigData();
+ ~cDxr3ConfigData() {}
+
+ int GetUseDigitalOut() const
+ {
+ return m_digitaloutput;
+ }
+ int SetUseDigitalOut(int value)
+ {
+ return m_digitaloutput = value;
+ }
+ int GetDxr3Card() const
+ {
+ return m_card;
+ }
+ int SetDxr3Card(int value)
+ {
+ return m_card = value;
+ }
+ int GetForceLetterBox() const
+ {
+ return m_forceletterbox;
+ }
+ int SetForceLetterBox(int value)
+ {
+ return m_forceletterbox = value;
+ }
+ int GetAc3OutPut() const
+ {
+ return m_ac3output;
+ }
+ int SetAc3OutPut(int value)
+ {
+ return m_ac3output = value;
+ }
+
+ eVideoMode GetVideoMode() const
+ {
+ return m_videomode;
+ }
+ eVideoMode SetVideoMode(eVideoMode videoMode)
+ {
+ return m_videomode = videoMode;
+ }
+ eMenuMode GetMenuMode() const
+ {
+ return m_menumode;
+ }
+ eMenuMode SetMenuMode(eMenuMode menuMode)
+ {
+ return m_menumode = menuMode;
+ }
+
+ int GetBrightness() const
+ {
+ return m_brightness;
+ }
+ int SetBrightness(int value)
+ {
+ return m_brightness = value;
+ }
+ int GetContrast() const
+ {
+ return m_contrast;
+ }
+ int SetContrast(int value)
+ {
+ return m_contrast = value;
+ }
+ int GetSaturation() const
+ {
+ return m_saturation;
+ }
+ int SetSaturation(int value)
+ {
+ return m_saturation = value;
+ }
+
+ int GetHideMenu() const
+ {
+ return m_hidemenu;
+ }
+ int SetHideMenu(int value)
+ {
+ return m_hidemenu = value;
+ }
+
+ unsigned int GetOsdFlushRate() const
+ {
+ return (unsigned) m_osdflushrate;
+ }
+ int SetOsdFlushRate(int value)
+ {
+ return m_osdflushrate = value;
+ }
+
+protected:
+ eVideoMode m_videomode;
+ eMenuMode m_menumode;
+
+ int m_digitaloutput;
+ int m_ac3output;
+ int m_card;
+ int m_forceletterbox;
+ int m_brightness;
+ int m_contrast;
+ int m_saturation;
+ int m_hidemenu;
+ int m_osdflushrate;
+};
+
+#endif /*_DXR3_CONFIGDATA_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3demuxdevice.c b/dxr3demuxdevice.c
new file mode 100644
index 0000000..762cf9d
--- /dev/null
+++ b/dxr3demuxdevice.c
@@ -0,0 +1,710 @@
+/*
+ * dxr3demuxdevice.c
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include "dxr3demuxdevice.h"
+#include <linux/em8300.h>
+#include "dxr3pesframe.h"
+#include "dxr3configdata.h"
+
+// ==================================
+//! constructor
+cDxr3DemuxDevice::cDxr3DemuxDevice(cDxr3Interface& dxr3Device) :
+ m_dxr3Device(dxr3Device),
+ m_aBuf(AUDIO_MAX_BUFFER_SIZE, AUIDO_MAX_FRAME_SIZE, m_dxr3Device),
+ m_vBuf(VIDEO_MAX_BUFFER_SIZE, VIDEO_MAX_FRAME_SIZE, m_dxr3Device)
+{
+ m_ReUseFrame = 1;
+ m_synchState = DXR3_DEMUX_UNSYNCHED;
+ m_demuxMode = DXR3_DEMUX_OFF_MODE;
+ m_pAudioThread = new cDxr3AudioOutThread(dxr3Device, m_aBuf);
+ if (!m_pAudioThread)
+ {
+ esyslog("dxr3: fatal: unable to allocate memory for audio thread");
+ exit(1);
+ }
+ m_pAudioThread->Start();
+
+ m_pVideoThread = new cDxr3VideoOutThread(dxr3Device, m_vBuf);
+ if (!m_pVideoThread)
+ {
+ esyslog("dxr3: fatal: unable to allocate memory for video thread");
+ exit(1);
+ }
+ m_pVideoThread->Start();
+ m_aDecoder.Init();
+}
+
+// ==================================
+cDxr3DemuxDevice::cDxr3DemuxDevice() : // dummy constructor
+ m_dxr3Device(cDxr3Interface::Instance()),
+ m_aBuf(AUDIO_MAX_BUFFER_SIZE, AUIDO_MAX_FRAME_SIZE, m_dxr3Device),
+ m_vBuf(VIDEO_MAX_BUFFER_SIZE, VIDEO_MAX_FRAME_SIZE, m_dxr3Device)
+{
+ m_synchState = DXR3_DEMUX_UNSYNCHED;
+ m_demuxMode = DXR3_DEMUX_OFF_MODE;
+}
+
+// ==================================
+// deconstr.
+cDxr3DemuxDevice::~cDxr3DemuxDevice()
+{
+ if (m_pVideoThread)
+ {
+ delete m_pVideoThread;
+ }
+
+ if (m_pAudioThread)
+ {
+ delete m_pAudioThread;
+ }
+}
+
+// ==================================
+// stop demuxing process
+void cDxr3DemuxDevice::Stop()
+{
+ m_dxr3Device.DisableVideo();
+ m_dxr3Device.DisableAudio();
+ m_vBuf.Clear();
+ m_aBuf.Clear();
+ m_vBuf.WakeUp();
+ m_aBuf.WakeUp();
+ m_aDecoder.Init();
+ m_vBuf.WaitForReceiverStopped();
+ m_aBuf.WaitForReceiverStopped();
+ m_synchState = DXR3_DEMUX_UNSYNCHED;
+ m_demuxMode = DXR3_DEMUX_OFF_MODE;
+
+ m_dxr3Device.PlayBlackFrame();
+ m_dxr3Device.ReOpenAudio();
+}
+
+// ==================================
+void cDxr3DemuxDevice::Resync()
+{
+ m_dxr3Device.DisableVideo();
+ m_dxr3Device.DisableAudio();
+ m_vBuf.Clear();
+ m_aBuf.Clear();
+ m_vBuf.WakeUp();
+ m_aBuf.WakeUp();
+ m_aDecoder.Init();
+ m_vBuf.WaitForReceiverStopped();
+ m_aBuf.WaitForReceiverStopped();
+ m_synchState = DXR3_DEMUX_UNSYNCHED;
+ m_demuxMode = DXR3_DEMUX_OFF_MODE;
+}
+
+// ==================================
+void cDxr3DemuxDevice::Clear()
+{
+ m_dxr3Device.DisableVideo();
+ m_dxr3Device.DisableAudio();
+ m_vBuf.Clear();
+ m_aBuf.Clear();
+ m_vBuf.WakeUp();
+ m_aBuf.WakeUp();
+ m_aDecoder.Init();
+ m_vBuf.WaitForReceiverStopped();
+ m_aBuf.WaitForReceiverStopped();
+ m_synchState = DXR3_DEMUX_UNSYNCHED;
+ m_demuxMode = DXR3_DEMUX_OFF_MODE;
+}
+
+// ==================================
+void cDxr3DemuxDevice::Init()
+{
+ m_vBuf.Clear();
+ m_aBuf.Clear();
+ m_synchState = DXR3_DEMUX_UNSYNCHED;
+ m_demuxMode = DXR3_DEMUX_OFF_MODE;
+ m_aDecoder.Init();
+}
+
+// ==================================
+void cDxr3DemuxDevice::SetTvMode()
+{
+ m_synchState = DXR3_DEMUX_UNSYNCHED;
+ m_demuxMode = DXR3_DEMUX_TV_MODE;
+ m_aBuf.SetDemuxMode(DXR3_DEMUX_TV_MODE);
+ m_vBuf.SetDemuxMode(DXR3_DEMUX_TV_MODE);
+ m_aBuf.Start();
+ m_vBuf.Start();
+}
+
+// ==================================
+void cDxr3DemuxDevice::SetAudioOnlyMode()
+{
+ m_synchState = DXR3_DEMUX_UNSYNCHED;
+ m_demuxMode = DXR3_DEMUX_AUDIO_ONLY_MODE;
+ m_aBuf.SetDemuxMode(DXR3_DEMUX_REPLAY_MODE);
+ m_vBuf.SetDemuxMode(DXR3_DEMUX_REPLAY_MODE);
+ m_aBuf.Start();
+ m_vBuf.Start();
+}
+
+// ==================================
+void cDxr3DemuxDevice::SetReplayMode()
+{
+ if (m_demuxMode != DXR3_DEMUX_REPLAY_MODE)
+ {
+ if (m_demuxMode == DXR3_DEMUX_TRICK_MODE &&
+ m_trickState == DXR3_FREEZE)
+ {
+ m_dxr3Device.SetPlayMode();
+ m_dxr3Device.SetSysClock(m_stopScr);
+ m_dxr3Device.EnableVideo();
+ m_dxr3Device.EnableAudio();
+ m_vBuf.Start();
+ m_aBuf.Start();
+ m_vBuf.WakeUp();
+ m_aBuf.WakeUp();
+ }
+ else
+ {
+ m_synchState = DXR3_DEMUX_UNSYNCHED;
+ m_aBuf.SetDemuxMode(DXR3_DEMUX_REPLAY_MODE);
+ m_vBuf.SetDemuxMode(DXR3_DEMUX_REPLAY_MODE);
+ }
+ }
+ m_demuxMode = DXR3_DEMUX_REPLAY_MODE;
+}
+
+// ==================================
+void cDxr3DemuxDevice::SetTrickMode(eDxr3TrickState trickState, int Speed)
+{
+ m_demuxMode = DXR3_DEMUX_TRICK_MODE;
+ m_trickState = trickState;
+ m_dxr3Device.DisableAudio();
+
+ if (m_demuxMode == DXR3_DEMUX_TRICK_MODE &&
+ m_trickState == DXR3_FREEZE)
+ {
+ m_stopScr = m_dxr3Device.GetSysClock();
+ // m_dxr3Device.Pause();
+ m_vBuf.Stop();
+ m_aBuf.Stop();
+ }
+ else
+ {
+ m_vBuf.Clear();
+ m_aBuf.Clear();
+ }
+
+ m_ReUseFrame = 1;//Speed;
+}
+
+// ==================================
+void cDxr3DemuxDevice::SetVideoOnlyMode()
+{
+ m_demuxMode = DXR3_DEMUX_VIDEO_ONLY_MODE;
+ m_dxr3Device.DisableAudio();
+
+ if (m_demuxMode == DXR3_DEMUX_TRICK_MODE && m_trickState == DXR3_FREEZE)
+ {
+ m_stopScr = m_dxr3Device.GetSysClock();
+ // m_dxr3Device.Pause();
+ m_vBuf.Stop();
+ m_aBuf.Stop();
+ }
+ else
+ {
+ m_vBuf.Clear();
+ m_aBuf.Clear();
+ }
+ m_dxr3Device.SetPlayMode();
+}
+
+// ==================================
+void cDxr3DemuxDevice::StillPicture(const uint8_t* buf, int length)
+{
+ m_vBuf.Clear();
+ m_aBuf.Clear();
+ m_demuxMode = DXR3_DEMUX_TRICK_MODE;
+ m_trickState = DXR3_FREEZE;
+ m_dxr3Device.SingleStep();
+
+ dsyslog("dxr3: demux: stillpicture length: %d", length);
+
+ DemuxPes(buf, length);
+ DemuxPes(buf, length);
+ DemuxPes(buf, length);
+}
+
+// ==================================
+int cDxr3DemuxDevice::DemuxPes(const uint8_t* buf, int length, bool bAc3Dts)
+{
+ uint32_t pts = 0;
+ static uint32_t aPts = 0;
+ static uint32_t vPts = 0;
+ static uint32_t lastPts = 0;
+ static bool bPlaySuc = false;
+ static bool bPlayedFrame = false;
+ int origLength = length;
+
+ int scr = 0;
+ int pcr = 0;
+
+ scr = m_dxr3Device.GetSysClock();
+
+ //printf("vBuf size = %d\n", m_vBuf.Available());
+ //printf("aBuf size = %d\n", m_aBuf.Available());
+ /*
+ if (cDxr3ConfigData::Instance().GetAc3OutPut())
+ cDxr3AbsDevice::Instance().SetAudioDigitalAC3(); // !!! FIXME
+ */
+
+ if (m_pAudioThread->NeedResync() || m_pVideoThread->NeedResync())
+ {
+ Resync();
+ if (m_demuxMode == DXR3_DEMUX_REPLAY_MODE)
+ {
+ SetReplayMode();
+ }
+ m_aBuf.Clear();
+ m_vBuf.Clear();
+ m_pAudioThread->ClearResyncRequest();
+ m_pVideoThread->ClearResyncRequest();
+ m_aDecoder.Reset();
+ lastPts = 0;
+ aPts = 0;
+ vPts = 0;
+ bPlaySuc = false;
+ }
+
+ if (m_demuxMode == DXR3_DEMUX_OFF_MODE)
+ {
+ m_demuxMode = DXR3_DEMUX_TV_MODE;
+ m_synchState = DXR3_DEMUX_UNSYNCHED;
+
+ lastPts = 0;
+ aPts = 0;
+ vPts = 0;
+ bPlaySuc = false;
+ /*
+ if (cDxr3ConfigData::Instance().GetAc3OutPut())
+ cDxr3AbsDevice::Instance().SetAudioDigitalAC3(); // !!! FIXME
+ */
+ }
+
+ // find start code
+ try
+ {
+ cDxr3PesFrame pesFrame;
+
+ pesFrame.ExtractNextFrame(buf, length);
+
+ while (pesFrame.IsValid())
+ {
+ if (pesFrame.GetEsLength() > (uint32_t) VIDEO_MAX_FRAME_SIZE)
+ {
+ throw (cDxr3PesFrame::PES_GENERAL_ERROR);
+ };
+ if (pesFrame.GetPts() != lastPts)
+ {
+ pts = lastPts = pesFrame.GetPts();
+ }
+ else
+ {
+ pts = 0;
+ }
+
+ if (pesFrame.GetPesDataType() == cDxr3PesFrame::PES_VIDEO_DATA)
+ {
+ /*
+ m_dxr3Device.PlayVideoFrame(pesFrame.GetEsStart(),
+ (int) (pesFrame.GetEsLength()));
+ */
+
+ if (m_demuxMode == DXR3_DEMUX_TRICK_MODE)
+ {
+ switch (pesFrame.GetFrameType())
+ {
+ case I_FRAME:
+ dsyslog("dxr3: demux: I-frame");
+ m_dxr3Device.SingleStep();
+ bPlaySuc = true;
+ //if (bPlayedFrame) return length;
+ bPlayedFrame = true;
+ //usleep(30000); // otherwise there is problem with audio (driver bug?)
+ m_dxr3Device.SetHorizontalSize(pesFrame.GetHorizontalSize());
+ m_dxr3Device.SetVerticalSize(pesFrame.GetVerticalSize());
+ m_dxr3Device.PlayVideoFrame(pesFrame.GetEsStart(), (int) (pesFrame.GetEsLength()), m_ReUseFrame);
+ break;
+
+ case UNKNOWN_FRAME:
+ dsyslog("dxr3: demux: unknown frame");
+ if (bPlaySuc)
+ {
+ m_dxr3Device.PlayVideoFrame(pesFrame.GetEsStart(), (int) (pesFrame.GetEsLength()), m_ReUseFrame);
+ }
+ break;
+
+ default:
+ dsyslog("dxr3: demux: default frame");
+ if (bPlaySuc)
+ {
+ m_dxr3Device.PlayVideoFrame(pesFrame.GetEsStart(), (int) (pesFrame.GetOffset()), m_ReUseFrame);
+ }
+
+ bPlaySuc = false;
+ break;
+ }
+
+ }
+ else if (m_demuxMode == DXR3_DEMUX_VIDEO_ONLY_MODE)
+ {
+ m_dxr3Device.PlayVideoFrame(pesFrame.GetEsStart(),
+ (int)(pesFrame.GetEsLength()));
+ }
+ else if (m_synchState == DXR3_DEMUX_VIDEO_SYNCHED ||
+ m_synchState == DXR3_DEMUX_SYNCHED)
+ {
+ m_dxr3Device.SetHorizontalSize(pesFrame.GetHorizontalSize());
+ m_dxr3Device.SetVerticalSize(pesFrame.GetVerticalSize());
+ while (!Poll(100));
+ cFixedLengthFrame* pTempFrame = m_vBuf.Push(pesFrame.GetEsStart(), (int) (pesFrame.GetEsLength()), pts, ftVideo);
+ if (!pTempFrame) /* Push Timeout */
+ throw (cDxr3PesFrame::PES_GENERAL_ERROR);
+
+ pTempFrame->SetAspectRatio(pesFrame.GetAspectRatio());
+
+ m_aBuf.WakeUp();
+
+ if (m_vBuf.GetFillLevel() > 5 &&
+ m_synchState != DXR3_DEMUX_SYNCHED)
+ {
+ m_synchState = DXR3_DEMUX_SYNCHED;
+ pcr = vPts - PRE_BUFFER_LENGTH;
+ m_dxr3Device.SetSysClock(pcr);
+ m_dxr3Device.SetPlayMode();
+ m_dxr3Device.EnableVideo();
+ m_dxr3Device.EnableAudio();
+ m_vBuf.Start();
+ m_aBuf.Start();
+ }
+ }
+ else
+ {
+ if (pesFrame.GetFrameType() == I_FRAME)
+ {
+ vPts = pts;
+
+ m_dxr3Device.SetHorizontalSize(pesFrame.GetHorizontalSize());
+ m_dxr3Device.SetVerticalSize(pesFrame.GetVerticalSize());
+ cFixedLengthFrame* pTempFrame = m_vBuf.Push(pesFrame.GetEsStart(), (int) (pesFrame.GetEsLength()), pts, ftVideo);
+ if (!pTempFrame) /* Push Timeout */
+ throw (cDxr3PesFrame::PES_GENERAL_ERROR);
+
+ pTempFrame->SetAspectRatio(pesFrame.GetAspectRatio());
+
+ if (m_synchState == DXR3_DEMUX_AUDIO_SYNCHED)
+ {
+ m_synchState = DXR3_DEMUX_SYNCHED;
+ }
+ else
+ {
+ m_synchState = DXR3_DEMUX_VIDEO_SYNCHED;
+ }
+ if (m_synchState == DXR3_DEMUX_SYNCHED)
+ {
+ if (!vPts) vPts = aPts;
+ if (aPts < vPts)
+ {
+ pcr = aPts - PRE_BUFFER_LENGTH;
+ }
+ else
+ {
+ pcr = vPts - PRE_BUFFER_LENGTH;
+ }
+ m_dxr3Device.SetSysClock(pcr);
+ m_dxr3Device.SetPlayMode();
+ m_dxr3Device.EnableVideo();
+ m_dxr3Device.EnableAudio();
+ m_vBuf.Start();
+ m_aBuf.Start();
+ }
+ }
+ }
+
+ }
+ else if (pesFrame.GetPesDataType() == cDxr3PesFrame::PES_AUDIO_DATA
+ && m_demuxMode != DXR3_DEMUX_VIDEO_ONLY_MODE
+ && !cDxr3ConfigData::Instance().GetAc3OutPut())
+ {
+ if (m_synchState == DXR3_DEMUX_AUDIO_SYNCHED ||
+ m_synchState == DXR3_DEMUX_SYNCHED)
+ {
+ if (pts && m_synchState != DXR3_DEMUX_SYNCHED)
+ {
+ m_synchState = DXR3_DEMUX_SYNCHED;
+ pcr = aPts - PRE_BUFFER_LENGTH;
+ m_dxr3Device.SetSysClock(pcr);
+ m_dxr3Device.SetPlayMode();
+ m_dxr3Device.EnableVideo();
+ m_dxr3Device.EnableAudio();
+ m_vBuf.Start();
+ m_aBuf.Start();
+ }
+ while(!Poll(100));
+ m_aDecoder.Decode(pesFrame.GetEsStart(),
+ (int) (pesFrame.GetEsLength()),
+ pts, m_aBuf);
+
+ }
+ else
+ {
+ if (pts)
+ {
+ aPts = pts;
+
+ m_aDecoder.Decode(pesFrame.GetEsStart(),
+ (int) (pesFrame.GetEsLength()),
+ pts, m_aBuf);
+
+ if (m_synchState == DXR3_DEMUX_VIDEO_SYNCHED)
+ {
+ m_synchState = DXR3_DEMUX_SYNCHED;
+ }
+ else
+ {
+ m_synchState = DXR3_DEMUX_AUDIO_SYNCHED;
+ }
+ if (m_synchState == DXR3_DEMUX_SYNCHED)
+ {
+ if (!vPts) vPts = aPts;
+ if (aPts < vPts)
+ {
+ pcr = aPts - PRE_BUFFER_LENGTH;
+ }
+ else
+ {
+ pcr = vPts - PRE_BUFFER_LENGTH;
+ }
+ m_dxr3Device.SetSysClock(pcr);
+ m_dxr3Device.SetPlayMode();
+ m_dxr3Device.EnableVideo();
+ m_dxr3Device.EnableAudio();
+ m_vBuf.Start();
+ m_aBuf.Start();
+ }
+ }
+ }
+ }
+ else if (pesFrame.GetPesDataType() == cDxr3PesFrame::PES_PRIVATE_DATA
+ && m_demuxMode != DXR3_DEMUX_VIDEO_ONLY_MODE
+ && !cDxr3ConfigData::Instance().GetAc3OutPut()
+ && !bAc3Dts)
+ {
+ if (m_synchState == DXR3_DEMUX_AUDIO_SYNCHED ||
+ m_synchState == DXR3_DEMUX_SYNCHED)
+ {
+ m_aDecoder.DecodeLpcm(pesFrame.GetEsStart(),
+ pesFrame.GetEsLength(), pts, m_aBuf);
+ }
+ else
+ {
+ if (pts)
+ {
+ aPts = pts;
+ m_aDecoder.DecodeLpcm(pesFrame.GetEsStart(),
+ pesFrame.GetEsLength(),
+ pts, m_aBuf);
+
+ if (m_synchState == DXR3_DEMUX_VIDEO_SYNCHED)
+ {
+ m_synchState = DXR3_DEMUX_SYNCHED;
+ }
+ else
+ {
+ m_synchState = DXR3_DEMUX_AUDIO_SYNCHED;
+ }
+ if (m_synchState == DXR3_DEMUX_SYNCHED)
+ {
+ if (!vPts) vPts = aPts;
+ if (aPts < vPts)
+ {
+ pcr = aPts - PRE_BUFFER_LENGTH;
+ }
+ else
+ {
+ pcr = vPts - PRE_BUFFER_LENGTH;
+ }
+ m_dxr3Device.SetSysClock(pcr);
+ m_dxr3Device.SetPlayMode();
+ m_dxr3Device.EnableVideo();
+ m_dxr3Device.EnableAudio();
+ m_vBuf.Start();
+ m_aBuf.Start();
+ }
+ }
+ }
+ }
+ else if (pesFrame.GetPesDataType() == cDxr3PesFrame::PES_PRIVATE_DATA
+ && m_demuxMode != DXR3_DEMUX_VIDEO_ONLY_MODE
+ && cDxr3ConfigData::Instance().GetAc3OutPut()
+ && bAc3Dts)
+ {
+ if (m_synchState == DXR3_DEMUX_AUDIO_SYNCHED ||
+ m_synchState == DXR3_DEMUX_SYNCHED)
+ {
+ m_aDecoder.DecodeAc3Dts(pesFrame.GetPesStart(),
+ pesFrame.GetEsStart(),
+ pesFrame.GetEsLength(),
+ pts, m_aBuf);
+ }
+ else
+ {
+ if (pts)
+ {
+ aPts = pts;
+ m_aDecoder.DecodeAc3Dts(pesFrame.GetPesStart(),
+ pesFrame.GetEsStart(),
+ pesFrame.GetEsLength(),
+ pts, m_aBuf);
+
+ if (m_synchState == DXR3_DEMUX_VIDEO_SYNCHED)
+ {
+ m_synchState = DXR3_DEMUX_SYNCHED;
+ }
+ else
+ {
+ m_synchState = DXR3_DEMUX_AUDIO_SYNCHED;
+ }
+ if (m_synchState == DXR3_DEMUX_SYNCHED)
+ {
+ if (!vPts) vPts = aPts;
+ if (aPts < vPts)
+ {
+ pcr = aPts - PRE_BUFFER_LENGTH;
+ }
+ else
+ {
+ pcr = vPts - PRE_BUFFER_LENGTH;
+ }
+ m_dxr3Device.SetSysClock(pcr);
+ m_dxr3Device.SetPlayMode();
+ m_dxr3Device.EnableVideo();
+ m_dxr3Device.EnableAudio();
+ m_vBuf.Start();
+ m_aBuf.Start();
+ }
+ }
+ }
+
+ }
+
+ if (pesFrame.IsValid())
+ {
+ pesFrame.ExtractNextFrame(pesFrame.GetNextStart(),
+ pesFrame.GetRemainingLength());
+ }
+
+ }
+
+ length -= pesFrame.GetRemainingLength();
+
+ //if (m_demuxMode == DXR3_DEMUX_TRICK_MODE) return origLength;
+ return length;
+ }
+ catch (cDxr3PesFrame::ePesFrameError err)
+ {
+ dsyslog("cDxr3DemuxDevice::DemuxPes() ePesFrameError skipping data and resync");
+ Resync();
+ return origLength;
+ }
+ catch (cDxr3SyncBuffer::eSyncBufferException err)
+ {
+ Stop();
+ return origLength;
+ }
+}
+
+// ==================================
+int cDxr3DemuxDevice::DemuxAudioPes(const uint8_t* buf, int length)
+{
+ static int syncCounter = 0;
+ int origLength = length;
+
+ m_demuxMode = DXR3_DEMUX_AUDIO_ONLY_MODE;
+ m_aBuf.SetDemuxMode(DXR3_DEMUX_REPLAY_MODE);
+ m_vBuf.SetDemuxMode(DXR3_DEMUX_REPLAY_MODE);
+
+ try
+ {
+ cDxr3PesFrame pesFrame;
+
+ pesFrame.ExtractNextFrame(buf, length);
+
+ while (pesFrame.IsValid())
+ {
+ if (pesFrame.GetPesDataType() == cDxr3PesFrame::PES_PRIVATE_DATA)
+ {
+ if (m_synchState != DXR3_DEMUX_AUDIO_SYNCHED &&
+ syncCounter > 2)
+ {
+ m_synchState = DXR3_DEMUX_AUDIO_SYNCHED;
+ m_dxr3Device.SetPlayMode();
+ m_dxr3Device.EnableVideo();
+ m_dxr3Device.EnableAudio();
+ m_vBuf.Start();
+ m_aBuf.Start();
+ }
+ if (m_synchState != DXR3_DEMUX_AUDIO_SYNCHED &&
+ syncCounter <= 2)
+ {
+ syncCounter++;
+ }
+ while (!m_aBuf.Poll(100));
+ m_aDecoder.DecodeLpcm(pesFrame.GetEsStart(),
+ pesFrame.GetEsLength(), 0, m_aBuf);
+
+ }
+
+ if (pesFrame.IsValid())
+ {
+ pesFrame.ExtractNextFrame(pesFrame.GetNextStart(),
+ pesFrame.GetRemainingLength());
+ }
+ }
+
+ length -= pesFrame.GetRemainingLength();
+
+ return length;
+ }
+ catch (cDxr3PesFrame::ePesFrameError err)
+ {
+ dsyslog("cDxr3DemuxDevice::DemuxAudioPes() ePesFrameError skipping data and resync");
+ Stop();
+ return origLength;
+ }
+}
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3demuxdevice.h b/dxr3demuxdevice.h
new file mode 100644
index 0000000..1d8441c
--- /dev/null
+++ b/dxr3demuxdevice.h
@@ -0,0 +1,103 @@
+/*
+ * dxr3demuxdevice.h
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __DXR3_DEMUX_DEVICE_H
+#define __DXR3_DEMUX_DEVICE_H
+
+#include "dxr3vdrincludes.h"
+#include "dxr3generaldefines.h"
+#include "dxr3syncbuffer.h"
+#include "dxr3audiodecoder.h"
+#include "dxr3outputthread.h"
+
+const int AUDIO_MAX_BUFFER_SIZE = 200;
+const int VIDEO_MAX_BUFFER_SIZE = 500;
+
+const int AUIDO_MAX_FRAME_SIZE = 5000;
+const int VIDEO_MAX_FRAME_SIZE = 3000;
+const uint32_t PRE_BUFFER_LENGTH = 0;
+
+// ==================================
+// extract video and audio
+class cDxr3DemuxDevice
+{
+public:
+ cDxr3DemuxDevice();
+ cDxr3DemuxDevice(cDxr3Interface& dxr3Device);
+ ~cDxr3DemuxDevice();
+
+public:
+ void Stop(void);
+ void Resync(void);
+ void Clear(void);
+ void Init(void);
+ void SetTvMode(void);
+ void SetAudioOnlyMode(void);
+ void SetVideoOnlyMode(void);
+ void SetReplayMode(void);
+ void SetTrickMode(eDxr3TrickState trickState, int Speed = 1);
+
+ int DemuxPes(const uint8_t* buf, int length, bool bAc3Dts = false);
+ int DemuxAudioPes(const uint8_t* buf, int length);
+ void StillPicture(const uint8_t* buf, int length);
+
+ eDxr3DemuxMode GetDemuxMode(void)
+ {
+ return m_demuxMode;
+ };
+ eDxr3TrickState GetTrickState(void)
+ {
+ return m_trickState;
+ };
+ bool Poll(int TimeoutMs)
+ {
+ return m_aBuf.Poll(TimeoutMs) && m_vBuf.Poll(TimeoutMs);
+ /*
+ return m_demuxMode == DXR3_DEMUX_AUDIO_ONLY_MODE ?
+ m_aBuf.Poll(TimeoutMs) : m_aBuf.Poll(TimeoutMs);
+ */
+ };
+
+protected:
+ cDxr3Interface& m_dxr3Device;
+ cDxr3SyncBuffer m_aBuf;
+ cDxr3SyncBuffer m_vBuf;
+ eDxr3DemuxSynchState m_synchState;
+ eDxr3DemuxMode m_demuxMode;
+ eDxr3TrickState m_trickState;
+ cDxr3AudioDecoder m_aDecoder;
+ cDxr3AudioOutThread* m_pAudioThread;
+ cDxr3VideoOutThread* m_pVideoThread;
+ uint32_t m_stopScr;
+ int m_ReUseFrame; // how often a frame should be used
+
+private:
+ cDxr3DemuxDevice(cDxr3DemuxDevice&); // no copy constructor
+};
+
+#endif // __DXR3_DEMUX_DEVICE_H
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3device.c b/dxr3device.c
new file mode 100644
index 0000000..39467ed
--- /dev/null
+++ b/dxr3device.c
@@ -0,0 +1,467 @@
+/*
+ * dxr3device.c
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ * Copyright (C) 2004 Christian Gmeiner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "dxr3device.h"
+#include "dxr3configdata.h"
+#include "dxr3interface.h"
+#include "dxr3tools.h"
+#include "dxr3osd.h"
+
+extern "C"
+{
+#include <jpeglib.h>
+}
+
+// ==================================
+//! constructor
+cDxr3Device::cDxr3Device() : m_DemuxDevice(cDxr3Interface::Instance())
+{
+ m_Offset = 0;
+ m_strBuf.erase(m_strBuf.begin(), m_strBuf.end());
+ m_spuDecoder = NULL;
+ m_AC3Present = false;
+ m_CalledBySet = false;
+}
+
+// ==================================
+cDxr3Device::~cDxr3Device()
+{
+ if (m_spuDecoder)
+ {
+ delete m_spuDecoder;
+ }
+}
+
+// ==================================
+void cDxr3Device::MakePrimaryDevice(bool On)
+{
+ new cDxr3OsdProvider();
+}
+
+// replaying
+// ==================================
+//! does we have an mpeg2 devocer?
+bool cDxr3Device::HasDecoder() const
+{
+ // sure we have one ;)
+ return true;
+}
+
+// ==================================
+//! can we replay vdr recordings?
+bool cDxr3Device::CanReplay() const
+{
+ // also sure...
+ return true;
+}
+
+// ==================================
+bool cDxr3Device::SetPlayMode(ePlayMode PlayMode)
+{
+ if (PlayMode == pmExtern_THIS_SHOULD_BE_AVOIDED)
+ {
+ Tools::WriteInfoToOsd(tr("DXR3: releasing devices"));
+ cDxr3Interface::Instance().ExternalReleaseDevices();
+ }
+ else
+ {
+ cDxr3Interface::Instance().ExternalReopenDevices();
+ }
+
+ // should this relay be here?
+ m_Offset = 0;
+ m_AC3Present = false;
+ m_strBuf.erase(m_strBuf.begin(), m_strBuf.end());
+
+ if (PlayMode == pmAudioOnlyBlack)
+ {
+ m_PlayMode = pmAudioOnly;
+ }
+ else
+ {
+ m_PlayMode = PlayMode;
+ }
+
+ if (m_PlayMode == pmAudioVideo)
+ {
+ m_DemuxDevice.SetReplayMode();
+ }
+
+ if (m_PlayMode == pmNone)
+ {
+ m_DemuxDevice.Stop();
+ }
+
+ if (cDxr3ConfigData::Instance().GetUseDigitalOut())
+ {
+ if (cDxr3ConfigData::Instance().GetAc3OutPut() && m_CalledBySet)
+ {
+ isyslog("dxr3: Setting AC3 audio mode");
+ cDxr3Interface::Instance().SetAudioDigitalAC3(); // !!! FIXME
+ }
+ else
+ {
+ isyslog("dxr3: Setting digital PCM audio mode");
+ cDxr3Interface::Instance().SetAudioDigitalPCM();
+ cDxr3ConfigData::Instance().SetAc3OutPut(0);
+ }
+ }
+ else
+ {
+ isyslog("dxr3: Setting analog audio mode");
+ cDxr3Interface::Instance().SetAudioAnalog();
+ }
+
+ return true;
+}
+
+// ==================================
+int64_t cDxr3Device::GetSTC()
+{
+ return cDxr3Interface::Instance().GetPts();
+}
+
+// ==================================
+void cDxr3Device::TrickSpeed(int Speed)
+{
+ dsyslog("dxr3: device: tricspeed: %d", Speed);
+
+ m_DemuxDevice.SetTrickMode(DXR3_FAST, Speed);
+
+ /*
+ 6 ... 1x vowärts
+ 3 ... 2x vowärts
+ 1 ... 2x vowärts
+
+ 6 ... 1x rückwärts
+ 3 ... 2x rückwärts
+ 1 ... 3x rückwärts
+
+ 8 ... 1x vorwörts, wenn Pause gedrückt
+ */
+
+ /*
+#define EM8300_PLAYMODE_PAUSED 1
+#define EM8300_PLAYMODE_SLOWFORWARDS 2
+#define EM8300_PLAYMODE_SLOWBACKWARDS 3
+#define EM8300_PLAYMODE_SINGLESTEP 4
+ */
+ /*
+ if (Speed == 8)
+ {
+ cDxr3Interface::Instance().SingleStep();
+ }
+ else
+ {
+ m_DemuxDevice.SetTrickMode(DXR3_FAST);
+ }
+ */
+}
+
+// ==================================
+//! clear our demux buffer
+void cDxr3Device::Clear()
+{
+ m_DemuxDevice.Clear();
+ m_Offset = 0;
+ m_strBuf.erase(m_strBuf.begin(), m_strBuf.end());
+}
+
+// ==================================
+//! play a recording
+void cDxr3Device::Play()
+{
+ m_DemuxDevice.SetReplayMode();
+ m_Offset = 0;
+ ///< free buffer
+ m_strBuf.erase(m_strBuf.begin(), m_strBuf.end());
+}
+
+// ==================================
+//! puts the device into "freeze frame" mode
+void cDxr3Device::Freeze()
+{
+ m_DemuxDevice.SetTrickMode(DXR3_FREEZE);
+}
+
+// ==================================
+void cDxr3Device::Mute()
+{
+ m_DemuxDevice.SetTrickMode(DXR3_FAST);
+}
+
+// ==================================
+//! displays the given I-frame as a still picture.
+void cDxr3Device::StillPicture(const uchar *Data, int Length)
+{
+ m_DemuxDevice.StillPicture(Data, Length);
+}
+
+// ==================================
+bool cDxr3Device::Poll(cPoller &Poller, int TimeoutMs)
+{
+ if ((m_DemuxDevice.GetDemuxMode() == DXR3_DEMUX_TRICK_MODE &&
+ m_DemuxDevice.GetTrickState() == DXR3_FREEZE) ||
+ cDxr3Interface::Instance().IsExternalReleased())
+ {
+#if VDRVERSNUM >= 10314
+ cCondWait::SleepMs(TimeoutMs);
+#else
+ usleep(TimeoutMs * 1000);
+#endif
+ return false;
+ }
+ return m_DemuxDevice.Poll(TimeoutMs); // Poller.Poll(TimeoutMs);
+}
+
+// ==================================
+//! actually plays the given data block as video
+int cDxr3Device::PlayVideo(const uchar *Data, int Length)
+{
+ int retLength = 0;
+ int origLength = Length;
+
+ if ((m_DemuxDevice.GetDemuxMode() == DXR3_DEMUX_TRICK_MODE &&
+ m_DemuxDevice.GetTrickState() == DXR3_FREEZE) ||
+ cDxr3Interface::Instance().IsExternalReleased())
+ {
+ // Why is here so a huge time waster?
+ //usleep(1000000);
+ return -1;
+ }
+
+ if (m_strBuf.length())
+ {
+ m_strBuf.append((const char*)Data, Length);
+
+ if (m_PlayMode == pmAudioOnly)
+ {
+ retLength = m_DemuxDevice.DemuxAudioPes((const uint8_t*)m_strBuf.data(), m_strBuf.length());
+ }
+ else
+ {
+ retLength = m_DemuxDevice.DemuxPes((const uint8_t*)m_strBuf.data(), m_strBuf.length());
+ }
+ }
+ else
+ {
+ if (m_PlayMode == pmAudioOnly)
+ {
+ retLength = m_DemuxDevice.DemuxAudioPes((const uint8_t*)Data, Length);
+ }
+ else
+ {
+ retLength = m_DemuxDevice.DemuxPes((const uint8_t*)Data, Length);
+ }
+ }
+
+ Length -= retLength;
+
+ if (m_strBuf.length())
+ {
+ m_strBuf.erase(m_strBuf.length() - retLength, retLength);
+ }
+ else
+ {
+ if (Length)
+ {
+ m_strBuf.append((const char*)(Data + retLength), Length);
+ }
+ }
+
+ return origLength;
+}
+
+// ==================================
+// plays additional audio streams, like Dolby Digital
+#if VDRVERSNUM >= 10318
+int cDxr3Device::PlayAudio(const uchar *Data, int Length)
+#else
+void cDxr3Device::PlayAudio(const uchar *Data, int Length)
+#endif
+{
+ int retLength = 0;
+#if VDRVERSNUM >= 10318
+ int origLength = Length;
+#endif
+
+ m_AC3Present = true;
+
+ if ((m_DemuxDevice.GetDemuxMode() == DXR3_DEMUX_TRICK_MODE &&
+ m_DemuxDevice.GetTrickState() == DXR3_FREEZE) ||
+ cDxr3Interface::Instance().IsExternalReleased())
+ {
+ //usleep(1000000);
+#if VDRVERSNUM >= 10318
+ return 0;
+#else
+ return;
+#endif
+ }
+
+ if (m_strBuf.length())
+ {
+ m_strBuf.append((const char*)Data, Length);
+ if (m_PlayMode == pmAudioOnly)
+ {
+ retLength = m_DemuxDevice.DemuxAudioPes((const uint8_t*)m_strBuf.data(), m_strBuf.length());
+ } else {
+ retLength = m_DemuxDevice.DemuxPes((const uint8_t*)m_strBuf.data(), m_strBuf.length(), true);
+ }
+ }
+ else
+ {
+ if (m_PlayMode == pmAudioOnly)
+ {
+ retLength = m_DemuxDevice.DemuxAudioPes((const uint8_t*) Data, Length);
+ } else {
+ retLength = m_DemuxDevice.DemuxPes((const uint8_t*)Data, Length, true);
+ }
+ }
+
+ Length -= retLength;
+
+ if (m_strBuf.length())
+ {
+ m_strBuf.erase(m_strBuf.length() - retLength, retLength);
+ }
+ else
+ {
+ if (Length)
+ {
+ m_strBuf.append((const char*)(Data + retLength), Length);
+ }
+ }
+
+#if VDRVERSNUM >= 10318
+ return origLength;
+#endif
+}
+
+// addition functions
+// ==================================
+//! capture a single frame as an image
+bool cDxr3Device::GrabImage(const char *FileName, bool Jpeg, int Quality,
+ int SizeX, int SizeY)
+{
+ int w = SizeX;
+ int h = SizeY;
+ unsigned char *Data = new unsigned char[w * h * 3];
+ memset(Data, 0, w * h * 3);
+
+ // we could get a I-Frame and save it
+ //m_DemuxDevice.StillPicture(Data, 100 * 1024);
+
+ isyslog("grabbing to %s (%s %d %d %d)",
+ FileName, Jpeg ? "JPEG" : "PNM", Quality, w, h);
+ FILE *f = fopen(FileName, "wb");
+ if (f)
+ {
+ if (Jpeg)
+ {
+ ///< write JPEG file:
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+ jpeg_stdio_dest(&cinfo, f);
+ cinfo.image_width = w;
+ cinfo.image_height = h;
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_RGB;
+
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, Quality, true);
+ jpeg_start_compress(&cinfo, true);
+
+ int rs = w * 3;
+ JSAMPROW rp[h];
+ for (int k = 0; k < h; k++)
+ {
+ rp[k] = &Data[rs * k];
+ }
+ jpeg_write_scanlines(&cinfo, rp, h);
+ jpeg_finish_compress(&cinfo);
+ jpeg_destroy_compress(&cinfo);
+
+ }
+ else
+ {
+ ///< write PNM file:
+ if (fprintf(f, "P6\n%d\n%d\n255\n", w, h) < 0 ||
+ fwrite(Data, w * h * 3, 1, f) != 1)
+ {
+ LOG_ERROR_STR(FileName);
+ }
+ }
+ fclose(f);
+ }
+ else
+ {
+ return false;
+ }
+
+ delete Data;
+ return true;
+}
+
+// ==================================
+void cDxr3Device::SetVideoFormat(bool VideoFormat16_9)
+{
+ // Do we need this function?
+}
+
+// ==================================
+//! sets volume for audio output
+void cDxr3Device::SetVolumeDevice(int Volume)
+{
+ cDxr3Interface::Instance().SetVolume(Volume);
+}
+
+// ==================================
+//! sets audio channel for audio output (stero, mono left, mono right)
+void cDxr3Device::SetAudioChannelDevice(int AudioChannel)
+{
+ cDxr3Interface::Instance().SetAudioChannel(AudioChannel);
+}
+int cDxr3Device::GetAudioChannelDevice(void)
+{
+ return cDxr3Interface::Instance().GetAudioChannel();
+}
+
+// ==================================
+// get spudecoder
+cSpuDecoder *cDxr3Device::GetSpuDecoder(void)
+{
+ if (!m_spuDecoder && IsPrimaryDevice())
+ {
+ m_spuDecoder = new cDxr3SpuDecoder();
+ }
+ return m_spuDecoder;
+}
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3device.h b/dxr3device.h
new file mode 100644
index 0000000..ca11ba6
--- /dev/null
+++ b/dxr3device.h
@@ -0,0 +1,105 @@
+/*
+ * dxr3device.h
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ * Copyright (C) 2004 Christian Gmeiner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _DXR3_DEVICE_H_
+#define _DXR3_DEVICE_H_
+
+#include "dxr3interface.h"
+#include "dxr3demuxdevice.h"
+#include "dxr3spudecoder.h"
+#include <string>
+
+// ==================================
+// our device :)
+/*!
+ cDxr3Device is the interface for VDR devices.
+ Is is the part, which VDR "talks" with our plugin.
+*/
+class cDxr3Device : public cDevice, public Singleton<cDxr3Device>
+{
+public:
+ cDxr3Device();
+ cDxr3Device(cDxr3Interface& demuxDevice);
+ ~cDxr3Device();
+
+ virtual void MakePrimaryDevice(bool On);
+
+ // replaying
+ virtual bool HasDecoder() const;
+ virtual bool CanReplay() const;
+ virtual bool SetPlayMode(ePlayMode PlayMode);
+ virtual int64_t GetSTC();
+ virtual void TrickSpeed(int Speed);
+ virtual void Clear();
+ virtual void Play();
+ virtual void Freeze();
+ virtual void Mute();
+ virtual void StillPicture(const uchar *Data, int Length);
+ virtual bool Poll(cPoller &Poller, int TimeoutMs = 0);
+ virtual int PlayVideo(const uchar *Data, int Length);
+#if VDRVERSNUM >= 10318
+ virtual int PlayAudio(const uchar *Data, int Length);
+#else
+ virtual void PlayAudio(const uchar *Data, int Length);
+#endif
+
+ // addition functions
+ virtual bool GrabImage(const char *FileName, bool Jpeg = true,
+ int Quality = -1, int SizeX = -1, int SizeY = -1);
+ virtual void SetVideoFormat(bool VideoFormat16_9);
+ virtual void SetVolumeDevice(int Volume);
+ virtual void SetAudioChannelDevice(int AudioChannel);
+ virtual int GetAudioChannelDevice(void);
+
+ // osd
+ virtual cSpuDecoder *GetSpuDecoder();
+
+ // helper function
+ void Reset()
+ {
+ m_CalledBySet = true;
+ SetPlayMode(m_PlayMode);
+ m_CalledBySet = false;
+ }
+
+protected:
+ ePlayMode m_PlayMode;
+ cDxr3DemuxDevice m_DemuxDevice;
+ bool m_AC3Present;
+ bool m_CalledBySet;
+ std::string m_strBuf;
+ int m_Offset;
+
+ //virtual bool SetPlayMode(ePlayMode PlayMode);
+ //uint8_t m_pBuffer[MAX_VIDEO_BUFFER_SIZE];
+ //cDxr3StartStopThread* m_pStartStopThread;
+ cDxr3SpuDecoder* m_spuDecoder;
+};
+
+#endif /*_DXR3_DEVICE_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3ffmpeg.c b/dxr3ffmpeg.c
new file mode 100644
index 0000000..fcb6e2d
--- /dev/null
+++ b/dxr3ffmpeg.c
@@ -0,0 +1,91 @@
+/*
+ * dxr3ffmpeg.c
+ *
+ * Copyright (C) 2004 Christian Gmeiner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "dxr3ffmpeg.h"
+#include "dxr3configdata.h"
+#include <vdr/tools.h>
+
+// ==================================
+//! constructor
+cDxr3Ffmepg::cDxr3Ffmepg()
+{
+ avcodec_init();
+ // Register only codec(s) we'll need.
+ register_avcodec(&mp2_decoder);
+}
+
+// ==================================
+//! look if Codec is supported by ffmpeg
+bool cDxr3Ffmepg::FindCodec(struct Dxr3Codec& Codec)
+{
+ // find codec
+ Codec.codec = avcodec_find_decoder(Codec.id);
+
+ if (!Codec.codec)
+ {
+ esyslog("dxr3: ffmpeg: codec %#.5x not found - not supported"
+ " by FFmpeg?", Codec.id);
+ return false;
+ }
+
+ // init codec_context
+ memset(&Codec.codec_context, 0, sizeof(Codec.codec_context));
+
+ return true;
+}
+
+// ==================================
+//! try to open Codec
+bool cDxr3Ffmepg::OpenCodec(struct Dxr3Codec& Codec)
+{
+ // try to open codec
+ int result = avcodec_open(&Codec.codec_context, Codec.codec);
+
+ if (result < 0)
+ {
+ esyslog("dxr3: ffmpeg: couldn't open codec %#.5x", Codec.id);
+ return false;
+ }
+ else
+ {
+ Codec.Open = true;
+ }
+
+ return true;
+}
+
+// ==================================
+//! close codec
+void cDxr3Ffmepg::CloseCodec(struct Dxr3Codec& Codec)
+{
+ if (Codec.Open)
+ {
+ avcodec_close(&Codec.codec_context);
+ Codec.Open = false;
+ }
+}
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3ffmpeg.h b/dxr3ffmpeg.h
new file mode 100644
index 0000000..98557c5
--- /dev/null
+++ b/dxr3ffmpeg.h
@@ -0,0 +1,75 @@
+/*
+ * dxr3ffmpeg.h
+ *
+ * Copyright (C) 2004 Christian Gmeiner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _DXR3_FFMPEG_H_
+#define _DXR3_FFMPEG_H_
+
+extern "C"
+{
+#include <avcodec.h>
+}
+
+#include <string.h>
+#include "dxr3singleton.h"
+
+// ==================================
+//! a codec used by this plugin
+struct Dxr3Codec
+{
+ Dxr3Codec() : Open(false) {}
+
+ AVCodec* codec; ///< ffmpeg's AVCodec
+ AVCodecContext codec_context; ///< ffmpeg's AVCodecContext
+ enum CodecID id; ///< id's from ffmpeg, eg. CODEC_ID_MP2
+ bool Open; ///< is codec open?
+};
+
+// ==================================
+// class to work with ffmpeg
+/*!
+ With cDxr3Ffmepg you can easily handle as many
+ codecs as you want.
+ At the moment we need this only for
+ the audiodecoder, but in future i want to use
+ it for ohter nice stuff :)
+*/
+class cDxr3Ffmepg : public Singleton<cDxr3Ffmepg>
+{
+public:
+ cDxr3Ffmepg();
+ ~cDxr3Ffmepg() {}
+
+ bool FindCodec(struct Dxr3Codec& Codec);
+ bool OpenCodec(struct Dxr3Codec& Codec);
+ void CloseCodec(struct Dxr3Codec& Codec);
+
+private:
+ cDxr3Ffmepg(cDxr3Ffmepg&); // no copy constructor
+};
+
+#endif /*_DXR3_FFMPEG_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3generaldefines.h b/dxr3generaldefines.h
new file mode 100644
index 0000000..e0c1d35
--- /dev/null
+++ b/dxr3generaldefines.h
@@ -0,0 +1,54 @@
+/*
+ * dxr3generaldefines.h
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __DXR3_GENERAL_DEFINES_H
+#define __DXR3_GENERAL_DEFINES_H
+
+enum eDxr3DemuxSynchState {
+ DXR3_DEMUX_AUDIO_SYNCHED,
+ DXR3_DEMUX_VIDEO_SYNCHED,
+ DXR3_DEMUX_SYNCHED,
+ DXR3_DEMUX_UNSYNCHED
+};
+
+enum eDxr3DemuxMode {
+ DXR3_DEMUX_TV_MODE,
+ DXR3_DEMUX_REPLAY_MODE,
+ DXR3_DEMUX_AUDIO_ONLY_MODE,
+ DXR3_DEMUX_VIDEO_ONLY_MODE,
+ DXR3_DEMUX_TRICK_MODE,
+ DXR3_DEMUX_OFF_MODE
+};
+
+enum eDxr3TrickState {
+ DXR3_FAST,
+ DXR3_SLOW,
+ DXR3_FREEZE,
+};
+
+#endif // __DXR3_GENERAL_DEFINES_H
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3i18n.c b/dxr3i18n.c
new file mode 100644
index 0000000..1397183
--- /dev/null
+++ b/dxr3i18n.c
@@ -0,0 +1,607 @@
+/*
+ * dxr3i18n.c
+ *
+ * Copyright (C) 2004 Christian Gmeiner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "dxr3i18n.h"
+
+const char *i18n_name = 0;
+
+const tI18nPhrase Phrases[] = {
+ {
+ "DXR3",
+ "DXR3",
+ "", // Slovenski
+ "DXR3",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "DXR3-toiminnot",
+ "", // Polski
+ "DXR3",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "DXR3",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "Hardware MPEG decoder",
+ "", // Deutsch
+ "", // Slovenski
+ "Decoder MPEG Hardware",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "MPEG-purkukortti",
+ "", // Polski
+ "Descodificador MPEG Hardware",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "Descodificador MPEG Hardware",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "DXR3 Adjustment",
+ "DXR3 Einstellungen",
+ "", // Slovenski
+ "Opzioni DXR3",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "DXR3-toiminnot",
+ "", // Polski
+ "Opciones DXR3",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "Opcions DXR3",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "Digital audio output",
+ "Digitaler Audioausgang",
+ "", // Slovenski
+ "Uscita audio digitale",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "Digitaalinen audioulostulo",
+ "", // Polski
+ "Salida audio digital",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "Sortida àudio digital",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "Card number",
+ "Karte",
+ "", // Slovenski
+ "Scheda",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "Kortin järjestysnumero",
+ "", // Polski
+ "Tarjeta",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "Targeta",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "Video mode",
+ "Videomodus",
+ "", // Slovenski
+ "Modo Video",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "Näyttötila",
+ "", // Polski
+ "Modalidad vídeo",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "Modalitat vídeo",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "PAL",
+ "PAL",
+ "", // Slovenski
+ "PAL",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "PAL",
+ "", // Polski
+ "PAL",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "PAL",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "PAL60",
+ "PAL60",
+ "", // Slovenski
+ "PAL60",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "PAL60",
+ "", // Polski
+ "PAL60",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "PAL60",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "NTSC",
+ "NTSC",
+ "", // Slovenski
+ "NTSC",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "NTSC",
+ "", // Polski
+ "NTSC",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "NTSC",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "Reset DXR3 hardware",
+ "Reset DXR3 Hardware",
+ "", // Slovenski
+ "Reset hardware DXR3",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "Palauta kortti alkutilaan",
+ "", // Polski
+ "Reset hardware DXR3",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "Reset hardware DXR3",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "Toggle force letterbox",
+ "Letterbox erzwingen",
+ "", // Slovenski
+ "Commuta modo letterbox forzato ",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "Letterbox-näyttötilan pakotus päälle/pois",
+ "", // Polski
+ "Conmuta modalidad letterbox forzada",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "Commuta modalitat letterbox forçada",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "Switch to analog audio output",
+ "Analoge Ausgabe",
+ "", // Slovenski
+ "Seleziona uscita audio analogica",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "Kytke analoginen audioulostulo",
+ "", // Polski
+ "Selecciona salida audio analógica",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "Selecciona sortida àudio analògica",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "AC3 output on",
+ "AC3 Ausgabe Ein",
+ "", // Slovenski
+ "Attiva uscita AC3",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "AC3-ulostulo päälle",
+ "", // Polski
+ "Activa salida AC3",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "Activa sortida AC3",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "AC3 output off",
+ "AC3 Ausgabe Aus",
+ "", // Slovenski
+ "Disattiva uscita AC3",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "AC3-ulostulo pois",
+ "", // Polski
+ "Desactiva salida AC3",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "Desactiva sortida AC3",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "Switch to digital audio output",
+ "Digitaler Ausgang",
+ "", // Slovenski
+ "Seleziona uscita audio digitale",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "Kytke digitaalinen audioulostulo",
+ "", // Polski
+ "Selecciona salida audio digital",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "Selecciona sortida àudio digital",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "DXR3: releasing devices",
+ "DXR3: Releasing Devices",
+ "", // Slovenski
+ "DXR3: liberando dispositivo",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "DXR3: vapautetaan laitteet",
+ "", // Polski
+ "DXR3: liberando dispositivo",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "DXR3: alliberant dispositiu",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "Color settings",
+ "Farbeinstellungen",
+ "", // Slovenski
+ "Regolazioni colore",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "Väriasetukset",
+ "", // Polski
+ "Ajustes color",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "Ajustaments color",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "Brightness",
+ "Helligkeit",
+ "", // Slovenski
+ "Luminosità",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "Kirkkaus",
+ "", // Polski
+ "Luminosidad",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "Lluminositat",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "Contrast",
+ "Kontrast",
+ "", // Slovenski
+ "Contrasto",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "Kontrasti",
+ "", // Polski
+ "Contraste",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "Contrast",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "Saturation",
+ "Sättigung",
+ "", // Slovenski
+ "Saturazione",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "Värikylläisyys",
+ "", // Polski
+ "Saturación",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "Saturació",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "Hide main menu entry",
+ "Hauptmenüeintrag verstecken",
+ "", // Slovenski
+ "Nascondi voce menù",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "Piilota valinta päävalikosta",
+ "", // Polski
+ "Esconde entrada menú",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "Amaga entrada menú",
+ "ÁÚàëâì ÚÞÜÐÝÔã Ò ÓÛÐÒÝÞÜ ÜÕÝî",
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "Peida valik peamenüüs",
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ {
+ "OSD flush rate (ms)",
+ "", // Deutsch
+ "", // Slovenski
+ "Tempo minimo rinfresco OSD (ms)",
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "Kuvaruutunäytön päivitysväli (ms)",
+ "", // Polski
+ "Tiempo mínimo refresco OSD (ms)",
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "Temps mínim refresc OSD (ms)",
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+#if VDRVERSNUM > 10312
+ "", // Eesti
+#if VDRVERSNUM > 10315
+ "", // Dansk
+#endif
+#endif
+ },
+ { NULL }
+};
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3i18n.h b/dxr3i18n.h
new file mode 100644
index 0000000..063e773
--- /dev/null
+++ b/dxr3i18n.h
@@ -0,0 +1,36 @@
+/*
+ * dxr3i18n.h
+ *
+ * Copyright (C) 2004 Christian Gmeiner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _DXR3_I18N_H_
+#define _DXR3_I18N_H_
+
+#include <vdr/i18n.h>
+
+extern const tI18nPhrase Phrases[];
+
+#endif /*_DXR3_I18N_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3interface.c b/dxr3interface.c
new file mode 100644
index 0000000..9f735fa
--- /dev/null
+++ b/dxr3interface.c
@@ -0,0 +1,1205 @@
+/*
+ * dxr3interface.c
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ * Copyright (C) 2004 Christian Gmeiner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <assert.h>
+#include <math.h>
+#include <sys/soundcard.h>
+#include <linux/dvb/audio.h>
+
+#include "dxr3interface.h"
+#include "dxr3syncbuffer.h"
+#include "dxr3osd.h"
+
+// ==================================
+const int LPCM_HEADER_LENGTH = 7;
+const int ZEROBUFFER_SIZE = 4096;
+uint8_t zerobuffer[ZEROBUFFER_SIZE] = {0};
+const uint32_t UNKNOWN_AUDIO_MODE = 9; // default, unused value
+
+// ==================================
+//! helper function to generate name
+static const char *Dxr3Name(const char *Name, int n)
+{
+ static char buffer[PATH_MAX];
+ snprintf(buffer, sizeof(buffer), "/dev/em8300%s-%d", Name, n);
+ return buffer;
+}
+
+// ==================================
+//! helper function to open card #n
+static int Dxr3Open(const char *Name, int n, int Mode)
+{
+ const char *FileName = Dxr3Name(Name, n);
+ int fd = open(FileName, Mode);
+
+ if (fd < 0)
+ {
+ esyslog("dxr3: unable to open %s: %m", FileName);
+ }
+ return fd;
+}
+
+// ==================================
+//! constructor
+cDxr3Interface::cDxr3Interface() :
+ m_fdControl(-1), m_fdVideo(-1), m_fdAudio(-1), m_fdSpu(-1)
+{
+ // open control stream
+ m_fdControl = Dxr3Open("", cDxr3ConfigData::Instance().GetDxr3Card(),
+ O_WRONLY | O_SYNC);
+ if (m_fdControl < 0)
+ {
+ esyslog("dxr3: please verify that the em8300 modules are loaded");
+ exit(1);
+ }
+
+ // upload microcode to dxr3
+ UploadMicroCode();
+
+ ///< open multimedia streams
+ m_fdVideo = Dxr3Open("_mv", cDxr3ConfigData::Instance().GetDxr3Card(),
+ O_WRONLY | O_SYNC);
+ m_fdAudio = Dxr3Open("_ma", cDxr3ConfigData::Instance().GetDxr3Card(),
+ O_WRONLY | O_SYNC);
+ m_fdSpu = Dxr3Open("_sp", cDxr3ConfigData::Instance().GetDxr3Card(),
+ O_WRONLY | O_SYNC);
+
+ // everything ok?
+ if (m_fdVideo < 0 || m_fdAudio < 0 || m_fdSpu < 0)
+ {
+
+ esyslog("dxr3: fatal: unable to open some em8300 devices");
+ exit(1);
+ }
+
+ // create clock
+ m_pClock = new cDxr3SysClock(m_fdControl, m_fdVideo, m_fdSpu);
+
+ // everything ok?
+ if (!m_pClock)
+ {
+ esyslog("dxr3: fatal: unable to allocate memory for em8300 clock");
+ exit(1);
+ }
+
+ // set default values
+ m_AudioActive = false;
+ m_VideoActive = false;
+ m_OverlayActive = false;
+ m_ExternalReleased = false;
+ m_volume = 255;
+ m_audioChannel = AUDIO_STEREO;
+ m_horizontal = 720;
+ m_vertical = 576;
+ m_audioChannelCount = UNKNOWN_CHANNEL_COUNT;
+ m_audioDataRate = 0;
+ m_audioSampleSize = 0;
+
+ m_audioMode = UNKNOWN_AUDIO_MODE;
+ m_aspectRatio = UNKNOWN_ASPECT_RATIO;
+ m_spuMode = EM8300_SPUMODE_OFF;
+
+ // configure device based on settings
+ ConfigureDevice();
+
+ // get bcs values from driver
+ if (ioctl(m_fdControl, EM8300_IOCTL_GETBCS, &m_bcs) < 0)
+ {
+ esyslog("dxr3: failed to get brightness/contrast/saturation: %m");
+ }
+ else
+ {
+ dsyslog("dxr3: intf: brightness=%d,contrast=%d,saturation=%d at init",
+ m_bcs.brightness, m_bcs.contrast, m_bcs.saturation);
+ }
+
+ PlayBlackFrame();
+ SetChannelCount(1);
+}
+
+// ==================================
+//! destructor
+cDxr3Interface::~cDxr3Interface()
+{
+ // close filehandles
+ if (m_fdControl > -1)
+ {
+ close(m_fdControl);
+ }
+ if (m_fdVideo > -1)
+ {
+ close(m_fdVideo);
+ }
+ if (m_fdSpu > -1)
+ {
+ close(m_fdSpu);
+ }
+ if (m_fdAudio > -1)
+ {
+ close(m_fdAudio);
+ }
+
+ // free some memory
+ if (m_pClock)
+ {
+ delete m_pClock;
+ }
+}
+
+// main
+// ==================================
+void cDxr3Interface::Start()
+{
+}
+
+// ==================================
+void cDxr3Interface::Stop()
+{
+}
+
+// audio
+// ==================================
+//! set audio output to analog
+void cDxr3Interface::SetAudioAnalog()
+{
+ int ioval = 0;
+ Lock();
+
+ if (!m_ExternalReleased && m_audioMode != EM8300_AUDIOMODE_ANALOG)
+ {
+ int prevMode = m_audioMode;
+ m_audioMode = ioval = EM8300_AUDIOMODE_ANALOG;
+ if (ioctl(m_fdControl, EM8300_IOCTL_SET_AUDIOMODE, &ioval) < 0)
+ {
+ esyslog("dxr3: unable to set analog audio mode: %m");
+ }
+ if (prevMode == EM8300_AUDIOMODE_DIGITALAC3)
+ {
+ ReOpenAudio();
+ }
+ }
+
+ Unlock();
+}
+
+// ==================================
+//! set audio output to digital pcm
+void cDxr3Interface::SetAudioDigitalPCM()
+{
+ int ioval = 0;
+ Lock();
+
+ if (!m_ExternalReleased && m_audioMode != EM8300_AUDIOMODE_DIGITALPCM)
+ {
+ int prevMode = m_audioMode;
+ m_audioMode = ioval = EM8300_AUDIOMODE_DIGITALPCM;
+
+ if (ioctl(m_fdControl, EM8300_IOCTL_SET_AUDIOMODE, &ioval) < 0)
+ {
+ esyslog("dxr3: unable to set digital PCM audio mode: %m");
+ }
+ if (prevMode == EM8300_AUDIOMODE_DIGITALAC3)
+ {
+ ReOpenAudio();
+ }
+ }
+
+ Unlock();
+}
+
+// ==================================
+//! set audio output to digital ac3
+void cDxr3Interface::SetAudioDigitalAC3()
+{
+ if (m_audioMode != EM8300_AUDIOMODE_DIGITALAC3)
+ {
+ int ioval = 0;
+ Lock();
+
+ if (!m_ExternalReleased && m_audioMode != EM8300_AUDIOMODE_DIGITALAC3)
+ {
+ m_audioMode = ioval = EM8300_AUDIOMODE_DIGITALAC3;
+ if (ioctl(m_fdControl, EM8300_IOCTL_SET_AUDIOMODE, &ioval) < 0)
+ {
+ esyslog("dxr3: unable to set AC3 audio mode: %m");
+ }
+ ReOpenAudio();
+ }
+
+ Unlock();
+ }
+}
+
+// ==================================
+//! set audio speed
+void cDxr3Interface::SetAudioSpeed(uint32_t speed)
+{
+ if (m_audioDataRate != speed && speed != UNKNOWN_DATA_RATE)
+ {
+ if (!m_ExternalReleased)
+ {
+ if (m_audioMode != EM8300_AUDIOMODE_DIGITALAC3)
+ {
+ if (ioctl(m_fdAudio, SNDCTL_DSP_SPEED, &speed) < 0)
+ {
+ esyslog("dxr3: unable to set DSP speed to %d: %m", speed);
+ }
+ }
+ }
+ m_audioDataRate = speed;
+ }
+}
+
+// ==================================
+//! set number of channels
+void cDxr3Interface::SetChannelCount(uint32_t count)
+{
+ if (m_audioChannelCount != count && count != UNKNOWN_CHANNEL_COUNT)
+ {
+ if (!m_ExternalReleased)
+ {
+ if (m_audioMode != EM8300_AUDIOMODE_DIGITALAC3)
+ {
+ if (ioctl(m_fdAudio, SNDCTL_DSP_STEREO, &count) < 0)
+ {
+ esyslog("dxr3: unable to set channel count to %d: %m",
+ count);
+ }
+ }
+ }
+ m_audioChannelCount = count;
+ }
+}
+
+// ==================================
+//! set audio sample size
+void cDxr3Interface::SetAudioSampleSize(uint32_t sampleSize)
+{
+ if (!m_ExternalReleased)
+ {
+ if (ioctl(m_fdAudio, SNDCTL_DSP_SAMPLESIZE, sampleSize) < 0)
+ {
+ esyslog("dxr3: unable to set audio sample size to %d: %m",
+ sampleSize);
+ }
+ }
+ m_audioSampleSize = sampleSize;
+}
+
+// clock
+// ==================================
+void cDxr3Interface::SetSysClock(uint32_t scr)
+{
+ if (!m_ExternalReleased)
+ {
+ m_pClock->SetSysClock(scr);
+ }
+}
+
+// ==================================
+uint32_t cDxr3Interface::GetSysClock() const
+{
+ uint32_t ret = 0;
+ if (!m_ExternalReleased)
+ {
+ ret = m_pClock->GetSysClock();
+ }
+ return ret;
+}
+
+// ==================================
+int64_t cDxr3Interface::GetPts()
+{
+ return m_lastSeenPts << 1;
+}
+
+// ==================================
+void cDxr3Interface::SetPts(uint32_t pts)
+{
+ if (!m_ExternalReleased)
+ {
+ m_pClock->SetPts(pts);
+ }
+}
+
+// ==================================
+void cDxr3Interface::SetSpuPts(uint32_t pts)
+{
+ pts = pts >> 1;
+ if (!m_ExternalReleased)
+ {
+ if (pts > m_pClock->GetSysClock() &&
+ pts - m_pClock->GetSysClock() < 100000)
+ {
+ m_pClock->SetSpuPts(pts);
+ }
+ }
+}
+
+// state changes
+// ==================================
+//! enable subpicture processing of the dxr3
+void cDxr3Interface::EnableSPU()
+{
+ int ioval = 0;
+ Lock();
+
+ if (!m_ExternalReleased && m_spuMode != EM8300_SPUMODE_ON)
+ {
+ m_spuMode = ioval = EM8300_SPUMODE_ON;
+ if (ioctl(m_fdControl, EM8300_IOCTL_SET_SPUMODE, &ioval) < 0)
+ {
+ esyslog("dxr3: unable to enable subpicture mode: %m");
+ }
+ }
+
+ Unlock();
+}
+
+// ==================================
+//! disable subpicture proeccesing of the dxr3
+void cDxr3Interface::DisableSPU()
+{
+ int ioval = 0;
+ Lock();
+
+ if (!m_ExternalReleased && m_spuMode != EM8300_SPUMODE_OFF)
+ {
+ m_spuMode = ioval = EM8300_SPUMODE_OFF;
+ if (ioctl(m_fdControl, EM8300_IOCTL_SET_SPUMODE, &ioval) < 0)
+ {
+ esyslog("dxr3: unable to disable subpicture mode: %m");
+ }
+ }
+
+ Unlock();
+}
+
+// ==================================
+//! disable audio output of dxr3
+void cDxr3Interface::DisableAudio()
+{
+ m_AudioActive = false;
+
+ // we write zero buffers to dxr3
+ if (!m_ExternalReleased)
+ {
+ if (write(m_fdAudio, zerobuffer, ZEROBUFFER_SIZE) < 0) Resuscitation();
+ if (write(m_fdAudio, zerobuffer, ZEROBUFFER_SIZE) < 0) Resuscitation();
+ if (write(m_fdAudio, zerobuffer, ZEROBUFFER_SIZE) < 0) Resuscitation();
+ if (write(m_fdAudio, zerobuffer, ZEROBUFFER_SIZE) < 0) Resuscitation();
+ }
+}
+
+// ==================================
+//! enable overlay mode of the dxr3
+void cDxr3Interface::EnableOverlay()
+{
+ // first check if it is enabled already
+ if (m_OverlayActive)
+ {
+ return;
+ }
+
+ /*
+#define EM8300_OVERLAY_SIGNAL_ONLY 1
+#define EM8300_OVERLAY_SIGNAL_WITH_VGA 2
+#define EM8300_OVERLAY_VGA_ONLY 3
+ */
+
+ int ioval = EM8300_OVERLAY_SIGNAL_WITH_VGA;
+ // set overlay signal mode
+ if (ioctl(m_fdControl, EM8300_IOCTL_OVERLAY_SIGNALMODE, &ioval) < 0)
+ {
+ //######
+ esyslog("dxr3: unable to set overlay signal mode: %m");
+ return;
+ }
+
+ // setup overlay screen
+ em8300_overlay_screen_t scr;
+ scr.xsize = 1024;
+ scr.ysize = 768;
+
+ if (ioctl(m_fdControl, EM8300_IOCTL_OVERLAY_SETSCREEN, &scr) < 0)
+ {
+ //######
+ esyslog("dxr3: unable to set up overlay screen: %m");
+ return;
+ }
+
+ // setup overlay window
+ em8300_overlay_window_t win;
+ win.xpos = 0;
+ win.ypos = 0;
+ win.width = 1024;
+ win.height = 768;
+
+ if (ioctl(m_fdControl, EM8300_IOCTL_OVERLAY_SETWINDOW, &win) < 0)
+ {
+ //######
+ esyslog("dxr3: unable to set up overlay window: %m");
+ return;
+ }
+
+ m_OverlayActive = true;
+}
+
+// ==================================
+//! disable overlay mode of the dxr3
+void cDxr3Interface::DisanleOverlay()
+{
+ // is it already disabled
+ if (!m_OverlayActive)
+ {
+ return;
+ }
+}
+
+// set/get functions
+// ==================================
+//! get aspect ratio
+uint32_t cDxr3Interface::GetAspectRatio() const
+{
+ int ioval = 0;
+ Lock();
+
+ if (!m_ExternalReleased)
+ {
+ if (ioctl(m_fdControl, EM8300_IOCTL_GET_ASPECTRATIO, &ioval) < 0)
+ {
+ esyslog("dxr3: unable to get aspect ratio: %m");
+ }
+ }
+
+ Unlock();
+ return ioval;
+}
+
+// ==================================
+//! set aspect ratio
+void cDxr3Interface::SetAspectRatio(uint32_t ratio)
+{
+ static int requestCounter = 0;
+
+ Lock();
+
+ if (cDxr3ConfigData::Instance().GetForceLetterBox())
+ ratio = EM8300_ASPECTRATIO_16_9;
+ if (Setup.VideoFormat)
+ ratio = EM8300_ASPECTRATIO_4_3;
+
+ if (!m_ExternalReleased && ratio != UNKNOWN_ASPECT_RATIO)
+ {
+ if (ratio != m_aspectRatio && requestCounter > 50)
+ {
+ requestCounter = 0;
+ if (ioctl(m_fdControl, EM8300_IOCTL_SET_ASPECTRATIO, &ratio) < 0)
+ {
+ esyslog("dxr3: unable to set aspect ratio: %m");
+ }
+ else
+ {
+ m_aspectRatio = ratio;
+ }
+ }
+ else
+ {
+ if (ratio != m_aspectRatio)
+ {
+ ++requestCounter;
+ }
+ else
+ {
+ requestCounter = 0;
+ }
+ }
+ }
+
+ Unlock();
+}
+
+// play functions
+// ==================================
+//! set playing mode and start sync engine
+void cDxr3Interface::SetPlayMode()
+{
+ em8300_register_t reg;
+ int ioval;
+
+ Lock();
+
+ if (!m_ExternalReleased)
+ {
+ ioval = EM8300_SUBDEVICE_AUDIO;
+ ioctl(m_fdControl, EM8300_IOCTL_FLUSH, &ioval);
+ fsync(m_fdVideo);
+
+
+ ioval = EM8300_PLAYMODE_PLAY;
+ if (ioctl(m_fdControl, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0)
+ {
+ esyslog("dxr3: unable to set play mode: %m");
+ }
+ reg.microcode_register = 1;
+ reg.reg = 0;
+ reg.val = MVCOMMAND_SYNC;
+
+ if (ioctl(m_fdControl, EM8300_IOCTL_WRITEREG, &reg) < 0)
+ {
+ esyslog("dxr3: unable to start em8300 sync engine: %m");
+ }
+ }
+
+ Unlock();
+}
+
+// ==================================
+void cDxr3Interface::Pause()
+{
+ int ioval = EM8300_PLAYMODE_PAUSED;
+ Lock();
+
+ if (!m_ExternalReleased)
+ {
+ if (ioctl(m_fdControl, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0)
+ {
+ esyslog("dxr3: unable to set pause mode: %m");
+ }
+ }
+
+ Unlock();
+}
+// ==================================
+void cDxr3Interface::SingleStep()
+{
+ int ioval = EM8300_PLAYMODE_SINGLESTEP;
+ Lock();
+
+ if (!m_ExternalReleased)
+ {
+ if (ioctl(m_fdControl, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0)
+ {
+ esyslog("dxr3: unable to set single-step mode: %m");
+ }
+ }
+
+ Unlock();
+}
+
+// ==================================
+void cDxr3Interface::PlayVideoFrame(cFixedLengthFrame* pFrame, int times)
+{
+ int written = 0;
+ int count = 0;
+
+ if (m_VideoActive)
+ {
+ Lock();
+
+ if (!m_ExternalReleased)
+ {
+ for (int i = 0; i < times; i++)
+ {
+ if (times > 1)
+ {
+ dsyslog("dxr3: playvideoframe: times=%d", times);
+ }
+
+ while (written < pFrame->GetCount() && count >= 0)
+ {
+ if ((count = write(m_fdVideo, pFrame->GetData() + written, pFrame->GetCount() - written)) < 0)
+ {
+ // an error occured
+ Resuscitation();
+ }
+ written += count;
+ }
+
+ // reset
+ written = 0;
+ }
+ }
+
+ Unlock();
+
+ SetAspectRatio(pFrame->GetAspectRatio());
+ uint32_t pts = pFrame->GetPts();
+ if (pts > 0) m_lastSeenPts = pts;
+ }
+}
+
+// ==================================
+void cDxr3Interface::PlayVideoFrame(const uint8_t* pBuf, int length, int times)
+{
+ Lock();
+
+ if (!m_ExternalReleased)
+ {
+ for (int i = 0; i < times; i++)
+ {
+ if (write(m_fdVideo, pBuf, length) < 0) Resuscitation();
+ }
+ }
+
+ Unlock();
+}
+
+// ==================================
+void cDxr3Interface::PlayAudioFrame(cFixedLengthFrame* pFrame)
+{
+ // XXX: Call this only with we are not in external mode?
+ int written = 0;
+
+ if (m_AudioActive)
+ {
+ Lock();
+
+ SetAudioSpeed(pFrame->GetDataRate());
+ SetChannelCount(pFrame->GetChannelCount());
+
+ if (!m_ExternalReleased)
+ {
+ if (!cDxr3ConfigData::Instance().GetAc3OutPut())
+ ResampleVolume((short*)pFrame->GetData(), pFrame->GetCount());
+
+ written = write(m_fdAudio, pFrame->GetData(), pFrame->GetCount());
+ if (written < 0)
+ {
+ esyslog("dxr3: unable to play audio frame: %m");
+ // TODO: Resuscitation() ?
+ }
+ else if (written != pFrame->GetCount())
+ {
+ esyslog("dxr3: unable to play whole audio frame, skipped"
+ " %d bytes", pFrame->GetCount() - written);
+ }
+ }
+
+ Unlock();
+ }
+}
+
+// ==================================
+void cDxr3Interface::PlayAudioFrame(uint8_t* pBuf, int length)
+{
+ int written = 0;
+ Lock();
+
+ if (!m_ExternalReleased)
+ {
+ if (!cDxr3ConfigData::Instance().GetAc3OutPut())
+ ResampleVolume((short*)pBuf, length);
+
+ if ((written = write(m_fdAudio, pBuf, length)) < 0)
+ {
+ esyslog("dxr3: unable to play audio frame: %m");
+ Resuscitation();
+ }
+ else if (written != length)
+ {
+ esyslog("dxr3: unable to play whole audio frame, skipped %d bytes",
+ length - written);
+ }
+ }
+
+ Unlock();
+}
+
+// ==================================
+void cDxr3Interface::PlayAudioLpcmFrame(uint8_t* pBuf, int length)
+{
+ if (length > (LPCM_HEADER_LENGTH + 2))
+ {
+ uint8_t* pFrame = new uint8_t[length - LPCM_HEADER_LENGTH];
+ // only even number of bytes are allowed
+ assert(!((length - LPCM_HEADER_LENGTH) % 2));
+
+ for (int i = LPCM_HEADER_LENGTH; i < length; i += 2)
+ {
+ pFrame[i - LPCM_HEADER_LENGTH] = pBuf[i + 1];
+ pFrame[i - LPCM_HEADER_LENGTH + 1] = pBuf[i];
+ }
+
+ int codedSpeed = (pBuf[5] >> 4) & 0x03;
+ int speed = 0;
+
+ switch (codedSpeed)
+ {
+ case 1:
+ speed = 96000;
+ break;
+
+ case 2:
+ speed = 44100;
+ break;
+
+ case 3:
+ speed = 32000;
+ break;
+
+ default:
+ speed = 48000;
+ break;
+ }
+
+ SetAudioSpeed(speed);
+ PlayAudioFrame(pFrame, length - LPCM_HEADER_LENGTH);
+ delete[] pFrame;
+ }
+}
+
+// external device access
+// ==================================
+//! release devices, so mplayer-plugin, for instance,
+//! can access the dxr3
+void cDxr3Interface::ExternalReleaseDevices()
+{
+ Lock();
+
+ if (!m_ExternalReleased)
+ {
+ if (m_fdControl > -1) close(m_fdControl);
+ if (m_fdVideo > -1) close(m_fdVideo);
+ if (m_fdSpu > -1) close(m_fdSpu);
+ if (m_fdAudio > -1) close(m_fdAudio);
+ m_fdControl = m_fdVideo = m_fdSpu = m_fdAudio = -1;
+ m_aspectRatio = UNKNOWN_ASPECT_RATIO;
+ m_audioMode = UNKNOWN_AUDIO_MODE;
+
+ m_ExternalReleased = true;
+
+ delete m_pClock;
+ m_pClock = 0;
+ }
+
+ Unlock();
+}
+
+// ==================================
+//! reopen devices for using in the dxr3 plugin
+void cDxr3Interface::ExternalReopenDevices()
+{
+ Lock();
+
+ if (m_ExternalReleased)
+ {
+ // open control stream
+ m_fdControl = Dxr3Open("", cDxr3ConfigData::Instance().GetDxr3Card(),
+ O_WRONLY | O_SYNC);
+
+ // open 'multimedia' streams
+ m_fdVideo = Dxr3Open("_mv", cDxr3ConfigData::Instance().GetDxr3Card(),
+ O_WRONLY | O_SYNC);
+ m_fdAudio = Dxr3Open("_ma", cDxr3ConfigData::Instance().GetDxr3Card(),
+ O_WRONLY | O_SYNC);
+ m_fdSpu = Dxr3Open("_sp", cDxr3ConfigData::Instance().GetDxr3Card(),
+ O_WRONLY | O_SYNC);
+
+ if (m_fdControl < 0 || m_fdVideo < 0 || m_fdAudio < 0 || m_fdSpu <0)
+ {
+ ExternalReleaseDevices();
+ }
+ else
+ {
+ m_pClock = new cDxr3SysClock(m_fdControl, m_fdVideo, m_fdSpu);
+ if (!m_pClock)
+ {
+ esyslog("dxr3: fatal: failed to allocate memory for em8300"
+ " system clock in reopen");
+ exit(1);
+ }
+
+ SetChannelCount(1);
+ m_ExternalReleased = false;
+ }
+
+ Resuscitation();
+ }
+
+ Unlock();
+}
+
+
+// tools
+// ==================================
+//! play black frame on tv
+void cDxr3Interface::PlayBlackFrame()
+{
+ extern char blackframe[];
+ extern int blackframeLength;
+
+ Lock();
+
+ if (!m_ExternalReleased)
+ {
+ if (write(m_fdVideo, blackframe, blackframeLength) < 0)
+ Resuscitation();
+ if (write(m_fdVideo, blackframe, blackframeLength) < 0)
+ Resuscitation();
+ if (write(m_fdVideo, blackframe, blackframeLength) < 0)
+ Resuscitation();
+ }
+ m_horizontal = 720;
+ m_vertical = 576;
+
+ Unlock();
+}
+
+// ==================================
+void cDxr3Interface::ReOpenAudio()
+{
+ Lock();
+
+ if (!m_ExternalReleased)
+ {
+ if (m_fdAudio > -1)
+ {
+ int bufsize = 0;
+ ioctl(m_fdAudio, SNDCTL_DSP_GETODELAY, &bufsize);
+ usleep(bufsize / 192 * 1000);
+
+ delete m_pClock;
+ close(m_fdAudio);
+
+ m_fdAudio = Dxr3Open("_ma",
+ cDxr3ConfigData::Instance().GetDxr3Card(),
+ O_WRONLY | O_SYNC);
+
+ uint32_t tmpAudioDataRate = m_audioDataRate;
+ uint32_t tmpAudioChannelCount = m_audioChannelCount;
+ m_audioDataRate = m_audioChannelCount = 0;
+ m_pClock = new cDxr3SysClock(m_fdControl, m_fdVideo, m_fdSpu);
+ SetAudioSpeed(tmpAudioDataRate);
+ SetChannelCount(tmpAudioChannelCount);
+ }
+ }
+
+ Unlock();
+}
+
+// ==================================
+//! uploadroutine for microcode
+void cDxr3Interface::UploadMicroCode()
+{
+ em8300_microcode_t em8300_microcode;
+ struct stat s;
+
+ // try to open it
+ // MICROCODE comes from makefile
+ int UCODE = open(MICROCODE, O_RDONLY);
+
+ if (UCODE <0)
+ {
+ esyslog("dxr3: fatal: unable to open microcode file %s: %m",
+ MICROCODE);
+ exit(1);
+ }
+
+ if (fstat(UCODE, &s ) <0)
+ {
+ esyslog("dxr3: fatal: unable to fstat microcode file %s: %m",
+ MICROCODE);
+ exit(1);
+ }
+
+ // read microcode
+ em8300_microcode.ucode = new char[s.st_size];
+ if (em8300_microcode.ucode == NULL)
+ {
+ esyslog("dxr3: fatal: unable to malloc() space for microcode");
+ exit(1);
+ }
+
+ if (read(UCODE,em8300_microcode.ucode,s.st_size) < 1)
+ {
+ esyslog("dxr3: fatal: unable to read microcode file %s: %m",
+ MICROCODE);
+ // free memory to avoid memory leak
+ delete [] (char*) em8300_microcode.ucode;
+ exit(1);
+ }
+
+ close(UCODE);
+
+ em8300_microcode.ucode_size = s.st_size;
+
+ // upload it
+ if( ioctl(m_fdControl, EM8300_IOCTL_INIT, &em8300_microcode) == -1)
+ {
+ esyslog("dxr3: fatal: microcode upload failed: %m");
+ // free memory to avoid memory leak
+ delete [] (char*) em8300_microcode.ucode;
+ exit(1);
+ }
+
+ // free memory to avoid memory leak
+ delete [] (char*) em8300_microcode.ucode;
+}
+
+// ==================================
+//! config and setup device via ioctl calls
+void cDxr3Interface::ConfigureDevice()
+{
+ uint32_t videomode = 0;
+
+ // set video mode
+ if (cDxr3ConfigData::Instance().GetVideoMode() == PAL)
+ {
+ dsyslog("dxr3: configure: video mode: PAL");
+ videomode = EM8300_VIDEOMODE_PAL;
+ }
+ else if (cDxr3ConfigData::Instance().GetVideoMode() == PAL60)
+ {
+ dsyslog("dxr3: configure: video mode: PAL60");
+ videomode = EM8300_VIDEOMODE_PAL60;
+ }
+ else
+ {
+ dsyslog("dxr3: configure: video mode: NTSC");
+ videomode = EM8300_VIDEOMODE_NTSC;
+ }
+
+ // make ioctl
+ if (ioctl(m_fdControl, EM8300_IOCTL_SET_VIDEOMODE, &videomode) == -1)
+ {
+ esyslog("dxr3: fatal: unable to set video mode: %m");
+ exit(1);
+ }
+
+ // set audio mode
+ if (!cDxr3ConfigData::Instance().GetUseDigitalOut())
+ {
+ dsyslog("dxr3: configure: audio mode: analog");
+ SetAudioAnalog();
+ }
+}
+
+// ==================================
+//! reset whole hardware
+void cDxr3Interface::Resuscitation()
+{
+ time_t startt = time(&startt);
+ time_t endt = 0;
+ m_ExternalReleased = true;
+
+ dsyslog("dxr3: resuscitation: device failure or user initiated reset");
+
+ UploadMicroCode();
+
+ //NonBlockingCloseOpen();
+ m_ExternalReleased = false;
+
+ endt = time(&endt);
+
+ if (endt - startt > 4)
+ {
+ esyslog("dxr3: fatal: reopening devices took too long");
+ exit(1);
+ }
+ dsyslog("dxr3: resuscitation: reopening devices took %ld seconds",
+ endt - startt);
+
+ ConfigureDevice();
+}
+
+// ==================================
+//! pcm resampling function
+void cDxr3Interface::ResampleVolume(short* pcmbuf, int size)
+{
+ if (m_volume == 0)
+ {
+ memset(pcmbuf, 0, size);
+ }
+ if (m_volume < 255 || m_audioChannel != AUDIO_STEREO)
+ {
+ int factor = (int)pow (2.0, (double)m_volume/32 + 8.0) - 1;
+ //int factor = (int)pow (2.0, (double)m_volume/16) - 1;
+ for (int i = 0; i < size / (int)sizeof(short); i++)
+ {
+ if (m_audioChannel == AUDIO_MONO_RIGHT && !(i & 0x1))
+ {
+ pcmbuf[i] = pcmbuf[i+1];
+ }
+ if (m_audioChannel == AUDIO_MONO_LEFT && (i & 0x1))
+ {
+ pcmbuf[i] = pcmbuf[i-1];
+ }
+ else if (m_volume < 255)
+ {
+ pcmbuf[i] = (((int)pcmbuf[i]) * factor) / 65536;
+ }
+ }
+ }
+}
+
+// ==================================
+void cDxr3Interface::ClearOsd()
+{
+ encodedata ed;
+ int controlstart= 0;
+ int x1 = 0;
+ int& i = ed.count = 0;
+
+ // display duration...
+ ed.data[i++]= 0x00;
+ ed.data[i++]= 0x00; //durration before turn on command occurs
+ //in 90000/1024 units
+ // x1
+ ed.data[i++]= x1 >> 8; //since this is the last command block, this
+ ed.data[i++]= x1 & 0xff; //points back to itself
+
+
+ // 0x01: start displaying
+ ed.data[i++]= 0x02;
+
+ // 0xFF: end sequence
+ ed.data[i++]= 0xFF;
+ if (!i&1)
+ {
+ ed.data[i++]= 0xff;
+ }
+
+ // x0
+ ed.data[2]= (controlstart) >> 8;
+ ed.data[3]= (controlstart) & 0xff;
+
+ // packet size
+ ed.data[0]= i >> 8;
+ ed.data[1]= i & 0xff;
+
+ if (!m_ExternalReleased)
+ {
+ WriteSpu((const uint8_t*) &ed, (int) ed.count);
+ ClearButton();
+ }
+}
+
+// ==================================
+void cDxr3Interface::WriteSpu(const uint8_t* pBuf, int length)
+{
+ Lock();
+
+ if (!m_ExternalReleased)
+ {
+ if (write(m_fdSpu, pBuf, length) < 0) Resuscitation();
+ }
+
+ Unlock();
+}
+
+// ==================================
+void cDxr3Interface::SetButton(uint16_t sx, uint16_t sy, uint16_t ex,
+ uint16_t ey, uint32_t palette)
+{
+ em8300_button_t button;
+
+ button.color = palette >> 16;
+ button.contrast = palette & 0xFFFF;
+ button.top = sy;
+ button.bottom = ey;
+ button.left = sx;
+ button.right = ex;
+
+ ioctl(m_fdSpu, EM8300_IOCTL_SPU_BUTTON, &button);
+}
+
+// ==================================
+void cDxr3Interface::ClearButton()
+{
+ em8300_button_t button;
+
+ button.color = 0;
+ button.contrast = 0;
+ button.top = 1;
+ button.bottom = 2;
+ button.left = 1;
+ button.right = 2;
+
+ ioctl(m_fdSpu, EM8300_IOCTL_SPU_BUTTON, &button);
+}
+
+// ==================================
+void cDxr3Interface::SetPalette(unsigned int *pal)
+{
+ ioctl(m_fdSpu, EM8300_IOCTL_SPU_SETPALETTE, (uint8_t*)pal);
+}
+
+// helper functions for dxr3 main osd screen
+// ==================================
+//! reset dxr3 card
+void cDxr3Interface::ResetHardware()
+{
+ Lock();
+
+ isyslog("dxr3: hardware reset requested");
+ Resuscitation();
+
+ Unlock();
+}
+
+// set brightness/contrast/saturation
+// ==================================
+//! set brightness
+void cDxr3Interface::SetBrightness(int value)
+{
+ m_bcs.brightness = value;
+
+ if (ioctl(m_fdControl, EM8300_IOCTL_SETBCS, &m_bcs) < 0)
+ {
+ esyslog("dxr3: unable to set brightness to %d: %m", value);
+ }
+}
+
+// ==================================
+//! set contrast
+void cDxr3Interface::SetContrast(int value)
+{
+ m_bcs.contrast = value;
+
+ if (ioctl(m_fdControl, EM8300_IOCTL_SETBCS, &m_bcs) < 0)
+ {
+ esyslog("dxr3: unable to set contrast to %d: %m", value);
+ }
+}
+
+// ==================================
+//! set saturation
+void cDxr3Interface::SetSaturation(int value)
+{
+ m_bcs.saturation = value;
+
+ if (ioctl(m_fdControl, EM8300_IOCTL_SETBCS, &m_bcs) < 0)
+ {
+ esyslog("dxr3: unable to set saturation to %d: %m", value);
+ }
+}
+
+// ==================================
+cMutex* cDxr3Interface::m_pMutex = new cMutex;
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3interface.h b/dxr3interface.h
new file mode 100644
index 0000000..c6b0cf4
--- /dev/null
+++ b/dxr3interface.h
@@ -0,0 +1,221 @@
+/*
+ * dxr3interface.h
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ * Copyright (C) 2004 Christian Gmeiner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _DXR3_INTERFACE_H_
+#define _DXR3_INTERFACE_H_
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <linux/em8300.h>
+#include <sys/ioctl.h>
+
+#include "dxr3vdrincludes.h"
+#include "dxr3configdata.h"
+#include "dxr3sysclock.h"
+
+// ==================================
+class cFixedLengthFrame;
+
+// ==================================
+//! interafce to dxr3-card
+/*!
+ cDxr3Interface is the interface to the dxr3
+ driver and so to the card,
+ so this is the layer between plugin and driver.
+*/
+class cDxr3Interface : public Singleton<cDxr3Interface>
+{
+public:
+ cDxr3Interface();
+ ~cDxr3Interface();
+
+ // main
+ void Start();
+ void Stop();
+
+ // audio
+ void SetAudioAnalog();
+ void SetAudioDigitalPCM();
+ void SetAudioDigitalAC3();
+ void SetVolume(int volume)
+ {
+ m_volume = volume;
+ }
+ void SetAudioChannel(int audiochannel)
+ {
+ m_audioChannel = audiochannel;
+ }
+ int GetAudioChannel(void)
+ {
+ return m_audioChannel;
+ }
+ void SetAudioSpeed(uint32_t speed);
+ void SetChannelCount(uint32_t count);
+ void SetAudioSampleSize(uint32_t sampleSize);
+
+ // clock
+ void SetSysClock(uint32_t scr);
+ uint32_t GetSysClock() const;
+ void SetPts(uint32_t pts);
+ void SetSpuPts(uint32_t pts);
+ int64_t GetPts();
+
+ // state changes
+ void EnableSPU();
+ void DisableSPU();
+ void EnableVideo()
+ {
+ m_VideoActive = true;
+ }
+ void DisableVideo()
+ {
+ m_VideoActive = false;
+ }
+ void EnableAudio()
+ {
+ m_AudioActive = true;
+ }
+ void DisableAudio();
+ void EnableOverlay();
+ void DisanleOverlay();
+
+ // set/get functions
+ uint32_t GetAspectRatio() const;
+ void SetAspectRatio(uint32_t ratio);
+ uint32_t GetHorizontalSize() const
+ {
+ return m_horizontal;
+ }
+ void SetHorizontalSize(uint32_t horizontal)
+ {
+ m_horizontal = horizontal;
+ };
+ uint32_t GetVerticalSize() const
+ {
+ return m_vertical;
+ }
+ void SetVerticalSize(uint32_t vertical)
+ {
+ m_vertical = vertical;
+ };
+
+ // play functions
+ void SetPlayMode();
+ void Pause();
+ void SingleStep();
+ void PlayVideoFrame(cFixedLengthFrame* pFrame, int times = 1);
+ void PlayVideoFrame(const uint8_t* pBuf, int length, int times = 1);
+ void PlayAudioFrame(cFixedLengthFrame* pFrame);
+ void PlayAudioFrame(uint8_t* pBuf, int length);
+ void PlayAudioLpcmFrame(uint8_t* pBuf, int length);
+
+ // external device access
+ void ExternalReleaseDevices();
+ void ExternalReopenDevices();
+ bool IsExternalReleased() const
+ {
+ return m_ExternalReleased;
+ }
+
+ // tools
+ void PlayBlackFrame();
+ void ReOpenAudio();
+
+ // osd/spu
+
+ void ClearOsd();
+ void WriteSpu(const uint8_t* pBuf, int length);
+ void SetButton(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey,
+ uint32_t palette);
+ void ClearButton();
+ void SetPalette(unsigned int *pal = NULL);
+
+ // overlay functions
+
+ // helper functions for dxr3 main osd screen
+ void ResetHardware();
+
+ // set brightness/contrast/saturation
+ void SetBrightness(int value);
+ void SetContrast(int value);
+ void SetSaturation(int value);
+
+private:
+ // file handles
+ int m_fdControl; ///< filehandle for contol fifo of dxr3 card
+ int m_fdVideo; ///< filehandle for video fifo of dxr3 card
+ int m_fdAudio; ///< filehandle for audio fifo of dxr3 card
+ int m_fdSpu; ///< filehandle for spu fifo of dxr3 card
+ uint32_t m_lastSeenPts;
+
+ // dxr3 clock
+ cDxr3SysClock* m_pClock; ///< clock used for sync
+
+ uint32_t m_audioChannelCount; ///< how many channels in the current audiostream
+ uint32_t m_audioDataRate; ///< which rate is used for the current audiostream
+ int m_aspectDelayCounter;
+ uint32_t m_aspectRatio; ///< current used aspect ratio
+ uint32_t m_horizontal; ///< horizontal size of current videostream
+ uint32_t m_vertical; ///< vertical size of current videostream
+ uint32_t m_audioSampleSize; ///< how big is the sample size for the current audiostream
+ uint32_t m_audioMode;
+ uint32_t m_spuMode;
+ bool m_ExternalReleased; ///< is dxr3 used by e.g. mplayer?
+ int m_volume; ///< volumevalue (0...255)
+ int m_audioChannel; ///> 0=stereo, 1=left, 2=right audio channel
+ bool m_AudioActive; ///< is audio active?
+ bool m_VideoActive; ///< is video active?
+ bool m_OverlayActive; ///< is overlay active?
+
+ // bcs
+ em8300_bcs_t m_bcs; ///< BrightnessContrastSaturation values
+
+ // spu
+ //cDxr3InterfaceSpu m_SpuInterface;
+
+ void UploadMicroCode();
+ void ConfigureDevice();
+ void ResampleVolume(short* pcmbuf, int size);
+ void Resuscitation();
+
+protected:
+ static cMutex* m_pMutex; ///< mutex for dxr3interface
+
+ static void Lock()
+ {
+ cDxr3Interface::m_pMutex->Lock();
+ }
+ static void Unlock()
+ {
+ cDxr3Interface::m_pMutex->Unlock();
+ }
+};
+
+#endif /*_DXR3_INTERFACE_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3interface_spu_encoder.c b/dxr3interface_spu_encoder.c
new file mode 100644
index 0000000..405da33
--- /dev/null
+++ b/dxr3interface_spu_encoder.c
@@ -0,0 +1,688 @@
+/*
+ * dxr3interface_spu_encoder.c - encodes an OSD bitmap as subpicture
+ *
+ * Assimilated and adapted by
+ * Stefan Schluenss <dxr3_osd@schluenss.de>
+ * Nov. 2002
+ *
+ * Based on the subpicture encoding routines from MPlayer and
+ * the information given by
+ * Samuel Hocevar
+ * Michel Lespinasse
+ * and http://members.aol.com/mpucoder/DVD/spu.html
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "dxr3interface_spu_encoder.h"
+#include "dxr3tools.h"
+
+/*
+ ToDo:
+ - cSPUEncoder::encode_do_row: FIXME: watch this space for EOL
+*/
+
+
+#ifdef USE_XINE_SCALER
+/*=======================================================================
+ *
+ * Scaling functions taken from the xine plugin
+ *
+ */
+
+#include <math.h>
+#include <signal.h>
+#include <string>
+#include <vdr/plugin.h>
+
+namespace XineScaler
+{
+
+ template <const int yInc = 1, class T = int>
+ class cBresenham
+ {
+ const int m_dx;
+ const int m_dy;
+
+ int m_eps;
+ T m_y;
+
+ public:
+ cBresenham(const int dy, const int dx, const int eps, T const y0 = 0)
+ : m_dx(dx), m_dy(dy), m_eps(eps - m_dx), m_y(y0)
+ {
+ }
+
+ int eps() const
+ {
+ return m_eps;
+ }
+
+ T step()
+ {
+ m_eps += m_dy;
+ while (m_eps >= 0)
+ {
+ m_eps -= m_dx;
+ m_y += yInc;
+ }
+ return m_y;
+ }
+
+ T step(int n)
+ {
+ if (n <= 0)
+ return m_y;
+ while (--n > 0)
+ step();
+ return step();
+ }
+
+ T stepRelative(int n = 1)
+ {
+ T const y = m_y;
+ return step(n) - y;
+ }
+ };
+
+ static uint8_t *ScaleBitmapLQ(const uint8_t *src, uint8_t *dest, int x0,
+ int y0, int w, int h, int ws, int hs, int x1,
+ int y1, int w1, int h1,
+ const uint8_t transparentIndex)
+ {
+ uint8_t *const screen = new uint8_t[ OSDHEIGHT * OSDWIDTH ];
+ {
+ int x1 = x0 + w;
+ int y1 = y0 + h;
+ int x2 = OSDWIDTH;
+ int y2 = OSDHEIGHT;
+
+ if (x1 > x2)
+ x1 = x2;
+
+ if (y1 > y2)
+ y1 = y2;
+
+ uint8_t *dst = screen;
+
+ for (int y = 0; y < y0; y++)
+ {
+ for (int x = 0; x < x2; x++)
+ *dst++ = transparentIndex;
+ }
+
+ for (int y = y0; y < y1; y++)
+ {
+ for (int x = 0; x < x0; x++)
+ *dst++ = transparentIndex;
+
+ for (int x = x0; x < x1; x++)
+ *dst++ = *src++;
+
+ for (int x = x1; x < x2; x++)
+ *dst++ = transparentIndex;
+ }
+
+ for (int y = y1; y < y2; y++)
+ {
+ for (int x = 0; x < x2; x++)
+ *dst++ = transparentIndex;
+ }
+ }
+
+ uint8_t *scaled = dest; //new uint8_t[ hs * ws ];
+ {
+ int x2 = x1 + w1;
+ int y2 = y1 + h1;
+
+ if (x2 > ws)
+ {
+ x2 = ws;
+ w1 = x2 - x1;
+ if (w1 < 0)
+ w1 = 0;
+ }
+
+ if (y2 > hs)
+ {
+ y2 = hs;
+ h1 = y2 - y1;
+ if (h1 < 0)
+ h1 = 0;
+ }
+
+ cBresenham<OSDWIDTH, uint8_t *> yyBh(2 * OSDHEIGHT, 2 * hs, hs, screen);
+ uint8_t *screen0 = yyBh.step(y1); //(((2 * y1 + 1) * OSDHEIGHT / hs) / 2);
+
+ cBresenham<> xxBh0(2 * OSDWIDTH, 2 * ws, ws);
+ xxBh0.step(x1); //(((2 * x1 + 1) * OSDWIDTH / ws) / 2);
+
+ uint8_t *scaled0 = scaled + y1 * OSDWIDTH; //ws; ******
+
+ for (int y = y1; y < y2; y++)
+ {
+ cBresenham<> xxBh(xxBh0);
+ int xxx = xxBh.step(0); //(((2 * x1 + 1) * OSDWIDTH / ws) / 2);
+
+ uint8_t *screen00 = screen0 + xxx;
+ uint8_t *scaled00 = scaled0 + x1;
+
+ for (int x = x1; x < x2; x++)
+ {
+ *scaled00++ = *screen00;
+ screen00 += xxBh.stepRelative();
+ }
+
+ scaled0 += OSDWIDTH; //ws; *******
+ screen0 = yyBh.step();
+ }
+ }
+
+ delete [] screen;
+ return scaled;
+ }
+
+};
+
+/*=======================================================================
+ *
+ * End of scaling functions taken from the xine plugin
+ *
+ */
+#endif /* USE_XINE_SCALER */
+
+
+// ==================================
+// dec.
+cSpuData::~cSpuData()
+{
+ Clear();
+}
+
+// ==================================
+// free buffer and set it to 0
+void cSpuData::Clear()
+{
+ if (data)
+ {
+ free(data);
+ count = malloc_size = 0;
+ }
+}
+
+// ==================================
+// wirte a byte to spu buffer
+void cSpuData::WriteByte(uint8_t byte)
+{
+ if (count >= malloc_size)
+ {
+ data = (u_char*) realloc(data, malloc_size += 2048);
+ }
+ data[count++] = byte;
+}
+
+// ==================================
+void cSpuData::WriteNibble(int *higher_nibble, uint8_t nibble)
+{
+}
+
+// ==================================
+void cSpuData::WriteRle(int *higher_nibble, int length, int color)
+{
+}
+
+// ==================================
+cSPUEncoder::cSPUEncoder()
+{
+ // clear osd
+ memset(OSD_Screen, 0x00, OSDWIDTH * OSDHEIGHT);
+ memset(OSD_Screen2, 0x00, OSDWIDTH * OSDHEIGHT);
+ memset(OSD_Screen3, 0x00, OSDWIDTH * OSDHEIGHT);
+
+ // set active area to 0
+ //m_x0 = m_x1 = m_y0 = m_y1 = 0;
+}
+
+
+//========================================
+//Sets the palette indexes to use for one
+//window taking into account the global
+//palette (with colors needed by all windows)
+
+void cSPUEncoder::SetPalette(int numWindow, cPalette* commonPalette,
+ cPalette* windowPalette)
+{
+ int NumColors;
+ const tColor *Colors = windowPalette->Colors(NumColors);
+ if (Colors)
+ {
+ for (int i = 0; i < NumColors; i++)
+ {
+ int idx = commonPalette->Index(Colors[i] & 0x00FFFFFF);
+ int opacity = ((Colors[i] & 0xFF000000) >> 24) * 0xF / 0xFF;
+ bitmapcolor[numWindow][i] = (opacity<<4) | idx;
+ }
+ }
+}
+
+//========================================
+//Clears the OSD bitmap
+
+void cSPUEncoder::Clear(void)
+{
+ memset(OSD_Screen, 0, sizeof(OSD_Screen));
+}
+
+//=============================================================
+//Sets the spu palette and flushes the OSD content into the spu
+int cSPUEncoder::Flush(cPalette *Palette)
+{
+ int NumColors;
+ const tColor *Colors = Palette->Colors(NumColors);
+ if (Colors)
+ {
+ unsigned int palcolors[16];
+ for (int i = 0; i < NumColors; i++)
+ {
+ // convert AARRGGBB to AABBGGRR (the driver expected the the
+ // colors the wrong way, so does Rgb2YCrCb and friends)
+ unsigned int color = ((Colors[i] & 0x0000FF) << 16)
+ | (Colors[i] & 0x00FF00) | ((Colors[i] & 0xFF0000) >> 16);
+ palcolors[i] = Tools::Rgb2YCrCb(color);
+ }
+ cDxr3Interface::Instance().SetPalette(palcolors);
+ }
+
+ // calculate osd size (actually dead code)
+ CalculateActiveOsdArea();
+
+ m_encodeddata.count = 0;
+ EncodePixelbufRle(0, 0, OSDWIDTH, OSDHEIGHT-1, OSD_Screen, 0,
+ &m_encodeddata);
+
+ dsyslog("dxr3: cSPUEncoder::Flush: OSD data size: %d",
+ m_encodeddata.count);
+
+ if (m_encodeddata.count <= DATASIZE)
+ {
+ cDxr3Interface::Instance().WriteSpu((uint8_t*) &m_encodeddata,
+ m_encodeddata.count);
+ return 0;
+ }
+ else
+ {
+ esyslog("dxr3: spu: warning: SPU data size (%d) exceeds limit (%d)",
+ m_encodeddata.count, DATASIZE);
+ return -1;
+ }
+}
+
+// ==================================
+// stamps window content into full osd bitmap
+void cSPUEncoder::CopyBlockIntoOSD(int numWindow, int linewidth, int x0,
+ int y0, int x1, int y1, const tIndex *data)
+{
+ tIndex *cp;
+ const tIndex *sp = data;
+
+ if (x1 >= OSDWIDTH)
+ x1 = OSDWIDTH - 1;
+ if (y1 >= OSDHEIGHT)
+ y1 = OSDHEIGHT - 1;
+ cp = &OSD_Screen[y0 * OSDWIDTH + x0];
+
+ for (int y = y0; y <= y1; y++)
+ {
+ for (int x = x0; x <= x1; x++)
+ {
+ *(cp++) = bitmapcolor[numWindow][*(sp++) & 0x0f];
+ }
+ cp += OSDWIDTH - (x1 - x0 + 1);
+ sp += linewidth - (x1 - x0 + 1);
+ }
+}
+
+// ==================================
+// taken from mplayer (spuenc.c)
+void cSPUEncoder::EncodePixelbufRle(int x, int y, int w, int h, u_char *inbuf,
+ int stride, encodedata *ed)
+{
+ pixbuf pb;
+ int i, row;
+ pb.x = w;
+ pb.y = h;
+
+#ifdef USE_XINE_SCALER
+ int ws = cDxr3Interface::Instance().GetHorizontalSize();
+ int hs = cDxr3Interface::Instance().GetVerticalSize();
+ if (ws < 720 || hs < 576)
+ inbuf = XineScaler::ScaleBitmapLQ(inbuf, OSD_Screen2, 0, 0, OSDWIDTH,
+ OSDHEIGHT, ws, hs, 0, 0, ws, hs,
+ 0 /* clrTransparent */);
+#else
+ if (cDxr3Interface::Instance().GetHorizontalSize() < 700)
+ {
+ double fac = (double)OSDWIDTH / (double)OSDWIDTH2;
+ ScaleOSD(fac, inbuf, 10);
+ inbuf = OSD_Screen2;
+ }
+#endif /* USE_XINE_SCALER */
+
+ m_ColorManager = new cColorManager();
+
+ // Encode colors into highlight regions
+ m_ColorManager->EncodeColors(w, h, inbuf, OSD_Screen3);
+ inbuf = OSD_Screen3;
+
+ pb.pixels = inbuf;
+ ed->count = 4;
+ ed->nibblewaiting = 0;
+
+ row = 0;
+ for (i = 0; i < pb.y; i++)
+ {
+ encode_do_row(ed, &pb, row);
+ row += 2;
+ if (row > pb.y)
+ {
+ row = 1;
+ ed->oddstart = ed->count;
+ }
+ }
+ encode_do_control(x, y, ed, &pb);
+
+ delete m_ColorManager;
+}
+
+#ifndef USE_XINE_SCALER
+// ==================================
+void cSPUEncoder::ScaleOSD(double fac, unsigned char* buf,
+ unsigned char NumColors)
+{
+ int y, x, s, d;
+ unsigned char dline[2 * OSDWIDTH + 10];
+
+ memset(OSD_Screen2, 0x00, OSDWIDTH * OSDHEIGHT);
+
+ if (cDxr3Interface::Instance().GetHorizontalSize() < 470)
+ {
+ for (y = 0; y < OSDHEIGHT; y++)
+ for (s = 0, d = 0; d < OSDWIDTH; s++, d += 2)
+ OSD_Screen2[y * OSDWIDTH + s] = buf[y * OSDWIDTH + d];
+ }
+ else
+ {
+ for (y = 0; y < OSDHEIGHT; y++)
+ {
+ memset(dline, 0, 2 * OSDWIDTH + 10);
+
+ for (s = 0, d = 0; s < OSDWIDTH; s++, d += 2)
+ {
+ // stretch line to double width to 1440
+ dline[d] = buf[y * OSDWIDTH + s];
+ }
+
+ for (d = 1; d < (2 * OSDWIDTH); d += 2)
+ {
+ dline[d] = dline[d + 1];
+ }
+
+ for (s = 0, x = 0; x < OSDWIDTH2; x++, s += 3)
+ {
+ // now take every third pixel (1440/3=480)
+ OSD_Screen2[y * OSDWIDTH + x] = dline[s];
+ }
+ }
+ }
+}
+#endif /* not USE_XINE_SCALER */
+
+// ==================================
+// taken from mplayer (spuenc.c)
+void cSPUEncoder::encode_put_nibble(encodedata* ed, u_char nibble)
+{
+ if (ed->nibblewaiting)
+ {
+ ed->data[ed->count++] |= nibble;
+ ed->nibblewaiting = 0;
+ }
+ else
+ {
+ ed->data[ed->count] = nibble << 4;
+ ed->nibblewaiting = 1;
+ }
+}
+
+// ==================================
+// taken from mplayer (spuenc.c)
+void cSPUEncoder::encode_pixels(encodedata* ed, int color, int number)
+{
+ if (number > 3)
+ {
+ if (number > 15)
+ {
+ encode_put_nibble(ed, 0);
+ if (number > 63)
+ {
+ encode_put_nibble(ed, (number & 0xC0) >> 6);
+ }
+ }
+ encode_put_nibble(ed, (number & 0x3C) >> 2);
+ }
+ encode_put_nibble(ed, ((number & 0xF) << 2) | color);
+}
+
+// ==================================
+// taken from mplayer (spuenc.c)
+void cSPUEncoder::encode_eol(encodedata* ed)
+{
+ if (ed->nibblewaiting)
+ {
+ ed->count++;
+ ed->nibblewaiting = 0;
+ }
+ ed->data[ed->count++] = 0x00;
+ ed->data[ed->count++] = 0x00;
+}
+
+// ==================================
+// taken from mplayer (spuenc.c)
+void cSPUEncoder::encode_do_row(encodedata* ed, pixbuf* pb, int row)
+{
+ int i = 0;
+ u_char* pix = pb->pixels + row * pb->x;
+ int color = *pix & 0x03;
+ int n = 0; /* the number of pixels of this color */
+
+ while (i++ < pb->x)
+ {
+ /* FIXME: watch this space for EOL */
+ if ((*pix & 0x03) != color || n == 255)
+ {
+ encode_pixels(ed, color, n);
+ color = *pix & 0x03;
+ n = 1;
+ }
+ else
+ {
+ n++;
+ }
+ pix++;
+ }
+
+ /* this small optimization: (n>63) can save up to two bytes per line
+ * I wonder if this is compatible with all the hardware... */
+ if (color == 0 && n > 63)
+ {
+ encode_eol(ed);
+ }
+ else
+ {
+ encode_pixels(ed, color, n);
+ }
+
+ if (ed->nibblewaiting)
+ {
+ ed->count++;
+ ed->nibblewaiting = 0;
+ }
+}
+
+// ==================================
+// taken from mplayer (spuenc.c)
+void cSPUEncoder::encode_do_control(int x, int y, encodedata* ed, pixbuf* pb)
+{
+ int controlstart = ed->count;
+ int x1;
+ int i;
+ u_int top, left, bottom, right;
+
+ top = y; //this forces the first bit to be visible on a TV
+ left = x; //you could actually pass in x/y and do some nice
+
+ bottom = top + pb->y - 1;
+ right = left + pb->x - 1;
+
+ /* start at x0+2*/
+ i = controlstart;
+
+ x1 = (i); //marker for last command block address
+
+ /* display duration... */
+ ed->data[i++] = 0x00;
+ ed->data[i++] = 0x00; //duration before turn on command occurs (will not be used)
+
+ /* x1 */
+ ed->data[i++] = x1 >> 8; //since this is the last command block, this
+ ed->data[i++] = x1 & 0xff; //points back to itself
+
+ /* 0x00: force displaying */
+ ed->data[i++] = 0x00;
+
+ /* 0x03: palette info */
+ ed->data[i++] = 0x03;
+ ed->data[i++] = 0x01;
+ ed->data[i++] = 0x23;
+
+ /* 0x04: transparency info (reversed) */
+ ed->data[i++] = 0x04; // SET_CONTR
+ ed->data[i++] = 0xFF;
+ ed->data[i++] = 0x70;
+
+ /* 0x05: coordinates */
+ ed->data[i++] = 0x05; // SET_DAREA
+ ed->data[i++] = left >> 4;
+ ed->data[i++] = ((left & 0xf) << 4) + (right >> 8);
+ ed->data[i++] = (right & 0xff);
+ ed->data[i++] = top >> 4;
+ ed->data[i++] = ((top&0xf) << 4) + (bottom >> 8);
+ ed->data[i++] = (bottom&0xff);
+
+ /* 0x06: both fields' offsets */
+ ed->data[i++] = 0x06; // SET_DSPXA
+ ed->data[i++] = 0x00;
+ ed->data[i++] = 0x04;
+ ed->data[i++] = ed->oddstart >> 8;
+ ed->data[i++] = ed->oddstart & 0xff;
+
+ int len;
+ unsigned char *spudata;
+
+ spudata = m_ColorManager->GetSpuData(len);
+ //check that the highlight regions data wont overflow the buffer
+ if (i + len + 2 > DATASIZE)
+ {
+ ed->count = DATASIZE + 1;
+ return;
+ }
+
+ for (int si = 0; si < len; si++)
+ {
+ ed->data[i++] = *(spudata + si);
+ }
+
+ /* 0xFF: end sequence */
+ ed->data[i++]= 0xFF;
+ if (! i&1)
+ {
+ ed->data[i++]= 0xff;
+ }
+
+ /* x0 */
+ ed->data[2] = (controlstart) >> 8;
+ ed->data[3] = (controlstart) & 0xff;
+
+ /* packet size */
+ ed->data[0] = i >> 8;
+ ed->data[1] = i & 0xff;
+
+ ed->count = i;
+}
+
+// ==================================
+// Stop spu display
+void cSPUEncoder::StopSpu(void)
+{
+ uint8_t ed[10];
+ /* packet size */
+ ed[0] = 0;
+ ed[1] = 10;
+
+ /* pointer to the SP_DCSQT */
+ ed[2] = 0;
+ ed[3] = 4;
+
+ /* SP_DCSQT */
+ /* display duration... */
+ ed[4] = 0x00;
+ ed[5] = 0x00; //duration before turn on command occurs (will not be used)
+
+ /* pointer to next command block */
+ ed[6] = 0; //since this is the last command block, this
+ ed[7] = 4;//points back to itself
+
+ /* 0x02: stop displaying */
+ ed[8] = 0x02;
+
+ /* 0xFF: end sequence */
+ ed[9] = 0xFF;
+ cDxr3Interface::Instance().WriteSpu(ed, 10);
+}
+
+// ==================================
+// we _only_ write usefull data
+void cSPUEncoder::CalculateActiveOsdArea()
+{
+ // reset
+ //m_x0 = m_x1 = m_y0 = m_y1 = 0;
+
+ // calculate
+ /*
+ for (int i = 1; i < 8; i++)
+ {
+ m_x0 = max(m_x0, m_windows[i].x0);
+ m_x1 = max(m_x1, m_windows[i].y0);
+ m_y0 = max(m_y0, m_windows[i].x1);
+ m_y1 = max(m_y1, m_windows[i].y1);
+ }
+ */
+}
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3interface_spu_encoder.h b/dxr3interface_spu_encoder.h
new file mode 100644
index 0000000..b3f75cc
--- /dev/null
+++ b/dxr3interface_spu_encoder.h
@@ -0,0 +1,153 @@
+/*
+ * dxr3interface_spu_encoder.h - encodes an OSD bitmap as subpicture
+ *
+ * Assimilated and adapted by
+ * Stefan Schluenss <dxr3_osd@schluenss.de>
+ * Nov. 2002
+ *
+ * Based on the subpicture encoding routines from MPlayer and
+ * the information given by
+ * Samuel Hocevar
+ * Michel Lespinasse
+ * and http://members.aol.com/mpucoder/DVD/spu.html
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#ifndef _DXR3_INTERFACE_SPU_ENCODER_
+#define _DXR3_INTERFACE_SPU_ENCODER_
+
+#include <stdlib.h>
+#include <linux/dvb/osd.h>
+#include "dxr3vdrincludes.h"
+#include "dxr3colormanager.h"
+#include "dxr3interface.h"
+#include "dxr3singleton.h"
+
+// ==================================
+#define MAXWINDOWS 8
+#define DATASIZE 53220
+#define OSDWIDTH 720
+#define OSDWIDTH2 480
+#define OSDHEIGHT 576
+
+// ==================================
+// used to get active osd area
+struct sRectal
+{
+ sRectal() : x0(0), x1(0), y0(0), y1(0) {}
+
+ size_t x0;
+ size_t x1;
+ size_t y0;
+ size_t y1;
+};
+
+// ==================================
+// our spu(data) with all needed routines
+class cSpuData
+{
+public:
+ cSpuData(): count(0), malloc_size(0) {}
+ ~cSpuData();
+
+ void Clear();
+ u_char* GetData() const
+ {
+ return data;
+ }
+
+ // write operations
+ void WriteByte(uint8_t byte);
+ void WriteNibble(int *higher_nibble, uint8_t nibble);
+ void WriteRle(int *higher_nibble, int length, int color);
+
+private:
+ u_char *data;
+ size_t count; // the count of bytes written
+ size_t malloc_size; // size of data
+};
+
+// ==================================
+struct pixbuf
+{
+ int x, y;
+ u_int rgb[4];
+ u_char* pixels;
+};
+
+// ==================================
+struct encodedata
+{
+ u_char data[DATASIZE];
+ int count; // the count of bytes written
+ int oddstart;
+ int nibblewaiting;
+};
+
+// ==================================
+class cSPUEncoder : public Singleton<cSPUEncoder>
+{
+public:
+ cSPUEncoder();
+ ~cSPUEncoder() {}
+
+ int Flush(cPalette *Palette);
+ void CopyBlockIntoOSD(int numWindow, int linewidth,
+ int x0,int y0, int x1, int y1, const tIndex *data);
+ void StopSpu(void);
+ void SetPalette(int numWindow, cPalette* commonPalette,
+ cPalette* windowPalette);
+ void Clear(void);
+
+private:
+ cSPUEncoder(cSPUEncoder&); // no copy constructor
+
+ // helper functions
+ void EncodePixelbufRle(int x, int y, int w, int h,
+ u_char *inbuf, int stride, encodedata *ed);
+#ifndef USE_XINE_SCALER
+ void ScaleOSD(double fac, unsigned char* buf, unsigned char NumColors=4);
+#endif
+ void encode_put_nibble(encodedata* ed, u_char nibble);
+ void encode_pixels(encodedata* ed, int color, int number);
+ void encode_eol(encodedata* ed);
+ void encode_do_row(encodedata* ed, pixbuf* pb, int row);
+ void encode_do_control(int x,int y, encodedata* ed, pixbuf* pb);
+
+ void CalculateActiveOsdArea();
+
+ int bitmapcolor[8][16];
+ cColorManager* m_ColorManager;
+ encodedata m_encodeddata;
+
+ // our osd :)
+ u_char OSD_Screen[OSDWIDTH * OSDHEIGHT];
+ u_char OSD_Screen2[OSDWIDTH * OSDHEIGHT];
+ u_char OSD_Screen3[OSDWIDTH * OSDHEIGHT];
+
+ // 'active' osd sizes
+ sRectal m_active_osd;
+};
+
+#endif /*_DXR3_INTERFACE_SPU_ENCODER_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3multichannelaudio.c b/dxr3multichannelaudio.c
new file mode 100644
index 0000000..abab4b8
--- /dev/null
+++ b/dxr3multichannelaudio.c
@@ -0,0 +1,784 @@
+/*
+ * dxr3multichannelaudio.c:
+ *
+ * taken from the AC3overDVB Patch maintained by Stefan Huelswitt
+ *
+ *
+ */
+
+#include <malloc.h>
+#include "dxr3multichannelaudio.h"
+#include <vdr/ringbuffer.h>
+
+//#define DEBUG(x...) printf(x)
+#define DEBUG(x...)
+
+//#define ED(x...) printf(x)
+#define ED(x...)
+
+#define aAC3 0x80
+#define aDTS 0x88
+#define aLPCM 0xA0
+#define aMPEG 0xC0
+
+#define aVDR 0x0B // VDR specific audio substream
+#define aSPU 0x20 // SPU stream
+
+#define PES_HDR_SIZE 6 // length of PES header
+#define PTS_SIZE 5 // length of PTS data
+#define MAX_FRAMECOUNT 1536 // max. LPCM payload size
+
+#define SYNC_SIZE 7 // how many bytes needed to sync on a audio header
+
+#define AC3_SIZE 6144 // size of AC3 IEC paket
+#define DTS_SIZE 2048 // size of DTS IEC paket
+#define IEC_HDR_SIZE 8 // size of IEC header
+
+// --- cAudioEncapsulator -----------------------------------------------------
+
+class cAudioEncapsulator
+{
+private:
+ int totalSize, frameCount;
+ cFrame *frame;
+ uchar *frameData;
+ //
+ uchar syncBuff[SYNC_SIZE];
+ int have, length, skipped;
+ //
+ uchar ptsFlags;
+ const uchar *ptsData;
+ int ptsDelay;
+ //
+ void NewFrame(uchar PTSflags, const uchar *PTSdata);
+ void SyncFound(const uchar *data);
+protected:
+ int streamType;
+ cRingBufferFrame *ringBuffer;
+ int fillup, firstBurst;
+ bool mute, muteData;
+ //
+ void StartFrame(int size, uchar PTSflags, const uchar *PTSdata);
+ void FinishFrame(void);
+ void PutData(const uchar *data, int len);
+ void SendIECpause(int type, uchar PTSflags, const uchar *PTSdata);
+ //
+ virtual int SyncInfo(const uchar *data)=0;
+ virtual void StartIECFrame(const uchar *buf, int length, uchar PTSflags,
+ const uchar *PTSdata) = 0;
+ virtual void FinishIECFrame(void);
+public:
+ cAudioEncapsulator(cRingBufferFrame *rb, int StreamType);
+ virtual ~cAudioEncapsulator();
+ void Clear(void);
+ void Decode(const uchar *data, int len, uchar PTSflags, int PTSdelay,
+ const uchar *PTSdata);
+ int StreamType()
+ {
+ return streamType;
+ }
+ void Mute(bool Mute)
+ {
+ mute = Mute;
+ }
+};
+
+cAudioEncapsulator::cAudioEncapsulator(cRingBufferFrame *rb, int StreamType)
+{
+ ringBuffer = rb;
+ streamType = StreamType;
+ frame = 0;
+ firstBurst = 1;
+ Clear();
+}
+
+cAudioEncapsulator::~cAudioEncapsulator()
+{
+ delete frame;
+}
+
+void cAudioEncapsulator::Clear(void)
+{
+ delete frame;
+ frame = 0;
+ frameCount = 0;
+ fillup = 0;
+ mute = muteData = false;
+ have = length = skipped = 0;
+}
+
+void cAudioEncapsulator::StartFrame(int size, uchar PTSflags,
+ const uchar *PTSdata)
+{
+ if (frame)
+ {
+ DEBUG("StartFrame() with unfinished frame!\n");
+ FinishFrame();
+ }
+ ED("StartFrame: size=%d ptsFlags=%d\n", size, PTSflags);
+ totalSize = size;
+ NewFrame(PTSflags, PTSdata);
+}
+
+void cAudioEncapsulator::NewFrame(uchar PTSflags, const uchar *PTSdata)
+{
+ if (!totalSize)
+ {
+ DEBUG("NewFrame: new frame requested, but totalSize=0\n");
+ return;
+ }
+ static const int ptslen[] = { 0, 0, PTS_SIZE, PTS_SIZE*2 };
+ const int plen = ptslen[PTSflags];
+ int len = std::min(totalSize, MAX_FRAMECOUNT);
+ ED("NewFrame: totalSize=%d frameCount=%d PTSflags=%d", totalSize, len, PTSflags);
+ totalSize -= len;
+ ED(" new totalSize=%d\n",totalSize);
+ len += (plen + 3 + 7);
+ frameCount = len + PES_HDR_SIZE;
+ frameData = MALLOC(uchar, frameCount);
+ if (frameData)
+ {
+ frame = new cFrame(frameData, -frameCount, ftUnknown);
+ if (frame)
+ {
+ uchar buf[10];
+ // build the PES header
+ buf[0] = 0x00;
+ buf[1] = 0x00;
+ buf[2] = 0x01;
+ buf[3] = 0xBD; // PRIVATE_STREAM1
+ buf[4] = (len >> 8) & 0xFF;
+ buf[5] = len & 0xFF;
+ buf[6] = 0x84;
+ buf[7] = plen ? (PTSflags << 6) : 0;
+ buf[8] = plen;
+ PutData(buf, 9);
+
+ if (plen)
+ PutData(PTSdata, plen);
+
+ // build LPCM header
+ buf[0] = aLPCM; // substream ID
+ buf[1] = 0xFF;
+ buf[2] = 0x00;
+ buf[3] = 0x00;
+ buf[4] = 0x00;
+ buf[5] = 0x00;
+ buf[6] = 0x81;
+ PutData(buf, 7);
+ return;
+ }
+ else
+ {
+ free(frameData);
+ frameData = 0;
+ }
+ }
+ esyslog("Failed to build frame for audio encapsulation");
+}
+
+void cAudioEncapsulator::FinishFrame(void)
+{
+ if (frameCount)
+ {
+ DEBUG("FinishFrame() with frameCount>0\n");
+ PutData(0, frameCount);
+ }
+ if (frame && frameData)
+ {
+ ED("FinishFrame: totalSize=%d\n", totalSize);
+ if (!ringBuffer->Put(frame)) {
+ esyslog("Ringbuffer overflow. Encapsulated audio frame lost");
+ delete frame;
+ }
+ }
+ frame = 0;
+ frameData = 0;
+ frameCount = 0;
+}
+
+void cAudioEncapsulator::PutData(const uchar *data, int len)
+{
+ if (!muteData)
+ {
+ if (!frameData)
+ DEBUG("PutData() without frame\n");
+ while (frameData && len > 0)
+ {
+ int l = std::min(len, frameCount);
+ if (data)
+ {
+ memcpy(frameData, data, l);
+ data += l;
+ }
+ else
+ memset(frameData, 0, l);
+ frameData += l;
+ len -= l;
+ frameCount -= l;
+
+ ED("PutData: %s=%d len=%d frameCount=%d\n",
+ data ? "put" : "zero", l, len, frameCount);
+ if (!frameCount)
+ {
+ FinishFrame();
+ if (totalSize > 0)
+ NewFrame(0, 0);
+ }
+ }
+ }
+}
+
+void cAudioEncapsulator::SendIECpause(int type, uchar PTSflags,
+ const uchar *PTSdata)
+{
+ StartFrame(AC3_SIZE, PTSflags, PTSdata);
+ uchar burst[IEC_HDR_SIZE];
+ // prepare IEC 60958 data frame
+ burst[0] = 0xF8;
+ burst[1] = 0x72;
+ burst[2] = 0x4E;
+ burst[3] = 0x1F;
+
+ switch (type) {
+ default:
+ case 0:
+ burst[4] = 7 << 5; // null frame, stream = 7
+ burst[5] = 0x00;
+ burst[6] = 0x00; // No data therein
+ burst[7] = 0x00;
+ break;
+ case 1:
+ burst[4] = 0x00; // Audio ES Channel empty, wait
+ burst[5] = 0x03; // for DD Decoder or pause
+ burst[6] = 0x00; // Trailing frame size is 32 bits payload
+ burst[7] = 0x20;
+ break;
+ case -1:
+ burst[4] = 0x01; // User stop, skip or error
+ burst[5] = 0x03;
+ burst[6] = 0x08; // Trailing frame size is zero
+ burst[7] = 0x00;
+ break;
+ }
+ PutData(burst, sizeof(burst));
+ PutData(0, AC3_SIZE - sizeof(burst));
+ FinishFrame();
+ muteData = true;
+}
+
+void cAudioEncapsulator::FinishIECFrame(void)
+{
+ if (!muteData)
+ {
+ ED("FinishIECFrame: fillup=%d\n", fillup);
+ if (fillup)
+ PutData(0, fillup);
+ FinishFrame();
+ }
+ muteData = false;
+ fillup = 0;
+}
+
+void cAudioEncapsulator::SyncFound(const uchar *data)
+{
+ if (skipped)
+ {
+ DEBUG("Decode: skipped %d bytes\n", skipped);
+ ED("skipped: "); for(int k = -skipped; k < 0; k++) ED("%02x ",data[k]);
+ ED("\ndata: "); for(int k = 0; k<24; k++) ED("%02x ", data[k]);
+ ED("\n");
+ skipped = 0;
+ }
+ uchar pf = 0;
+ ED("Decode: sync found ptsFlags=%d ptsDelay=%d\n", ptsFlags, ptsDelay);
+ if (ptsFlags && ptsDelay <= 1)
+ {
+ pf = ptsFlags;
+ ptsFlags = 0;
+ }
+ if (firstBurst || mute)
+ {
+ SendIECpause(1, pf, ptsData);
+ if (firstBurst && ++firstBurst>10)
+ firstBurst = 0;
+ }
+ else
+ StartIECFrame(data, length, pf, ptsData);
+ PutData(data, SYNC_SIZE);
+ have = SYNC_SIZE;
+}
+
+void cAudioEncapsulator::Decode(const uchar *data, int len, uchar PTSflags,
+ int PTSdelay, const uchar *PTSdata)
+{
+ ED("Decode: enter length=%d have=%d len=%d PTSflags=%d PTSdelay=%d\n",
+ length, have, len, PTSflags, PTSdelay);
+ if (PTSflags)
+ {
+ // if we are close to the end of an audio frame, but are already
+ // receiving the start of the next frame, assume a corrupted stream
+ // and finish the incomplete frame.
+ if (length && length-have < 20 && !PTSdelay && SyncInfo(data))
+ {
+ int miss = length - have;
+ DEBUG("Decode: incomplete frame (stream corrupt?). syncing to next. miss=%d\n", miss);
+ PutData(0, miss);
+ FinishIECFrame();
+ length = have = 0;
+ }
+ /*
+ // we only send PTS info if we're nearly at frame start, except
+ // if we're signaled to delay the PTS
+ if (length && have > 40)
+ {
+ if(PTSdelay)
+ ED("Decode: PTS delayed\n");
+ else
+ {
+ DEBUG("Decode: PTS info dropped length=%d have=%d\n",
+ length, have);
+ PTSflags = 0;
+ }
+ }
+ */
+ ptsFlags = PTSflags;
+ ptsData = PTSdata;
+ ptsDelay = PTSdelay;
+ //ED("Decode: saved PTS flags=%d delay=%d\n", ptsFlags, ptsDelay);
+ }
+
+#if 0
+ {
+ printf("Decode: len=%d\n", len);
+ for (int i = 0; i < len; )
+ {
+ printf("%04x:", i);
+ for (int j = 0; j < 16 && i < len; j++)
+ printf(" %02x", data[i++]);
+ printf("\n");
+ }
+ }
+#endif
+
+ int used = 0;
+ while (used < len)
+ {
+ if (!length) // we are still searching for a header sync
+ {
+ if (!have) // buffer is empty, work without buffering
+ {
+ if (used + SYNC_SIZE < len)
+ {
+ length = SyncInfo(&data[used]);
+ if (length)
+ {
+ ED("Decode: sync found at offset %d (len=%d)\n",
+ used, length);
+ SyncFound(&data[used]);
+ used += SYNC_SIZE;
+ ptsDelay -= SYNC_SIZE;
+ continue;
+ }
+ else
+ {
+ used++;
+ skipped++;
+ }
+ }
+ else // not enough data to try a sync, buffer the rest
+ {
+ ED("Decode: buffering started\n");
+ have = len - used;
+ memcpy(syncBuff, &data[used], have);
+ used += have;
+ ptsDelay -= have;
+ }
+ }
+ else // unfortunately buffer is not empty, so continue with
+ // buffering until sync found
+ {
+ int need = std::min(SYNC_SIZE - have, len - used);
+ if (need)
+ {
+ memcpy(&syncBuff[have], &data[used], need);
+ have += need;
+ used += need;
+ ptsDelay -= need;
+ }
+ if (have == SYNC_SIZE)
+ {
+ length = SyncInfo(syncBuff);
+ if (length)
+ {
+ ED("Decode: (buffered) sync found at offset %d (len=%d)\n",used-7,length);
+ SyncFound(syncBuff);
+ continue;
+ }
+ else
+ {
+ memmove(syncBuff, syncBuff + 1, SYNC_SIZE - 1);
+ have--;
+ skipped++;
+ }
+ }
+ }
+ }
+ else // we have a header sync and are copying data
+ {
+ int need = std::min(length - have, len - used);
+ if (need)
+ {
+ ED("Decode: writing %d\n", need);
+ PutData(&data[used], need);
+ have += need;
+ used += need;
+ ptsDelay -= need;
+ if (have == length)
+ {
+ FinishIECFrame();
+ length = have = 0;
+ continue;
+ }
+ }
+ }
+ }
+ ED("Decode: leave length=%d have=%d len=%d used=%d\n",
+ length, have, len, used);
+}
+
+// --- cAudioEncapsulatorAC3 --------------------------------------------------
+
+class cAudioEncapsulatorAC3 : public cAudioEncapsulator {
+private:
+ virtual int SyncInfo(const uchar *buf);
+ virtual void StartIECFrame(const uchar *buf, int length, uchar PTSflags,
+ const uchar *PTSdata);
+public:
+ cAudioEncapsulatorAC3(cRingBufferFrame *rb, int StreamType);
+};
+
+cAudioEncapsulatorAC3::cAudioEncapsulatorAC3(cRingBufferFrame *rb,
+ int StreamType)
+ : cAudioEncapsulator(rb, StreamType)
+{}
+
+int cAudioEncapsulatorAC3::SyncInfo(const uchar *buf)
+{
+ static const int rate[] = { 32, 40, 48, 56, 64, 80, 96, 112,
+ 128, 160, 192, 224, 256, 320, 384, 448,
+ 512, 576, 640 };
+
+ if ((buf[0] != 0x0B) || (buf[1] != 0x77)) /* syncword */
+ return 0;
+ if (buf[5] >= 0x60) /* bsid >= 12 */
+ return 0;
+
+ int frmsizecod = buf[4] & 63;
+ if (frmsizecod >= 38)
+ return 0;
+ int bitrate = rate[frmsizecod >> 1];
+
+ switch (buf[4] & 0xC0) {
+ case 0:
+ return 4 * bitrate;
+ case 0x40:
+ return 2 * (320 * bitrate / 147 + (frmsizecod & 1));
+ case 0x80:
+ return 6 * bitrate;
+ default:
+ return 0;
+ }
+}
+
+void cAudioEncapsulatorAC3::StartIECFrame(const uchar *buf, int length,
+ uchar PTSflags, const uchar *PTSdata)
+{
+ StartFrame(AC3_SIZE, PTSflags, PTSdata);
+ fillup = AC3_SIZE - IEC_HDR_SIZE - length;
+
+ // prepare IEC 60958 data frame
+ uchar burst[IEC_HDR_SIZE];
+ burst[0] = 0xF8;
+ burst[1] = 0x72;
+ burst[2] = 0x4E;
+ burst[3] = 0x1F;
+ burst[4] = (buf[5] & 0x07); // Pc1
+ burst[5] = 0x01; // Pc2 AC-3
+ burst[6] = ((length * 8) >> 8 ) & 0xFF; // Pd1
+ burst[7] = (length * 8) & 0xFF; // Pd2
+ PutData(burst,sizeof(burst));
+}
+
+// --- cAudioEncapsulatorDTS --------------------------------------------------
+
+class cAudioEncapsulatorDTS : public cAudioEncapsulator
+{
+private:
+ virtual int SyncInfo(const uchar *buf);
+ virtual void StartIECFrame(const uchar *buf, int length, uchar PTSflags,
+ const uchar *PTSdata);
+public:
+ cAudioEncapsulatorDTS(cRingBufferFrame *rb, int StreamType);
+};
+
+cAudioEncapsulatorDTS::cAudioEncapsulatorDTS(cRingBufferFrame *rb,
+ int StreamType)
+ : cAudioEncapsulator(rb, StreamType)
+{}
+
+int cAudioEncapsulatorDTS::SyncInfo(const uchar *buf)
+{
+ if ((buf[0] != 0x7F) ||
+ (buf[1] != 0xfE) ||
+ (buf[2] != 0x80) ||
+ (buf[3] != 0x01))
+ return 0;
+
+ int length = ((buf[5] & 0x03) << 12) |
+ ((buf[6] & 0xFF) << 4) |
+ ((buf[7] & 0xF0) >> 4);
+
+ return length + 1;
+}
+
+void cAudioEncapsulatorDTS::StartIECFrame(const uchar *buf, int length,
+ uchar PTSflags, const uchar *PTSdata)
+{
+ uchar ac5_type = ((buf[4] & 0x01) << 6) | ((buf[5] >>2) & 0x3F);
+ uchar ac5_spdif_type;
+ switch(ac5_type)
+ {
+ case 0x0F:
+ ac5_spdif_type = 0x0B; // DTS
+ break;
+ case 0x1F:
+ ac5_spdif_type = 0x0C; // DTS
+ break;
+ case 0x3F:
+ ac5_spdif_type = 0x0D; // DTS
+ break;
+ default:
+ ac5_spdif_type = 0x00; // DTS
+ esyslog("DTS: SPDIF type not detected: ac5 type = %X!\n", ac5_type);
+ break;
+ }
+
+ if (length > DTS_SIZE-IEC_HDR_SIZE)
+ {
+ DEBUG("DTS: length too long %d\n", length);
+ return;
+ }
+
+ StartFrame(DTS_SIZE, PTSflags, PTSdata);
+ fillup = DTS_SIZE - IEC_HDR_SIZE - length;
+
+ // prepare IEC 60958 data frame
+ uchar burst[IEC_HDR_SIZE];
+ burst[0] = 0xF8;
+ burst[1] = 0x72;
+ burst[2] = 0x4E;
+ burst[3] = 0x1F;
+ burst[4] = 0x00;
+ burst[5] = ac5_spdif_type; // DTS data
+ burst[6] = ((length * 8) >> 8) & 0xFF; // ac5_length * 8
+ burst[7] = (length * 8) & 0xFF;
+ PutData(burst,sizeof(burst));
+}
+
+// --- cMultichannelAudio -----------------------------------------------------
+
+cMultichannelAudio::cMultichannelAudio(cRingBufferFrame *rb)
+{
+ encapsulator = 0;
+ ringBuffer = rb;
+ fixed = false;
+ if (!ringBuffer)
+ DEBUG("multichannel: no ringbuffer!");
+}
+
+cMultichannelAudio::~cMultichannelAudio()
+{
+ delete encapsulator;
+}
+
+void cMultichannelAudio::Clear()
+{
+ Lock();
+ if (encapsulator)
+ encapsulator->Clear();
+ Unlock();
+}
+
+void cMultichannelAudio::Reset()
+{
+ Lock();
+ delete encapsulator;
+ encapsulator = 0;
+ fixed = false;
+ Unlock();
+}
+
+/*
+void cMultichannelAudio::Mute(bool Mute)
+{
+ Lock();
+ if (encapsulator)
+ encapsulator->Mute(Mute);
+ Unlock();
+}
+*/
+
+int cMultichannelAudio::Check(uchar *b, int length, uchar *header)
+{
+ Lock();
+ int res = 0;
+ ptsDelay = 0;
+ offset = 0;
+ ptsData = 0;
+
+ // get PTS information
+ ptsFlags = header[7] >> 6;
+ if (ptsFlags)
+ ptsData = &header[9];
+
+ // AC3 frames may span over multiple PES packets. Unfortunately the
+ // continuation packets start with the aLPCM code sometimes. Some magic
+ // here to detect this case.
+ uchar subStreamType = b[0];
+ if (subStreamType != aVDR)
+ subStreamType&=0xF8;
+ bool aligned = header[6] & 4;
+ if (!aligned)
+ {
+ uchar ost = encapsulator ? encapsulator->StreamType() : 0;
+ if (!ptsFlags)
+ {
+ if ((subStreamType != aLPCM && subStreamType != aSPU) || fixed)
+ {
+ if (ost > 0)
+ {
+ ED("multichannel: crossing -> keep encapsulator\n");
+ subStreamType = ost;
+ }
+ else
+ {
+ ED("multichannel: crossing -> skip\n");
+ res = 1;
+ goto out; // skip
+ }
+ }
+ }
+ else if (fixed && ost > 0)
+ {
+ ED("multichannel: fixed unaligned -> keep encapsulator\n");
+ subStreamType = ost;
+ }
+ }
+ fixed = false;
+
+ switch (subStreamType)
+ {
+ case aDTS:
+ case aAC3:
+ offset = 4; // skip the DVD stream infos
+ break;
+ default:
+ if (aligned || !ptsFlags)
+ {
+ if (encapsulator)
+ {
+ Reset();
+ DEBUG("multichannel: interrupted encapsulator stream (unknown)\n");
+ }
+ DEBUG("multichannel: unknown substream type %x (skipped)\n",
+ subStreamType);
+ res = 1;
+ goto out; // skip
+ }
+ subStreamType = aVDR;
+ ED("multichannel: assuming aVDR for unknown substream type\n");
+ // fall through
+ case aVDR:
+ fixed = true;
+ break;
+ case aLPCM:
+ if (encapsulator)
+ {
+ Reset();
+ DEBUG("multichannel: interrupted encapsulator stream (LPCM)\n");
+ }
+ ED("multichannel: LPCM\n");
+ res = 2;
+ goto out; // pass
+ case aSPU:
+ ED("multichannel: SPU stream (skipped)\n");
+ res = 1;
+ goto out; // skip
+ }
+
+ // If the SubStreamType has changed then select the right encapsulator
+ if (!encapsulator || encapsulator->StreamType() != subStreamType)
+ {
+ DEBUG("multichannel: new encapsulator %x\n", subStreamType);
+ Reset();
+ switch (subStreamType)
+ {
+ case aAC3:
+ case aVDR: // AC3
+ encapsulator = new cAudioEncapsulatorAC3(ringBuffer,subStreamType);
+ break;
+ case aDTS: // Dts
+ encapsulator = new cAudioEncapsulatorDTS(ringBuffer,subStreamType);
+ break;
+ }
+ if (!encapsulator)
+ {
+ DEBUG("multichannel: no encapsulator\n");
+ res = 1;
+ goto out; // skip
+ }
+ }
+
+out:
+ ED("HEADER type=%x sub=%x ptsflags=%d length=%d\n",
+ header[3], subStreamType, ptsFlags, length);
+ ED("head: "); for(int k = 0; k < 24; k++) ED("%02x ", header[k]);
+ ED("\ndata: "); for(int k = 0; k < 24; k++) ED("%02x ", b[k]);
+ ED("\n");
+
+ Unlock();
+ return res;
+}
+
+void cMultichannelAudio::Encapsulate(uchar *b, int length)
+{
+ Lock();
+ if(offset && ptsFlags)
+ { // get start of the packet to which the PTS belong (DVD only)
+ if (offset >= 2 && length > offset - 2)
+ ptsDelay |= b[offset - 2] * 256;
+ if (offset >= 1 && length > offset - 1)
+ ptsDelay |= b[offset - 1];
+ }
+ if (length >= offset)
+ {
+ if (encapsulator)
+ encapsulator->Decode(b+offset, length - offset, ptsFlags,
+ ptsDelay, ptsData);
+ ptsFlags = 0;
+ ptsDelay = 0;
+ offset = 0;
+ ptsData = 0;
+ }
+ else
+ offset -= length;
+ Unlock();
+}
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3multichannelaudio.h b/dxr3multichannelaudio.h
new file mode 100644
index 0000000..d2dd40c
--- /dev/null
+++ b/dxr3multichannelaudio.h
@@ -0,0 +1,43 @@
+#ifndef _DXR3MULTICHANNELAUDIO_H_
+#define _DXR3MULTICHANNELAUDIO_H_
+
+#include "dxr3vdrincludes.h"
+
+class cAudioEncapsulator;
+class cRingBufferFrame;
+
+// ==================================
+// Based on AC3overDVB Patch maintained
+// by Stefan Huelswitt
+class cMultichannelAudio : public cMutex
+{
+private:
+ cAudioEncapsulator *encapsulator;
+ cRingBufferFrame *ringBuffer;
+ int ptsFlags, ptsDelay, offset;
+ uchar *ptsData;
+ bool fixed;
+
+public:
+ cMultichannelAudio(cRingBufferFrame *rb);
+ virtual ~cMultichannelAudio();
+
+ int Check(uchar *b, int length, uchar *header);
+ int Offset(void)
+ {
+ return offset;
+ }
+ void Encapsulate(uchar *b, int length);
+ void Clear();
+ void Reset();
+ //void Mute(bool Mute);
+};
+
+#endif /*_DXR3MULTICHANNELAUDIO_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3nextpts.c b/dxr3nextpts.c
new file mode 100644
index 0000000..b30751d
--- /dev/null
+++ b/dxr3nextpts.c
@@ -0,0 +1,32 @@
+/*
+ * dxr3nextpts.c
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "dxr3nextpts.h"
+
+// ==================================
+cMutex* cDxr3NextPts::m_pMutex = new cMutex;
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3nextpts.h b/dxr3nextpts.h
new file mode 100644
index 0000000..7aaf4e3
--- /dev/null
+++ b/dxr3nextpts.h
@@ -0,0 +1,85 @@
+/*
+ * dxr3nextpts.h
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _DXR3NEXTPTS_H_
+#define _DXR3NEXTPTS_H_
+
+#include <unistd.h>
+#include <stdint.h>
+#include "dxr3vdrincludes.h"
+#include "dxr3singleton.h"
+
+// ==================================
+// pts program time stamp
+// damit wird ermittelt welches audio frame zu welchem bild gehört
+class cDxr3NextPts : public Singleton<cDxr3NextPts>
+{
+public:
+ cDxr3NextPts() {}
+ ~cDxr3NextPts() {}
+
+ void SetNextPts(uint32_t pts)
+ {
+ Lock();
+ if (pts)
+ m_nextPts = pts;
+ Unlock();
+ }
+ uint32_t GetNextPts()
+ {
+ Lock();
+ uint32_t tmpPts = m_nextPts;
+ Unlock();
+ return tmpPts;
+ }
+
+ void Clear()
+ {
+ Lock();
+ m_nextPts = 0;
+ Unlock();
+ }
+
+protected:
+ static cMutex* m_pMutex;
+ uint32_t m_nextPts;
+
+ static void Lock()
+ {
+ cDxr3NextPts::m_pMutex->Lock();
+ }
+ static void Unlock()
+ {
+ cDxr3NextPts::m_pMutex->Unlock();
+ }
+
+private:
+ cDxr3NextPts(cDxr3NextPts&); // no copy constructor
+};
+
+#endif /*_DXR3NEXTPTS_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3osd.c b/dxr3osd.c
new file mode 100644
index 0000000..2be8398
--- /dev/null
+++ b/dxr3osd.c
@@ -0,0 +1,48 @@
+/*
+ * dxr3osd.c
+ *
+ * Copyright (C) 2002 Stefan Schluenss
+ * Copyright (C) 2004 Christian Gmeiner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <linux/em8300.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/unistd.h>
+
+#include "dxr3vdrincludes.h"
+#include "dxr3interface.h"
+
+#include "dxr3osd.h"
+#include "dxr3interface_spu_encoder.h"
+
+#include "dxr3osd_subpicture.h"
+
+// ==================================
+// ! create osd at (Left, Top)
+cOsd *cDxr3OsdProvider::CreateOsd(int Left, int Top)
+{
+ return new cDxr3SubpictureOsd(Left, Top);
+}
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3osd.h b/dxr3osd.h
new file mode 100644
index 0000000..53e5d0f
--- /dev/null
+++ b/dxr3osd.h
@@ -0,0 +1,23 @@
+#ifndef _DXR3_OSD_H_
+#define _DXR3_OSD_H_
+
+#include "dxr3vdrincludes.h"
+#include "dxr3interface_spu_encoder.h"
+
+// ==================================
+// osd plugin provider
+class cDxr3OsdProvider : public cOsdProvider
+{
+public:
+ cDxr3OsdProvider() {}
+ virtual cOsd *CreateOsd(int Left, int Top);
+};
+
+#endif /*_DXR3_OSD_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3osd_subpicture.c b/dxr3osd_subpicture.c
new file mode 100644
index 0000000..65f20c3
--- /dev/null
+++ b/dxr3osd_subpicture.c
@@ -0,0 +1,265 @@
+#include "dxr3osd_subpicture.h"
+
+// Enables some time measure debugging code
+// (taken from the osdteletext plugin, thanks folks)
+#ifdef timingdebug
+#include <sys/timeb.h>
+class cTime
+{
+ // Debugging: Simple class to measure time
+ timeb start;
+public:
+ void Start()
+ {
+ ftime(&start);
+ }
+ void Stop(char *txt)
+ {
+ timeb t;
+ ftime(&t);
+ int s = t.time-start.time;
+ int ms = t.millitm - start.millitm;
+ if (ms<0)
+ {
+ s--;
+ ms += 1000;
+ }
+ printf("%s: %i.%03i\n", txt, s, ms);
+ }
+};
+#endif
+
+#define MAXNUMWINDOWS 7 // OSD windows are counted 1...7
+
+// ==================================
+//! constructor
+cDxr3SubpictureOsd::cDxr3SubpictureOsd(int Left, int Top) : cOsd(Left, Top)
+{
+ shown = false;
+ Palette = new cPalette(4);
+#if VDRVERSNUM >= 10318
+ last = new cTimeMs();
+ last->Set(-cDxr3ConfigData::Instance().GetOsdFlushRate());
+#else
+ last = time_ms() - cDxr3ConfigData::Instance().GetOsdFlushRate();
+#endif
+ Spu = &cSPUEncoder::Instance();
+
+ //Clears the OSD screen image
+ Spu->Clear();
+}
+
+// ==================================
+cDxr3SubpictureOsd::~cDxr3SubpictureOsd()
+{
+ //Remove the OSD from the screen
+ Spu->StopSpu();
+ delete Palette;
+#if VDRVERSNUM >= 10318
+ delete last;
+#endif
+}
+
+// ==================================
+eOsdError cDxr3SubpictureOsd::CanHandleAreas(const tArea *Areas, int NumAreas)
+{
+
+ eOsdError Result = cOsd::CanHandleAreas(Areas, NumAreas);
+ if (Result == oeOk)
+ {
+ if (NumAreas > MAXNUMWINDOWS)
+ {
+ return oeTooManyAreas;
+ }
+
+ for (int i = 0; i < NumAreas; i++)
+ {
+ if (Areas[i].bpp != 1 &&
+ Areas[i].bpp != 2 &&
+ Areas[i].bpp != 4 &&
+ Areas[i].bpp != 8)
+ {
+ return oeBppNotSupported;
+ }
+
+ if ((Areas[i].Width() & (8 / Areas[i].bpp - 1)) != 0)
+ {
+ return oeWrongAlignment;
+ }
+ }
+ }
+ return Result;
+}
+
+// ==================================
+void cDxr3SubpictureOsd::Flush()
+{
+#if VDRVERSNUM >= 10318
+ if (last->Elapsed() < cDxr3ConfigData::Instance().GetOsdFlushRate())
+ return;
+ last->Set();
+#else
+ if (time_ms() - last < cDxr3ConfigData::Instance().GetOsdFlushRate())
+ return;
+ last = time_ms();
+#endif
+
+#ifdef timingdebug
+ cTime t;
+ t.Start();
+#endif
+
+ cBitmap *Bitmap;
+ int oldi;
+ int newi;
+ int i;
+ int indexfree[16];
+ int firstfree = -1;
+ int indexnoassigned[16];
+ int firstnoassigned = -1;
+ bool colfree[16];
+ int NumNewColors;
+ int NumOldColors;
+
+ //determine the palette used by all bitmaps (without alpha channel)
+
+ cPalette *newPalette = new cPalette(4);
+ for (i = 0; i < 16; i++)
+ colfree[i]=true;
+ for (i = 0; (Bitmap = GetBitmap(i)) != NULL; i++)
+ {
+ int nc;
+ const tColor *col = Bitmap->Colors(nc);
+ if (col)
+ for (int kk = 0; kk < nc; kk++)
+ newPalette->Index(col[kk] & 0x00FFFFFF);
+ }
+ const tColor *newColors = newPalette->Colors(NumNewColors);
+ const tColor *oldColors = Palette->Colors(NumOldColors);
+ // colors already assigned
+ for (newi = 0; newi < NumNewColors; newi++)
+ {
+ for (oldi = 0; oldi < NumOldColors; oldi++)
+ {
+ if (newColors[newi] == oldColors[oldi])
+ {
+ colfree[oldi] = false;
+ break;
+ }
+ }
+ if (oldi >= NumOldColors)
+ {
+ firstnoassigned++;
+ indexnoassigned[firstnoassigned] = newi;
+ }
+ }
+ // unused colors
+ for (i = 0; i < NumOldColors; i++)
+ {
+ if (colfree[i]) {
+ firstfree++;
+ indexfree[firstfree] = i;
+ }
+ }
+ // replace unused colors with unassigned ones
+ for (i = 0; i <= firstnoassigned; i++)
+ {
+ newi = indexnoassigned[i];
+ if (firstfree >= 0)
+ {
+ Palette->SetColor(indexfree[firstfree], newColors[newi]);
+ firstfree--;
+ } else {
+ Palette->Index(newColors[newi]);
+ }
+ }
+ delete newPalette;
+
+ // Shove the bitmaps to the OSD global bitmap
+ for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++)
+ {
+ int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+ if (Bitmap->Dirty(x1, y1, x2, y2))
+ {
+ /* TODO workaround:
+ apparently the bitmap sent to the driver always has to be a
+ multiple of 8 bits wide, and (dx * dy) also has to be a
+ multiple of 8. Fix driver (should be able to handle any size
+ bitmaps!)
+ This isn't actually necessary with this plugin, but since other
+ plugins rely on this behaviour to work correctly, I left it
+ here. It doesn't hurt too much.
+ */
+
+// http://article.gmane.org/gmane.linux.vdr/21572
+//#define optimize_bitmap_transfer
+#ifdef optimize_bitmap_transfer
+ while ((x1 > 0 || x2 < Bitmap->Width() - 1) &&
+ ((x2 - x1) & 7) != 7)
+ {
+ if (x2 < Bitmap->Width() - 1)
+ {
+ x2++;
+ }
+ else if (x1 > 0)
+ {
+ x1--;
+ }
+ }
+
+ //TODO "... / 2" <==> Bpp???
+ while ((y1 > 0 || y2 < Bitmap->Height() - 1) &&
+ (((x2 - x1 + 1) * (y2 - y1 + 1) / 2) & 7) != 0)
+ {
+ if (y2 < Bitmap->Height() - 1)
+ {
+ y2++;
+ }
+ else if (y1 > 0)
+ {
+ y1--;
+ }
+ }
+
+ while ((x1 > 0 || x2 < Bitmap->Width() - 1) &&
+ (((x2 - x1 + 1) * (y2 - y1 + 1) / 2) & 7) != 0)
+ {
+ if (x2 < Bitmap->Width() - 1)
+ {
+ x2++;
+ }
+ else if (x1 > 0)
+ {
+ x1--;
+ }
+ }
+#else
+ x1 = 0;
+ y1 = 0;
+ x2 = Bitmap->Width() - 1;
+ y2 = Bitmap->Height() - 1;
+#endif
+
+ Spu->SetPalette(i + 1, Palette, Bitmap);
+ int origx = Left() + Bitmap->X0();
+ int origy = Top() + Bitmap->Y0();
+ Spu->CopyBlockIntoOSD(i + 1, Bitmap->Width(), origx + x1,
+ origy + y1, origx + x2, origy + y2,
+ Bitmap->Data(x1, y1));
+ Bitmap->Clean();
+ }
+ }
+
+ Spu->Flush(Palette);
+ shown = true;
+#ifdef timingdebug
+ t.Stop("cDxr3SubpictureOsd::Flush");
+#endif
+}
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3osd_subpicture.h b/dxr3osd_subpicture.h
new file mode 100644
index 0000000..33a5a81
--- /dev/null
+++ b/dxr3osd_subpicture.h
@@ -0,0 +1,37 @@
+#ifndef _DXR3OSD_SUBPICTURE_H_
+#define _DXR3OSD_SUBPICTURE_H_
+
+#include "dxr3vdrincludes.h"
+#include "dxr3interface_spu_encoder.h"
+
+// ==================================
+// osd interface
+class cDxr3SubpictureOsd : public cOsd
+{
+private:
+ cSPUEncoder* Spu; ///< interface to cSPUEncoder
+ bool shown; ///< is the osd shown?
+ cPalette* Palette; ///< global palette (needed by all bitmaps)
+#if VDRVERSNUM >= 10318
+ cTimeMs *last;
+#else
+ int last;
+#endif
+
+public:
+ cDxr3SubpictureOsd(int Left, int Top/*, int SpuDev*/);
+ ~cDxr3SubpictureOsd();
+
+ eOsdError CanHandleAreas(const tArea *Areas, int NumAreas);
+
+ void Flush();
+};
+
+#endif /*_DXR3OSD_SUBPICTURE_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3outputthread.c b/dxr3outputthread.c
new file mode 100644
index 0000000..5bfc7ac
--- /dev/null
+++ b/dxr3outputthread.c
@@ -0,0 +1,239 @@
+/*
+ * dxr3outputthread.c
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <time.h>
+#include "dxr3outputthread.h"
+
+// ==================================
+const int AUDIO_OFFSET = 4500;
+#define SCR m_dxr3Device.GetSysClock()
+// ==================================
+
+// ==================================
+//! constructor
+cDxr3OutputThread::cDxr3OutputThread(cDxr3Interface& dxr3Device,
+ cDxr3SyncBuffer& buffer) :
+ cThread(),
+ m_dxr3Device(dxr3Device),
+ m_buffer(buffer),
+ m_bStopThread(false),
+ m_bNeedResync(false)
+{
+}
+
+// ==================================
+//! send stop signal
+void cDxr3OutputThread::SetStopSignal()
+{
+ Lock();
+ m_bStopThread = true;
+ Unlock();
+}
+
+// ==================================
+//! was stop signal send?
+bool cDxr3OutputThread::GetStopSignal()
+{
+ bool ret = false;
+ Lock();
+ ret = m_bStopThread;
+ Unlock();
+
+ return ret;
+}
+
+// ==================================
+//! constr.
+cDxr3AudioOutThread::cDxr3AudioOutThread(cDxr3Interface& dxr3Device,
+ cDxr3SyncBuffer& buffer) :
+ cDxr3OutputThread(dxr3Device, buffer)
+{
+ SetDescription("DXR3 audio output");
+}
+
+//! destructor
+cDxr3AudioOutThread::~cDxr3AudioOutThread()
+{
+ m_buffer.Stop();
+ SetStopSignal();
+ Cancel(3);
+}
+
+// ==================================
+//! thread action
+void cDxr3AudioOutThread::Action()
+{
+ bool resync = false;
+ uint32_t pts = 0;
+
+ while (!GetStopSignal())
+ {
+ pts = 0;
+ cFixedLengthFrame* pNext = m_buffer.Get();
+
+ if (pNext) pts = pNext->GetPts();
+
+ if (pts && abs((int)pts-(int)SCR) > 30000 ||
+ m_dxr3Device.IsExternalReleased())
+ {
+ m_buffer.Clear();
+ m_bNeedResync = true;
+ }
+ else if (pNext)
+ {
+ if (!pts || pts < SCR)
+ {
+ if (!pts && resync)
+ {
+ continue;
+ }
+ else
+ {
+ resync = false;
+ }
+
+ if (pts && (pts < SCR) && ((SCR - pts) > 5000))
+ {
+ m_dxr3Device.SetSysClock(pts + 1 * AUDIO_OFFSET);
+ m_dxr3Device.PlayAudioFrame(pNext);
+ if (m_buffer.IsPolled())
+ {
+ m_buffer.Clear();
+ m_bNeedResync = true;
+ }
+ }
+ else
+ {
+ m_dxr3Device.PlayAudioFrame(pNext);
+ m_buffer.Pop();
+ }
+ }
+ else
+ {
+ if (abs((int)pts - (int)SCR) < (AUDIO_OFFSET ))
+ {
+ m_dxr3Device.PlayAudioFrame(pNext);
+ m_buffer.Pop();
+ }
+ }
+ }
+
+ if ((pts > SCR && abs((int)pts - (int)SCR) > AUDIO_OFFSET))
+ {
+ usleep(10000);
+ }
+ }
+}
+
+// ==================================
+//! constr.
+cDxr3VideoOutThread::cDxr3VideoOutThread(cDxr3Interface& dxr3Device,
+ cDxr3SyncBuffer& buffer) :
+ cDxr3OutputThread(dxr3Device, buffer)
+{
+ SetDescription("DXR3 video output");
+}
+
+//! destructor
+cDxr3VideoOutThread::~cDxr3VideoOutThread()
+{
+ m_buffer.Stop();
+ SetStopSignal();
+ Cancel(3);
+}
+
+// ==================================
+//! thread action
+void cDxr3VideoOutThread::Action()
+{
+ uint32_t pts = 0;
+ static uint32_t lastPts = 0;
+
+ while (!GetStopSignal())
+ {
+ cFixedLengthFrame* pNext = m_buffer.Get();
+ if (pNext)
+ {
+ pts = pNext->GetPts();
+ if (pts == lastPts)
+ pts = 0;
+
+ if (pts > SCR && abs((int)pts - (int)SCR) < 7500)
+ {
+ m_dxr3Device.SetPts(pts);
+ }
+
+ if (!pts || pts < SCR)
+ {
+ if (m_buffer.Available())
+ {
+ m_dxr3Device.PlayVideoFrame(pNext);
+ m_buffer.Pop();
+ }
+ }
+ else
+ {
+ if ((pts > SCR) && abs((int)pts - (int)SCR) < 7500)
+ {
+ m_dxr3Device.SetPts(pts);
+
+ if (m_buffer.Available() && pNext->GetData() &&
+ pNext->GetCount())
+ {
+ m_dxr3Device.PlayVideoFrame(pNext);
+ m_buffer.Pop();
+ }
+ }
+ else
+ {
+ if (pts < SCR)
+ {
+ m_dxr3Device.PlayVideoFrame(pNext);
+ m_buffer.Pop();
+ }
+ }
+ }
+
+
+ if (m_dxr3Device.IsExternalReleased())
+ {
+ m_bNeedResync = true;
+ m_buffer.Clear();
+ }
+
+ if ((pts > SCR && abs((int)pts - (int)SCR) > 7500 ))
+ {
+ usleep(10000);
+ }
+ }
+ }
+}
+
+#undef SCR
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3outputthread.h b/dxr3outputthread.h
new file mode 100644
index 0000000..8ac46ee
--- /dev/null
+++ b/dxr3outputthread.h
@@ -0,0 +1,104 @@
+/*
+ * dxr3outputthread.h
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _DXR3OUTPUTTHREAD_H_
+#define _DXR3OUTPUTTHREAD_H_
+
+#include "dxr3vdrincludes.h"
+#include "dxr3syncbuffer.h"
+#include "dxr3audiodecoder.h"
+
+// ==================================
+class cDxr3OutputThread : public cThread
+{
+public:
+ cDxr3OutputThread(cDxr3Interface& dxr3Device, cDxr3SyncBuffer& buffer);
+ virtual ~cDxr3OutputThread()
+ {
+ Cancel();
+ };
+ /*
+ virtual void Start(void)
+ {
+ cThread::Start();
+ };
+ */
+ void SetStopSignal();
+ bool NeedResync()
+ {
+ return m_bNeedResync;
+ };
+ void ClearResyncRequest()
+ {
+ m_bNeedResync = false;
+ };
+
+protected:
+ virtual void Action() = 0;
+ bool GetStopSignal();
+
+ cDxr3Interface& m_dxr3Device;
+ cDxr3SyncBuffer& m_buffer;
+ bool m_bStopThread;
+ bool m_bNeedResync;
+
+private:
+ cDxr3OutputThread(cDxr3OutputThread&); // no copy contructor
+};
+
+// ==================================
+class cDxr3AudioOutThread : public cDxr3OutputThread
+{
+public:
+ cDxr3AudioOutThread(cDxr3Interface& dxr3Device, cDxr3SyncBuffer& buffer);
+ virtual ~cDxr3AudioOutThread();
+
+protected:
+ void Action();
+
+private:
+ //cDxr3AudioOutThread(); // no standard constructor
+ cDxr3AudioOutThread(cDxr3AudioOutThread&); // no copy constructor
+};
+
+// ==================================
+class cDxr3VideoOutThread : public cDxr3OutputThread
+{
+public:
+ cDxr3VideoOutThread(cDxr3Interface& dxr3Device, cDxr3SyncBuffer& buffer);
+ virtual ~cDxr3VideoOutThread();
+
+protected:
+ void Action();
+
+private:
+ //cDxr3VideoOutThread(); // no standard constructor
+ cDxr3VideoOutThread(cDxr3VideoOutThread&); // no copy constructor
+};
+
+#endif /*_DXR3OUTPUTTHREAD_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3pesframe.c b/dxr3pesframe.c
new file mode 100644
index 0000000..8bf5fe3
--- /dev/null
+++ b/dxr3pesframe.c
@@ -0,0 +1,273 @@
+/*
+ * dxr3pesframe.c
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "dxr3pesframe.h"
+
+#include <linux/em8300.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <vdr/tools.h>
+
+// ==================================
+bool cDxr3PesFrame::ExtractNextFrame(const uint8_t* pBuf, uint32_t length)
+ throw (ePesFrameError)
+{
+ cDxr3SafeArray<uint8_t> pesArray((uint8_t*)pBuf, length);
+ uint32_t pos = 0;
+ m_pNextStart = pBuf;
+ m_remainingLength = length;
+
+ InitData();
+
+ try
+ {
+ if (length > 9)
+ {
+ for (; pos + 9 < length && !IsPesHeader(pesArray.SubArray(pos, 4)); pos++);
+ if (pos + 9 >= length)
+ {
+ // Corrupt stream?
+ m_remainingLength = 0;
+ return m_bValid;
+ }
+ m_pPesStart = pBuf + pos;
+
+ if ((pesArray[pos + 6] & 0xC0) == 0x80
+ /*|| (pesArray[pos + 6] & 0xC0) == 0x00*/)
+ {
+ if (pos + 9 + pesArray[pos + 8] < length)
+ {
+ m_pEsStart = pBuf + pos + 9 + pesArray[pos + 8];
+ if ((((int)pesArray[pos + 4]) * (int)256 + (int)pesArray[pos + 5]) > 0)
+ {
+ m_esLength = ((int)pesArray[pos + 4]) *
+ (int)256 + (int)pesArray[pos + 5] + (int)6 -
+ (9 + (int)pesArray[pos + 8]);
+ if (pos + 9 + pesArray[pos + 8] + m_esLength <= length)
+ {
+ m_bValid = true;
+ m_pNextStart = m_pEsStart + m_esLength;
+ m_remainingLength = pBuf + length - (m_pEsStart + m_esLength);
+ if (pesArray[pos + 6] >> 6 == 2 &&
+ pesArray[pos + 7] >> 7 != 0)
+ {
+ ExtractPts(pesArray.SubArray(pos + 9, 5));
+ }
+ if (m_pesDataType == PES_VIDEO_DATA)
+ {
+ int retval = ExtractVideoData(pesArray.SubArray(pos + 9 + pesArray[pos + 8], m_esLength));
+ if (m_videoFrameType != UNKNOWN_FRAME && retval)
+ m_offset = retval + pos + 9 + pesArray[pos + 8];
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ uint32_t fpos = pos + 6;
+ m_esLength = ((int)pesArray[pos + 4]) * (int)256 + (int)pesArray[pos + 5];
+ if (length >= pos + 6 + m_esLength)
+ {
+ while (pesArray[fpos] == 0xff)
+ ++fpos; // skip stuffing bytes
+ if ((pesArray[fpos] & 0xC0) == 0x40)
+ fpos += 2; // skip std buffer scale and size
+ if ((pesArray[fpos] & 0xF0) == 0x20)
+ {
+ // pts only
+ ExtractPts(pesArray.SubArray(fpos, 5));
+ fpos += 5;
+ }
+ else if ((pesArray[fpos] & 0xF0) == 0x30)
+ {
+ // pts and dts
+ ExtractPts(pesArray.SubArray(fpos, 5));
+ fpos += 10;
+ }
+ else
+ {
+ ++fpos;
+ }
+
+ if (m_esLength) m_esLength = m_esLength - (fpos - pos - 6);
+ m_pEsStart = pBuf + fpos;
+ m_pNextStart = m_pEsStart + m_esLength;
+ m_remainingLength = pBuf + length - (m_pEsStart + m_esLength);
+ m_bValid = true;
+ if (m_pesDataType == PES_VIDEO_DATA)
+ {
+ int retval = ExtractVideoData(pesArray.SubArray(fpos, m_esLength));
+ if (m_videoFrameType != UNKNOWN_FRAME && retval)
+ m_offset = 0;
+ }
+ }
+ }
+ }
+ }
+ catch (cDxr3SafeArray<uint8_t>::eSafeArrayException ex)
+ {
+ m_bValid = false;
+ esyslog("dxr3: general PES error");
+ throw(PES_GENERAL_ERROR);
+ }
+
+ return m_bValid;
+}
+
+// ==================================
+int cDxr3PesFrame::ExtractVideoData(cDxr3SafeArray<uint8_t> esFrame)
+ throw (cDxr3SafeArray<uint8_t>::eSafeArrayException)
+{
+ int retval = 0;
+ for (uint32_t i = 0; esFrame.GetLength() > (uint32_t) 8 && i < esFrame.GetLength() - 8; i++)
+ {
+ if (esFrame[i] == 0 && esFrame[i+1] == 0 && esFrame[i+2] == 1)
+ {
+ // start code
+ if ((esFrame[i + 3] & 0xFF) == 0x00)
+ {
+ // extract frame type
+ if (m_offset == 0) retval = i;
+ switch ((esFrame[ i + 5] >> 3) & 0x7)
+ {
+ case 0x1:
+ m_videoFrameType = I_FRAME;
+ break;
+
+ case 0x2:
+ m_videoFrameType = P_FRAME;
+ break;
+
+ case 0x3:
+ m_videoFrameType = B_FRAME;
+ break;
+
+ default:
+ m_videoFrameType = UNKNOWN_FRAME;
+ break;
+ }
+ }
+ else if ((esFrame[i + 3] & 0xFF) == 0xB3)
+ {
+ // aspect ratio
+ switch ((esFrame[i + 7]) & 0xF0)
+ {
+ case 0x20:
+ m_staticAspectRatio = m_aspectRatio = ASPECTRATIO_4_3;
+ break;
+
+ case 0x30:
+ m_staticAspectRatio = m_aspectRatio = ASPECTRATIO_16_9;
+ break;
+
+ default:
+ break;
+ }
+ m_staticHorizontalSize = m_horizontalSize = (esFrame[i + 5] & 0xF0) >> 4 | esFrame[i + 4] << 4;
+ m_staticVerticalSize = m_verticalSize = ((esFrame[i + 5] & 0x0F) << 8) | (esFrame[i + 6]);
+ }
+ }
+ }
+ return retval;
+}
+
+// ==================================
+void cDxr3PesFrame::ExtractPts(cDxr3SafeArray<uint8_t> ptsData)
+ throw (cDxr3SafeArray<uint8_t>::eSafeArrayException)
+{
+ m_pts = ((ptsData[0] >> 1) & 0x07) << 29;
+ m_pts |= ptsData[1] << 21;
+ m_pts |= (ptsData[2] >> 1) << 14;
+ m_pts |= ptsData[3] << 6;
+ m_pts |= ptsData[4] >> 2;
+}
+
+// ==================================
+bool cDxr3PesFrame::IsPesHeader(cDxr3SafeArray<uint8_t> header)
+ throw (cDxr3SafeArray<uint8_t>::eSafeArrayException)
+{
+ bool ret = false;
+
+ if (!header[0] && !header[1] && header[2] == 0x01 )
+ {
+ ret = true;
+ switch (header[3])
+ {
+ case 0xC0 ... 0xDF: // audio stream
+ m_pesDataType = PES_AUDIO_DATA;
+ break;
+
+ case 0xE0 ... 0xEF: // video stream
+ m_pesDataType = PES_VIDEO_DATA;
+ break;
+
+ case 0xBD: // private stream 1
+ m_pesDataType = PES_PRIVATE_DATA;
+ break;
+
+ case 0xBA:
+ ret = false;
+ break;
+
+ case 0xBE: // padding stream
+ ret = false;
+ break;
+
+ case 0xBC: // program stream map
+ case 0xBF: // private stream 2
+ case 0xF0: // ECM stream
+ case 0xF1: // EMM stream
+ case 0xF2: // DSMCC stream
+ case 0xF3: // 13522 stream
+ case 0xF4: // H.22.1 type A
+ case 0xF5: // H.22.1 type B
+ case 0xF6: // H.22.1 type C
+ case 0xF7: // H.22.1 type D
+ case 0xF8: // H.22.1 type E
+ case 0xF9: // ancillary stream
+ case 0xFA ... 0xFE: // reserved data stream
+ case 0xFF: // program stream directory
+ break;
+ default:
+ ret = false;
+ break;
+ }
+ m_streamId = header[3];
+ }
+
+ return ret;
+}
+
+// ==================================
+uint32_t cDxr3PesFrame::m_staticAspectRatio = EM8300_ASPECTRATIO_4_3;
+uint32_t cDxr3PesFrame::m_staticHorizontalSize = 720;
+uint32_t cDxr3PesFrame::m_staticVerticalSize = 576;
+const uint32_t cDxr3PesFrame::MAX_PES_HEADER_SIZE = 184;
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3pesframe.h b/dxr3pesframe.h
new file mode 100644
index 0000000..26e334a
--- /dev/null
+++ b/dxr3pesframe.h
@@ -0,0 +1,268 @@
+/*
+ * dxr3pesframe.h
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _DXR3PESFRAME_H_
+#define _DXR3PESFRAME_H_
+
+#include <assert.h>
+#include <stdint.h>
+
+// ==================================
+const int ASPECTRATIO_4_3 = 0;
+const int ASPECTRATIO_16_9 = 1;
+
+// ==================================
+enum eVideoFrameType
+{
+ I_FRAME,
+ P_FRAME,
+ B_FRAME,
+ UNKNOWN_FRAME
+};
+
+// ==================================
+// XXX: Should we use here std:vector?
+template <class T>
+class cDxr3SafeArray
+{
+public:
+ // ==================================
+ enum eSafeArrayException
+ {
+ SAFE_ARRAY_INDEX_OUT_OF_BOUND
+ };
+
+ cDxr3SafeArray(T* pBuf, uint32_t length) :
+ m_pBuf(pBuf), m_length(length) {};
+ cDxr3SafeArray(const cDxr3SafeArray& from) :
+ m_pBuf(from.m_pBuf), m_length(from.m_length) {};
+ virtual ~cDxr3SafeArray() {};
+
+ T& operator[](uint32_t index) throw (eSafeArrayException)
+ {
+ if (index >= m_length)
+ throw(SAFE_ARRAY_INDEX_OUT_OF_BOUND);
+ return m_pBuf[index];
+ };
+ cDxr3SafeArray SubArray(uint32_t offset, uint32_t length)
+ {
+ if (offset + length > m_length)
+ throw(SAFE_ARRAY_INDEX_OUT_OF_BOUND);
+ return cDxr3SafeArray(m_pBuf + offset, length);
+ };
+
+ uint32_t GetLength(void)
+ {
+ return m_length;
+ };
+
+protected:
+ T* m_pBuf;
+ uint32_t m_length;
+
+private:
+ cDxr3SafeArray(); // no standard constructor
+};
+
+
+// ==================================
+// pes - packetized elementary stream
+class cDxr3PesFrame
+{
+public:
+
+ // ==================================
+ enum ePesDataType
+ {
+ PES_AUDIO_DATA,
+ PES_VIDEO_DATA,
+ PES_PRIVATE_DATA,
+ PES_UNKNOWN_DATA
+ };
+
+ // ==================================
+ enum ePesFrameError
+ {
+ PES_GENERAL_ERROR
+ };
+
+public:
+ cDxr3PesFrame() :
+ m_pesDataType(PES_UNKNOWN_DATA),
+ m_bValid(false),
+ m_pPesStart(0),
+ m_pEsStart(0),
+ m_esLength(0),
+ m_pts(0),
+ m_videoFrameType(UNKNOWN_FRAME),
+ m_aspectRatio(m_staticAspectRatio),
+ m_horizontalSize(m_staticHorizontalSize),
+ m_verticalSize(m_staticVerticalSize),
+ m_streamId(0),
+ m_pNextStart(0),
+ m_remainingLength(0),
+ m_offset(0) {};
+
+ virtual ~cDxr3PesFrame() {}
+
+ bool ExtractNextFrame(const uint8_t* pBuf, uint32_t length)
+ throw (ePesFrameError);
+
+ ePesDataType GetPesDataType(void) const
+ {
+ assert(m_bValid);
+ return m_pesDataType;
+ };
+ const uint8_t* GetPesStart(void) const
+ {
+ assert(m_bValid);
+ return m_pPesStart;
+ };
+ const uint8_t* GetEsStart(void) const
+ {
+ assert(m_bValid);
+ return m_pEsStart;
+ };
+ uint32_t GetEsLength(void) const
+ {
+ assert(m_bValid);
+ return m_esLength;
+ };
+
+ const uint8_t* GetNextStart(void) const
+ {
+ return m_pNextStart;
+ };
+ uint32_t GetRemainingLength(void) const
+ {
+ return m_remainingLength;
+ };
+
+ uint32_t GetPts(void) const
+ {
+ assert(m_bValid);
+ return m_pts;
+ };
+
+ eVideoFrameType GetFrameType(void) const
+ {
+ assert(m_bValid);
+ assert(m_pesDataType == PES_VIDEO_DATA);
+ return m_videoFrameType;
+ };
+ uint32_t GetAspectRatio(void) const
+ {
+ assert(m_bValid);
+ assert(m_pesDataType == PES_VIDEO_DATA);
+ return m_aspectRatio;
+ };
+ uint32_t GetHorizontalSize(void) const
+ {
+ assert(m_bValid);
+ assert(m_pesDataType == PES_VIDEO_DATA);
+ return m_horizontalSize;
+ };
+ uint32_t GetVerticalSize(void) const
+ {
+ assert(m_bValid);
+ assert(m_pesDataType == PES_VIDEO_DATA);
+ return m_verticalSize;
+ };
+ uint8_t GetStreamId(void) const
+ {
+ assert(m_bValid);
+ assert(m_pesDataType == PES_VIDEO_DATA);
+ return m_streamId;
+ };
+ int GetOffset(void) const
+ {
+ assert(m_bValid);
+ return m_offset;
+ };
+
+ bool IsValid(void)
+ {
+ return m_bValid;
+ };
+
+protected:
+ bool IsPesHeader(cDxr3SafeArray<uint8_t> header)
+ throw (cDxr3SafeArray<uint8_t>::eSafeArrayException);
+ void ExtractPts(cDxr3SafeArray<uint8_t> ptsData)
+ throw (cDxr3SafeArray<uint8_t>::eSafeArrayException);
+ int ExtractVideoData(cDxr3SafeArray<uint8_t> esFrame)
+ throw (cDxr3SafeArray<uint8_t>::eSafeArrayException);
+
+ void InitData(void)
+ {
+ m_pesDataType = PES_UNKNOWN_DATA;
+ m_bValid = false;
+ m_pPesStart = 0;
+ m_pEsStart = 0;
+ m_esLength = 0;
+ m_pts = 0;
+ m_videoFrameType = UNKNOWN_FRAME;
+ m_aspectRatio = m_staticAspectRatio;
+ m_horizontalSize = m_staticHorizontalSize;
+ m_verticalSize = m_staticVerticalSize;
+ m_streamId = 0;
+ m_pNextStart = 0;
+ m_remainingLength = 0;
+ m_offset = 0;
+ }
+
+ ePesDataType m_pesDataType;
+ bool m_bValid;
+ const uint8_t* m_pPesStart;
+ const uint8_t* m_pEsStart;
+ uint32_t m_esLength;
+ uint32_t m_pts;
+
+ eVideoFrameType m_videoFrameType;
+ uint32_t m_aspectRatio;
+ uint32_t m_horizontalSize;
+ uint32_t m_verticalSize;
+ uint8_t m_streamId;
+
+ const uint8_t* m_pNextStart;
+ uint32_t m_remainingLength;
+ int m_offset;
+
+ static uint32_t m_staticAspectRatio;
+ static uint32_t m_staticHorizontalSize;
+ static uint32_t m_staticVerticalSize;
+
+protected:
+ static const uint32_t MAX_PES_HEADER_SIZE;
+
+private:
+ cDxr3PesFrame(cDxr3PesFrame&); // no copy constructor
+
+};
+
+#endif /*_DXR3PESFRAME_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3singleton.h b/dxr3singleton.h
new file mode 100644
index 0000000..b289328
--- /dev/null
+++ b/dxr3singleton.h
@@ -0,0 +1,59 @@
+/*
+ * dxr3singleton.h
+ *
+ * Copyright (C) 2004 Christian Gmeiner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _DXR3_SINGLETON_H_
+#define _DXR3_SINGLETON_H_
+
+// ==================================
+//! A singleton template.
+/*!
+ Is a nice solution to use only
+ one instance of a class.
+*/
+template<typename T>
+class Singleton
+{
+protected:
+ Singleton() {}
+ virtual ~Singleton() {}
+
+public:
+ static T& Instance()
+ {
+ static T m_Instance;
+ return m_Instance;
+ }
+
+ static T* InstanceP()
+ {
+ static T* m_InstanceP = new T;
+ return m_InstanceP;
+ }
+};
+
+#endif /*_DXR3_SINGLETON_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3spudecoder.c b/dxr3spudecoder.c
new file mode 100644
index 0000000..1013216
--- /dev/null
+++ b/dxr3spudecoder.c
@@ -0,0 +1,640 @@
+/*
+ * dxr3spudecoder.c
+ *
+ * Copyright (C) 2004 Christian Gmeiner
+ *
+ * Orginal:
+ * Copyright (C) 2001.2002 Andreas Schultz <aschultz@warp10.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include "dxr3spudecoder.h"
+#include "dxr3interface.h"
+#include "dxr3tools.h"
+
+// ==================================
+#define CMD_SPU_MENU 0x00
+#define CMD_SPU_SHOW 0x01
+#define CMD_SPU_HIDE 0x02
+#define CMD_SPU_SET_PALETTE 0x03
+#define CMD_SPU_SET_ALPHA 0x04
+#define CMD_SPU_SET_SIZE 0x05
+#define CMD_SPU_SET_PXD_OFFSET 0x06
+#define CMD_SPU_CHG_COLCON 0x07
+#define CMD_SPU_EOF 0xff
+
+#define spuU32(i) ((spu[i] << 8) + spu[i+1])
+
+
+/*
+ * cDxr3Spubitmap:
+ *
+ * this is a bitmap of the full screen and two palettes
+ * the normal palette for the background and the highlight palette
+ *
+ * Inputs:
+ * - a SPU rle encoded image on creation, which will be decoded into
+ * the full screen indexed bitmap
+ *
+ * Output:
+ * - a minimal sized cDxr3SpuBitmap a given palette, the indexed bitmap
+ * will be scanned to get the smallest possible resulting bitmap considering
+ * transparencies
+ */
+
+// ==================================
+void cDxr3SpuPalette::setPalette(const uint32_t * pal)
+{
+ for (int i = 0; i < 16; i++)
+ palette[i] = Tools::YUV2Rgb(pal[i]);
+}
+
+// ==================================
+#define setMin(a, b) if (a > b) a = b
+#define setMax(a, b) if (a < b) a = b
+
+#define spuXres 720
+#define spuYres 576
+
+#define revRect(r1, r2) { r1.x1 = r2.x2; r1.y1 = r2.y2; r1.x2 = r2.x1; r1.y2 = r2.y1; }
+
+// ==================================
+cDxr3SpuBitmap::cDxr3SpuBitmap(sDxr3SpuRect size, uint8_t * fodd,
+ uint8_t * eodd, uint8_t * feven,
+ uint8_t * eeven)
+{
+ if (size.x1 < 0 || size.y1 < 0 || size.x2 >= spuXres || size.y2 >= spuYres)
+ throw;
+
+ bmpsize = size;
+ revRect(minsize[0], size);
+ revRect(minsize[1], size);
+ revRect(minsize[2], size);
+ revRect(minsize[3], size);
+
+ if (!(bmp = new uint8_t[spuXres * spuYres * sizeof(uint8_t)]))
+ throw;
+
+ memset(bmp, 0, spuXres * spuYres * sizeof(uint8_t));
+ putFieldData(0, fodd, eodd);
+ putFieldData(1, feven, eeven);
+}
+
+// ==================================
+cDxr3SpuBitmap::~cDxr3SpuBitmap()
+{
+ delete[]bmp;
+}
+
+// ==================================
+cBitmap *cDxr3SpuBitmap::getBitmap(const aDxr3SpuPalDescr paldescr,
+ const cDxr3SpuPalette & pal,
+ sDxr3SpuRect & size) const
+{
+ int h = size.height();
+ int w = size.width();
+
+ if (size.y1 + h >= spuYres)
+ {
+ h = spuYres - size.y1 - 1;
+ }
+ if (size.x1 + w >= spuXres)
+ {
+ w = spuXres - size.x1 - 1;
+ }
+
+ if (w & 0x03)
+ {
+ w += 4 - (w & 0x03);
+ }
+
+ cBitmap *ret = new cBitmap(w, h, 2);
+
+ // set the palette
+ for (int i = 0; i < 4; i++)
+ {
+ uint32_t color = pal.getColor(paldescr[i].index, paldescr[i].trans);
+ ret->SetColor(i, (tColor) color);
+ }
+
+ // set the content
+ for (int yp = 0; yp < h; yp++)
+ {
+ for (int xp = 0; xp < w; xp++)
+ {
+ uint8_t idx = bmp[(size.y1 + yp) * spuXres + size.x1 + xp];
+ ret->SetIndex(xp, yp, idx);
+ }
+ }
+ return ret;
+}
+
+// ==================================
+// find the minimum non-transparent area
+bool cDxr3SpuBitmap::getMinSize(const aDxr3SpuPalDescr paldescr,
+ sDxr3SpuRect & size) const
+{
+ bool ret = false;
+ for (int i = 0; i < 4; i++)
+ {
+ if (paldescr[i].trans != 0)
+ {
+ if (!ret)
+ {
+ size = minsize[i];
+ }
+ else
+ {
+ setMin(size.x1, minsize[i].x1);
+ setMin(size.y1, minsize[i].y1);
+ setMax(size.x2, minsize[i].x2);
+ setMax(size.y2, minsize[i].y2);
+ }
+ ret = true;
+ }
+ }
+ dsyslog("dxr3: getminsize: (%d,%d) x (%d,%d)",
+ size.x1, size.y1, size.x2, size.y2);
+ if (size.x1 > size.x2 || size.y1 > size.y2)
+ return false;
+ return ret;
+}
+
+// ==================================
+void cDxr3SpuBitmap::putPixel(int xp, int yp, int len, uint8_t colorid)
+{
+ memset(bmp + spuXres * yp + xp, colorid, len);
+ setMin(minsize[colorid].x1, xp);
+ setMin(minsize[colorid].y1, yp);
+ setMax(minsize[colorid].x2, xp + len - 1);
+ setMax(minsize[colorid].y2, yp + len - 1);
+}
+
+// ==================================
+static uint8_t getBits(uint8_t * &data, uint8_t & bitf)
+{
+ uint8_t ret = *data;
+ if (bitf)
+ {
+ ret >>= 4;
+ }
+ else
+ {
+ data++;
+ }
+
+ bitf ^= 1;
+
+ return (ret & 0xf);
+}
+
+// ==================================
+void cDxr3SpuBitmap::putFieldData(int field, uint8_t * data, uint8_t * endp)
+{
+ int xp = bmpsize.x1;
+ int yp = bmpsize.y1 + field;
+ uint8_t bitf = 1;
+
+ while (data < endp)
+ {
+ uint16_t vlc = getBits(data, bitf);
+ if (vlc < 0x0004)
+ {
+ vlc = (vlc << 4) | getBits(data, bitf);
+ if (vlc < 0x0010)
+ {
+ vlc = (vlc << 4) | getBits(data, bitf);
+ if (vlc < 0x0040)
+ {
+ vlc = (vlc << 4) | getBits(data, bitf);
+ }
+ }
+ }
+
+ uint8_t color = vlc & 0x03;
+ int len = vlc >> 2;
+
+ // if len == 0 -> end sequence - fill to end of line
+ len = len ? len : bmpsize.x2 - xp + 1;
+ putPixel(xp, yp, len, color);
+ xp += len;
+
+ if (xp > bmpsize.x2)
+ {
+ // nextLine
+ if (!bitf)
+ data++;
+ bitf = 1;
+ xp = bmpsize.x1;
+ yp += 2;
+ if (yp > bmpsize.y2)
+ return;
+ }
+ }
+}
+
+// ==================================
+// ! constructor
+cDxr3SpuDecoder::cDxr3SpuDecoder()
+{
+ clean = true;
+ scaleMode = eSpuNormal;
+ spu = NULL;
+ osd = NULL;
+ spubmp = NULL;
+ allowedShow = true;
+}
+
+// ==================================
+cDxr3SpuDecoder::~cDxr3SpuDecoder()
+{
+ delete spubmp;
+ delete spu;
+ delete osd;
+}
+
+// ==================================
+// ! send spu data to dxr3
+#if VDRVERSNUM >= 10318
+void cDxr3SpuDecoder::processSPU(uint32_t pts, uint8_t * buf, bool AllowedShow)
+#else
+void cDxr3SpuDecoder::processSPU(uint32_t pts, uint8_t * buf)
+#endif
+{
+ setTime(pts);
+ dsyslog("dxr3: spudec push: pts=%d", pts);
+
+ delete spubmp;
+ spubmp = NULL;
+ delete[]spu;
+ spu = buf;
+ spupts = pts;
+
+ DCSQ_offset = cmdOffs();
+ prev_DCSQ_offset = 0;
+
+ clean = true;
+#if VDRVERSNUM >= 10318
+ allowedShow = AllowedShow;
+#endif
+}
+
+// ==================================
+// ! get scalemode
+cSpuDecoder::eScaleMode cDxr3SpuDecoder::getScaleMode(void)
+{
+ return scaleMode;
+}
+
+// ==================================
+// ! set scalemode
+void cDxr3SpuDecoder::setScaleMode(cSpuDecoder::eScaleMode ScaleMode)
+{
+ scaleMode = ScaleMode;
+}
+
+// ==================================
+// ! send palette to dxr3
+void cDxr3SpuDecoder::setPalette(uint32_t * pal)
+{
+ palette.setPalette(pal);
+}
+
+// ==================================
+// ! send highlight to dxr3
+void cDxr3SpuDecoder::setHighlight(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint32_t palette)
+{
+ aDxr3SpuPalDescr pld;
+ for (int i = 0; i < 4; i++)
+ {
+ pld[i].index = 0xf & (palette >> (16 + 4 * i));
+ pld[i].trans = 0xf & (palette >> (4 * i));
+ }
+
+ bool ne = hlpsize.x1 != sx || hlpsize.y1 != sy ||
+ hlpsize.x2 != ex || hlpsize.y2 != ey ||
+ pld[0] != hlpDescr[0] || pld[1] != hlpDescr[1] ||
+ pld[2] != hlpDescr[2] || pld[3] != hlpDescr[3];
+
+ if (ne)
+ {
+ dsyslog("dxr3: spu highlight: %d, %d, %d, %d", sx, sy, ex, ey);
+
+ hlpsize.x1 = sx;
+ hlpsize.y1 = sy;
+ hlpsize.x2 = ex;
+ hlpsize.y2 = ey;
+ memcpy(hlpDescr, pld, sizeof(aDxr3SpuPalDescr));
+ highlight = true;
+ clean = false;
+ }
+}
+
+// ==================================
+// ! clear highlight
+void cDxr3SpuDecoder::clearHighlight()
+{
+ clean &= !highlight;
+ highlight = false;
+ hlpsize.x1 = -1;
+ hlpsize.y1 = -1;
+ hlpsize.x2 = -1;
+ hlpsize.y2 = -1;
+}
+
+// ==================================
+int cDxr3SpuDecoder::ScaleYcoord(int value)
+{
+ if (scaleMode == eSpuLetterBox)
+ {
+ int offset =
+ cDevice::PrimaryDevice()->GetVideoSystem() == vsPAL ? 72 : 60;
+ return lround((value * 3.0) / 4.0) + offset;
+ }
+ return value;
+}
+
+// ==================================
+int cDxr3SpuDecoder::ScaleYres(int value)
+{
+ if (scaleMode == eSpuLetterBox)
+ {
+ return lround((value * 3.0) / 4.0);
+ }
+ return value;
+}
+
+// ==================================
+void cDxr3SpuDecoder::DrawBmp(sDxr3SpuRect & size, cBitmap * bmp)
+{
+ int x2 = size.x2;
+ while ((x2 - size.x1 + 1) & 0x03)
+ x2++;
+ tArea Area = { size.x1, size.y1, x2, size.y2, 2 };
+ osd->SetAreas(&Area, 1);
+ if (x2 > size.x2)
+ osd->DrawRectangle(size.x2 + 1, size.y1, x2, size.y2, clrTransparent);
+ osd->DrawBitmap(size.x1, size.y1, *bmp);
+ delete bmp;
+}
+
+// ==================================
+// ! draw nav, subtitles, ...
+void cDxr3SpuDecoder::Draw()
+{
+ Hide();
+
+ if (!spubmp)
+ {
+ return;
+ }
+
+ cBitmap *fg = NULL;
+ cBitmap *bg = NULL;
+ sDxr3SpuRect bgsize;
+ sDxr3SpuRect hlsize;
+
+ hlsize.x1 = hlpsize.x1;
+ hlsize.y1 = ScaleYcoord(hlpsize.y1);
+ hlsize.x2 = hlpsize.x2;
+ hlsize.y2 = ScaleYcoord(hlpsize.y2);
+
+ if (highlight)
+ {
+ fg = spubmp->getBitmap(hlpDescr, palette, hlsize);
+ }
+
+ if (spubmp->getMinSize(palDescr, bgsize))
+ {
+ bg = spubmp->getBitmap(palDescr, palette, bgsize);
+ if (scaleMode == eSpuLetterBox)
+ {
+ // the coordinates have to be modified for letterbox
+ int y1 = ScaleYres(bgsize.y1) + bgsize.height();
+ bgsize.y2 = y1 + bgsize.height();
+ bgsize.y1 = y1;
+ }
+ }
+
+ if (bg || fg)
+ {
+ if (osd == NULL)
+ if ((osd = cOsdProvider::NewOsd(0, 0)) == NULL)
+ {
+ esyslog("dxr3: could not instantiate new OSD");
+ return;
+ }
+
+ if (fg)
+ {
+ DrawBmp(hlsize, fg);
+ }
+
+ if (bg)
+ {
+ DrawBmp(bgsize, bg);
+ }
+
+ osd->Flush();
+ }
+
+ clean = true;
+}
+
+// ==================================
+// ! hide nav, subtitles, ...
+void cDxr3SpuDecoder::Hide()
+{
+ delete osd;
+ osd = NULL;
+}
+
+// ==================================
+// ! clear highlight and osd
+void cDxr3SpuDecoder::Empty()
+{
+ Hide();
+
+ delete spubmp;
+ spubmp = NULL;
+
+ delete[]spu;
+ spu = NULL;
+
+ clearHighlight();
+ clean = true;
+}
+
+// ==================================
+// ! set pts
+int cDxr3SpuDecoder::setTime(uint32_t pts)
+{
+ if (!spu)
+ {
+ return 0;
+ }
+
+ if (spu && !clean)
+ {
+ Draw();
+ }
+
+ while (DCSQ_offset != prev_DCSQ_offset)
+ {
+ // Display Control Sequences
+ int i = DCSQ_offset;
+ state = spNONE;
+
+ uint32_t exec_time = spupts + spuU32(i) * 1024;
+ if ((pts != 0) && (exec_time > pts))
+ {
+ return 0;
+ }
+
+ if (pts != 0)
+ {
+ uint16_t feven = 0;
+ uint16_t fodd = 0;
+
+ i += 2;
+
+ prev_DCSQ_offset = DCSQ_offset;
+ DCSQ_offset = spuU32(i);
+ i += 2;
+
+ while (spu[i] != CMD_SPU_EOF)
+ {
+ // Command Sequence
+ switch (spu[i])
+ {
+ case CMD_SPU_SHOW:
+ // show subpicture
+ dsyslog("dxr3: spu show");
+ state = spSHOW;
+ i++;
+ break;
+
+ case CMD_SPU_HIDE:
+ // hide subpicture
+ dsyslog("dxr3: spu hide");
+ state = spHIDE;
+ i++;
+ break;
+
+ case CMD_SPU_SET_PALETTE:
+ // CLUT
+ palDescr[0].index = spu[i + 2] & 0xf;
+ palDescr[1].index = spu[i + 2] >> 4;
+ palDescr[2].index = spu[i + 1] & 0xf;
+ palDescr[3].index = spu[i + 1] >> 4;
+ i += 3;
+ break;
+
+ case CMD_SPU_SET_ALPHA:
+ // transparency palette
+ palDescr[0].trans = spu[i + 2] & 0xf;
+ palDescr[1].trans = spu[i + 2] >> 4;
+ palDescr[2].trans = spu[i + 1] & 0xf;
+ palDescr[3].trans = spu[i + 1] >> 4;
+ i += 3;
+ break;
+
+ case CMD_SPU_SET_SIZE:
+ // image coordinates
+ size.x1 = (spu[i + 1] << 4) | (spu[i + 2] >> 4);
+ size.x2 = ((spu[i + 2] & 0x0f) << 8) | spu[i + 3];
+
+ size.y1 = (spu[i + 4] << 4) | (spu[i + 5] >> 4);
+ size.y2 = ((spu[i + 5] & 0x0f) << 8) | spu[i + 6];
+
+ dsyslog("dxr3: spu size (%d,%d) x (%d,%d)",
+ size.x1, size.y1, size.x2, size.y2);
+ i += 7;
+ break;
+
+ case CMD_SPU_SET_PXD_OFFSET:
+ // image 1 / image 2 offsets
+ fodd = spuU32(i + 1);
+ feven = spuU32(i + 3);
+
+ dsyslog("dxr3: spu offset: odd=%d, even=%d", fodd, feven);
+ i += 5;
+ break;
+
+ case CMD_SPU_CHG_COLCON:
+ {
+ int size = spuU32(i + 1);
+ i += 1 + size;
+ }
+ break;
+
+ case CMD_SPU_MENU:
+ dsyslog("dxr3: spu menu");
+ state = spMENU;
+ i++;
+ break;
+
+ default:
+ esyslog("dxr3: invalid sequence in control header (%.2x)",
+ spu[i]);
+ assert(0);
+ i++;
+ break;
+ }
+ }
+ if (fodd != 0 && feven != 0)
+ {
+ delete spubmp;
+ spubmp = new cDxr3SpuBitmap(size, spu + fodd, spu + feven,
+ spu + feven, spu + cmdOffs());
+ }
+ }
+ else if (!clean)
+ {
+ state = spSHOW;
+ }
+
+ if ((state == spSHOW && allowedShow) || state == spMENU)
+ {
+ Draw();
+ }
+
+ if (state == spHIDE)
+ {
+ Hide();
+ }
+
+ if (pts == 0)
+ {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3spudecoder.h b/dxr3spudecoder.h
new file mode 100644
index 0000000..9f5adb1
--- /dev/null
+++ b/dxr3spudecoder.h
@@ -0,0 +1,190 @@
+/*
+ * dxr3spudecoder.h
+ *
+ * Copyright (C) 2004 Christian Gmeiner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _DXR3SPUDECODER_H_
+#define _DXR3SPUDECODER_H_
+
+#include "dxr3vdrincludes.h"
+#include <inttypes.h>
+
+// ==================================
+typedef struct sDxr3SpuPalDescr
+{
+ uint8_t index;
+ uint8_t trans;
+
+ bool operator != (const sDxr3SpuPalDescr pd) const
+ {
+ return index != pd.index && trans != pd.trans;
+ };
+} aDxr3SpuPalDescr[4];
+
+// ==================================
+struct sDxr3SpuRect
+{
+ int x1, y1;
+ int x2, y2;
+
+ int width()
+ {
+ return x2 - x1 + 1;
+ };
+
+ int height()
+ {
+ return y2 - y1 + 1;
+ };
+
+ bool operator != (const sDxr3SpuRect r) const
+ {
+ return r.x1 != x1 || r.y1 != y1 || r.x2 != x2 || r.y2 != y2;
+ };
+};
+
+// ==================================
+class cDxr3SpuPalette
+{
+private:
+ uint32_t palette[16];
+
+public:
+ void setPalette(const uint32_t * pal);
+ uint32_t getColor(uint8_t idx, uint8_t trans) const;
+};
+
+// ==================================
+class cDxr3SpuBitmap
+{
+private:
+ sDxr3SpuRect bmpsize;
+ sDxr3SpuRect minsize[4];
+ uint8_t *bmp;
+
+ void putPixel(int xp, int yp, int len, uint8_t colorid);
+ void putFieldData(int field, uint8_t * data, uint8_t * endp);
+
+public:
+ cDxr3SpuBitmap(sDxr3SpuRect size, uint8_t * fodd, uint8_t * eodd,
+ uint8_t * feven, uint8_t * eeven);
+ ~cDxr3SpuBitmap();
+
+ bool getMinSize(const aDxr3SpuPalDescr paldescr,
+ sDxr3SpuRect & size) const;
+ cBitmap *getBitmap(const aDxr3SpuPalDescr paldescr,
+ const cDxr3SpuPalette & pal, sDxr3SpuRect & size) const;
+};
+
+// ==================================
+class cDxr3SpuDecoder : public cSpuDecoder
+{
+public:
+ cDxr3SpuDecoder();
+ ~cDxr3SpuDecoder();
+
+ int setTime(uint32_t pts);
+
+ cSpuDecoder::eScaleMode getScaleMode(void);
+ void setScaleMode(cSpuDecoder::eScaleMode ScaleMode);
+ void setPalette(uint32_t * pal);
+ void setHighlight(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey,
+ uint32_t palette);
+ void clearHighlight();
+ void Empty();
+#if VDRVERSNUM >= 10318
+ void processSPU(uint32_t pts, uint8_t * buf, bool AllowedShow);
+#else
+ void processSPU(uint32_t pts, uint8_t * buf);
+#endif
+
+ void Hide();
+ void Draw();
+ bool IsVisible()
+ {
+ return osd != NULL;
+ }
+
+private:
+ cOsd * osd;
+
+ // processing state
+ uint8_t *spu;
+ uint32_t spupts;
+ bool clean;
+ bool ready;
+ bool allowedShow;
+
+ enum spFlag
+ {
+ spNONE,
+ spHIDE,
+ spSHOW,
+ spMENU
+ };
+ spFlag state;
+
+ cSpuDecoder::eScaleMode scaleMode;
+
+ // highligh area
+ bool highlight;
+ sDxr3SpuRect hlpsize;
+ aDxr3SpuPalDescr hlpDescr;
+
+ // palette
+ cDxr3SpuPalette palette;
+
+ // spu info's
+ sDxr3SpuRect size;
+ aDxr3SpuPalDescr palDescr;
+
+ uint16_t DCSQ_offset;
+ uint16_t prev_DCSQ_offset;
+
+ cDxr3SpuBitmap *spubmp;
+
+ int cmdOffs()
+ {
+ return ((spu[2] << 8) | spu[3]);
+ }
+ int spuSize()
+ {
+ return ((spu[0] << 8) | spu[1]);
+ }
+
+ int ScaleYcoord(int value);
+ int ScaleYres(int value);
+ void DrawBmp(sDxr3SpuRect & size, cBitmap * bmp);
+};
+
+// ==================================
+inline uint32_t cDxr3SpuPalette::getColor(uint8_t idx, uint8_t trans) const
+{
+ uint8_t t = trans == 0x0f ? 0xff : trans << 4;
+ return palette[idx] | (t << 24);
+}
+
+#endif /*_DXR3SPUDECODER_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3syncbuffer.c b/dxr3syncbuffer.c
new file mode 100644
index 0000000..66be71b
--- /dev/null
+++ b/dxr3syncbuffer.c
@@ -0,0 +1,496 @@
+/*
+ * dxr3syncbuffer.c
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/*
+ ToDo:
+ - cDxr3SyncBuffer::Push: XXX This is only a workaround until a
+ sufficient control algorithm is implemented
+*/
+
+#include <unistd.h>
+#include <sys/time.h>
+#include "dxr3syncbuffer.h"
+
+const int DXR3_MAX_VIDEO_FRAME_LENGTH = 4096;
+const int DXR3_MAX_AUDIO_FRAME_LENGTH = 4096;
+
+// ==================================
+//! constructor
+cFixedLengthFrame::cFixedLengthFrame() :
+ m_count(0), m_length(0), m_pts(0), m_type(ftUnknown)
+{
+
+ m_audioChannelCount = UNKNOWN_CHANNEL_COUNT;
+ m_audioDataRate = UNKNOWN_DATA_RATE;
+ m_videoAspectRatio = UNKNOWN_ASPECT_RATIO;
+}
+
+// ==================================
+cFixedLengthFrame::~cFixedLengthFrame()
+{
+ if (m_pData)
+ {
+ delete[] m_pData;
+ }
+}
+
+// ==================================
+// ! setup our frame
+void cFixedLengthFrame::Init(uint32_t lenght)
+{
+ m_length = lenght;
+ m_pData = new uint8_t[lenght];
+
+ // allocation ok?
+ if (!m_pData)
+ {
+ esyslog("dxr3: fatal: unable to allocate memory for new frame");
+ exit(1);
+ }
+}
+
+// ==================================
+void cFixedLengthFrame::CopyFrame(const uint8_t* pStart, int length,
+ uint32_t pts, eFrameType type)
+{
+ if (length > m_length)
+ {
+ delete[] m_pData;
+ m_pData = new uint8_t[length];
+ m_length = length;
+ }
+ m_type = type;
+ m_count = length;
+ m_pts = pts;
+ memcpy((void*) m_pData, (void*) pStart, length);
+}
+
+// ==================================
+uint8_t* cFixedLengthFrame::GetData(void)
+{
+ return m_pData;
+}
+
+// ==================================
+int cFixedLengthFrame::GetCount(void)
+{
+ return m_count;
+}
+
+// ==================================
+uint32_t cFixedLengthFrame::GetPts(void)
+{
+ return m_pts;
+}
+
+// ==================================
+void cFixedLengthFrame::SetPts(uint32_t pts)
+{
+ m_pts = pts;
+}
+
+// ==================================
+uint32_t cFixedLengthFrame::m_staticAudioChannelCount = 0;
+uint32_t cFixedLengthFrame::m_staticAudioDataRate = 0;
+
+
+// ==================================
+//! constructor
+cDxr3SyncBuffer::cDxr3SyncBuffer(int frameCount, int frameLength,
+ cDxr3Interface& dxr3Device) :
+ cRingBuffer(frameCount, true), m_dxr3Device(dxr3Device)
+{
+ m_pBuffer = new cFixedLengthFrame[frameCount];
+
+ // got we a valid m_pBuffer?
+ if (!m_pBuffer)
+ {
+ esyslog("dxr3: fatal: unable to allocate memory for new frame");
+ exit(1);
+ }
+
+ // init our new m_pBuffer;
+ for (int i = 0; i < frameCount; i++)
+ {
+ m_pBuffer[i].Init(frameLength);
+ }
+
+ // set some default values
+ m_count = 0;
+ m_nextFree = 0;
+ m_next = 0;
+ m_bWaitPts = false;
+ m_waitPts = 0;
+ m_waitDelta = 0;
+ m_lastPts = 0;
+ m_bPutBlock = false;
+ m_bGetBlock = false;
+ m_bStartReceiver = false;
+ m_bStopped = false;
+ m_demuxMode = DXR3_DEMUX_TV_MODE;
+ m_bPollSync = false;
+ SetTimeouts(1000, 10);
+}
+
+// ==================================
+cDxr3SyncBuffer::~cDxr3SyncBuffer()
+{
+ if (m_pBuffer)
+ {
+ delete[] m_pBuffer;
+ }
+}
+
+// ==================================
+int cDxr3SyncBuffer::Available(void)
+{
+ int ret = 0;
+#if VDRVERSNUM < 10313
+ Lock();
+#endif
+ ret = m_count;
+#if VDRVERSNUM < 10313
+ Unlock();
+#endif
+ return ret;
+}
+
+// ==================================
+const int BUFFER_LIMIT = 5;
+const int BUFFER_LIMIT_2 = 10;
+
+// ==================================
+bool cDxr3SyncBuffer::Poll(int TimeoutMs)
+{
+ bool retVal = true;
+ uint32_t currTime = m_dxr3Device.GetSysClock();
+ struct timeval tv_start, tv;
+ m_bPollSync = true;
+ gettimeofday(&tv_start, NULL);
+ if (m_demuxMode == DXR3_DEMUX_REPLAY_MODE)
+ {
+ if (Available() >= Size() - (Size()*BUFFER_LIMIT/100))
+ {
+ m_bPollSync = true;
+ while ((Available() >= Size() - (Size()*BUFFER_LIMIT_2)/100) &&
+ ((m_dxr3Device.GetSysClock() - currTime) <
+ ((uint32_t)TimeoutMs * (uint32_t)45)))
+ {
+ int d_s, d_us, ms;
+ m_bPutBlock = true;
+ EnableGet();
+ m_bWaitPts = false;
+ WaitForPut();
+ gettimeofday(&tv, NULL);
+ d_s = tv.tv_sec - tv_start.tv_sec;
+ d_us = tv.tv_usec - tv_start.tv_usec;
+ ms = d_s * 1000 + d_us / 1000;
+ if (ms > TimeoutMs * 2) {
+ esyslog("dxr3: sync: secondary timeout");
+ break;
+ }
+ }
+ if (Available() >= Size() - (Size()*BUFFER_LIMIT_2)/100)
+ {
+ retVal = false;
+ }
+ }
+ }
+
+ return retVal;
+}
+
+// ==================================
+cFixedLengthFrame* cDxr3SyncBuffer::Push(const uint8_t* pStart, int length, uint32_t pts, eFrameType type) throw (eSyncBufferException)
+{
+ int lastIndex = 0;
+ struct timeval tv_start, tv;
+ gettimeofday(&tv_start, NULL);
+
+ switch (m_demuxMode)
+ {
+ case DXR3_DEMUX_TRICK_MODE:
+ break;
+
+ case DXR3_DEMUX_TV_MODE:
+ case DXR3_DEMUX_REPLAY_MODE:
+ default:
+
+ while ((Available() >= Size() - (Size()*10)/100))
+ {
+ int d_s, d_us, ms;
+ m_bPutBlock = true;
+ EnableGet();
+ m_bWaitPts = false;
+ WaitForPut();
+ gettimeofday(&tv, NULL);
+ d_s = tv.tv_sec - tv_start.tv_sec;
+ d_us = tv.tv_usec - tv_start.tv_usec;
+ ms = d_s * 1000 + d_us / 1000;
+ if (ms > 2000) {
+ esyslog("dxr3: sync: push timeout");
+ return NULL;
+ }
+ }
+
+#if VDRVERSNUM < 10313
+ Lock();
+#endif
+ if (pts == m_lastPts)
+ {
+ pts = 0;
+ }
+ else
+ {
+ m_lastPts = pts;
+ }
+ lastIndex = m_nextFree;
+ m_pBuffer[m_nextFree].CopyFrame(pStart, length, pts, type);
+ m_pBuffer[m_nextFree].SetChannelCount(UNKNOWN_CHANNEL_COUNT);
+ m_pBuffer[m_nextFree].SetDataRate(UNKNOWN_DATA_RATE);
+ m_pBuffer[m_nextFree].SetAspectRatio(UNKNOWN_ASPECT_RATIO);
+ m_nextFree++;
+ m_count++;
+ m_nextFree %= Size();
+
+ if (m_nextFree == m_next)
+ {
+ esyslog("dxr3: sync: push buffer overrun");
+ Clear(); // XXX This is only a workaround until a sufficient control algorithm is implemented
+ throw(SYNC_BUFFER_OVERRUN);
+ }
+ if (!m_bWaitPts)
+ {
+ if (m_bStartReceiver)
+ {
+ EnableGet();
+ }
+ }
+ else
+ {
+ if (m_waitPts < m_dxr3Device.GetSysClock() ||
+ m_waitPts - m_dxr3Device.GetSysClock() < m_waitDelta)
+ {
+ EnableGet();
+ m_bWaitPts = false;
+ }
+ }
+#if VDRVERSNUM < 10313
+ Unlock();
+#endif
+ break;
+ }
+
+ return &m_pBuffer[lastIndex];
+}
+
+// ==================================
+void cDxr3SyncBuffer::Pop(void)
+{
+#if VDRVERSNUM < 10313
+ Lock();
+#endif
+ if (m_count)
+ {
+ uint32_t nextPts = 0;
+ uint32_t tmpBuffer = m_next;
+ for (int i = 0; i < m_count && nextPts == 0; ++i)
+ {
+ if (tmpBuffer) tmpBuffer = --tmpBuffer ? tmpBuffer : (Size() - 1);
+ nextPts = m_pBuffer[tmpBuffer].GetPts();
+ }
+ if (nextPts != 30)
+ {
+ cDxr3NextPts::Instance().SetNextPts(nextPts);
+ }
+
+ m_next++;
+ m_count--;
+ m_next %= Size();
+ if (m_next == m_nextFree)
+ {
+ m_next = m_nextFree = m_count = 0;
+ }
+ }
+ EnablePut();
+#if VDRVERSNUM < 10313
+ Unlock();
+#endif
+}
+
+// ==================================
+cFixedLengthFrame* cDxr3SyncBuffer::Get(void)
+{
+ cFixedLengthFrame* pRet = 0;
+
+ if (!m_bStopped)
+ {
+ while ((!Available() || !m_bStartReceiver) && !m_bStopped)
+ {
+ m_bGetBlock = true;
+ ReceiverStopped();
+ WaitForGet();
+ }
+
+#if VDRVERSNUM < 10313
+ Lock();
+#endif
+ if (m_nextFree != m_next)
+ {
+ pRet = &m_pBuffer[m_next];
+ }
+#if VDRVERSNUM < 10313
+ Unlock();
+#endif
+ }
+ else
+ {
+ WaitForGet();
+ }
+
+ return pRet;
+}
+
+// ==================================
+void cDxr3SyncBuffer::Clear(void)
+{
+#if VDRVERSNUM < 10313
+ Lock();
+#endif
+ m_next = 0;
+ m_nextFree = 0;
+ m_count = 0;
+ m_lastPts = 0;
+ m_bWaitPts = false;
+ m_bStartReceiver = false;
+ m_bPollSync = false;
+ if (m_bPutBlock)
+ {
+ EnablePut();
+ m_bPutBlock = false;
+ }
+ cFixedLengthFrame::Clear();
+ cDxr3NextPts::Instance().Clear();
+#if VDRVERSNUM < 10313
+ Unlock();
+#endif
+}
+
+// ==================================
+void cDxr3SyncBuffer::WaitForSysClock(uint32_t pts, uint32_t delta)
+{
+ m_waitPts = pts;
+ m_waitDelta = delta;
+ if (!m_bPutBlock)
+ {
+#if VDRVERSNUM < 10313
+ Lock();
+#endif
+ m_bWaitPts = true;
+#if VDRVERSNUM < 10313
+ Unlock();
+#endif
+ m_bGetBlock = true;
+ ReceiverStopped();
+ WaitForGet();
+ }
+ else
+ {
+ usleep(1); //* (pts - pSysClock->GetSysClock()));
+ }
+}
+
+// ==================================
+void cDxr3SyncBuffer::WaitForNextPut(void)
+{
+ if (!m_bPutBlock)
+ {
+ m_bGetBlock = true;
+ ReceiverStopped();
+ WaitForGet();
+ }
+ else
+ {
+ usleep(1);
+ }
+}
+
+// ==================================
+void cDxr3SyncBuffer::Start(void)
+{
+ m_bStartReceiver = true;
+ m_bStopped = false;
+ if (Available())
+ {
+ EnableGet();
+ }
+}
+
+// ==================================
+void cDxr3SyncBuffer::WakeUp(void)
+{
+#if VDRVERSNUM < 10313
+ Lock();
+#endif
+ if (m_bStartReceiver == true)
+ {
+ if (!m_bWaitPts)
+ {
+ EnableGet();
+ }
+ else
+ {
+ if (m_waitPts < m_dxr3Device.GetSysClock() ||
+ m_waitPts - m_dxr3Device.GetSysClock() < m_waitDelta)
+ {
+ EnableGet();
+ m_bWaitPts = false;
+ }
+ }
+ }
+#if VDRVERSNUM < 10313
+ Unlock();
+#endif
+}
+
+// ==================================
+void cDxr3SyncBuffer::WaitForReceiverStopped(void)
+{
+ if (!m_bGetBlock)
+ {
+ receiverStoppedMutex.Lock();
+ receiverStopped.Wait(receiverStoppedMutex);
+ receiverStoppedMutex.Unlock();
+ }
+}
+
+// ==================================
+void cDxr3SyncBuffer::ReceiverStopped(void)
+{
+ receiverStopped.Broadcast();
+}
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3syncbuffer.h b/dxr3syncbuffer.h
new file mode 100644
index 0000000..01ae9b8
--- /dev/null
+++ b/dxr3syncbuffer.h
@@ -0,0 +1,198 @@
+/*
+ * dxr3syncbuffer.h
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _DXR3SYNCBUFFER_H_
+#define _DXR3SYNCBUFFER_H_
+
+#include <stdint.h>
+
+#include "dxr3vdrincludes.h"
+#include "dxr3interface.h"
+#include "dxr3generaldefines.h"
+#include "dxr3nextpts.h"
+
+// ==================================
+const uint32_t UNKNOWN_CHANNEL_COUNT = 0xFFFFFFFF;
+const uint32_t UNKNOWN_DATA_RATE = 0xFFFFFFFF;
+const uint32_t UNKNOWN_ASPECT_RATIO = 0xFFFFFFFF;
+
+// ==================================
+class cFixedLengthFrame
+{
+public:
+ cFixedLengthFrame();
+ ~cFixedLengthFrame();
+
+ void Init(uint32_t lenght);
+
+ void CopyFrame(const uint8_t* pStart, int length, uint32_t pts,
+ eFrameType type);
+ uint8_t* GetData(void);
+ int GetCount(void);
+ uint32_t GetPts(void);
+ void SetPts(uint32_t pts);
+ void SetChannelCount(uint32_t channelCount)
+ {
+ if (channelCount != UNKNOWN_CHANNEL_COUNT)
+ m_staticAudioChannelCount = m_audioChannelCount = channelCount;
+ else
+ m_audioChannelCount = m_staticAudioChannelCount;
+ };
+ void SetDataRate(uint32_t dataRate)
+ {
+ if (m_audioDataRate != UNKNOWN_DATA_RATE)
+ m_staticAudioDataRate = m_audioDataRate = dataRate;
+ else
+ m_audioDataRate = m_staticAudioDataRate;
+ };
+ void SetAspectRatio(uint32_t aspectRatio)
+ {
+ m_videoAspectRatio = aspectRatio;
+ };
+ uint32_t GetChannelCount(void)
+ {
+ return ((m_audioChannelCount == m_staticAudioChannelCount ||
+ !m_staticAudioChannelCount)?
+ m_audioChannelCount : m_staticAudioChannelCount);
+ };
+ uint32_t GetDataRate(void)
+ {
+ return ((m_audioDataRate == m_staticAudioDataRate ||
+ !m_staticAudioDataRate) ?
+ m_audioDataRate : m_staticAudioDataRate);
+ };
+ uint32_t GetAspectRatio(void)
+ {
+ return m_videoAspectRatio;
+ };
+ eFrameType GetFrameType(void)
+ {
+ return m_type;
+ }
+
+ static void Clear(void)
+ {
+ m_staticAudioDataRate = 0;
+ m_staticAudioChannelCount = 0;
+ };
+
+protected:
+ uint8_t* m_pData;
+ int m_count;
+ int m_length;
+ uint32_t m_pts;
+ eFrameType m_type;
+
+ uint32_t m_audioChannelCount;
+ uint32_t m_audioDataRate;
+ uint32_t m_videoAspectRatio;
+
+ static uint32_t m_staticAudioChannelCount;
+ static uint32_t m_staticAudioDataRate;
+
+private:
+ //cFixedLengthFrame(); // you are not allowed to use this constructor
+ cFixedLengthFrame(cFixedLengthFrame&); // no copy constructor
+
+};
+
+// ==================================
+class cDxr3SyncBuffer : public cRingBuffer
+{
+public:
+ enum eSyncBufferException
+ {
+ SYNC_BUFFER_OVERRUN
+ };
+public:
+ cDxr3SyncBuffer(int frameCount, int frameLength,
+ cDxr3Interface& dxr3Device);
+ ~cDxr3SyncBuffer();
+
+ virtual int Available(void);
+ cFixedLengthFrame* Push(const uint8_t* pStart, int length, uint32_t pts,
+ eFrameType type = ftUnknown)
+ throw (eSyncBufferException);
+ void Pop(void);
+ cFixedLengthFrame* Get(void);
+ void Clear(void);
+ void Stop(void)
+ {
+ m_bStopped = true;
+ };
+ void Start(void);
+ void WaitForSysClock(uint32_t pts, uint32_t delta);
+ void WaitForNextPut(void);
+ void WakeUp(void);
+ void WaitForReceiverStopped(void);
+ void SetDemuxMode(eDxr3DemuxMode demuxMode)
+ {
+ m_demuxMode = demuxMode;
+ };
+ eDxr3DemuxMode GetDemuxMode(void)
+ {
+ return m_demuxMode;
+ };
+ bool Poll(int TimeoutMs);
+ bool IsPolled(void)
+ {
+ return m_bPollSync;
+ };
+ uint32_t GetFillLevel(void)
+ {
+ return Available() * 100 / Size();
+ };
+
+protected:
+ void ReceiverStopped(void);
+
+ cFixedLengthFrame* m_pBuffer;
+ int m_count;
+ int m_nextFree;
+ int m_next;
+ bool m_bWaitPts;
+ bool m_bPutBlock;
+ bool m_bGetBlock;
+ bool m_bStartReceiver;
+ bool m_bStopped;
+ uint32_t m_waitPts;
+ uint32_t m_waitDelta;
+ uint32_t m_lastPts;
+ eDxr3DemuxMode m_demuxMode;
+
+ cCondVar receiverStopped;
+ cMutex receiverStoppedMutex;
+ cDxr3Interface& m_dxr3Device;
+ bool m_bPollSync;
+
+private:
+ cDxr3SyncBuffer(); // you are not allowed to use this constructor
+ cDxr3SyncBuffer(cDxr3SyncBuffer&); // no constructor
+};
+
+#endif /*_DXR3SYNCBUFFER_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3sysclock.c b/dxr3sysclock.c
new file mode 100644
index 0000000..189ac0b
--- /dev/null
+++ b/dxr3sysclock.c
@@ -0,0 +1,77 @@
+/*
+ * dxr3sysclock.c
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <sys/ioctl.h>
+#include "dxr3sysclock.h"
+
+// ==================================
+void cDxr3SysClock::SetSysClock(uint32_t scr)
+{
+ uint32_t sc;
+
+ mutex.Lock();
+ ioctl(m_fdcontrol, EM8300_IOCTL_SCR_GET, &sc);
+ m_offset = scr - sc;
+ mutex.Unlock();
+}
+
+// ==================================
+uint32_t cDxr3SysClock::GetSysClock(void)
+{
+ uint32_t sc;
+ uint32_t retval;
+
+ mutex.Lock();
+ ioctl(m_fdcontrol, EM8300_IOCTL_SCR_GET, &sc);
+ retval = sc + m_offset;
+ mutex.Unlock();
+
+ return retval;
+}
+
+// ==================================
+void cDxr3SysClock::SetPts(uint32_t pts)
+{
+ uint32_t newPts = 0;
+
+ mutex.Lock();
+ newPts = pts - m_offset;
+ ioctl(m_fdvideo, EM8300_IOCTL_VIDEO_SETPTS, &newPts);
+ mutex.Unlock();
+}
+
+// ==================================
+void cDxr3SysClock::SetSpuPts(uint32_t pts)
+{
+ uint32_t newPts = 0;
+
+ mutex.Lock();
+ newPts = (pts - m_offset) << 1; // fix for DVD subtitles
+ ioctl(m_fdspu, EM8300_IOCTL_SPU_SETPTS, &newPts);
+ mutex.Unlock();
+}
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3sysclock.h b/dxr3sysclock.h
new file mode 100644
index 0000000..0f1396e
--- /dev/null
+++ b/dxr3sysclock.h
@@ -0,0 +1,66 @@
+/*
+ * dxr3sysclock.h
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _DXR3_SYSCLOCK_H_
+#define _DXR3_SYSCLOCK_H_
+
+#include "dxr3vdrincludes.h"
+#include <linux/em8300.h>
+
+// ==================================
+// work with dxr3's clock
+class cDxr3SysClock
+{
+public:
+ cDxr3SysClock(int fd_control, int fd_video, int fd_spu):
+ m_fdcontrol(fd_control),
+ m_fdvideo(fd_video),
+ m_fdspu(fd_spu),
+ m_offset(0) {};
+
+ virtual ~cDxr3SysClock() {};
+
+public:
+ void SetSysClock(uint32_t scr);
+ uint32_t GetSysClock(void);
+ void SetPts(uint32_t pts);
+ void SetSpuPts(uint32_t pts);
+
+protected:
+ int m_fdcontrol;
+ int m_fdvideo;
+ int m_fdspu;
+ uint32_t m_offset;
+ cMutex mutex;
+
+protected:
+ cDxr3SysClock(); // you are not allowed to use this contructor
+ cDxr3SysClock(cDxr3SysClock&); // no copy constructor
+};
+
+#endif /*_DXR3_SYSCLOCK_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3tools.h b/dxr3tools.h
new file mode 100644
index 0000000..971859c
--- /dev/null
+++ b/dxr3tools.h
@@ -0,0 +1,109 @@
+/*
+ * dxr3tools.h
+ *
+ * Copyright (C) 2004 Christian Gmeiner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _DXR3TOOLS_H_
+#define _DXR3TOOLS_H_
+
+#include "dxr3vdrincludes.h"
+
+namespace Tools
+{
+ // ==================================
+ //! convert Rgb to CrCb
+ inline unsigned int Rgb2YCrCb(unsigned long rgb)
+ {
+ float Y,U,V;
+ float R,G,B;
+ unsigned int yuv = 0x0;
+
+ B = ((rgb >> 16) & 0xFF);
+ G = ((rgb >> 8) & 0xFF);
+ R = (rgb & 0xFF);
+
+ Y = (0.2578125 * R) + (0.50390625 * G) + (0.09765625 * B) + 16;
+ U = (0.4375 * R) - (0.3671875 * G) - (0.0703125 * B) + 128;
+ V =-(0.1484375 * R) - (0.2890625 * G) + (0.4375 * B) + 128;
+
+ yuv = (int(Y) << 16) | (int(U) << 8) | int(V);
+
+ return yuv;
+ }
+
+ // ==================================
+ //! convert YUV to Rgb
+ inline unsigned int YUV2Rgb(unsigned int yuv_color)
+ {
+ int Y, Cb, Cr;
+ int Ey, Epb, Epr;
+ int Eg, Eb, Er;
+
+ Y = (yuv_color >> 16) & 0xff;
+ Cb = (yuv_color) & 0xff;
+ Cr = (yuv_color >> 8) & 0xff;
+
+ Ey = (Y - 16);
+ Epb = (Cb - 128);
+ Epr = (Cr - 128);
+ /* ITU-R 709
+ Eg = (298*Ey - 55*Epb - 137*Epr)/256;
+ Eb = (298*Ey + 543*Epb)/256;
+ Er = (298*Ey + 460*Epr)/256;
+ */
+ /* FCC ~= mediaLib */
+ Eg = (298 * Ey - 100 * Epb - 208 * Epr) / 256;
+ Eb = (298 * Ey + 516 * Epb) / 256;
+ Er = (298 * Ey + 408 * Epr) / 256;
+
+ if (Eg > 255)
+ Eg = 255;
+ if (Eg < 0)
+ Eg = 0;
+
+ if (Eb > 255)
+ Eb = 255;
+ if (Eb < 0)
+ Eb = 0;
+
+ if (Er > 255)
+ Er = 255;
+ if (Er < 0)
+ Er = 0;
+
+ return Eb | (Eg << 8) | (Er << 16);
+ }
+
+ // ==================================
+ //! write a string via vdr to OSD
+ inline void WriteInfoToOsd(std::string x)
+ {
+ Skins.Message(mtInfo, x.c_str());
+ }
+
+}
+
+#endif /*_DXR3TOOLS_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End:
diff --git a/dxr3vdrincludes.h b/dxr3vdrincludes.h
new file mode 100644
index 0000000..23ce128
--- /dev/null
+++ b/dxr3vdrincludes.h
@@ -0,0 +1,58 @@
+/*
+ * dxr3vdrincludes.h
+ *
+ * Copyright (C) 2002-2004 Kai Möller
+ * Copyright (C) 2004 Christian Gmeiner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _DXR3_VDRINCLUDES_H_
+#define _DXR3_VDRINCLUDES_H_
+
+#include <string>
+#include <algorithm>
+#include <vector>
+
+#ifndef __STL_CONFIG_H
+#define __STL_CONFIG_H
+#define __DXR3_UNDEF_STL_CONFIG_AFTERWARDS
+#endif
+
+// all includes from vdr
+#include <vdr/osd.h>
+#include <vdr/config.h>
+#include <vdr/thread.h>
+#include <vdr/ringbuffer.h>
+#include <vdr/spu.h>
+#include <vdr/tools.h>
+#include <vdr/device.h>
+#include <vdr/status.h>
+#include <vdr/plugin.h>
+#include <vdr/audio.h>
+
+#ifdef __DXR3_UNDEF_STL_CONFIG_AFTERWARDS
+#undef __STL_CONFIG_H
+#endif
+
+#endif /*_DXR3_VDRINCLUDES_H_*/
+
+// Local variables:
+// mode: c++
+// c-file-style: "stroustrup"
+// c-file-offsets: ((inline-open . 0))
+// indent-tabs-mode: t
+// End: