summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraustriancoder <austriancoder>2004-08-05 23:05:21 +0000
committeraustriancoder <austriancoder>2004-08-05 23:05:21 +0000
commitc47666d42f7972e1b51f9de61ce0fa27c72f3127 (patch)
treee34a87e37901b7f892fb6f330ccb15bcba30039b
downloadvdr-plugin-dxr3-c47666d42f7972e1b51f9de61ce0fa27c72f3127.tar.gz
vdr-plugin-dxr3-c47666d42f7972e1b51f9de61ce0fa27c72f3127.tar.bz2
initial import
-rw-r--r--COPYING340
-rw-r--r--HISTORY230
-rw-r--r--INSTALL18
-rw-r--r--Makefile97
-rw-r--r--README14
-rw-r--r--dxr3.c189
-rw-r--r--dxr3.h107
-rw-r--r--dxr3audiodecoder.c296
-rw-r--r--dxr3audiodecoder.h53
-rw-r--r--dxr3blackframe.c1286
-rw-r--r--dxr3colormanager.c378
-rw-r--r--dxr3colormanager.h122
-rw-r--r--dxr3configdata.c16
-rw-r--r--dxr3configdata.h76
-rw-r--r--dxr3cpu.c127
-rw-r--r--dxr3cpu.h107
-rw-r--r--dxr3demuxdevice.c662
-rw-r--r--dxr3demuxdevice.h75
-rw-r--r--dxr3device.c472
-rw-r--r--dxr3device.h65
-rw-r--r--dxr3ffmpeg.c72
-rw-r--r--dxr3ffmpeg.h42
-rw-r--r--dxr3generaldefines.h37
-rw-r--r--dxr3i18n.c804
-rw-r--r--dxr3i18n.h12
-rw-r--r--dxr3interface.c1072
-rw-r--r--dxr3interface.h136
-rw-r--r--dxr3interface_spu_encoder.c620
-rw-r--r--dxr3interface_spu_encoder.h153
-rw-r--r--dxr3log.c60
-rw-r--r--dxr3log.h94
-rw-r--r--dxr3memcpy.c421
-rw-r--r--dxr3memcpy.h74
-rw-r--r--dxr3multichannelaudio.c645
-rw-r--r--dxr3multichannelaudio.h33
-rw-r--r--dxr3nextpts.c4
-rw-r--r--dxr3nextpts.h42
-rw-r--r--dxr3osd.c161
-rw-r--r--dxr3osd.h42
-rw-r--r--dxr3osd_subpicture.c174
-rw-r--r--dxr3osd_subpicture.h29
-rw-r--r--dxr3outputthread.c279
-rw-r--r--dxr3outputthread.h71
-rw-r--r--dxr3palettemanager.c114
-rw-r--r--dxr3palettemanager.h39
-rw-r--r--dxr3pesframe.c226
-rw-r--r--dxr3pesframe.h158
-rw-r--r--dxr3singleton.h43
-rw-r--r--dxr3spudecoder.c628
-rw-r--r--dxr3spudecoder.h138
-rw-r--r--dxr3syncbuffer.c420
-rw-r--r--dxr3syncbuffer.h123
-rw-r--r--dxr3sysclock.c49
-rw-r--r--dxr3sysclock.h36
-rw-r--r--dxr3tools.h82
-rw-r--r--dxr3unixserversocket.c190
-rw-r--r--dxr3unixserversocket.h71
-rw-r--r--dxr3vdrincludes.h33
58 files changed, 12157 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..5b6e7c6
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <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..6c25450
--- /dev/null
+++ b/HISTORY
@@ -0,0 +1,230 @@
+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>
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..f5ef4c4
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,18 @@
+Prerequisites:
+
+- Make sure your DXR3 card is running under linux. For more information look at the "http://dxr3.sourceforge.net"
+ You should modify the dxr3-driver by applying the delivered patch with "patch -p1 -R < em8300_patch.diff" in
+ the dxr3/modules directory.
+
+- Install the (latest) VDR developer version
+- The plugin needs the libavcodec library from "http://ffmpeg.sourceforge.net"
+
+Installation:
+
+- Get the latest dxr3-plugin version from "http://www.schluenss.de/dxr3.html"
+- Get the current CVS of the dxr3 drivers from dxr3.sf.net
+- Unpack the package into "PLUGINS/SRC" directory
+- Make a symbolic link to this dxr3-plugin (ln -s vdr_dxr3_x.x.x dxr3)
+- 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"
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..7d9fa05
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,97 @@
+#
+# Makefile for a Video Disk Recorder plugin
+#
+# $Id: Makefile,v 1.1 2004/08/05 23:05:21 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 = ../../../../ffmpeg
+### LIBMP3DIR = /usr/lib
+
+DVBDIR = /usr/src/linux
+VDRDIR = /usr/include/vdr
+LIBDIR = /usr/lib
+TMPDIR = /tmp
+FFMDIR = /usr/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 = vdr-$(ARCHIVE)
+
+### 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 += -DSOCKET_CHMOD=0660
+DEFINES += -D_GNU_SOURCE
+
+### The object files (add further files here):
+
+OBJS = $(PLUGIN).o dxr3multichannelaudio.o dxr3sysclock.o dxr3colormanager.o dxr3syncbuffer.o dxr3audiodecoder.o \
+dxr3blackframe.o dxr3palettemanager.o dxr3nextpts.o dxr3pesframe.o dxr3demuxdevice.o dxr3configdata.o \
+dxr3log.o dxr3ffmpeg.o dxr3interface_spu_encoder.o dxr3i18n.o \
+dxr3interface.o dxr3device.o dxr3outputthread.o dxr3osd.o dxr3osd_subpicture.o dxr3spudecoder.o dxr3unixserversocket.o \
+dxr3cpu.o dxr3memcpy.o
+
+### Implicit rules:
+
+%.o: %.c
+ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
+
+# Dependencies:
+
+MAKEDEP = g++ -MM -MG
+DEPFILE = .dependencies
+$(DEPFILE): Makefile
+ @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
+
+-include $(DEPFILE)
+
+### Targets:
+
+all: libvdr-$(PLUGIN).so
+
+libvdr-$(PLUGIN).so: $(OBJS)
+ $(CXX) $(CXXFLAGS) -lz -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) $(ARCHIVE)
+ @-rm -rf $(TMPDIR)/$(ARCHIVE)
+ @echo Distribution package created as $(PACKAGE).tgz
+
+clean:
+ @-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~
diff --git a/README b/README
new file mode 100644
index 0000000..fa2addc
--- /dev/null
+++ b/README
@@ -0,0 +1,14 @@
+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>
+
+Project's homepage: http://www.schluenss.de/DXR3.html
+
+Latest version available at: see homepage
+
+See the file COPYING for license information.
+
+Description: DXR3/Hollywod+ MPEG decoder card plugin which allows using such a
+ card as primary interface for VDR.
+
diff --git a/dxr3.c b/dxr3.c
new file mode 100644
index 0000000..0024a48
--- /dev/null
+++ b/dxr3.c
@@ -0,0 +1,189 @@
+/*
+* 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.1 2004/08/05 23:05:21 austriancoder Exp $
+*/
+
+
+#include "dxr3vdrincludes.h"
+#include "dxr3device.h"
+#include "dxr3syncbuffer.h"
+#include "dxr3configdata.h"
+#include "dxr3interface.h"
+#include "dxr3.h"
+
+static const char *VERSION = "0.2.3-pre3-cvs";
+static const char *DESCRIPTION = "DXR3-MPEG decoder plugin";
+static const char *MAINMENUENTRY = "DXR3";
+
+#include "dxr3cpu.h"
+
+// ==================================
+// 'message-handler' for the main screen
+eOSState cDxr3OsdItem::ProcessKey(eKeys Key)
+{
+ if (Key == kOk)
+ {
+ switch (m_item)
+ {
+ case DXR3_RESET_HARDWARE:
+ cDxr3Interface::Instance().ResetHardware();
+ cDxr3Device::Instance().Reset();
+ break;
+
+ case DXR3_FORCE_LETTER_BOX:
+ cDxr3ConfigData::Instance().SetForceLetterBox(!cDxr3ConfigData::Instance().GetForceLetterBox());
+ break;
+
+ case DXR3_ANALOG_OUT:
+ cLog::Instance() << "Changing audio to analog\n";
+ cDxr3ConfigData::Instance().SetUseDigitalOut(0);
+ cDxr3ConfigData::Instance().SetAc3OutPut(0);
+ cDxr3Device::Instance().Reset();
+ break;
+
+ case DXR3_DIGITAL_OUT:
+ cLog::Instance() << "Changing audio to digital\n";
+ cDxr3ConfigData::Instance().SetUseDigitalOut(1);
+ cDxr3ConfigData::Instance().SetAc3OutPut(0);
+ cDxr3Device::Instance().Reset();
+ break;
+
+ case DXR3_AC3_OUT:
+ cLog::Instance() << "Changing audio to ac3\n";
+ cDxr3ConfigData::Instance().SetAc3OutPut(!cDxr3ConfigData::Instance().GetAc3OutPut());
+ cDxr3Device::Instance().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("DXR3 card"), &newDxr3Card));
+ newVideoMode = (int) cDxr3ConfigData::Instance().GetVideoMode();
+ Add(new cMenuEditStraItem(tr("DXR3 video mode"), &newVideoMode, 3, menuVideoModes));
+ newDebug = (int) cDxr3ConfigData::Instance().GetDebug();
+ Add(new cMenuEditBoolItem(tr("Debug mode"), &newDebug));
+ newDebugLevel = (int) cDxr3ConfigData::Instance().GetDebugLevel();
+ Add(new cMenuEditStraItem(tr("Debug level"), &newDebugLevel, 2, menuDebugModes));
+}
+
+// ==================================
+// 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("Dxr3Debug", cDxr3ConfigData::Instance().SetDebug(newDebug));
+ SetupStore("Dxr3DebugLevel", cDxr3ConfigData::Instance().SetDebugLevel(newDebugLevel));
+}
+
+// ==================================
+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 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()
+{
+ new cDxr3CPU();
+ cDxr3Device::Instance();
+ return true;
+}
+
+// ==================================
+void cPluginDxr3::Housekeeping()
+{
+}
+
+// ==================================
+cMenuSetupPage* cPluginDxr3::SetupMenu()
+{
+ return new cMenuSetupDxr3();
+}
+
+// ==================================
+bool cPluginDxr3::SetupParse(const char *Name, const char *Value)
+{
+ // Parse your own setup parameters and store their values.
+ 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, "Dxr3Debug")) { cDxr3ConfigData::Instance().SetDebug(atoi(Value)); return true; }
+ if (!strcasecmp(Name, "Dxr3VideoMode")) { cDxr3ConfigData::Instance().SetVideoMode((eVideoMode) atoi(Value)); return true;}
+ if (!strcasecmp(Name, "Dxr3DebugLevel")) { cDxr3ConfigData::Instance().SetDebugLevel(atoi(Value)); return true;}
+
+ return false;
+}
+
+// ==================================
+const char* cPluginDxr3::MainMenuEntry()
+{
+ return tr(MAINMENUENTRY);
+}
+
+// ==================================
+cOsdObject* cPluginDxr3::MainMenuAction()
+{
+ return new cDxr3OsdMenu;
+}
+
+VDRPLUGINCREATOR(cPluginDxr3); // Don't touch this!
diff --git a/dxr3.h b/dxr3.h
new file mode 100644
index 0000000..069f488
--- /dev/null
+++ b/dxr3.h
@@ -0,0 +1,107 @@
+#ifndef _DXR3_H_
+#define _DXR3_H_
+
+// --- cMenuSetupDxr3 -------------------------------------------------------
+const char* menuVideoModes[] =
+{
+ "PAL",
+ "PAL60",
+ "NTSC"
+};
+
+// debug modes
+const char* menuDebugModes[] =
+{
+ "Low",
+ "Everything"
+};
+
+// ==================================
+// setup screen
+class cMenuSetupDxr3 : public cMenuSetupPage
+{
+public:
+ cMenuSetupDxr3();
+
+protected:
+ virtual void Store();
+
+private:
+ int newUseDigitalOut;
+ int newDxr3Card;
+ int newVideoMode;
+ int newDebug;
+ int newDebugLevel;
+};
+
+
+// ==================================
+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("DXR3 Adjustment")
+ {
+ Clear();
+ SetHasHotkeys();
+ Add(new cDxr3OsdItem(hk("Reset DXR3 Hardware"), DXR3_RESET_HARDWARE));
+ Add(new cDxr3OsdItem(hk("Toggle Force LetterBox"), DXR3_FORCE_LETTER_BOX));
+
+ if (cDxr3ConfigData::Instance().GetUseDigitalOut())
+ {
+ Add(new cDxr3OsdItem(hk("Analog Output"), DXR3_ANALOG_OUT));
+ }
+ else
+ {
+ Add(new cDxr3OsdItem(hk("Digital 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("AC3 Output Off"), DXR3_AC3_OUT));
+ }
+ else
+ {
+ if (cDxr3Interface::Instance().IsAc3Present())
+ {
+ Add(new cDxr3OsdItem(hk("AC3 Output On"), DXR3_AC3_OUT));
+ }
+ }
+ }
+ else
+ {
+ Add(new cDxr3OsdItem(hk("Digital Output"), DXR3_DIGITAL_OUT));
+ }
+ */
+ }
+};
+
+#endif /*_DXR3_H_*/
diff --git a/dxr3audiodecoder.c b/dxr3audiodecoder.c
new file mode 100644
index 0000000..c7fb3a7
--- /dev/null
+++ b/dxr3audiodecoder.c
@@ -0,0 +1,296 @@
+/*
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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;
+
+// ==================================
+// constr.
+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))
+ {
+ cLog::Instance() << "cDxr3AudioDecoder::Decode Found different audio header -> init\n";
+ cLog::Instance() << "cDxr3AduioDecoder::Decode Old header 0x" << hex << *((uint32_t*) lastHeader) << " new header 0x" << *((uint32_t*) (buf+i))<< dec << "\n";
+
+ 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)
+ {
+ cLog::Instance() << "cDxr3AudioDecoder::Decode Sample rate = " << Codec.codec_context.sample_rate << "\n";
+ if (rate != -1) throw UNEXPECTED_PARAMETER_CHANGE;
+ rate = Codec.codec_context.sample_rate;
+ }
+ if (Codec.codec_context.channels != channels+1 )
+ {
+ if (channels != -1) throw UNEXPECTED_PARAMETER_CHANGE;
+ channels = (Codec.codec_context.channels == 2) ? 1 : 0;
+ cLog::Instance() << "cDxr3AudioDecoder::Decode channels = " << Codec.codec_context.channels << "\n";
+ }
+ 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:
+ cLog::Instance() << "cDxr3AudioDecoder::Decode wrong length\n";
+ break;
+
+ case UNEXPECTED_PARAMETER_CHANGE:
+ cLog::Instance() << "cDxr3AudioDecoder::Decode unexpected parameter change\n";
+ break;
+
+ default:
+ cLog::Instance() << "cDxr3AudioDecoder::Decode unexpeced exception\n";
+ break;
+ }
+ dsyslog("cDxr3AudioDecoder::Decode 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];
+ assert(!((length - LPCM_HEADER_LENGTH) % 2)); // only even number of bytes are allowed
+
+ 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)
+ {
+ 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;
+}
diff --git a/dxr3audiodecoder.h b/dxr3audiodecoder.h
new file mode 100644
index 0000000..32467e4
--- /dev/null
+++ b/dxr3audiodecoder.h
@@ -0,0 +1,53 @@
+#ifndef _DXR3_AUDIODECODER_H_
+#define _DXR3_AUDIODECODER_H_
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "dxr3ffmpeg.h"
+#include "dxr3syncbuffer.h"
+#include "dxr3multichannelaudio.h"
+#include "dxr3log.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_*/
diff --git a/dxr3blackframe.c b/dxr3blackframe.c
new file mode 100644
index 0000000..c21417b
--- /dev/null
+++ b/dxr3blackframe.c
@@ -0,0 +1,1286 @@
+/*
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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);
diff --git a/dxr3colormanager.c b/dxr3colormanager.c
new file mode 100644
index 0000000..50e3877
--- /dev/null
+++ b/dxr3colormanager.c
@@ -0,0 +1,378 @@
+/***************************************************************************
+ 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 "dxr3memcpy.h"
+#include <stdio.h>
+#include <string.h>
+
+// ==================================
+cColorManager::cColorManager()
+{
+ NrOfRegions = 0;
+ isopen = false;
+ 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, int NrOfSecToCopy)
+{
+ hlr[NrOfRegions] = new yRegion();
+ hlr[NrOfRegions]->Y1 = y;
+ isopen = true;
+
+ if (NrOfSecToCopy > 0)
+ {
+ for (int i = 0; i < NrOfSecToCopy; i++)
+ {
+ hlr[NrOfRegions]->Section[i] = hlr[NrOfRegions - 1]->Section[i];
+ }
+ }
+}
+
+// ==================================
+// Closes the spu-highlight region
+void cColorManager::CloseRegion(int y)
+{
+
+ hlr[NrOfRegions]->Y2 = y;
+ isopen = false;
+
+ if (hlr[NrOfRegions]->N != 0) // skip this region if there is no section defined
+ {
+ if (NrOfRegions < MAX_NO_OF_SECTIONS -1)
+ {
+ NrOfRegions++;
+ }
+ }
+
+}
+
+// ==================================
+void cColorManager::EncodeColors(int width, int height, unsigned char* map, unsigned char* dmap)
+{
+ unsigned char color = 0xFF, ccol = 0xFF;
+ unsigned char ColorIndex = 0xFF;
+ unsigned char buffer[1024] = {0};
+
+ for (int y = 0; y < height; ++y)
+ {
+ color = 0xFF;
+ for(int x = 0; x < width; ++x)
+ {
+ ccol = map[y * width + x];
+ if (ccol != 0) MaxY = y;
+ if (ccol != color)
+ {
+ color = ccol; // save this color
+ if (!AddColor(x,y,color, ColorIndex))
+ {
+ // add this color to highlight regions
+ color = 0xFF;
+ x = -1;
+ }
+ else
+ {
+ // color successfully added
+ buffer[x] = ColorIndex;
+ }
+ }
+ else
+ {
+ buffer[x] = ColorIndex;//*(dmap+(y * width + x)) = ColorIndex;
+ }
+ }
+ dxr3_memcpy(dmap+y*width, buffer,width);
+ }
+}
+
+// ==================================
+unsigned char cColorManager::AddColor(int x, int y, unsigned char color, unsigned char &ColorIndex) {
+ static int yold = -1;
+ xSection* Section = 0;
+ int SectionIndex = 0;
+
+ if (isopen)
+ {
+ // there is an opened highlight-region
+ Section = GetSection(x, SectionIndex);
+
+ // checks whether we have a section defined on the formerly line on this x-position
+ if (Section != NULL)
+ {
+ // there was a section
+ if (!Section->HasColor(color, ColorIndex))
+ {
+ // this color is new for this section
+ if (Section->AllColorsUsed())
+ {
+ // no more free colors
+ if (yold != y)
+ {
+ CloseRegion(y-1);
+ // terminate region
+ return(0);
+ yold = y;
+ // open new region
+ OpenRegion(y,SectionIndex+1);
+ }
+ // create new section
+ Section = NewSection(x);
+ }
+ // and add new color
+ ColorIndex = Section->AddColor(color);
+ }
+ }
+ else
+ {
+ // no section found (but region already open)
+
+ // terminate region
+ CloseRegion(y-1);
+ yold = y;
+ // open new region
+ OpenRegion(y);
+ // create new section
+ Section = NewSection(x);
+ // and add new color
+ ColorIndex = Section->AddColor(color);
+ }
+ }
+ else
+ {
+ // currently no region open
+ yold = y;
+
+ // open new region
+ OpenRegion(y);
+ // create new section
+ Section = NewSection(x);
+ // and add new color
+ ColorIndex = Section->AddColor(color);
+ }
+ return(1);
+}
+
+// ==================================
+xSection *cColorManager::GetSection(int x, int &n)
+{
+ int i;
+ n = 0;
+
+ // for every section in the current region
+ for (i = 0; i < hlr[NrOfRegions]->N; i++)
+ {
+ if ((x <= hlr[NrOfRegions]->Section[i]->X2) && (x >= hlr[NrOfRegions]->Section[i]->X1)) // x-pos is in section
+ {
+ n = i;
+ return (hlr[NrOfRegions]->Section[i]);
+ }
+ }
+ return(NULL);
+}
+
+/** Adds a new highlight region beginning from FIRST to LAST column */
+/**
+void cColorManager::AddRegion(int first, int last, unsigned int color, unsigned int opac)
+{
+ DIAG("AddRegion(%d %d %x %x)\n",first, last, color, opac);
+ hlr[NrOfRegions]->AddSection(first, last, color, opac);
+}
+**/
+
+// ==================================
+// convert into SPU - hope is correct description
+unsigned char* cColorManager::GetSpuData(int& len)
+{
+ if (isopen) // there is an opened highlight-region
+ CloseRegion(MaxY);
+
+ 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);
+}
+
+// ==================================
+xSection *cColorManager::NewSection(int x)
+{
+ xSection* sec = new xSection(x);
+ int N = hlr[NrOfRegions]->N;
+
+ hlr[NrOfRegions]->Section[hlr[NrOfRegions]->N] = sec;
+ if (N > 0)
+ hlr[NrOfRegions]->Section[hlr[NrOfRegions]->N - 1]->X2 = x-1;
+ (hlr[NrOfRegions]->N)++;
+
+ return(sec);
+}
+
+/**
+// No descriptions */
+/**
+void HLRegion::AddSection(int first, int last, unsigned int color, unsigned int opac)
+{
+ DIAG(" AddSection %d,%d %X,%X\n",first, last, color, opac);
+ Region[N] = new ColRegion(first, last, color, opac);
+ assert(N<MAX_NO_OF_REGIONS -1);
+ N++;
+ DIAG("HL N:%d\n",N);
+}
+**/
+
+// ==================================
+xSection::xSection(int x)
+{
+ X1 = x;
+ X2 = 0xFFF;
+ 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);
+}
+
+/** No descriptions */
+void cColorManager::SetBgColor(unsigned int bgColor)
+{
+// cColorManager::BgColor = bgColor;
+}
diff --git a/dxr3colormanager.h b/dxr3colormanager.h
new file mode 100644
index 0000000..063252d
--- /dev/null
+++ b/dxr3colormanager.h
@@ -0,0 +1,122 @@
+/***************************************************************************
+ 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 30
+
+
+// ==================================
+class xSection
+{
+public:
+ xSection(int x);
+ bool HasColor(unsigned int color, unsigned char &ColorIndex);
+ unsigned char AddColor(unsigned int color);
+ bool AllColorsUsed() {/*DIAG("AllColorsUsed: %d\n",NrOfColors)*/;if(NrOfColors >= 4) return(true); else return (false); };
+ 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);
+
+ /** Adds a new highlight region beginning from FIRST to LAST column */
+// void AddRegion(int first, int last, unsigned int color, unsigned int opac=0xFFFF);
+
+ /** No descriptions */
+ void SetBgColor(unsigned int bgColor);
+
+private: // Private attributes
+ yRegion *hlr[MAX_NO_OF_REGIONS];
+ int NrOfRegions;
+ bool isopen;
+ unsigned char spudata[2*4096];
+ unsigned int BgCol;
+ int MaxY;
+
+ /** Opens a new highlight region */
+ void OpenRegion(int y, int NrOfSecToCopy = 0);
+ /** Closes the spu-highlight region */
+ void CloseRegion(int y);
+
+ xSection* NewSection(int x);
+ xSection *GetSection(int x, int &n);
+};
+
+#endif /*_DXR3COLORMANAGER_H_*/
diff --git a/dxr3configdata.c b/dxr3configdata.c
new file mode 100644
index 0000000..ee46081
--- /dev/null
+++ b/dxr3configdata.c
@@ -0,0 +1,16 @@
+//#include <stdio.h>
+#include "dxr3configdata.h"
+
+// ==================================
+// constr.
+cDxr3ConfigData::cDxr3ConfigData()
+{
+ UseDigitalOut = 0;
+ Dxr3Card = 0;
+ ForceLetterBox = 0;
+ Ac3OutPut = 0;
+ m_videoMode = PAL;
+ m_menuMode = SUBPICTURE;
+ m_debug = 1;
+ m_debuglevel = 0;
+}
diff --git a/dxr3configdata.h b/dxr3configdata.h
new file mode 100644
index 0000000..672c3f9
--- /dev/null
+++ b/dxr3configdata.h
@@ -0,0 +1,76 @@
+#ifndef _DXR3_CONFIGDATA_H_
+#define _DXR3_CONFIGDATA_H_
+
+//#include <stdio.h>
+
+#include "dxr3singleton.h"
+
+// ==================================
+// possible video modes
+enum eVideoMode
+{
+ PAL = 0,
+ PAL60,
+ NTSC
+};
+
+// ==================================
+// possible menu modes
+enum eMenuMode
+{
+ SUBPICTURE = 0,
+ MPEG
+};
+
+// ==================================
+// possible debug levels
+enum eDebugLevel
+{
+ LOW = 0,
+ EVERYTHING
+};
+
+// ==================================
+// global interface to access all config
+// datas of this plugin
+class cDxr3ConfigData : public Singleton<cDxr3ConfigData>
+{
+public:
+ cDxr3ConfigData();
+ ~cDxr3ConfigData() {}
+
+ int GetUseDigitalOut() const { return UseDigitalOut; }
+ int SetUseDigitalOut(int value) { return UseDigitalOut = value; }
+ int GetDxr3Card() const { return Dxr3Card; }
+ int SetDxr3Card(int value) { return Dxr3Card = value; }
+ int GetForceLetterBox() const { return ForceLetterBox; }
+ int SetForceLetterBox(int value) { return ForceLetterBox = value; }
+ int GetAc3OutPut() const { return Ac3OutPut; }
+ int SetAc3OutPut(int value) { return 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 GetDebug() const { return m_debug; }
+ int SetDebug(int value) { return m_debug = value; }
+ int GetDebugLevel() const { return m_debuglevel; }
+ int SetDebugLevel(int value) { return m_debuglevel = value; }
+
+ // some little helpers to save some writing
+ int GetDebugLow() const { return (m_debug && !m_debuglevel); }
+ int GetDebugEverything() const { if (m_debug == 1 && m_debuglevel == 0) { return 1; } else { return 0; } }
+
+protected:
+ int UseDigitalOut;
+ int Dxr3Card;
+ int ForceLetterBox;
+ int Ac3OutPut;
+ eVideoMode m_videoMode;
+ eMenuMode m_menuMode;
+ int m_debug;
+ int m_debuglevel;
+};
+
+#endif /*_DXR3_CONFIGDATA_H_*/
diff --git a/dxr3cpu.c b/dxr3cpu.c
new file mode 100644
index 0000000..4666e89
--- /dev/null
+++ b/dxr3cpu.c
@@ -0,0 +1,127 @@
+/*
+* dxr3cpu.c
+*
+* Copyright (C) 2004 Christian Gmeiner
+*
+* Taken from Nesseia-Renderengine Copyright (C) 2003-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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+*/
+
+#include "dxr3cpu.h"
+#include "dxr3log.h"
+#include "dxr3memcpy.h"
+
+// ==================================
+// const.
+cDxr3CPU::cDxr3CPU()
+{
+ unsigned long eax,ebx,edx,unused;
+
+ // readout the vendor
+ cpuid(0,eax,ebx,unused,edx);
+
+ // set Vendor to ""
+ memset(m_Info.Vendor, 0, 16);
+
+ // connect the single register values to the vendor string
+ // maybe there is an better solution - i will google :)
+ *(unsigned long *)(m_Info.Vendor) = ebx;
+ *(unsigned long *)(m_Info.Vendor + 4) = edx;
+ *(unsigned long *)(m_Info.Vendor + 8) = unused;
+
+ // check the features
+ // could we get the needed infos?
+ if (cpuid(1,eax,ebx,unused,edx))
+ {
+ m_Info.MMX = ((edx & 1<<23) != 0);
+ m_Info.SSE = ((edx & 1<<25) != 0);
+ m_Info.SSE2= ((edx & 1<<26) != 0);
+ m_Info.RDTSC=((edx & 1<<4) != 0); /*0x10*/
+ m_Info.HT = ((edx & 1<<28) !=0); // should we do here addinonal checks?
+
+ // 3DNow is a litle bit harder to read out
+ // We read the ext. CPUID level 0x80000000
+ if (cpuid(0x80000000,eax,ebx,unused,edx))
+ {
+ // now in eax there is the max. supported extended CPUID level
+ // we check if theres an extended CPUID level support
+ if (eax >= 0x80000001)
+ {
+ // If we can access the extended CPUID level 0x80000001 we get the
+ // edx register
+ if (cpuid(0x80000001,eax,ebx,unused,edx))
+ {
+ // Now we can mask some AMD specific cpu extensions
+ // 22 ... Extended MMX_MultimediaExtensions
+ m_Info.MMXEXT = ((edx & 1<<22) != 0);
+ m_Info.AMD64Bit = ((edx & 1<<29) != 0);
+ // 30 ... Extended 3DNOW_InstructionExtensions
+ m_Info.Now = ((edx & (1<<31)) != 0);
+ }
+ }
+ }
+ }
+
+ // fill cabs
+ if (m_Info.MMX)
+ {
+ m_Info.caps = CC_MMX;
+ }
+
+ if (m_Info.MMXEXT)
+ {
+ m_Info.caps |= CC_MMXEXT;
+ }
+
+ if (m_Info.SSE)
+ {
+ m_Info.caps |= CC_SSE;
+ }
+
+ if (m_Info.Now)
+ {
+ m_Info.caps |= CC_3DNOW;
+ }
+
+ // print some infos about cpu
+ cLog::Instance() << "cpu vandor: " << m_Info.Vendor << "\n";
+ cLog::Instance() << "cpu extensions:\n";
+ cLog::Instance() << "mmx: " << m_Info.MMX << "\n";
+ cLog::Instance() << "mmx-ext: " << m_Info.MMXEXT << "\n";
+ cLog::Instance() << "sse: " << m_Info.SSE << "\n";
+ cLog::Instance() << "sse2: " << m_Info.SSE2 << "\n";
+ cLog::Instance() << "3dnow: " << m_Info.Now << "\n";
+
+ // now we select the best memcpy mehtode
+ cDxr3MemcpyBench Benchmark(m_Info.caps);
+}
+
+// ==================================
+// does the cpu support cpuid instructions
+bool cDxr3CPU::CheckCPUIDPresence()
+{
+ // todo
+ return true;
+}
+
+// ==================================
+// cpuid function
+bool cDxr3CPU::cpuid(unsigned long function, unsigned long& out_eax, unsigned long& out_ebx, unsigned long& out_ecx, unsigned long& out_edx)
+{
+ asm("cpuid": "=a" (out_eax), "=b" (out_ebx), "=c" (out_ecx), "=d" (out_edx) : "a" (function));
+ return true;
+}
diff --git a/dxr3cpu.h b/dxr3cpu.h
new file mode 100644
index 0000000..b18f510
--- /dev/null
+++ b/dxr3cpu.h
@@ -0,0 +1,107 @@
+/*
+ * dxr3cpu.h
+ *
+ * Copyright (C) 2004 Christian Gmeiner
+ *
+ * Taken (modifized) from Nesseia-Renderengine Copyright (C) 2003-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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _DXR3_CPU_H_
+#define _DXR3_CPU_H_
+
+#include <inttypes.h>
+#include "dxr3singleton.h"
+
+// ==================================
+// all possible cabs
+enum Cpu_cabs
+{
+ CC_MMX = 0x80000000,
+ CC_3DNOW = 0x40000000,
+ CC_MMXEXT = 0x20000000,
+ CC_SSE = 0x10000000,
+ CC_SSE2 = 0x08000000
+};
+
+// ==================================
+// Easy and fast access to all infos
+struct CPUInformation
+{
+ CPUInformation()
+ {
+ AMD = false;
+ INTEL = false;
+ MMX = false;
+ MMXEXT = false;
+ SSE = false;
+ SSE2 = false;
+ Now = false;
+ RDTSC = false;
+ HT = false;
+ AMD64Bit = false;
+ }
+
+ char Vendor[16];
+
+ bool AMD; // is it an AMD CPU?
+ bool INTEL; // is it an Intel CPU?
+ bool MMX; // is MMX-Technology supported?
+ bool MMXEXT; // are Extended MMX_MultimediaExtensions supported?
+ bool SSE; // is SSE-Technology supported?
+ bool SSE2; // is SSE2-Technology supported?
+ bool Now; // is 3DNow-Technology supported?
+ bool RDTSC; // is RDTSC-Technology supported?
+ bool HT; // is HyperThreading supported?
+ bool AMD64Bit; // is it a 64 bit machine?
+
+ uint32_t caps; // all features represanted as caps
+};
+
+// ==================================
+//! Grab some infos about the cpu(s)
+/*!
+If you want to know what the cpu of the
+target machine can do, this class is for you :)
+It is used intern for the math and memcpy part.
+*/
+class cDxr3CPU : public Singleton<cDxr3CPU>
+{
+public:
+ cDxr3CPU();
+ ~cDxr3CPU() {}
+
+ bool HasMMXSupport() const { return m_Info.MMX; }
+ bool HasSSESupport() const { return m_Info.SSE; }
+ bool HasSSE2Support() const { return m_Info.SSE2; }
+ bool Has3DNowSupport() const { return m_Info.Now; }
+ bool HasRDTSCSupport() const { return m_Info.RDTSC; }
+ bool HasHTSupport() const { return m_Info.HT; }
+
+ inline CPUInformation GetInfos() const { return m_Info ;}
+
+private:
+ bool CheckCPUIDPresence();
+
+ // main function to get cpu(s) features
+ bool cpuid(unsigned long function, unsigned long& out_eax, unsigned long& out_ebx, unsigned long& out_ecx, unsigned long& out_edx);
+
+ CPUInformation m_Info;
+};
+
+
+#endif /*_DXR3_CPU_H_*/
diff --git a/dxr3demuxdevice.c b/dxr3demuxdevice.c
new file mode 100644
index 0000000..d39b07b
--- /dev/null
+++ b/dxr3demuxdevice.c
@@ -0,0 +1,662 @@
+/*
+ * dxr3demuxdevice.c:
+ *
+ * See the main source file 'dxr3.c' for copyright information and
+ * how to reach the author.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include "dxr3demuxdevice.h"
+#include <linux/em8300.h>
+#include "dxr3log.h"
+#include "dxr3pesframe.h"
+#include "dxr3configdata.h"
+#include "dxr3log.h"
+
+// ==================================
+// constr.
+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)
+ {
+ cLog::Instance() << "cDxr3DemuxDevice::cDxr3DemuxDevice: failed to allocate memory\n";
+ exit(1);
+ }
+ m_pAudioThread->Start();
+
+ m_pVideoThread = new cDxr3VideoOutThread(dxr3Device, m_vBuf);
+ if (!m_pVideoThread)
+ {
+ cLog::Instance() << "cDxr3DemuxDevice::cDxr3DemuxDevice: failed to allocate memory\n";
+ 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_pVideoThread)
+ {
+ delete m_pVideoThread;
+ }
+}
+
+// ==================================
+// 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();
+
+}
+
+#if VDRVERSNUM < 10307
+// ==================================
+cOsdBase* cDxr3DemuxDevice::NewOsd(int x, int y)
+{
+ return m_dxr3Device.NewOsd(x, y);
+}
+#endif
+
+// ==================================
+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();
+
+ cLog::Instance() << "StillPicture: len = " << length << "\n";
+
+ 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:
+ cLog::Instance() << "i - frame\n";
+ 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.PlayVideoFrame(pesFrame.GetEsStart(), (int) (pesFrame.GetEsLength()), m_ReUseFrame);
+ break;
+
+ case UNKNOWN_FRAME:
+ cLog::Instance() << "frame unknown\n";
+ if (bPlaySuc)
+ {
+ m_dxr3Device.PlayVideoFrame(pesFrame.GetEsStart(), (int) (pesFrame.GetEsLength()), m_ReUseFrame);
+ }
+ break;
+
+ default:
+ cLog::Instance() << "default frame\n";
+ 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());
+ while(!Poll(100));
+ cFixedLengthFrame* pTempFrame = m_vBuf.Push(pesFrame.GetEsStart(), (int) (pesFrame.GetEsLength()), pts, ftVideo);
+ 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());
+ cFixedLengthFrame* pTempFrame = m_vBuf.Push(pesFrame.GetEsStart(), (int) (pesFrame.GetEsLength()), pts, ftVideo);
+ 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;
+ }
+}
diff --git a/dxr3demuxdevice.h b/dxr3demuxdevice.h
new file mode 100644
index 0000000..0bd6add
--- /dev/null
+++ b/dxr3demuxdevice.h
@@ -0,0 +1,75 @@
+/*
+ * dxr3demuxdevice.h:
+ *
+ * See the main source file 'dxr3.c' for copyright information and
+ * how to reach the author.
+ *
+ */
+
+#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);
+
+ #if VDRVERSNUM < 10307
+ cOsdBase* NewOsd(int x, int y);
+ #endif
+
+ 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
diff --git a/dxr3device.c b/dxr3device.c
new file mode 100644
index 0000000..b7e2553
--- /dev/null
+++ b/dxr3device.c
@@ -0,0 +1,472 @@
+#include "dxr3device.h"
+#include "dxr3configdata.h"
+#include "dxr3interface.h"
+#include "dxr3tools.h"
+#include "dxr3log.h"
+
+extern "C"
+{
+ #include <jpeglib.h>
+}
+
+// ==================================
+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)
+{
+#if VDRVERSNUM >= 10307
+ new cDxr3OsdProvider();
+#endif
+}
+
+// replaying
+// ==================================
+bool cDxr3Device::HasDecoder() const
+{
+ // sure we have one ;)
+ return true;
+}
+
+// ==================================
+bool cDxr3Device::CanReplay() const
+{
+ // also sure...
+ return true;
+}
+
+// ==================================
+bool cDxr3Device::SetPlayMode(ePlayMode PlayMode)
+{
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ switch (PlayMode)
+ {
+ case pmNone:
+ cLog::Instance() << "cDxr3Device::SetPlayMode audio/video from decoder\n";
+ break;
+
+ case pmAudioVideo:
+ cLog::Instance() << "cDxr3Device::SetPlayMode audio/video from player\n";
+ break;
+
+ case pmAudioOnly:
+ cLog::Instance() << "cDxr3Device::SetPlayMode audio only from player, video from decoder\n";
+ break;
+
+ case pmAudioOnlyBlack:
+ cLog::Instance() << "cDxr3Device::SetPlayMode audio only from player, no video (black screen)\n";
+ break;
+
+ case pmExtern_THIS_SHOULD_BE_AVOIDED:
+ cLog::Instance() << "cDxr3Device::SetPlayMode this should be avoided\n";
+ break;
+
+ #if VDRVERSNUM >= 10307
+ case pmVideoOnly:
+ cLog::Instance() << "cDxr3Device::SetPlayMode video only from player, audio from decoder\n";
+ break;
+ #endif
+ }
+ }
+
+ if (PlayMode == pmExtern_THIS_SHOULD_BE_AVOIDED)
+ {
+ Tools::WriteInfoToOsd("Dxr3: Releasing devices\n");
+ 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();
+ }
+
+ cLog::Instance() << "Setting audio mode...";
+
+ if (cDxr3ConfigData::Instance().GetUseDigitalOut())
+ {
+ if (cDxr3ConfigData::Instance().GetAc3OutPut() && m_CalledBySet)
+ {
+ cDxr3Interface::Instance().SetAudioDigitalAC3(); // !!! FIXME
+ cLog::Instance() << "ac3\n";
+ }
+ else
+ {
+ cDxr3Interface::Instance().SetAudioDigitalPCM();
+ cDxr3ConfigData::Instance().SetAc3OutPut(0);
+ cLog::Instance() << "digital pcm\n";
+ }
+ }
+ else
+ {
+ cDxr3Interface::Instance().SetAudioAnalog();
+ cLog::Instance() << "analog\n";
+ }
+
+ return true;
+}
+
+// ==================================
+int64_t cDxr3Device::GetSTC()
+{
+ return cDxr3Interface::Instance().GetSysClock();
+}
+
+// ==================================
+void cDxr3Device::TrickSpeed(int Speed)
+{
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3Device::TrickSpeed(int Speed): " << Speed << "\n";
+ }
+
+
+ m_DemuxDevice.SetTrickMode(DXR3_FAST, Speed);
+
+
+/*
+ switch (Speed)
+ {
+ case 6:
+ cLog::Instance() << "Trickspeed: 1x vorwärts\n";
+ break;
+
+ case 3:
+ cLog::Instance() << "Trickspeed: 2x vorwärts\n";
+ break;
+
+ case 1:
+ cLog::Instance() << "Trickspeed: 3x vorwärts\n";
+ break;
+ };
+*/
+/*
+ 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;
+ 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)
+{
+ 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 0;
+ }
+
+ 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
+void cDxr3Device::PlayAudio(const uchar *Data, int Length)
+{
+ int retLength = 0;
+
+ #if VDRVERSNUM < 10307
+ if (!m_AC3Present)
+ {
+ Interface->Write(Interface->Width() / 2, 0, "AC3", clrRed);
+ }
+ #endif
+
+ m_AC3Present = true;
+
+ if ((m_DemuxDevice.GetDemuxMode() == DXR3_DEMUX_TRICK_MODE &&
+ m_DemuxDevice.GetTrickState() == DXR3_FREEZE) || cDxr3Interface::Instance().IsExternalReleased())
+ {
+ //usleep(1000000);
+ return;
+ }
+
+ if (m_strBuf.length())
+ {
+ m_strBuf.append((const char*)Data, Length);
+ retLength = m_DemuxDevice.DemuxPes((const uint8_t*)m_strBuf.data(), m_strBuf.length(), true);
+ }
+ 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);
+ }
+ }
+}
+
+// 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) < 0)
+ {
+ LOG_ERROR_STR(FileName);
+ }
+ }
+ fclose(f);
+ }
+ else
+ {
+ return false;
+ }
+
+ delete Data;
+ return true;
+}
+
+// ==================================
+void cDxr3Device::SetVideoFormat(bool VideoFormat16_9)
+{
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3Device::SetPlayMode(ePlayMode PlayMode)() done\n";
+ }
+ // Do we need this function?
+}
+
+// ==================================
+// sets volume for audio output
+void cDxr3Device::SetVolumeDevice(int Volume)
+{
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "change volume to " << Volume << " \n";
+ }
+ cDxr3Interface::Instance().SetVolume(Volume);
+}
+
+// ==================================
+// get spudecoder
+cSpuDecoder *cDxr3Device::GetSpuDecoder(void)
+{
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3Device::GetSpuDecoder";
+ }
+
+ if (!m_spuDecoder && IsPrimaryDevice())
+ {
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3Device::GetSpuDecoder: ok";
+ }
+ m_spuDecoder = new cDxr3SpuDecoder();
+ }
+ return m_spuDecoder;
+}
+
+#if VDRVERSNUM < 10307
+// ==================================
+// return osd
+cOsdBase *cDxr3Device::NewOsd(int x, int y)
+{
+ return m_DemuxDevice.NewOsd(x, y);
+}
+#endif
+
diff --git a/dxr3device.h b/dxr3device.h
new file mode 100644
index 0000000..69ad28d
--- /dev/null
+++ b/dxr3device.h
@@ -0,0 +1,65 @@
+#ifndef _DXR3_DEVICE_H_
+#define _DXR3_DEVICE_H_
+
+#include "dxr3interface.h"
+#include "dxr3log.h"
+#include "dxr3demuxdevice.h"
+#include "dxr3spudecoder.h"
+#include <string>
+using namespace std;
+
+// ==================================
+// our device :)
+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);
+ virtual void PlayAudio(const uchar *Data, int Length);
+
+ // 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);
+
+ // osd
+ virtual cSpuDecoder *GetSpuDecoder();
+ #if VDRVERSNUM < 10307
+ virtual cOsdBase* NewOsd(int x, int y);
+ #endif
+
+ // 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;
+ 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_*/
diff --git a/dxr3ffmpeg.c b/dxr3ffmpeg.c
new file mode 100644
index 0000000..e35319a
--- /dev/null
+++ b/dxr3ffmpeg.c
@@ -0,0 +1,72 @@
+/*
+ * dxr3audiodecoder.c:
+ *
+ * See the main source file 'dxr3.c' for copyright information and
+ * how to reach the author.
+ *
+ */
+
+#include "dxr3ffmpeg.h"
+
+#include "dxr3configdata.h"
+#include "dxr3log.h"
+
+// ==================================
+cDxr3Ffmepg::cDxr3Ffmepg()
+{
+ avcodec_init();
+ avcodec_register_all();
+}
+
+// ==================================
+bool cDxr3Ffmepg::FindCodec(struct Dxr3Codec& Codec)
+{
+ // find codec
+ Codec.codec = avcodec_find_decoder(Codec.id);
+
+ if (!Codec.codec)
+ {
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3Ffmepg::OpenCodec(struct Dxr3Codec& Codec) codec not found (" << Codec.id << ")\n";
+ }
+ return false;
+ }
+
+ // init codec_context
+ memset(&Codec.codec_context, 0, sizeof(Codec.codec_context));
+
+ return true;
+}
+
+// ==================================
+bool cDxr3Ffmepg::OpenCodec(struct Dxr3Codec& Codec)
+{
+ // try to open codec
+ int result = avcodec_open(&Codec.codec_context, Codec.codec);
+
+ if (result < 0)
+ {
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3Ffmepg::OpenCodec(struct Dxr3Codec& Codec) coudnt open codec (" << Codec.id << ")\n";
+ }
+ return false;
+ }
+ else
+ {
+ Codec.Open = true;
+ }
+
+ return true;
+}
+
+// ==================================
+void cDxr3Ffmepg::CloseCodec(struct Dxr3Codec& Codec)
+{
+ if (Codec.Open)
+ {
+ avcodec_close(&Codec.codec_context);
+ Codec.Open = false;
+ }
+}
diff --git a/dxr3ffmpeg.h b/dxr3ffmpeg.h
new file mode 100644
index 0000000..7795f74
--- /dev/null
+++ b/dxr3ffmpeg.h
@@ -0,0 +1,42 @@
+#ifndef _DXR3_FFMPEG_H_
+#define _DXR3_FFMPEG_H_
+
+extern "C"
+{
+ #include <avcodec.h>
+};
+
+//#include <stdlib.h>
+//#include <stdint.h>
+#include <string.h>
+#include "dxr3singleton.h"
+
+// ==================================
+// a codec used by this plugin
+struct Dxr3Codec
+{
+ Dxr3Codec() : Open(false) {}
+
+ AVCodec* codec;
+ AVCodecContext codec_context;
+ enum CodecID id;
+ bool Open;
+};
+
+// ==================================
+// class to work with ffmpeg
+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_*/
diff --git a/dxr3generaldefines.h b/dxr3generaldefines.h
new file mode 100644
index 0000000..29a0ae6
--- /dev/null
+++ b/dxr3generaldefines.h
@@ -0,0 +1,37 @@
+/*
+ * dxr3generaldefines.h:
+ *
+ * See the main source file 'dxr3.c' for copyright information and
+ * how to reach the author.
+ *
+ */
+
+#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
diff --git a/dxr3i18n.c b/dxr3i18n.c
new file mode 100644
index 0000000..2c91e33
--- /dev/null
+++ b/dxr3i18n.c
@@ -0,0 +1,804 @@
+#include "dxr3i18n.h"
+
+const char *i18n_name = 0;
+
+// vdr 1.1.32 -> 16
+// vdr 1.3.2 -> 17
+// vdr 1.3.7 -> 18
+
+// Digital audio output
+// DXR3 card
+// DXR3 video mode
+// DXR3 menu mode
+// Reset DXR3 Hardware
+// Toggle Force LetterBox
+// Analog Output
+// AC3 Output On
+// AC3 Output Off
+// Digital Output
+// Sub-Picutre
+// MPEG
+// Dxr3: Releasing devices
+
+// add
+// Dxr3: Releasing devices
+/*
+ * Translations provided by:
+ *
+ * Slovenian Miha Setina <mihasetina@softhome.net> and Matjaz Thaler <matjaz.thaler@guest.arnes.si>
+ * Italian Alberto Carraro <bertocar@tin.it> and Antonio Ospite <ospite@studenti.unina.it>
+ * Dutch Arnold Niessen <niessen@iae.nl> <arnold.niessen@philips.com> and Hans Dingemans <hans.dingemans@tacticalops.nl>
+ * Portuguese Paulo Lopes <pmml@netvita.pt>
+ * French Jean-Claude Repetto <jc@repetto.org>, Olivier Jacques <jacquesolivier@hotmail.com> and Gregoire Favre <greg@magma.unil.ch>
+ * Norwegian Jørgen Tvedt <pjtvedt@online.no> and Truls Slevigen <truls@slevigen.no>
+ * Finnish Hannu Savolainen <hannu@opensound.com>, Jaakko Hyvätti <jaakko@hyvatti.iki.fi>, Niko Tarnanen <niko.tarnanen@hut.fi> and Rolf Ahrenberg <rahrenbe@cc.hut.fi>
+ * Polish Michael Rakowski <mrak@gmx.de>
+ * Spanish Ruben Nunez Francisco <ruben.nunez@tang-it.com>
+ * Greek Dimitrios Dimitrakos <mail@dimitrios.de>
+ * Swedish Tomas Prybil <tomas@prybil.se> and Jan Ekholm <chakie@infa.abo.fi>
+ * Romanian Paul Lacatus <paul@campina.iiruc.ro>
+ * Hungarian Istvan Koenigsberger <istvnko@hotmail.com> and Guido Josten <guido.josten@t-online.de>
+ * Catalanian Marc Rovira Vall <tm05462@salleURL.edu>, Ramon Roca <ramon.roca@xcombo.com> and Jordi Vilà <jvila@tinet.org>
+ * Russian Vyacheslav Dikonov <sdiconov@mail.ru>
+ * Croatian Drazen Dupor <drazen.dupor@dupor.com>
+ *
+ */
+
+
+#if VDRVERSNUM >= 10307
+// vdr 1.3.7 -> 18 languages
+
+/*
+const tI18nPhrase Phrases[] = {
+ // The name of the language (this MUST be the first phrase!):
+ { "English",
+ "Deutsch",
+ "Slovenski",
+ "Italiano",
+ "Nederlands",
+ "Português",
+ "Français",
+ "Norsk",
+ "suomi", // this is not a typo - it's really lowercase!
+ "Polski",
+ "Español",
+ "ÅëëçíéêÜ", // Greek
+ "Svenska",
+ "Romaneste",
+ "Magyar",
+ "Català",
+ "ÀãááÚØÙ", // Russian
+ "Hrvatski",
+ },
+*/
+
+const tI18nPhrase Phrases[] = {
+ {
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ },
+ {
+ "Digital audio output",
+ "Digitaler Audioausgang",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "Saída áudio digital",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "DXR3 card",
+ "DXR3 Karte",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "Placa DXR3",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "DXR3 video mode",
+ "DXR3 Video-Modus",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "Modo vídeo DXR3",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "DXR3 menu mode",
+ "DXR3 Menü-Modus",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "Modo menu DXR3",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "Reset DXR3 Hardware",
+ "Resete DXR3 Hardware",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "Reiniciar DXR3",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "Toggle Force LetterBox",
+ "LetterBox erzwingen",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "Activar Forçar LetterBox",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "Analog Output",
+ "Analoge Ausgabe",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "Saída Analógica",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "AC3 Output On",
+ "AC3 Ausgabe Ein",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "Saída AC3 Activa",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "AC3 Output Off",
+ "AC3 Ausgabe Aus",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "Saída AC3 Inactiva",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "Digital Output",
+ "Digitaler Ausgang",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "Saída Digital",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Imagem",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ },
+ { "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ },
+ { "DXR3: Releasing devices",
+ "DXR3: Releasing devices",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "DXR3: A libertar dispositivos",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { NULL }
+};
+
+
+#elif VDRVERSNUM <= 10302
+// vdr 1.1.32 -> 16 languages
+
+const tI18nPhrase Phrases[] = {
+ {
+ "Digital audio output",
+ "Digitaler Audioausgang",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "DXR3 card",
+ "DXR3 Karte",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "DXR3 video mode",
+ "DXR3 Video-Modus",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "DXR3 menu mode",
+ "DXR3 Menü-Modus",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "Reset DXR3 Hardware",
+ "Resete DXR3 Hardware",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "Toggle Force LetterBox",
+ "LetterBox erzwingen",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "Analog Output",
+ "Analoge Ausgabe",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "AC3 Output On",
+ "AC3 Ausgabe Ein",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "AC3 Output Off",
+ "AC3 Ausgabe Aus",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "Digital Output",
+ "Digitaler Ausgang",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ },
+ { "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ },
+ { NULL }
+};
+
+#else
+// vdr 1.3.2 -> 17 languages
+
+const tI18nPhrase Phrases[] = {
+ {
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ "DXR3",
+ },
+ {
+ "Digital audio output",
+ "Digitaler Audioausgang",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "DXR3 card",
+ "DXR3 Karte",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "DXR3 video mode",
+ "DXR3 Video-Modus",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "DXR3 menu mode",
+ "DXR3 Menü-Modus",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "Reset DXR3 Hardware",
+ "Resete DXR3 Hardware",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "Toggle Force LetterBox",
+ "LetterBox erzwingen",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "Analog Output",
+ "Analoge Ausgabe",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "AC3 Output On",
+ "AC3 Ausgabe Ein",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "AC3 Output Off",
+ "AC3 Ausgabe Aus",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "Digital Output",
+ "Digitaler Ausgang",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
+ { "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ "Sub-Picture",
+ },
+ { "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ "MPEG",
+ },
+ { NULL }
+};
+
+#endif
diff --git a/dxr3i18n.h b/dxr3i18n.h
new file mode 100644
index 0000000..990d2ee
--- /dev/null
+++ b/dxr3i18n.h
@@ -0,0 +1,12 @@
+#ifndef _DXR3_I18N_H_
+#define _DXR3_I18N_H_
+
+#include <vdr/i18n.h>
+
+extern const char *i18n_name;
+extern const tI18nPhrase Phrases[];
+
+#undef tr
+#define tr(s) I18nTranslate(s, i18n_name)
+
+#endif /*_DXR3_I18N_H_*/
diff --git a/dxr3interface.c b/dxr3interface.c
new file mode 100644
index 0000000..50302d6
--- /dev/null
+++ b/dxr3interface.c
@@ -0,0 +1,1072 @@
+#include <assert.h>
+#include <math.h>
+#include <sys/soundcard.h>
+#include "dxr3interface.h"
+#include "dxr3syncbuffer.h"
+
+#include "dxr3log.h"
+#include "dxr3configdata.h"
+
+// ==================================
+const int LPCM_HEADER_LENGTH = 7;
+const int ZEROBUFFER_SIZE = 4096;
+uint8_t zerobuffer[ZEROBUFFER_SIZE] = {0};
+
+// ==================================
+// 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 the 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)
+ {
+ cLog::Instance() << "Unable to open " << FileName << "\n";
+ }
+ return fd;
+}
+
+// ==================================
+cDxr3Interface::cDxr3Interface()
+{
+ // open control stream
+ m_fdControl = Dxr3Open("", cDxr3ConfigData::Instance().GetDxr3Card(), O_WRONLY | O_SYNC);
+ if (!m_fdControl)
+ {
+ cLog::Instance() << "Unable to open the control stream!\n";
+ cLog::Instance() << "Please check if the dxr3 modules are loaded!\n";
+ }
+
+ // 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 || !m_fdAudio || !m_fdSpu)
+ {
+ cLog::Instance() << "Unable to open one of the 'mulitmedia' streams!\n";
+ exit(1);
+ }
+
+ m_pClock = new cDxr3SysClock(m_fdControl, m_fdVideo, m_fdSpu);
+
+ if (!m_pClock)
+ {
+ cLog::Instance() << "Unable to allocate memory for m_pClock in cDxr3Interface\n";
+ exit(1);
+ }
+
+ // set default values
+ m_AudioActive = false;
+ m_VideoActive = false;
+ m_OverlayActive = false;
+ m_ExternalReleased = false;
+ m_volume = 255;
+ m_horizontal = 720;
+ m_audioChannelCount = UNKNOWN_CHANNEL_COUNT;
+ m_audioDataRate = 0;
+ m_audioSampleSize = 0;
+
+ // default value 9 = unused value
+ m_audioMode = 9;
+ m_aspectRatio = UNKNOWN_ASPECT_RATIO;
+ m_spuMode = EM8300_SPUMODE_OFF;
+
+ // configure device based on settings
+ ConfigureDevice();
+
+ PlayBlackFrame();
+ SetChannelCount(1);
+}
+
+// ==================================
+cDxr3Interface::~cDxr3Interface()
+{
+ // close filehandles
+ if (m_fdControl)
+ {
+ close(m_fdControl);
+ }
+ if (m_fdVideo)
+ {
+ close(m_fdVideo);
+ }
+ if (m_fdSpu)
+ {
+ close(m_fdSpu);
+ }
+ if (m_fdAudio)
+ {
+ 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)
+ {
+ cLog::Instance() << "cDxr3AbsDevice::SetAudioAnalog Unable to set audiomode!\n";
+ }
+ 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)
+ {
+ cLog::Instance() << "cDxr3AbsDevice::SetAudioAnalog Unable to set audiomode!\n";
+ }
+ 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)
+ {
+ cLog::Instance() << "cDxr3AbsDevice::SetAudioAnalog Unable to set audiomode!\n";
+ }
+ ReOpenAudio();
+ }
+
+ Unlock();
+ }
+}
+
+// ==================================
+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)
+ {
+ cLog::Instance() << "cDxr3AbsDevice::SetAudioSpeed Unable to set dsp speed\n";
+ }
+ }
+ }
+ m_audioDataRate = speed;
+ }
+}
+
+// ==================================
+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)
+ {
+ cLog::Instance() << "cDxr3AbsDevice::SetChannelCount Unable to set channel count\n";
+ }
+ }
+ }
+ m_audioChannelCount = count;
+ }
+}
+
+// ==================================
+void cDxr3Interface::SetAudioSampleSize(uint32_t sampleSize)
+{
+ if (!m_ExternalReleased)
+ {
+ if (ioctl(m_fdAudio, SNDCTL_DSP_SAMPLESIZE, sampleSize))
+ {
+ cLog::Instance() <<"cDxr3AbsDevice::SetAudioSampleSize Unable to set audio sample size\n";
+ }
+ }
+ 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;
+}
+
+// ==================================
+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 proeccesing 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)
+ {
+ cLog::Instance() << "cDxr3AbsDevice::EnableSpu Unable to set subpicture mode!\n";
+ }
+ }
+
+ 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)
+ {
+ cLog::Instance() << "cDxr3AbsDevice::EnableSpu Unable to set subpicture mode!\n";
+ }
+ }
+
+ Unlock();
+}
+
+// ==================================
+// disable audio output of dxr3
+void cDxr3Interface::DisableAudio()
+{
+ m_AudioActive = false;
+
+ // we wirte 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 we check, if it is enable yet
+ 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)
+ {
+ //######
+ cLog::Instance() << "Singnalmode failed\n";
+ 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)
+ {
+ //######
+ cLog::Instance() << "seting up screen failed\n";
+ 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)
+ {
+ //######
+ cLog::Instance() << "seting up window failed\n";
+ return;
+ }
+
+ m_OverlayActive = true;
+}
+
+// ==================================
+// disable overlay mode of the dxr3
+void cDxr3Interface::DisanleOverlay()
+{
+ // is it allready 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)
+ {
+ cLog::Instance() << "cDxr3AbsDevice::GetAspectRatio Unable to get aspect ratio\n";
+ }
+ }
+
+ Unlock();
+ return ioval;
+}
+
+// ==================================
+void cDxr3Interface::SetAspectRatio(uint32_t ratio)
+{
+ static int requestCounter = 0;
+
+ Lock();
+
+ if (cDxr3ConfigData::Instance().GetForceLetterBox()) ratio = EM8300_ASPECTRATIO_16_9;
+
+ 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)
+ {
+ cLog::Instance() << "cDxr3AbsDevice::SetAspectRatio Unable to set aspect ratio\n";
+ }
+ 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)
+ {
+ cLog::Instance() << "cDxr3Device::SetPlayMode Unable to set playmode!\n";
+ }
+ reg.microcode_register = 1;
+ reg.reg = 0;
+ reg.val = MVCOMMAND_SYNC;
+
+ if (ioctl(m_fdControl, EM8300_IOCTL_WRITEREG, &reg) < 0)
+ {
+ cLog::Instance() << "cDxr3Device::SetPlayMode Unable to start em8300 sync engine\n";
+ }
+ }
+
+ Unlock();
+}
+
+// ==================================
+void cDxr3Interface::Pause()
+{
+ int ioval = EM8300_PLAYMODE_PAUSED;
+ Lock();
+
+ if (!m_ExternalReleased)
+ {
+ if (ioctl(m_fdControl, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0)
+ {
+ cLog::Instance() << "cDxr3Device::Pause Unable to set playmode!\n";
+ }
+ }
+
+ Unlock();
+}
+// ==================================
+void cDxr3Interface::SingleStep()
+{
+ int ioval = EM8300_PLAYMODE_SINGLESTEP;
+ Lock();
+
+ if (!m_ExternalReleased)
+ {
+ if (ioctl(m_fdControl, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
+ cLog::Instance() << "cDxr3Device::Pause Unable to set playmode!\n";
+ }
+ }
+
+ 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)
+ {
+ cLog::Instance() << "times: " << times << "\n";
+ }
+
+ 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());
+ }
+}
+
+// ==================================
+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?
+
+ if (m_AudioActive)
+ {
+ Lock();
+
+ SetAudioSpeed(pFrame->GetDataRate());
+ SetChannelCount(pFrame->GetChannelCount());
+
+ if (!m_ExternalReleased)
+ {
+ if (!cDxr3ConfigData::Instance().GetAc3OutPut()) ResampleVolume((short*)pFrame->GetData(), pFrame->GetCount());
+ write(m_fdAudio, pFrame->GetData(), pFrame->GetCount());
+ }
+
+ 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)) Resuscitation();
+ if (written != length)
+ {
+ cLog::Instance() << "cDxr3Interface::PlayAudioFrame(uint8_t* pBuf, int length): Not written = " << length - written << "\n";
+ }
+ }
+ 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];
+ assert(!((length - LPCM_HEADER_LENGTH) % 2)); // only even number of bytes are allowed
+
+ 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 > 0) close(m_fdControl);
+ if (m_fdVideo > 0) close(m_fdVideo);
+ if (m_fdSpu > 0) close(m_fdSpu);
+ if (m_fdAudio > 0) close(m_fdAudio);
+ m_fdControl = m_fdVideo = m_fdSpu = m_fdAudio = -1;
+
+ 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)
+ {
+ cLog::Instance() << "Unable to allocate memory for m_pClock in cDxr3Interface\n";
+ exit(1);
+ }
+
+ SetChannelCount(1);
+ m_ExternalReleased = false;
+ }
+
+ Resuscitation();
+ }
+
+ Unlock();
+}
+
+
+// tools
+// ==================================
+// play blackframe 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;
+
+ Unlock();
+}
+
+// ==================================
+void cDxr3Interface::ReOpenAudio()
+{
+ Lock();
+
+ if (!m_ExternalReleased)
+ {
+ if (m_fdAudio > 0)
+ {
+ int bufsize = 0;
+ ioctl(m_fdAudio, SNDCTL_DSP_GETODELAY, &bufsize);
+ usleep(bufsize / 192 * 1000);
+
+ delete m_pClock;
+ close(m_fdAudio);
+
+ m_fdAudio = open("/dev/em8300_ma-0", 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();
+}
+
+#if VDRVERSNUM < 10307
+// ==================================
+cOsdBase* cDxr3Interface::NewOsd(int x, int y)
+{
+ return new cDxr3Osd(x, y);
+}
+#endif
+
+// ==================================
+// uploadroutine for microcode
+void cDxr3Interface::UploadMicroCode()
+{
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3Interface::UploadMicroCode: uploading...";
+ }
+
+ em8300_microcode_t em8300_microcode;
+ const char* MICRO_CODE_FILE = "/usr/share/misc/em8300.uc";
+ struct stat s;
+ int UCODE = open(MICRO_CODE_FILE, O_RDONLY);
+
+ if (UCODE <0)
+ {
+ cLog::Instance() << "Unable to open microcode file " << MICRO_CODE_FILE << " for reading\n";
+ exit(1);
+ }
+
+ if (fstat(UCODE, &s ) <0)
+ {
+ cLog::Instance() << "Unable to fstat ucode file\n";
+ exit(1);
+ }
+
+ // read microcode
+ em8300_microcode.ucode = new char[s.st_size];
+ if (em8300_microcode.ucode == NULL)
+ {
+ cLog::Instance() << "Unable to malloc() space for ucode\n";
+ exit(1);
+ }
+
+ if (read(UCODE,em8300_microcode.ucode,s.st_size) < 1)
+ {
+ cLog::Instance() << "Unable to read data from microcode file\n";
+ // 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)
+ {
+ cLog::Instance() << "Microcode upload to failed!! \n";
+ // free memory to avoid memory leak
+ delete [] (char*) em8300_microcode.ucode;
+ exit(1);
+ }
+ delete [] (char*) em8300_microcode.ucode;
+
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "...done\n";
+ }
+}
+
+// ==================================
+// config and setup device via ioctl calls
+void cDxr3Interface::ConfigureDevice()
+{
+ uint32_t videomode = 0;
+
+ // set video mode
+ if (cDxr3ConfigData::Instance().GetVideoMode() == PAL)
+ {
+ videomode = EM8300_VIDEOMODE_PAL;
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3Interface::ConfigureDevice: Videomode = PAL\n";
+ }
+ }
+ else if (cDxr3ConfigData::Instance().GetVideoMode() == PAL60)
+ {
+ videomode = EM8300_VIDEOMODE_PAL60;
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3Interface::ConfigureDevice: Videomode = PAL60\n";
+ }
+ }
+ else
+ {
+ videomode = EM8300_VIDEOMODE_NTSC;
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3Interface::ConfigureDevice: Videomode = NTSC\n";
+ }
+ }
+
+ // make ioctl
+ if (ioctl(m_fdControl, EM8300_IOCTL_SET_VIDEOMODE, &videomode) == -1)
+ {
+ cLog::Instance() << "Unable to set videomode\n";
+ exit(1);
+ }
+
+ // set audio mode
+ if (!cDxr3ConfigData::Instance().GetUseDigitalOut())
+ {
+ SetAudioAnalog();
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3Interface::ConfigureDevice: Audiomode = Analog\n";
+ }
+ }
+}
+
+// ==================================
+// reset whole hardware
+void cDxr3Interface::Resuscitation()
+{
+ time_t startt = time(&startt);
+ time_t endt = 0;
+ m_ExternalReleased = true;
+ dsyslog("cDxr3Interface::Resuscitation Device failure detected");
+
+ UploadMicroCode();
+ dsyslog("cDxr3Interface::Resuscitation Micro code upload successfully");
+
+// NonBlockingCloseOpen();
+ m_ExternalReleased = false;
+
+ endt = time(&endt);
+
+ dsyslog("cDxr3Interface::Resuscitation Reopening devices took %d", (int)(endt - startt));
+
+ if (endt - startt > 4)
+ {
+ exit(1);
+ }
+
+ ConfigureDevice();
+}
+
+// ==================================
+void cDxr3Interface::ResampleVolume(short* pcmbuf, int size)
+{
+ if (m_volume == 0)
+ {
+ memset(pcmbuf, 0, size);
+ }
+ else if (m_volume != 255)
+ {
+ 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++)
+ {
+ 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();
+ cLog::Instance() << "cDxr3Interface: Resting DXR3 hardware\n";
+ Resuscitation();
+ Unlock();
+}
+
+// ==================================
+cMutex* cDxr3Interface::m_pMutex = new cMutex;
diff --git a/dxr3interface.h b/dxr3interface.h
new file mode 100644
index 0000000..d1df60e
--- /dev/null
+++ b/dxr3interface.h
@@ -0,0 +1,136 @@
+#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 "dxr3log.h"
+#include "dxr3configdata.h"
+#include "dxr3sysclock.h"
+#include "dxr3osd.h"
+
+// ==================================
+class cFixedLengthFrame;
+
+// ==================================
+// interafce to dxr3-card
+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 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);
+
+ // 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;};
+
+ // 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
+ #if VDRVERSNUM < 10307
+ cOsdBase* NewOsd(int x, int y);
+ #endif
+
+ 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();
+
+private:
+ // file handles
+ int m_fdControl;
+ int m_fdVideo;
+ int m_fdSpu;
+ int m_fdAudio;
+
+ // dxr3 clock
+ cDxr3SysClock* m_pClock;
+
+ uint32_t m_audioChannelCount;
+ uint32_t m_audioDataRate;
+ int m_aspectDelayCounter;
+ uint32_t m_aspectRatio;
+ uint32_t m_horizontal;
+ uint32_t m_audioSampleSize;
+ uint32_t m_audioMode;
+ uint32_t m_spuMode;
+ bool m_ExternalReleased; // is dxr3 used by e.g. mplayer?
+ int m_volume;
+ bool m_AudioActive;
+ bool m_VideoActive;
+ bool m_OverlayActive;
+
+ // spu
+// cDxr3InterfaceSpu m_SpuInterface;
+
+ void UploadMicroCode();
+ void ConfigureDevice();
+ void ResampleVolume(short* pcmbuf, int size);
+ void Resuscitation();
+
+protected:
+ static cMutex* m_pMutex;
+
+ static void Lock() { cDxr3Interface::m_pMutex->Lock(); }
+ static void Unlock() { cDxr3Interface::m_pMutex->Unlock(); }
+};
+
+#endif /*_DXR3_INTERFACE_H_*/
diff --git a/dxr3interface_spu_encoder.c b/dxr3interface_spu_encoder.c
new file mode 100644
index 0000000..59b1a33
--- /dev/null
+++ b/dxr3interface_spu_encoder.c
@@ -0,0 +1,620 @@
+/*
+ * spuenc.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "dxr3interface_spu_encoder.h"
+
+/*
+ToDo:
+ - cSPUEncoder::encode_do_row: FIXME: watch this space for EOL
+*/
+
+
+// ==================================
+// 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;
+}
+
+// ==================================
+// main function for the osd
+// makes life nicer :)
+int cSPUEncoder::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, const void *data)
+{
+ u_char *cp;
+ unsigned char idx = 0;
+ int opacity = 0;
+#if VDRVERSNUM >= 10307
+ const tColor *col;
+#else
+ eDvbColor *col;
+#endif
+
+ switch (cmd)
+ {
+ case OSD_SetWindow:
+ // (x0) set window with number 0<x0<8 as current
+ if (x0 < 8 && x0 > 0)
+ {
+ m_lastwindow = x0;
+ return 0;
+ }
+
+ return -1;
+ break;
+
+ case OSD_Open:
+ // (x0,y0,x1,y1,BitPerPixel[2/4/8](color&0x0F),mix[0..15](color&0xF0))
+ // Opens OSD with this size and bit depth
+ // returns 0 on success, -1 on DRAM allocation error, -2 on "already open"
+ m_windows[m_lastwindow].x0 = x0;
+ m_windows[m_lastwindow].y0 = y0;
+ m_windows[m_lastwindow].x1 = x1;
+ m_windows[m_lastwindow].y1 = y1;
+
+ return 0;
+ break;
+
+ case OSD_SetPalette:
+ // Spu->Cmd(OSD_SetPalette, 0, NumColors - 1, 0, 0, 0, Colors);
+ // (firstcolor{color},lastcolor{x0},data)
+ // Set a number of entries in the palette
+ // sets the entries "firstcolor" through "lastcolor" from the array "data"
+ // data has 4 byte for each color:
+ // R,G,B, and a opacity value: 0->transparent, 1..254->mix, 255->pixel
+
+ #if VDRVERSNUM >= 10307
+ col = (tColor*)data;
+ #else
+ eDvbColor *col;
+ col = (eDvbColor*)data;
+ #endif
+
+ m_windows[m_lastwindow].NumColors = x0;
+
+ for (int x = color, i = 0; x <= x0; x++,i++)
+ {
+ m_palManager.AddColor((int)*col & 0xFFFFFF);
+
+ idx = m_palManager.GetIndex((int)*col & 0xFFFFFF);
+ if (m_palManager.HasChanged())
+ {
+ cDxr3Interface::Instance().SetPalette(m_palManager.GetPalette());
+ }
+
+ opacity = ((*col & 0xFF000000) >> 24) * 0xF / 0xFF;
+ m_windows[m_lastwindow].colors[i] = (opacity << 4) | idx;
+ m_windows[m_lastwindow].opacity[i] = opacity;
+ col++;
+ }
+
+ return 0;
+ break;
+
+ case OSD_SetBlock:
+ // (x0,y0,x1,y1,increment{color},data)
+ // fills pixels x0,y0 through x1,y1 with the content of data[]
+ // inc contains the width of one line in the data block,
+ // inc<=0 uses blockwidth as linewidth
+ // returns 0 on success, -1 on clipping all pixel
+
+ CopyBlockIntoOSD
+ (
+ color,
+ m_windows[m_lastwindow].x0 + x0,
+ m_windows[m_lastwindow].y0 + y0,
+ m_windows[m_lastwindow].x0 + x1,
+ m_windows[m_lastwindow].y0 + y1,
+ (u_char *)data
+ );
+
+ // calculate osd size
+ CalculateActiveOsdArea();
+
+ //cLog::Instance() << "(" << m_x0 << ", " << m_x1 << ") - (" << m_y0 << ", " << m_y1 << ")";
+
+ m_encodeddata.count = 0;
+ EncodePixelbufRle(0,0, OSDWIDTH, OSDHEIGHT-1, OSD_Screen, 0, &m_encodeddata);
+
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "OSD Datasize: " << m_encodeddata.count << "\n";
+ }
+
+ if (m_encodeddata.count <= DATASIZE)
+ {
+ cDxr3Interface::Instance().WriteSpu((uint8_t*) &m_encodeddata, m_encodeddata.count);
+ return 0;
+ }
+ else
+ {
+ cLog::Instance() << "Waring: SPU data (" << m_encodeddata.count << ") size exceeds limit\n";
+ return -1;
+ }
+ break;
+
+ case OSD_Close:
+ // clear colors from plattemanager
+
+ #if VDRVERSNUM >= 10307
+ if ((col = (tColor*)m_windows[m_lastwindow].colors) != NULL)
+ #else
+ if ((col = (eDvbColor*)m_windows[m_lastwindow].colors) != NULL)
+ #endif
+ {
+ for (int i = 0; i < m_windows[m_lastwindow].NumColors; ++i)
+ {
+ m_palManager.RemoveColor((int)(col[i]) & 0xFFFFFF);
+ }
+ }
+
+ // clear osd
+ for (int i = m_windows[m_lastwindow].y0; i <= m_windows[m_lastwindow].y1; ++i)
+ {
+ cp = &OSD_Screen[i*OSDWIDTH + m_windows[m_lastwindow].x0];
+ if ((cp+m_windows[m_lastwindow].x1-m_windows[m_lastwindow].x0+1) < &OSD_Screen[OSDWIDTH * OSDHEIGHT-1])
+ {
+ for (int xx=0; xx <= (m_windows[m_lastwindow].x1-m_windows[m_lastwindow].x0); xx++)
+ {
+ *(cp+xx) = 0x00;
+ }
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ // encode rle
+ m_encodeddata.count = 0;
+ EncodePixelbufRle(0,0, OSDWIDTH, OSDHEIGHT-1, OSD_Screen, 0, &m_encodeddata);
+
+ // set windows position to 0
+ m_windows[m_lastwindow].x0 = 0;
+ m_windows[m_lastwindow].y0 = 0;
+ m_windows[m_lastwindow].x1 = 0;
+ m_windows[m_lastwindow].y1 = 0;
+
+ if (m_encodeddata.count <= DATASIZE)
+ {
+ cDxr3Interface::Instance().WriteSpu((uint8_t*) &m_encodeddata, m_encodeddata.count);
+ return 0;
+ }
+ else
+ {
+ cLog::Instance() << "Waring: SPU data (" << m_encodeddata.count << ") size exceeds limit\n";
+ return -1;
+ }
+
+ return 0;
+ break;
+
+ case OSD_Clear:
+ // Sets all pixel to color 0
+ // returns 0 on success
+
+ // This should be done in cSPUEncoder::cSPUEncoder
+
+ return 0;
+ break;
+
+ // not needed - at the moment
+ case OSD_Show:
+ case OSD_Hide:
+ case OSD_Fill:
+ case OSD_SetColor:
+ case OSD_SetTrans:
+ case OSD_SetPixel:
+ case OSD_GetPixel:
+ case OSD_SetRow:
+ case OSD_FillRow:
+ case OSD_FillBlock:
+ case OSD_Line:
+ case OSD_Query:
+ case OSD_Test:
+ case OSD_Text:
+ case OSD_MoveWindow:
+ break;
+ };
+
+ return -1;
+}
+
+// ==================================
+// stamps window content into full osd bitmap
+void cSPUEncoder::CopyBlockIntoOSD(int linewidth, int x0, int y0, int x1, int y1, u_char *data)
+{
+ int i;
+ int w;
+ u_char *cp;
+ u_char *sp = data;
+
+
+ // linewidth contains the width of one line in the data block,
+ // linewidth<=0 uses blockwidth as linewidth
+ if (linewidth <= 0)
+ {
+ w = m_windows[m_lastwindow].x1 - m_windows[m_lastwindow].x0;
+ }
+ else
+ {
+ w = linewidth;
+ }
+
+ for (i = y0; i <= y1; ++i)
+ {
+ cp = &OSD_Screen[i*OSDWIDTH + x0];
+ if ((cp+x1-x0+1) < &OSD_Screen[OSDWIDTH * OSDHEIGHT-1])
+ {
+ for (int xx=0; xx <= (x1-x0); xx++)
+ {
+ *(cp+xx) = m_windows[m_lastwindow].colors[*(sp+xx) & 0x0f];
+ }
+ }
+ else
+ {
+ continue;
+ }
+ sp += w;
+ }
+}
+
+// ==================================
+// 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;
+
+ if (cDxr3Interface::Instance().GetHorizontalSize() < 700)
+ {
+ double fac = (double)OSDWIDTH / (double)OSDWIDTH2;
+ ScaleOSD(fac, inbuf,10);
+ inbuf = OSD_Screen2;
+ }
+
+ 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;
+}
+
+// ==================================
+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);
+
+ 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)
+ {
+ #if VDRVERSNUM <= 10307
+ // 'interpolate' values
+ if ((dline[d-1] == BLACK) || (dline[d+1] == BLACK))
+ {
+ dline[d] = BLACK;
+ }
+ else if ((dline[d-1] == WHITE) || (dline[d+1] == WHITE))
+ {
+ dline[d] = WHITE;
+ }
+ else if ((dline[d-1] == CYAN) || (dline[d+1] == CYAN))
+ {
+ dline[d] = CYAN;
+ }
+ else
+ {
+ dline[d] = dline[d+1];
+ }
+ #else /*VDRVERSNUM*/
+ dline[d] = dline[d+1];
+ #endif /*VDRVERSNUM*/
+ }
+
+ 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];
+ }
+ }
+}
+
+// ==================================
+// 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);
+
+ 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;
+}
+
+// ==================================
+// 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);
+ }
+*/
+}
diff --git a/dxr3interface_spu_encoder.h b/dxr3interface_spu_encoder.h
new file mode 100644
index 0000000..bee994b
--- /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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#ifndef _DXR3_INTERFACE_SPU_ENCODER_
+#define _DXR3_INTERFACE_SPU_ENCODER_
+
+#include <stdlib.h>
+#include <linux/dvb/osd.h>
+#include "dxr3vdrincludes.h"
+#include "dxr3palettemanager.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
+
+// ==================================
+// basic infos about one osd "window"
+struct sOSD_Window
+{
+ size_t x0;
+ size_t y0;
+ size_t x1;
+ size_t y1;
+
+ unsigned char colors[16];
+ unsigned char opacity[16];
+
+ size_t NumColors;
+};
+
+// ==================================
+// 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 Cmd(OSD_Command cmd, int color = 0, int x0 = 0, int y0 = 0, int x1 = 0, int y1 = 0, const void *data = 0);
+
+private:
+ cSPUEncoder(cSPUEncoder&); // no copy constructor
+
+ // helper functions
+ void CopyBlockIntoOSD(int linewidth, int x0,int y0, int x1, int y1, u_char *data);
+ void EncodePixelbufRle(int x, int y, int w, int h, u_char *inbuf, int stride, encodedata *ed);
+ void ScaleOSD(double fac, unsigned char* buf, unsigned char NumColors=4);
+ 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();
+
+ sOSD_Window m_windows[8];
+ cDxr3PaletteManager m_palManager;
+ cColorManager* m_ColorManager;
+ encodedata m_encodeddata;
+ int m_lastwindow;
+
+ // 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_*/
diff --git a/dxr3log.c b/dxr3log.c
new file mode 100644
index 0000000..09f54c1
--- /dev/null
+++ b/dxr3log.c
@@ -0,0 +1,60 @@
+/*
+ * dxr3log.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "dxr3log.h"
+
+// ==================================
+cLog::cLog()
+{
+ m_LogOpen = false;
+ m_ForeFlush = true;
+
+ Open("dxr3plugin.log");
+}
+
+// ==================================
+cLog::cLog(std::string Filename)
+{
+ m_LogOpen = false;
+ m_ForeFlush = true;
+
+ Open(Filename);
+}
+
+// ==================================
+void cLog::Open(std::string Filename)
+{
+ m_LogStream.open(Filename.c_str());
+ m_LogOpen = true;
+}
+
+// ==================================
+void cLog::Close()
+{
+ if (m_LogOpen)
+ {
+ // close file now
+ m_LogStream.flush();
+ m_LogStream.close();
+
+ m_LogOpen = false;
+ }
+}
diff --git a/dxr3log.h b/dxr3log.h
new file mode 100644
index 0000000..b09e86e
--- /dev/null
+++ b/dxr3log.h
@@ -0,0 +1,94 @@
+/*
+ * dxr3log.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _DXR3_LOG_H_
+#define _DXR3_LOG_H_
+
+#include <fstream>
+#include <string>
+#include "dxr3singleton.h"
+
+// ==================================
+//! A log class.
+/*!
+ With this nice util dxr3plugin generates and mange a log file. In this
+ file the developer/enduser can find informations and can find errors,
+ problems and ohter stuff.
+*/
+class cLog : public Singleton<cLog>
+{
+public:
+ cLog(); // use default log file
+ cLog(std::string FileName);
+
+ ~cLog() { Close(); }
+
+ void SetForceFlush(const bool v) { m_ForeFlush = v; }
+ bool GetForceFlush() const { return m_ForeFlush; }
+
+ // write type data to log file.
+ template <class Type>
+ inline cLog& operator << ( Type item )
+ {
+ if (m_LogOpen)
+ {
+ m_LogStream << item;
+ if (m_ForeFlush) m_LogStream.flush();
+ }
+ return *this;
+ }
+ inline cLog& operator << ( size_t item )
+ {
+ if (m_LogOpen)
+ {
+ m_LogStream << (unsigned int)item;
+ if (m_ForeFlush) m_LogStream.flush();
+ }
+ return *this;
+ }
+ inline cLog& operator << ( bool item )
+ {
+ if (m_LogOpen)
+ {
+ if (item == true)
+ {
+ m_LogStream << "true";
+ }
+ else
+ {
+ m_LogStream << "false";
+ }
+ if (m_ForeFlush) m_LogStream.flush();
+ }
+ return *this;
+ }
+
+private:
+ std::ofstream m_LogStream;
+ bool m_LogOpen;
+ bool m_ForeFlush;
+
+ void Open(std::string Filename); // with this function we open our logfile
+ void Close(); // with this function we close our logfile
+};
+
+
+#endif /*_DXR3_LOG_H_*/
diff --git a/dxr3memcpy.c b/dxr3memcpy.c
new file mode 100644
index 0000000..1866c95
--- /dev/null
+++ b/dxr3memcpy.c
@@ -0,0 +1,421 @@
+/*
+ * Copyright (C) 2001-2003 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * These are the MMX/MMX2/SSE optimized versions of memcpy
+ *
+ * This code was adapted from Linux Kernel sources by Nick Kurshev to
+ * the mplayer program. (http://mplayer.sourceforge.net)
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "dxr3log.h"
+#include "dxr3cpu.h"
+#include "dxr3memcpy.h"
+
+
+void *(* dxr3_memcpy)(void *to, const void *from, size_t len);
+
+
+//#if defined(ARCH_X86) || defined(ARCH_X86_64)
+
+#ifndef _MSC_VER
+// ==================================
+// for small memory blocks (<256 bytes) this version is faster
+#define small_memcpy(to,from,n)\
+{\
+register unsigned long int dummy;\
+__asm__ __volatile__(\
+ "rep; movsb"\
+ :"=&D"(to), "=&S"(from), "=&c"(dummy)\
+ :"0" (to), "1" (from),"2" (n)\
+ : "memory");\
+}
+
+// ==================================
+// linux kernel __memcpy (from: /include/asm/string.h)
+static __inline__ void * __memcpy (
+ void * to,
+ const void * from,
+ size_t n)
+{
+int d0, d1, d2;
+
+ if( n < 4 ) {
+ small_memcpy(to,from,n);
+ }
+ else
+ __asm__ __volatile__(
+ "rep ; movsl\n\t"
+ "testb $2,%b4\n\t"
+ "je 1f\n\t"
+ "movsw\n"
+ "1:\ttestb $1,%b4\n\t"
+ "je 2f\n\t"
+ "movsb\n"
+ "2:"
+ : "=&c" (d0), "=&D" (d1), "=&S" (d2)
+ :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
+ : "memory");
+
+ return (to);
+}
+
+#define SSE_MMREG_SIZE 16
+#define MMX_MMREG_SIZE 8
+
+#define MMX1_MIN_LEN 0x800 /* 2K blocks */
+#define MIN_LEN 0x40 /* 64-byte blocks */
+
+// ==================================
+/* SSE note: i tried to move 128 bytes a time instead of 64 but it
+didn't make any measureable difference. i'm using 64 for the sake of
+simplicity. [MF] */
+static void * sse_memcpy(void * to, const void * from, size_t len)
+{
+ void *retval;
+ size_t i;
+ retval = to;
+
+ /* PREFETCH has effect even for MOVSB instruction ;) */
+ __asm__ __volatile__ (
+ " prefetchnta (%0)\n"
+ " prefetchnta 32(%0)\n"
+ " prefetchnta 64(%0)\n"
+ " prefetchnta 96(%0)\n"
+ " prefetchnta 128(%0)\n"
+ " prefetchnta 160(%0)\n"
+ " prefetchnta 192(%0)\n"
+ " prefetchnta 224(%0)\n"
+ " prefetchnta 256(%0)\n"
+ " prefetchnta 288(%0)\n"
+ : : "r" (from) );
+
+ if(len >= MIN_LEN)
+ {
+ register unsigned long int delta;
+ /* Align destinition to MMREG_SIZE -boundary */
+ delta = ((unsigned long int)to)&(SSE_MMREG_SIZE-1);
+ if(delta)
+ {
+ delta=SSE_MMREG_SIZE-delta;
+ len -= delta;
+ small_memcpy(to, from, delta);
+ }
+ i = len >> 6; /* len/64 */
+ len&=63;
+ if(((unsigned long)from) & 15)
+ /* if SRC is misaligned */
+ for(; i>0; i--)
+ {
+ __asm__ __volatile__ (
+ "prefetchnta 320(%0)\n"
+ "prefetchnta 352(%0)\n"
+ "movups (%0), %%xmm0\n"
+ "movups 16(%0), %%xmm1\n"
+ "movups 32(%0), %%xmm2\n"
+ "movups 48(%0), %%xmm3\n"
+ "movntps %%xmm0, (%1)\n"
+ "movntps %%xmm1, 16(%1)\n"
+ "movntps %%xmm2, 32(%1)\n"
+ "movntps %%xmm3, 48(%1)\n"
+ :: "r" (from), "r" (to) : "memory");
+ ((const unsigned char *)from)+=64;
+ ((unsigned char *)to)+=64;
+ }
+ else
+ /*
+ Only if SRC is aligned on 16-byte boundary.
+ It allows to use movaps instead of movups, which required data
+ to be aligned or a general-protection exception (#GP) is generated.
+ */
+ for(; i>0; i--)
+ {
+ __asm__ __volatile__ (
+ "prefetchnta 320(%0)\n"
+ "prefetchnta 352(%0)\n"
+ "movaps (%0), %%xmm0\n"
+ "movaps 16(%0), %%xmm1\n"
+ "movaps 32(%0), %%xmm2\n"
+ "movaps 48(%0), %%xmm3\n"
+ "movntps %%xmm0, (%1)\n"
+ "movntps %%xmm1, 16(%1)\n"
+ "movntps %%xmm2, 32(%1)\n"
+ "movntps %%xmm3, 48(%1)\n"
+ :: "r" (from), "r" (to) : "memory");
+ ((const unsigned char *)from)+=64;
+ ((unsigned char *)to)+=64;
+ }
+ /* since movntq is weakly-ordered, a "sfence"
+ * is needed to become ordered again. */
+ __asm__ __volatile__ ("sfence":::"memory");
+ /* enables to use FPU */
+ __asm__ __volatile__ ("emms":::"memory");
+ }
+ /*
+ * Now do the tail of the block
+ */
+ if(len) __memcpy(to, from, len);
+ return retval;
+}
+
+// ==================================
+static void * mmx_memcpy(void * to, const void * from, size_t len)
+{
+ void *retval;
+ size_t i;
+ retval = to;
+
+ if(len >= MMX1_MIN_LEN)
+ {
+ register unsigned long int delta;
+ /* Align destinition to MMREG_SIZE -boundary */
+ delta = ((unsigned long int)to)&(MMX_MMREG_SIZE-1);
+ if(delta)
+ {
+ delta=MMX_MMREG_SIZE-delta;
+ len -= delta;
+ small_memcpy(to, from, delta);
+ }
+ i = len >> 6; /* len/64 */
+ len&=63;
+ for(; i>0; i--)
+ {
+ __asm__ __volatile__ (
+ "movq (%0), %%mm0\n"
+ "movq 8(%0), %%mm1\n"
+ "movq 16(%0), %%mm2\n"
+ "movq 24(%0), %%mm3\n"
+ "movq 32(%0), %%mm4\n"
+ "movq 40(%0), %%mm5\n"
+ "movq 48(%0), %%mm6\n"
+ "movq 56(%0), %%mm7\n"
+ "movq %%mm0, (%1)\n"
+ "movq %%mm1, 8(%1)\n"
+ "movq %%mm2, 16(%1)\n"
+ "movq %%mm3, 24(%1)\n"
+ "movq %%mm4, 32(%1)\n"
+ "movq %%mm5, 40(%1)\n"
+ "movq %%mm6, 48(%1)\n"
+ "movq %%mm7, 56(%1)\n"
+ :: "r" (from), "r" (to) : "memory");
+ ((const unsigned char *)from)+=64;
+ ((unsigned char *)to)+=64;
+ }
+ __asm__ __volatile__ ("emms":::"memory");
+ }
+ /*
+ * Now do the tail of the block
+ */
+ if(len) __memcpy(to, from, len);
+ return retval;
+}
+
+// ==================================
+static void * mmx2_memcpy(void * to, const void * from, size_t len)
+{
+ void *retval;
+ size_t i;
+ retval = to;
+
+ /* PREFETCH has effect even for MOVSB instruction ;) */
+ __asm__ __volatile__ (
+ " prefetchnta (%0)\n"
+ " prefetchnta 32(%0)\n"
+ " prefetchnta 64(%0)\n"
+ " prefetchnta 96(%0)\n"
+ " prefetchnta 128(%0)\n"
+ " prefetchnta 160(%0)\n"
+ " prefetchnta 192(%0)\n"
+ " prefetchnta 224(%0)\n"
+ " prefetchnta 256(%0)\n"
+ " prefetchnta 288(%0)\n"
+ : : "r" (from) );
+
+ if(len >= MIN_LEN)
+ {
+ register unsigned long int delta;
+ /* Align destinition to MMREG_SIZE -boundary */
+ delta = ((unsigned long int)to)&(MMX_MMREG_SIZE-1);
+ if(delta)
+ {
+ delta=MMX_MMREG_SIZE-delta;
+ len -= delta;
+ small_memcpy(to, from, delta);
+ }
+ i = len >> 6; /* len/64 */
+ len&=63;
+ for(; i>0; i--)
+ {
+ __asm__ __volatile__ (
+ "prefetchnta 320(%0)\n"
+ "prefetchnta 352(%0)\n"
+ "movq (%0), %%mm0\n"
+ "movq 8(%0), %%mm1\n"
+ "movq 16(%0), %%mm2\n"
+ "movq 24(%0), %%mm3\n"
+ "movq 32(%0), %%mm4\n"
+ "movq 40(%0), %%mm5\n"
+ "movq 48(%0), %%mm6\n"
+ "movq 56(%0), %%mm7\n"
+ "movntq %%mm0, (%1)\n"
+ "movntq %%mm1, 8(%1)\n"
+ "movntq %%mm2, 16(%1)\n"
+ "movntq %%mm3, 24(%1)\n"
+ "movntq %%mm4, 32(%1)\n"
+ "movntq %%mm5, 40(%1)\n"
+ "movntq %%mm6, 48(%1)\n"
+ "movntq %%mm7, 56(%1)\n"
+ :: "r" (from), "r" (to) : "memory");
+ ((const unsigned char *)from)+=64;
+ ((unsigned char *)to)+=64;
+ }
+ /* since movntq is weakly-ordered, a "sfence"
+ * is needed to become ordered again. */
+ __asm__ __volatile__ ("sfence":::"memory");
+ __asm__ __volatile__ ("emms":::"memory");
+ }
+ /*
+ * Now do the tail of the block
+ */
+ if(len) __memcpy(to, from, len);
+ return retval;
+}
+
+// ==================================
+static void *linux_kernel_memcpy(void *to, const void *from, size_t len) {
+ return __memcpy(to,from,len);
+}
+#endif /* _MSC_VER */
+//#endif /* ARCH_X86 */
+
+
+
+// ==================================
+// constr.
+cDxr3MemcpyBench::cDxr3MemcpyBench(uint32_t config_flags)
+{
+ //
+ // add all aviable memcpy routines
+ //
+
+ memcpy_routine routine;
+
+ // glibc memcpy
+ routine.name = "glibc memcpy()";
+ routine.function = memcpy;
+ routine.time = 0;
+ routine.cpu_require = 0;
+ m_methods.push_back(routine);
+
+// #ifdef ARCH_X86
+
+// cLog::Instance() << "test\n";
+
+ // linux_kernel_memcpy
+ routine.name = "linux_kernel_memcpy()";
+ routine.function = linux_kernel_memcpy;
+ routine.cpu_require = 0;
+ m_methods.push_back(routine);
+
+ // MMX optimized memcpy()
+ routine.name = "MMX optimized memcpy()";
+ routine.function = mmx_memcpy;
+ routine.cpu_require = CC_MMX;
+ m_methods.push_back(routine);
+
+ // MMXEXT optimized memcpy()
+ routine.name = "MMXEXT optimized memcpy()";
+ routine.function = mmx2_memcpy;
+ routine.cpu_require = CC_MMXEXT;
+ m_methods.push_back(routine);
+
+ #ifndef __FreeBSD__
+
+ // SSE optimized memcpy()
+ routine.name = "SSE optimized memcpy()";
+ routine.function = sse_memcpy;
+ routine.cpu_require = CC_MMXEXT|CC_SSE;
+ m_methods.push_back(routine);
+
+ #endif /*__FreeBSD__*/
+
+// #endif /*ARCH_X86*/
+
+
+ //
+ // run benchmarking
+ //
+
+ unsigned long long t = 0;
+ void *buf1, *buf2;
+ int j, best = -1;
+
+ if ((buf1 = malloc(BUFSIZE)) == NULL)
+ return;
+
+ if ((buf2 = malloc(BUFSIZE)) == NULL)
+ {
+ free(buf1);
+ return;
+ }
+
+ cLog::Instance() << "\nBenchmarking memcpy() methods (smaller is better):\n";
+ // make sure buffers are present on physical memory
+ memcpy(buf1,buf2,BUFSIZE);
+
+ for (size_t i = 0; i < m_methods.size(); i++)
+ {
+ if ((config_flags & m_methods[i].cpu_require) != m_methods[i].cpu_require)
+ {
+ continue;
+ }
+
+ // count 100 runs of the memcpy function
+ t = rdtsc();
+ for (j = 0; j < 50; j++)
+ {
+ m_methods[i].function(buf2,buf1,BUFSIZE);
+ m_methods[i].function(buf1,buf2,BUFSIZE);
+ }
+ t = rdtsc() - t;
+
+ m_methods[i].time = t;
+
+ cLog::Instance() << m_methods[i].name.c_str() << ": " << (unsigned long long)t << "\n";
+
+ if (best == -1 || t < m_methods[best].time)
+ {
+ best = i;
+ }
+ }
+ cLog::Instance() << "\nBest one: " << m_methods[best].name.c_str() << "\n\n";
+
+ dxr3_memcpy = m_methods[best].function;
+
+
+ // clear unused memory
+ free(buf1);
+ free(buf2);
+}
+
+
+// ==================================
+// neede for exact timing
+unsigned long long int cDxr3MemcpyBench::rdtsc()
+{
+// #ifdef ARCH_X86
+ unsigned long long int x;
+ __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
+ return x;
+// #else
+ /* FIXME: implement an equivalent for using optimized memcpy on other
+ architectures */
+// return 0;
+// #endif
+}
diff --git a/dxr3memcpy.h b/dxr3memcpy.h
new file mode 100644
index 0000000..8ec863d
--- /dev/null
+++ b/dxr3memcpy.h
@@ -0,0 +1,74 @@
+/*****************************************************************************
+ * memcpy.h: functions and definitions of the MMX/MMX2/SSE optimized versions
+ * of memcpy
+ *****************************************************************************
+ * Copyright (C) 2001 Keuleu
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************
+ *
+ * Original code:
+ *
+ * Copyright (C) 2000-2001 the xine project
+ *
+ * This file is part of xine, a unix video player.
+ *
+ *****************************************************************************/
+
+#ifndef _DXR3MEMCPY_H_
+#define _DXR3MEMCPY_H_
+
+#include "dxr3vdrincludes.h"
+
+// ==================================
+// size of buffer for benchmark
+#define BUFSIZE 1024*1024
+
+enum {
+ MEMCPY_PROBE = 0,
+ MEMCPY_GLIBC,
+ MEMCPY_KERNEL,
+ MEMCPY_MMX,
+ MEMCPY_MMXEXT,
+ MEMCPY_SSE
+};
+
+// ==================================
+struct memcpy_routine
+{
+ string name;
+ void *(* function)(void *to, const void *from, size_t len);
+ unsigned long long time;
+ uint32_t cpu_require; // caps from dxr3cpu.h
+};
+
+// ==================================
+// little class to to a nice benchmark
+class cDxr3MemcpyBench
+{
+public:
+ cDxr3MemcpyBench(uint32_t config_flags = 0);
+
+private:
+ unsigned long long int rdtsc();
+
+ vector<memcpy_routine> m_methods;
+};
+
+// ==================================
+// optimized/fast memcpy
+extern void *(* dxr3_memcpy)(void *to, const void *from, size_t len);
+
+#endif /*_DXR3MEMCPY_H_*/
diff --git a/dxr3multichannelaudio.c b/dxr3multichannelaudio.c
new file mode 100644
index 0000000..0bbb15e
--- /dev/null
+++ b/dxr3multichannelaudio.c
@@ -0,0 +1,645 @@
+/*
+* dxr3multichannelaudio.c:
+*
+* taken from the AC3overDVB Patch maintained by Stefan Huelswitt
+*
+*
+*/
+
+#include <malloc.h>
+#include "dxr3multichannelaudio.h"
+#include "dxr3log.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 we need 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 = 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 = 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 { // unfortunaly buffer is not empty, so continue with buffering until sync found
+ int need=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 = 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. Unfortunaly 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();
+}
+
diff --git a/dxr3multichannelaudio.h b/dxr3multichannelaudio.h
new file mode 100644
index 0000000..689f8f1
--- /dev/null
+++ b/dxr3multichannelaudio.h
@@ -0,0 +1,33 @@
+#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_*/
diff --git a/dxr3nextpts.c b/dxr3nextpts.c
new file mode 100644
index 0000000..72b3e31
--- /dev/null
+++ b/dxr3nextpts.c
@@ -0,0 +1,4 @@
+#include "dxr3nextpts.h"
+
+// ==================================
+cMutex* cDxr3NextPts::m_pMutex = new cMutex;
diff --git a/dxr3nextpts.h b/dxr3nextpts.h
new file mode 100644
index 0000000..0391a48
--- /dev/null
+++ b/dxr3nextpts.h
@@ -0,0 +1,42 @@
+/*
+ * dxr3nextpts.h:
+ *
+ * See the main source file 'dxr3.c' for copyright information and
+ * how to reach the author.
+ *
+ */
+
+#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_*/
diff --git a/dxr3osd.c b/dxr3osd.c
new file mode 100644
index 0000000..6bb5f43
--- /dev/null
+++ b/dxr3osd.c
@@ -0,0 +1,161 @@
+/*
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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"
+
+#if VDRVERSNUM >= 10307
+
+//#include "dxr3osd_mpeg.h"
+#include "dxr3osd_subpicture.h"
+
+// ==================================
+cOsd *cDxr3OsdProvider::CreateOsd(int Left, int Top)
+{
+// if (cDxr3ConfigData::Instance().GetMenuMode() == (eMenuMode)SUBPICTURE)
+// {
+ // use subpicture
+ return new cDxr3SubpictureOsd(Left, Top);
+/* }
+ else
+ {
+ // mpeg based menu system
+ return new cDxr3MpegOsd(Left, Top);
+ }*/
+}
+
+#else /*VDRVERSNUM*/
+
+// ==================================
+bool cDxr3Osd::SetWindow(cWindow *Window)
+{
+ if (Window)
+ {
+ // Window handles are counted 0...(MAXNUMWINDOWS - 1), but the actual window
+ // numbers in the driver are used from 1...MAXNUMWINDOWS.
+ int Handle = Window->Handle();
+ if (0 <= Handle && Handle < MAXNUMWINDOWS)
+ {
+ Spu->Cmd(OSD_SetWindow, 0, Handle + 1);
+ return true;
+ }
+ esyslog("ERROR: illegal window handle: %d", Handle);
+
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3Osd::SetWindow: illegal window handle:" << Handle << "\n";
+ }
+ }
+ return false;
+}
+
+// ==================================
+cDxr3Osd::cDxr3Osd(int x, int y) : cOsdBase(x, y)
+{
+ Spu = &cSPUEncoder::Instance();
+}
+
+// ==================================
+cDxr3Osd::~cDxr3Osd()
+{
+ for (int i = 0; i < NumWindows(); i++)
+ {
+ CloseWindow(GetWindowNr(i));
+ }
+}
+
+// ==================================
+bool cDxr3Osd::OpenWindow(cWindow *Window)
+{
+ if (SetWindow(Window))
+ {
+ Spu->Cmd(OSD_Open, Window->Bpp(), X0() + Window->X0(), Y0() + Window->Y0(), X0() + Window->X0() + Window->Width() - 1, Y0() + Window->Y0() + Window->Height() - 1, (void *)1); // initially hidden!
+ return true;
+ }
+ return false;
+}
+
+// ==================================
+void cDxr3Osd::CommitWindow(cWindow *Window)
+{
+ if (SetWindow(Window))
+ {
+ int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+
+ if (Window->Dirty(x1, y1, x2, y2))
+ {
+ // commit colors:
+ int FirstColor = 0, LastColor = 0;
+ const eDvbColor *pal;
+ while ((pal = Window->NewColors(FirstColor, LastColor)) != NULL)
+ Spu->Cmd(OSD_SetPalette, FirstColor, LastColor, 0, 0, 0, pal);
+ // commit modified data:
+ Spu->Cmd(OSD_SetBlock, Window->Width(), x1, y1, x2, y2, Window->Data(x1, y1));
+ }
+ }
+}
+
+// ==================================
+void cDxr3Osd::ShowWindow(cWindow *Window)
+{
+ if (SetWindow(Window))
+ {
+ Spu->Cmd(OSD_MoveWindow, 0, X0() + Window->X0(), Y0() + Window->Y0());
+ }
+}
+
+// ==================================
+void cDxr3Osd::HideWindow(cWindow *Window, bool Hide)
+{
+ if (SetWindow(Window))
+ {
+ Spu->Cmd(Hide ? OSD_Hide : OSD_Show, 0);
+ }
+}
+
+// ==================================
+void cDxr3Osd::CloseWindow(cWindow *Window)
+{
+ if (SetWindow(Window))
+ {
+ Spu->Cmd(OSD_Close);
+ }
+}
+
+// ==================================
+void cDxr3Osd::MoveWindow(cWindow *Window, int x, int y)
+{
+ if (SetWindow(Window))
+ {
+ Spu->Cmd(OSD_MoveWindow, 0, X0() + x, Y0() + y);
+ }
+}
+
+#endif /*VDRVERSNUM*/
diff --git a/dxr3osd.h b/dxr3osd.h
new file mode 100644
index 0000000..234689e
--- /dev/null
+++ b/dxr3osd.h
@@ -0,0 +1,42 @@
+#ifndef _DXR3_OSD_H_
+#define _DXR3_OSD_H_
+
+#include "dxr3vdrincludes.h"
+#include "dxr3interface_spu_encoder.h"
+
+#if VDRVERSNUM >= 10307
+
+// ==================================
+// osd plugin provider
+class cDxr3OsdProvider : public cOsdProvider
+{
+public:
+ cDxr3OsdProvider() {}
+ virtual cOsd *CreateOsd(int Left, int Top);
+};
+
+#else /*VDRVERSNUM*/
+
+// ==================================
+// osd interface for =< vdr1,3,7
+class cDxr3Osd : public cOsdBase
+{
+private:
+ cSPUEncoder* Spu;
+
+ bool SetWindow(cWindow*);
+
+public:
+ cDxr3Osd(int x, int y);
+ ~cDxr3Osd();
+
+ virtual bool OpenWindow(cWindow *Window);
+ virtual void CommitWindow(cWindow *Window);
+ virtual void ShowWindow(cWindow *Window);
+ virtual void HideWindow(cWindow *Window, bool Hide);
+ virtual void CloseWindow(cWindow *Window);
+ virtual void MoveWindow(cWindow *Window, int x, int y);
+};
+
+#endif /*VDRVERSNUM*/
+#endif /*_DXR3_OSD_H_*/
diff --git a/dxr3osd_subpicture.c b/dxr3osd_subpicture.c
new file mode 100644
index 0000000..e6dc154
--- /dev/null
+++ b/dxr3osd_subpicture.c
@@ -0,0 +1,174 @@
+#include "dxr3osd_subpicture.h"
+
+#if VDRVERSNUM >= 10307
+
+#define MAXNUMWINDOWS 7 // OSD windows are counted 1...7
+
+// ==================================
+cDxr3SubpictureOsd::cDxr3SubpictureOsd(int Left, int Top) : cOsd(Left, Top)
+{
+ shown = false;
+ Spu = &cSPUEncoder::Instance();
+
+ // must clear all windows here to avoid flashing effects - doesn't work if done
+ // in Flush() only for the windows that are actually used...
+ for (int i = 0; i < MAXNUMWINDOWS; i++)
+ {
+ Spu->Cmd(OSD_SetWindow, 0, i + 1);
+ Spu->Cmd(OSD_Clear);
+ }
+
+}
+
+// ==================================
+cDxr3SubpictureOsd::~cDxr3SubpictureOsd()
+{
+ if (shown)
+ {
+ cBitmap *Bitmap;
+ for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++)
+ {
+ Spu->Cmd(OSD_SetWindow, 0, i + 1);
+ Spu->Cmd(OSD_Close);
+ }
+ }
+}
+
+// ==================================
+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::SaveRegion(int x1, int y1, int x2, int y2)
+{
+ // ToDo?
+}
+
+// ==================================
+void cDxr3SubpictureOsd::RestoreRegion()
+{
+ // ToDo?
+}
+
+// ==================================
+void cDxr3SubpictureOsd::Flush()
+{
+ cBitmap *Bitmap;
+
+ for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++)
+ {
+ Spu->Cmd(OSD_SetWindow, 0, i + 1);
+
+ if (!shown)
+ {
+ Spu->Cmd(OSD_Open, Bitmap->Bpp(), Left() + Bitmap->X0(), Top() + Bitmap->Y0(), Left() + Bitmap->X0() + Bitmap->Width() - 1, Top() + Bitmap->Y0() + Bitmap->Height() - 1, (void *)1); // initially hidden!
+ }
+
+ 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
+ //TODO of 8 bits wide, and (dx * dy) also has to be a multiple of 8.
+ //TODO Fix driver (should be able to handle any size bitmaps!)
+
+ 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--;
+ }
+ }
+
+ // commit colors:
+ int NumColors;
+ const tColor *Colors = Bitmap->Colors(NumColors);
+
+ if (Colors)
+ {
+
+ // TODO this should be fixed in the driver!
+ tColor colors[NumColors];
+ for (int i = 0; i < NumColors; i++)
+ {
+ // convert AARRGGBB to AABBGGRR (the driver expects the colors the wrong way):
+ colors[i] = (Colors[i] & 0xFF000000) | ((Colors[i] & 0x0000FF) << 16) | (Colors[i] & 0x00FF00) | ((Colors[i] & 0xFF0000) >> 16);
+ }
+
+ Colors = colors;
+ //TODO end of stuff that should be fixed in the driver
+ Spu->Cmd(OSD_SetPalette, 0, NumColors - 1, 0, 0, 0, Colors);
+ }
+ // commit modified data:
+ //Spu->Cmd(OSD_SetBlock, Bitmap->Width(), x1, y1, x2, y2, Bitmap->Data(x1, y1));
+ Spu->Cmd(OSD_SetBlock, Bitmap->Width(), x1, y1, x2, y2, Bitmap->Data(x1, y1));
+ }
+ Bitmap->Clean();
+ }
+
+ if (!shown)
+ {
+ // Showing the windows in a separate loop to avoid seeing them come up one after another
+ for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++)
+ {
+ Spu->Cmd(OSD_SetWindow, 0, i + 1);
+ Spu->Cmd(OSD_MoveWindow, 0, Left() + Bitmap->X0(), Top() + Bitmap->Y0());
+ }
+ shown = true;
+ }
+}
+
+#endif /*VDRVERSNUM*/
+
diff --git a/dxr3osd_subpicture.h b/dxr3osd_subpicture.h
new file mode 100644
index 0000000..6806c90
--- /dev/null
+++ b/dxr3osd_subpicture.h
@@ -0,0 +1,29 @@
+#ifndef _DXR3OSD_SUBPICTURE_H_
+#define _DXR3OSD_SUBPICTURE_H_
+
+#include "dxr3vdrincludes.h"
+#include "dxr3interface_spu_encoder.h"
+
+#if VDRVERSNUM >= 10307
+
+// ==================================
+// osd interface for => vdr1,3,7
+class cDxr3SubpictureOsd : public cOsd
+{
+private:
+ cSPUEncoder* Spu;
+ bool shown;
+
+public:
+ cDxr3SubpictureOsd(int Left, int Top/*, int SpuDev*/);
+ ~cDxr3SubpictureOsd();
+
+ eOsdError CanHandleAreas(const tArea *Areas, int NumAreas);
+ void SaveRegion(int x1, int y1, int x2, int y2);
+ void RestoreRegion(void);
+
+ void Flush();
+};
+
+#endif /*VDRVERSNUM*/
+#endif /*_DXR3OSD_SUBPICTURE_H_*/
diff --git a/dxr3outputthread.c b/dxr3outputthread.c
new file mode 100644
index 0000000..d4a4a8e
--- /dev/null
+++ b/dxr3outputthread.c
@@ -0,0 +1,279 @@
+/*
+ * dxr3outputthread.c:
+ *
+ * See the main source file 'dxr3.c' for copyright information and
+ * how to reach the author.
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <time.h>
+#include <pthread.h>
+#include "dxr3outputthread.h"
+#include "dxr3log.h"
+
+// ==================================
+const int AUDIO_OFFSET = 4500;
+#define SCR m_dxr3Device.GetSysClock()
+// ==================================
+
+// ==================================
+// constr.
+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)
+{
+}
+
+// ==================================
+// thread action
+void cDxr3AudioOutThread::Action()
+{
+ bool resync = false;
+ uint32_t pts = 0;
+
+ cLog::Instance() << "cDxr3AudioOutThread::Action Thread started\n";
+
+ sched_param temp;
+ temp.sched_priority = 2;
+
+ if (!pthread_setschedparam(pthread_self(), SCHED_RR, &temp))
+ {
+ cLog::Instance() << "cDxr3AudioOutThread::Action(): Error can't set priority\n";
+ }
+
+ 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())
+ {
+ if (cDxr3ConfigData::Instance().GetDebugEverything())
+ {
+ cLog::Instance() << "cDxr3AudioOutThread::Action " << "pts = " << pts << " scr = " << SCR << "\n";
+ }
+ m_buffer.Clear();
+ m_bNeedResync = true;
+ }
+ else if (pNext)
+ {
+ if (!pts || pts < SCR)
+ {
+ if (cDxr3ConfigData::Instance().GetDebugEverything())
+ {
+// if (pts) cLog::Instance() << "cDxr3AudioOutThread::Action pts " << pNext->GetPts() << " scr " << SCR << " delta " << (pts - SCR) << "\n";
+ }
+ if (!pts && resync)
+ {
+ continue;
+ }
+ else
+ {
+ resync = false;
+ }
+
+ if (pts && (pts < SCR) && ((SCR - pts) > 5000))
+ {
+ if (cDxr3ConfigData::Instance().GetDebugEverything())
+ {
+// cLog::Instance() << "cDxr3AudioOutThread::Action pts audio too small " << (SCR - pts) << "\n";
+ }
+ m_dxr3Device.SetSysClock(pts+ 1 * AUDIO_OFFSET);
+ m_dxr3Device.PlayAudioFrame(pNext);
+ if (m_buffer.IsPolled())
+ {
+ m_buffer.Clear();
+ m_bNeedResync = true;
+ }
+ }
+ else
+ {
+ if (cDxr3ConfigData::Instance().GetDebugEverything())
+ {
+// cLog::Instance() << "cDxr3AudioOutThread::Action write audio\n";
+ }
+ m_dxr3Device.PlayAudioFrame(pNext);
+ m_buffer.Pop();
+ }
+ }
+ else
+ {
+ if (abs((int)pts - (int)SCR) < (AUDIO_OFFSET ))
+ {
+ if (cDxr3ConfigData::Instance().GetDebugEverything())
+ {
+// if (pts) cLog::Instance() << "cDxr3AudioOutThread::Action pts " << pNext->GetPts() << " scr " << SCR << " delta " << (pts - SCR) << "\n";
+ }
+ m_dxr3Device.PlayAudioFrame(pNext);
+ m_buffer.Pop();
+ }
+ }
+ }
+
+ if ((pts > SCR && abs((int)pts - (int)SCR) > AUDIO_OFFSET))
+ {
+ if (cDxr3ConfigData::Instance().GetDebugEverything())
+ {
+// cLog::Instance() << "cDxr3AudioOutThread::Action Stopping audio " << SCR << " " << pts << "\n";
+ }
+
+ usleep(10000);
+
+ if (cDxr3ConfigData::Instance().GetDebugEverything())
+ {
+// cLog::Instance() << "cDxr3AudioOutThread::Action Starting audio " << SCR << " " << pts << "\n";
+ }
+ }
+ }
+}
+
+// ==================================
+// constr.
+cDxr3VideoOutThread::cDxr3VideoOutThread(cDxr3Interface& dxr3Device, cDxr3SyncBuffer& buffer) :
+cDxr3OutputThread(dxr3Device, buffer)
+{
+}
+
+// ==================================
+// thread action
+void cDxr3VideoOutThread::Action()
+{
+ uint32_t pts = 0;
+ static uint32_t lastPts = 0;
+
+ cLog::Instance() << "cDxr3VideoOutThread::Action Thread started\n";
+
+ sched_param temp;
+ temp.sched_priority = 1;
+
+ if (!pthread_setschedparam(pthread_self(), SCHED_RR, &temp))
+ {
+// cLog::Instance() << "cDxr3VideoOutThread::Action(): Error can't set priority\n";
+ }
+
+ 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)
+ {
+ if (cDxr3ConfigData::Instance().GetDebugEverything())
+ {
+// cLog::Instance() << "cDxr3VideoOutThread::Action pts " << pts << " scr " << SCR << " delta " << (pts - SCR) << "\n";
+ }
+
+ m_dxr3Device.SetPts(pts);
+
+ if (cDxr3ConfigData::Instance().GetDebugEverything())
+ {
+// cLog::Instance() << "cDxr3VideoOutThread::Action done\n";
+ }
+
+ if (m_buffer.Available() && pNext->GetData() && pNext->GetCount())
+ {
+ m_dxr3Device.PlayVideoFrame(pNext);
+
+ if (cDxr3ConfigData::Instance().GetDebugEverything())
+ {
+// cLog::Instance() << "cDxr3VideoOutThread::Action write\n";
+ }
+
+ m_buffer.Pop();
+
+ if (cDxr3ConfigData::Instance().GetDebugEverything())
+ {
+// cLog::Instance() << "cDxr3VideoOutThread::Action done pop\n";
+ }
+ }
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+// cLog::Instance() << "cDxr3VideoOutThread::Action done complete\n";
+ }
+ }
+ 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 ))
+ {
+ if (cDxr3ConfigData::Instance().GetDebugEverything())
+ {
+// cLog::Instance() << "cDxr3VideoOutThread::Action Stopping video " << SCR << " " << pts << "\n";
+ }
+
+ usleep(10000);
+
+ if (cDxr3ConfigData::Instance().GetDebugEverything())
+ {
+// cLog::Instance() << "cDxr3VideoOutThread::Action Starting video " << SCR << " " << pts << "\n";
+ }
+ }
+ }
+ }
+}
+
+
+#undef SCR
diff --git a/dxr3outputthread.h b/dxr3outputthread.h
new file mode 100644
index 0000000..1ed7dc6
--- /dev/null
+++ b/dxr3outputthread.h
@@ -0,0 +1,71 @@
+/*
+ * dxr3outputthread.h:
+ *
+ * See the main source file 'dxr3.c' for copyright information and
+ * how to reach the author.
+ *
+ */
+
+#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_*/
diff --git a/dxr3palettemanager.c b/dxr3palettemanager.c
new file mode 100644
index 0000000..0769722
--- /dev/null
+++ b/dxr3palettemanager.c
@@ -0,0 +1,114 @@
+/*
+ * dxr3palettemanager.c:
+ *
+ * See the main source file 'dxr3.c' for copyright information and
+ * how to reach the author.
+ *
+ */
+
+/*
+ ToDo:
+ - cDxr3PaletteManager: Should we use here std::vector?
+*/
+
+#include <string.h>
+#include "dxr3palettemanager.h"
+#include "dxr3tools.h"
+
+// ==================================
+cDxr3PaletteManager::cDxr3PaletteManager()
+{
+ memset(m_colors, 0, sizeof(int) * MAX_COLORS);
+ memset(m_users, 0, sizeof(int) * MAX_COLORS);
+ memset(m_pal, 0, sizeof(int) * MAX_COLORS);
+ m_changed = false;
+};
+
+// ==================================
+void cDxr3PaletteManager::AddColor(int color)
+{
+ int freeIndex = MAX_COLORS;
+ bool found = false;
+
+ for (int i = 0; i < MAX_COLORS && !found; ++i)
+ {
+ if (color == m_colors[i])
+ {
+ if (m_users[i] == 0) m_changed = true;
+ ++m_users[i];
+ found = true;
+ }
+ if (m_users[i] == 0 && freeIndex >= MAX_COLORS)
+ {
+ freeIndex = i;
+ }
+ }
+ if (!found && freeIndex < MAX_COLORS)
+ {
+ m_colors[freeIndex] = color;
+ m_users[freeIndex] = 1;
+ m_changed = true;
+ }
+}
+
+// ==================================
+void cDxr3PaletteManager::RemoveColor(int color)
+{
+ bool found = false;
+ for (int i = 0; i < MAX_COLORS && !found; ++i)
+ {
+ if (color == m_colors[i])
+ {
+ if (m_users[i] > 0) --m_users[i];
+ found = true;
+ }
+ }
+}
+
+// ==================================
+int cDxr3PaletteManager::GetIndex(int color)
+{
+ bool found = false;
+ int index = 0;
+ for (int i = 0; i < MAX_COLORS && !found; ++i)
+ {
+ if (color == m_colors[i])
+ {
+ index = i;
+ found = true;
+ }
+ }
+ return index;
+}
+
+// ==================================
+int cDxr3PaletteManager::GetCount()
+{
+ return MAX_COLORS;
+}
+
+// ==================================
+int cDxr3PaletteManager::operator[](int index)
+{
+ assert(index < MAX_COLORS && index > 0);
+ return m_colors[index];
+}
+
+// ==================================
+bool cDxr3PaletteManager::HasChanged()
+{
+ bool retval = m_changed;
+ m_changed = false;
+ return retval;
+}
+
+// ==================================
+uint32_t* cDxr3PaletteManager::GetPalette()
+{
+ for (int i = 0; i < MAX_COLORS; ++i)
+ {
+ m_pal[i] = Tools::Rgb2YCrCb(m_colors[i]);
+ }
+
+ return m_pal;
+}
diff --git a/dxr3palettemanager.h b/dxr3palettemanager.h
new file mode 100644
index 0000000..94253b8
--- /dev/null
+++ b/dxr3palettemanager.h
@@ -0,0 +1,39 @@
+/*
+ * dxr3palettemanager.h:
+ *
+ * See the main source file 'dxr3.c' for copyright information and
+ * how to reach the author.
+ *
+ */
+
+#ifndef _DXR3PALETTEMANAGER_H_
+#define _DXR3PALETTEMANAGER_H_
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+// ==================================
+class cDxr3PaletteManager
+{
+public:
+ cDxr3PaletteManager();
+ ~cDxr3PaletteManager() {};
+
+ void AddColor(int color);
+ void RemoveColor(int color);
+ int GetCount();
+ int operator[](int index);
+ int GetIndex(int color);
+ bool HasChanged();
+ uint32_t* GetPalette();
+
+private:
+ static const int MAX_COLORS = 16;
+ int m_colors[MAX_COLORS];
+ uint32_t m_pal[MAX_COLORS];
+ int m_users[MAX_COLORS];
+ bool m_changed;
+};
+
+#endif /*_DXR3PALETTEMANAGER_H_*/
diff --git a/dxr3pesframe.c b/dxr3pesframe.c
new file mode 100644
index 0000000..c86002e
--- /dev/null
+++ b/dxr3pesframe.c
@@ -0,0 +1,226 @@
+#include "dxr3pesframe.h"
+#include "dxr3log.h"
+#include <linux/em8300.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.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++);
+ 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;
+ cLog::Instance() << "*** PES_GENERAL_ERROR ****\n";
+ 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;
+ }
+ }
+ }
+ 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;
+const uint32_t cDxr3PesFrame::MAX_PES_HEADER_SIZE = 184;
+
diff --git a/dxr3pesframe.h b/dxr3pesframe.h
new file mode 100644
index 0000000..e0d9034
--- /dev/null
+++ b/dxr3pesframe.h
@@ -0,0 +1,158 @@
+/*
+ * dxr3pesframe.h:
+ *
+ * See the main source file 'dxr3.c' for copyright information and
+ * how to reach the author.
+ *
+ */
+
+#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_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;};
+ 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_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;
+ 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;
+
+protected:
+ static const uint32_t MAX_PES_HEADER_SIZE;
+
+private:
+ cDxr3PesFrame(cDxr3PesFrame&); // no copy constructor
+
+};
+
+
+#endif /*_DXR3PESFRAME_H_*/
+
+
diff --git a/dxr3singleton.h b/dxr3singleton.h
new file mode 100644
index 0000000..6db2c26
--- /dev/null
+++ b/dxr3singleton.h
@@ -0,0 +1,43 @@
+/*
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _DXR3_SINGLETON_H_
+#define _DXR3_SINGLETON_H_
+
+// ==================================
+// This template makes it easy to make
+// global things
+template<typename T>
+class Singleton
+{
+ protected:
+ Singleton() {}
+ virtual ~Singleton() {}
+
+ public:
+ static T& Instance()
+ {
+ static T m_Instance;
+ return m_Instance;
+ }
+};
+
+#endif /*_DXR3_SINGLETON_H_*/
diff --git a/dxr3spudecoder.c b/dxr3spudecoder.c
new file mode 100644
index 0000000..7e56219
--- /dev/null
+++ b/dxr3spudecoder.c
@@ -0,0 +1,628 @@
+/*
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+/*
+ToDo:
+ - Line 175
+*/
+
+#include <assert.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include "dxr3spudecoder.h"
+#include "dxr3interface.h"
+#include "dxr3tools.h"
+#include "dxr3log.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_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;
+ }
+ }
+/*
+ if (ret && cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3SpuBitmap::getMinSize: (" << size.x1 ", " << size.y1 << ") x (" << size.x2 << ", " << size.y2 << ")\n";
+ }
+*/
+ 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;
+ }
+ }
+}
+
+// ==================================
+cDxr3SpuDecoder::cDxr3SpuDecoder()
+{
+ clean = true;
+ scaleMode = eSpuNormal;
+ spu = NULL;
+ osd = NULL;
+ spubmp = NULL;
+}
+
+// ==================================
+cDxr3SpuDecoder::~cDxr3SpuDecoder()
+{
+ delete spubmp;
+ delete spu;
+ delete osd;
+}
+
+// ==================================
+void cDxr3SpuDecoder::processSPU(uint32_t pts, uint8_t * buf)
+{
+ setTime(pts);
+
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3SpuDecoder::processSPU: SPU pushData: pts: " << pts << "\n";
+ }
+
+ delete spubmp;
+ spubmp = NULL;
+ delete[]spu;
+ spu = buf;
+ spupts = pts;
+
+ DCSQ_offset = cmdOffs();
+ prev_DCSQ_offset = 0;
+
+ clean = true;
+}
+
+// ==================================
+void cDxr3SpuDecoder::setScaleMode(cSpuDecoder::eScaleMode ScaleMode)
+{
+ scaleMode = ScaleMode;
+}
+
+// ==================================
+void cDxr3SpuDecoder::setPalette(uint32_t * pal)
+{
+ palette.setPalette(pal);
+}
+
+// ==================================
+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)
+ {
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3SpuDecoder::setHighlight: " << sx << ", " << sy << ", " << ex << ", " << ey << "\n";
+ }
+
+ hlpsize.x1 = sx;
+ hlpsize.y1 = sy;
+ hlpsize.x2 = ex;
+ hlpsize.y2 = ey;
+ memcpy(hlpDescr, pld, sizeof(aDxr3SpuPalDescr));
+ highlight = true;
+ clean = false;
+ }
+}
+
+// ==================================
+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;
+}
+
+// ==================================
+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)
+ {
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3SpuDecoder::Draw: New OSD faild!\n";
+ }
+ dsyslog("NewOsd failed\n");
+ return;
+ }
+
+ if (fg)
+ {
+ DrawBmp(hlsize, fg);
+ }
+
+ if (bg)
+ {
+ DrawBmp(bgsize, bg);
+ }
+
+ osd->Flush();
+ }
+
+ clean = true;
+}
+
+// ==================================
+void cDxr3SpuDecoder::Hide()
+{
+ delete osd;
+ osd = NULL;
+}
+
+// ==================================
+void cDxr3SpuDecoder::Empty()
+{
+ Hide();
+
+ delete spubmp;
+ spubmp = NULL;
+
+ delete[]spu;
+ spu = NULL;
+
+ clearHighlight();
+ clean = true;
+}
+
+// ==================================
+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
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3SpuDecoder::setTime: show subpicture\n";
+ }
+ state = spSHOW;
+ i++;
+ break;
+
+ case CMD_SPU_HIDE:
+ // hide subpicture
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3SpuDecoder::setTime: hide subpicture\n";
+ }
+ 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];
+
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3SpuDecoder::setTime: (" << size.x1 << ", " << size.y1 <<") x (" << size.x2 << ", " << size.y2 <<")\n";
+ }
+ i += 7;
+ break;
+
+ case CMD_SPU_SET_PXD_OFFSET:
+ // image 1 / image 2 offsets
+ fodd = spuU32(i + 1);
+ feven = spuU32(i + 3);
+
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3SpuDecoder::setTime: odd = " << fodd << " even = " << feven << "\n";
+ }
+ i += 5;
+ break;
+
+ case CMD_SPU_MENU:
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "cDxr3SpuDecoder::setTime: spu menu\n";
+ }
+ state = spMENU;
+
+ i++;
+ break;
+
+ default:
+ esyslog("invalid sequence in control header (%.2x)\n", 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 || state == spMENU)
+ {
+ Draw();
+ }
+
+ if (state == spHIDE)
+ {
+ Hide();
+ }
+
+ if (pts == 0)
+ {
+ return 0;
+ }
+ }
+
+ return 1;
+}
diff --git a/dxr3spudecoder.h b/dxr3spudecoder.h
new file mode 100644
index 0000000..adaed7f
--- /dev/null
+++ b/dxr3spudecoder.h
@@ -0,0 +1,138 @@
+#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);
+
+ 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();
+ void processSPU(uint32_t pts, uint8_t * buf);
+
+ #if VDRVERSNUM >= 10311
+ void Hide();
+ void Draw();
+ bool IsVisible() { return osd != NULL; }
+ #endif
+
+private:
+ cOsd * osd;
+
+ // processing state
+ uint8_t *spu;
+ uint32_t spupts;
+ bool clean;
+ bool ready;
+
+ 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_*/
diff --git a/dxr3syncbuffer.c b/dxr3syncbuffer.c
new file mode 100644
index 0000000..8ea8ccd
--- /dev/null
+++ b/dxr3syncbuffer.c
@@ -0,0 +1,420 @@
+/*
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+/*
+ ToDo:
+ - cDxr3SyncBuffer::Push: XXX This is only a workaround until a sufficient control algorithm is implemented
+*/
+
+#include <unistd.h>
+#include "dxr3syncbuffer.h"
+#include "dxr3memcpy.h"
+
+const int DXR3_MAX_VIDEO_FRAME_LENGTH = 4096;
+const int DXR3_MAX_AUDIO_FRAME_LENGTH = 4096;
+
+// ==================================
+cFixedLengthFrame::cFixedLengthFrame(uint32_t length) :
+m_count(0), m_length(length), m_pts(0), m_type(ftUnknown) {
+
+ m_pData = new uint8_t[length];
+ if (!m_pData)
+ {
+ cLog::Instance() << "Failed to allocate memory in cFixedLengthFrame (m_pData) - will stop now";
+ exit(1);
+ }
+
+ m_audioChannelCount = UNKNOWN_CHANNEL_COUNT;
+ m_audioDataRate = UNKNOWN_DATA_RATE;
+ m_videoAspectRatio = UNKNOWN_ASPECT_RATIO;
+}
+
+// ==================================
+cFixedLengthFrame::~cFixedLengthFrame()
+{
+ if (m_pData)
+ {
+ delete[] m_pData;
+ }
+}
+
+// ==================================
+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;
+ dxr3_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;
+
+
+
+
+// ==================================
+cDxr3SyncBuffer::cDxr3SyncBuffer(int frameCount, int frameLength, cDxr3Interface& dxr3Device) : cRingBuffer(frameCount, true), m_dxr3Device(dxr3Device)
+{
+ m_pBuffer = new cFixedLengthFrame[frameCount](frameLength);
+
+ if (!m_pBuffer)
+ {
+ cLog::Instance() << "Failed to allocate memory in cDxr3SyncBuffer (m_pBuffer) - will stop now";
+ exit(1);
+ }
+
+ 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;
+ Lock();
+ ret = m_count;
+ Unlock();
+ 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();
+ m_bPollSync = true;
+ 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)))
+ {
+ m_bPutBlock = true;
+ EnableGet();
+ m_bWaitPts = false;
+ WaitForPut();
+ }
+ 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;
+
+ 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))
+ {
+ m_bPutBlock = true;
+ EnableGet();
+ m_bWaitPts = false;
+ WaitForPut();
+ }
+
+ Lock();
+ 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)
+ {
+ cLog::Instance() << "Buffer overrun\n";
+// cLog::Instance() << "cDxr3SyncBuffer::Push m_demuxMode: " << (int)m_demuxMode << endl;
+// cLog::Instance() << "cDxr3SyncBuffer::Push Available(): " << Available() << endl;
+// cLog::Instance() << "cDxr3SyncBuffer::Push Size(): " << Size() << endl;
+
+ 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;
+ }
+ }
+ Unlock();
+ break;
+ }
+
+ return &m_pBuffer[lastIndex];
+}
+
+// ==================================
+void cDxr3SyncBuffer::Pop(void)
+{
+ Lock();
+ 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();
+ Unlock();
+}
+
+// ==================================
+cFixedLengthFrame* cDxr3SyncBuffer::Get(void)
+{
+ cFixedLengthFrame* pRet = 0;
+
+ if (!m_bStopped)
+ {
+ while (!Available() || !m_bStartReceiver)
+ {
+ m_bGetBlock = true;
+ ReceiverStopped();
+ WaitForGet();
+ }
+
+ Lock();
+ if (m_nextFree != m_next)
+ {
+ pRet = &m_pBuffer[m_next];
+ }
+ Unlock();
+ }
+ else
+ {
+ WaitForGet();
+ }
+
+ return pRet;
+}
+
+// ==================================
+void cDxr3SyncBuffer::Clear(void)
+{
+ Lock();
+ 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();
+ Unlock();
+}
+
+// ==================================
+void cDxr3SyncBuffer::WaitForSysClock(uint32_t pts, uint32_t delta)
+{
+ m_waitPts = pts;
+ m_waitDelta = delta;
+ if (!m_bPutBlock)
+ {
+ Lock();
+ m_bWaitPts = true;
+ Unlock();
+ 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)
+{
+ Lock();
+ 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;
+ }
+ }
+ }
+ Unlock();
+}
+
+// ==================================
+void cDxr3SyncBuffer::WaitForReceiverStopped(void)
+{
+ if (!m_bGetBlock)
+ {
+ receiverStoppedMutex.Lock();
+ receiverStopped.Wait(receiverStoppedMutex);
+ receiverStoppedMutex.Unlock();
+ }
+}
+
+// ==================================
+void cDxr3SyncBuffer::ReceiverStopped(void)
+{
+ receiverStopped.Broadcast();
+}
diff --git a/dxr3syncbuffer.h b/dxr3syncbuffer.h
new file mode 100644
index 0000000..1598b62
--- /dev/null
+++ b/dxr3syncbuffer.h
@@ -0,0 +1,123 @@
+/*
+ * dxr3syncbuffer.h:
+ *
+ * See the main source file 'dxr3.c' for copyright information and
+ * how to reach the author.
+ *
+ */
+
+#ifndef _DXR3SYNCBUFFER_H_
+#define _DXR3SYNCBUFFER_H_
+
+#include <stdint.h>
+
+#include "dxr3vdrincludes.h"
+#include "dxr3interface.h"
+#include "dxr3generaldefines.h"
+#include "dxr3nextpts.h"
+#include "dxr3log.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:
+ explicit cFixedLengthFrame(uint32_t length);
+ ~cFixedLengthFrame();
+
+ 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_*/
diff --git a/dxr3sysclock.c b/dxr3sysclock.c
new file mode 100644
index 0000000..9d7d050
--- /dev/null
+++ b/dxr3sysclock.c
@@ -0,0 +1,49 @@
+#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();
+}
diff --git a/dxr3sysclock.h b/dxr3sysclock.h
new file mode 100644
index 0000000..50c5540
--- /dev/null
+++ b/dxr3sysclock.h
@@ -0,0 +1,36 @@
+#ifndef _DXR3_SYSCLOCK_H_
+#define _DXR3_SYSCLOCK_H_
+
+//#include <stdint.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_*/
diff --git a/dxr3tools.h b/dxr3tools.h
new file mode 100644
index 0000000..ee8f9e3
--- /dev/null
+++ b/dxr3tools.h
@@ -0,0 +1,82 @@
+#ifndef _DXR3TOOLS_H_
+#define _DXR3TOOLS_H_
+
+#include "dxr3vdrincludes.h"
+
+namespace Tools
+{
+ // ==================================
+ 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;
+ }
+
+ // ==================================
+ 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);
+ }
+
+ // ==================================
+ inline void WriteInfoToOsd(string x)
+ {
+ #if VDRVERSNUM <= 10306
+ Interface->Info(x.c_str());
+ #else
+ Skins.Message(mtInfo, x.c_str());
+ #endif
+ }
+
+}
+
+#endif /*_DXR3TOOLS_H_*/
diff --git a/dxr3unixserversocket.c b/dxr3unixserversocket.c
new file mode 100644
index 0000000..49816fa
--- /dev/null
+++ b/dxr3unixserversocket.c
@@ -0,0 +1,190 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+
+
+#include <iostream>
+#include <cstring>
+#include <string>
+
+#include "dxr3unixserversocket.h"
+#include "dxr3interface.h"
+#include "dxr3log.h"
+
+using namespace std;
+
+#ifndef SOCKET_CHMOD
+#define SOCKET_CHMOD 0660
+#endif
+
+// ==================================
+cDxr3UnixServerSocket::cDxr3UnixServerSocket(const char* pFileName, int backlog)
+{
+ m_bConnected = false;
+ m_backlog = backlog;
+ m_addr.sun_family = AF_UNIX;
+ m_msgSize = 0;
+
+ m_pFileName = pFileName;
+ strcpy(m_addr.sun_path, pFileName);
+ unlink(pFileName);
+
+
+ m_fdServerSocket = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (m_fdServerSocket > -1)
+ {
+ if (bind(m_fdServerSocket, (sockaddr*)&m_addr, (socklen_t)sizeof(m_addr))) {
+ cLog::Instance() << "cDxr3UnixServerSocket::cDxr3UnixServerSocket Error: binding socket failed\n";
+ }
+
+ if (listen(m_fdServerSocket, m_backlog))
+ {
+ cLog::Instance() << "cDxr3UnixServerSocket::cDxr3UnixServerSocket Error: Listen failed\n";
+ }
+
+ if (chmod(m_pFileName, SOCKET_CHMOD))
+ {
+ cLog::Instance() << "cDxr3UnixServerSocket::cDxr3UnixServerSocket Error: Chmod failed\n";
+ }
+ }
+ else
+ {
+ cLog::Instance() << "cDxr3UnixServerSocket::cDxr3UnixServerSocket Error: Unable to create socket\n";
+ }
+}
+
+// ==================================
+bool cDxr3UnixServerSocket::WaitForConnection()
+{
+ cLog::Instance() << "cDxr3UnixServerSocket::WaitForConnection Waiting ...\n";
+ if (m_fdServerSocket > -1)
+ {
+ m_fdConnectionSocket = accept(m_fdServerSocket, 0, 0);
+ if (m_fdConnectionSocket > -1)
+ {
+ m_bConnected = true;
+ cLog::Instance() << "cDxr3UnixServerSocket::WaitForConnection Connected\n";
+ }
+ else
+ {
+ m_bConnected = false;
+ cLog::Instance() << "cDxr3UnixServerSocket::WaitForConnection failed\n";
+ }
+ }
+ else
+ {
+ m_bConnected = false;
+ }
+ return m_bConnected;
+}
+
+// ==================================
+bool cDxr3UnixServerSocket::GetNextMessage()
+{
+ bool ret = false;
+ m_msgSize = 0;
+ memset(m_msg, 0, MAX_REC_SIZE);
+
+ if (m_bConnected)
+ {
+ m_msgSize = read(m_fdConnectionSocket, m_msg, MAX_REC_SIZE - 1);
+ if (m_msgSize <= 0)
+ {
+ m_msgSize = 0;
+ m_bConnected = 0;
+ close(m_fdConnectionSocket);
+ cLog::Instance() << "cDxr3UnixServerSocket::GetNextMessage failed/connection closed\n";
+ }
+ else
+ {
+ ret = true;
+ }
+ }
+
+ if (ret) ProcessMessage();
+
+ return ret;
+}
+
+// ==================================
+bool cDxr3UnixServerSocket::IsConnected()
+{
+ return m_bConnected;
+}
+
+// ==================================
+cDxr3UnixServerSocket::~cDxr3UnixServerSocket()
+{
+ close(m_fdConnectionSocket);
+ close(m_fdServerSocket);
+ unlink(m_pFileName);
+}
+
+// ==================================
+void cDxr3StartStopSocket::SendStatus()
+{
+ if (cDxr3Interface::Instance().IsExternalReleased())
+ {
+ string res("CloseDxr3DeviceRsp\n");
+ write(m_fdConnectionSocket, res.c_str(), res.size());
+ }
+ else
+ {
+ string res("OpenDxr3DeviceRsp\n");
+ write(m_fdConnectionSocket, res.c_str(), res.size());
+ }
+}
+
+// ==================================
+void cDxr3StartStopSocket::ProcessMessage(void)
+{
+ cLog::Instance() << "cDxr3StartStopSocket::ProcessMessage Rec: " << (const char*) m_msg << "\n";
+
+ if (string((const char*)m_msg) == string("OpenDxr3DeviceCmd"))
+ {
+ cDxr3Interface::Instance().ExternalReopenDevices();
+ SendStatus();
+ }
+ else if (string((const char*)m_msg) == string("CloseDxr3DeviceCmd"))
+ {
+ cDxr3Interface::Instance().ExternalReleaseDevices();
+ SendStatus();
+ }
+ else if (string((const char*)m_msg) == string("StatusDxr3DeviceCmd"))
+ {
+ SendStatus();
+ }
+ else if (string((const char *)m_msg) == string("SaveDxr3DeviceCmd"))
+ {
+ m_bSavedState = cDxr3Interface::Instance().IsExternalReleased();
+ SendStatus();
+ }
+ else if (string((const char *)m_msg) == string("RestoreDxr3DeviceCmd"))
+ {
+ if (m_bSavedState)
+ {
+ cDxr3Interface::Instance().ExternalReleaseDevices();
+ }
+ else
+ {
+ cDxr3Interface::Instance().ExternalReopenDevices();
+ }
+ SendStatus();
+ }
+ else
+ {
+ string res("Error\n");
+ write(m_fdConnectionSocket, res.c_str(), res.size());
+ }
+}
+
+// ==================================
+void cDxr3StartStopThread::Action()
+{
+ cDxr3StartStopSocket mySocket;
+ while (mySocket.WaitForConnection())
+ {
+ while (mySocket.GetNextMessage());
+ }
+}
diff --git a/dxr3unixserversocket.h b/dxr3unixserversocket.h
new file mode 100644
index 0000000..3233995
--- /dev/null
+++ b/dxr3unixserversocket.h
@@ -0,0 +1,71 @@
+/*
+ * dxr3unixserversocket.h:
+ *
+ * See the main source file 'dxr3.c' for copyright information and
+ * how to reach the author.
+ *
+ */
+
+#ifndef __DXR3_UNIX_SERVER_SOCKET_H
+#define __DXR3_UNIX_SERVER_SOCKET_H
+
+#include <stdint.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+
+#include "dxr3vdrincludes.h"
+
+class cDxr3UnixServerSocket {
+public:
+ cDxr3UnixServerSocket(const char* pFileName = "/tmp/.dxr3-ux-sock", int backlog = 5);
+ virtual ~cDxr3UnixServerSocket();
+
+ bool WaitForConnection(void);
+ bool GetNextMessage(void);
+ bool IsConnected(void);
+protected:
+ virtual void ProcessMessage(void) = 0;
+
+ const char* m_pFileName;
+ bool m_bConnected;
+ int m_backlog;
+ int m_fdServerSocket;
+ int m_fdConnectionSocket;
+ sockaddr_un m_addr;
+ enum eDxr3socketMessageSize { MAX_REC_SIZE = 100 };
+ uint8_t m_msg[MAX_REC_SIZE];
+ uint8_t m_msgSize;
+
+private:
+ cDxr3UnixServerSocket(cDxr3UnixServerSocket&); // no copy constructor
+};
+
+
+class cDxr3StartStopSocket : public cDxr3UnixServerSocket {
+public:
+ cDxr3StartStopSocket() : m_bSavedState(false) {};
+ virtual ~cDxr3StartStopSocket() {};
+protected:
+ void ProcessMessage(void);
+ void SendStatus(void);
+
+ bool m_bSavedState;
+
+private:
+ cDxr3StartStopSocket(cDxr3StartStopSocket&); // no copy constructor
+};
+
+
+class cDxr3StartStopThread : public cThread {
+public:
+ cDxr3StartStopThread() {};
+ virtual ~cDxr3StartStopThread() {};
+protected:
+ virtual void Action(void);
+
+private:
+ cDxr3StartStopThread(cDxr3StartStopThread&); // no copy constructor
+};
+
+#endif // __DXR3_UNIX_SERVER_SOCKET_H
diff --git a/dxr3vdrincludes.h b/dxr3vdrincludes.h
new file mode 100644
index 0000000..896718e
--- /dev/null
+++ b/dxr3vdrincludes.h
@@ -0,0 +1,33 @@
+#ifndef _DXR3_VDRINCLUDES_H_
+#define _DXR3_VDRINCLUDES_H_
+
+#include <string>
+#include <algorithm>
+#include <vector>
+using namespace std;
+
+#ifndef __STL_CONFIG_H
+#define __STL_CONFIG_H
+#define __DXR3_UNDEF_STL_CONFIG_AFTERWARDS
+#endif
+
+// all includes from vdr
+#if VDRVERSNUM >= 10307
+ #include <vdr/osd.h>
+#else
+ #include <vdr/osdbase.h>
+#endif
+#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>
+
+#ifdef __DXR3_UNDEF_STL_CONFIG_AFTERWARDS
+#undef __STL_CONFIG_H
+#endif
+
+#endif /*_DXR3_VDRINCLUDES_H_*/