summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTORS27
-rw-r--r--HISTORY50
-rw-r--r--Make.config.template6
-rw-r--r--Makefile19
-rw-r--r--PLUGINS.html5
-rw-r--r--PLUGINS/src/dvbhddevice/COPYING340
-rw-r--r--PLUGINS/src/dvbhddevice/HISTORY16
-rw-r--r--PLUGINS/src/dvbhddevice/Makefile114
-rw-r--r--PLUGINS/src/dvbhddevice/README18
-rw-r--r--PLUGINS/src/dvbhddevice/bitbuffer.c97
-rw-r--r--PLUGINS/src/dvbhddevice/bitbuffer.h31
-rw-r--r--PLUGINS/src/dvbhddevice/dvbhddevice.c48
-rw-r--r--PLUGINS/src/dvbhddevice/dvbhdffdevice.c760
-rw-r--r--PLUGINS/src/dvbhddevice/dvbhdffdevice.h123
-rw-r--r--PLUGINS/src/dvbhddevice/hdffcmd.c1120
-rw-r--r--PLUGINS/src/dvbhddevice/hdffcmd.h102
-rw-r--r--PLUGINS/src/dvbhddevice/hdffmsgdef.h304
-rw-r--r--PLUGINS/src/dvbhddevice/hdffosd.c755
-rw-r--r--PLUGINS/src/dvbhddevice/hdffosd.h26
-rw-r--r--PLUGINS/src/dvbhddevice/setup.c252
-rw-r--r--PLUGINS/src/dvbhddevice/setup.h53
-rw-r--r--PLUGINS/src/dvbsddevice/HISTORY4
-rw-r--r--PLUGINS/src/dvbsddevice/dvbsddevice.c4
-rw-r--r--PLUGINS/src/dvbsddevice/dvbsdffosd.c8
-rw-r--r--PLUGINS/src/osddemo/HISTORY9
-rw-r--r--PLUGINS/src/osddemo/osddemo.c12
-rw-r--r--config.h10
-rw-r--r--device.h9
-rw-r--r--dvbspu.h5
-rw-r--r--dvbsubtitle.c84
-rw-r--r--dvbsubtitle.h5
-rw-r--r--font.c4
-rw-r--r--osd.c57
-rw-r--r--osd.h7
-rw-r--r--pat.c52
-rw-r--r--po/sr_SR.po2
-rw-r--r--recording.c35
-rw-r--r--recording.h7
-rw-r--r--remote.c6
-rw-r--r--remux.c44
-rw-r--r--remux.h7
-rwxr-xr-xrunvdr.template8
-rw-r--r--tools.c7
-rw-r--r--vdr.54
44 files changed, 4520 insertions, 136 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 74090c2..f6ba82c 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -1103,6 +1103,7 @@ Rolf Ahrenberg <rahrenbe@cc.hut.fi>
for fixing the array size of Atypes in cPatFilter::Process()
for adding support for "registration descriptor" to 'libsi' and using it in pat.c
for adding an include of VDR's 'Make.global' to libsi's Makefile
+ for adding handling of "ANSI/SCTE 57" descriptors
Ralf Klueber <ralf.klueber@vodafone.com>
for reporting a bug in cutting a recording if there is only a single editing mark
@@ -1264,6 +1265,10 @@ Reinhard Nissl <rnissl@gmx.de>
for some valuable input during development of the TrueColor OSD, help with
debugging, and an implementation of the AlphaBlend() function.
for storing the original display size when handling DVB subtitles
+ for reporting a problem with horizontal scaling of subtitles
+ for fixing a buffer overflow in cFont::Bidi()
+ for avoiding an unecessary call to Recordings.ResetResume()
+ for debugging a problem in handling the bitmap color depth for scaled subtitles
Richard Robson <richard_robson@beeb.net>
for reporting freezing replay if a timer starts while in Transfer Mode from the
@@ -1392,6 +1397,7 @@ Andreas Regel <andreas.regel@gmx.de>
for adding some missing 'const' statements to cBitmap
for making cDevice::AddPid() store the stream type of the given pid
for adding cFont::FontName() and cFont::Size()
+ for writing the dvbhddevice plugin
Thomas Bergwinkl <Thomas.Bergwinkl@vr-web.de>
for fixing the validity check for channel IDs, because some providers use TIDs
@@ -1688,6 +1694,8 @@ Udo Richter <udo_richter@gmx.de>
for reporting missing defines for large files in the 'newplugin' script
for pointing out that the full timer file name should be displayed if it ends with
"TITLE" or "EPISODE"
+ for a patch to "Made updating the editing marks during replay react faster in case
+ the marks file has just been written"
Sven Kreiensen <svenk@kammer.uni-hannover.de>
for his help in keeping 'channels.conf.terr' up to date
@@ -1886,6 +1894,9 @@ Ville Skyttä <ville.skytta@iki.fi>
for adding passing package name and version to xgettext
for making 'dist' target dependent on up to date *.po
for adding Language and fixing Language-Team header of *.po
+ for fixing the Language header of the Serbian translation file
+ for using pkg-config to get fribidi, freetype and fontconfig cflags and libs
+ for making the Makefile also install the include files
Steffen Beyer <cpunk@reactor.de>
for fixing setting the colored button help after deleting a recording in case the next
@@ -2205,6 +2216,7 @@ Christoph Haubrich <christoph1.haubrich@arcor.de>
for reporting unused 'synced' member in cTsToPes
for suggesting to add a note to cTsToPes about all TS packets having to belong to
the same PID
+ for adding HD stream content identifiers to vdr.5
Pekka Mauno <pekka.mauno@iki.fi>
for fixing cSchedule::GetFollowingEvent() in case there is currently no present
@@ -2522,6 +2534,8 @@ Winfried Köhler <w_koehl@gmx.de>
for fixing wrong value for TableIdBAT in libsi/si.h
for making several code modifications to avoid compiler warnings
for improving the description of the transponder parameters in vdr.5
+ for reporting a necessary fix in the description of cReceiver in PLUGINS.html,
+ regarding detaching a receiver from its device before deleting it
Igor M. Liplianin <liplianin@tut.by>
for a patch that was used to convert VDR to the S2API driver API
@@ -2601,6 +2615,7 @@ Francesco Saverio Schiavarelli <fschiava@libero.it>
Matti Lehtimäki <matti.lehtimaki@gmail.com>
for implementing the setup option "Miscellaneous/Channels wrap"
+ for reporting a missing change from -O2 to -O3 in Make.config.template
Stephan Austermühle <au@hcsd.de>
for suggesting to flush the file in cSafeFile::Close()
@@ -2622,6 +2637,8 @@ Paul Menzel <paulepanter@users.sourceforge.net>
for making include paths not be overwritten in the Makefile
for adding LDFLAGS to the linker calls in the Makefiles
for reporting a possible memory leak in the "pictures" plugin
+ for removing an obsolete local variable in dvbsdffosd.c
+ for reporting a possible NULL pointer dereference in osddemo.c
Radek Stastny <dedkus@gmail.com>
for translating OSD texts to the Czech language
@@ -2670,3 +2687,13 @@ Frank Neumann <frank.neumann@hp.com>
Gerald Dachs <vdr@dachsweb.de>
for reporting a problem with checking for minimum line length of 21 characters in
the LIRC receiver code
+
+Juergen Lock <vdr-l@jelal.kn-bremen.de>
+ for fixing cUnbufferedFile::Seek() in case it is compiled without USE_FADVISE
+
+Sergiu Dotenco <sergiu.dotenco@googlemail.com>
+ for reporting a missing initialization in sDvbSpuRect
+ for replacing "%lld" and "%llX" print format specifiers with "PRId64" and "PRIX64"
+
+Mika Laitio <lamikr@pilppa.org>
+ for reporting a case where cRecordingInfo::Read(FILE *f) was called with a NULL pointer
diff --git a/HISTORY b/HISTORY
index f73f5cf..c4e22fd 100644
--- a/HISTORY
+++ b/HISTORY
@@ -6556,3 +6556,53 @@ Video Disk Recorder Revision History
Reinhard Nissl).
- The original display size of subtitles is now used to scale them properly when
displaying them on an HD OSD.
+
+2011-04-17: Version 1.7.18
+
+- Changed -O2 to -O3 in Make.config.template (reported by Matti Lehtimäki).
+- Added a missing 'default' case in cPixmapMemory::DrawEllipse().
+- Fixed some direct comparisons of double values.
+- Fixed detecting frames on channels that broadcast with separate "fields" instead
+ of complete frames.
+- Made updating the editing marks during replay react faster in case the marks
+ file has just been written (with a patch from Udo Richter).
+- Fixed horizontal scaling of subtitles (reported by Reinhard Nissl).
+- Stripped the note "The data returned by this function is only used for informational
+ purposes (if any)" from the description of cDevice::GetVideoSize(). The VideoAspect
+ is now used to properly scale subtitles.
+- Fixed cUnbufferedFile::Seek() in case it is compiled without USE_FADVISE (thanks
+ to Juergen Lock).
+- Fixed the Language header of the Serbian translation file (thanks to Ville Skyttä).
+- Added anti-aliasing when upscaling bitmaps, which improves the display of SD subtitles
+ when replayed on an HD OSD (thanks to Reinhard Nissl for his help in debugging).
+- Renamed cBitmap::Scale() to Scaled(), because it doesn't modify the bitmap itself,
+ but rather returns a scaled copy.
+- Fixed the description of cReceiver in PLUGINS.html, regarding detaching a receiver
+ from its device before deleting it (reported by Winfried Köhler). This change in
+ behavior was introduced in version 1.5.7.
+- Fixed scaling subtitles in case the OSD size is exactly the same as the display
+ size of the subtitles.
+- Added a missing initialization to sDvbSpuRect (reported by Sergiu Dotenco).
+- Replaced "%lld" and "%llX" print format specifiers with "PRId64" and "PRIX64" to
+ avoid compiler warnings with gcc 4.5.2 (thanks to Sergiu Dotenco).
+ On a personal note: I find it a step in the totally wrong direction that there
+ have been macros introduced to work around this problem in the first place. There
+ should have been "real" format specifiers defined that address this. These macros
+ are nothing but an ugly workaround.
+- Added Cancel(3) to ~cTrueColorDemo() in the "osddemo" plugin (thanks to Reinhard Nissl).
+- Added a missing font deletion in cTrueColorDemo::Action() in the "osddemo" plugin
+ (thanks to Reinhard Nissl).
+- Fixed a buffer overflow in cFont::Bidi() (thanks to Reinhard Nissl).
+- Added HD stream content identifiers to vdr.5 (thanks to Christoph Haubrich).
+- Made cRecordingInfo::Read(FILE *f) private to avoid calls to it from outside
+ cRecordingInfo or cRecording (reported by Mika Laitio).
+- The dvbhddevice plugin is now part of the VDR distribution archive (thanks to
+ Andreas Regel).
+- Removed an obsolete local variable in dvbsdffosd.c (thanks to Paul Menzel).
+- Fixed a possible NULL pointer dereference in osddemo.c (reported by Paul Menzel).
+- Now using pkg-config to get fribidi, freetype and fontconfig cflags and libs (thanks
+ to Ville Skyttä).
+- The Makefile now also installs the include files (thanks to Ville Skyttä).
+- Added handling of "ANSI/SCTE 57" descriptors (thanks too Rolf Ahrenberg).
+- Avoiding an unecessary call to Recordings.ResetResume() (thanks to Reinhard
+ Nissl).
diff --git a/Make.config.template b/Make.config.template
index 3abb724..1fc8227 100644
--- a/Make.config.template
+++ b/Make.config.template
@@ -6,15 +6,15 @@
# See the main source file 'vdr.c' for copyright information and
# how to reach the author.
#
-# $Id: Make.config.template 2.2 2010/02/06 14:50:03 kls Exp $
+# $Id: Make.config.template 2.3 2011/03/13 13:41:12 kls Exp $
### The C compiler and options:
CC = gcc
-CFLAGS = -g -O2 -Wall
+CFLAGS = -g -O3 -Wall
CXX = g++
-CXXFLAGS = -g -O2 -Wall -Woverloaded-virtual -Wno-parentheses
+CXXFLAGS = -g -O3 -Wall -Woverloaded-virtual -Wno-parentheses
ifdef PLUGIN
CFLAGS += -fPIC
diff --git a/Makefile b/Makefile
index e84849b..9317839 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@
# See the main source file 'vdr.c' for copyright information and
# how to reach the author.
#
-# $Id: Makefile 2.14 2011/02/27 09:59:11 kls Exp $
+# $Id: Makefile 2.17 2011/04/17 13:35:53 kls Exp $
.DELETE_ON_ERROR:
@@ -19,9 +19,10 @@ DESTDIR ?=
PREFIX ?= /usr/local
MANDIR = $(PREFIX)/share/man
BINDIR = $(PREFIX)/bin
+INCDIR = $(PREFIX)/include
LOCDIR = ./locale
-LIBS = -ljpeg -lpthread -ldl -lcap -lrt -lfreetype -lfontconfig
-INCLUDES ?= $(shell pkg-config --cflags freetype2)
+LIBS = -ljpeg -lpthread -ldl -lcap -lrt $(shell pkg-config --libs freetype2 fontconfig)
+INCLUDES ?= $(shell pkg-config --cflags freetype2 fontconfig)
PLUGINDIR= ./PLUGINS
PLUGINLIBDIR= $(PLUGINDIR)/lib
@@ -54,9 +55,9 @@ ifdef VDR_USER
DEFINES += -DVDR_USER=\"$(VDR_USER)\"
endif
ifdef BIDI
-INCLUDES += -I/usr/include/fribidi
+INCLUDES += $(shell pkg-config --cflags fribidi)
DEFINES += -DBIDI
-LIBS += -lfribidi
+LIBS += $(shell pkg-config --libs fribidi)
endif
LIRC_DEVICE ?= /dev/lircd
@@ -162,7 +163,7 @@ clean-plugins:
# Install the files:
-install: install-bin install-conf install-doc install-plugins install-i18n
+install: install-bin install-conf install-doc install-plugins install-i18n install-includes
# VDR binary:
@@ -193,6 +194,12 @@ install-plugins: plugins
@mkdir -p $(DESTDIR)$(PLUGINLIBDIR)
@cp --remove-destination $(PLUGINDIR)/lib/lib*-*.so.$(APIVERSION) $(DESTDIR)$(PLUGINLIBDIR)
+# Includes:
+
+install-includes: include-dir
+ @mkdir -p $(DESTDIR)$(INCDIR)
+ @cp -pLR include/vdr include/libsi $(DESTDIR)$(INCDIR)
+
# Source documentation:
srcdoc:
diff --git a/PLUGINS.html b/PLUGINS.html
index 05fb7ed..3859918 100644
--- a/PLUGINS.html
+++ b/PLUGINS.html
@@ -1523,8 +1523,9 @@ the receiver is attached to the device that actually receives the current live
video stream (this may be different from the primary device in case of <i>Transfer
Mode</i>).
<p>
-If the <tt>cReceiver</tt> isn't needed any more, it may simply be <i>deleted</i>
-and will automatically detach itself from the <tt>cDevice</tt>.
+<div class="modified">
+The <tt>cReceiver</tt> must be detached from its device before it is deleted.
+</div modified>
<hr><h2><a name="Filters">Filters</a></h2>
diff --git a/PLUGINS/src/dvbhddevice/COPYING b/PLUGINS/src/dvbhddevice/COPYING
new file mode 100644
index 0000000..f90922e
--- /dev/null
+++ b/PLUGINS/src/dvbhddevice/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/PLUGINS/src/dvbhddevice/HISTORY b/PLUGINS/src/dvbhddevice/HISTORY
new file mode 100644
index 0000000..aa788fd
--- /dev/null
+++ b/PLUGINS/src/dvbhddevice/HISTORY
@@ -0,0 +1,16 @@
+VDR Plugin 'dvbhddevice' Revision History
+-----------------------------------------
+
+2009-12-29: Version 0.0.1
+
+- Initial revision.
+
+2010-01-04: Version 0.0.2
+
+- Calling the MakePrimaryDevice() function of the base class to allow
+ the cDevice to stop displaying subtitles.
+- Added support for DVB cards with multiple frontends.
+
+2011-04-17: Version 0.0.3
+
+- Added support for TrueColor OSD.
diff --git a/PLUGINS/src/dvbhddevice/Makefile b/PLUGINS/src/dvbhddevice/Makefile
new file mode 100644
index 0000000..ea1b9d1
--- /dev/null
+++ b/PLUGINS/src/dvbhddevice/Makefile
@@ -0,0 +1,114 @@
+#
+# Makefile for a Video Disk Recorder plugin
+#
+# $Id: Makefile 1.7 2011/04/17 11:40:55 kls 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.
+# IMPORTANT: the presence of this macro is important for the Make.config
+# file. So it must be defined, even if it is not used here!
+#
+PLUGIN = dvbhddevice
+
+### 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 ?= -g -O3 -Wall -Woverloaded-virtual -Wno-parentheses
+
+### The directory environment:
+
+VDRDIR = ../../..
+LIBDIR = ../../lib
+TMPDIR = /tmp
+
+### Make sure that necessary options are included:
+
+include $(VDRDIR)/Make.global
+
+### Allow user defined options to overwrite defaults:
+
+-include $(VDRDIR)/Make.config
+
+### The version number of VDR's plugin API (taken from VDR's "config.h"):
+
+APIVERSION = $(shell sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/config.h)
+
+### The name of the distribution archive:
+
+ARCHIVE = $(PLUGIN)-$(VERSION)
+PACKAGE = vdr-$(ARCHIVE)
+
+### Includes and Defines (add further entries here):
+
+INCLUDES += -I$(VDRDIR)/include
+
+DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
+
+### The object files (add further files here):
+
+OBJS = $(PLUGIN).o bitbuffer.o dvbhdffdevice.o hdffcmd.o hdffosd.o setup.o
+
+### The main target:
+
+all: libvdr-$(PLUGIN).so i18n
+
+### Implicit rules:
+
+%.o: %.c
+ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
+
+### Dependencies:
+
+MAKEDEP = $(CXX) -MM -MG
+DEPFILE = .dependencies
+$(DEPFILE): Makefile
+ @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
+
+-include $(DEPFILE)
+
+### Internationalization (I18N):
+
+PODIR = po
+LOCALEDIR = $(VDRDIR)/locale
+I18Npo = $(wildcard $(PODIR)/*.po)
+I18Nmsgs = $(addprefix $(LOCALEDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLUGIN).mo, $(notdir $(foreach file, $(I18Npo), $(basename $(file))))))
+I18Npot = $(PODIR)/$(PLUGIN).pot
+
+%.mo: %.po
+ msgfmt -c -o $@ $<
+
+$(I18Npot): $(wildcard *.c)
+ xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --package-name=VDR --package-version=$(VDRVERSION) --msgid-bugs-address='<see README>' -o $@ $^
+
+%.po: $(I18Npot)
+ msgmerge -U --no-wrap --no-location --backup=none -q $@ $<
+ @touch $@
+
+$(I18Nmsgs): $(LOCALEDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo
+ @mkdir -p $(dir $@)
+ cp $< $@
+
+.PHONY: i18n
+i18n: $(I18Nmsgs) $(I18Npot)
+
+### Targets:
+
+libvdr-$(PLUGIN).so: $(OBJS)
+ $(CXX) $(CXXFLAGS) -shared $(OBJS) -o $@
+ @cp --remove-destination $@ $(LIBDIR)/$@.$(APIVERSION)
+
+dist: $(I18Npo) 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* *~ $(PODIR)/*.mo $(PODIR)/*.pot
diff --git a/PLUGINS/src/dvbhddevice/README b/PLUGINS/src/dvbhddevice/README
new file mode 100644
index 0000000..5697dea
--- /dev/null
+++ b/PLUGINS/src/dvbhddevice/README
@@ -0,0 +1,18 @@
+This is a "plugin" for the Video Disk Recorder (VDR).
+
+Written by: Andreas Regel <andreas.regel@gmx.de>
+
+Project's homepage: http://powarman.dyndns.org/hg/dvbhddevice
+
+Latest version available at: http://powarman.dyndns.org/hg/dvbhddevice
+
+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.
+See the file COPYING for more information.
+
+Description:
+
+The 'dvbhddevice' plugin implements the output device for the
+"Full Featured TechnoTrend S2-6400" DVB cards.
diff --git a/PLUGINS/src/dvbhddevice/bitbuffer.c b/PLUGINS/src/dvbhddevice/bitbuffer.c
new file mode 100644
index 0000000..244b85e
--- /dev/null
+++ b/PLUGINS/src/dvbhddevice/bitbuffer.c
@@ -0,0 +1,97 @@
+/*
+ * bitbuffer.c: TODO(short description)
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id: bitbuffer.c 1.1 2009/12/29 14:29:20 kls Exp $
+ */
+
+#include "bitbuffer.h"
+#include <stdlib.h>
+
+cBitBuffer::cBitBuffer(uint32_t MaxLength)
+{
+ mData = NULL;
+ mMaxLength = 0;
+ mBitPos = 0;
+
+ if (MaxLength <= 0x10000)
+ {
+ mData = new uint8_t[MaxLength];
+ if (mData)
+ {
+ mMaxLength = MaxLength * 8;
+ }
+ }
+}
+
+cBitBuffer::~cBitBuffer(void)
+{
+ if (mData)
+ delete[] mData;
+}
+
+uint8_t * cBitBuffer::GetData(void)
+{
+ return mData;
+}
+
+uint32_t cBitBuffer::GetMaxLength(void)
+{
+ return mMaxLength / 8;
+}
+
+uint32_t cBitBuffer::GetBits(int NumBits)
+{
+ return 0;
+}
+
+void cBitBuffer::SetBits(int NumBits, uint32_t Data)
+{
+ uint32_t nextBitPos;
+ uint32_t bytePos;
+ uint32_t bitsInByte;
+ int shift;
+
+ if (NumBits <= 0 || NumBits > 32)
+ return;
+
+ nextBitPos = mBitPos + NumBits;
+
+ if (nextBitPos > mMaxLength)
+ return;
+
+ bytePos = mBitPos / 8;
+ bitsInByte = mBitPos % 8;
+
+ mData[bytePos] &= (uint8_t) (0xFF << (8 - bitsInByte));
+ shift = NumBits - (8 - bitsInByte);
+ if (shift > 0)
+ mData[bytePos] |= (uint8_t) (Data >> shift);
+ else
+ mData[bytePos] |= (uint8_t) (Data << (-shift));
+ NumBits -= 8 - bitsInByte;
+ bytePos++;
+ while (NumBits > 0)
+ {
+ shift = NumBits - 8;
+ if (shift > 0)
+ mData[bytePos] = (uint8_t) (Data >> shift);
+ else
+ mData[bytePos] = (uint8_t) (Data << (-shift));
+ NumBits -= 8;
+ bytePos++;
+ }
+ mBitPos = nextBitPos;
+}
+
+uint32_t cBitBuffer::GetByteLength(void)
+{
+ return (mBitPos + 7) / 8;
+}
+
+void cBitBuffer::SetDataByte(uint32_t Position, uint8_t Data)
+{
+ if (Position < mMaxLength)
+ mData[Position] = Data;
+}
diff --git a/PLUGINS/src/dvbhddevice/bitbuffer.h b/PLUGINS/src/dvbhddevice/bitbuffer.h
new file mode 100644
index 0000000..e7b3650
--- /dev/null
+++ b/PLUGINS/src/dvbhddevice/bitbuffer.h
@@ -0,0 +1,31 @@
+/*
+ * bitbuffer.h: TODO(short description)
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id: bitbuffer.h 1.1 2009/12/29 14:27:03 kls Exp $
+ */
+
+#ifndef _HDFF_BITBUFFER_H_
+#define _HDFF_BITBUFFER_H_
+
+#include <stdint.h>
+
+class cBitBuffer
+{
+private:
+ uint8_t * mData;
+ uint32_t mMaxLength;
+ uint32_t mBitPos;
+public:
+ cBitBuffer(uint32_t MaxLength);
+ ~cBitBuffer(void);
+ uint8_t * GetData(void);
+ uint32_t GetMaxLength(void);
+ uint32_t GetBits(int NumBits);
+ void SetBits(int NumBits, uint32_t Data);
+ uint32_t GetByteLength(void);
+ void SetDataByte(uint32_t Position, uint8_t Data);
+};
+
+#endif
diff --git a/PLUGINS/src/dvbhddevice/dvbhddevice.c b/PLUGINS/src/dvbhddevice/dvbhddevice.c
new file mode 100644
index 0000000..d639922
--- /dev/null
+++ b/PLUGINS/src/dvbhddevice/dvbhddevice.c
@@ -0,0 +1,48 @@
+/*
+ * dvbhddevice.c: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id: dvbhddevice.c 1.12 2011/04/17 11:20:22 kls Exp $
+ */
+
+#include <vdr/plugin.h>
+#include "dvbhdffdevice.h"
+#include "setup.h"
+
+static const char *VERSION = "0.0.3";
+static const char *DESCRIPTION = "HD Full Featured DVB device";
+
+class cPluginDvbhddevice : public cPlugin {
+private:
+ cDvbHdFfDeviceProbe *probe;
+public:
+ cPluginDvbhddevice(void);
+ virtual ~cPluginDvbhddevice();
+ virtual const char *Version(void) { return VERSION; }
+ virtual const char *Description(void) { return DESCRIPTION; }
+ virtual cMenuSetupPage *SetupMenu(void);
+ virtual bool SetupParse(const char *Name, const char *Value);
+ };
+
+cPluginDvbhddevice::cPluginDvbhddevice(void)
+{
+ probe = new cDvbHdFfDeviceProbe;
+}
+
+cPluginDvbhddevice::~cPluginDvbhddevice()
+{
+ delete probe;
+}
+
+cMenuSetupPage *cPluginDvbhddevice::SetupMenu(void)
+{
+ return new cHdffSetupPage(cDvbHdFfDevice::GetHdffCmdHandler());
+}
+
+bool cPluginDvbhddevice::SetupParse(const char *Name, const char *Value)
+{
+ return gHdffSetup.SetupParse(Name, Value);
+}
+
+VDRPLUGINCREATOR(cPluginDvbhddevice); // Don't touch this!
diff --git a/PLUGINS/src/dvbhddevice/dvbhdffdevice.c b/PLUGINS/src/dvbhddevice/dvbhdffdevice.c
new file mode 100644
index 0000000..9263009
--- /dev/null
+++ b/PLUGINS/src/dvbhddevice/dvbhdffdevice.c
@@ -0,0 +1,760 @@
+/*
+ * dvbhdffdevice.c: The DVB HD Full Featured device interface
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id: dvbhdffdevice.c 1.29 2011/04/17 11:20:22 kls Exp $
+ */
+
+#include "dvbhdffdevice.h"
+#include <errno.h>
+#include <limits.h>
+#include <libsi/si.h>
+#include <linux/videodev2.h>
+#include <linux/dvb/audio.h>
+#include <linux/dvb/dmx.h>
+#include <linux/dvb/video.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <vdr/eitscan.h>
+#include <vdr/transfer.h>
+#include "hdffosd.h"
+#include "setup.h"
+
+// --- cDvbHdFfDevice ----------------------------------------------------------
+
+int cDvbHdFfDevice::devHdffOffset = -1;
+
+cDvbHdFfDevice::cDvbHdFfDevice(int Adapter, int Frontend)
+:cDvbDevice(Adapter, Frontend)
+{
+ spuDecoder = NULL;
+ audioChannel = 0;
+ playMode = pmNone;
+ mHdffCmdIf = NULL;
+
+ // Devices that are only present on cards with decoders:
+
+ fd_osd = DvbOpen(DEV_DVB_OSD, adapter, frontend, O_RDWR);
+ fd_video = DvbOpen(DEV_DVB_VIDEO, adapter, frontend, O_RDWR | O_NONBLOCK);
+ fd_audio = DvbOpen(DEV_DVB_AUDIO, adapter, frontend, O_RDWR | O_NONBLOCK);
+
+ //TODO missing /dev/video offset calculation
+
+ isHdffPrimary = false;
+ if (devHdffOffset < 0) {
+ devHdffOffset = adapter;
+ isHdffPrimary = true;
+ mHdffCmdIf = new HDFF::cHdffCmdIf(fd_osd);
+ mHdffCmdIf->CmdAvSetAudioDelay(gHdffSetup.AudioDelay);
+ mHdffCmdIf->CmdAvSetAudioDownmix((HDFF::eDownmixMode) gHdffSetup.AudioDownmix);
+ mHdffCmdIf->CmdMuxSetVideoOut((HDFF::eVideoOut) gHdffSetup.AnalogueVideo);
+ mHdffCmdIf->CmdHdmiSetVideoMode(gHdffSetup.GetVideoMode());
+ HDFF::tHdmiConfig hdmiConfig;
+ hdmiConfig.TransmitAudio = true;
+ hdmiConfig.ForceDviMode = false;
+ hdmiConfig.CecEnabled = gHdffSetup.CecEnabled;
+ mHdffCmdIf->CmdHdmiConfigure(&hdmiConfig);
+ if (gHdffSetup.CecEnabled)
+ mHdffCmdIf->CmdHdmiSendCecCommand(HDFF::cecCommandTvOn);
+ mHdffCmdIf->CmdRemoteSetProtocol((HDFF::eRemoteProtocol) gHdffSetup.RemoteProtocol);
+ mHdffCmdIf->CmdRemoteSetAddressFilter(gHdffSetup.RemoteAddress >= 0, gHdffSetup.RemoteAddress);
+ }
+
+ // Video format:
+
+ SetVideoFormat(Setup.VideoFormat);
+}
+
+cDvbHdFfDevice::~cDvbHdFfDevice()
+{
+ delete spuDecoder;
+ if (isHdffPrimary)
+ delete mHdffCmdIf;
+ // We're not explicitly closing any device files here, since this sometimes
+ // caused segfaults. Besides, the program is about to terminate anyway...
+}
+
+void cDvbHdFfDevice::MakePrimaryDevice(bool On)
+{
+ if (On)
+ new cHdffOsdProvider(mHdffCmdIf);
+ cDvbDevice::MakePrimaryDevice(On);
+}
+
+bool cDvbHdFfDevice::HasDecoder(void) const
+{
+ return isHdffPrimary;
+}
+
+cSpuDecoder *cDvbHdFfDevice::GetSpuDecoder(void)
+{
+ if (!spuDecoder && IsPrimaryDevice())
+ spuDecoder = new cDvbSpuDecoder();
+ return spuDecoder;
+}
+
+uchar *cDvbHdFfDevice::GrabImage(int &Size, bool Jpeg, int Quality, int SizeX, int SizeY)
+{
+ //TODO
+ return NULL;
+}
+
+void cDvbHdFfDevice::SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat)
+{
+ //TODO???
+ cDevice::SetVideoDisplayFormat(VideoDisplayFormat);
+}
+
+void cDvbHdFfDevice::SetVideoFormat(bool VideoFormat16_9)
+{
+ HDFF::tVideoFormat videoFormat;
+ videoFormat.AutomaticEnabled = true;
+ videoFormat.AfdEnabled = true;
+ videoFormat.TvFormat = (HDFF::eTvFormat) gHdffSetup.TvFormat;
+ videoFormat.VideoConversion = (HDFF::eVideoConversion) gHdffSetup.VideoConversion;
+ mHdffCmdIf->CmdAvSetVideoFormat(0, &videoFormat);
+}
+
+eVideoSystem cDvbHdFfDevice::GetVideoSystem(void)
+{
+ eVideoSystem VideoSystem = vsPAL;
+ if (fd_video >= 0) {
+ video_size_t vs;
+ if (ioctl(fd_video, VIDEO_GET_SIZE, &vs) == 0) {
+ if (vs.h == 480 || vs.h == 240)
+ VideoSystem = vsNTSC;
+ }
+ else
+ LOG_ERROR;
+ }
+ return VideoSystem;
+}
+
+void cDvbHdFfDevice::GetVideoSize(int &Width, int &Height, double &VideoAspect)
+{
+ if (fd_video >= 0) {
+ video_size_t vs;
+ if (ioctl(fd_video, VIDEO_GET_SIZE, &vs) == 0) {
+ Width = vs.w;
+ Height = vs.h;
+ switch (vs.aspect_ratio) {
+ default:
+ case VIDEO_FORMAT_4_3: VideoAspect = 4.0 / 3.0; break;
+ case VIDEO_FORMAT_16_9: VideoAspect = 16.0 / 9.0; break;
+ case VIDEO_FORMAT_221_1: VideoAspect = 2.21; break;
+ }
+ return;
+ }
+ else
+ LOG_ERROR;
+ }
+ cDevice::GetVideoSize(Width, Height, VideoAspect);
+}
+
+void cDvbHdFfDevice::GetOsdSize(int &Width, int &Height, double &PixelAspect)
+{
+ gHdffSetup.GetOsdSize(Width, Height, PixelAspect);
+}
+
+/*TODO obsolete?
+bool cDvbHdFfDevice::SetAudioBypass(bool On)
+{
+ if (setTransferModeForDolbyDigital != 1)
+ return false;
+ return ioctl(fd_audio, AUDIO_SET_BYPASS_MODE, On) == 0;
+}
+TODO*/
+
+bool cDvbHdFfDevice::SetPid(cPidHandle *Handle, int Type, bool On)
+{
+ if (Handle->pid) {
+ dmx_pes_filter_params pesFilterParams;
+ memset(&pesFilterParams, 0, sizeof(pesFilterParams));
+ if (On) {
+ if (Handle->handle < 0) {
+ Handle->handle = DvbOpen(DEV_DVB_DEMUX, adapter, frontend, O_RDWR | O_NONBLOCK, true);
+ if (Handle->handle < 0) {
+ LOG_ERROR;
+ return false;
+ }
+ }
+ if (Type == ptPcr)
+ mHdffCmdIf->CmdAvSetPcrPid(0, Handle->pid);
+ else if (Type == ptVideo) {
+ if (Handle->streamType == 0x1B)
+ mHdffCmdIf->CmdAvSetVideoPid(0, Handle->pid, HDFF::videoStreamH264);
+ else
+ mHdffCmdIf->CmdAvSetVideoPid(0, Handle->pid, HDFF::videoStreamMpeg2);
+ }
+ else if (Type == ptAudio)
+ mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF::audioStreamMpeg1);
+ else if (Type == ptDolby)
+ mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF::audioStreamAc3);
+ if (!(Type <= ptDolby && Handle->used <= 1)) {
+ pesFilterParams.pid = Handle->pid;
+ pesFilterParams.input = DMX_IN_FRONTEND;
+ pesFilterParams.output = DMX_OUT_TS_TAP;
+ pesFilterParams.pes_type= DMX_PES_OTHER;
+ pesFilterParams.flags = DMX_IMMEDIATE_START;
+ if (ioctl(Handle->handle, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
+ LOG_ERROR;
+ return false;
+ }
+ }
+ }
+ else if (!Handle->used) {
+ CHECK(ioctl(Handle->handle, DMX_STOP));
+ if (Type == ptPcr)
+ mHdffCmdIf->CmdAvSetPcrPid(0, 0);
+ else if (Type == ptVideo)
+ mHdffCmdIf->CmdAvSetVideoPid(0, 0, HDFF::videoStreamMpeg2);
+ else if (Type == ptAudio)
+ mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF::audioStreamMpeg1);
+ else if (Type == ptDolby)
+ mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF::audioStreamAc3);
+ //TODO missing setting to 0x1FFF??? see cDvbDevice::SetPid()
+ close(Handle->handle);
+ Handle->handle = -1;
+ }
+ }
+ return true;
+}
+
+void cDvbHdFfDevice::TurnOffLiveMode(bool LiveView)
+{
+ // Turn off live PIDs:
+
+ DetachAll(pidHandles[ptAudio].pid);
+ DetachAll(pidHandles[ptVideo].pid);
+ DetachAll(pidHandles[ptPcr].pid);
+ DetachAll(pidHandles[ptTeletext].pid);
+ DelPid(pidHandles[ptAudio].pid);
+ DelPid(pidHandles[ptVideo].pid);
+ DelPid(pidHandles[ptPcr].pid, ptPcr);
+ DelPid(pidHandles[ptTeletext].pid);
+ DelPid(pidHandles[ptDolby].pid);
+}
+
+bool cDvbHdFfDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
+{
+ int apid = Channel->Apid(0);
+ int vpid = Channel->Vpid();
+ int dpid = Channel->Dpid(0);
+
+ bool DoTune = !IsTunedToTransponder(Channel);
+
+ bool pidHandlesVideo = pidHandles[ptVideo].pid == vpid;
+ bool pidHandlesAudio = pidHandles[ptAudio].pid == apid;
+
+ bool TurnOffLivePIDs = DoTune
+ || !IsPrimaryDevice()
+ || LiveView // for a new live view the old PIDs need to be turned off
+ || pidHandlesVideo // for recording the PIDs must be shifted from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER
+ ;
+
+ bool StartTransferMode = IsPrimaryDevice() && !DoTune
+ && (LiveView && HasPid(vpid ? vpid : apid) && (!pidHandlesVideo || (!pidHandlesAudio && (dpid ? pidHandles[ptAudio].pid != dpid : true)))// the PID is already set as DMX_PES_OTHER
+ || !LiveView && (pidHandlesVideo || pidHandlesAudio) // a recording is going to shift the PIDs from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER
+ );
+ if (CamSlot() && !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), CamSlot()->SlotNumber()))
+ StartTransferMode |= LiveView && IsPrimaryDevice() && Channel->Ca() >= CA_ENCRYPTED_MIN;
+
+ bool TurnOnLivePIDs = !StartTransferMode && LiveView;
+
+ // Turn off live PIDs if necessary:
+
+ if (TurnOffLivePIDs)
+ TurnOffLiveMode(LiveView);
+
+ // Set the tuner:
+
+ if (!cDvbDevice::SetChannelDevice(Channel, LiveView))
+ return false;
+
+ // If this channel switch was requested by the EITScanner we don't wait for
+ // a lock and don't set any live PIDs (the EITScanner will wait for the lock
+ // by itself before setting any filters):
+
+ if (EITScanner.UsesDevice(this)) //XXX
+ return true;
+
+ // PID settings:
+
+ if (TurnOnLivePIDs) {
+ //SetAudioBypass(false);//TODO obsolete?
+ if (!(AddPid(Channel->Ppid(), ptPcr) && AddPid(vpid, ptVideo, Channel->Vtype()) && AddPid(apid, ptAudio))) {
+ esyslog("ERROR: failed to set PIDs for channel %d on device %d", Channel->Number(), CardIndex() + 1);
+ return false;
+ }
+ if (IsPrimaryDevice())
+ AddPid(Channel->Tpid(), ptTeletext);//TODO obsolete?
+ }
+ else if (StartTransferMode)
+ cControl::Launch(new cTransferControl(this, Channel));
+
+ return true;
+}
+
+int cDvbHdFfDevice::GetAudioChannelDevice(void)
+{
+ return audioChannel;
+}
+
+void cDvbHdFfDevice::SetAudioChannelDevice(int AudioChannel)
+{
+ mHdffCmdIf->CmdAvSetAudioChannel(AudioChannel);
+ audioChannel = AudioChannel;
+}
+
+void cDvbHdFfDevice::SetVolumeDevice(int Volume)
+{
+ mHdffCmdIf->CmdMuxSetVolume(Volume * 100 / 255);
+}
+
+void cDvbHdFfDevice::SetDigitalAudioDevice(bool On)
+{
+ // not needed
+}
+
+void cDvbHdFfDevice::SetAudioTrackDevice(eTrackType Type)
+{
+ //printf("SetAudioTrackDevice %d\n", Type);
+ const tTrackId *TrackId = GetTrack(Type);
+ if (TrackId && TrackId->id) {
+ if (IS_AUDIO_TRACK(Type)) {
+ if (pidHandles[ptAudio].pid && pidHandles[ptAudio].pid != TrackId->id) {
+ DetachAll(pidHandles[ptAudio].pid);
+ if (CamSlot())
+ CamSlot()->SetPid(pidHandles[ptAudio].pid, false);
+ pidHandles[ptAudio].pid = TrackId->id;
+ SetPid(&pidHandles[ptAudio], ptAudio, true);
+ if (CamSlot()) {
+ CamSlot()->SetPid(pidHandles[ptAudio].pid, true);
+ CamSlot()->StartDecrypting();
+ }
+ }
+ }
+ else if (IS_DOLBY_TRACK(Type)) {
+ pidHandles[ptDolby].pid = TrackId->id;
+ SetPid(&pidHandles[ptDolby], ptDolby, true);
+ }
+ }
+}
+
+bool cDvbHdFfDevice::CanReplay(void) const
+{
+ return cDevice::CanReplay();
+}
+
+bool cDvbHdFfDevice::SetPlayMode(ePlayMode PlayMode)
+{
+ if (PlayMode == pmNone) {
+ mHdffCmdIf->CmdAvEnableVideoAfterStop(0, false);
+ mHdffCmdIf->CmdAvSetPcrPid(0, 0);
+ mHdffCmdIf->CmdAvSetVideoPid(0, 0, HDFF::videoStreamMpeg2);
+ mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF::audioStreamMpeg1);
+
+ ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX);
+ mHdffCmdIf->CmdAvSetDecoderInput(0, 0);
+ mHdffCmdIf->CmdAvEnableSync(0, true);
+ mHdffCmdIf->CmdAvSetPlayMode(0, true);
+ }
+ else {
+ if (playMode == pmNone)
+ TurnOffLiveMode(true);
+
+ mHdffCmdIf->CmdAvSetPlayMode(1, Transferring());
+ mHdffCmdIf->CmdAvSetStc(0, 100000);
+ mHdffCmdIf->CmdAvEnableSync(0, true);
+ mHdffCmdIf->CmdAvEnableVideoAfterStop(0, true);
+
+ playVideoPid = -1;
+ playAudioPid = -1;
+ audioCounter = 0;
+ videoCounter = 0;
+
+ mHdffCmdIf->CmdAvSetDecoderInput(0, 2);
+ ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY);
+ }
+ playMode = PlayMode;
+ return true;
+}
+
+int64_t cDvbHdFfDevice::GetSTC(void)
+{
+ if (fd_video >= 0) {
+ uint64_t pts;
+ if (ioctl(fd_video, VIDEO_GET_PTS, &pts) == -1) {
+ esyslog("ERROR: pts %d: %m", CardIndex() + 1);
+ return -1;
+ }
+ return pts;
+ }
+ if (fd_audio >= 0) {
+ uint64_t pts;
+ if (ioctl(fd_audio, AUDIO_GET_PTS, &pts) == -1) {
+ esyslog("ERROR: pts %d: %m", CardIndex() + 1);
+ return -1;
+ }
+ return pts;
+ }
+ return -1;
+}
+
+void cDvbHdFfDevice::TrickSpeed(int Speed)
+{
+ mHdffCmdIf->CmdAvEnableSync(0, false);
+ mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF::audioStreamMpeg1);
+ playAudioPid = -1;
+ if (Speed > 0)
+ mHdffCmdIf->CmdAvSetVideoSpeed(0, 100 / Speed);
+}
+
+void cDvbHdFfDevice::Clear(void)
+{
+ CHECK(ioctl(fd_video, VIDEO_CLEAR_BUFFER));
+ mHdffCmdIf->CmdAvSetVideoPid(0, 0, HDFF::videoStreamMpeg1);
+ mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF::audioStreamMpeg1);
+ playVideoPid = -1;
+ playAudioPid = -1;
+ cDevice::Clear();
+}
+
+void cDvbHdFfDevice::Play(void)
+{
+ mHdffCmdIf->CmdAvEnableSync(0, true);
+ mHdffCmdIf->CmdAvSetVideoSpeed(0, 100);
+ mHdffCmdIf->CmdAvSetAudioSpeed(0, 100);
+ cDevice::Play();
+}
+
+void cDvbHdFfDevice::Freeze(void)
+{
+ mHdffCmdIf->CmdAvSetVideoSpeed(0, 0);
+ mHdffCmdIf->CmdAvSetAudioSpeed(0, 0);
+ cDevice::Freeze();
+}
+
+void cDvbHdFfDevice::Mute(void)
+{
+ //TODO???
+ cDevice::Mute();
+}
+
+static HDFF::eVideoStreamType MapVideoStreamTypes(int Vtype)
+{
+ switch (Vtype) {
+ case 0x01: return HDFF::videoStreamMpeg1;
+ case 0x02: return HDFF::videoStreamMpeg2;
+ case 0x1B: return HDFF::videoStreamH264;
+ default: return HDFF::videoStreamMpeg2; // fallback to MPEG2
+ }
+}
+
+void cDvbHdFfDevice::StillPicture(const uchar *Data, int Length)
+{
+ if (!Data || Length < TS_SIZE)
+ return;
+ if (Data[0] == 0x47) {
+ // TS data
+ cDevice::StillPicture(Data, Length);
+ }
+ else if (Data[0] == 0x00 && Data[1] == 0x00 && Data[2] == 0x01 && (Data[3] & 0xF0) == 0xE0) {
+ // PES data
+ char *buf = MALLOC(char, Length);
+ if (!buf)
+ return;
+ int i = 0;
+ int blen = 0;
+ while (i < Length - 6) {
+ if (Data[i] == 0x00 && Data[i + 1] == 0x00 && Data[i + 2] == 0x01) {
+ int len = Data[i + 4] * 256 + Data[i + 5];
+ if ((Data[i + 3] & 0xF0) == 0xE0) { // video packet
+ // skip PES header
+ int offs = i + 6;
+ // skip header extension
+ if ((Data[i + 6] & 0xC0) == 0x80) {
+ // MPEG-2 PES header
+ if (Data[i + 8] >= Length)
+ break;
+ offs += 3;
+ offs += Data[i + 8];
+ len -= 3;
+ len -= Data[i + 8];
+ if (len < 0 || offs + len > Length)
+ break;
+ }
+ else {
+ // MPEG-1 PES header
+ while (offs < Length && len > 0 && Data[offs] == 0xFF) {
+ offs++;
+ len--;
+ }
+ if (offs <= Length - 2 && len >= 2 && (Data[offs] & 0xC0) == 0x40) {
+ offs += 2;
+ len -= 2;
+ }
+ if (offs <= Length - 5 && len >= 5 && (Data[offs] & 0xF0) == 0x20) {
+ offs += 5;
+ len -= 5;
+ }
+ else if (offs <= Length - 10 && len >= 10 && (Data[offs] & 0xF0) == 0x30) {
+ offs += 10;
+ len -= 10;
+ }
+ else if (offs < Length && len > 0) {
+ offs++;
+ len--;
+ }
+ }
+ if (blen + len > Length) // invalid PES length field
+ break;
+ memcpy(&buf[blen], &Data[offs], len);
+ i = offs + len;
+ blen += len;
+ }
+ else if (Data[i + 3] >= 0xBD && Data[i + 3] <= 0xDF) // other PES packets
+ i += len + 6;
+ else
+ i++;
+ }
+ else
+ i++;
+ }
+ mHdffCmdIf->CmdAvShowStillImage(0, (uint8_t *)buf, blen, MapVideoStreamTypes(PatPmtParser()->Vtype()));
+ free(buf);
+ }
+ else {
+ // non-PES data
+ mHdffCmdIf->CmdAvShowStillImage(0, Data, Length, MapVideoStreamTypes(PatPmtParser()->Vtype()));
+ }
+}
+
+bool cDvbHdFfDevice::Poll(cPoller &Poller, int TimeoutMs)
+{
+ Poller.Add(fd_video, true);
+ return Poller.Poll(TimeoutMs);
+}
+
+bool cDvbHdFfDevice::Flush(int TimeoutMs)
+{
+ //TODO actually this function should wait until all buffered data has been processed by the card, but how?
+ return true;
+}
+
+void cDvbHdFfDevice::BuildTsPacket(uint8_t * TsBuffer, bool PusiSet, uint16_t Pid, uint8_t Counter, const uint8_t * Data, uint32_t Length)
+{
+ TsBuffer[0] = 0x47;
+ TsBuffer[1] = PusiSet ? 0x40 : 0x00;
+ TsBuffer[1] |= Pid >> 8;
+ TsBuffer[2] = Pid & 0xFF;
+ if (Length >= 184)
+ {
+ TsBuffer[3] = 0x10 | Counter;
+ memcpy(TsBuffer + 4, Data, 184);
+ }
+ else
+ {
+ uint8_t adaptationLength;
+
+ TsBuffer[3] = 0x30 | Counter;
+ adaptationLength = 183 - Length;
+ TsBuffer[4] = adaptationLength;
+ if (adaptationLength > 0)
+ {
+ TsBuffer[5] = 0x00;
+ memset(TsBuffer + 6, 0xFF, adaptationLength - 1);
+ }
+ memcpy(TsBuffer + 5 + adaptationLength, Data, Length);
+ }
+}
+
+uint32_t cDvbHdFfDevice::PesToTs(uint8_t * TsBuffer, uint16_t Pid, uint8_t & Counter, const uint8_t * Data, uint32_t Length)
+{
+ uint32_t tsOffset;
+ uint32_t i;
+
+ tsOffset = 0;
+ i = 0;
+ while (Length > 0)
+ {
+ BuildTsPacket(TsBuffer + tsOffset, i == 0, Pid, Counter, Data + i * 184, Length);
+ if (Length >= 184)
+ Length -= 184;
+ else
+ Length = 0;
+ Counter = (Counter + 1) & 15;
+ tsOffset += 188;
+ i++;
+ }
+ return tsOffset;
+}
+
+int cDvbHdFfDevice::PlayVideo(const uchar *Data, int Length)
+{
+ //TODO: support greater Length
+ uint8_t tsBuffer[188 * 16];
+ uint32_t tsLength;
+ int pid = 100;
+
+ tsLength = PesToTs(tsBuffer, pid, videoCounter, Data, Length);
+
+ if (pid != playVideoPid) {
+ playVideoPid = pid;
+ mHdffCmdIf->CmdAvSetVideoPid(0, playVideoPid, HDFF::videoStreamMpeg2, true);
+ }
+ if (WriteAllOrNothing(fd_video, tsBuffer, tsLength, 1000, 10) <= 0)
+ Length = 0;
+ return Length;
+}
+
+int cDvbHdFfDevice::PlayAudio(const uchar *Data, int Length, uchar Id)
+{
+ uint8_t streamId;
+ uint8_t tsBuffer[188 * 16];
+ uint32_t tsLength;
+ HDFF::eAudioStreamType streamType = HDFF::audioStreamMpeg1;
+ HDFF::eAVContainerType containerType = HDFF::avContainerPes;
+ int pid;
+
+ streamId = Data[3];
+ if (streamId >= 0xC0 && streamId <= 0xDF)
+ {
+ streamType = HDFF::audioStreamMpeg1;
+ }
+ else if (streamId == 0xBD)
+ {
+ const uint8_t * payload = Data + 9 + Data[8];
+ if ((payload[0] & 0xF8) == 0xA0)
+ {
+ containerType = HDFF::avContainerPesDvd;
+ streamType = HDFF::audioStreamPcm;
+ }
+ else if ((payload[0] & 0xF8) == 0x88)
+ {
+ containerType = HDFF::avContainerPesDvd;
+ streamType = HDFF::audioStreamDts;
+ }
+ else if ((payload[0] & 0xF8) == 0x80)
+ {
+ containerType = HDFF::avContainerPesDvd;
+ streamType = HDFF::audioStreamAc3;
+ }
+ else
+ {
+ streamType = HDFF::audioStreamAc3;
+ }
+ }
+ pid = 200 + (int) streamType;
+ tsLength = PesToTs(tsBuffer, pid, audioCounter, Data, Length);
+
+ if (pid != playAudioPid) {
+ playAudioPid = pid;
+ mHdffCmdIf->CmdAvSetAudioPid(0, playAudioPid, streamType, containerType);
+ }
+ if (WriteAllOrNothing(fd_video, tsBuffer, tsLength, 1000, 10) <= 0)
+ Length = 0;
+ return Length;
+}
+
+int cDvbHdFfDevice::PlayTsVideo(const uchar *Data, int Length)
+{
+ int pid = TsPid(Data);
+ if (pid != playVideoPid) {
+ PatPmtParser();
+ if (pid == PatPmtParser()->Vpid()) {
+ playVideoPid = pid;
+ mHdffCmdIf->CmdAvSetVideoPid(0, playVideoPid, MapVideoStreamTypes(PatPmtParser()->Vtype()), true);
+ }
+ }
+ return WriteAllOrNothing(fd_video, Data, Length, 1000, 10);
+}
+
+static HDFF::eAudioStreamType MapAudioStreamTypes(int Atype)
+{
+ switch (Atype) {
+ case 0x03: return HDFF::audioStreamMpeg1;
+ case 0x04: return HDFF::audioStreamMpeg2;
+ case SI::AC3DescriptorTag: return HDFF::audioStreamAc3;
+ case SI::EnhancedAC3DescriptorTag: return HDFF::audioStreamEAc3;
+ case 0x0F: return HDFF::audioStreamAac;
+ case 0x11: return HDFF::audioStreamHeAac;
+ default: return HDFF::audioStreamMaxValue; // there is no HDFF::audioStreamNone
+ }
+}
+
+int cDvbHdFfDevice::PlayTsAudio(const uchar *Data, int Length)
+{
+ int pid = TsPid(Data);
+ if (pid != playAudioPid) {
+ playAudioPid = pid;
+ int AudioStreamType = -1;
+ for (int i = 0; PatPmtParser()->Apid(i); i++) {
+ if (playAudioPid == PatPmtParser()->Apid(i)) {
+ AudioStreamType = PatPmtParser()->Atype(i);
+ break;
+ }
+ }
+ if (AudioStreamType < 0) {
+ for (int i = 0; PatPmtParser()->Dpid(i); i++) {
+ if (playAudioPid == PatPmtParser()->Dpid(i)) {
+ AudioStreamType = PatPmtParser()->Dtype(i);
+ break;
+ }
+ }
+ }
+ mHdffCmdIf->CmdAvSetAudioPid(0, playAudioPid, MapAudioStreamTypes(AudioStreamType));
+ }
+ return WriteAllOrNothing(fd_video, Data, Length, 1000, 10);
+}
+
+HDFF::cHdffCmdIf *cDvbHdFfDevice::GetHdffCmdHandler(void)
+{
+ //TODO why not just keep a pointer?
+ if (devHdffOffset >= 0) {
+ cDvbHdFfDevice *device = (cDvbHdFfDevice *)GetDevice(devHdffOffset);
+ if (device)
+ return device->mHdffCmdIf;
+ }
+ return NULL;
+}
+
+// --- cDvbHdFfDeviceProbe ---------------------------------------------------
+
+bool cDvbHdFfDeviceProbe::Probe(int Adapter, int Frontend)
+{
+ static uint32_t SubsystemIds[] = {
+ 0x13C23009, // Technotrend S2-6400 HDFF
+ 0x00000000
+ };
+ cString FileName;
+ cReadLine ReadLine;
+ FILE *f = NULL;
+ uint32_t SubsystemId = 0;
+ FileName = cString::sprintf("/sys/class/dvb/dvb%d.frontend%d/device/subsystem_vendor", Adapter, Frontend);
+ if ((f = fopen(FileName, "r")) != NULL) {
+ if (char *s = ReadLine.Read(f))
+ SubsystemId = strtoul(s, NULL, 0) << 16;
+ fclose(f);
+ }
+ FileName = cString::sprintf("/sys/class/dvb/dvb%d.frontend%d/device/subsystem_device", Adapter, Frontend);
+ if ((f = fopen(FileName, "r")) != NULL) {
+ if (char *s = ReadLine.Read(f))
+ SubsystemId |= strtoul(s, NULL, 0);
+ fclose(f);
+ }
+ for (uint32_t *sid = SubsystemIds; *sid; sid++) {
+ if (*sid == SubsystemId) {
+ FileName = cString::sprintf("/dev/dvb/adapter%d/osd0", Adapter);
+ int fd = open(FileName, O_RDWR);
+ if (fd != -1) { //TODO treat the second path of the S2-6400 as a budget device
+ close(fd);
+ dsyslog("creating cDvbHdFfDevice");
+ new cDvbHdFfDevice(Adapter, Frontend);
+ return true;
+ }
+ }
+ }
+ return false;
+}
diff --git a/PLUGINS/src/dvbhddevice/dvbhdffdevice.h b/PLUGINS/src/dvbhddevice/dvbhdffdevice.h
new file mode 100644
index 0000000..4dcfb6a
--- /dev/null
+++ b/PLUGINS/src/dvbhddevice/dvbhdffdevice.h
@@ -0,0 +1,123 @@
+/*
+ * dvbhdffdevice.h: The DVB HD Full Featured device interface
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id: dvbhdffdevice.h 1.6 2010/03/13 11:18:13 kls Exp $
+ */
+
+#ifndef __DVBHDFFDEVICE_H
+#define __DVBHDFFDEVICE_H
+
+#include "hdffcmd.h"
+#include "vdr/dvbdevice.h"
+#include "vdr/dvbspu.h"
+
+/// The cDvbHdFfDevice implements a DVB device which can be accessed through the Linux DVB driver API.
+
+class cDvbHdFfDevice : public cDvbDevice {
+private:
+ int fd_osd, fd_audio, fd_video;
+protected:
+ virtual void MakePrimaryDevice(bool On);
+public:
+ static bool Probe(int Adapter, int Frontend);
+ cDvbHdFfDevice(int Adapter, int Frontend);
+ virtual ~cDvbHdFfDevice();
+ virtual bool HasDecoder(void) const;
+
+// SPU facilities
+
+private:
+ cDvbSpuDecoder *spuDecoder;
+public:
+ virtual cSpuDecoder *GetSpuDecoder(void);
+
+// Channel facilities
+
+private:
+ void TurnOffLiveMode(bool LiveView);
+protected:
+ virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);
+
+// PID handle facilities
+
+protected:
+ virtual bool SetPid(cPidHandle *Handle, int Type, bool On);
+
+// Image Grab facilities
+
+public:
+ virtual uchar *GrabImage(int &Size, bool Jpeg = true, int Quality = -1, int SizeX = -1, int SizeY = -1);
+
+// Video format facilities
+
+public:
+ virtual void SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat);
+ virtual void SetVideoFormat(bool VideoFormat16_9);
+ virtual eVideoSystem GetVideoSystem(void);
+ virtual void GetVideoSize(int &Width, int &Height, double &VideoAspect);
+ virtual void GetOsdSize(int &Width, int &Height, double &PixelAspect);
+
+// Track facilities
+
+protected:
+ virtual void SetAudioTrackDevice(eTrackType Type);
+
+// Audio facilities
+
+private:
+ int audioChannel;
+protected:
+ virtual int GetAudioChannelDevice(void);
+ virtual void SetAudioChannelDevice(int AudioChannel);
+ virtual void SetVolumeDevice(int Volume);
+ virtual void SetDigitalAudioDevice(bool On);
+
+// Player facilities
+
+private:
+ int playVideoPid;
+ int playAudioPid;
+
+ // Pes2Ts conversion stuff
+ uint8_t videoCounter;
+ uint8_t audioCounter;
+ void BuildTsPacket(uint8_t * TsBuffer, bool PusiSet, uint16_t Pid, uint8_t Counter, const uint8_t * Data, uint32_t Length);
+ uint32_t PesToTs(uint8_t * TsBuffer, uint16_t Pid, uint8_t & Counter, const uint8_t * Data, uint32_t Length);
+
+protected:
+ ePlayMode playMode;
+ virtual bool CanReplay(void) const;
+ virtual bool SetPlayMode(ePlayMode PlayMode);
+ virtual int PlayVideo(const uchar *Data, int Length);
+ virtual int PlayAudio(const uchar *Data, int Length, uchar Id);
+ virtual int PlayTsVideo(const uchar *Data, int Length);
+ virtual int PlayTsAudio(const uchar *Data, int Length);
+public:
+ virtual int64_t GetSTC(void);
+ virtual void TrickSpeed(int Speed);
+ virtual void Clear(void);
+ virtual void Play(void);
+ virtual void Freeze(void);
+ virtual void Mute(void);
+ virtual void StillPicture(const uchar *Data, int Length);
+ virtual bool Poll(cPoller &Poller, int TimeoutMs = 0);
+ virtual bool Flush(int TimeoutMs = 0);
+
+// HDFF specific things
+
+public:
+ static HDFF::cHdffCmdIf *GetHdffCmdHandler(void);
+private:
+ static int devHdffOffset;//TODO
+ bool isHdffPrimary;//TODO implicit!
+ HDFF::cHdffCmdIf *mHdffCmdIf;
+};
+
+class cDvbHdFfDeviceProbe : public cDvbDeviceProbe {
+public:
+ virtual bool Probe(int Adapter, int Frontend);
+ };
+
+#endif //__DVBHDFFDEVICE_H
diff --git a/PLUGINS/src/dvbhddevice/hdffcmd.c b/PLUGINS/src/dvbhddevice/hdffcmd.c
new file mode 100644
index 0000000..ecd26ed
--- /dev/null
+++ b/PLUGINS/src/dvbhddevice/hdffcmd.c
@@ -0,0 +1,1120 @@
+/*
+ * hdffcmd.c: TODO(short description)
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id: hdffcmd.c 1.19 2011/04/17 11:20:22 kls Exp $
+ */
+
+#include "hdffcmd.h"
+#include <linux/dvb/osd.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <vdr/tools.h>
+
+namespace HDFF
+{
+
+cHdffCmdIf::cHdffCmdIf(int OsdDev)
+{
+ mOsdDev = OsdDev;
+ if (mOsdDev < 0)
+ {
+ //printf("ERROR: invalid OSD device handle (%d)!\n", mOsdDev);
+ }
+}
+
+cHdffCmdIf::~cHdffCmdIf(void)
+{
+}
+
+void cHdffCmdIf::CmdBuildHeader(cBitBuffer & MsgBuf, eMessageType MsgType, eMessageGroup MsgGroup, eMessageId MsgId)
+{
+ MsgBuf.SetBits(16, 0); // length field will be set later
+ MsgBuf.SetBits(6, 0); // reserved
+ MsgBuf.SetBits(2, MsgType);
+ MsgBuf.SetBits(8, MsgGroup);
+ MsgBuf.SetBits(16, MsgId);
+}
+
+uint32_t cHdffCmdIf::CmdSetLength(cBitBuffer & MsgBuf)
+{
+ uint32_t length;
+
+ length = MsgBuf.GetByteLength() - 2;
+ MsgBuf.SetDataByte(0, (uint8_t) (length >> 8));
+ MsgBuf.SetDataByte(1, (uint8_t) length);
+
+ return length + 2;
+}
+
+
+uint32_t cHdffCmdIf::CmdGetFirmwareVersion(char * pString, uint32_t MaxLength)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ cBitBuffer resBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ osd_cmd.result_data = resBuf.GetData();
+ osd_cmd.result_len = resBuf.GetMaxLength();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupGeneric, msgGenGetFirmwareVersion);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+ if (osd_cmd.result_len > 0)
+ {
+ uint8_t * result = resBuf.GetData();
+ uint8_t textLength = result[9];
+ if (textLength >= MaxLength)
+ textLength = MaxLength - 1;
+ memcpy(pString, &result[10], textLength);
+ pString[textLength] = 0;
+ return (result[6] << 16) | (result[7] << 8) | result[8];
+ }
+ return 0;
+}
+
+uint32_t cHdffCmdIf::CmdGetInterfaceVersion(char * pString, uint32_t MaxLength)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ cBitBuffer resBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ osd_cmd.result_data = resBuf.GetData();
+ osd_cmd.result_len = resBuf.GetMaxLength();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupGeneric, msgGenGetInterfaceVersion);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+ if (osd_cmd.result_len > 0)
+ {
+ uint8_t * result = resBuf.GetData();
+ uint8_t textLength = result[9];
+ if (textLength >= MaxLength)
+ textLength = MaxLength - 1;
+ memcpy(pString, &result[10], textLength);
+ pString[textLength] = 0;
+ return (result[6] << 16) | (result[7] << 8) | result[8];
+ }
+ return 0;
+}
+
+uint32_t cHdffCmdIf::CmdGetCopyrights(uint8_t Index, char * pString, uint32_t MaxLength)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ cBitBuffer resBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ osd_cmd.result_data = resBuf.GetData();
+ osd_cmd.result_len = resBuf.GetMaxLength();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupGeneric, msgGenGetCopyrights);
+ cmdBuf.SetBits(8, Index);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+ if (osd_cmd.result_len > 0)
+ {
+ uint8_t * result = resBuf.GetData();
+ uint8_t index = result[6];
+ uint8_t textLen = result[7];
+ if (index == Index && textLen > 0)
+ {
+ if (textLen >= MaxLength)
+ {
+ textLen = MaxLength - 1;
+ }
+ memcpy(pString, result + 8, textLen);
+ pString[textLen] = 0;
+ return textLen;
+ }
+ }
+ return 0;
+}
+
+
+void cHdffCmdIf::CmdAvSetPlayMode(uint8_t PlayMode, bool Realtime)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetPlayMode);
+ cmdBuf.SetBits(1, Realtime ? 1 : 0);
+ cmdBuf.SetBits(7, PlayMode);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdAvSetVideoPid(uint8_t DecoderIndex, uint16_t VideoPid, eVideoStreamType StreamType, bool PlaybackMode)
+{
+ //printf("SetVideoPid %d %d\n", VideoPid, StreamType);
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetVideoPid);
+ cmdBuf.SetBits(4, DecoderIndex);
+ cmdBuf.SetBits(4, StreamType);
+ cmdBuf.SetBits(1, PlaybackMode ? 1 : 0);
+ cmdBuf.SetBits(15, VideoPid);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdAvSetAudioPid(uint8_t DecoderIndex, uint16_t AudioPid, eAudioStreamType StreamType, eAVContainerType ContainerType)
+{
+ //printf("SetAudioPid %d %d %d\n", AudioPid, StreamType, ContainerType);
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetAudioPid);
+ cmdBuf.SetBits(4, DecoderIndex);
+ cmdBuf.SetBits(4, StreamType);
+ cmdBuf.SetBits(2, 0); // reserved
+ cmdBuf.SetBits(1, ContainerType);
+ cmdBuf.SetBits(13, AudioPid);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdAvSetPcrPid(uint8_t DecoderIndex, uint16_t PcrPid)
+{
+ //printf("SetPcrPid %d\n", PcrPid);
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetPcrPid);
+ cmdBuf.SetBits(4, DecoderIndex);
+ cmdBuf.SetBits(4, 0); // reserved
+ cmdBuf.SetBits(16, PcrPid);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdAvSetTeletextPid(uint8_t DecoderIndex, uint16_t TeletextPid)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetTeletextPid);
+ cmdBuf.SetBits(4, DecoderIndex);
+ cmdBuf.SetBits(4, 0); // reserved
+ cmdBuf.SetBits(16, TeletextPid);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdAvSetVideoWindow(uint8_t DecoderIndex, bool Enable, uint16_t X, uint16_t Y, uint16_t Width, uint16_t Height)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetVideoWindow);
+ cmdBuf.SetBits(4, DecoderIndex);
+ cmdBuf.SetBits(3, 0); // reserved
+ if (Enable)
+ cmdBuf.SetBits(1, 1);
+ else
+ cmdBuf.SetBits(1, 0);
+ cmdBuf.SetBits(16, X);
+ cmdBuf.SetBits(16, Y);
+ cmdBuf.SetBits(16, Width);
+ cmdBuf.SetBits(16, Height);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdAvShowStillImage(uint8_t DecoderIndex, const uint8_t * pStillImage, int Size, eVideoStreamType StreamType)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+ osd_raw_data_t osd_data;
+
+ memset(&osd_data, 0, sizeof(osd_raw_data_t));
+ osd_data.data_buffer = (void *) pStillImage;
+ osd_data.data_length = Size;
+ ioctl(mOsdDev, OSD_RAW_DATA, &osd_data);
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvShowStillImage);
+ cmdBuf.SetBits(4, DecoderIndex);
+ cmdBuf.SetBits(4, StreamType);
+ cmdBuf.SetBits(16, osd_data.data_handle);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdAvSetDecoderInput(uint8_t DecoderIndex, uint8_t DemultiplexerIndex)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetDecoderInput);
+ cmdBuf.SetBits(4, DecoderIndex);
+ cmdBuf.SetBits(4, DemultiplexerIndex);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdAvSetDemultiplexerInput(uint8_t DemultiplexerIndex, uint8_t TsInputIndex)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetDemultiplexerInput);
+ cmdBuf.SetBits(4, DemultiplexerIndex);
+ cmdBuf.SetBits(4, TsInputIndex);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdAvSetVideoFormat(uint8_t DecoderIndex, const tVideoFormat * pVideoFormat)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetVideoFormat);
+ cmdBuf.SetBits(4, DecoderIndex);
+ if (pVideoFormat->AutomaticEnabled)
+ {
+ cmdBuf.SetBits(1, 1);
+ }
+ else
+ {
+ cmdBuf.SetBits(1, 0);
+ }
+ if (pVideoFormat->AfdEnabled)
+ {
+ cmdBuf.SetBits(1, 1);
+ }
+ else
+ {
+ cmdBuf.SetBits(1, 0);
+ }
+ cmdBuf.SetBits(2, pVideoFormat->TvFormat);
+ cmdBuf.SetBits(8, pVideoFormat->VideoConversion);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdAvSetVideoOutputMode(uint8_t DecoderIndex, eVideoOutputMode OutputMode)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetVideoOutputMode);
+ cmdBuf.SetBits(8, OutputMode);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdAvSetStc(uint8_t DecoderIndex, uint64_t Stc)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetStc);
+ cmdBuf.SetBits(4, DecoderIndex);
+ cmdBuf.SetBits(3, 0); // reserved
+ cmdBuf.SetBits(1, (uint32_t) (Stc >> 32));
+ cmdBuf.SetBits(32, (uint32_t) Stc);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdAvFlushBuffer(uint8_t DecoderIndex, bool FlushAudio, bool FlushVideo)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvFlushBuffer);
+ cmdBuf.SetBits(4, DecoderIndex);
+ if (FlushAudio)
+ {
+ cmdBuf.SetBits(1, 1);
+ }
+ else
+ {
+ cmdBuf.SetBits(1, 0);
+ }
+ if (FlushVideo)
+ {
+ cmdBuf.SetBits(1, 1);
+ }
+ else
+ {
+ cmdBuf.SetBits(1, 0);
+ }
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdAvEnableSync(uint8_t DecoderIndex, bool EnableSync)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvEnableSync);
+ cmdBuf.SetBits(4, DecoderIndex);
+ if (EnableSync)
+ {
+ cmdBuf.SetBits(1, 1);
+ cmdBuf.SetBits(1, 1);
+ }
+ else
+ {
+ cmdBuf.SetBits(1, 0);
+ cmdBuf.SetBits(1, 0);
+ }
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdAvSetVideoSpeed(uint8_t DecoderIndex, int32_t Speed)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetVideoSpeed);
+ cmdBuf.SetBits(4, DecoderIndex);
+ cmdBuf.SetBits(4, 0);
+ cmdBuf.SetBits(32, Speed);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdAvSetAudioSpeed(uint8_t DecoderIndex, int32_t Speed)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetAudioSpeed);
+ cmdBuf.SetBits(4, DecoderIndex);
+ cmdBuf.SetBits(4, 0);
+ cmdBuf.SetBits(32, Speed);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdAvEnableVideoAfterStop(uint8_t DecoderIndex, bool EnableVideoAfterStop)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvEnableVideoAfterStop);
+ cmdBuf.SetBits(4, DecoderIndex);
+ if (EnableVideoAfterStop)
+ {
+ cmdBuf.SetBits(1, 1);
+ }
+ else
+ {
+ cmdBuf.SetBits(1, 0);
+ }
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdAvSetAudioDelay(int16_t Delay)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetAudioDelay);
+ cmdBuf.SetBits(16, Delay);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdAvSetAudioDownmix(eDownmixMode DownmixMode)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetAudioDownmix);
+ cmdBuf.SetBits(8, DownmixMode);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdAvSetAudioChannel(uint8_t AudioChannel)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetAudioChannel);
+ cmdBuf.SetBits(8, AudioChannel);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+
+void cHdffCmdIf::CmdOsdConfigure(const tOsdConfig * pConfig)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdConfigure);
+ if (pConfig->FontAntialiasing)
+ {
+ cmdBuf.SetBits(1, 1);
+ }
+ else
+ {
+ cmdBuf.SetBits(1, 0);
+ }
+ if (pConfig->FontKerning)
+ {
+ cmdBuf.SetBits(1, 1);
+ }
+ else
+ {
+ cmdBuf.SetBits(1, 0);
+ }
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdOsdReset(void)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdReset);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+uint32_t cHdffCmdIf::CmdOsdCreateDisplay(uint32_t Width, uint32_t Height, eColorType ColorType)
+{
+ //printf("CreateDisplay %d %d %d\n", Width, Height, ColorType);
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ cBitBuffer resBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ osd_cmd.result_data = resBuf.GetData();
+ osd_cmd.result_len = resBuf.GetMaxLength();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdCreateDisplay);
+ cmdBuf.SetBits(16, Width);
+ cmdBuf.SetBits(16, Height);
+ cmdBuf.SetBits(8, ColorType);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+ if (osd_cmd.result_len > 0)
+ {
+ uint8_t * result = resBuf.GetData();
+ return (result[6] << 24) | (result[7] << 16) | (result[8] << 8) | result[9];
+ }
+ return InvalidHandle;
+}
+
+void cHdffCmdIf::CmdOsdDeleteDisplay(uint32_t hDisplay)
+{
+ //printf("DeleteDisplay\n");
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdDeleteDisplay);
+ cmdBuf.SetBits(32, hDisplay);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdOsdEnableDisplay(uint32_t hDisplay, bool Enable)
+{
+ //printf("EnableDisplay\n");
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdEnableDisplay);
+ cmdBuf.SetBits(32, hDisplay);
+ if (Enable)
+ {
+ cmdBuf.SetBits(1, 1);
+ }
+ else
+ {
+ cmdBuf.SetBits(1, 0);
+ }
+ cmdBuf.SetBits(7, 0); // reserved
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdOsdSetDisplayOutputRectangle(uint32_t hDisplay, uint32_t X, uint32_t Y, uint32_t Width, uint32_t Height)
+{
+ //printf("SetOutputRect %d %d %d %d %d\n", hDisplay, X, Y, Width, Height);
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdSetDisplayOutputRectangle);
+ cmdBuf.SetBits(32, hDisplay);
+ cmdBuf.SetBits(16, X);
+ cmdBuf.SetBits(16, Y);
+ cmdBuf.SetBits(16, Width);
+ cmdBuf.SetBits(16, Height);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdOsdSetDisplayClippingArea(uint32_t hDisplay, bool Enable, uint32_t X, uint32_t Y, uint32_t Width, uint32_t Height)
+{
+ //printf("SetClippingArea %d %d %d %d %d %d\n", hDisplay, Enable, X, Y, Width, Height);
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdSetDisplayClippingArea);
+ cmdBuf.SetBits(32, hDisplay);
+ if (Enable)
+ {
+ cmdBuf.SetBits(1, 1);
+ }
+ else
+ {
+ cmdBuf.SetBits(1, 0);
+ }
+ cmdBuf.SetBits(7, 0); // reserved
+ cmdBuf.SetBits(16, X);
+ cmdBuf.SetBits(16, Y);
+ cmdBuf.SetBits(16, Width);
+ cmdBuf.SetBits(16, Height);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdOsdRenderDisplay(uint32_t hDisplay)
+{
+ //printf("Render\n");
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdRenderDisplay);
+ cmdBuf.SetBits(32, hDisplay);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+uint32_t cHdffCmdIf::CmdOsdCreatePalette(eColorType ColorType, eColorFormat ColorFormat,
+ uint32_t NumColors, const uint32_t * pColors)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ cBitBuffer resBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+ uint32_t i;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ osd_cmd.result_data = resBuf.GetData();
+ osd_cmd.result_len = resBuf.GetMaxLength();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdCreatePalette);
+ cmdBuf.SetBits(8, ColorType);
+ cmdBuf.SetBits(8, ColorFormat);
+ if (NumColors > 256)
+ NumColors = 256;
+ cmdBuf.SetBits(8, NumColors == 256 ? 0 : NumColors);
+ for (i = 0; i < NumColors; i++)
+ {
+ cmdBuf.SetBits(32, pColors[i]);
+ }
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+ if (osd_cmd.result_len > 0)
+ {
+ uint8_t * result = resBuf.GetData();
+ return (result[6] << 24) | (result[7] << 16) | (result[8] << 8) | result[9];
+ }
+ return InvalidHandle;
+}
+
+void cHdffCmdIf::CmdOsdDeletePalette(uint32_t hPalette)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdDeletePalette);
+ cmdBuf.SetBits(32, hPalette);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdOsdSetDisplayPalette(uint32_t hDisplay, uint32_t hPalette)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdSetDisplayPalette);
+ cmdBuf.SetBits(32, hDisplay);
+ cmdBuf.SetBits(32, hPalette);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdOsdSetPaletteColors(uint32_t hPalette, eColorFormat ColorFormat,
+ uint8_t StartColor, uint32_t NumColors, const uint32_t * pColors)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+ uint32_t i;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdSetPaletteColors);
+ cmdBuf.SetBits(32, hPalette);
+ cmdBuf.SetBits(8, ColorFormat);
+ cmdBuf.SetBits(8, StartColor);
+ if (NumColors > 256)
+ NumColors = 256;
+ cmdBuf.SetBits(8, NumColors == 256 ? 0 : NumColors);
+ for (i = 0; i < NumColors; i++)
+ {
+ cmdBuf.SetBits(32, pColors[i]);
+ }
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+uint32_t cHdffCmdIf::CmdOsdCreateFontFace(const uint8_t * pFontData, uint32_t DataSize)
+{
+ //printf("CreateFontFace %d\n", DataSize);
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ cBitBuffer resBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+ osd_raw_data_t osd_data;
+
+ memset(&osd_data, 0, sizeof(osd_raw_data_t));
+ osd_data.data_buffer = pFontData;
+ osd_data.data_length = DataSize;
+ ioctl(mOsdDev, OSD_RAW_DATA, &osd_data);
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ osd_cmd.result_data = resBuf.GetData();
+ osd_cmd.result_len = resBuf.GetMaxLength();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdCreateFontFace);
+ cmdBuf.SetBits(16, osd_data.data_handle);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+ if (osd_cmd.result_len > 0)
+ {
+ uint8_t * result = resBuf.GetData();
+ return (result[6] << 24) | (result[7] << 16) | (result[8] << 8) | result[9];
+ }
+ return InvalidHandle;
+}
+
+void cHdffCmdIf::CmdOsdDeleteFontFace(uint32_t hFontFace)
+{
+ //printf("DeleteFontFace %08X\n", hFontFace);
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdDeleteFontFace);
+ cmdBuf.SetBits(32, hFontFace);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+uint32_t cHdffCmdIf::CmdOsdCreateFont(uint32_t hFontFace, uint32_t Size)
+{
+ //printf("CreateFont %d\n", Size);
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ cBitBuffer resBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ osd_cmd.result_data = resBuf.GetData();
+ osd_cmd.result_len = resBuf.GetMaxLength();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdCreateFont);
+ cmdBuf.SetBits(32, hFontFace);
+ cmdBuf.SetBits(32, Size);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+ if (osd_cmd.result_len > 0)
+ {
+ uint8_t * result = resBuf.GetData();
+ return (result[6] << 24) | (result[7] << 16) | (result[8] << 8) | result[9];
+ }
+ return InvalidHandle;
+}
+
+void cHdffCmdIf::CmdOsdDeleteFont(uint32_t hFont)
+{
+ //printf("DeleteFont %08X\n", hFont);
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdDeleteFont);
+ cmdBuf.SetBits(32, hFont);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdOsdDrawRectangle(uint32_t hDisplay, int X, int Y, int Width, int Height, uint32_t Color)
+{
+ //printf("Rect (%d,%d) %d x %d, %08X\n", X, Y, Width, Height, Color);
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdDrawRectangle);
+ cmdBuf.SetBits(32, hDisplay);
+ cmdBuf.SetBits(16, X);
+ cmdBuf.SetBits(16, Y);
+ cmdBuf.SetBits(16, Width);
+ cmdBuf.SetBits(16, Height);
+ cmdBuf.SetBits(32, Color);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdOsdDrawEllipse(uint32_t hDisplay, int CX, int CY, int RadiusX, int RadiusY,
+ uint32_t Color, uint32_t Flags)
+{
+ //printf("Ellipse (%d,%d) %d x %d, %08X, %d\n", CX, CY, RadiusX, RadiusY, Color, Flags);
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdDrawEllipse);
+ cmdBuf.SetBits(32, hDisplay);
+ cmdBuf.SetBits(16, CX);
+ cmdBuf.SetBits(16, CY);
+ cmdBuf.SetBits(16, RadiusX);
+ cmdBuf.SetBits(16, RadiusY);
+ cmdBuf.SetBits(32, Color);
+ cmdBuf.SetBits(32, Flags);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdOsdDrawText(uint32_t hDisplay, uint32_t hFont, int X, int Y, const char * pText, uint32_t Color)
+{
+ //printf("Text %08X (%d,%d), %s, %08X\n", hFont, X, Y, pText, Color);
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+ int i;
+ int length;
+
+ length = 0;
+ while (pText[length])
+ {
+ length++;
+ }
+ if (length > 980)
+ length = 980;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdDrawText);
+ cmdBuf.SetBits(32, hDisplay);
+ cmdBuf.SetBits(32, hFont);
+ cmdBuf.SetBits(16, X);
+ cmdBuf.SetBits(16, Y);
+ cmdBuf.SetBits(32, Color);
+ cmdBuf.SetBits(16, length);
+ for (i = 0; i < length; i++)
+ {
+ cmdBuf.SetBits(8, pText[i]);
+ }
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdOsdDrawTextW(uint32_t hDisplay, uint32_t hFont, int X, int Y, const uint16_t * pText, uint32_t Color)
+{
+ //printf("TextW %08X (%d,%d), %08X\n", hFont, X, Y, Color);
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+ int i;
+ int length;
+
+ length = 0;
+ while (pText[length])
+ {
+ length++;
+ }
+ if (length > 480)
+ length = 480;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdDrawTextW);
+ cmdBuf.SetBits(32, hDisplay);
+ cmdBuf.SetBits(32, hFont);
+ cmdBuf.SetBits(16, X);
+ cmdBuf.SetBits(16, Y);
+ cmdBuf.SetBits(32, Color);
+ cmdBuf.SetBits(16, length);
+ for (i = 0; i < length; i++)
+ {
+ cmdBuf.SetBits(16, pText[i]);
+ }
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdOsdDrawBitmap(uint32_t hDisplay, int X, int Y, const uint8_t * pBitmap,
+ int BmpWidth, int BmpHeight, int BmpSize,
+ eColorType ColorType, uint32_t hPalette)
+{
+ //printf("Bitmap (%d,%d) %d x %d\n", X, Y, BmpWidth, BmpHeight);
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+ osd_raw_data_t osd_data;
+
+ memset(&osd_data, 0, sizeof(osd_raw_data_t));
+ osd_data.data_buffer = pBitmap;
+ osd_data.data_length = BmpSize;
+ ioctl(mOsdDev, OSD_RAW_DATA, &osd_data);
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdDrawBitmap);
+ cmdBuf.SetBits(32, hDisplay);
+ cmdBuf.SetBits(16, X);
+ cmdBuf.SetBits(16, Y);
+ cmdBuf.SetBits(16, BmpWidth);
+ cmdBuf.SetBits(16, BmpHeight);
+ cmdBuf.SetBits(8, ColorType);
+ cmdBuf.SetBits(6, 0); // reserved
+ cmdBuf.SetBits(2, 0); // uncompressed
+ cmdBuf.SetBits(32, hPalette);
+ cmdBuf.SetBits(16, osd_data.data_handle);
+ cmdBuf.SetBits(32, 0);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdOsdSaveRegion(uint32_t hDisplay, int X, int Y, int Width, int Height)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdSaveRegion);
+ cmdBuf.SetBits(32, hDisplay);
+ cmdBuf.SetBits(16, X);
+ cmdBuf.SetBits(16, Y);
+ cmdBuf.SetBits(16, Width);
+ cmdBuf.SetBits(16, Height);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdOsdRestoreRegion(uint32_t hDisplay)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdRestoreRegion);
+ cmdBuf.SetBits(32, hDisplay);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdMuxSetVideoOut(eVideoOut VideoOut)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvMux, msgMuxSetVideoOut);
+ cmdBuf.SetBits(4, VideoOut);
+ cmdBuf.SetBits(4, 0); // reserved
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdMuxSetVolume(uint8_t Volume)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvMux, msgMuxSetVolume);
+ cmdBuf.SetBits(8, Volume);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdMuxMuteAudio(bool Mute)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvMux, msgMuxSetAudioMute);
+ cmdBuf.SetBits(1, Mute);
+ cmdBuf.SetBits(7, 0); // reserved
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdHdmiSetVideoMode(eHdmiVideoMode VideoMode)
+{
+ //printf("HdmiSetVideoMode %d\n", VideoMode);
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupHdmi, msgHdmiSetVideoMode);
+ cmdBuf.SetBits(8, VideoMode);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdHdmiConfigure(const tHdmiConfig * pConfig)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupHdmi, msgHdmiConfigure);
+ if (pConfig->TransmitAudio)
+ {
+ cmdBuf.SetBits(1, 1);
+ }
+ else
+ {
+ cmdBuf.SetBits(1, 0);
+ }
+ if (pConfig->ForceDviMode)
+ {
+ cmdBuf.SetBits(1, 1);
+ }
+ else
+ {
+ cmdBuf.SetBits(1, 0);
+ }
+ if (pConfig->CecEnabled)
+ {
+ cmdBuf.SetBits(1, 1);
+ }
+ else
+ {
+ cmdBuf.SetBits(1, 0);
+ }
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdHdmiSendCecCommand(eCecCommand Command)
+{
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupHdmi, msgHdmiSendCecCommand);
+ cmdBuf.SetBits(8, Command);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdRemoteSetProtocol(eRemoteProtocol Protocol)
+{
+ //printf("%s %d\n", __func__, Protocol);
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupRemoteControl, msgRemoteSetProtocol);
+ cmdBuf.SetBits(8, Protocol);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+void cHdffCmdIf::CmdRemoteSetAddressFilter(bool Enable, uint32_t Address)
+{
+ //printf("%s %d %d\n", __func__, Enable, Address);
+ cBitBuffer cmdBuf(MAX_CMD_LEN);
+ osd_raw_cmd_t osd_cmd;
+
+ memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t));
+ osd_cmd.cmd_data = cmdBuf.GetData();
+ CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupRemoteControl, msgRemoteSetAddressFilter);
+ cmdBuf.SetBits(1, Enable);
+ cmdBuf.SetBits(7, 0); // reserved
+ cmdBuf.SetBits(32, Address);
+ osd_cmd.cmd_len = CmdSetLength(cmdBuf);
+ ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd);
+}
+
+} // end of namespace
diff --git a/PLUGINS/src/dvbhddevice/hdffcmd.h b/PLUGINS/src/dvbhddevice/hdffcmd.h
new file mode 100644
index 0000000..cd641eb
--- /dev/null
+++ b/PLUGINS/src/dvbhddevice/hdffcmd.h
@@ -0,0 +1,102 @@
+/*
+ * hdffcmd.h: TODO(short description)
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id: hdffcmd.h 1.17 2011/04/17 11:20:22 kls Exp $
+ */
+
+#ifndef _HDFF_CMD_H_
+#define _HDFF_CMD_H_
+
+#include "bitbuffer.h"
+#include "hdffmsgdef.h"
+
+namespace HDFF
+{
+
+class cHdffCmdIf
+{
+private:
+ int mOsdDev;
+
+ void CmdBuildHeader(cBitBuffer & MsgBuf, eMessageType MsgType, eMessageGroup MsgGroup, eMessageId MsgId);
+ uint32_t CmdSetLength(cBitBuffer & MsgBuf);
+
+public:
+ cHdffCmdIf(int OsdDev);
+ ~cHdffCmdIf(void);
+
+ uint32_t CmdGetFirmwareVersion(char * pString, uint32_t MaxLength);
+ uint32_t CmdGetInterfaceVersion(char * pString, uint32_t MaxLength);
+ uint32_t CmdGetCopyrights(uint8_t Index, char * pString, uint32_t MaxLength);
+
+ void CmdAvSetPlayMode(uint8_t PlayMode, bool Realtime);
+ void CmdAvSetVideoPid(uint8_t DecoderIndex, uint16_t VideoPid, eVideoStreamType StreamType, bool PlaybackMode = false);
+ void CmdAvSetAudioPid(uint8_t DecoderIndex, uint16_t AudioPid, eAudioStreamType StreamType, eAVContainerType ContainerType = avContainerPes);
+ void CmdAvSetPcrPid(uint8_t DecoderIndex, uint16_t PcrPid);
+ void CmdAvSetTeletextPid(uint8_t DecoderIndex, uint16_t TeletextPid);
+ void CmdAvSetVideoWindow(uint8_t DecoderIndex, bool Enable, uint16_t X, uint16_t Y, uint16_t Width, uint16_t Height);
+ void CmdAvShowStillImage(uint8_t DecoderIndex, const uint8_t * pStillImage, int Size, eVideoStreamType StreamType);
+ void CmdAvSetDecoderInput(uint8_t DecoderIndex, uint8_t DemultiplexerIndex);
+ void CmdAvSetDemultiplexerInput(uint8_t DemultiplexerIndex, uint8_t TsInputIndex);
+ void CmdAvSetVideoFormat(uint8_t DecoderIndex, const tVideoFormat * pVideoFormat);
+ void CmdAvSetVideoOutputMode(uint8_t DecoderIndex, eVideoOutputMode OutputMode);
+ void CmdAvSetStc(uint8_t DecoderIndex, uint64_t Stc);
+ void CmdAvFlushBuffer(uint8_t DecoderIndex, bool FlushAudio, bool FlushVideo);
+ void CmdAvEnableSync(uint8_t DecoderIndex, bool EnableSync);
+ void CmdAvSetVideoSpeed(uint8_t DecoderIndex, int32_t Speed);
+ void CmdAvSetAudioSpeed(uint8_t DecoderIndex, int32_t Speed);
+ void CmdAvEnableVideoAfterStop(uint8_t DecoderIndex, bool EnableVideoAfterStop);
+ void CmdAvSetAudioDelay(int16_t Delay);
+ void CmdAvSetAudioDownmix(eDownmixMode DownmixMode);
+ void CmdAvSetAudioChannel(uint8_t AudioChannel);
+
+ void CmdOsdConfigure(const tOsdConfig * pConfig);
+ void CmdOsdReset(void);
+
+ uint32_t CmdOsdCreateDisplay(uint32_t Width, uint32_t Height, eColorType ColorType);
+ void CmdOsdDeleteDisplay(uint32_t hDisplay);
+ void CmdOsdEnableDisplay(uint32_t hDisplay, bool Enable);
+ void CmdOsdSetDisplayOutputRectangle(uint32_t hDisplay, uint32_t X, uint32_t Y, uint32_t Width, uint32_t Height);
+ void CmdOsdSetDisplayClippingArea(uint32_t hDisplay, bool Enable, uint32_t X, uint32_t Y, uint32_t Width, uint32_t Height);
+ void CmdOsdRenderDisplay(uint32_t hDisplay);
+
+ uint32_t CmdOsdCreatePalette(eColorType ColorType, eColorFormat ColorFormat,
+ uint32_t NumColors, const uint32_t * pColors);
+ void CmdOsdDeletePalette(uint32_t hPalette);
+ void CmdOsdSetDisplayPalette(uint32_t hDisplay, uint32_t hPalette);
+ void CmdOsdSetPaletteColors(uint32_t hPalette, eColorFormat ColorFormat,
+ uint8_t StartColor, uint32_t NumColors, const uint32_t * pColors);
+
+ uint32_t CmdOsdCreateFontFace(const uint8_t * pFontData, uint32_t DataSize);
+ void CmdOsdDeleteFontFace(uint32_t hFontFace);
+ uint32_t CmdOsdCreateFont(uint32_t hFontFace, uint32_t Size);
+ void CmdOsdDeleteFont(uint32_t hFont);
+
+ void CmdOsdDrawRectangle(uint32_t hDisplay, int X, int Y, int Width, int Height, uint32_t Color);
+ void CmdOsdDrawEllipse(uint32_t hDisplay, int CX, int CY, int RadiusX, int RadiusY,
+ uint32_t Color, uint32_t Flags);
+ void CmdOsdDrawText(uint32_t hDisplay, uint32_t hFont, int X, int Y, const char * pText, uint32_t Color);
+ void CmdOsdDrawTextW(uint32_t hDisplay, uint32_t hFont, int X, int Y, const uint16_t * pText, uint32_t Color);
+ void CmdOsdDrawBitmap(uint32_t hDisplay, int X, int Y, const uint8_t * pBitmap,
+ int BmpWidth, int BmpHeight, int BmpSize,
+ eColorType ColorType, uint32_t hPalette);
+ void CmdOsdSaveRegion(uint32_t hDisplay, int X, int Y, int Width, int Height);
+ void CmdOsdRestoreRegion(uint32_t hDisplay);
+
+ void CmdMuxSetVideoOut(eVideoOut VideoOut);
+ void CmdMuxSetVolume(uint8_t Volume);
+ void CmdMuxMuteAudio(bool Mute);
+
+ void CmdHdmiSetVideoMode(eHdmiVideoMode VideoMode);
+ void CmdHdmiConfigure(const tHdmiConfig * pConfig);
+ void CmdHdmiSendCecCommand(eCecCommand Command);
+
+ void CmdRemoteSetProtocol(eRemoteProtocol Protocol);
+ void CmdRemoteSetAddressFilter(bool Enable, uint32_t Address);
+};
+
+} // end of namespace
+
+#endif
diff --git a/PLUGINS/src/dvbhddevice/hdffmsgdef.h b/PLUGINS/src/dvbhddevice/hdffmsgdef.h
new file mode 100644
index 0000000..a6c3f4b
--- /dev/null
+++ b/PLUGINS/src/dvbhddevice/hdffmsgdef.h
@@ -0,0 +1,304 @@
+/*
+ * hdffmsgdef.h: TODO(short description)
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id: hdffmsgdef.h 1.12 2011/04/17 11:20:22 kls Exp $
+ */
+
+#ifndef _HDFF_MSGDEF_H_
+#define _HDFF_MSGDEF_H_
+
+#define MAX_CMD_LEN 1536
+
+namespace HDFF
+{
+
+typedef enum _eMessageType
+{
+ msgTypeCommand,
+ msgTypeAnswer,
+ msgTypeResult,
+ msgTypeEvent
+} eMessageType;
+
+typedef enum _eMessageGroup
+{
+ msgGroupGeneric,
+ msgGroupAvDec,
+ msgGroupAvMux,
+ msgGroupFrontend,
+ msgGroupOsd,
+ msgGroupHdmi,
+ msgGroupRemoteControl
+} eMessageGroup;
+
+typedef enum _eMessageId
+{
+ msgGenGetFirmwareVersion = 0,
+ msgGenGetInterfaceVersion,
+ msgGenGetCopyrights,
+
+ msgAvSetAudioPid = 0,
+ msgAvSetVideoPid,
+ msgAvSetPcrPid,
+ msgAvSetTeletextPid,
+ msgAvShowStillImage,
+ msgAvSetVideoWindow,
+ msgAvSetDecoderInput,
+ msgAvSetDemultiplexerInput,
+ msgAvSetVideoFormat,
+ msgAvSetVideoOutputMode,
+ msgAvSetStc,
+ msgAvFlushBuffer,
+ msgAvEnableSync,
+ msgAvSetVideoSpeed,
+ msgAvSetAudioSpeed,
+ msgAvEnableVideoAfterStop,
+ msgAvGetVideoFormatInfo,
+ msgAvSetAudioDelay,
+ msgAvSetAudioDownmix,
+ msgAvSetAudioChannel,
+ msgAvSetPlayMode,
+
+ msgMuxSetVideoOut = 0,
+ msgMuxSetSlowBlank,
+ msgMuxSetFastBlank,
+ msgMuxSetVolume,
+ msgMuxSetAudioMute,
+
+ msgOsdConfigure = 0,
+ msgOsdReset,
+ msgOsdCreateDisplay = 10,
+ msgOsdDeleteDisplay,
+ msgOsdEnableDisplay,
+ msgOsdSetDisplayOutputRectangle,
+ msgOsdSetDisplayClippingArea,
+ msgOsdRenderDisplay,
+ msgOsdSaveRegion,
+ msgOsdRestoreRegion,
+ msgOsdCreatePalette = 30,
+ msgOsdDeletePalette,
+ msgOsdSetDisplayPalette,
+ msgOsdSetPaletteColors,
+ msgOsdCreateFontFace = 50,
+ msgOsdDeleteFontFace,
+ msgOsdCreateFont,
+ msgOsdDeleteFont,
+ msgOsdDrawPixel = 70,
+ msgOsdDrawRectangle,
+ msgOsdDrawCircle,
+ msgOsdDrawEllipse,
+ msgOsdDrawSlope,
+ msgOsdDrawText,
+ msgOsdDrawTextW,
+ msgOsdDrawBitmap,
+
+ msgHdmiEnableOutput = 0,
+ msgHdmiSetVideoMode,
+ msgHdmiConfigure,
+ msgHdmiIsDisplayConnected,
+ msgHdmiGetDisplayInfo,
+ msgHdmiGetVideoMode,
+ msgHdmiSendCecCommand,
+
+ msgRemoteSetProtocol = 0,
+ msgRemoteSetAddressFilter,
+ msgRemoteKeyEvent
+} eMessageId;
+
+
+// AvDec definitions
+
+typedef enum _eAVContainerType
+{
+ avContainerPes,
+ avContainerPesDvd,
+ avContainerMaxValue
+} eAVContainerType;
+
+typedef enum _eAudioStreamType
+{
+ audioStreamMpeg1,
+ audioStreamMpeg2,
+ audioStreamAc3,
+ audioStreamAac,
+ audioStreamHeAac,
+ audioStreamPcm,
+ audioStreamEAc3,
+ audioStreamDts,
+ audioStreamMaxValue
+} eAudioStreamType;
+
+typedef enum _eVideoStreamType
+{
+ videoStreamMpeg1,
+ videoStreamMpeg2,
+ videoStreamH264,
+ videoStreamMpeg4Asp,
+ videoStreamVc1,
+ videoStreamMaxValue
+} eVideoStreamType;
+
+
+typedef enum _eTvFormat
+{
+ tvFormat4by3,
+ tvFormat16by9,
+ tvFormatMaxValue
+} eTvFormat;
+
+typedef enum _eVideoConversion
+{
+ videoConversionAutomatic,
+ videoConversionLetterbox16by9,
+ videoConversionLetterbox14by9,
+ videoConversionPillarbox,
+ videoConversionCentreCutOut,
+ videoConversionAlways16by9,
+ videoConversionMaxValue
+} eVideoConversion;
+
+typedef struct _tVideoFormat
+{
+ bool AutomaticEnabled;
+ bool AfdEnabled;
+ eTvFormat TvFormat;
+ eVideoConversion VideoConversion;
+} tVideoFormat;
+
+typedef enum _eVideoOutputMode
+{
+ videoOutputClone,
+ videoOutputDualView,
+ videoOutputMaxValue
+} eVideoOutputMode;
+
+typedef enum _eDownmixMode
+{
+ downmixOff,
+ downmixAnalog,
+ downmixAlways,
+ downmixAutomatic,
+ downmixHdmi
+} eDownmixMode;
+
+// AvMux definitions
+
+typedef enum _eVideoOut
+{
+ videoOutDisabled,
+ videoOutRgb,
+ videoOutCvbsYuv,
+ videoOutYc,
+ videoOutMaxValue
+} eVideoOut;
+
+typedef enum _eSlowBlank
+{
+ slowBlankOff,
+ slowBlank16by9,
+ slowBlank4by3,
+ slowBlankMaxValue
+} eSlowBlank;
+
+typedef enum _eFastBlank
+{
+ fastBlankCvbs,
+ fastBlankRgb,
+ fastBlankMaxValue
+} eFastBlank;
+
+
+// OSD definitions
+
+#define InvalidHandle 0xFFFFFFFF
+#define ScreenDisplayHandle 0xFFFFFFFE
+
+#define PositionScreenCentered 0xFFFF
+
+#define SizeFullScreen 0xFFFF
+#define SizeSameAsSource 0xFFFE
+
+#define FontFaceTiresias 0x00000000
+
+typedef enum _eColorType
+{
+ colorTypeClut1,
+ colorTypeClut2,
+ colorTypeClut4,
+ colorTypeClut8,
+ colorTypeARGB8888,
+ colorTypeARGB8565,
+ colorTypeARGB4444,
+ colorTypeARGB1555,
+} eColorType;
+
+typedef enum _eColorFormat
+{
+ colorFormatARGB,
+ colorFormatACbYCr,
+} eColorFormat;
+
+typedef enum _eDrawingFlags
+{
+ drawFull,
+ drawHalfTop,
+ drawHalfLeft,
+ drawHalfBottom,
+ drawHalfRight,
+ drawQuarterTopLeft,
+ drawQuarterTopRight,
+ drawQuarterBottomLeft,
+ drawQuarterBottomRight,
+ drawQuarterTopLeftInverted,
+ drawQuarterTopRightInverted,
+ drawQuarterBottomLeftInverted,
+ drawQuarterBottomRightInverted
+} eDrawingFlags;
+
+typedef struct _tOsdConfig
+{
+ bool FontAntialiasing;
+ bool FontKerning;
+} tOsdConfig;
+
+// HDMI definitions
+
+typedef enum _eHdmiVideoMode
+{
+ videoMode576p50 = 18,
+ videoMode720p50 = 19,
+ videoMode1080i50 = 20,
+ videoMode576i50 = 22,
+ videoModeMaxValue
+} eHdmiVideoMode;
+
+typedef enum _eCecCommand
+{
+ cecCommandTvOn,
+ cecCommandTvOff,
+ cecCommandActiveSource,
+ cecCommandInactiveSource
+} eCecCommand;
+
+typedef struct _tHdmiConfig
+{
+ bool TransmitAudio;
+ bool ForceDviMode;
+ bool CecEnabled;
+} tHdmiConfig;
+
+// Remote control definitions
+
+typedef enum _eRemoteProtocol
+{
+ remoteProtocolNone,
+ remoteProtocolRc5,
+ remoteProtocolRc6,
+ remoteProtocolMaxValue
+} eRemoteProtocol;
+
+} // end of namespace
+
+#endif
diff --git a/PLUGINS/src/dvbhddevice/hdffosd.c b/PLUGINS/src/dvbhddevice/hdffosd.c
new file mode 100644
index 0000000..254f2af
--- /dev/null
+++ b/PLUGINS/src/dvbhddevice/hdffosd.c
@@ -0,0 +1,755 @@
+/*
+ * hdffosd.c: Implementation of the DVB HD Full Featured On Screen Display
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id: hdffosd.c 1.9 2011/04/17 11:20:22 kls Exp $
+ */
+
+#include "hdffosd.h"
+#include <linux/dvb/osd.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include "hdffcmd.h"
+#include "setup.h"
+
+#define MAX_NUM_FONTFACES 8
+#define MAX_NUM_FONTS 8
+#define MAX_BITMAP_SIZE (1024*1024)
+
+typedef struct _tFontFace
+{
+ cString Name;
+ uint32_t Handle;
+} tFontFace;
+
+typedef struct _tFont
+{
+ uint32_t hFontFace;
+ int Size;
+ uint32_t Handle;
+} tFont;
+
+class cHdffOsd : public cOsd
+{
+private:
+ HDFF::cHdffCmdIf * mHdffCmdIf;
+ int mLeft;
+ int mTop;
+ int mDispWidth;
+ int mDispHeight;
+ bool shown;
+ bool mChanged;
+ bool mBitmapModified;
+ uint32_t mDisplay;
+ tFontFace mFontFaces[MAX_NUM_FONTFACES];
+ tFont mFonts[MAX_NUM_FONTS];
+ uint32_t mBitmapPalette;
+ uint32_t mBitmapColors[256];
+ uint32_t mBitmapNumColors;
+
+protected:
+ virtual void SetActive(bool On);
+public:
+ cHdffOsd(int Left, int Top, HDFF::cHdffCmdIf * pHdffCmdIf, uint Level);
+ virtual ~cHdffOsd();
+ cBitmap *GetBitmap(int Area);
+ virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas);
+ virtual eOsdError SetAreas(const tArea *Areas, int NumAreas);
+ virtual void SaveRegion(int x1, int y1, int x2, int y2);
+ virtual void RestoreRegion(void);
+ virtual void DrawPixel(int x, int y, tColor Color);
+ virtual void DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg = 0, tColor ColorBg = 0, bool ReplacePalette = false, bool Overlay = false);
+ virtual void DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width = 0, int Height = 0, int Alignment = taDefault);
+ virtual void DrawRectangle(int x1, int y1, int x2, int y2, tColor Color);
+ virtual void DrawEllipse(int x1, int y1, int x2, int y2, tColor Color, int Quadrants = 0);
+ virtual void DrawSlope(int x1, int y1, int x2, int y2, tColor Color, int Type);
+ virtual void Flush(void);
+};
+
+cHdffOsd::cHdffOsd(int Left, int Top, HDFF::cHdffCmdIf * pHdffCmdIf, uint Level)
+: cOsd(Left, Top, Level)
+{
+ double pixelAspect;
+ HDFF::tOsdConfig config;
+
+ //printf("cHdffOsd %d, %d, %d\n", Left, Top, Level);
+ mHdffCmdIf = pHdffCmdIf;
+ mLeft = Left;
+ mTop = Top;
+ shown = false;
+ mChanged = false;
+ mBitmapModified = false;
+ mBitmapPalette = InvalidHandle;
+ config.FontKerning = false;
+ config.FontAntialiasing = Setup.AntiAlias ? true : false;
+ mHdffCmdIf->CmdOsdConfigure(&config);
+
+ gHdffSetup.GetOsdSize(mDispWidth, mDispHeight, pixelAspect);
+ mDisplay = mHdffCmdIf->CmdOsdCreateDisplay(mDispWidth, mDispHeight, HDFF::colorTypeARGB8888);
+ mHdffCmdIf->CmdOsdSetDisplayOutputRectangle(mDisplay, 0, 0, SizeFullScreen, SizeFullScreen);
+ for (int i = 0; i < MAX_NUM_FONTFACES; i++)
+ {
+ mFontFaces[i].Name = "";
+ mFontFaces[i].Handle = InvalidHandle;
+ }
+ for (int i = 0; i < MAX_NUM_FONTS; i++)
+ {
+ mFonts[i].hFontFace = InvalidHandle;
+ mFonts[i].Size = 0;
+ mFonts[i].Handle = InvalidHandle;
+ }
+}
+
+cHdffOsd::~cHdffOsd()
+{
+ //printf("~cHdffOsd %d %d\n", mLeft, mTop);
+ SetActive(false);
+
+ for (int i = 0; i < MAX_NUM_FONTS; i++)
+ {
+ if (mFonts[i].Handle == InvalidHandle)
+ break;
+ mHdffCmdIf->CmdOsdDeleteFont(mFonts[i].Handle);
+ }
+ for (int i = 0; i < MAX_NUM_FONTFACES; i++)
+ {
+ if (mFontFaces[i].Handle == InvalidHandle)
+ break;
+ mHdffCmdIf->CmdOsdDeleteFontFace(mFontFaces[i].Handle);
+ }
+
+ if (mBitmapPalette != InvalidHandle)
+ mHdffCmdIf->CmdOsdDeletePalette(mBitmapPalette);
+ mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, 0, 0, mDispWidth, mDispHeight, 0);
+ mHdffCmdIf->CmdOsdRenderDisplay(mDisplay);
+ mHdffCmdIf->CmdOsdDeleteDisplay(mDisplay);
+}
+
+cBitmap * cHdffOsd::GetBitmap(int Area)
+{
+ //printf("GetBitmap %d\n", Area);
+ mChanged = true;
+ mBitmapModified = true;
+ return cOsd::GetBitmap(Area);
+}
+
+eOsdError cHdffOsd::CanHandleAreas(const tArea *Areas, int NumAreas)
+{
+ eOsdError Result = cOsd::CanHandleAreas(Areas, NumAreas);
+ if (Result == oeOk)
+ {
+ 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;
+ }
+ }
+ return Result;
+}
+
+eOsdError cHdffOsd::SetAreas(const tArea *Areas, int NumAreas)
+{
+ for (int i = 0; i < NumAreas; i++)
+ {
+ //printf("SetAreas %d: %d %d %d %d %d\n", i, Areas[i].x1, Areas[i].y1, Areas[i].x2, Areas[i].y2, Areas[i].bpp);
+ }
+ mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, 0, 0, mDispWidth, mDispHeight, 0);
+ mHdffCmdIf->CmdOsdRenderDisplay(mDisplay);
+ return cOsd::SetAreas(Areas, NumAreas);
+}
+
+void cHdffOsd::SetActive(bool On)
+{
+ if (On != Active())
+ {
+ cOsd::SetActive(On);
+ if (On)
+ {
+ }
+ else if (shown)
+ {
+ shown = false;
+ }
+ }
+}
+
+void cHdffOsd::SaveRegion(int x1, int y1, int x2, int y2)
+{
+ mHdffCmdIf->CmdOsdSaveRegion(mDisplay, mLeft + x1, mTop + y1, x2 - x1 + 1, y2 - y1 + 1);
+ mChanged = true;
+ mBitmapModified = false;
+}
+
+void cHdffOsd::RestoreRegion(void)
+{
+ mHdffCmdIf->CmdOsdRestoreRegion(mDisplay);
+ mChanged = true;
+ mBitmapModified = false;
+}
+
+void cHdffOsd::DrawPixel(int x, int y, tColor Color)
+{
+ //printf("DrawPixel\n");
+ mBitmapModified = false;
+}
+
+void cHdffOsd::DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg, tColor ColorBg, bool ReplacePalette, bool Overlay)
+{
+ //printf("DrawBitmap %d %d %d\n", x, y, Overlay);
+ int i;
+ int numColors;
+ const tColor * colors = Bitmap.Colors(numColors);
+
+ for (i = 0; i < numColors; i++)
+ {
+ mBitmapColors[i] = colors[i];
+ if (ColorFg || ColorBg)
+ {
+ if (i == 0)
+ mBitmapColors[i] = ColorBg;
+ else if (i == 1)
+ mBitmapColors[i] = ColorFg;
+ }
+ }
+ if (mBitmapPalette == InvalidHandle)
+ {
+ mBitmapPalette = mHdffCmdIf->CmdOsdCreatePalette(HDFF::colorTypeClut8,
+ HDFF::colorFormatARGB, numColors, mBitmapColors);
+ }
+ else
+ {
+ mHdffCmdIf->CmdOsdSetPaletteColors(mBitmapPalette,
+ HDFF::colorFormatARGB, 0, numColors, mBitmapColors);
+ }
+ mHdffCmdIf->CmdOsdDrawBitmap(mDisplay, mLeft + x, mTop + y,
+ (uint8_t *) Bitmap.Data(0, 0), Bitmap.Width(), Bitmap.Height(),
+ Bitmap.Width() * Bitmap.Height(), HDFF::colorTypeClut8, mBitmapPalette);
+#if 0
+ uint32_t * tmpBitmap = new uint32_t[Bitmap.Width() * Bitmap.Height()];
+ for (int ix = 0; ix < Bitmap.Width(); ix++)
+ {
+ for (int iy = 0; iy < Bitmap.Height(); iy++)
+ {
+ const tIndex * pixel = Bitmap.Data(ix, iy);
+ tColor color = Bitmap.Color(*pixel);
+ if (!Overlay || *pixel != 0)
+ {
+ if (ColorFg || ColorBg)
+ {
+ if (*pixel == 0)
+ color = ColorBg;
+ else if (*pixel == 1)
+ color = ColorFg;
+ }
+ tmpBitmap[Bitmap.Width() * iy + ix] = color;
+ }
+ }
+ }
+ mHdffCmdIf->CmdOsdDrawBitmap(mDisplay, mLeft + x, mTop + y,
+ (uint8_t *) tmpBitmap, Bitmap.Width(), Bitmap.Height(),
+ Bitmap.Width() * Bitmap.Height() * 4, HDFF::colorTypeARGB8888, InvalidHandle);
+ delete[] tmpBitmap;
+#endif
+ mChanged = true;
+ mBitmapModified = false;
+}
+
+void cHdffOsd::DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width, int Height, int Alignment)
+{
+ int w = Font->Width(s);
+ int h = Font->Height();
+ int limit = 0;
+ int cw = Width ? Width : w;
+ int ch = Height ? Height : h;
+ int i;
+ int size = Font->Size();
+ tFontFace * pFontFace;
+ tFont * pFont;
+
+ if (ColorBg != clrTransparent)
+ mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, mLeft + x, mTop + y, cw, ch, ColorBg);
+
+ if (s == NULL)
+ return;
+
+ pFontFace = NULL;
+ for (i = 0; i < MAX_NUM_FONTFACES; i++)
+ {
+ if (mFontFaces[i].Handle == InvalidHandle)
+ break;
+
+ if (strcmp(mFontFaces[i].Name, Font->FontName()) == 0)
+ {
+ pFontFace = &mFontFaces[i];
+ break;
+ }
+ }
+ if (pFontFace == NULL)
+ {
+ if (i < MAX_NUM_FONTFACES)
+ {
+ cString fontFileName = Font->FontName();
+ FILE * fp = fopen(fontFileName, "rb");
+ if (fp)
+ {
+ fseek(fp, 0, SEEK_END);
+ long fileSize = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+ if (fileSize > 0)
+ {
+ uint8_t * buffer = new uint8_t[fileSize];
+ if (buffer)
+ {
+ if (fread(buffer, fileSize, 1, fp) == 1)
+ {
+ mFontFaces[i].Handle = mHdffCmdIf->CmdOsdCreateFontFace(buffer, fileSize);
+ if (mFontFaces[i].Handle != InvalidHandle)
+ {
+ mFontFaces[i].Name = Font->FontName();
+ pFontFace = &mFontFaces[i];
+ }
+ }
+ delete[] buffer;
+ }
+ }
+ fclose(fp);
+ }
+ }
+ }
+ if (pFontFace == NULL)
+ return;
+
+ pFont = NULL;
+ for (i = 0; i < MAX_NUM_FONTS; i++)
+ {
+ if (mFonts[i].Handle == InvalidHandle)
+ break;
+
+ if (mFonts[i].hFontFace == pFontFace->Handle
+ && mFonts[i].Size == size)
+ {
+ pFont = &mFonts[i];
+ break;
+ }
+ }
+ if (pFont == NULL)
+ {
+ if (i < MAX_NUM_FONTS)
+ {
+ mFonts[i].Handle = mHdffCmdIf->CmdOsdCreateFont(pFontFace->Handle, size);
+ if (mFonts[i].Handle != InvalidHandle)
+ {
+ mFonts[i].hFontFace = pFontFace->Handle;
+ mFonts[i].Size = size;
+ pFont = &mFonts[i];
+ }
+ }
+ }
+ if (pFont == NULL)
+ return;
+
+ mHdffCmdIf->CmdOsdSetDisplayClippingArea(mDisplay, true, mLeft + x, mTop + y, cw, ch);
+
+ if (Width || Height)
+ {
+ limit = x + cw;// - mLeft;
+ if (Width)
+ {
+ if ((Alignment & taLeft) != 0)
+ ;
+ else if ((Alignment & taRight) != 0)
+ {
+ if (w < Width)
+ x += Width - w;
+ }
+ else
+ { // taCentered
+ if (w < Width)
+ x += (Width - w) / 2;
+ }
+ }
+ if (Height)
+ {
+ if ((Alignment & taTop) != 0)
+ ;
+ else if ((Alignment & taBottom) != 0)
+ {
+ if (h < Height)
+ y += Height - h;
+ }
+ else
+ { // taCentered
+ if (h < Height)
+ y += (Height - h) / 2;
+ }
+ }
+ }
+ //x -= mLeft;
+ //y -= mTop;
+ {
+ uint16_t tmp[1000];
+ uint16_t len = 0;
+ while (*s && (len < (sizeof(tmp) - 1)))
+ {
+ int sl = Utf8CharLen(s);
+ uint sym = Utf8CharGet(s, sl);
+ s += sl;
+ tmp[len] = sym;
+ len++;
+ }
+ tmp[len] = 0;
+ mHdffCmdIf->CmdOsdDrawTextW(mDisplay, pFont->Handle, x + mLeft, y + mTop + h, tmp, ColorFg);
+ }
+ //mHdffCmdIf->CmdOsdDrawText(mDisplay, pFont->Handle, x + mLeft, y + mTop + h - 7, s, ColorFg);
+ mHdffCmdIf->CmdOsdSetDisplayClippingArea(mDisplay, false, 0, 0, 0, 0);
+ //Font->DrawText(this, x, y, s, ColorFg, ColorBg, limit);
+ mChanged = true;
+ mBitmapModified = false;
+}
+
+void cHdffOsd::DrawRectangle(int x1, int y1, int x2, int y2, tColor Color)
+{
+ mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, mLeft + x1, mTop + y1, x2 - x1 + 1, y2 - y1 + 1, Color);
+ mChanged = true;
+ mBitmapModified = false;
+}
+
+void cHdffOsd::DrawEllipse(int x1, int y1, int x2, int y2, tColor Color, int Quadrants)
+{
+ uint32_t flags;
+ int cx;
+ int cy;
+ int rx;
+ int ry;
+
+ switch (abs(Quadrants))
+ {
+ case 1:
+ if (Quadrants > 0)
+ flags = HDFF::drawQuarterTopRight;
+ else
+ flags = HDFF::drawQuarterTopRightInverted;
+ cx = x1;
+ cy = y2;
+ rx = x2 - x1;
+ ry = y2 - y1;
+ break;
+ case 2:
+ if (Quadrants > 0)
+ flags = HDFF::drawQuarterTopLeft;
+ else
+ flags = HDFF::drawQuarterTopLeftInverted;
+ cx = x2;
+ cy = y2;
+ rx = x2 - x1;
+ ry = y2 - y1;
+ break;
+ case 3:
+ if (Quadrants > 0)
+ flags = HDFF::drawQuarterBottomLeft;
+ else
+ flags = HDFF::drawQuarterBottomLeftInverted;
+ cx = x2;
+ cy = y1;
+ rx = x2 - x1;
+ ry = y2 - y1;
+ break;
+ case 4:
+ if (Quadrants > 0)
+ flags = HDFF::drawQuarterBottomRight;
+ else
+ flags = HDFF::drawQuarterBottomRightInverted;
+ cx = x1;
+ cy = y1;
+ rx = x2 - x1;
+ ry = y2 - y1;
+ break;
+ case 5:
+ flags = HDFF::drawHalfRight;
+ cx = x1;
+ cy = (y1 + y2) / 2;
+ rx = x2 - x1;
+ ry = (y2 - y1) / 2;
+ break;
+ case 6:
+ flags = HDFF::drawHalfTop;
+ cx = (x1 + x2) / 2;
+ cy = y2;
+ rx = (x2 - x1) / 2;
+ ry = y2 - y1;
+ break;
+ case 7:
+ flags = HDFF::drawHalfLeft;
+ cx = x2;
+ cy = (y1 + y2) / 2;
+ rx = x2 - x1;
+ ry = (y2 - y1) / 2;
+ break;
+ case 8:
+ flags = HDFF::drawHalfBottom;
+ cx = (x1 + x2) / 2;
+ cy = y1;
+ rx = (x2 - x1) / 2;
+ ry = y2 - y1;
+ break;
+ default:
+ flags = HDFF::drawFull;
+ cx = (x1 + x2) / 2;
+ cy = (y1 + y2) / 2;
+ rx = (x2 - x1) / 2;
+ ry = (y2 - y1) / 2;
+ break;
+ }
+ mHdffCmdIf->CmdOsdDrawEllipse(mDisplay, mLeft + cx, mTop + cy, rx, ry, Color, flags);
+ mChanged = true;
+ mBitmapModified = false;
+}
+
+void cHdffOsd::DrawSlope(int x1, int y1, int x2, int y2, tColor Color, int Type)
+{
+ //printf("DrawSlope\n");
+ mChanged = true;
+ mBitmapModified = false;
+}
+
+void cHdffOsd::Flush(void)
+{
+ if (!Active())
+ return;
+
+ if (!mChanged)
+ return;
+
+ //printf("Flush\n");
+ if (mBitmapModified)
+ {
+ cBitmap *Bitmap;
+ for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++)
+ {
+ DrawBitmap(0, 0, *Bitmap);
+ }
+ }
+
+ mHdffCmdIf->CmdOsdRenderDisplay(mDisplay);
+
+ mChanged = false;
+ mBitmapModified = false;
+}
+
+
+class cHdffOsdRaw : public cOsd
+{
+private:
+ HDFF::cHdffCmdIf * mHdffCmdIf;
+ int mDispWidth;
+ int mDispHeight;
+ bool shown;
+ uint32_t mDisplay;
+ uint32_t mBitmapPalette;
+ uint32_t mBitmapColors[256];
+ uint32_t mBitmapNumColors;
+
+protected:
+ virtual void SetActive(bool On);
+public:
+ cHdffOsdRaw(int Left, int Top, HDFF::cHdffCmdIf * pHdffCmdIf, uint Level);
+ virtual ~cHdffOsdRaw();
+ virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas);
+ virtual eOsdError SetAreas(const tArea *Areas, int NumAreas);
+ virtual void Flush(void);
+};
+
+cHdffOsdRaw::cHdffOsdRaw(int Left, int Top, HDFF::cHdffCmdIf * pHdffCmdIf, uint Level)
+: cOsd(Left, Top, Level)
+{
+ double pixelAspect;
+
+ //printf("cHdffOsdRaw %d, %d, %d\n", Left, Top, Level);
+ mHdffCmdIf = pHdffCmdIf;
+ shown = false;
+ mBitmapPalette = InvalidHandle;
+
+ gHdffSetup.GetOsdSize(mDispWidth, mDispHeight, pixelAspect);
+ mDisplay = mHdffCmdIf->CmdOsdCreateDisplay(mDispWidth, mDispHeight, HDFF::colorTypeARGB8888);
+ mHdffCmdIf->CmdOsdSetDisplayOutputRectangle(mDisplay, 0, 0, SizeFullScreen, SizeFullScreen);
+}
+
+cHdffOsdRaw::~cHdffOsdRaw()
+{
+ //printf("~cHdffOsdRaw %d %d\n", Left(), Top());
+ SetActive(false);
+
+ if (mBitmapPalette != InvalidHandle)
+ mHdffCmdIf->CmdOsdDeletePalette(mBitmapPalette);
+ mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, 0, 0, mDispWidth, mDispHeight, 0);
+ mHdffCmdIf->CmdOsdRenderDisplay(mDisplay);
+ mHdffCmdIf->CmdOsdDeleteDisplay(mDisplay);
+}
+
+void cHdffOsdRaw::SetActive(bool On)
+{
+ if (On != Active())
+ {
+ cOsd::SetActive(On);
+ if (On)
+ {
+ }
+ else if (shown)
+ {
+ shown = false;
+ }
+ }
+}
+
+eOsdError cHdffOsdRaw::CanHandleAreas(const tArea *Areas, int NumAreas)
+{
+ eOsdError Result = cOsd::CanHandleAreas(Areas, NumAreas);
+ if (Result == oeOk)
+ {
+ for (int i = 0; i < NumAreas; i++)
+ {
+ if (Areas[i].bpp != 1 && Areas[i].bpp != 2 && Areas[i].bpp != 4 && Areas[i].bpp != 8
+ && (Areas[i].bpp != 32 || !gHdffSetup.TrueColorOsd))
+ return oeBppNotSupported;
+ }
+ }
+ return Result;
+}
+
+eOsdError cHdffOsdRaw::SetAreas(const tArea *Areas, int NumAreas)
+{
+ for (int i = 0; i < NumAreas; i++)
+ {
+ //printf("SetAreas %d: %d %d %d %d %d\n", i, Areas[i].x1, Areas[i].y1, Areas[i].x2, Areas[i].y2, Areas[i].bpp);
+ }
+ mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, 0, 0, mDispWidth, mDispHeight, 0);
+ mHdffCmdIf->CmdOsdRenderDisplay(mDisplay);
+ return cOsd::SetAreas(Areas, NumAreas);
+}
+
+void cHdffOsdRaw::Flush(void)
+{
+ if (!Active())
+ return;
+ //struct timeval start;
+ //struct timeval end;
+ //struct timezone timeZone;
+ //gettimeofday(&start, &timeZone);
+
+ bool render = false;
+ if (IsTrueColor())
+ {
+ LOCK_PIXMAPS;
+ while (cPixmapMemory *pm = RenderPixmaps())
+ {
+ int w = pm->ViewPort().Width();
+ int h = pm->ViewPort().Height();
+ int d = w * sizeof(tColor);
+ int Chunk = MAX_BITMAP_SIZE / w / sizeof(tColor);
+ if (Chunk > h)
+ Chunk = h;
+ for (int y = 0; y < h; y += Chunk)
+ {
+ int hc = Chunk;
+ if (y + hc > h)
+ hc = h - y;
+ mHdffCmdIf->CmdOsdDrawBitmap(mDisplay,
+ Left() + pm->ViewPort().X(), Top() + pm->ViewPort().Y() + y,
+ pm->Data() + y * d, w, hc, hc * d,
+ HDFF::colorTypeARGB8888, InvalidHandle);
+ }
+ delete pm;
+ render = true;
+ }
+ }
+ else
+ {
+ uint8_t * buffer = new uint8_t[MAX_BITMAP_SIZE];
+ if (!buffer)
+ return;
+ cBitmap * bitmap;
+ for (int i = 0; (bitmap = GetBitmap(i)) != NULL; i++)
+ {
+ int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+ if (!shown || bitmap->Dirty(x1, y1, x2, y2))
+ {
+ if (!shown)
+ {
+ x2 = bitmap->Width() - 1;
+ y2 = bitmap->Height() - 1;
+ }
+ // commit colors:
+ int numColors;
+ const tColor * colors = bitmap->Colors(numColors);
+ if (colors)
+ {
+ for (int c = 0; c < numColors; c++)
+ mBitmapColors[c] = colors[c];
+ if (mBitmapPalette == InvalidHandle)
+ {
+ mBitmapPalette = mHdffCmdIf->CmdOsdCreatePalette(HDFF::colorTypeClut8,
+ HDFF::colorFormatARGB, numColors, mBitmapColors);
+ }
+ else
+ {
+ mHdffCmdIf->CmdOsdSetPaletteColors(mBitmapPalette,
+ HDFF::colorFormatARGB, 0, numColors, mBitmapColors);
+ }
+ }
+ // commit modified data:
+ int width = x2 - x1 + 1;
+ int height = y2 - y1 + 1;
+ int chunk = MAX_BITMAP_SIZE / width;
+ if (chunk > height)
+ chunk = height;
+ for (int y = 0; y < height; y += chunk)
+ {
+ int hc = chunk;
+ if (y + hc > height)
+ hc = height - y;
+ for (int r = 0; r < hc; r++)
+ memcpy(buffer + r * width, bitmap->Data(x1, y1 + y + r), width);
+ mHdffCmdIf->CmdOsdDrawBitmap(mDisplay,
+ Left() + bitmap->X0() + x1, Top() + bitmap->Y0() + y1 + y,
+ buffer, width, hc, hc * width,
+ HDFF::colorTypeClut8, mBitmapPalette);
+ }
+ render = true;
+ }
+ bitmap->Clean();
+ }
+ delete[] buffer;
+ }
+ if (render)
+ {
+ mHdffCmdIf->CmdOsdRenderDisplay(mDisplay);
+ //gettimeofday(&end, &timeZone);
+ //int timeNeeded = end.tv_usec - start.tv_usec;
+ //timeNeeded += (end.tv_sec - start.tv_sec) * 1000000;
+ //printf("time = %d\n", timeNeeded);
+ }
+ shown = true;
+}
+
+
+
+
+cHdffOsdProvider::cHdffOsdProvider(HDFF::cHdffCmdIf * HdffCmdIf)
+{
+ mHdffCmdIf = HdffCmdIf;
+}
+
+cOsd *cHdffOsdProvider::CreateOsd(int Left, int Top, uint Level)
+{
+ //printf("CreateOsd %d %d %d\n", Left, Top, Level);
+ if (gHdffSetup.HighLevelOsd)
+ return new cHdffOsd(Left, Top, mHdffCmdIf, Level);
+ else
+ return new cHdffOsdRaw(Left, Top, mHdffCmdIf, Level);
+}
+
+bool cHdffOsdProvider::ProvidesTrueColor(void)
+{
+ return gHdffSetup.TrueColorOsd && !gHdffSetup.HighLevelOsd;
+}
diff --git a/PLUGINS/src/dvbhddevice/hdffosd.h b/PLUGINS/src/dvbhddevice/hdffosd.h
new file mode 100644
index 0000000..533897e
--- /dev/null
+++ b/PLUGINS/src/dvbhddevice/hdffosd.h
@@ -0,0 +1,26 @@
+/*
+ * hdffosd.h: Implementation of the DVB HD Full Featured On Screen Display
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id: hdffosd.h 1.2 2011/01/30 15:27:48 kls Exp $
+ */
+
+#ifndef _HDFF_OSD_H_
+#define _HDFF_OSD_H_
+
+#include <vdr/osd.h>
+
+#include "hdffcmd.h"
+
+class cHdffOsdProvider : public cOsdProvider
+{
+private:
+ HDFF::cHdffCmdIf * mHdffCmdIf;
+public:
+ cHdffOsdProvider(HDFF::cHdffCmdIf * pHdffCmdIf);
+ virtual cOsd *CreateOsd(int Left, int Top, uint Level);
+ virtual bool ProvidesTrueColor(void);
+};
+
+#endif
diff --git a/PLUGINS/src/dvbhddevice/setup.c b/PLUGINS/src/dvbhddevice/setup.c
new file mode 100644
index 0000000..3cb69b1
--- /dev/null
+++ b/PLUGINS/src/dvbhddevice/setup.c
@@ -0,0 +1,252 @@
+/*
+ * setup.c: Setup for the DVB HD Full Featured On Screen Display
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id: setup.c 1.11 2011/04/17 11:45:17 kls Exp $
+ */
+
+#include "setup.h"
+#include "hdffcmd.h"
+
+const int kResolutions = 4;
+const int kTvFormats = 2;
+const int kVideoConversions = 6;
+const int kAnalogueVideos = 4;
+const int kAudioDownmixes = 5;
+const int kOsdSizes = 5;
+const int kRemoteProtocols = 3;
+
+const int kResolution1080i = 0;
+const int kResolution720p = 1;
+const int kResolution576p = 2;
+const int kResolution576i = 3;
+
+static const char * ResolutionItems[] =
+{
+ "1080i",
+ "720p",
+ "576p",
+ "576i",
+ NULL
+};
+
+static const char * TvFormatItems[] =
+{
+ "4/3",
+ "16/9",
+ NULL
+};
+
+static const char * VideoConversionItems[] =
+{
+ "Automatic",
+ "Letterbox 16/9",
+ "Letterbox 14/9",
+ "Pillarbox",
+ "CentreCutOut",
+ "Always 16/9",
+ NULL
+};
+
+static const char * AnalogueVideoItems[] =
+{
+ "Disabled",
+ "RGB",
+ "CVBS + YUV",
+ "YC (S-Video)",
+ NULL
+};
+
+static const char * AudioDownmixItems[] =
+{
+ "Disabled",
+ "Analogue only",
+ "Always",
+ "Automatic",
+ "HDMI only",
+ NULL
+};
+
+static const char * OsdSizeItems[] =
+{
+ "Follow resolution",
+ "1920x1080",
+ "1280x720",
+ "1024x576",
+ "720x576",
+ NULL
+};
+
+static const char * RemoteProtocolItems[] =
+{
+ "none",
+ "RC5",
+ "RC6",
+ NULL
+};
+
+cHdffSetup gHdffSetup;
+
+cHdffSetup::cHdffSetup(void)
+{
+ Resolution = kResolution1080i;
+ TvFormat = HDFF::tvFormat16by9;
+ VideoConversion = HDFF::videoConversionPillarbox;
+ AnalogueVideo = HDFF::videoOutCvbsYuv;
+ AudioDelay = 0;
+ AudioDownmix = HDFF::downmixAutomatic;
+ OsdSize = 0;
+ CecEnabled = 1;
+ RemoteProtocol = 1;
+ RemoteAddress = -1;
+ HighLevelOsd = 1;
+ TrueColorOsd = 1;
+}
+
+bool cHdffSetup::SetupParse(const char *Name, const char *Value)
+{
+ if (strcmp(Name, "Resolution") == 0) Resolution = atoi(Value);
+ else if (strcmp(Name, "TvFormat") == 0) TvFormat = atoi(Value);
+ else if (strcmp(Name, "VideoConversion") == 0) VideoConversion = atoi(Value);
+ else if (strcmp(Name, "AnalogueVideo") == 0) AnalogueVideo = atoi(Value);
+ else if (strcmp(Name, "AudioDelay") == 0) AudioDelay = atoi(Value);
+ else if (strcmp(Name, "AudioDownmix") == 0) AudioDownmix = atoi(Value);
+ else if (strcmp(Name, "OsdSize") == 0) OsdSize = atoi(Value);
+ else if (strcmp(Name, "CecEnabled") == 0) CecEnabled = atoi(Value);
+ else if (strcmp(Name, "RemoteProtocol") == 0) RemoteProtocol = atoi(Value);
+ else if (strcmp(Name, "RemoteAddress") == 0) RemoteAddress = atoi(Value);
+ else if (strcmp(Name, "HighLevelOsd") == 0) HighLevelOsd = atoi(Value);
+ else if (strcmp(Name, "TrueColorOsd") == 0) TrueColorOsd = atoi(Value);
+ else return false;
+ return true;
+}
+
+void cHdffSetup::GetOsdSize(int &Width, int &Height, double &PixelAspect)
+{
+ if (OsdSize == 0) {
+ if (Resolution == kResolution1080i) {
+ Width = 1920;
+ Height = 1080;
+ }
+ else if (Resolution == kResolution720p) {
+ Width = 1280;
+ Height = 720;
+ }
+ else {
+ Width = 720;
+ Height = 576;
+ }
+ if (TvFormat == HDFF::tvFormat16by9)
+ PixelAspect = 16.0 / 9.0;
+ else
+ PixelAspect = 4.0 / 3.0;
+ }
+ else if (OsdSize == 1) {
+ Width = 1920;
+ Height = 1080;
+ PixelAspect = 16.0 / 9.0;
+ }
+ else if (OsdSize == 2) {
+ Width = 1280;
+ Height = 720;
+ PixelAspect = 16.0 / 9.0;
+ }
+ else if (OsdSize == 3) {
+ Width = 1024;
+ Height = 576;
+ PixelAspect = 16.0 / 9.0;
+ }
+ else {
+ Width = 720;
+ Height = 576;
+ PixelAspect = 4.0 / 3.0;
+ }
+ PixelAspect /= double(Width) / Height;
+}
+
+HDFF::eHdmiVideoMode cHdffSetup::GetVideoMode(void)
+{
+ switch (Resolution)
+ {
+ case kResolution1080i:
+ default:
+ return HDFF::videoMode1080i50;
+ case kResolution720p:
+ return HDFF::videoMode720p50;
+ case kResolution576p:
+ return HDFF::videoMode576p50;
+ case kResolution576i:
+ return HDFF::videoMode576i50;
+ }
+}
+
+cHdffSetupPage::cHdffSetupPage(HDFF::cHdffCmdIf * pHdffCmdIf)
+{
+ mHdffCmdIf = pHdffCmdIf;
+ mNewHdffSetup = gHdffSetup;
+
+ Add(new cMenuEditStraItem("Resolution", &mNewHdffSetup.Resolution, kResolutions, ResolutionItems));
+ Add(new cMenuEditStraItem("TV format", &mNewHdffSetup.TvFormat, kTvFormats, TvFormatItems));
+ Add(new cMenuEditStraItem("Video Conversion", &mNewHdffSetup.VideoConversion, kVideoConversions, VideoConversionItems));
+ Add(new cMenuEditStraItem("Analogue Video", &mNewHdffSetup.AnalogueVideo, kAnalogueVideos, AnalogueVideoItems));
+ Add(new cMenuEditIntItem("Audio Delay (ms)", &mNewHdffSetup.AudioDelay, 0, 500));
+ Add(new cMenuEditStraItem("Audio Downmix", &mNewHdffSetup.AudioDownmix, kAudioDownmixes, AudioDownmixItems));
+ Add(new cMenuEditStraItem("Osd Size", &mNewHdffSetup.OsdSize, kOsdSizes, OsdSizeItems));
+ Add(new cMenuEditBoolItem("HDMI CEC", &mNewHdffSetup.CecEnabled));
+ Add(new cMenuEditStraItem("Remote Control Protocol", &mNewHdffSetup.RemoteProtocol, kRemoteProtocols, RemoteProtocolItems));
+ Add(new cMenuEditIntItem("Remote Control Address", &mNewHdffSetup.RemoteAddress, -1, 31));
+ Add(new cMenuEditBoolItem("High Level OSD", &mNewHdffSetup.HighLevelOsd));
+ Add(new cMenuEditBoolItem("Allow True Color OSD", &mNewHdffSetup.TrueColorOsd));
+}
+
+cHdffSetupPage::~cHdffSetupPage(void)
+{
+}
+
+void cHdffSetupPage::Store(void)
+{
+ SetupStore("Resolution", mNewHdffSetup.Resolution);
+ SetupStore("TvFormat", mNewHdffSetup.TvFormat);
+ SetupStore("VideoConversion", mNewHdffSetup.VideoConversion);
+ SetupStore("AnalogueVideo", mNewHdffSetup.AnalogueVideo);
+ SetupStore("AudioDelay", mNewHdffSetup.AudioDelay);
+ SetupStore("AudioDownmix", mNewHdffSetup.AudioDownmix);
+ SetupStore("OsdSize", mNewHdffSetup.OsdSize);
+ SetupStore("CecEnabled", mNewHdffSetup.CecEnabled);
+ SetupStore("RemoteProtocol", mNewHdffSetup.RemoteProtocol);
+ SetupStore("RemoteAddress", mNewHdffSetup.RemoteAddress);
+ SetupStore("HighLevelOsd", mNewHdffSetup.HighLevelOsd);
+ SetupStore("TrueColorOsd", mNewHdffSetup.TrueColorOsd);
+
+ if (mHdffCmdIf)
+ {
+ if (mNewHdffSetup.Resolution != gHdffSetup.Resolution)
+ {
+ mHdffCmdIf->CmdHdmiSetVideoMode(mNewHdffSetup.GetVideoMode());
+ }
+ HDFF::tVideoFormat videoFormat;
+ HDFF::tHdmiConfig hdmiConfig;
+
+ videoFormat.AutomaticEnabled = true;
+ videoFormat.AfdEnabled = true;
+ videoFormat.TvFormat = (HDFF::eTvFormat) mNewHdffSetup.TvFormat;
+ videoFormat.VideoConversion = (HDFF::eVideoConversion) mNewHdffSetup.VideoConversion;
+ mHdffCmdIf->CmdAvSetVideoFormat(0, &videoFormat);
+
+ mHdffCmdIf->CmdAvSetAudioDelay(mNewHdffSetup.AudioDelay);
+ mHdffCmdIf->CmdAvSetAudioDownmix((HDFF::eDownmixMode) mNewHdffSetup.AudioDownmix);
+
+ mHdffCmdIf->CmdMuxSetVideoOut((HDFF::eVideoOut) mNewHdffSetup.AnalogueVideo);
+
+ hdmiConfig.TransmitAudio = true;
+ hdmiConfig.ForceDviMode = false;
+ hdmiConfig.CecEnabled = mNewHdffSetup.CecEnabled;
+ mHdffCmdIf->CmdHdmiConfigure(&hdmiConfig);
+
+ mHdffCmdIf->CmdRemoteSetProtocol((HDFF::eRemoteProtocol) mNewHdffSetup.RemoteProtocol);
+ mHdffCmdIf->CmdRemoteSetAddressFilter(mNewHdffSetup.RemoteAddress >= 0, mNewHdffSetup.RemoteAddress);
+ }
+
+ gHdffSetup = mNewHdffSetup;
+}
diff --git a/PLUGINS/src/dvbhddevice/setup.h b/PLUGINS/src/dvbhddevice/setup.h
new file mode 100644
index 0000000..07c9d1a
--- /dev/null
+++ b/PLUGINS/src/dvbhddevice/setup.h
@@ -0,0 +1,53 @@
+/*
+ * setup.h: Setup for the DVB HD Full Featured On Screen Display
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id: setup.h 1.8 2011/04/17 11:20:22 kls Exp $
+ */
+
+#ifndef _HDFF_SETUP_H_
+#define _HDFF_SETUP_H_
+
+#include <vdr/plugin.h>
+#include "hdffcmd.h"
+
+struct cHdffSetup
+{
+ cHdffSetup(void);
+ bool SetupParse(const char * Name, const char * Value);
+ void GetOsdSize(int &Width, int &Height, double &PixelAspect);
+ HDFF::eHdmiVideoMode GetVideoMode(void);
+
+ int Resolution;
+ int TvFormat;
+ int VideoConversion;
+ int AnalogueVideo;
+ int AudioDelay;
+ int AudioDownmix;
+ int OsdSize;
+ int CecEnabled;
+ int RemoteProtocol;
+ int RemoteAddress;
+
+ int HighLevelOsd;
+ int TrueColorOsd;
+};
+
+extern cHdffSetup gHdffSetup;
+
+class cHdffSetupPage : public cMenuSetupPage
+{
+private:
+ HDFF::cHdffCmdIf * mHdffCmdIf;
+ cHdffSetup mNewHdffSetup;
+
+protected:
+ virtual void Store(void);
+
+public:
+ cHdffSetupPage(HDFF::cHdffCmdIf * pHdffCmdIf);
+ virtual ~cHdffSetupPage(void);
+};
+
+#endif
diff --git a/PLUGINS/src/dvbsddevice/HISTORY b/PLUGINS/src/dvbsddevice/HISTORY
index 0d1047b..9672f6f 100644
--- a/PLUGINS/src/dvbsddevice/HISTORY
+++ b/PLUGINS/src/dvbsddevice/HISTORY
@@ -15,3 +15,7 @@ VDR Plugin 'dvbsddevice' Revision History
- The PCR pid is now recorded for channels where this is different from the
video PID.
+
+2011-04-17: Version 0.0.4
+
+- Removed an obsolete local variable in dvbsdffosd.c (thanks to Paul Menzel).
diff --git a/PLUGINS/src/dvbsddevice/dvbsddevice.c b/PLUGINS/src/dvbsddevice/dvbsddevice.c
index cc48b28..6f042d8 100644
--- a/PLUGINS/src/dvbsddevice/dvbsddevice.c
+++ b/PLUGINS/src/dvbsddevice/dvbsddevice.c
@@ -3,13 +3,13 @@
*
* See the README file for copyright information and how to reach the author.
*
- * $Id: dvbsddevice.c 1.3 2010/01/30 10:05:42 kls Exp $
+ * $Id: dvbsddevice.c 1.4 2011/04/17 12:55:43 kls Exp $
*/
#include <vdr/plugin.h>
#include "dvbsdffdevice.h"
-static const char *VERSION = "0.0.3";
+static const char *VERSION = "0.0.4";
static const char *DESCRIPTION = "SD Full Featured DVB device";
class cPluginDvbsddevice : public cPlugin {
diff --git a/PLUGINS/src/dvbsddevice/dvbsdffosd.c b/PLUGINS/src/dvbsddevice/dvbsdffosd.c
index 4b60ef5..46c65e0 100644
--- a/PLUGINS/src/dvbsddevice/dvbsdffosd.c
+++ b/PLUGINS/src/dvbsddevice/dvbsdffosd.c
@@ -3,7 +3,7 @@
*
* See the README file for copyright information and how to reach the author.
*
- * $Id: dvbsdffosd.c 2.2 2010/09/19 12:43:45 kls Exp $
+ * $Id: dvbsdffosd.c 2.3 2011/04/17 12:55:09 kls Exp $
*/
#include "dvbsdffosd.h"
@@ -73,8 +73,7 @@ void cDvbSdFfOsd::SetActive(bool On)
Flush();
}
else if (shown) {
- cBitmap *Bitmap;
- for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) {
+ for (int i = 0; GetBitmap(i); i++) {
Cmd(OSD_SetWindow, 0, i + 1);
Cmd(OSD_Close);
}
@@ -108,8 +107,7 @@ eOsdError cDvbSdFfOsd::CanHandleAreas(const tArea *Areas, int NumAreas)
eOsdError cDvbSdFfOsd::SetAreas(const tArea *Areas, int NumAreas)
{
if (shown) {
- cBitmap *Bitmap;
- for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) {
+ for (int i = 0; GetBitmap(i); i++) {
Cmd(OSD_SetWindow, 0, i + 1);
Cmd(OSD_Close);
}
diff --git a/PLUGINS/src/osddemo/HISTORY b/PLUGINS/src/osddemo/HISTORY
index 1270fbf..ac386b0 100644
--- a/PLUGINS/src/osddemo/HISTORY
+++ b/PLUGINS/src/osddemo/HISTORY
@@ -25,3 +25,12 @@ VDR Plugin 'osddemo' Revision History
2011-02-20: Version 0.2.0
- Added support for TrueColor OSD.
+
+2011-03-28: Version 0.2.1
+
+- Added Cancel(3) to ~cTrueColorDemo() (thanks to Reinhard Nissl).
+- Added a missing font deletion in cTrueColorDemo::Action() (thanks to Reinhard Nissl).
+
+2011-04-17: Version 0.2.2
+
+- Fixed a possible NULL pointer dereference in osddemo.c (reported by Paul Menzel).
diff --git a/PLUGINS/src/osddemo/osddemo.c b/PLUGINS/src/osddemo/osddemo.c
index 2e6a33b..9ad9df7 100644
--- a/PLUGINS/src/osddemo/osddemo.c
+++ b/PLUGINS/src/osddemo/osddemo.c
@@ -3,13 +3,13 @@
*
* See the README file for copyright information and how to reach the author.
*
- * $Id: osddemo.c 2.3 2011/02/26 12:08:13 kls Exp $
+ * $Id: osddemo.c 2.5 2011/04/17 13:05:13 kls Exp $
*/
#include <vdr/osd.h>
#include <vdr/plugin.h>
-static const char *VERSION = "0.2.0";
+static const char *VERSION = "0.2.2";
static const char *DESCRIPTION = "Demo of arbitrary OSD setup";
static const char *MAINMENUENTRY = "Osd Demo";
@@ -103,6 +103,7 @@ cTrueColorDemo::cTrueColorDemo(void)
cTrueColorDemo::~cTrueColorDemo()
{
+ Cancel(3);
delete osd;
}
@@ -262,12 +263,13 @@ void cTrueColorDemo::Action(void)
case 3: {
if (cFont *Font = cFont::CreateFont(DefaultFontOsd, osd->Height() / 10)) {
NextPixmap = CreateTextPixmap("Millions of colors", Line, 1, clrYellow, clrTransparent, Font);
+ delete Font;
if (NextPixmap) {
FadeInPixmap = NextPixmap;
+ Start = cTimeMs::Now();
+ StartLine = Line;
+ Line += NextPixmap->DrawPort().Height();
}
- Start = cTimeMs::Now();
- StartLine = Line;
- Line += NextPixmap->DrawPort().Height();
}
State++;
}
diff --git a/config.h b/config.h
index c9aeb5e..e4ac2f2 100644
--- a/config.h
+++ b/config.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: config.h 2.29 2010/10/24 11:22:35 kls Exp $
+ * $Id: config.h 2.30 2011/03/13 12:02:31 kls Exp $
*/
#ifndef __CONFIG_H
@@ -22,13 +22,13 @@
// VDR's own version number:
-#define VDRVERSION "1.7.17"
-#define VDRVERSNUM 10717 // Version * 10000 + Major * 100 + Minor
+#define VDRVERSION "1.7.18"
+#define VDRVERSNUM 10718 // Version * 10000 + Major * 100 + Minor
// The plugin API's version number:
-#define APIVERSION "1.7.17"
-#define APIVERSNUM 10717 // Version * 10000 + Major * 100 + Minor
+#define APIVERSION "1.7.18"
+#define APIVERSNUM 10718 // Version * 10000 + Major * 100 + Minor
// When loading plugins, VDR searches them by their APIVERSION, which
// may be smaller than VDRVERSION in case there have been no changes to
diff --git a/device.h b/device.h
index 1598af2..a383dac 100644
--- a/device.h
+++ b/device.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: device.h 2.23 2010/10/24 12:11:16 kls Exp $
+ * $Id: device.h 2.24 2011/03/21 17:58:41 kls Exp $
*/
#ifndef __DEVICE_H
@@ -405,10 +405,9 @@ public:
///< (default is PAL).
virtual void GetVideoSize(int &Width, int &Height, double &VideoAspect);
///< Returns the With, Height and VideoAspect ratio of the currently
- ///< displayed video material. The data returned by this function is
- ///< only used for informational purposes (if any). Width and
- ///< Height are given in pixel (e.g. 720x576) and VideoAspect is
- ///< e.g. 1.33333 for a 4:3 broadcast, or 1.77778 for 16:9.
+ ///< displayed video material. Width and Height are given in pixel
+ ///< (e.g. 720x576) and VideoAspect is e.g. 1.33333 for a 4:3 broadcast,
+ ///< or 1.77778 for 16:9.
///< The default implementation returns 0 for Width and Height
///< and 1.0 for VideoAspect.
virtual void GetOsdSize(int &Width, int &Height, double &PixelAspect);
diff --git a/dvbspu.h b/dvbspu.h
index 9e33e45..863e446 100644
--- a/dvbspu.h
+++ b/dvbspu.h
@@ -8,7 +8,7 @@
*
* parts of this file are derived from the OMS program.
*
- * $Id: dvbspu.h 2.4 2009/12/13 12:07:00 kls Exp $
+ * $Id: dvbspu.h 2.5 2011/03/27 14:50:48 kls Exp $
*/
#ifndef __DVBSPU_H
@@ -32,6 +32,9 @@ typedef struct sDvbSpuRect {
int x1, y1;
int x2, y2;
+ sDvbSpuRect(void) {
+ x1 = y1 = x2 = y2 = 0;
+ };
int width() const {
return x2 - x1 + 1;
};
diff --git a/dvbsubtitle.c b/dvbsubtitle.c
index c1a0a0c..de1cd1c 100644
--- a/dvbsubtitle.c
+++ b/dvbsubtitle.c
@@ -7,10 +7,13 @@
* Original author: Marco Schlüßler <marco@lordzodiac.de>
* With some input from the "subtitle plugin" by Pekka Virtanen <pekka.virtanen@sci.fi>
*
- * $Id: dvbsubtitle.c 2.11 2011/03/12 15:13:03 kls Exp $
+ * $Id: dvbsubtitle.c 2.17 2011/04/17 14:34:05 kls Exp $
*/
+
#include "dvbsubtitle.h"
+#define __STDC_FORMAT_MACROS // Required for format specifiers
+#include <inttypes.h>
#include "device.h"
#define PAGE_COMPOSITION_SEGMENT 0x10
@@ -420,7 +423,7 @@ public:
int PageId(void) { return pageId; }
int Version(void) { return version; }
int State(void) { return state; }
- tArea *GetAreas(double Factor);
+ tArea *GetAreas(double FactorX, double FactorY);
cSubtitleClut *GetClutById(int ClutId, bool New = false);
cSubtitleObject *GetObjectById(int ObjectId);
cSubtitleRegion *GetRegionById(int RegionId, bool New = false);
@@ -446,16 +449,16 @@ cDvbSubtitlePage::~cDvbSubtitlePage()
{
}
-tArea *cDvbSubtitlePage::GetAreas(double Factor)
+tArea *cDvbSubtitlePage::GetAreas(double FactorX, double FactorY)
{
if (regions.Count() > 0) {
tArea *Areas = new tArea[regions.Count()];
tArea *a = Areas;
for (cSubtitleRegion *sr = regions.First(); sr; sr = regions.Next(sr)) {
- a->x1 = int(round(Factor * sr->HorizontalAddress()));
- a->y1 = int(round(Factor * sr->VerticalAddress()));
- a->x2 = int(round(Factor * (sr->HorizontalAddress() + sr->Width() - 1)));
- a->y2 = int(round(Factor * (sr->VerticalAddress() + sr->Height() - 1)));
+ a->x1 = int(round(FactorX * sr->HorizontalAddress()));
+ a->y1 = int(round(FactorY * sr->VerticalAddress()));
+ a->x2 = int(round(FactorX * (sr->HorizontalAddress() + sr->Width() - 1)));
+ a->y2 = int(round(FactorY * (sr->VerticalAddress() + sr->Height() - 1)));
a->bpp = sr->Bpp();
while ((a->Width() & 3) != 0)
a->x2++; // aligns width to a multiple of 4, so 2, 4 and 8 bpp will work
@@ -616,10 +619,11 @@ private:
int timeout;
tArea *areas;
int numAreas;
- double osdFactor;
+ double osdFactorX;
+ double osdFactorY;
cVector<cBitmap *> bitmaps;
public:
- cDvbSubtitleBitmaps(int64_t Pts, int Timeout, tArea *Areas, int NumAreas, double OsdFactor);
+ cDvbSubtitleBitmaps(int64_t Pts, int Timeout, tArea *Areas, int NumAreas, double OsdFactorX, double OsdFactorY);
~cDvbSubtitleBitmaps();
int64_t Pts(void) { return pts; }
int Timeout(void) { return timeout; }
@@ -627,13 +631,14 @@ public:
void Draw(cOsd *Osd);
};
-cDvbSubtitleBitmaps::cDvbSubtitleBitmaps(int64_t Pts, int Timeout, tArea *Areas, int NumAreas, double OsdFactor)
+cDvbSubtitleBitmaps::cDvbSubtitleBitmaps(int64_t Pts, int Timeout, tArea *Areas, int NumAreas, double OsdFactorX, double OsdFactorY)
{
pts = Pts;
timeout = Timeout;
areas = Areas;
numAreas = NumAreas;
- osdFactor = OsdFactor;
+ osdFactorX = OsdFactorX;
+ osdFactorY = OsdFactorY;
}
cDvbSubtitleBitmaps::~cDvbSubtitleBitmaps()
@@ -650,12 +655,27 @@ void cDvbSubtitleBitmaps::AddBitmap(cBitmap *Bitmap)
void cDvbSubtitleBitmaps::Draw(cOsd *Osd)
{
+ bool Scale = !(DoubleEqual(osdFactorX, 1.0) && DoubleEqual(osdFactorY, 1.0));
+ bool AntiAlias = true;
+ if (Scale && osdFactorX > 1.0 || osdFactorY > 1.0) {
+ // Upscaling requires 8bpp:
+ int Bpp[MAXOSDAREAS];
+ for (int i = 0; i < numAreas; i++) {
+ Bpp[i] = areas[i].bpp;
+ areas[i].bpp = 8;
+ }
+ if (Osd->CanHandleAreas(areas, numAreas) != oeOk) {
+ for (int i = 0; i < numAreas; i++)
+ Bpp[i] = areas[i].bpp = Bpp[i];
+ AntiAlias = false;
+ }
+ }
if (Osd->SetAreas(areas, numAreas) == oeOk) {
for (int i = 0; i < bitmaps.Size(); i++) {
cBitmap *b = bitmaps[i];
- if (osdFactor != 1.0)
- b = b->Scale(osdFactor, osdFactor);
- Osd->DrawBitmap(int(round(b->X0() * osdFactor)), int(round(b->Y0() * osdFactor)), *b);
+ if (Scale)
+ b = b->Scaled(osdFactorX, osdFactorY, AntiAlias);
+ Osd->DrawBitmap(int(round(b->X0() * osdFactorX)), int(round(b->Y0() * osdFactorY)), *b);
if (b != bitmaps[i])
delete b;
}
@@ -733,7 +753,7 @@ int cDvbSubtitleConverter::ConvertFragments(const uchar *Data, int Length)
if (Length > PayloadOffset + SubstreamHeaderLength) {
int64_t pts = PesHasPts(Data) ? PesGetPts(Data) : 0;
if (pts)
- dbgconverter("Converter PTS: %lld\n", pts);
+ dbgconverter("Converter PTS: %"PRId64"\n", pts);
const uchar *data = Data + PayloadOffset + SubstreamHeaderLength; // skip substream header
int length = Length - PayloadOffset - SubstreamHeaderLength; // skip substream header
if (ResetSubtitleAssembler)
@@ -769,7 +789,7 @@ int cDvbSubtitleConverter::Convert(const uchar *Data, int Length)
if (Length > PayloadOffset) {
int64_t pts = PesGetPts(Data);
if (pts)
- dbgconverter("Converter PTS: %lld\n", pts);
+ dbgconverter("Converter PTS: %"PRId64"\n", pts);
const uchar *data = Data + PayloadOffset;
int length = Length - PayloadOffset;
if (length > 3) {
@@ -828,7 +848,7 @@ void cDvbSubtitleConverter::Action(void)
if (AssertOsd()) {
sb->Draw(osd);
Timeout.Set(sb->Timeout() * 1000);
- dbgconverter("PTS: %lld STC: %lld (%lld) timeout: %d\n", sb->Pts(), cDevice::PrimaryDevice()->GetSTC(), Delta, sb->Timeout());
+ dbgconverter("PTS: %"PRId64" STC: %"PRId64" (%"PRId64") timeout: %d\n", sb->Pts(), cDevice::PrimaryDevice()->GetSTC(), Delta, sb->Timeout());
}
bitmaps->Del(sb);
}
@@ -862,27 +882,27 @@ tColor cDvbSubtitleConverter::yuv2rgb(int Y, int Cb, int Cr)
void cDvbSubtitleConverter::SetOsdData(void)
{
- int OsdWidth;
- int OsdHeight;
+ int OsdWidth, OsdHeight;
double OsdAspect;
+ int VideoWidth, VideoHeight;
+ double VideoAspect;
cDevice::PrimaryDevice()->GetOsdSize(OsdWidth, OsdHeight, OsdAspect);
- osdDeltaX = osdDeltaY = 0;
- osdFactor = 1.0;
- double fw = double(OsdWidth) / displayWidth;
- double fh = double(OsdHeight) / displayHeight;
- if (fw >= fh) {
- osdFactor = fh;
- osdDeltaX = (OsdWidth - displayWidth * osdFactor) / 2;
+ cDevice::PrimaryDevice()->GetVideoSize(VideoWidth, VideoHeight, VideoAspect);
+ if (OsdWidth == displayWidth && OsdHeight == displayHeight) {
+ osdFactorX = osdFactorY = 1.0;
+ osdDeltaX = osdDeltaY = 0;
}
else {
- osdFactor = fw;
- osdDeltaY = (OsdHeight - displayHeight * osdFactor) / 2;
+ osdFactorX = VideoAspect * OsdHeight / displayWidth;
+ osdFactorY = double(OsdHeight) / displayHeight;
+ osdDeltaX = (OsdWidth - displayWidth * osdFactorX) / 2;
+ osdDeltaY = (OsdHeight - displayHeight * osdFactorY) / 2;
}
}
bool cDvbSubtitleConverter::AssertOsd(void)
{
- return osd || (osd = cOsdProvider::NewOsd(int(round(osdFactor * windowHorizontalOffset + osdDeltaX)), int(round(osdFactor * windowVerticalOffset + osdDeltaY)) + Setup.SubtitleOffset, OSD_LEVEL_SUBTITLES));
+ return osd || (osd = cOsdProvider::NewOsd(int(round(osdFactorX * windowHorizontalOffset + osdDeltaX)), int(round(osdFactorY * windowVerticalOffset + osdDeltaY)) + Setup.SubtitleOffset, OSD_LEVEL_SUBTITLES));
}
int cDvbSubtitleConverter::ExtractSegment(const uchar *Data, int Length, int64_t Pts)
@@ -918,7 +938,7 @@ int cDvbSubtitleConverter::ExtractSegment(const uchar *Data, int Length, int64_t
page->SetTimeout(Data[6]);
page->SetState((Data[6 + 1] & 0x0C) >> 2);
page->regions.Clear();
- dbgpages("Update page id %d version %d pts %lld timeout %d state %d\n", pageId, page->Version(), page->Pts(), page->Timeout(), page->State());
+ dbgpages("Update page id %d version %d pts %"PRId64" timeout %d state %d\n", pageId, page->Version(), page->Pts(), page->Timeout(), page->State());
for (int i = 6 + 2; i < segmentLength; i += 6) {
cSubtitleRegion *region = page->GetRegionById(Data[i], true);
region->SetHorizontalAddress((Data[i + 2] << 8) + Data[i + 3]);
@@ -1079,7 +1099,7 @@ void cDvbSubtitleConverter::FinishPage(cDvbSubtitlePage *Page)
{
if (!AssertOsd())
return;
- tArea *Areas = Page->GetAreas(osdFactor);
+ tArea *Areas = Page->GetAreas(osdFactorX, osdFactorY);
int NumAreas = Page->regions.Count();
int Bpp = 8;
bool Reduced = false;
@@ -1116,7 +1136,7 @@ void cDvbSubtitleConverter::FinishPage(cDvbSubtitlePage *Page)
}
}
}
- cDvbSubtitleBitmaps *Bitmaps = new cDvbSubtitleBitmaps(Page->Pts(), Page->Timeout(), Areas, NumAreas, osdFactor);
+ cDvbSubtitleBitmaps *Bitmaps = new cDvbSubtitleBitmaps(Page->Pts(), Page->Timeout(), Areas, NumAreas, osdFactorX, osdFactorY);
bitmaps->Add(Bitmaps);
for (cSubtitleRegion *sr = Page->regions.First(); sr; sr = Page->regions.Next(sr)) {
int posX = sr->HorizontalAddress();
diff --git a/dvbsubtitle.h b/dvbsubtitle.h
index 6e71765..a9f453e 100644
--- a/dvbsubtitle.h
+++ b/dvbsubtitle.h
@@ -6,7 +6,7 @@
*
* Original author: Marco Schlüßler <marco@lordzodiac.de>
*
- * $Id: dvbsubtitle.h 2.5 2011/03/12 14:03:42 kls Exp $
+ * $Id: dvbsubtitle.h 2.6 2011/03/20 13:34:23 kls Exp $
*/
#ifndef __DVBSUBTITLE_H
@@ -35,7 +35,8 @@ private:
int windowHeight;
int osdDeltaX;
int osdDeltaY;
- double osdFactor;
+ double osdFactorX;
+ double osdFactorY;
cList<cDvbSubtitlePage> *pages;
cList<cDvbSubtitleBitmaps> *bitmaps;
tColor yuv2rgb(int Y, int Cb, int Cr);
diff --git a/font.c b/font.c
index db1bd89..16d1013 100644
--- a/font.c
+++ b/font.c
@@ -6,7 +6,7 @@
*
* BiDi support by Osama Alrawab <alrawab@hotmail.com> @2008 Tripoli-Libya.
*
- * $Id: font.c 2.7 2011/02/26 12:09:18 kls Exp $
+ * $Id: font.c 2.8 2011/03/28 16:29:51 kls Exp $
*/
#include "font.h"
@@ -520,7 +520,7 @@ cString cFont::Bidi(const char *Ltr)
bool ok = fribidi_log2vis(Logical, RtlLen, &Base, Visual, NULL, NULL, NULL);
if (ok) {
fribidi_remove_bidi_marks(Visual, RtlLen, NULL, NULL, NULL);
- Rtl = MALLOC(char, RtlLen * 4);
+ Rtl = MALLOC(char, RtlLen * 4 + 1);
fribidi_unicode_to_charset(fribidiCharset, Visual, RtlLen, Rtl);
}
free(Logical);
diff --git a/osd.c b/osd.c
index 3a53556..d4e095a 100644
--- a/osd.c
+++ b/osd.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: osd.c 2.17 2011/03/12 15:32:33 kls Exp $
+ * $Id: osd.c 2.21 2011/04/17 14:25:07 kls Exp $
*/
#include "osd.h"
@@ -503,8 +503,7 @@ void cBitmap::DrawPixel(int x, int y, tColor Color)
{
x -= x0;
y -= y0;
- if (0 <= x && x < width && 0 <= y && y < height)
- SetIndex(x, y, Index(Color));
+ SetIndex(x, y, Index(Color));
}
void cBitmap::DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg, tColor ColorBg, bool ReplacePalette, bool Overlay)
@@ -807,7 +806,7 @@ void cBitmap::ShrinkBpp(int NewBpp)
}
}
-cBitmap *cBitmap::Scale(double FactorX, double FactorY)
+cBitmap *cBitmap::Scaled(double FactorX, double FactorY, bool AntiAlias)
{
// Fixed point scaling code based on www.inversereality.org/files/bitmapscaling.pdf
// by deltener@mindtremors.com
@@ -815,19 +814,42 @@ cBitmap *cBitmap::Scale(double FactorX, double FactorY)
b->Replace(*this); // copy palette
int RatioX = (Width() << 16) / b->Width();
int RatioY = (Height() << 16) / b->Height();
- tIndex *DestRow = b->bitmap;
- int SourceY = 0;
- for (int y = 0; y < b->Height(); y++) {
- int SourceX = 0;
- tIndex *SourceRow = bitmap + (SourceY >> 16) * Width();
- tIndex *Dest = DestRow;
- for (int x = 0; x < b->Width(); x++) {
- *Dest++ = SourceRow[SourceX >> 16];
- SourceX += RatioX;
- }
- SourceY += RatioY;
- DestRow += b->Width();
- }
+ if (!AntiAlias || FactorX <= 1.0 && FactorY <= 1.0) {
+ // Downscaling - no anti-aliasing:
+ tIndex *DestRow = b->bitmap;
+ int SourceY = 0;
+ for (int y = 0; y < b->Height(); y++) {
+ int SourceX = 0;
+ tIndex *SourceRow = bitmap + (SourceY >> 16) * Width();
+ tIndex *Dest = DestRow;
+ for (int x = 0; x < b->Width(); x++) {
+ *Dest++ = SourceRow[SourceX >> 16];
+ SourceX += RatioX;
+ }
+ SourceY += RatioY;
+ DestRow += b->Width();
+ }
+ }
+ else {
+ // Upscaling - anti-aliasing:
+ b->SetBpp(8);
+ int SourceY = 0;
+ for (int y = 0; y < b->Height() - 1; y++) {
+ int SourceX = 0;
+ int sy = SourceY >> 16;
+ uint8_t BlendY = 0xFF - ((SourceY >> 8) & 0xFF);
+ for (int x = 0; x < b->Width() - 1; x++) {
+ int sx = SourceX >> 16;
+ uint8_t BlendX = 0xFF - ((SourceX >> 8) & 0xFF);
+ tColor c1 = b->Blend(GetColor(sx, sy), GetColor(sx + 1, sy), BlendX);
+ tColor c2 = b->Blend(GetColor(sx, sy + 1), GetColor(sx + 1, sy + 1), BlendX);
+ tColor c3 = b->Blend(c1, c2, BlendY);
+ b->DrawPixel(x + X0(), y + Y0(), c3);
+ SourceX += RatioX;
+ }
+ SourceY += RatioY;
+ }
+ }
return b;
}
@@ -1394,6 +1416,7 @@ void cPixmapMemory::DrawEllipse(const cRect &Rect, tColor Color, int Quadrants)
case -2: DrawRectangle(cRect(x1, cy - y, cx - x - x1 + 1, 1), Color); break;
case -3: DrawRectangle(cRect(x1, cy + y, cx - x - x1 + 1, 1), Color); break;
case -4: DrawRectangle(cRect(cx + x, cy + y, x2 - x + 1, 1), Color); break;
+ default: ;
}
x++;
StoppingX += TwoBSquare;
diff --git a/osd.h b/osd.h
index ebd2797..b56853a 100644
--- a/osd.h
+++ b/osd.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: osd.h 2.11 2011/03/12 16:06:48 kls Exp $
+ * $Id: osd.h 2.13 2011/04/17 14:24:32 kls Exp $
*/
#ifndef __OSD_H
@@ -273,8 +273,11 @@ public:
///< the 2^NewBpp most frequently used colors as defined in the current palette.
///< If NewBpp is not smaller than the bitmap's current color depth,
///< or if it is not one of 4bpp or 2bpp, nothing happens.
- cBitmap *Scale(double FactorX, double FactorY);
+ cBitmap *Scaled(double FactorX, double FactorY, bool AntiAlias = false);
///< Creates a copy of this bitmap, scaled by the given factors.
+ ///< If AntiAlias is true and either of the factors is greater than 1.0,
+ ///< anti-aliasing is applied. This will also set the color depth of the
+ ///< returned bitmap to 8bpp.
///< The caller must delete the returned bitmap once it is no longer used.
};
diff --git a/pat.c b/pat.c
index 862bf46..b7493ec 100644
--- a/pat.c
+++ b/pat.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: pat.c 2.15 2010/11/07 13:47:16 kls Exp $
+ * $Id: pat.c 2.16 2011/04/17 13:45:25 kls Exp $
*/
#include "pat.h"
@@ -456,7 +456,37 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
}
}
break;
- case 0x80 ... 0xFF: // STREAMTYPE_USER_PRIVATE
+ case 0x80: // STREAMTYPE_USER_PRIVATE - DigiCipher II VIDEO (ANSI/SCTE 57)
+ Vpid = esPid;
+ Ppid = pmt.getPCRPid();
+ Vtype = 0x02; // compression based upon MPEG-2
+ ProcessCaDescriptors = true;
+ break;
+ case 0x81: // STREAMTYPE_USER_PRIVATE - ATSC A/53 AUDIO (ANSI/SCTE 57)
+ {
+ char lang[MAXLANGCODE1] = { 0 };
+ SI::Descriptor *d;
+ for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
+ switch (d->getDescriptorTag()) {
+ case SI::ISO639LanguageDescriptorTag: {
+ SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d;
+ strn0cpy(lang, I18nNormalizeLanguageCode(ld->languageCode), MAXLANGCODE1);
+ }
+ break;
+ default: ;
+ }
+ delete d;
+ }
+ if (NumDpids < MAXDPIDS) {
+ Dpids[NumDpids] = esPid;
+ Dtypes[NumDpids] = SI::AC3DescriptorTag;
+ strn0cpy(DLangs[NumDpids], lang, MAXLANGCODE1);
+ NumDpids++;
+ }
+ ProcessCaDescriptors = true;
+ }
+ break;
+ case 0x82 ... 0xFF: // STREAMTYPE_USER_PRIVATE
{
char lang[MAXLANGCODE1] = { 0 };
bool IsAc3 = false;
@@ -467,17 +497,11 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
SI::RegistrationDescriptor *rd = (SI::RegistrationDescriptor *)d;
// http://www.smpte-ra.org/mpegreg/mpegreg.html
switch (rd->getFormatIdentifier()) {
- case 0x44434949: // 'DCII' aka. DigiCipher II
- Vpid = esPid;
- Ppid = pmt.getPCRPid();
- Vtype = 0x02; // DCII compression is based upon MPEG-2
- ProcessCaDescriptors = true;
- break;
case 0x41432D33: // 'AC-3'
IsAc3 = true;
break;
default:
- //printf("Format identifier: 0x08X\n", rd->getFormatIdentifier());
+ //printf("Format identifier: 0x%08X (pid: %d)\n", rd->getFormatIdentifier(), esPid);
break;
}
}
@@ -493,11 +517,11 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
}
if (IsAc3) {
if (NumDpids < MAXDPIDS) {
- Dpids[NumDpids] = esPid;
- Dtypes[NumDpids] = SI::AC3DescriptorTag;
- strn0cpy(DLangs[NumDpids], lang, MAXLANGCODE1);
- NumDpids++;
- }
+ Dpids[NumDpids] = esPid;
+ Dtypes[NumDpids] = SI::AC3DescriptorTag;
+ strn0cpy(DLangs[NumDpids], lang, MAXLANGCODE1);
+ NumDpids++;
+ }
ProcessCaDescriptors = true;
}
}
diff --git a/po/sr_SR.po b/po/sr_SR.po
index 0900cbc..9a20687 100644
--- a/po/sr_SR.po
+++ b/po/sr_SR.po
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ISO-8859-2\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language: Serbian-latin\n"
+"Language: sr\n"
msgid "*** Invalid Channel ***"
msgstr "*** Neispravan Kanal ***"
diff --git a/recording.c b/recording.c
index 02a6e61..d4cf9c3 100644
--- a/recording.c
+++ b/recording.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: recording.c 2.26 2011/02/27 13:35:20 kls Exp $
+ * $Id: recording.c 2.30 2011/04/17 13:53:11 kls Exp $
*/
#include "recording.h"
@@ -12,6 +12,8 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#define __STDC_FORMAT_MACROS // Required for format specifiers
+#include <inttypes.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
@@ -301,9 +303,10 @@ bool cResumeFile::Save(int Index)
void cResumeFile::Delete(void)
{
if (fileName) {
- if (remove(fileName) < 0 && errno != ENOENT)
+ if (remove(fileName) == 0)
+ Recordings.ResetResume(fileName);
+ else if (errno != ENOENT)
LOG_ERROR_STR(fileName);
- Recordings.ResetResume(fileName);
}
}
@@ -1270,19 +1273,31 @@ bool cMarks::Load(const char *RecordingFileName, double FramesPerSecond, bool Is
{
fileName = AddDirectory(RecordingFileName, IsPesRecording ? MARKSFILESUFFIX ".vdr" : MARKSFILESUFFIX);
framesPerSecond = FramesPerSecond;
- lastUpdate = 0;
+ nextUpdate = 0;
lastFileTime = -1; // the first call to Load() must take place!
+ lastChange = 0;
return Update();
}
bool cMarks::Update(void)
{
time_t t = time(NULL);
- if (t - lastUpdate > MARKSUPDATEDELTA) {
- lastUpdate = t;
- t = LastModifiedTime(fileName);
- if (t > lastFileTime) {
- lastFileTime = t;
+ if (t > nextUpdate) {
+ time_t LastModified = LastModifiedTime(fileName);
+ if (LastModified != lastFileTime) // change detected, or first run
+ lastChange = LastModified > 0 ? LastModified : t;
+ int d = t - lastChange;
+ if (d < 60)
+ d = 1; // check frequently if the file has just been modified
+ else if (d < 3600)
+ d = 10; // older files are checked less frequently
+ else
+ d /= 360; // phase out checking for very old files
+ nextUpdate = t + d;
+ if (LastModified != lastFileTime) { // change detected, or first run
+ lastFileTime = LastModified;
+ if (lastFileTime == t)
+ lastFileTime--; // make sure we don't miss updates in the remaining second
cMutexLock MutexLock(&MutexMarkFramesPerSecond);
MarkFramesPerSecond = framesPerSecond;
if (cConfig<cMark>::Load(fileName)) {
@@ -1550,7 +1565,7 @@ cIndexFile::cIndexFile(const char *FileName, bool Record, bool IsPesRecording)
delta = int(buf.st_size % sizeof(tIndexTs));
if (delta) {
delta = sizeof(tIndexTs) - delta;
- esyslog("ERROR: invalid file size (%lld) in '%s'", buf.st_size, fileName);
+ esyslog("ERROR: invalid file size (%"PRId64") in '%s'", buf.st_size, fileName);
}
last = int((buf.st_size + delta) / sizeof(tIndexTs) - 1);
if (!Record && last >= 0) {
diff --git a/recording.h b/recording.h
index 93b5a9c..8ec7f49 100644
--- a/recording.h
+++ b/recording.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: recording.h 2.16 2011/02/27 12:48:21 kls Exp $
+ * $Id: recording.h 2.19 2011/04/17 13:18:04 kls Exp $
*/
#ifndef __RECORDING_H
@@ -57,6 +57,7 @@ private:
int lifetime;
char *fileName;
cRecordingInfo(const cChannel *Channel = NULL, const cEvent *Event = NULL);
+ bool Read(FILE *f);
void SetData(const char *Title, const char *ShortText, const char *Description);
void SetAux(const char *Aux);
public:
@@ -72,7 +73,6 @@ public:
const char *Aux(void) const { return aux; }
double FramesPerSecond(void) const { return framesPerSecond; }
void SetFramesPerSecond(double FramesPerSecond);
- bool Read(FILE *f);
bool Write(FILE *f, const char *Prefix = "") const;
bool Read(void);
bool Write(void) const;
@@ -192,8 +192,9 @@ class cMarks : public cConfig<cMark> {
private:
cString fileName;
double framesPerSecond;
- time_t lastUpdate;
+ time_t nextUpdate;
time_t lastFileTime;
+ time_t lastChange;
public:
bool Load(const char *RecordingFileName, double FramesPerSecond = DEFAULTFRAMESPERSECOND, bool IsPesRecording = false);
bool Update(void);
diff --git a/remote.c b/remote.c
index 048b98c..cd3a758 100644
--- a/remote.c
+++ b/remote.c
@@ -4,11 +4,13 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: remote.c 2.2 2010/12/24 15:26:05 kls Exp $
+ * $Id: remote.c 2.3 2011/03/27 15:03:36 kls Exp $
*/
#include "remote.h"
#include <fcntl.h>
+#define __STDC_FORMAT_MACROS // Required for format specifiers
+#include <inttypes.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/types.h>
@@ -122,7 +124,7 @@ bool cRemote::PutMacro(eKeys Key)
bool cRemote::Put(uint64_t Code, bool Repeat, bool Release)
{
char buffer[32];
- snprintf(buffer, sizeof(buffer), "%016llX", Code);
+ snprintf(buffer, sizeof(buffer), "%016"PRIX64, Code);
return Put(buffer, Repeat, Release);
}
diff --git a/remux.c b/remux.c
index f7ad86d..f7ef87a 100644
--- a/remux.c
+++ b/remux.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: remux.c 2.51 2011/02/26 15:51:04 kls Exp $
+ * $Id: remux.c 2.53 2011/03/20 10:21:14 kls Exp $
*/
#include "remux.h"
@@ -783,9 +783,11 @@ cFrameDetector::cFrameDetector(int Pid, int Type)
synced = false;
newFrame = independentFrame = false;
numPtsValues = 0;
+ numFrames = 0;
numIFrames = 0;
framesPerSecond = 0;
framesInPayloadUnit = framesPerPayloadUnit = 0;
+ payloadUnitOfFrame = 0;
scanning = false;
scanner = EMPTY_SCANNER;
}
@@ -807,6 +809,7 @@ void cFrameDetector::SetPid(int Pid, int Type)
void cFrameDetector::Reset(void)
{
newFrame = independentFrame = false;
+ payloadUnitOfFrame = 0;
scanning = false;
scanner = EMPTY_SCANNER;
}
@@ -833,7 +836,7 @@ int cFrameDetector::Analyze(const uchar *Data, int Length)
return Processed;
if (Length < MIN_TS_PACKETS_FOR_FRAME_DETECTOR * TS_SIZE)
return Processed; // need more data, in case the frame type is not stored in the first TS packet
- if (!framesPerSecond) {
+ if (framesPerSecond <= 0.0) {
// frame rate unknown, so collect a sequence of PTS values:
if (numPtsValues < MaxPtsValues && numIFrames < 2) { // collect a sequence containing at least two I-frames
const uchar *Pes = Data + TsPayloadOffset(Data);
@@ -844,6 +847,7 @@ int cFrameDetector::Analyze(const uchar *Data, int Length)
dbgframes("#");
numPtsValues = 0;
numIFrames = 0;
+ numFrames = 0;
}
else
numPtsValues++;
@@ -863,10 +867,23 @@ int cFrameDetector::Analyze(const uchar *Data, int Length)
framesPerSecond = 25.0;
else if (Delta % 3003 == 0)
framesPerSecond = 30.0 / 1.001;
- else if (abs(Delta - 1800) <= 1)
- framesPerSecond = 50.0;
+ else if (abs(Delta - 1800) <= 1) {
+ if (numFrames > 50) {
+ // this is a "best guess": if there are more than 50 frames between two I-frames, we assume each "frame" actually contains a "field", so two "fields" make one "frame"
+ framesPerSecond = 25.0;
+ framesPerPayloadUnit = -2;
+ }
+ else
+ framesPerSecond = 50.0;
+ }
else if (Delta == 1501)
- framesPerSecond = 60.0 / 1.001;
+ if (numFrames > 50) {
+ // this is a "best guess": if there are more than 50 frames between two I-frames, we assume each "frame" actually contains a "field", so two "fields" make one "frame"
+ framesPerSecond = 30.0 / 1.001;
+ framesPerPayloadUnit = -2;
+ }
+ else
+ framesPerSecond = 60.0 / 1.001;
else {
framesPerSecond = 25.0;
dsyslog("unknown frame delta (%d), assuming 25 fps", Delta);
@@ -874,7 +891,7 @@ int cFrameDetector::Analyze(const uchar *Data, int Length)
}
else // audio
framesPerSecond = 90000.0 / Delta; // PTS of audio frames is always increasing
- dbgframes("\nDelta = %d FPS = %5.2f FPPU = %d\n", Delta, framesPerSecond, framesPerPayloadUnit);
+ dbgframes("\nDelta = %d FPS = %5.2f FPPU = %d NF = %d\n", Delta, framesPerSecond, framesPerPayloadUnit, numFrames);
}
}
scanner = EMPTY_SCANNER;
@@ -909,6 +926,8 @@ int cFrameDetector::Analyze(const uchar *Data, int Length)
framesInPayloadUnit++;
if (independentFrame)
numIFrames++;
+ if (numIFrames == 1)
+ numFrames++;
dbgframes("%d ", (Data[i + 2] >> 3) & 0x07);
}
if (synced)
@@ -923,6 +942,13 @@ int cFrameDetector::Analyze(const uchar *Data, int Length)
newFrame = true;
independentFrame = Data[i + 1] == 0x10;
if (synced) {
+ if (framesPerPayloadUnit < 0) {
+ payloadUnitOfFrame = (payloadUnitOfFrame + 1) % -framesPerPayloadUnit;
+ if (payloadUnitOfFrame != 0 && independentFrame)
+ payloadUnitOfFrame = 0;
+ if (payloadUnitOfFrame)
+ newFrame = false;
+ }
if (framesPerPayloadUnit <= 1)
scanning = false;
}
@@ -930,6 +956,8 @@ int cFrameDetector::Analyze(const uchar *Data, int Length)
framesInPayloadUnit++;
if (independentFrame)
numIFrames++;
+ if (numIFrames == 1)
+ numFrames++;
dbgframes("%02X ", Data[i + 1]);
}
if (synced)
@@ -953,9 +981,9 @@ int cFrameDetector::Analyze(const uchar *Data, int Length)
pid = 0; // let's just ignore any further data
}
}
- if (!synced && framesPerSecond && independentFrame) {
+ if (!synced && framesPerSecond > 0.0 && independentFrame) {
synced = true;
- dbgframes("*");
+ dbgframes("*\n");
Reset();
return Processed + TS_SIZE;
}
diff --git a/remux.h b/remux.h
index 7140aaf..60a9a57 100644
--- a/remux.h
+++ b/remux.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: remux.h 2.27 2010/11/01 11:24:20 kls Exp $
+ * $Id: remux.h 2.28 2011/03/19 16:52:46 kls Exp $
*/
#ifndef __REMUX_H
@@ -345,12 +345,15 @@ private:
bool independentFrame;
uint32_t ptsValues[MaxPtsValues]; // 32 bit is enough - we only need the delta
int numPtsValues;
+ int numFrames;
int numIFrames;
bool isVideo;
double framesPerSecond;
int framesInPayloadUnit;
int framesPerPayloadUnit; // Some broadcasters send one frame per payload unit (== 1),
- // while others put an entire GOP into one payload unit (> 1).
+ // some put an entire GOP into one payload unit (> 1), and
+ // some spread a single frame over several payload units (< 0).
+ int payloadUnitOfFrame;
bool scanning;
uint32_t scanner;
public:
diff --git a/runvdr.template b/runvdr.template
index ebc2f04..2f6fd87 100755
--- a/runvdr.template
+++ b/runvdr.template
@@ -20,7 +20,7 @@
# See the main source file 'vdr.c' for copyright information and
# how to reach the author.
#
-# $Id: runvdr.template 2.1 2010/01/17 12:39:27 kls Exp $
+# $Id: runvdr.template 2.2 2011/04/17 12:34:30 kls Exp $
VDRPRG="./vdr"
@@ -30,8 +30,12 @@ VDROPTIONS="-w 60"
VDRPLUGINS=""
# You will need to select your output device plugin if you want
# to use VDR to watch video. For instance, for a "Full Featured"
-# DVB card that would be
+# SD DVB card that would be
# VDRPLUGINS="-P dvbsddevice"
+# For a "Full Featured" HD DVB card you could use
+# VDRPLUGINS="-P dvbhddevice"
+# There are also other output device plugins available, see
+# http://www.vdr-wiki.de/wiki/index.php/Plugins.
VDRCMD="$VDRPRG $VDROPTIONS $VDRPLUGINS $*"
diff --git a/tools.c b/tools.c
index d03595e..ab7fe96 100644
--- a/tools.c
+++ b/tools.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: tools.c 2.12 2011/02/25 14:58:31 kls Exp $
+ * $Id: tools.c 2.13 2011/03/20 12:07:18 kls Exp $
*/
#include "tools.h"
@@ -1575,9 +1575,9 @@ ssize_t cUnbufferedFile::Read(void *Data, size_t Size)
cachedstart = min(cachedstart, curpos);
#endif
ssize_t bytesRead = safe_read(fd, Data, Size);
-#ifdef USE_FADVISE
if (bytesRead > 0) {
curpos += bytesRead;
+#ifdef USE_FADVISE
cachedend = max(cachedend, curpos);
// Read ahead:
@@ -1597,8 +1597,9 @@ ssize_t cUnbufferedFile::Read(void *Data, size_t Size)
}
else
ahead = curpos; // jumped -> we really don't want any readahead, otherwise e.g. fast-rewind gets in trouble.
+#endif
}
-
+#ifdef USE_FADVISE
if (cachedstart < cachedend) {
if (curpos - cachedstart > READCHUNK * 2) {
// current position has moved forward enough, shrink tail window.
diff --git a/vdr.5 b/vdr.5
index ce15215..6274c1a 100644
--- a/vdr.5
+++ b/vdr.5
@@ -8,7 +8,7 @@
.\" License as specified in the file COPYING that comes with the
.\" vdr distribution.
.\"
-.\" $Id: vdr.5 2.21 2010/12/24 15:19:21 kls Exp $
+.\" $Id: vdr.5 2.22 2011/04/03 10:21:36 kls Exp $
.\"
.TH vdr 5 "10 Feb 2008" "1.6" "Video Disk Recorder Files"
.SH NAME
@@ -807,7 +807,7 @@ l l.
<description> @is the description of the event (any '|' characters will be interpreted as newlines)
<genre> @is a two digit hex code, as defined in ETSI EN 300 468, table 28 (up to 4 genre codes are supported)
<parental rating>@is the minimum age of the intended audience
-<stream> @is the stream content (1 = video, 2 = audio, 3 = subtitles, 4 = AC3)
+<stream> @is the stream content (1 = MPEG2 video, 2 = MP2 audio, 3 = subtitles, 4 = AC3 audio, 5 = H.264 video, 6 = HEAAC audio)
<type> @is the stream type according to ETSI EN 300 468
<language> @is the three letter language code (optionally two codes, separated by '+')
<descr> @is the description of this stream component