diff options
Diffstat (limited to 'PLUGINS/src/dvbhddevice')
-rw-r--r-- | PLUGINS/src/dvbhddevice/COPYING | 340 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/HISTORY | 16 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/Makefile | 114 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/README | 18 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/bitbuffer.c | 97 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/bitbuffer.h | 31 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/dvbhddevice.c | 48 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/dvbhdffdevice.c | 760 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/dvbhdffdevice.h | 123 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/hdffcmd.c | 1120 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/hdffcmd.h | 102 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/hdffmsgdef.h | 304 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/hdffosd.c | 755 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/hdffosd.h | 26 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/setup.c | 252 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/setup.h | 53 |
16 files changed, 4159 insertions, 0 deletions
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 |