]> git.vomp.tv Git - vompserver.git/commitdiff
Initial import start
authorChris Tallon <chris@vomp.tv>
Tue, 28 Jun 2005 22:13:04 +0000 (22:13 +0000)
committerChris Tallon <chris@vomp.tv>
Tue, 28 Jun 2005 22:13:04 +0000 (22:13 +0000)
48 files changed:
COPYING [new file with mode: 0644]
HISTORY [new file with mode: 0644]
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
config.c [new file with mode: 0644]
config.h [new file with mode: 0644]
defines.h [new file with mode: 0644]
dsock.c [new file with mode: 0644]
dsock.h [new file with mode: 0644]
libdvbmpeg/DVB.hh [new file with mode: 0644]
libdvbmpeg/Makefile [new file with mode: 0644]
libdvbmpeg/OSD.h [new file with mode: 0644]
libdvbmpeg/channel.h [new file with mode: 0644]
libdvbmpeg/ci.hh [new file with mode: 0644]
libdvbmpeg/cpptools.cc [new file with mode: 0644]
libdvbmpeg/cpptools.hh [new file with mode: 0644]
libdvbmpeg/ctools.c [new file with mode: 0644]
libdvbmpeg/ctools.h [new file with mode: 0644]
libdvbmpeg/devices.hh [new file with mode: 0644]
libdvbmpeg/osd.hh [new file with mode: 0644]
libdvbmpeg/remux.c [new file with mode: 0644]
libdvbmpeg/remux.h [new file with mode: 0644]
libdvbmpeg/ringbuffy.c [new file with mode: 0644]
libdvbmpeg/ringbuffy.h [new file with mode: 0644]
libdvbmpeg/transform.c [new file with mode: 0644]
libdvbmpeg/transform.h [new file with mode: 0644]
mvpclient.c [new file with mode: 0644]
mvpclient.h [new file with mode: 0644]
mvpserver.c [new file with mode: 0644]
mvpserver.h [new file with mode: 0644]
recplayer.c [new file with mode: 0644]
recplayer.h [new file with mode: 0644]
remux/README [new file with mode: 0644]
remux/ts2es.c [new file with mode: 0644]
remux/ts2es.h [new file with mode: 0644]
remux/ts2ps.c [new file with mode: 0644]
remux/ts2ps.h [new file with mode: 0644]
remux/tsremux.c [new file with mode: 0644]
remux/tsremux.h [new file with mode: 0644]
ringbuffer.c [new file with mode: 0644]
ringbuffer.h [new file with mode: 0644]
tcp.c [new file with mode: 0644]
tcp.h [new file with mode: 0644]
transceiver.c [new file with mode: 0644]
transceiver.h [new file with mode: 0644]
udpreplier.c [new file with mode: 0644]
udpreplier.h [new file with mode: 0644]
vompserver.c [new file with mode: 0644]

diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..5b6e7c6
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   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.)
+\f
+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.
+\f
+  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.
+\f
+  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
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/HISTORY b/HISTORY
new file mode 100644 (file)
index 0000000..d7cdb3e
--- /dev/null
+++ b/HISTORY
@@ -0,0 +1,7 @@
+VDR Plugin 'vompserver' Revision History
+----------------------------------------
+
+2005-06-28: Version 0.0.0
+
+- Upload to SF CVS. Not a release yet!
+
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..fdea30e
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,90 @@
+#
+# Makefile for a Video Disk Recorder plugin
+#
+# $Id$
+
+# The official name of this plugin.
+# This name will be used in the '-P...' option of VDR to load the plugin.
+# By default the main source file also carries this name.
+#
+PLUGIN = vompserver
+
+### The version number of this plugin (taken from the main source file):
+
+VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ print $$6 }' | sed -e 's/[";]//g')
+
+### The C++ compiler and options:
+
+CXX      ?= g++
+CXXFLAGS ?= -O2 -Wall -Woverloaded-virtual -Werror
+
+### The directory environment:
+
+DVBDIR = ../../../../DVB
+VDRDIR = ../../..
+LIBDIR = ../../lib
+TMPDIR = /tmp
+
+### Allow user defined options to overwrite defaults:
+
+-include $(VDRDIR)/Make.config
+
+### The version number of VDR (taken from VDR's "config.h"):
+
+VDRVERSION = $(shell grep 'define VDRVERSION ' $(VDRDIR)/config.h | awk '{ print $$3 }' | sed -e 's/"//g')
+
+### The name of the distribution archive:
+
+ARCHIVE = $(PLUGIN)-$(VERSION)
+PACKAGE = vdr-$(ARCHIVE)
+
+### Includes and Defines (add further entries here):
+
+INCLUDES += -I$(VDRDIR)/include -I$(DVBDIR)/include -Iremux -Ilibdvbmpeg
+
+DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
+
+### The object files (add further files here):
+
+OBJS = $(PLUGIN).o dsock.o mvpserver.o udpreplier.o mvpclient.o tcp.o \
+                   transceiver.o remux/ts2ps.o remux/ts2es.o remux/tsremux.o ringbuffer.o \
+                   recplayer.o config.o
+
+
+libdvbmpeg/libdvbmpegtools.a: libdvbmpeg/*.c libdvbmpeg/*.cc libdvbmpeg/*.h libdvbmpeg/*.hh
+       make -C ./libdvbmpeg libdvbmpegtools.a
+
+
+### Implicit rules:
+
+%.o: %.c
+       $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
+        
+# Dependencies:
+
+MAKEDEP = g++ -MM -MG
+DEPFILE = .dependencies
+$(DEPFILE): Makefile
+       @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
+
+-include $(DEPFILE)
+
+### Targets:
+
+all: libvdr-$(PLUGIN).so
+
+libvdr-$(PLUGIN).so: $(OBJS) libdvbmpeg/libdvbmpegtools.a
+       $(CXX) $(CXXFLAGS) -shared $(OBJS) libdvbmpeg/libdvbmpegtools.a -o $@
+       @cp $@ $(LIBDIR)/$@.$(VDRVERSION)
+
+dist: clean
+       @-rm -rf $(TMPDIR)/$(ARCHIVE)
+       @mkdir $(TMPDIR)/$(ARCHIVE)
+       @cp -a * $(TMPDIR)/$(ARCHIVE)
+       @tar czf $(PACKAGE).tgz -C $(TMPDIR) $(ARCHIVE)
+       @-rm -rf $(TMPDIR)/$(ARCHIVE)
+       @echo Distribution package created as $(PACKAGE).tgz
+
+clean:
+       make -C libdvbmpeg clean
+       rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~ remux/*.o
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..494c85f
--- /dev/null
+++ b/README
@@ -0,0 +1,13 @@
+This is a "plugin" for the Video Disk Recorder (VDR).
+
+Written by:                  Chris Tallon <chris@loggytronic.com>
+
+Project's homepage:          http://www.loggytronic.com/vomp
+
+Latest version available at: http://www.loggytronic.com/vomp
+
+See the file COPYING for license information.
+
+Description:
+
+Server side of VDR on MVP by Chris Tallon
diff --git a/config.c b/config.c
new file mode 100644 (file)
index 0000000..c70fe7d
--- /dev/null
+++ b/config.c
@@ -0,0 +1,516 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+    Copyright 2004-2005 University Of Bradford
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "config.h"
+
+Config::Config()
+{
+  initted = 0;
+  lastLineLength = 0;
+}
+
+int Config::init(char* takeFileName)
+{
+  if (initted) return 1;
+
+  pthread_mutex_init(&fileLock, NULL);
+
+  if (strlen(takeFileName) > (MAX_FILENAME_LENGTH - 1))
+  {
+    printf("Config error: Config filename too long\n");
+    return 0;
+  }
+
+  strcpy(fileName, takeFileName);
+  file = fopen(fileName, "r");
+  if (!file)
+  {
+    file = fopen(fileName, "w");
+    if (!file)
+    {
+      printf("Config error: Could not access config file\n");
+      return 0;
+    }
+  }
+  fclose(file);
+
+  initted = 1;
+
+  return 1;
+}
+
+int Config::shutdown()
+{
+  if (!initted) return 1;
+
+  pthread_mutex_lock(&fileLock);
+  initted = 0;
+  pthread_mutex_unlock(&fileLock);
+  pthread_mutex_destroy(&fileLock);
+
+  return 1;
+}
+
+int Config::openFile()
+{
+  if (!initted) return 0;
+  if (pthread_mutex_lock(&fileLock))
+  {
+    printf("Config error: Could not get lock\n");
+    return 0;
+  }
+  if (!initted)
+  {
+    printf("Config error: Initted 0 after lock\n");
+    pthread_mutex_unlock(&fileLock);
+    return 0;
+  }
+
+  file = fopen(fileName, "r");
+  if (!file)
+  {
+    printf("Config error: Could not open config file\n");
+    pthread_mutex_unlock(&fileLock);
+    return 0;
+  }
+  return 1;
+}
+
+void Config::closeFile()
+{
+  if (!initted) return;
+
+  fclose(file);
+  file = NULL;
+  pthread_mutex_unlock(&fileLock);
+}
+
+int Config::readLine()
+{
+  if (!initted || !file) { printf("1\n"); return 0; }
+  if (!fgets(buffer, BUFFER_LENGTH-1, file)) { printf("2\n"); return 0; }
+  lastLineLength = strlen(buffer);
+  printf("buffer before trim: '%s'\n", buffer);
+  trim(buffer);
+  printf("buffer after trim: '%s'\n", buffer);
+  return 1;
+}
+
+// START HERE
+
+FILE* Config::copyToHere(long position)
+{
+  strcpy(fileNameTemp, "/tmp/configXXXXXX");
+  int newFileDes = mkstemp(fileNameTemp);
+  FILE* newFile = fdopen(newFileDes, "w");
+
+  if (!newFile) return NULL;
+
+  long newPos = 0;
+  rewind(file);
+
+  while (newPos < position)
+  {
+    fgets(buffer, BUFFER_LENGTH-1, file);
+    fputs(buffer, newFile);
+    newPos += strlen(buffer);
+  }
+  return newFile;
+}
+
+int Config::copyRest(FILE* newFile)
+{
+  if (newFile)
+  {
+    while(fgets(buffer, BUFFER_LENGTH-1, file))
+    {
+      fputs(buffer, newFile);
+    }
+
+    fclose(newFile);
+  }
+  fclose(file);
+  file = NULL;
+
+  if (newFile) rename(fileNameTemp, fileName);
+
+  pthread_mutex_unlock(&fileLock);
+  return 1;
+}
+
+int Config::deleteValue(char* section, char* key)
+{
+  if (!initted) return 0;
+  if (!openFile()) return 0;
+
+  if (!findSection(section))
+  {
+    closeFile();
+    printf("Config error: Section %s not found\n", section);
+    return 0;
+  }
+  if (!findKey(key))
+  {
+    closeFile();
+    printf("Config error: Key %s not found\n", key);
+    return 0;
+  }
+
+  FILE* newFile = copyToHere(ftell(file) - lastLineLength);
+  fgets(buffer, BUFFER_LENGTH-1, file);
+
+  return copyRest(newFile);
+}
+
+int Config::setValueLong(char* section, char* key, long newValue)
+{
+  char longBuffer[50];
+  sprintf(longBuffer, "%li", newValue);
+  return setValueString(section, key, longBuffer);
+}
+
+int Config::setValueLongLong(char* section, char* key, long long newValue)
+{
+  char longBuffer[50];
+  sprintf(longBuffer, "%lli", newValue);
+  return setValueString(section, key, longBuffer);
+}
+
+int Config::setValueDouble(char* section, char* key, double newValue)
+{
+  char doubleBuffer[50];
+  sprintf(doubleBuffer, "%f", newValue);
+  return setValueString(section, key, doubleBuffer);
+}
+
+int Config::setValueString(char* section, char* key, char* newValue)
+{
+  if (!initted) return 0;
+  if (!openFile()) return 0;
+
+  if (findSection(section))
+  {
+    if (findKey(key))
+    {
+      FILE* newFile = copyToHere(ftell(file) - lastLineLength);
+      if (!newFile)
+      {
+        closeFile();
+        printf("Config error: Could not write temp config file\n");
+        return 0;
+      }
+
+      fgets(buffer, BUFFER_LENGTH-1, file);
+      fprintf(newFile, "%s = %s\n", key, newValue);
+      return copyRest(newFile);
+    }
+    else
+    {
+      rewind(file);
+      findSection(section);
+      FILE* newFile = copyToHere(ftell(file));
+      if (!newFile)
+      {
+        closeFile();
+        printf("Config error: Could not write temp config file\n");
+        return 0;
+      }
+
+      fprintf(newFile, "%s = %s\n", key, newValue);
+      return copyRest(newFile);
+    }
+  }
+  else
+  {
+    // section not found
+    fseek(file, 0, SEEK_END);
+    FILE* newFile = copyToHere(ftell(file));
+    if (!newFile)
+    {
+      closeFile();
+      printf("Config error: Could not write temp config file\n");
+      return 0;
+    }
+
+    fprintf(newFile, "[%s]\n%s = %s\n", section, key, newValue);
+    return copyRest(newFile);
+  }
+}
+
+char* Config::getSectionKeyNames(char* section, int& numberOfReturns, int& allKeysSize)
+{
+  numberOfReturns = 0;
+  allKeysSize = 0;
+  char* allKeys = NULL;
+  int allKeysIndex = 0;
+  int keyLength;
+  char* equalspos;
+
+  if (!initted) return NULL;
+  if (!openFile()) return NULL;
+  if (!findSection(section)) return NULL;
+
+  char foundKey[BUFFER_LENGTH];
+
+  while(readLine())
+  {
+    // Is this line a section header? if so, exit
+    if ((buffer[0] == '[') && (buffer[strlen(buffer)-1] == ']')) break;
+
+    equalspos = strstr(buffer, "=");
+    if (!equalspos) continue;  // if there is no = then it's not a key
+    memcpy(foundKey, buffer, equalspos-buffer);
+    foundKey[equalspos-buffer] = '\0';
+    trim(foundKey);
+    keyLength = strlen(foundKey);
+    allKeysSize += keyLength + 1;
+    allKeys = (char*)realloc(allKeys, allKeysSize);
+    memcpy(&allKeys[allKeysIndex], foundKey, keyLength);
+    allKeysIndex += keyLength;
+    allKeys[allKeysIndex] = '\0';
+    allKeysIndex++;
+    numberOfReturns++;
+  }
+
+  closeFile();
+  return allKeys;
+}
+
+
+// END HERE
+
+int Config::findSection(char* section)
+{
+  if (!initted || !file) return 0;
+  if (strlen(section) > (BUFFER_LENGTH-2))
+  {
+    printf("Config error: Section given exceeds max length\n");
+    return 0;
+  }
+
+  char toFind[BUFFER_LENGTH];
+  toFind[0] = '[';
+  toFind[1] = '\0';
+  strcat(toFind, section);
+  strcat(toFind, "]");
+
+  while(readLine())
+  {
+    printf("to find '%s' this line '%s'\n", toFind, buffer);
+    if (!strcmp(toFind, buffer)) return 1;
+  }
+  return 0;
+}
+
+int Config::findKey(char* key)
+{
+  if (!initted || !file) return 0;
+
+  if (strlen(key) > (BUFFER_LENGTH-1))
+  {
+    printf("Config error: Key given exceeds max length\n");
+    return 0;
+  }
+
+  char prepForTest[BUFFER_LENGTH];
+
+  // do a rough search first, this could match substrings that we don't want
+  while(readLine())
+  {
+    // Is this line a section header? if so, exit
+    if ((buffer[0] == '[') && (buffer[strlen(buffer)-1] == ']')) return 0;
+    if (strstr(buffer, key))
+    {
+      // rough search found match
+      char* equalspos = strstr(buffer, "=");
+      if (!equalspos) continue;
+      memcpy(prepForTest, buffer, equalspos-buffer);
+      prepForTest[equalspos-buffer] = '\0';
+      trim(prepForTest);
+
+      if (!strcmp(key, prepForTest))
+      {
+        // in buffer, set all up to equals to space, then trim!
+        for(char* curPos = buffer; curPos <= equalspos; curPos++)
+        {
+          *curPos = ' ';
+        }
+        trim(buffer);
+        return 1;
+      }
+    }
+  }
+  return 0;
+}
+
+char* Config::getValueString(char* section, char* key)
+{
+  if (!initted) return NULL;
+  if (!openFile()) return NULL;
+
+  if (!findSection(section))
+  {
+    closeFile();
+    printf("Config error: Section %s not found\n", section);
+    return 0;
+  }
+  if (!findKey(key))
+  {
+    closeFile();
+    printf("Config error: Key %s not found\n", key);
+    return 0;
+  }
+
+  char* returnString = new char[strlen(buffer)+1];
+  strcpy(returnString, buffer);
+
+  closeFile();
+
+  return returnString;
+}
+
+long Config::getValueLong(char* section, char* key, int* failure)
+{
+  *failure = 1;
+  if (!initted) return 0;
+  if (!openFile()) return 0;
+
+  if (!findSection(section))
+  {
+    closeFile();
+    printf("Config error: Section %s not found\n", section);
+    return 0;
+  }
+  if (!findKey(key))
+  {
+    closeFile();
+    printf("Config error: Key %s not found\n", key);
+    return 0;
+  }
+  *failure = 0;
+
+  char* check;
+  long retVal = strtol(buffer, &check, 10);
+  if ((retVal == 0) && (check == buffer)) *failure = 1;
+  closeFile();
+
+  return retVal;
+}
+
+long long Config::getValueLongLong(char* section, char* key, int* failure)
+{
+  *failure = 1;
+  if (!initted) return 0;
+  if (!openFile()) return 0;
+
+  if (!findSection(section))
+  {
+    closeFile();
+    printf("Config error: Section %s not found\n", section);
+    return 0;
+  }
+  if (!findKey(key))
+  {
+    closeFile();
+    printf("Config error: Key %s not found\n", key);
+    return 0;
+  }
+  *failure = 0;
+
+  char* check;
+  long long retVal = strtoll(buffer, &check, 10);
+  if ((retVal == 0) && (check == buffer)) *failure = 1;
+  closeFile();
+
+  return retVal;
+}
+
+double Config::getValueDouble(char* section, char* key, int* failure)
+{
+  *failure = 1;
+  if (!initted) return 0;
+  if (!openFile()) return 0;
+
+  if (!findSection(section))
+  {
+    closeFile();
+    printf("Config error: Section %s not found\n", section);
+    return 0;
+  }
+  if (!findKey(key))
+  {
+    closeFile();
+    printf("Config error: Key %s not found\n", key);
+    return 0;
+  }
+
+  *failure = 0;
+
+  char* check;
+  double retVal = strtod(buffer, &check);
+  if ((retVal == 0) && (check == buffer)) *failure = 1;
+
+  closeFile();
+
+  return retVal;
+}
+
+
+
+void Config::trim(char* str)
+{
+  int pos, len, start, end;
+
+  // Kill comments
+  len = strlen(str);
+  for(pos = 0; pos < len; pos++)
+  {
+    if ((str[pos] == '#') || (str[pos] == ';'))
+    {
+      // Mod. If #/; is at start of line ok. Else, if it is after a space, ok.
+
+      if ((pos == 0) || (isspace(str[pos - 1])))
+      {
+        str[pos] = '\0';
+        break;
+      }
+
+    }
+  }
+
+  len = strlen(str);
+  end = len;
+  if (!len) return;
+
+  start = 0;
+  while(isspace(str[start])) start++;
+  while(isspace(str[end-1]))
+  {
+    end--;
+    if (end == 0)
+    {
+      str[0] = '\0';
+      return;
+    }
+  }
+  for(pos = start; pos < end; pos++) str[pos - start] = str[pos];
+  str[end - start] = '\0';
+}
diff --git a/config.h b/config.h
new file mode 100644 (file)
index 0000000..161a497
--- /dev/null
+++ b/config.h
@@ -0,0 +1,77 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+    Copyright 2004-2005 University Of Bradford
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <ctype.h>
+
+#define MAX_FILENAME_LENGTH 500
+#define BUFFER_LENGTH 1500
+
+class Config
+{
+  public:
+    Config();
+
+    int init(char* fileName);
+    int shutdown();
+    int status();
+
+    char* getValueString(char* section, char* key);
+    long getValueLong(char* section, char* key, int* failure);
+    long long getValueLongLong(char* section, char* key, int* failure);
+    double getValueDouble(char* section, char* key, int* failure);
+
+    int setValueString(char* section, char* key, char* newValue);
+    int setValueLong(char* section, char* key, long newValue);
+    int setValueLongLong(char* section, char* key, long long newValue);
+    int setValueDouble(char* section, char* key, double newValue);
+
+    int deleteValue(char* section, char* key); // err.. delete "key".
+    char* getSectionKeyNames(char* section, int& numberOfReturns, int& length);
+
+  private:
+    pthread_mutex_t fileLock;
+    int initted;
+    int lastLineLength;
+
+    char fileName[MAX_FILENAME_LENGTH];
+    char fileNameTemp[MAX_FILENAME_LENGTH];
+
+    FILE* file;
+    char buffer[BUFFER_LENGTH];
+
+    int openFile();
+    void closeFile();
+    int readLine();
+    int findSection(char* section);
+    int findKey(char* key);
+    void trim(char* sting);
+    FILE* copyToHere(long position);
+    int copyRest(FILE* newFile);
+};
+
+#endif
diff --git a/defines.h b/defines.h
new file mode 100644 (file)
index 0000000..1144743
--- /dev/null
+++ b/defines.h
@@ -0,0 +1,33 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef DEFINES_H
+#define DEFINES_H
+
+typedef unsigned char UCHAR;
+typedef unsigned short USHORT;
+typedef unsigned long ULONG;
+typedef unsigned long long ULLONG;
+
+ULLONG htonll(ULLONG a);
+ULLONG ntohll(ULLONG a);
+
+
+#endif
diff --git a/dsock.c b/dsock.c
new file mode 100644 (file)
index 0000000..77755b4
--- /dev/null
+++ b/dsock.c
@@ -0,0 +1,174 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "dsock.h"
+
+DatagramSocket::DatagramSocket(short port)
+{
+  myPort = port;
+  addrlen = sizeof(struct sockaddr);
+
+  if ((socketnum = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
+  { perror("socket"); exit(1); }
+
+  myAddr.sin_family = AF_INET;         // host byte order
+  myAddr.sin_port = htons(myPort);     // short, network byte order
+  myAddr.sin_addr.s_addr = INADDR_ANY; // auto-fill with my IP
+  memset(&(myAddr.sin_zero), 0, 8);    // zero the rest of the struct
+  if (bind(socketnum, (struct sockaddr *)&myAddr, addrlen) == -1)
+  { perror("bind"); printf(" %s ", strerror(errno)); exit(1); }
+
+  FD_ZERO(&readfds);
+  FD_SET(socketnum, &readfds);
+  tv.tv_sec = 0;
+  tv.tv_usec = 0;
+}
+
+DatagramSocket::~DatagramSocket()
+{
+  close(socketnum);
+}
+
+unsigned char DatagramSocket::waitforMessage(unsigned char how)
+{
+  /* how = 0 - block
+     how = 1 - start new wait
+     how = 2 - continue wait
+  */
+
+  struct timeval* passToSelect = NULL;
+
+
+  if (how == 0)
+  {
+    passToSelect = NULL;
+  }
+  else if (how == 1)
+  {
+    tv.tv_sec = 1;
+    tv.tv_usec = 100000;
+    passToSelect = &tv;
+  }
+  else if (how == 2)
+  {
+    if ((tv.tv_sec == 0) && (tv.tv_usec == 0))  // protection in case timer = 0
+    {
+      tv.tv_sec = 1;
+      tv.tv_usec = 100000;
+    }
+    passToSelect = &tv;
+  }
+  FD_ZERO(&readfds);
+  FD_SET(socketnum, &readfds);
+
+  if (select(socketnum + 1, &readfds, NULL, NULL, passToSelect) <= 0)
+  {  return 1;  }
+
+  if ((mlength = recvfrom(socketnum, buf, MAXBUFLEN, 0,
+      (struct sockaddr *)&theirAddr, &addrlen)) == -1)
+  { perror("recvfrom"); return 0; }
+  else
+  {
+    memset(&buf[mlength], 0, MAXBUFLEN - mlength);
+    strcpy(fromIPA, inet_ntoa(theirAddr.sin_addr));
+    fromPort = ntohs(theirAddr.sin_port);
+
+    if (DSOCKDEBUG)
+    {
+      printf("%s:%i\tIN  %i\t", fromIPA, fromPort, mlength);
+      int k;
+      for(k = 0; k < mlength; k++)
+        printf("%u ", (unsigned char)buf[k]);
+      printf("\n");
+    }
+    return 2;
+  }
+
+  /* Return 0, failure
+     Return 1, nothing happened, timer expired
+     Return 2, packet arrived (timer not expired)
+  */
+}
+
+int DatagramSocket::getDataLength(void) const
+{
+  return mlength;
+}
+
+char *DatagramSocket::getData(void)             {  return buf;  }
+char *DatagramSocket::getFromIPA(void)          {  return fromIPA;  }
+short DatagramSocket::getFromPort(void) const   {  return fromPort; }
+
+void DatagramSocket::send(char *ipa, short port, char *message, int length)
+{
+  if (DSOCKDEBUG)
+  {
+    printf("%s:%i\tOUT %i\t", ipa, port, length);
+    int k;
+    uchar l;
+    for (k = 0; k < length; k++)
+      { l = (uchar)message[k]; printf("%u ", l); }
+  }
+
+  int sentLength = 0;
+
+  theirAddr.sin_family = AF_INET;      // host byte order
+  theirAddr.sin_port = htons(port);    // short, network byte order
+  struct in_addr tad;                  // temp struct tad needed to pass to theirAddr.sin_addr
+  tad.s_addr = inet_addr(ipa);
+  theirAddr.sin_addr = tad;            // address
+  memset(&(theirAddr.sin_zero), 0, 8); // zero the rest of the struct
+
+  unsigned char crypt[MAXBUFLEN];
+  memcpy(crypt, message, length);
+
+  sentLength = sendto(socketnum, crypt, length, 0, (struct sockaddr *)&theirAddr, addrlen);
+  if (sentLength == length)
+  {
+    printf(" GOOD\n");
+  }
+  else
+  {
+    printf(" --BAD--");  fflush(stdout);
+    sentLength = sendto(socketnum, crypt, length, 0, (struct sockaddr *)&theirAddr, addrlen);
+    if (sentLength == length)
+      printf(" GOOD\n");
+    else
+    {
+      printf(" -#-FAILED-#-\n");
+
+      if (DSOCKDEBUG && (sentLength != length))
+      {
+        printf("--------------\n");
+        printf("Sendto failure\n");
+        printf("--------------\n");
+        printf("%s:%i\tOUT %i %i ...\n", ipa, port, length, sentLength);
+        perror("Perror reports");
+        printf("errno value: %d\n", errno);
+        printf("errno translated: %s\n", strerror(errno));
+      //  printf("h_errno value: %d\n", h_errno);
+      //  printf("\nActual address: %s\n", inet_ntoa(tad));
+      //  printf("Actual port: %i\n", ntohs(theirAddr.sin_port));
+        printf("continuing...\n\n");
+      }
+    }
+  }
+}
+
diff --git a/dsock.h b/dsock.h
new file mode 100644 (file)
index 0000000..28ddf5c
--- /dev/null
+++ b/dsock.h
@@ -0,0 +1,65 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef DSOCK_H
+#define DSOCK_H
+
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#define MAXBUFLEN 2000
+const char DSOCKDEBUG = 1;
+typedef unsigned char uchar;
+
+class DatagramSocket
+{
+  public:
+    DatagramSocket(short);             // port
+    ~DatagramSocket();
+    unsigned char waitforMessage(unsigned char); // int =0-block =1-new wait =2-continue wait
+    int getDataLength(void) const;
+    char *getData(void);               // returns a pointer to the data
+    char *getFromIPA(void);            // returns a pointer to from IP address
+    short getFromPort(void) const;
+    void send(char *, short, char *, int); // send wants: IP Address ddn style, port,
+                                           // data, length of data
+  private:
+    int socketnum;                  // Socket descriptor
+    short myPort;                   // My port number
+    struct sockaddr_in myAddr;      // My address
+    struct sockaddr_in theirAddr;   // User address
+    socklen_t addrlen;              // length of sockaddr struct
+    char buf[MAXBUFLEN];            // main data buffer
+    char fromIPA[20];               // from string (ip address)
+    short fromPort;                 // which port user sent on
+    int mlength;                    // length of message
+    struct timeval tv;
+    fd_set readfds;
+};
+
+#endif
diff --git a/libdvbmpeg/DVB.hh b/libdvbmpeg/DVB.hh
new file mode 100644 (file)
index 0000000..e713bee
--- /dev/null
@@ -0,0 +1,446 @@
+#ifndef _DVB_DEV_HH_
+#define _DVB_DEV_HH_
+
+extern "C" {
+#include <asm/errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+#include <time.h>
+#include <unistd.h>
+
+#define NEWSTRUCT
+#include <channel.h>
+}
+
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+using namespace std;
+
+#include <osd.hh>
+#include <devices.hh>
+
+#ifndef MAXNAM
+#define MAXNAM 80
+#endif
+
+
+
+#define FRONT_DVBS 1
+#define FRONT_DVBC 2
+#define FRONT_DVBT 3
+
+#define VTXDIR "/var/vtx"
+
+#define DEC(N) dec << setw(N) << setfill('0') 
+#define HEX(N) hex << setw(N) << setfill('0') 
+
+#define MAXSECSIZE 4096
+
+#define NK 10
+enum {LNB=0,DIS,ROTOR,TRANS,CHAN,BOU,SAT,PICS,SWI,NTW};
+static const int nums[]={LNB,DIS,ROTOR,TRANS,CHAN,BOU,SAT,PICS,SWI,NTW};
+static const int maxs[]={ 32, 32,   32,  512,16384,512,100, 50, 10, 100};
+
+#define MAX_TRANS_CHAN  1024
+
+enum{DVB_ORIG=0, DVB_NOKIA, DVB_XML, DVB_SATCO};
+
+typedef struct frontend_stat_s{
+       fe_status_t status;
+       uint16_t snr;
+       uint16_t strength;
+       uint32_t ber;
+       uint32_t u_blocks;
+} frontend_stat;
+
+
+extern uint8_t hamtab[256];
+extern uint8_t invtab[256];
+
+#define MAX_MAG 8
+typedef struct mag_struct_ {
+        int valid;
+        int magn;
+        uint8_t flags;
+        uint8_t lang;
+        int pnum,sub;
+        uint8_t pagebuf[25*40];
+} magazin_t;
+
+
+class DVB {
+public:
+       int no_open;
+       int fd_frontend;
+       int fd_demuxa;
+       int fd_demuxv;
+       int fd_demuxpcr;
+       int fd_demuxtt;
+        int fdvb;
+
+       int minor;
+       int adapter;
+       int max_tpid;
+       int max_satid;
+       int max_chanid;
+       
+       frontend_stat festat;
+
+       struct dvb_diseqc_master_cmd dcmd;
+       fe_sec_tone_mode_t tone;
+       fe_sec_voltage_t voltage;
+        int burst;
+       struct dmx_pes_filter_params pesFilterParamsV; 
+       struct dmx_pes_filter_params pesFilterParamsA; 
+       struct dmx_pes_filter_params pesFilterParamsP; 
+       struct dmx_pes_filter_params pesFilterParamsTT; 
+       struct dvb_frontend_parameters front_param;
+        int front_type;
+       int dvr_enabled;
+        OSD osd;
+       uint32_t transponder_freq;
+       char transponder_pol;
+       uint32_t transponder_srate;
+
+
+
+       fe_status_t status;
+       uint32_t ber, uncorrected_blocks;
+       uint16_t snr, signal;
+
+
+        struct Lnb *lnbs;
+        struct DiSEqC *diseqcs;
+        struct Rotor *rotors;
+        struct Transponder *tps;
+        struct Channel *chans;
+        struct Bouquet *bouqs;
+        struct Sat *sats;
+        struct Picture *pics;
+        struct Switch *swis;
+        struct Network *ntws;
+        int num[NK];
+       int oldsec;
+       int tryit;
+       int oldpol;
+
+       char *vtxdir;
+       magazin_t magazin[MAX_MAG]; 
+
+       DVB(){
+               no_open = 0;
+               max_tpid = 0;
+               max_satid = 0;
+               max_chanid = 0;
+               minor = 0;
+
+               fd_frontend = -1;
+               fd_demuxa = -1;
+               fd_demuxpcr = -1;
+               fd_demuxv = -1;
+               fd_demuxtt = -1;
+               fdvb = -1;
+               vtxdir = NULL;
+               transponder_freq=0;
+               transponder_pol=0;
+               transponder_srate=0;
+       }
+
+       DVB(int i){
+               if (i >= 0) 
+                       no_open = 0;
+               else 
+                       no_open = 1;
+               max_tpid = 0;
+               max_satid = 0;
+               max_chanid = 0;
+       
+               fd_frontend = -1;
+               fd_demuxa = -1;
+               fd_demuxpcr = -1;
+               fd_demuxv = -1;
+               fd_demuxtt = -1;
+               fdvb = -1;
+               vtxdir = NULL;
+               transponder_freq=0;
+               transponder_pol=0;
+               transponder_srate=0;
+
+               init("","",i);
+       }
+
+        DVB(char *a, char *b) {
+               max_tpid = 0;
+               max_satid = 0;
+               max_chanid = 0;
+       
+               fd_frontend = -1;
+               fd_demuxa = -1;
+               fd_demuxpcr = -1;
+               fd_demuxv = -1;
+               fd_demuxtt = -1;
+
+               fdvb = -1;
+               vtxdir = NULL;
+               init(a,b,0);
+       }
+
+       ~DVB();
+  
+       void use_osd(int fd = -1){
+               char dvn[32];
+               if (no_open) return;
+               if (fd < 0) fd = 0;
+               sprintf(dvn,OSD_DEV,adapter,fd);
+               fdvb = open(dvn, O_RDWR);
+               
+               if (fdvb >= 0){
+                       cerr << dvn <<  " for OSD" << endl;
+                       osd.init(fdvb);
+               } else perror("osd");
+               osd.Open(80, 500, 640, 540, 2, 0, 2);
+               osd.SetColor(0, 0, 0, 0, 255);
+               osd.SetColor(1, 240, 240, 240, 255);
+               osd.Show();
+       }
+
+       void set_vtxdir(char *newname){
+               if (!newname) return;
+               if (vtxdir) free(vtxdir);
+               vtxdir = (char *) malloc(sizeof(char)*(strlen(newname)+1));
+               if (vtxdir)
+                       strncpy(vtxdir, newname, strlen(newname));
+       }
+
+       void close_osd(){
+               osd.Close(fdvb);
+               close(fdvb);
+       }
+  
+       int DVR_enabled(){
+               if (no_open) return -1;
+               return dvr_enabled;
+       }
+
+       void enable_DVR(){
+               if (no_open) return;
+               dvr_enabled = 1;
+       }
+
+       void enable_DVR_other(){
+               if (no_open) return;
+               dvr_enabled = 2;
+       }
+
+       void disable_DVR(){
+               if (no_open) return;
+               dvr_enabled = 0;
+       }
+
+        void init(char *a="/dev/video0", char *b="/dev/vbi0",int adapt=0,
+                 int minor = 0); 
+                 
+
+       inline void init(char *a, char *b){
+               if (no_open) return;
+               init(a,b,0,0);
+       }
+
+       int check_frontend();
+
+       void set_apid(ushort apid);
+       void set_vpid(ushort vpid); 
+       void set_pcrpid(ushort vpid); 
+       void set_ttpid(ushort ttpid); 
+        int set_apid_fd(ushort apid, int fd);
+        int set_vpid_fd(ushort vpid, int fd);
+        int set_ttpid_fd(ushort ttpid, int fd);
+        int set_pcrpid_fd(ushort pcrpid, int fd);
+        int set_otherpid_fd(ushort otherpid, int fd);
+
+
+        int set_lnb(int dis);
+       void set_diseqc_nb(int nr); 
+       int set_front(void); 
+       void get_front(void); 
+
+       void scan_pf_eit(int chnr,
+                        int (*callback)(uint8_t *data, int l, int pnr, 
+                                         int c_n, uint8_t *t));
+
+       void scan_pf_eit(Channel *chan, 
+                        int (*callback)(uint8_t *data, int l, int pnr, 
+                                         int c_n, uint8_t *t));
+       void scan_pf_eit(int chnr);
+
+
+       int search_in_TP(Transponder &tp, int show=1, int verbose=0);
+       int search_in_TP(uint16_t tpid, uint16_t satid, int show=1,
+                        int verbose=0);
+       int scan_TP(uint16_t tpid, uint16_t satid, int timeout=-1, int verbose=0);
+
+       int GetSection(uint8_t *buf, 
+                      uint16_t PID, uint8_t TID, uint16_t TIDExt, 
+                      uint16_t FilterTIDExt, 
+                      uint8_t secnum, uint8_t &msecnum);
+       int GetSection(uint8_t *buf, 
+                      uint16_t PID, uint8_t *filter, uint8_t *mask,
+                      uint8_t secnum, uint8_t &msecnum); 
+       int GetSection(uint8_t *buf, ushort PID, uint8_t sec,
+                      uint8_t secnum, uint8_t &msecnum); 
+       int SetFilter(uint16_t pid, uint8_t *filter, 
+                     uint8_t *mask,
+                     uint32_t timeout, uint32_t flags); 
+       uint16_t SetFilter(uint16_t pid, uint16_t section, uint16_t mode); 
+       int CloseFilter(int h);
+       
+
+       void bar2(int x, int y, int w, int h, int val, int col1, int col2);
+
+        int SetTP(unsigned int, unsigned int);
+        int scan(void);
+        int scan_all_tps(void);
+        int scan_lnb(struct Lnb &);
+        int scan_cable(Sat &sat);
+        int scan_sat(struct Sat &);
+        int scan_tp(struct Transponder &);
+
+        int AddLNB(int id, int t, uint l1, uint l2, uint sl,
+                  int dnr, int dis, int sw);
+       int AddSat(Sat &sat);
+        int AddSat(int satid, unsigned int lnbid, char *name, uint fmin, uint fmax);
+        int AddTP(Transponder &tp);
+        int AddChannel(Channel &chan);
+       int parse_descriptor(Channel *chan, uint8_t *data, int length);
+       int parse_pmt(Channel *chan, uint8_t *data);
+       int parse_pat(Channel *chan, uint8_t *data);
+
+       int check_pids(Channel *chan);
+       void check_all_pids();
+       void scan_sdt(Channel *chan);
+       int scan_sdts(int *chs, int n);
+
+        int channel_num(void) {
+               return num[CHAN];
+       };
+         
+        int channel_change(int n) {
+               return 0;
+       };
+        int SetChannel(uint16_t, uint16_t, uint16_t, uint16_t);
+       int SetChannel(Channel *chan,  char* apref=NULL, uint16_t *apidp=NULL, 
+                      uint16_t *vpidp=NULL) ;
+        int SetChannel(int chnr, char *apref=NULL, uint16_t *apidp=NULL, 
+                      uint16_t *vpidp=NULL);
+        int GetChannel(int chnr, struct channel *);
+        int NumChannel(void) {
+               return num[CHAN];
+       }
+       int tune_it(struct dvb_frontend_parameters *qpsk);
+       void find_satid(Channel &chan);
+       int check_input_format(istream &ins);
+       void read_original(istream &ins);
+       int get_all_progs(uint16_t *progbuf, uint16_t *pnrbuf, int length);
+       uint16_t find_pnr(uint16_t vpid, uint16_t apid);
+       int get_pids(uint16_t prog_pid, uint16_t *vpid, uint16_t *apids, 
+                    uint16_t *ttpid, uint8_t *apids_name=NULL);
+       void AddECM(Channel *chan, uint8_t *data, int length);
+       int check_ecm(Channel *chan);
+       void add_vtx_line(magazin_t *mag, int line, uint8_t *data, int pnr);
+       
+        friend ostream &operator<<(ostream &stream, DVB &x);
+        friend istream &operator>>(istream &stream, DVB &x);
+
+};
+
+#define NOKIA_MAX_SAT 4
+class nokiaconv{
+public:
+       DVB *dvb;
+       struct lnb_sat_l{
+               int n;
+               int diseqc[NOKIA_MAX_SAT];
+               char sat_names[NOKIA_MAX_SAT][MAXNAM+1];
+               int satid[NOKIA_MAX_SAT];
+       } lnb_sat;
+
+       nokiaconv(DVB *d){
+               dvb = d;
+       }
+
+        friend istream &operator>>(istream &stream, nokiaconv &x);
+};
+
+#define XML_MAX_SAT 4
+class xmlconv{
+public:
+       DVB *dvb;
+       struct lnb_sat_l{
+               int n;
+               int diseqc[XML_MAX_SAT];
+               char sat_names[XML_MAX_SAT][MAXNAM+1];
+               int satid[XML_MAX_SAT];
+       } lnb_sat;
+
+       xmlconv(DVB *d){
+               dvb = d;
+       }
+       int read_stream(istream &ins, int nchan);
+       int read_desc(istream &ins, int nchan);
+       int read_serv(istream &ins, int ctp, int csat);
+       int read_trans(istream &ins, int satid);
+       int read_sat(istream &ins, int satid = -1);
+       int skip_tag(istream &ins, char *tag);
+       int read_iso639(istream &ins, int nchan, int apids);
+
+        friend istream &operator>>(istream &stream, xmlconv &x);
+};
+
+
+
+#define SATCO_MAX_SAT 10
+class satcoconv{
+public:
+       DVB *dvb;
+       int nlnb;
+
+       satcoconv(DVB *d){
+               dvb = d;
+       }
+
+        friend istream &operator>>(istream &stream, satcoconv &x);
+};
+
+void hdump(uint8_t *buf, int n);
+int get_dvbrc(char *path, DVB &dv, int dev, int len);
+int set_dvbrc(char *path, DVB &dv, int dev, int len);
+void dvb2txt(char *out, char *in, int len);
+int set_sfront(int fdf, uint32_t freq, uint32_t pol, uint32_t sr , int snum, fe_code_rate_t fec);
+void set_pes_filt(int fd,uint16_t pes_pid);
+void set_diseqc(int fdf, int snum, fe_sec_voltage_t v, fe_sec_tone_mode_t t);
+int tune(int fdf, uint32_t freq, uint32_t sr, fe_code_rate_t fec);
+int set_sfront(int fdf, uint32_t freq, uint32_t pol, uint32_t sr , int snum, 
+              fe_code_rate_t fec);
+
+
+struct in_addr getaddress (const char *name);
+int tcp_client_connect(const char *hostname, int sckt);
+int udp_client_connect(const char *filename);
+void client_send_msg(int fd, uint8_t *msg, int size);
+int chck_frontend (int fefd, frontend_stat *festat);
+
+uint8_t deham(uint8_t x, uint8_t y);
+
+#endif
diff --git a/libdvbmpeg/Makefile b/libdvbmpeg/Makefile
new file mode 100644 (file)
index 0000000..a56cb6b
--- /dev/null
@@ -0,0 +1,33 @@
+INCS   = -I.
+CFLAGS =  -g -Wall -O2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
+MFLAG  = -M
+OBJS = ctools.o ringbuffy.o remux.o transform.o cpptools.o
+SRC  = $(wildcard *.c)
+CPPSRC = $(wildcard *.cpp)
+CSRC = $(wildcard *.cc) 
+
+DESTDIR = /usr/local
+
+.PHONY: depend clean install uninstall
+
+clean:
+       - rm -f *.o  *~ *.a .depend
+
+libdvbmpegtools.a: $(OBJS)
+       ar -rcs libdvbmpegtools.a $(OBJS) 
+
+%.o:    %.cc 
+       $(CXX) -c $(CFLAGS) $(INCS) $(DEFINES) $<
+
+%.o:    %.cpp
+       $(CXX) -c $(CFLAGS) $(INCS) $(DEFINES) $<
+
+%.o:    %.c 
+       $(CC) -c $(CFLAGS) $(INCS) $(DEFINES) $<
+
+.depend: 
+       $(CXX) $(DEFINES) $(MFLAG) $(SRC) $(CSRC) $(CPPSRC) $(INCS)> .depend
+
+
+
+-include .depend
diff --git a/libdvbmpeg/OSD.h b/libdvbmpeg/OSD.h
new file mode 100644 (file)
index 0000000..385ac78
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef _OSD_H_
+#define _OSD_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif  /* __cplusplus */
+int OSDClose(int dev);
+int OSDOpen(int dev, int x0, int y0, int x1, int y1, int BitPerPixel, int mix);
+int OSDShow(int dev);
+int OSDHide(int dev); 
+int OSDClear(int dev); 
+int OSDFill(int dev, int color); 
+int OSDSetColor(int dev, int color, int r, int g, int b, int op);
+int OSDText(int dev, int x, int y, int size, int color, const char *text);
+int OSDSetPalette(int dev, int first, int last, unsigned char *data);
+int OSDSetTrans(int dev, int trans);
+int OSDSetPixel(int dev, int x, int y, unsigned int color);
+int OSDGetPixel(int dev, int x, int y);
+int OSDSetRow(int dev, int x, int y, int x1, unsigned char *data);
+int OSDSetBlock(int dev, int x, int y, int x1, int y1, int inc, unsigned char *data);
+int OSDFillRow(int dev, int x, int y, int x1, int color);
+int OSDFillBlock(int dev, int x, int y, int x1, int y1, int color);
+int OSDLine(int dev, int x, int y, int x1, int y1, int color);
+int OSDQuery(int dev);
+int OSDSetWindow(int dev, int win);
+int OSDMoveWindow(int dev, int x, int y);
+#ifdef __cplusplus
+}
+#endif  /* __cplusplus */
+#endif
diff --git a/libdvbmpeg/channel.h b/libdvbmpeg/channel.h
new file mode 100644 (file)
index 0000000..c4f62b4
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef _CHANNEL_H
+#define _CHANNEL_H
+
+#include <sys/types.h>
+
+struct channel {
+        int id;
+        char name[81];
+        int type;
+        ushort pnr;
+        ushort vpid;
+        ushort apids[8];
+        ushort apidnum;
+        ushort ac3pid;
+        ushort pcrpid;
+        
+        uint freq;
+        int pol;
+        int qam;
+        uint srate;
+        int fec;
+};
+
+#ifdef NEWSTRUCT
+
+#include <linux/dvb/dmx.h>
+#include <linux/dvb/frontend.h>
+#include <linux/dvb/video.h>
+#include <linux/dvb/audio.h>
+
+#define DVR_DEV   "/dev/dvb/adapter%d/dvr%d"     
+#define VIDEO_DEV "/dev/dvb/adapter%d/video%d"
+#define AUDIO_DEV "/dev/dvb/adapter%d/audio%d"
+#define DEMUX_DEV "/dev/dvb/adapter%d/demux%d"
+#define FRONT_DEV "/dev/dvb/adapter%d/frontend%d"
+#define OSD_DEV   "/dev/dvb/adapter%d/osd%d"
+#define CA_DEV    "/dev/dvb/adapter%d/ca%d"
+
+#else
+
+#include <ost/dmx.h>
+#include <ost/frontend.h>
+#include <ost/sec.h>
+#include <ost/video.h>
+#include <ost/audio.h>
+
+#define DVR_DEV   "/dev/ost/dvr%d"
+#define VIDEO_DEV "/dev/ost/video%d"
+#define AUDIO_DEV "/dev/ost/audio%d"
+#define DEMUX_DEV "/dev/ost/demux%d"
+#define FRONT_DEV "/dev/ost/frontend%d"
+#define OSD_DEV   "/dev/ost/osd%d"
+#define CA_DEV   "/dev/ost/ca%d"
+
+#endif
+
+
+#endif
diff --git a/libdvbmpeg/ci.hh b/libdvbmpeg/ci.hh
new file mode 100644 (file)
index 0000000..77e7684
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * ci.hh: Common Interface
+ *
+ * Copyright (C) 2000 Klaus Schmidinger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ * The author can be reached at kls@cadsoft.de
+ *
+ * The project's page is at http://www.cadsoft.de/people/kls/vdr
+ *
+ */
+
+#ifndef __CI_H
+#define __CI_H
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+
+#define MAXCASYSTEMIDS 16
+
+class cMutex {
+  friend class cCondVar;
+private:
+  pthread_mutex_t mutex;
+  pid_t lockingPid;
+  int locked;
+public:
+  cMutex(void);
+  ~cMutex();
+  void Lock(void);
+  void Unlock(void);
+  };
+
+class cMutexLock {
+private:
+  cMutex *mutex;
+  bool locked;
+public:
+  cMutexLock(cMutex *Mutex = NULL);
+  ~cMutexLock();
+  bool Lock(cMutex *Mutex);
+  };
+
+
+class cCiMMI;
+
+class cCiMenu {
+  friend class cCiMMI;
+private:
+  enum { MAX_CIMENU_ENTRIES = 64 }; ///< XXX is there a specified maximum?
+  cCiMMI *mmi;
+  bool selectable;
+  char *titleText;
+  char *subTitleText;
+  char *bottomText;
+  char *entries[MAX_CIMENU_ENTRIES];
+  int numEntries;
+  bool AddEntry(char *s);
+  cCiMenu(cCiMMI *MMI, bool Selectable);
+public:
+  ~cCiMenu();
+  const char *TitleText(void) { return titleText; }
+  const char *SubTitleText(void) { return subTitleText; }
+  const char *BottomText(void) { return bottomText; }
+  const char *Entry(int n) { return n < numEntries ? entries[n] : NULL; }
+  int NumEntries(void) { return numEntries; }
+  bool Selectable(void) { return selectable; }
+  bool Select(int Index);
+  bool Cancel(void);
+  };
+
+class cCiEnquiry {
+  friend class cCiMMI;
+private:
+  cCiMMI *mmi;
+  char *text;
+  bool blind;
+  int expectedLength;
+  cCiEnquiry(cCiMMI *MMI);
+public:
+  ~cCiEnquiry();
+  const char *Text(void) { return text; }
+  bool Blind(void) { return blind; }
+  int ExpectedLength(void) { return expectedLength; }
+  bool Reply(const char *s);
+  bool Cancel(void);
+  };
+
+class cCiCaPmt {
+  friend class cCiConditionalAccessSupport;
+private:
+  int length;
+  int esInfoLengthPos;
+  uint8_t capmt[2048]; ///< XXX is there a specified maximum?
+public:
+  cCiCaPmt(int ProgramNumber);
+  void AddPid(int Pid);
+  void AddCaDescriptor(int Length, uint8_t *Data);
+  };
+
+#define MAX_CI_SESSION  16 //XXX
+
+class cCiSession;
+class cCiTransportLayer;
+class cCiTransportConnection;
+
+class cCiHandler {
+private:
+  cMutex mutex;
+  int numSlots;
+  bool newCaSupport;
+  bool hasUserIO;
+  cCiSession *sessions[MAX_CI_SESSION];
+  cCiTransportLayer *tpl;
+  cCiTransportConnection *tc;
+  int ResourceIdToInt(const uint8_t *Data);
+  bool Send(uint8_t Tag, int SessionId, int ResourceId = 0, int Status = -1);
+  cCiSession *GetSessionBySessionId(int SessionId);
+  cCiSession *GetSessionByResourceId(int ResourceId, int Slot);
+  cCiSession *CreateSession(int ResourceId);
+  bool OpenSession(int Length, const uint8_t *Data);
+  bool CloseSession(int SessionId);
+  int CloseAllSessions(int Slot);
+  cCiHandler(int Fd, int NumSlots);
+public:
+  ~cCiHandler();
+  static cCiHandler *CreateCiHandler(const char *FileName);
+  int NumSlots(void) { return numSlots; }
+  bool Process(void);
+  bool HasUserIO(void) { return hasUserIO; }
+  bool EnterMenu(int Slot);
+  cCiMenu *GetMenu(void);
+  cCiEnquiry *GetEnquiry(void);
+  bool SetCaPmt(cCiCaPmt &CaPmt);
+  const unsigned short *GetCaSystemIds(int Slot);
+  bool SetCaPmt(cCiCaPmt &CaPmt, int Slot);
+  bool Reset(int Slot);
+  };
+
+int tcp_listen(struct sockaddr_in *name,int sckt,unsigned long address=INADDR_ANY);
+int accept_tcp(int ip_sock,struct sockaddr_in *ip_name);
+int udp_listen(struct sockaddr_un *name,char const * const filename);
+int accept_udp(int ip_sock,struct sockaddr_un *ip_name);
+
+#endif //__CI_H
diff --git a/libdvbmpeg/cpptools.cc b/libdvbmpeg/cpptools.cc
new file mode 100644 (file)
index 0000000..91808cc
--- /dev/null
@@ -0,0 +1,946 @@
+/*
+ *  dvb-mpegtools for the Siemens Fujitsu DVB PCI card
+ *
+ * Copyright (C) 2000, 2001 Marcus Metzler 
+ *            for convergence integrated media GmbH
+ * Copyright (C) 2002  Marcus Metzler 
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ * 
+
+ * The author can be reached at mocm@metzlerbros.de
+ */
+
+#include "cpptools.hh"
+
+#define HEX(N) "0x" << hex << setw(2) << setfill('0') \
+<< int(N) << " " << dec
+#define HHEX(N,M) "0x" << hex << setw(M) << setfill('0') \
+<< int(N) << " " << dec
+#define LHEX(N,M) "0x" << hex << setw(M) << setfill('0') \
+<< long(N) << " " << dec
+
+#define MAX_SEARCH 1024 * 1024
+
+ostream & operator << (ostream & stream, PES_Packet & x){
+  
+       if (x.info){
+               cerr << "PES Packet: " ;
+               switch ( x.p.stream_id ) {
+                               
+               case PROG_STREAM_MAP:
+                       cerr << "Program Stream Map";
+                       break;
+               case PRIVATE_STREAM2:
+                       cerr << "Private Stream 2";
+                       break;
+               case PROG_STREAM_DIR:
+                       cerr << "Program Stream Directory";
+                       break;
+               case ECM_STREAM     :
+                       cerr << "ECM Stream";
+                       break;
+               case EMM_STREAM     :
+                       cerr << "EMM Stream";
+                       break;
+               case PADDING_STREAM :
+                       cerr << "Padding Stream";
+                       break;
+               case DSM_CC_STREAM  :
+                       cerr << "DSM Stream";
+                       break;
+               case ISO13522_STREAM:
+                       cerr << "ISO13522 Stream";
+                       break;
+               case PRIVATE_STREAM1:
+                       cerr << "Private Stream 1";
+                       break;
+               case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+                       cerr << "Audio Stream " << HEX(x.p.stream_id);
+                       break;
+               case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+                       cerr << "Video Stream " << HEX(x.p.stream_id);
+                       break;
+                       
+               }
+               cerr << " MPEG" << x.p.mpeg << endl;
+               if ( x.p.mpeg == 2 ){
+                       cerr << "    FLAGS: ";
+
+                       if (x.p.flags1 & SCRAMBLE_FLAGS){
+                               cerr << " SCRAMBLE(";
+                               cerr << ((x.p.flags1 & SCRAMBLE_FLAGS)>>4);
+                               cerr << ")";
+                       }
+                       if (x.p.flags1 & PRIORITY_FLAG) 
+                               cerr << " PRIORITY";    
+                       if (x.p.flags1 & DATA_ALIGN_FLAG)
+                               cerr << " DATA_ALIGN";  
+                       if (x.p.flags1 & COPYRIGHT_FLAG) 
+                               cerr << " COPYRIGHT";   
+                       if (x.p.flags1 & ORIGINAL_FLAG) 
+                               cerr << " ORIGINAL";   
+
+                       if (x.p.flags2 & PTS_DTS_FLAGS){
+                               cerr << " PTS_DTS(";
+                               cerr << ((x.p.flags2 & PTS_DTS_FLAGS)>>6);
+                               cerr << ")";
+                       }
+                       if (x.p.flags2 & ESCR_FLAG) 
+                               cerr << " ESCR";
+                       if (x.p.flags2 & ES_RATE_FLAG)
+                               cerr << " ES_RATE";   
+                       if (x.p.flags2 & DSM_TRICK_FLAG)
+                               cerr << " DSM_TRICK";   
+                       if (x.p.flags2 & ADD_CPY_FLAG)
+                               cerr << " ADD_CPY";     
+                       if (x.p.flags2 & PES_CRC_FLAG) 
+                               cerr << " CRC";     
+                       if (x.p.flags2 & PES_EXT_FLAG)
+                               cerr << " EXT";     
+
+                       cerr << endl;
+
+                       if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_ONLY)
+                               cerr << "   PTS: " 
+                                    << LHEX(ntohl(x.WPTS()),8)
+                                    << "(h" << int(x.high_pts()) << ")"
+                                    << endl; 
+                       else if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_DTS){
+                               cerr << "   PTS: " 
+                                    << LHEX(ntohl(x.WPTS()),8)
+                                    << "(h" << int(x.high_pts()) << ")";
+                               cerr << "   DTS: " 
+                                    << LHEX(ntohl(x.WDTS()),8)
+                                    << "(h" << int(x.high_dts()) << ")"
+                                    << endl; 
+                       }
+/*                     
+                       if (x.p.flags2 & ESCR_FLAG)
+
+                       
+                       if (x.p.flags2 & ES_RATE_FLAG)
+
+                       
+                       if (x.p.flags2 & DSM_TRICK_FLAG)
+
+                       
+                       if (x.p.flags2 & ADD_CPY_FLAG)
+
+                       
+                       if (x.p.flags2 & PES_CRC_FLAG)
+
+                       
+                       if (x.p.flags2 & PES_EXT_FLAG){
+                               
+                               if (x.p.priv_flags & PRIVATE_DATA)
+                                       stream.write(x.p.pes_priv_data,16);
+                               
+                               if (x.p.priv_flags & HEADER_FIELD){
+                                       stream.write(&x.p.pack_field_length,1);
+                                       x.p.pack_header = new 
+                                               uint8_t[x.p.pack_field_length];
+                                       stream.write(x.p.pack_header,
+                                                    x.p.pack_field_length);
+                               }
+                               
+                               if ( x.p.priv_flags & PACK_SEQ_CTR){
+                                       stream.write(&x.p.pck_sqnc_cntr,1);
+                                       stream.write(&x.p.org_stuff_length,1);
+                               }
+                               
+                               if ( x.p.priv_flags & P_STD_BUFFER)
+                                       stream.write(x.p.p_std,2);
+                               
+                               if ( x.p.priv_flags & PES_EXT_FLAG2){
+                                       stream.write(&x.p.pes_ext_lngth,1);
+                                       x.p.pes_ext = new 
+                                               uint8_t[x.p.pes_ext_lngth];
+                                       stream.write(x.p.pes_ext,
+                                                    x.p.pes_ext_lngth);
+                               }
+                       }
+               } else {
+                       if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_ONLY)
+                               stream.write(x.p.pts,5);
+                       else if ((x.p.flags2 & PTS_DTS_FLAGS) == 
+                                PTS_DTS){
+                               stream.write(x.p.pts,5);
+                               stream.write(x.p.dts,5);
+                       }
+*/     
+               }                       
+               cerr << endl << endl;
+               return stream;
+       }
+
+       int l = x.p.length+x.p.pes_hlength+9;
+       uint8_t buf[l];
+       int length = cwrite_pes(buf,&(x.p),l);
+       stream.write((char *)buf,length);
+       
+       return stream;
+}
+
+static unsigned int find_length(istream & stream){
+       streampos p = 0;
+       streampos start = 0;
+       streampos q = 0;
+       int found = 0;
+       uint8_t sync4[4];
+
+       start = stream.tellg();
+       start -=2;
+       stream.seekg(start);
+       while ( !stream.eof() && !found ){
+               p = stream.tellg();
+               stream.read((char *)&sync4,4);
+               if (sync4[0] == 0x00 && sync4[1] == 0x00 && sync4[2] == 0x01) {
+                       switch ( sync4[3] ) {
+                               
+                       case PROG_STREAM_MAP:
+                       case PRIVATE_STREAM2:
+                       case PROG_STREAM_DIR:
+                       case ECM_STREAM     :
+                       case EMM_STREAM     :
+                       case PADDING_STREAM :
+                       case DSM_CC_STREAM  :
+                       case ISO13522_STREAM:
+                       case PRIVATE_STREAM1:
+                       case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+                       case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+                               found = 1;
+                               break;
+                       default:
+                               q = stream.tellg();
+                               break;
+                       }       
+               } 
+       }
+       q = stream.tellg();
+       stream.seekg(streampos(2)+start);
+       if (found) return (unsigned int)(q-start)-4-2;
+       else return (unsigned int)(q-start)-2;
+       
+}
+
+istream & operator >> (istream & stream, PES_Packet & x){
+       
+       uint8_t sync4[4];
+       int found=0;
+       int done=0;
+       streampos p = 0;
+       
+       while (!stream.eof() && !found) {
+               p = stream.tellg();
+               stream.read((char *)&sync4,4);
+               if (sync4[0] == 0x00 && sync4[1] == 0x00 && sync4[2] == 0x01) {
+                       x.p.stream_id = sync4[3];
+
+                       switch ( sync4[3] ) {
+                               
+                       case PROG_STREAM_MAP:
+                       case PRIVATE_STREAM2:
+                       case PROG_STREAM_DIR:
+                       case ECM_STREAM     :
+                       case EMM_STREAM     :
+                               found = 1;
+                               stream.read((char *)x.p.llength,2);
+                               x.setlength();
+                               if (!x.p.length){ 
+                                       x.p.length = find_length(stream);
+                                       x.Nlength();
+                               }
+                               stream.read((char *)x.p.pes_pckt_data,x.p.length);
+                               done = 1;
+                               break;
+                       case PADDING_STREAM :
+                               found = 1;
+                               stream.read((char *)x.p.llength,2);
+                               x.setlength();
+                               if (!x.p.length){ 
+                                       x.p.length = find_length(stream);
+                                       x.Nlength();
+                               }
+                               x.p.padding = x.p.length;
+                               stream.read((char *)x.p.pes_pckt_data,x.p.length);
+                               done = 1;
+                               break;
+                               
+                       case DSM_CC_STREAM  :
+                       case ISO13522_STREAM:
+                       case PRIVATE_STREAM1:
+                       case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+                       case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+                               stream.read((char *)x.p.llength,2);
+                               x.setlength();
+                               if (!x.p.length){ 
+                                       x.p.length = find_length(stream);
+                                       x.Nlength();
+                               }
+                               found = 1;
+                               break;
+                               
+                       default:
+                               stream.seekg(p+streampos(1));
+                       break;
+                       }       
+               } else stream.seekg(p+streampos(1));
+       }
+       
+       if ( found && !done) {
+               p = stream.tellg();
+               stream.read((char *)&x.p.flags1,1);
+               if ( (x.p.flags1 & 0xC0) == 0x80 )
+                       x.p.mpeg = 2;
+               else
+                       x.p.mpeg = 1;
+               if ( x.p.mpeg == 2 ){
+                       stream.read((char *)&x.p.flags2,1);
+                       stream.read((char *)&x.p.pes_hlength,1);
+                       
+                       if ((int)x.p.length > x.p.pes_hlength+3)
+                               x.p.length -=x.p.pes_hlength+3;
+                       else 
+                               return stream;
+
+                       uint8_t count = x.p.pes_hlength;
+
+                       if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_ONLY){
+                               stream.read((char *)x.p.pts,5);
+                               count -=5;
+                       } else 
+                               if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_DTS){
+                                       stream.read((char *)x.p.pts,5);
+                                       stream.read((char *)x.p.dts,5);
+                                       count -= 10;
+                               }
+
+                       if (x.p.flags2 & ESCR_FLAG){
+                               stream.read((char *)x.p.escr,6);
+                               count -= 6;
+                       }
+
+                       if (x.p.flags2 & ES_RATE_FLAG){
+                               stream.read((char *)x.p.es_rate,3);
+                               count -= 6;
+                       }
+
+                       if (x.p.flags2 & DSM_TRICK_FLAG){
+                               stream.read((char *)&x.p.trick,1);
+                               count -= 1;
+                       }
+
+                       if (x.p.flags2 & ADD_CPY_FLAG){
+                               stream.read((char *)&x.p.add_cpy,1);
+                               count -= 1;
+                       }
+
+                       if (x.p.flags2 & PES_CRC_FLAG){
+                               stream.read((char *)x.p.prev_pes_crc,2);
+                               count -= 2;
+                       }                       
+
+                       if (x.p.flags2 & PES_EXT_FLAG){
+                               stream.read((char *)&x.p.priv_flags,1);
+                               count -= 1;
+                               
+                               if (x.p.priv_flags & PRIVATE_DATA){
+                                       stream.read((char *)x.p.pes_priv_data,16);
+                                       count -= 16;
+                               }
+
+                               if (x.p.priv_flags & HEADER_FIELD){
+                                       stream.read((char *)&x.p.pack_field_length,1);
+                                       x.p.pack_header = new 
+                                               uint8_t[x.p.pack_field_length];
+                                       stream.read((char *)x.p.pack_header,
+                                                   x.p.pack_field_length);
+                                       count -= 1+x.p.pack_field_length;
+                               }
+                               
+                               if ( x.p.priv_flags & PACK_SEQ_CTR){
+                                       stream.read((char *)&x.p.pck_sqnc_cntr,1);
+                                       stream.read((char *)&x.p.org_stuff_length,1);
+                                       count -= 2;
+                               }
+
+                               if ( x.p.priv_flags & P_STD_BUFFER){
+                                       stream.read((char *)x.p.p_std,2);
+                                       count -= 2;
+                               }
+
+                               if ( x.p.priv_flags & PES_EXT_FLAG2){
+                                       stream.read((char *)&x.p.pes_ext_lngth,1);
+                                       x.p.pes_ext = new 
+                                               uint8_t[x.p.pes_ext_lngth];
+                                       stream.read((char *)x.p.pes_ext,
+                                                   x.p.pes_ext_lngth);
+                                       count -= 1+x.p.pes_ext_lngth;
+                               }
+                       }
+                       x.p.stuffing = count;
+                       uint8_t dummy;
+                       for(int i = 0; i< count ;i++) 
+                               stream.read((char *)&dummy,1);
+                       
+               } else {
+                       uint8_t check;
+                       x.p.mpeg1_pad = 1;
+                       check = x.p.flags1;
+                       while (check == 0xFF){
+                               stream.read((char *)&check,1);
+                               x.p.mpeg1_pad++;
+                       }
+                   
+                       if ( (check & 0xC0) == 0x40){
+                               stream.read((char *)&check,1);
+                               x.p.mpeg1_pad++;
+                               stream.read((char *)&check,1);
+                               x.p.mpeg1_pad++;
+                       }
+                       x.p.flags2 = 0;
+                       x.p.length -= x.p.mpeg1_pad;
+
+                       stream.seekg(p);
+                       if ( (check & 0x30)){
+                               x.p.length ++;
+                               x.p.mpeg1_pad --;
+
+                               if (check == x.p.flags1){
+                                       x.p.pes_hlength = 0;
+                               } else {
+                                       x.p.mpeg1_headr = 
+                                               new uint8_t[x.p.mpeg1_pad];
+                                       x.p.pes_hlength = x.p.mpeg1_pad;
+                                       stream.read((char *)x.p.mpeg1_headr,
+                                                   x.p.mpeg1_pad);
+                               }
+
+                               x.p.flags2 = (check & 0xF0) << 2;
+                               if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_ONLY){
+                                       stream.read((char *)x.p.pts,5);
+                                       x.p.length -= 5;
+                                       x.p.pes_hlength += 5;
+                               }
+                               else if ((x.p.flags2 & PTS_DTS_FLAGS) == 
+                                        PTS_DTS){
+                                       stream.read((char *)x.p.pts,5);
+                                       stream.read((char *)x.p.dts,5);
+                                       x.p.length -= 10;
+                                       x.p.pes_hlength += 10;
+                               }
+                       } else {
+                               x.p.mpeg1_headr = new uint8_t[x.p.mpeg1_pad];
+                               x.p.pes_hlength = x.p.mpeg1_pad;
+                               stream.read((char *)x.p.mpeg1_headr,x.p.mpeg1_pad);
+                       }
+               }
+               stream.read((char *)x.p.pes_pckt_data,x.p.length);
+       }
+       return stream;
+}
+
+ostream & operator << (ostream & stream, TS_Packet & x){
+
+       uint8_t buf[TS_SIZE];
+       int length = cwrite_ts(buf,&(x.p),TS_SIZE);
+       stream.write((char *)buf,length);
+
+       return stream;
+}
+
+istream & operator >> (istream & stream, TS_Packet & x){
+       uint8_t sync;
+       int found=0;
+       streampos p,q;
+
+       sync=0;
+       while (!stream.eof() && !found) {
+               stream.read((char *)&sync,1);
+               if (sync == 0x47) 
+                       found = 1;
+       }
+       stream.read((char *)x.p.pid,2);
+       stream.read((char *)&x.p.flags,1);
+       x.p.count = x.p.flags & COUNT_MASK;
+        
+       if (!(x.p.flags & ADAPT_FIELD) && (x.p.flags & PAYLOAD)){
+               //no adapt. field only payload
+               stream.read((char *)x.p.data,184);
+               x.p.rest = 184;
+               return stream;
+       } 
+
+       if ( x.p.flags & ADAPT_FIELD ) {
+               // adaption field
+               stream.read((char *)&x.p.adapt_length,1);
+               if (x.p.adapt_length){
+                       p = stream.tellg();
+                       stream.read((char *)&x.p.adapt_flags,1);
+                       
+                       if ( x.p.adapt_flags & PCR_FLAG )
+                               stream.read((char *) x.p.pcr,6);
+
+                       if ( x.p.adapt_flags & OPCR_FLAG )
+                               stream.read((char *) x.p.opcr,6);
+
+                       if ( x.p.adapt_flags & SPLICE_FLAG )
+                               stream.read((char *) &x.p.splice_count,1);
+                       
+                       if( x.p.adapt_flags & TRANS_PRIV){
+                               stream.read((char *)&x.p.priv_dat_len,1);
+                               x.p.priv_dat = new uint8_t[x.p.priv_dat_len];
+                               stream.read((char *)x.p.priv_dat,x.p.priv_dat_len);
+                       }
+                       
+                       if( x.p.adapt_flags & ADAP_EXT_FLAG){
+                               stream.read((char *)&x.p.adapt_ext_len,1);
+                               stream.read((char *)&x.p.adapt_eflags,1);
+                               if( x.p.adapt_eflags & LTW_FLAG)
+                                       stream.read((char *)x.p.ltw,2);
+                               
+                               if( x.p.adapt_eflags & PIECE_RATE)
+                                       stream.read((char *)x.p.piece_rate,3);
+                               
+                               if( x.p.adapt_eflags & SEAM_SPLICE)
+                                       stream.read((char *)x.p.dts,5);
+                       }
+                       q = stream.tellg();
+                       x.p.stuffing = x.p.adapt_length -(q-p);
+                       x.p.rest = 183-x.p.adapt_length;
+                       stream.seekg(q+streampos(x.p.stuffing));
+                       if (x.p.flags & PAYLOAD) // payload
+                               stream.read((char *)x.p.data,x.p.rest);
+                       else 
+                               stream.seekg(q+streampos(x.p.rest));
+               } else {
+                       x.p.rest = 182;
+                       stream.read((char *)x.p.data, 183);
+                       return stream;
+               }
+
+       }
+       return stream;
+}
+
+
+ostream & operator << (ostream & stream, PS_Packet & x){
+
+       uint8_t buf[PS_MAX];
+       int length = cwrite_ps(buf,&(x.p),PS_MAX);
+       stream.write((char *)buf,length);
+
+       return stream;
+}
+
+istream & operator >> (istream & stream, PS_Packet & x){
+       uint8_t headr[4];
+       int found=0;
+       streampos p = 0;
+       streampos q = 0;
+       int count = 0;
+
+       p = stream.tellg();
+       while (!stream.eof() && !found && count < MAX_SEARCH) {
+               stream.read((char *)&headr,4);
+               if (headr[0] == 0x00 && headr[1] == 0x00 && headr[2] == 0x01)
+                       if ( headr[3] == 0xBA ) 
+                               found = 1;
+                       else if ( headr[3] == 0xB9 ) break;
+                       else stream.seekg(p+streampos(1));
+               count++;
+       }
+       
+       if (found){
+               stream.read((char *)x.p.scr,6);
+               if (x.p.scr[0] & 0x40)
+                       x.p.mpeg = 2;
+               else
+                       x.p.mpeg = 1;
+
+               if (x.p.mpeg == 2){
+                       stream.read((char *)x.p.mux_rate,3);
+                       stream.read((char *)&x.p.stuff_length,1);
+                       p = stream.tellg();
+                       stream.seekg(p+streampos(x.p.stuff_length & 3));
+               } else {
+                       x.p.mux_rate[0] = x.p.scr[5]; //mpeg1 scr is only 5 bytes
+                       stream.read((char *)x.p.mux_rate+1,2);
+               }
+                       
+               p=stream.tellg();
+               stream.read((char *)headr,4);
+               if (headr[0] == 0x00 && headr[1] == 0x00 && 
+                   headr[2] == 0x01 && headr[3] == 0xBB ) {
+                       stream.read((char *)x.p.sheader_llength,2);
+                       x.setlength();
+                       if (x.p.mpeg == 2){
+                               stream.read((char *)x.p.rate_bound,3);
+                               stream.read((char *)&x.p.audio_bound,1);
+                               stream.read((char *)&x.p.video_bound,1);
+                               stream.read((char *)&x.p.reserved,1);
+                       }
+                       stream.read((char *)x.p.data,x.p.sheader_length);
+               } else {
+                       stream.seekg(p);
+                       x.p.sheader_length = 0;
+               }
+
+               int i = 0;
+               int done = 0;
+               q = stream.tellg();
+               PES_Packet pes;
+               do {
+                       p=stream.tellg();
+                       stream.read((char *)headr,4);
+                       stream.seekg(p);
+                       if ( headr[0] == 0x00 && headr[1] == 0x00 
+                            && headr[2] == 0x01 && headr[3] != 0xBA){
+                               pes.init();
+                               stream >> pes;
+                               i++;
+                       } else done = 1;
+               } while (!stream.eof() && !done);
+               x.p.npes = i;
+               stream.seekg(q);
+       } 
+       return stream;
+}
+
+void extract_audio_from_PES(istream &in, ostream &out){
+       PES_Packet pes;
+       
+       while(!in.eof()){
+               pes.init();
+               in >> pes ;
+               if (pes.Stream_ID() == 0xC0)
+                       out << pes;
+       }
+}
+
+void extract_video_from_PES(istream &in, ostream &out){
+       PES_Packet pes;
+       
+       while(!in.eof()){
+               pes.init();
+               in >> pes ;
+               if (pes.Stream_ID() == 0xE0)
+                       out << pes;
+       }
+}
+
+void extract_es_audio_from_PES(istream &in, ostream &out){
+       PES_Packet pes;
+       
+       while(!in.eof()){
+               pes.init();
+               in >> pes ;
+               if (pes.Stream_ID() == 0xC0)
+                 out.write((char *)pes.Data(),pes.Length());
+       }
+}
+
+void extract_es_video_from_PES(istream &in, ostream &out){
+       PES_Packet pes;
+       
+       while(!in.eof()){
+               pes.init();
+               in >> pes ;
+               if (pes.Stream_ID() == 0xE0)
+                 out.write((char *)pes.Data(),pes.Length());
+       }
+}
+
+
+
+#define MAX_PID 20
+int TS_PIDS(istream &in, ostream &out){
+       int pid[MAX_PID];
+       TS_Packet ts;
+       int npid=0;
+       
+       for (int i=0 ; i<MAX_PID; i++)
+               pid[i] = -1;
+       while (!in.eof()) {
+               ts.init();
+               in >> ts;
+               int j;
+               int found = 0;
+               for (j=0;j<npid;j++){
+                       if ( ts.PID() == pid[j] )
+                               found = 1;
+               }
+               if (! found){ 
+                       out << ts.PID() << " ";
+                       pid[npid] = ts.PID();
+                       npid++;
+                       if (npid == MAX_PID) return -1;
+               }
+       }
+       out << endl;
+       return 0;
+}
+
+int tv_norm(istream &stream){
+       uint8_t headr[4];
+       int found=0;
+       streampos p = 0;
+       streampos q = 0;
+       int hsize,vsize;
+       int form= 0;
+
+       q = stream.tellg();
+       while (!stream.eof() && !found) {
+               p = stream.tellg();
+               stream.read((char *)headr,4);
+               if (headr[0] == 0x00 && headr[1] == 0x00 && headr[2] == 0x01)
+                       if ( headr[3] == 0xB3 ){ 
+                               found = 1;
+                       }
+               if (! found) stream.seekg(p+streampos(1));
+       }
+       stream.read((char *)headr,4);
+
+       hsize = (headr[1] &0xF0) >> 4 | headr[0] << 4;
+       vsize = (headr[1] &0x0F) << 8 | headr[2];
+       cerr << "SIZE: " << hsize << "x" << vsize << endl;
+       
+       switch(((headr[3]&0xF0) >>4)){
+       case 1:
+               cerr << "ASPECT: 1:1" << endl;
+               break;
+       case 2:
+               cerr << "ASPECT: 4:3" << endl;
+               break;
+       case 3:
+               cerr << "ASPECT: 16:9" << endl;
+               break;
+       case 4:
+               cerr << "ASPECT: 2.21:1" << endl;
+               break;
+       }
+
+       switch (int(headr[3]&0x0F)){
+       case 1:
+               cerr << "FRAMERATE: 23.976" << endl;
+               form = pDUNNO;
+               break;
+       case 2:
+               cerr << "FRAMERATE: 24" << endl;
+               form = pDUNNO;
+               break;
+       case 3:
+               cerr << "FRAMERATE: 25" << endl;
+               form = pPAL;
+               break;
+       case 4:
+               cerr << "FRAMERATE: 29.97" << endl;
+               form = pNTSC;
+               break;
+       case 5:
+               cerr << "FRAMERATE: 30" << endl;
+               form = pNTSC;
+               break;
+       case 6:
+               cerr << "FRAMERATE: 50" << endl;
+               form = pPAL;
+               break;
+       case 7:
+               cerr << "FRAMERATE: 59.94" << endl;
+               form = pNTSC;
+               break;
+       case 8:
+               cerr << "FRAMERATE: 60" << endl;
+               form = pNTSC;
+               break;
+       }
+
+       int mpeg = 0;
+       found = 0;
+       while (!stream.eof() && !found) {
+               p = stream.tellg();
+               stream.read((char *)headr,4);
+               if (headr[0] == 0x00 && headr[1] == 0x00 && headr[2] == 0x01)
+                       if ( headr[3] == 0xB5 ){ 
+                               char *profile[] = {"reserved", "High", "Spatially Scalable",
+                                                  "SNR Scalable", "Main", "Simple", "undef",
+                                                  "undef"};
+                               char *level[]   = {"res", "res", "res", "res",
+                                                  "High","res", "High 1440", "res",
+                                                  "Main","res", "Low", "res",
+                                                  "res", "res", "res", "res"};
+                               char *chroma[]  = {"res", "4:2:0", "4:2:2", "4:4:4:"};
+                               mpeg = 2;
+                               stream.read((char *)headr,4);
+                               cerr << "PROFILE: " << profile[headr[0] & 0x7] << endl;
+                               cerr << "LEVEL: " << level[headr[1]>>4 & 0xF] << endl;
+                               cerr << "CHROMA: " << chroma[headr[1]>>1 & 0x3] << endl;
+                               found = 1;
+                       } else {
+                               mpeg = 1;
+                               found = 1;
+                       }                               
+               if (! found) stream.seekg(p+streampos(1));
+       }
+
+       stream.seekg(q);
+       return (form | mpeg << 4);
+}
+
+
+
+int stream_type(istream &fin){
+       uint8_t headr[4];
+       streampos p=fin.tellg();
+       
+       TS_Packet ts;
+       fin >> ts;
+       fin.read((char *)headr,1);
+       fin.seekg(p);
+       if(fin && headr[0] == 0x47){
+               return TS_STREAM;
+       }
+
+       PS_Packet ps;
+       fin >> ps;
+       PES_Packet pes;
+       for(int j=0;j < ps.NPES();j++){
+               fin >> pes;
+       }
+       fin.read((char *)headr,4);
+       fin.seekg(p);
+       if (fin && headr[0] == 0x00 && headr[1] == 0x00
+           && headr[2] == 0x01 && headr[3] == 0xBA){
+               return PS_STREAM;
+       }
+       
+       fin >> pes;
+       fin.read((char *)!headr,4);
+                       fin.seekg(p);
+       if (fin && headr[0] == 0x00 && headr[1] == 0x00
+           && headr[2] == 0x01 ){
+               int found = 0;
+               switch ( headr[3] ) {
+                       
+               case PROG_STREAM_MAP:
+               case PRIVATE_STREAM2:
+               case PROG_STREAM_DIR:
+               case ECM_STREAM     :
+               case EMM_STREAM     :
+               case PADDING_STREAM :
+               case DSM_CC_STREAM  :
+               case ISO13522_STREAM:
+               case PRIVATE_STREAM1:
+               case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+               case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+                       found = 1;
+                       break;
+               }
+               if (found){
+                       return PES_STREAM;
+               }
+       }
+
+       
+
+       return -1;
+}
+
+
+void analyze(istream &fin)
+{
+       PS_Packet ps;
+       PES_Packet pes;
+       int fc = 0;
+       char *frames[3] = {"I-Frame","P-Frame","B-Frame"};
+                       
+       while(fin){
+               uint32_t pts;
+               fin >> ps;
+               cerr << "SCR base: " << hex << setw(5) 
+                    << setfill('0') \
+                    << ps.SCR_base() << " " << dec
+                    << "ext : " << ps.SCR_ext();
+
+               cerr << "   MUX rate: " << ps.MUX()*50*8/1000000.0
+                    << " Mbit/s   ";
+               cerr << "RATE bound: " << ps.Rate()*50*8/1000000.0
+                    << " Mbit/s" << endl;
+               cerr << "                             Audio bound: " 
+                    << hex << "0x" 
+                    << int(ps.P()->audio_bound);
+               cerr << "         Video bound: " << hex << "0x" 
+                    << int(ps.P()->video_bound)
+                    << dec
+                    << endl;
+               cerr << endl;
+
+               for (int i=0; i < ps.NPES(); i++){
+                       pes.init();
+                       fin >> pes;
+                       pts2pts((uint8_t *)&pts,pes.PTS());
+                       pes.Info() = 1;
+                       cerr  << pes;
+
+                       uint8_t *buf = pes.P()->pes_pckt_data;
+                       int c = 0;
+                       int l;
+                       switch (pes.P()->stream_id){
+                       case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+                               l=pes.P()->length;
+                               break;
+                       default:
+                               l = 0;
+                               break;
+                       }
+                       while ( c < l - 6){
+                               if (buf[c] == 0x00 && 
+                                   buf[c+1] == 0x00 &&
+                                   buf[c+2] == 0x01 && 
+                                   buf[c+3] == 0xB8) {
+                                       c += 4;
+                                       cerr << "TIME   hours: " 
+                                            << int((buf[c]>>2)& 0x1F)
+                                            << "  minutes: "
+                                            << int(((buf[c]<<4)& 0x30)|
+                                                   ((buf[c+1]>>4)& 0x0F))
+                                            << " seconds: "
+                                            << int(((buf[c+1]<<3)& 0x38)|
+                                                   ((buf[c+2]>>5)& 0x0F))
+                                            << endl;
+                               }
+                               
+                               if ( buf[c] == 0x00 && 
+                                    buf[c+1] == 0x00 &&
+                                    buf[c+2] == 0x01 && 
+                                    buf[c+3] == 0x00) {
+                                       fc++;
+                                       c += 4;
+                                       cerr << "picture: " 
+                                            << fc 
+                                            << " ("
+                                            << frames[((buf[c+1]&0x38) >>3)-1]
+                                            << ")" << endl << endl;
+                               } else c++;
+                       }
+               }
+       }
+}
+
+
diff --git a/libdvbmpeg/cpptools.hh b/libdvbmpeg/cpptools.hh
new file mode 100644 (file)
index 0000000..49ea5de
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ *  dvb-mpegtools for the Siemens Fujitsu DVB PCI card
+ *
+ * Copyright (C) 2000, 2001 Marcus Metzler 
+ *            for convergence integrated media GmbH
+ * Copyright (C) 2002 Marcus Metzler 
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ * 
+
+ * The author can be reached at mocm@metzlerbros.de, 
+ */
+
+#include <fstream>
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+using namespace std;
+
+
+#ifndef _CPPTOOLS_HH_
+#define _CPPTOOLS_HH_
+
+#include "ctools.h"
+
+
+class PES_Packet{
+       int info;
+       pes_packet p;
+public:
+       PES_Packet(){
+               info = 0;
+               init_pes(&p);
+       }
+
+       ~PES_Packet(){
+               if (p.pack_header)
+                       delete [] p.pack_header;
+               if (p.pes_ext)
+                       delete [] p.pes_ext;
+               if (p.pes_pckt_data)
+                       delete [] p.pes_pckt_data;
+               if (p.mpeg1_headr)
+                       delete [] p.mpeg1_headr;
+       }
+       
+       inline void init(){
+               if (p.pack_header)
+                       delete [] p.pack_header;
+               if (p.pes_ext)
+                       delete [] p.pes_ext;
+               if (p.pes_pckt_data)
+                       delete [] p.pes_pckt_data;
+               if (p.mpeg1_headr)
+                       delete [] p.mpeg1_headr;
+
+               info = 0;
+               init_pes(&p);
+       }
+
+       inline pes_packet *P(){
+               return &p;
+       }
+
+       inline void setlength(){
+               setlength_pes(&p);
+               if (p.length)
+                       p.pes_pckt_data = new uint8_t[p.length];
+       }
+
+       inline void Nlength(){
+               nlength_pes(&p);
+               p.pes_pckt_data = new uint8_t[p.length];
+       }
+
+
+       inline uint8_t &Stream_ID(){
+               return p.stream_id;
+       }
+
+       inline uint8_t &Flags1(){
+               return p.flags1;
+       }
+
+       inline uint8_t &Flags2(){
+               return p.flags2;
+       }
+
+       inline uint32_t &Length(){
+               return p.length;
+       }
+       
+       inline uint8_t &HLength(){
+               return p.pes_hlength;
+       }
+
+       inline uint8_t &Stuffing(){
+               return p.stuffing;
+       }
+
+       inline uint8_t *Data(){
+               return p.pes_pckt_data;
+       }
+       
+       inline int has_pts(){
+               return (p.flags2 & PTS_DTS);
+       }
+
+       inline int &MPEG(){
+               return p.mpeg;
+       }
+       inline uint8_t *PTS(){
+               return p.pts;
+       }
+
+       inline uint8_t *DTS(){
+               return p.dts;
+       }
+
+       inline int &Info(){
+               return info;
+       }
+  
+  
+
+       inline uint8_t high_pts(){
+               if (has_pts())
+                       return ((p.pts[0] & 0x08)>>3);
+               else
+                       return 0;
+       }
+
+       inline uint8_t high_dts(){
+               return ((p.dts[0] & 0x08)>>3);
+       }
+
+       inline int WDTS(){
+               int w_dts;
+               w_dts = (int)trans_pts_dts(p.dts);
+               return w_dts;
+       }
+
+       inline int WPTS(){
+               int w_dts;
+               w_dts = (int)trans_pts_dts(p.pts);
+               return w_dts;
+       }
+
+       friend ostream & operator << (ostream & stream, PES_Packet & x);
+       friend istream & operator >> (istream & stream, PES_Packet & x);
+
+};
+
+
+class TS_Packet{
+       ts_packet p;
+       int info;
+
+public:
+       TS_Packet(){
+               init_ts(&p);
+               info = 0;
+       }
+
+       ~TS_Packet(){
+               if (p.priv_dat)
+                       delete [] p.priv_dat;
+       }
+       
+       inline void init(){
+               if (p.priv_dat)
+                       delete [] p.priv_dat;
+
+               init_ts(&p);
+               info = 0;
+       }
+
+       inline ts_packet *P(){
+               return &p;
+       }
+               
+       inline int &Rest(){
+               return p.rest;
+       }
+
+       inline uint8_t *Data(){
+               return p.data;
+       }
+
+       inline short PID(){
+               return pid_ts(&p);
+       }
+
+       inline uint8_t FLAG1(){
+               return (p.pid[0] & ~PID_MASK_HI);
+       }
+
+       inline int &Info(){
+               return info;
+       }
+
+       friend ostream & operator << (ostream & stream, TS_Packet & x);
+       friend istream & operator >> (istream & stream, TS_Packet & x);
+};
+
+
+class PS_Packet{
+       int info;
+       ps_packet p;
+public:
+
+       PS_Packet(){
+               init_ps(&p);
+               info = 0;
+       }
+       
+       ~PS_Packet(){
+               if (p.data)
+                       delete [] p.data;
+       }
+
+       inline void init(){
+               if (p.data)
+                       delete [] p.data;
+
+               init_ps(&p);
+               info = 0;
+       }
+
+       inline ps_packet *P(){
+               return &p;
+       }
+
+       inline int MUX(){
+               return mux_ps(&p);
+       }
+
+       inline int Rate(){
+               return rate_ps(&p);
+       }
+
+       inline void setlength(){
+               setlength_ps(&p);
+               p.data = new uint8_t[p.sheader_length];
+       }
+
+       inline int Stuffing(){
+               return p.stuff_length & PACK_STUFF_MASK;
+       }
+
+       inline int NPES(){
+               return p.npes;
+       }
+
+       inline int &MPEG(){
+               return p.mpeg;
+       }
+
+       inline uint8_t &operator()(int l){
+               return p.data[l];
+       }
+
+       inline char * Data() {
+               return (char *)p.data+p.stuff_length;
+       }
+
+       inline int &SLENGTH(){
+               return p.sheader_length;
+       }
+       
+       inline int &Info(){
+               return info;
+       }
+       
+       uint32_t SCR_base(){
+               return scr_base_ps(&p);
+       }
+
+       uint16_t SCR_ext(){
+               return scr_ext_ps(&p);
+       }
+
+       friend ostream & operator << (ostream & stream, PS_Packet & x);
+       friend istream & operator >> (istream & stream, PS_Packet & x);
+};
+
+
+typedef void (* FILTER)(istream &in, ostream &out);
+
+typedef struct thread_args_{
+       FILTER function;
+       int *fd;
+       int in;
+       int out;
+} thread_args;
+
+
+void extract_audio_from_PES(istream &in, ostream &out);
+void extract_video_from_PES(istream &in, ostream &out);
+void extract_es_audio_from_PES(istream &in, ostream &out);
+void extract_es_video_from_PES(istream &in, ostream &out);
+int TS_PIDS(istream &in, ostream &out);
+int ifilter (istream &in, FILTER function);
+int ofilter (istream &in, FILTER function);
+int itfilter (int in, FILTER function);
+int otfilter (istream &in, FILTER function);
+int stream_type(int fd);
+int stream_type(istream &stream);
+int tv_norm(istream &fin);
+
+void analyze(istream &fin);
+
+
+#endif //_CPPTOOLS_HH_
+
diff --git a/libdvbmpeg/ctools.c b/libdvbmpeg/ctools.c
new file mode 100644 (file)
index 0000000..dfd1751
--- /dev/null
@@ -0,0 +1,2379 @@
+/*
+ *  dvb-mpegtools for the Siemens Fujitsu DVB PCI card
+ *
+ * Copyright (C) 2000, 2001 Marcus Metzler 
+ *            for convergence integrated media GmbH
+ * Copyright (C) 2002 Marcus Metzler 
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ * 
+
+ * The author can be reached at mocm@metzlerbros.de, 
+ */
+
+#include "ctools.h"
+
+#define MAX_SEARCH 1024 * 1024
+
+
+/*
+
+      PES
+  
+*/
+
+ssize_t save_read(int fd, void *buf, size_t count)
+{
+       ssize_t neof = 1;
+       size_t re = 0;
+       
+       while(neof >= 0 && re < count){
+               neof = read(fd, buf+re, count - re);
+               if (neof > 0) re += neof;
+               else break;
+       }
+
+       if (neof < 0 && re == 0) return neof;
+       else return re;
+}
+
+void init_pes(pes_packet *p){
+       p->stream_id = 0;
+       p->llength[0] = 0;
+       p->llength[1] = 0;
+       p->length = 0;
+       p->flags1 = 0x80;
+       p->flags2 = 0;
+       p->pes_hlength = 0;
+       p->trick = 0;
+       p->add_cpy = 0;
+       p->priv_flags = 0;
+       p->pack_field_length = 0;
+       p->pack_header = (uint8_t *) NULL;
+       p->pck_sqnc_cntr = 0;
+       p->org_stuff_length = 0;
+       p->pes_ext_lngth = 0;
+       p->pes_ext = (uint8_t *) NULL;
+       p->pes_pckt_data = (uint8_t *) NULL;
+       p->padding = 0;
+       p->mpeg = 2; // DEFAULT MPEG2
+       p->mpeg1_pad = 0;
+       p->mpeg1_headr = NULL;
+       p->stuffing = 0;
+}
+
+void kill_pes(pes_packet *p){
+       if (p->pack_header)
+               free(p->pack_header);
+       if (p->pes_ext)
+               free(p->pes_ext);
+       if (p->pes_pckt_data)
+               free(p->pes_pckt_data);
+       if (p->mpeg1_headr)
+               free(p->mpeg1_headr);
+       init_pes(p);
+}
+
+void setlength_pes(pes_packet *p){
+       short *ll;
+       ll = (short *) p->llength;
+       p->length = ntohs(*ll);
+}
+
+static void setl_pes(pes_packet *p){
+       setlength_pes(p);
+       if (p->length)
+               p->pes_pckt_data = (uint8_t *)malloc(p->length);
+}
+
+void nlength_pes(pes_packet *p){
+       if (p->length <= 0xFFFF){
+               short *ll = (short *) p->llength;
+               short l = p->length;
+               *ll = htons(l);
+       } else {
+               p->llength[0] =0x00;
+               p->llength[1] =0x00;
+       }
+}
+
+static void nl_pes(pes_packet *p)
+{
+       nlength_pes(p);
+       p->pes_pckt_data = (uint8_t *) malloc(p->length);
+}
+
+void pts2pts(uint8_t *av_pts, uint8_t *pts)
+{
+  
+       av_pts[0] = ((pts[0] & 0x06) << 5) | 
+               ((pts[1] & 0xFC) >> 2); 
+       av_pts[1] = ((pts[1] & 0x03) << 6) |
+               ((pts[2] & 0xFC) >> 2); 
+       av_pts[2] = ((pts[2] & 0x02) << 6) |
+                       ((pts[3] & 0xFE) >> 1);
+       av_pts[3] = ((pts[3] & 0x01) << 7) |
+               ((pts[4] & 0xFE) >> 1);
+       
+}
+
+
+int cwrite_pes(uint8_t *buf, pes_packet *p, long length){
+       int count,i;
+       uint8_t dummy;
+       int more = 0;
+       uint8_t headr[3] = { 0x00, 0x00 , 0x01};
+
+       if (length <  p->length+p->pes_hlength){
+               fprintf(stderr,"Wrong buffer size in cwrite_pes\n");
+               exit(1);
+       }
+
+
+       memcpy(buf,headr,3);
+       count = 3;
+       buf[count] = p->stream_id;
+       count++;
+
+       switch ( p->stream_id ) {
+                               
+       case PROG_STREAM_MAP:
+       case PRIVATE_STREAM2:
+       case PROG_STREAM_DIR:
+       case ECM_STREAM     :
+       case EMM_STREAM     :
+       case PADDING_STREAM :
+               buf[count] = p->llength[0];
+               count++;
+               buf[count] = p->llength[1];
+               count++;
+               memcpy(buf+count,p->pes_pckt_data,p->length);
+               count += p->length;
+               break;
+       case DSM_CC_STREAM  :
+       case ISO13522_STREAM:
+       case PRIVATE_STREAM1:
+       case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+       case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+               buf[count] = p->llength[0];
+               count++;
+               buf[count] = p->llength[1];
+               count++;
+               more = 1;
+               break;
+       }       
+       
+
+       if ( more ) {
+               if ( p->mpeg == 2 ){
+                       memcpy(buf+count,&p->flags1,1);
+                       count++;
+                       memcpy(buf+count,&p->flags2,1);
+                       count++;
+                       memcpy(buf+count,&p->pes_hlength,1);
+                       count++;
+                       
+                       if ((p->flags2 & PTS_DTS_FLAGS) == PTS_ONLY){
+                               memcpy(buf+count,p->pts,5);
+                               count += 5;
+                       } else 
+                               if ((p->flags2 & PTS_DTS_FLAGS) == PTS_DTS){
+                                       memcpy(buf+count,p->pts,5);
+                                       count += 5;
+                                       memcpy(buf+count,p->dts,5);
+                                       count += 5;
+                               }
+                       if (p->flags2 & ESCR_FLAG){
+                               memcpy(buf+count,p->escr,6);
+                               count += 6;
+                       }
+                       if (p->flags2 & ES_RATE_FLAG){
+                               memcpy(buf+count,p->es_rate,3);
+                               count += 3;
+                       }
+                       if (p->flags2 & DSM_TRICK_FLAG){
+                               memcpy(buf+count,&p->trick,1);
+                               count++;
+                       }
+                       if (p->flags2 & ADD_CPY_FLAG){
+                               memcpy(buf+count,&p->add_cpy,1);
+                               count++;
+                       }
+                       if (p->flags2 & PES_CRC_FLAG){
+                               memcpy(buf+count,p->prev_pes_crc,2);
+                               count += 2;
+                       }
+                       if (p->flags2 & PES_EXT_FLAG){
+                               memcpy(buf+count,&p->priv_flags,1);
+                               count++;
+
+                               if (p->priv_flags & PRIVATE_DATA){
+                                       memcpy(buf+count,p->pes_priv_data,16);
+                                       count += 16;
+                               }
+                               if (p->priv_flags & HEADER_FIELD){
+                                       memcpy(buf+count,&p->pack_field_length,
+                                              1);
+                                       count++;
+                                       memcpy(buf+count,p->pack_header,
+                                                    p->pack_field_length);
+                                       count += p->pack_field_length;
+
+                               }
+                               
+                               if ( p->priv_flags & PACK_SEQ_CTR){
+                                       memcpy(buf+count,&p->pck_sqnc_cntr,1);
+                                       count++;
+                                       memcpy(buf+count,&p->org_stuff_length,
+                                              1);
+                                       count++;
+                               }
+                               
+                               if ( p->priv_flags & P_STD_BUFFER){
+                                       memcpy(buf+count,p->p_std,2);
+                                       count += 2;
+                               }
+                               if ( p->priv_flags & PES_EXT_FLAG2){
+                                       memcpy(buf+count,&p->pes_ext_lngth,1);
+                                       count++;
+                                       memcpy(buf+count,p->pes_ext,
+                                                    p->pes_ext_lngth);
+                                       count += p->pes_ext_lngth;
+                               }
+                       }
+                       dummy = 0xFF;
+                       for (i=0;i<p->stuffing;i++) {
+                               memcpy(buf+count,&dummy,1);
+                               count++;
+                       }
+               } else {
+                       if (p->mpeg1_pad){
+                               memcpy(buf+count,p->mpeg1_headr,p->mpeg1_pad);
+                               count += p->mpeg1_pad;
+                       }
+                       if ((p->flags2 & PTS_DTS_FLAGS) == PTS_ONLY){
+                               memcpy(buf+count,p->pts,5);
+                               count += 5;
+                       }
+                       else if ((p->flags2 & PTS_DTS_FLAGS) == 
+                                PTS_DTS){
+                               memcpy(buf+count,p->pts,5);
+                                       count += 5;
+                               memcpy(buf+count,p->dts,5);
+                                       count += 5;
+                       }
+               }                       
+               memcpy(buf+count,p->pes_pckt_data,p->length);
+               count += p->length;
+       }
+
+       return count;
+
+}
+
+void write_pes(int fd, pes_packet *p){
+       long length;
+       uint8_t *buf;
+       int l = p->length+p->pes_hlength;
+       
+       buf = (uint8_t *) malloc(l);
+       length = cwrite_pes(buf,p,l);
+       write(fd,buf,length);
+       free(buf);
+}
+
+static unsigned int find_length(int f){
+       uint64_t p = 0;
+       uint64_t start = 0;
+       uint64_t q = 0;
+       int found = 0;
+       uint8_t sync4[4];
+       int neof = 1;
+
+       start = lseek(f,0,SEEK_CUR);
+       start -=2;
+        lseek(f,start,SEEK_SET);
+       while ( neof > 0 && !found ){
+               p = lseek(f,0,SEEK_CUR);
+               neof = save_read(f,&sync4,4);
+               if (sync4[0] == 0x00 && sync4[1] == 0x00 && sync4[2] == 0x01) {
+                       switch ( sync4[3] ) {
+                               
+                       case PROG_STREAM_MAP:
+                       case PRIVATE_STREAM2:
+                       case PROG_STREAM_DIR:
+                       case ECM_STREAM     :
+                       case EMM_STREAM     :
+                       case PADDING_STREAM :
+                       case DSM_CC_STREAM  :
+                       case ISO13522_STREAM:
+                       case PRIVATE_STREAM1:
+                       case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+                       case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+                               found = 1;
+                               break;
+                       default:
+                               q = lseek(f,0,SEEK_CUR);
+                               break;
+                       }       
+               } 
+       }
+       q = lseek(f,0,SEEK_CUR);
+       lseek(f,start+2,SEEK_SET);
+       if (found) return (unsigned int)(q-start)-4-2;
+       else return (unsigned int)(q-start-2);
+       
+}
+
+
+void cread_pes(char *buf, pes_packet *p){
+       
+       uint8_t count, dummy, check;
+       int i;
+       uint64_t po = 0;
+       int c=0;
+
+       switch ( p->stream_id ) {
+               
+       case PROG_STREAM_MAP:
+       case PRIVATE_STREAM2:
+       case PROG_STREAM_DIR:
+       case ECM_STREAM     :
+       case EMM_STREAM     :
+               memcpy(p->pes_pckt_data,buf+c,p->length);
+               return;
+               break;
+       case PADDING_STREAM :
+               p->padding = p->length;
+               memcpy(p->pes_pckt_data,buf+c,p->length);
+               return;
+               break;                  
+       case DSM_CC_STREAM  :
+       case ISO13522_STREAM:
+       case PRIVATE_STREAM1:
+       case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+       case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+               break;
+       default:
+               return;
+               break;
+       }       
+       
+       po = c;
+       memcpy(&p->flags1,buf+c,1);
+       c++;
+       if ( (p->flags1 & 0xC0) == 0x80 ) p->mpeg = 2;
+       else p->mpeg = 1;
+       
+       if ( p->mpeg == 2 ){
+               memcpy(&p->flags2,buf+c,1);
+               c++;
+               memcpy(&p->pes_hlength,buf+c,1);
+               c++;
+               
+               p->length -=p->pes_hlength+3;
+               count = p->pes_hlength;
+               
+               if ((p->flags2 & PTS_DTS_FLAGS) == PTS_ONLY){
+                       memcpy(p->pts,buf+c,5);
+                       c += 5;
+                       count -=5;
+               } else 
+                       if ((p->flags2 & PTS_DTS_FLAGS) == PTS_DTS){
+                               memcpy(p->pts,buf+c,5);
+                               c += 5;
+                               memcpy(p->dts,buf+c,5);
+                               c += 5;
+                               count -= 10;
+                       }
+               
+               if (p->flags2 & ESCR_FLAG){
+                       memcpy(p->escr,buf+c,6);
+                       c += 6;
+                       count -= 6;
+               }
+               
+               if (p->flags2 & ES_RATE_FLAG){
+                       memcpy(p->es_rate,buf+c,3);
+                       c += 3;
+                       count -= 3;
+               }
+
+               if (p->flags2 & DSM_TRICK_FLAG){
+                       memcpy(&p->trick,buf+c,1);
+                       c += 1;
+                       count -= 1;
+               }
+               
+               if (p->flags2 & ADD_CPY_FLAG){
+                       memcpy(&p->add_cpy,buf+c,1);
+                       c++;
+                       count -= 1;
+               }
+               
+               if (p->flags2 & PES_CRC_FLAG){
+                       memcpy(p->prev_pes_crc,buf+c,2);
+                       c += 2;
+                       count -= 2;
+               }                       
+               
+               if (p->flags2 & PES_EXT_FLAG){
+                       memcpy(&p->priv_flags,buf+c,1);
+                       c++;
+                       count -= 1;
+                       
+                       if (p->priv_flags & PRIVATE_DATA){
+                               memcpy(p->pes_priv_data,buf+c,16);
+                               c += 16;
+                               count -= 16;
+                       }
+                       
+                       if (p->priv_flags & HEADER_FIELD){
+                               memcpy(&p->pack_field_length,buf+c,1);
+                               c++;
+                               p->pack_header = (uint8_t *)
+                                       malloc(p->pack_field_length);
+                               memcpy(p->pack_header,buf+c,
+                                      p->pack_field_length);
+                               c += p->pack_field_length;
+                               count -= 1+p->pack_field_length;
+                       }
+                       
+                       if ( p->priv_flags & PACK_SEQ_CTR){
+                               memcpy(&p->pck_sqnc_cntr,buf+c,1);
+                               c++;
+                               memcpy(&p->org_stuff_length,buf+c,1);
+                               c++;
+                               count -= 2;
+                       }
+                       
+                       if ( p->priv_flags & P_STD_BUFFER){
+                               memcpy(p->p_std,buf+c,2);
+                               c += 2;
+                               count -= 2;
+                       }
+
+                       if ( p->priv_flags & PES_EXT_FLAG2){
+                               memcpy(&p->pes_ext_lngth,buf+c,1);
+                               c++;
+                               p->pes_ext = (uint8_t *)
+                                       malloc(p->pes_ext_lngth);
+                               memcpy(p->pes_ext,buf+c,
+                                      p->pes_ext_lngth);
+                               c += p->pes_ext_lngth;
+                               count -= 1+p->pes_ext_lngth;
+                       }
+               }
+               p->stuffing = count;
+               for(i = 0; i< count ;i++){ 
+                       memcpy(&dummy,buf+c,1);
+                       c++;
+               }
+       } else {
+               p->mpeg1_pad = 1;
+               check = p->flags1;
+               while (check == 0xFF){
+                       memcpy(&check,buf+c,1);
+                       c++;
+                       p->mpeg1_pad++;
+               }
+               
+               if ( (check & 0xC0) == 0x40){
+                       memcpy(&check,buf+c,1);
+                       c++;
+                       p->mpeg1_pad++;
+                       memcpy(&check,buf+c,1);
+                       c++;
+                       p->mpeg1_pad++;
+               }
+               p->flags2 = 0;
+               p->length -= p->mpeg1_pad;
+               
+               c = po;
+               if ( (check & 0x30)){
+                       p->length ++;
+                       p->mpeg1_pad --;
+                       
+                       if (check == p->flags1){
+                               p->pes_hlength = 0;
+                       } else {
+                               p->mpeg1_headr = (uint8_t *)
+                                       malloc(p->mpeg1_pad);
+                               p->pes_hlength = p->mpeg1_pad;
+                               memcpy(p->mpeg1_headr,buf+c,
+                                      p->mpeg1_pad);
+                               c += p->mpeg1_pad;
+                       }
+                       
+                       p->flags2 = (check & 0xF0) << 2;
+                       if ((p->flags2 & PTS_DTS_FLAGS) == PTS_ONLY){
+                               memcpy(p->pts,buf+c,5);
+                               c += 5;
+                               p->length -= 5;
+                               p->pes_hlength += 5;
+                       }
+                       else if ((p->flags2 & PTS_DTS_FLAGS) == 
+                                PTS_DTS){
+                               memcpy(p->pts,buf+c,5);
+                               c += 5;
+                               memcpy(p->dts,buf+c,5);
+                               c += 5;
+                               p->length -= 10;
+                               p->pes_hlength += 10;
+                       }
+               } else {
+                       p->mpeg1_headr = (uint8_t *) malloc(p->mpeg1_pad);
+                       p->pes_hlength = p->mpeg1_pad;
+                       memcpy(p->mpeg1_headr,buf+c,
+                              p->mpeg1_pad);
+                       c += p->mpeg1_pad;
+               }
+       }
+       memcpy(p->pes_pckt_data,buf+c,p->length);
+}
+
+
+int read_pes(int f, pes_packet *p){
+       
+       uint8_t sync4[4];
+       int found=0;
+       uint64_t po = 0;
+       int neof = 1;
+       uint8_t *buf;
+
+       while (neof > 0 && !found) {
+               po = lseek(f,0,SEEK_CUR);
+               if (po < 0) return -1;
+               if ((neof = save_read(f,&sync4,4)) < 4) return -1;
+               if (sync4[0] == 0x00 && sync4[1] == 0x00 && sync4[2] == 0x01) {
+                       p->stream_id = sync4[3];
+                       switch ( sync4[3] ) {
+                               
+                       case PROG_STREAM_MAP:
+                       case PRIVATE_STREAM2:
+                       case PROG_STREAM_DIR:
+                       case ECM_STREAM     :
+                       case EMM_STREAM     :
+                       case PADDING_STREAM :
+                       case DSM_CC_STREAM  :
+                       case ISO13522_STREAM:
+                       case PRIVATE_STREAM1:
+                       case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+                       case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+                               if((neof = save_read(f,p->llength,2)) < 2)
+                                       return -1;
+                               setl_pes(p);
+                               if (!p->length){ 
+                                       p->length = find_length(f);
+                                       nl_pes(p);
+                               }
+                               found = 1;
+                               break;
+                               
+                       default:
+                               if (lseek(f,po+1,SEEK_SET) < po+1) return -1;
+                       break;
+                       }       
+               } else if(lseek(f,po+1,SEEK_SET) < po+1) return -1;
+       }
+
+       if (!found || !p->length) return 0;
+       
+       if (p->length >0){
+               buf = (uint8_t *) malloc(p->length);
+               if((neof = save_read(f,buf,p->length))< p->length) return -1;
+               cread_pes((char *)buf,p);
+               free(buf);
+       } else return 0;
+
+       return neof;
+}
+
+/*
+
+   Transport Stream
+
+*/
+
+void init_ts(ts_packet *p){
+       p->pid[0] = 0;
+       p->pid[1] = 0;
+       p->flags = 0;
+       p->count = 0;
+       p->adapt_length = 0;
+       p->adapt_flags = 0;
+       p->splice_count = 0;
+       p->priv_dat_len = 0;
+       p->priv_dat = NULL;
+       p->adapt_ext_len = 0;
+       p->adapt_eflags = 0;
+       p->rest = 0;
+       p->stuffing = 0;
+}
+
+void kill_ts(ts_packet *p){
+       if (p->priv_dat)
+               free(p->priv_dat);
+       init_ts(p);
+}
+
+
+
+unsigned short pid_ts(ts_packet *p)
+{
+  return get_pid(p->pid);
+}
+
+int cwrite_ts(uint8_t *buf, ts_packet *p, long length){
+       long count,i;
+       uint8_t sync,dummy;
+
+       sync = 0x47;
+       memcpy(buf,&sync,1);
+       count = 1;
+       memcpy(buf+count,p->pid,2);
+       count += 2;
+       memcpy(buf+count,&p->flags,1);
+       count++;
+
+        
+       if (! (p->flags & ADAPT_FIELD) && (p->flags & PAYLOAD)){
+               memcpy(buf+count,p->data,184);
+               count += 184;
+       } else {
+               memcpy(buf+count,&p->adapt_length,1);
+               count++;
+               memcpy(buf+count,&p->adapt_flags,1);
+               count++;
+
+               if ( p->adapt_flags & PCR_FLAG ){
+                       memcpy(buf+count, p->pcr,6);
+                       count += 6;
+               }
+               if ( p->adapt_flags & OPCR_FLAG ){
+                       memcpy(buf+count, p->opcr,6);
+                       count += 6;
+               }
+               if ( p->adapt_flags & SPLICE_FLAG ){
+                       memcpy(buf+count, &p->splice_count,1);
+                       count++;
+               }
+               if( p->adapt_flags & TRANS_PRIV){
+                       memcpy(buf+count,&p->priv_dat_len,1);
+                       count++;
+                       memcpy(buf+count,p->priv_dat,p->priv_dat_len);
+                       count += p->priv_dat_len;
+               }
+                       
+               if( p->adapt_flags & ADAP_EXT_FLAG){
+                       memcpy(buf+count,&p->adapt_ext_len,1);
+                       count++;
+                       memcpy(buf+count,&p->adapt_eflags,1);
+                       count++;
+               
+                       if( p->adapt_eflags & LTW_FLAG){
+                               memcpy(buf+count,p->ltw,2);
+                               count += 2;
+                       }
+                       if( p->adapt_eflags & PIECE_RATE){
+                               memcpy(buf+count,p->piece_rate,3);
+                               count += 3;
+                       }
+                       if( p->adapt_eflags & SEAM_SPLICE){
+                               memcpy(buf+count,p->dts,5);
+                               count += 5;
+                       }
+               }
+               dummy = 0xFF;
+               for(i=0; i < p->stuffing ; i++){
+                       memcpy(buf+count,&dummy,1);
+                       count++;
+               }
+               if (p->flags & PAYLOAD){
+                       memcpy(buf+count,p->data,p->rest);
+                       count += p->rest;
+               }
+       } 
+
+
+       return count;
+}
+
+void write_ts(int fd, ts_packet *p){
+       long length;
+       uint8_t buf[TS_SIZE];
+
+       length = cwrite_ts(buf,p,TS_SIZE);
+       write(fd,buf,length);
+}
+
+int read_ts (int f, ts_packet *p){
+       uint8_t sync;
+       int found=0;
+       uint64_t po,q;
+       int neof = 1;
+
+       sync=0;
+       while (neof > 0 && !found) {
+               neof = save_read(f,&sync,1);
+               if (sync == 0x47) 
+                       found = 1;
+       }
+       neof = save_read(f,p->pid,2);
+       neof = save_read(f,&p->flags,1);
+       p->count = p->flags & COUNT_MASK;
+        
+       if (!(p->flags & ADAPT_FIELD) && (p->flags & PAYLOAD)){
+               //no adapt. field only payload
+               neof = save_read(f,p->data,184);
+               p->rest = 184;
+               return neof;
+       } 
+
+       if ( p->flags & ADAPT_FIELD ) {
+               // adaption field
+               neof = save_read(f,&p->adapt_length,1);
+               po = lseek(f,0,SEEK_CUR);
+               neof = save_read(f,&p->adapt_flags,1);
+
+               if ( p->adapt_flags & PCR_FLAG )
+                       neof = save_read(f, p->pcr,6);
+
+               if ( p->adapt_flags & OPCR_FLAG )
+                       neof = save_read(f, p->opcr,6);
+
+               if ( p->adapt_flags & SPLICE_FLAG )
+                       neof = save_read(f, &p->splice_count,1);
+
+               if( p->adapt_flags & TRANS_PRIV){
+                       neof = save_read(f,&p->priv_dat_len,1);
+                       p->priv_dat = (uint8_t *) malloc(p->priv_dat_len);
+                       neof = save_read(f,p->priv_dat,p->priv_dat_len);
+               }
+                       
+               if( p->adapt_flags & ADAP_EXT_FLAG){
+                       neof = save_read(f,&p->adapt_ext_len,1);
+                       neof = save_read(f,&p->adapt_eflags,1);
+                       if( p->adapt_eflags & LTW_FLAG)
+                               neof = save_read(f,p->ltw,2);
+                       
+                       if( p->adapt_eflags & PIECE_RATE)
+                               neof = save_read(f,p->piece_rate,3);
+                       
+                       if( p->adapt_eflags & SEAM_SPLICE)
+                               neof = save_read(f,p->dts,5);
+               }
+               q = lseek(f,0,SEEK_CUR);
+               p->stuffing = p->adapt_length -(q-po);
+               p->rest = 183-p->adapt_length;
+               lseek(f,q+p->stuffing,SEEK_SET);
+               if (p->flags & PAYLOAD) // payload
+                       neof = save_read(f,p->data,p->rest);
+               else 
+                       lseek(f,q+p->rest,SEEK_SET);
+       }
+       return neof;
+}
+
+void cread_ts (char *buf, ts_packet *p, long length){
+       uint8_t sync;
+       int found=0;
+       uint64_t po,q;
+       long count=0;
+       
+       sync=0;
+       while (count < length  && !found) {
+               sync=buf[count];
+               count++;
+               if (sync == 0x47) 
+                       found = 1;
+       }
+       memcpy(p->pid,buf+count,2);
+       count += 2;
+       p->flags = buf[count];
+       count++;
+       p->count = p->flags & COUNT_MASK;
+        
+       if (!(p->flags & ADAPT_FIELD) && (p->flags & PAYLOAD)){
+               //no adapt. field only payload
+               memcpy(p->data,buf+count,184);
+               p->rest = 184;
+               return;
+       } 
+
+       if ( p->flags & ADAPT_FIELD ) {
+               // adaption field
+               p->adapt_length = buf[count];
+               count++;
+               po = count;
+               memcpy(&p->adapt_flags,buf+count,1);
+               count++;
+
+               if ( p->adapt_flags & PCR_FLAG ){
+                       memcpy( p->pcr,buf+count,6);
+                       count += 6;
+               }
+               if ( p->adapt_flags & OPCR_FLAG ){
+                       memcpy( p->opcr,buf+count,6);
+                       count += 6;
+               }
+               if ( p->adapt_flags & SPLICE_FLAG ){
+                       memcpy( &p->splice_count,buf+count,1);
+                       count++;
+               }
+               if( p->adapt_flags & TRANS_PRIV){
+                       memcpy(&p->priv_dat_len,buf+count,1);
+                       count++;
+                       p->priv_dat = (uint8_t *) malloc(p->priv_dat_len);
+                       memcpy(p->priv_dat,buf+count,p->priv_dat_len);
+                       count += p->priv_dat_len;
+               }
+                       
+               if( p->adapt_flags & ADAP_EXT_FLAG){
+                       memcpy(&p->adapt_ext_len,buf+count,1);
+                       count++;
+                       memcpy(&p->adapt_eflags,buf+count,1);
+                       count++;
+                       if( p->adapt_eflags & LTW_FLAG){
+                               memcpy(p->ltw,buf+count,2);
+                               count += 2;
+                       }
+                       if( p->adapt_eflags & PIECE_RATE){
+                               memcpy(p->piece_rate,buf+count,3);
+                               count += 3;
+                       }
+                       if( p->adapt_eflags & SEAM_SPLICE){
+                               memcpy(p->dts,buf+count,5);
+                               count += 5;
+                       }
+               }
+               q = count;
+               p->stuffing = p->adapt_length -(q-po);
+               p->rest = 183-p->adapt_length;
+               count = q+p->stuffing;
+               if (p->flags & PAYLOAD){ // payload
+                       memcpy(p->data,buf+count,p->rest);
+                       count += p->rest;
+               } else 
+                       count = q+p->rest;
+       }
+}
+
+
+/*
+
+   Program Stream
+
+*/
+
+
+void init_ps(ps_packet *p)
+{
+       p->stuff_length=0xF8;
+       p->data = NULL;
+       p->sheader_length = 0;
+       p->audio_bound = 0;
+       p->video_bound = 0;
+       p->npes = 0;
+       p->mpeg = 2;
+}
+
+void kill_ps(ps_packet *p)
+{
+       if (p->data)
+               free(p->data);
+       init_ps(p);
+}
+
+void setlength_ps(ps_packet *p)
+{
+       short *ll;
+       ll = (short *) p->sheader_llength;
+       if (p->mpeg == 2)
+               p->sheader_length = ntohs(*ll) - 6;
+       else 
+               p->sheader_length = ntohs(*ll);
+}      
+
+static void setl_ps(ps_packet *p)
+{
+       setlength_ps(p);
+       p->data = (uint8_t *) malloc(p->sheader_length);
+}
+
+int mux_ps(ps_packet *p)
+{
+       uint32_t mux = 0;
+       uint8_t *i = (uint8_t *)&mux;
+
+       i[1] = p->mux_rate[0];
+       i[2] = p->mux_rate[1];
+       i[3] = p->mux_rate[2];
+       mux = ntohl(mux);
+       mux = (mux >>2);
+       return mux;
+}
+
+int rate_ps(ps_packet *p)
+{
+       uint32_t rate=0;
+       uint8_t *i= (uint8_t *) &rate;
+
+       i[1] = p->rate_bound[0] & 0x7F;
+       i[2] = p->rate_bound[1];
+       i[3] = p->rate_bound[2];
+       
+       rate = ntohl(rate);
+       rate = (rate >> 1);
+       return rate;
+}
+
+
+uint32_t scr_base_ps(ps_packet *p) // only 32 bit!!
+{
+       uint32_t base = 0;
+       uint8_t *buf = (uint8_t *)&base;
+       
+       buf[0] |= (long int)((p->scr[0] & 0x18) << 3);
+       buf[0] |= (long int)((p->scr[0] & 0x03) << 4);
+       buf[0] |= (long int)((p->scr[1] & 0xF0) >> 4);
+                
+       buf[1] |= (long int)((p->scr[1] & 0x0F) << 4);
+       buf[1] |= (long int)((p->scr[2] & 0xF0) >> 4);
+
+       buf[2] |= (long int)((p->scr[2] & 0x08) << 4);
+       buf[2] |= (long int)((p->scr[2] & 0x03) << 5);
+       buf[2] |= (long int)((p->scr[3] & 0xF8) >> 3);
+
+       buf[3] |= (long int)((p->scr[3] & 0x07) << 5);
+       buf[3] |= (long int)((p->scr[4] & 0xF8) >> 3);
+
+       base = ntohl(base);
+       return base;
+}
+
+uint16_t scr_ext_ps(ps_packet *p)
+{
+       short ext = 0;
+
+       ext = (short)(p->scr[5] >> 1);
+       ext += (short) (p->scr[4] &  0x03) * 128;
+
+       return ext;
+}
+
+int cwrite_ps(uint8_t *buf, ps_packet *p, long length)
+{
+       long count,i;
+       uint8_t headr1[4] = {0x00, 0x00, 0x01, 0xBA };
+       uint8_t headr2[4] = {0x00, 0x00, 0x01, 0xBB };
+       uint8_t buffy = 0xFF;
+
+       
+       memcpy(buf,headr1,4);
+       count = 4;
+       if (p->mpeg == 2){
+               memcpy(buf+count,p->scr,6);
+               count += 6;
+               memcpy(buf+count,p->mux_rate,3);
+               count += 3;
+               memcpy(buf+count,&p->stuff_length,1);
+               count++;
+               for(i=0; i< (p->stuff_length & 3); i++){
+                       memcpy(buf+count,&buffy,1);
+                       count++;
+               }
+       } else {
+               memcpy(buf+count,p->scr,5);
+               count += 5;
+               memcpy(buf+count,p->mux_rate,3);
+               count += 3;
+       }
+       if (p->sheader_length){
+               memcpy(buf+count,headr2,4);
+               count += 4;
+               memcpy(buf+count,p->sheader_llength,2);
+               count += 2;
+               if ( p->mpeg == 2){
+                       memcpy(buf+count,p->rate_bound,3);
+                       count += 3;
+                       memcpy(buf+count,&p->audio_bound,1);
+                       count++;
+                       memcpy(buf+count,&p->video_bound,1);
+                       count++;
+                       memcpy(buf+count,&p->reserved,1);
+                       count++;
+               }
+               memcpy(buf+count,p->data,p->sheader_length);
+               count += p->sheader_length;
+       }
+
+       return count;
+}
+
+void write_ps(int fd, ps_packet *p){
+       long length;
+       uint8_t buf[PS_MAX];
+
+       length = cwrite_ps(buf,p,PS_MAX);
+       write(fd,buf,length);
+}
+
+int read_ps (int f, ps_packet *p){
+       uint8_t headr[4];
+       pes_packet pes;
+       int i,done;
+       int found=0;
+       uint64_t po = 0;
+       uint64_t q = 0;
+       long count = 0;
+       int neof = 1;
+
+       po = lseek(f,0,SEEK_CUR);
+       while (neof > 0 && !found && count < MAX_SEARCH) {
+               neof = save_read(f,&headr,4);
+               if (headr[0] == 0x00 && headr[1] == 0x00 && headr[2] == 0x01){
+                       if ( headr[3] == 0xBA ) 
+                               found = 1;
+                       else 
+                               if ( headr[3] == 0xB9 ) break;
+                               else lseek(f,po+1,SEEK_SET);
+               }
+               count++;
+       }
+       
+       if (found){
+               neof = save_read(f,p->scr,6);
+               if (p->scr[0] & 0x40)
+                       p->mpeg = 2;
+               else
+                       p->mpeg = 1;
+
+               if (p->mpeg == 2){
+                       neof = save_read(f,p->mux_rate,3);
+                       neof = save_read(f,&p->stuff_length,1);
+                       po = lseek(f,0,SEEK_CUR);
+                       lseek(f,po+(p->stuff_length & 3),SEEK_SET);
+               } else {
+                       p->mux_rate[0] = p->scr[5]; //mpeg1 scr is only 5 bytes
+                       neof = save_read(f,p->mux_rate+1,2);
+               }
+                       
+               po = lseek(f,0,SEEK_CUR);
+               neof = save_read(f,headr,4);
+               if (headr[0] == 0x00 && headr[1] == 0x00 && 
+                   headr[2] == 0x01 && headr[3] == 0xBB ) {
+                       neof = save_read(f,p->sheader_llength,2);
+                       setl_ps(p);
+                       if (p->mpeg == 2){
+                               neof = save_read(f,p->rate_bound,3);
+                               neof = save_read(f,&p->audio_bound,1);
+                               neof = save_read(f,&p->video_bound,1);
+                               neof = save_read(f,&p->reserved,1);
+                       }
+                       neof = save_read(f,p->data,p->sheader_length);
+               } else {
+                       lseek(f,po,SEEK_SET);
+                       p->sheader_length = 0;
+               }
+
+               i = 0;
+               done = 0;
+               q = lseek(f,0,SEEK_CUR);
+               do {
+                       po = lseek(f,0,SEEK_CUR);
+                       neof = save_read(f,headr,4);
+                       lseek(f,po,SEEK_SET);
+                       if ( headr[0] == 0x00 && headr[1] == 0x00 
+                            && headr[2] == 0x01 && headr[3] != 0xBA){
+                               init_pes(&pes);
+                               neof = read_pes(f,&pes);
+                               i++;
+                       } else done = 1;
+                       kill_pes(&pes);
+               } while ( neof > 0 && !done);
+               p->npes = i;
+               lseek(f,q,SEEK_SET);
+       } 
+       return neof;
+}
+
+void cread_ps (char *buf, ps_packet *p, long length){
+       uint8_t *headr;
+       pes_packet pes;
+       int i,done;
+       int found=0;
+       uint64_t po = 0;
+       uint64_t q = 0;
+       long count = 0;
+       long c = 0;
+       
+       po = c;
+       while ( count < length && !found && count < MAX_SEARCH) {
+               headr = (uint8_t *)buf+c;
+               c += 4;
+               if (headr[0] == 0x00 && headr[1] == 0x00 && headr[2] == 0x01){
+                       if ( headr[3] == 0xBA ) 
+                               found = 1;
+                       else 
+                               if ( headr[3] == 0xB9 ) break;
+                               else c = po+1;
+               }
+               count++;
+       }
+       
+       if (found){
+               memcpy(p->scr,buf+c,6);
+               c += 6;
+               if (p->scr[0] & 0x40)
+                       p->mpeg = 2;
+               else
+                       p->mpeg = 1;
+
+               if (p->mpeg == 2){
+                       memcpy(p->mux_rate,buf+c,3);
+                       c += 3;
+                       memcpy(&p->stuff_length,buf+c,1);
+                       c++;
+                       po = c;
+                       c = po+(p->stuff_length & 3);
+               } else {
+                       p->mux_rate[0] = p->scr[5]; //mpeg1 scr is only 5 bytes
+                       memcpy(p->mux_rate+1,buf+c,2);
+                       c += 2;
+               }
+                       
+               po = c;
+               headr = (uint8_t *)buf+c;
+               c += 4;
+               if (headr[0] == 0x00 && headr[1] == 0x00 && 
+                   headr[2] == 0x01 && headr[3] == 0xBB ) {
+                       memcpy(p->sheader_llength,buf+c,2);
+                       c += 2;
+                       setl_ps(p);
+                       if (p->mpeg == 2){
+                               memcpy(p->rate_bound,buf+c,3);
+                               c += 3;
+                               memcpy(&p->audio_bound,buf+c,1);
+                               c++;
+                               memcpy(&p->video_bound,buf+c,1);
+                               c++;
+                               memcpy(&p->reserved,buf+c,1);
+                               c++;
+                       }
+                       memcpy(p->data,buf+c,p->sheader_length);
+                       c += p->sheader_length;
+               } else {
+                       c = po;
+                       p->sheader_length = 0;
+               }
+
+               i = 0;
+               done = 0;
+               q = c;
+               do {
+                       headr = (uint8_t *)buf+c;
+                       if ( headr[0] == 0x00 && headr[1] == 0x00 
+                            && headr[2] == 0x01 && headr[3] != 0xBA){
+                               init_pes(&pes);
+                               //      cread_pes(buf+c,&pes);
+                               i++;
+                       } else done = 1;
+                       kill_pes(&pes);
+               } while (c < length && !done);
+               p->npes = i;
+               c = q;
+       } 
+}
+
+
+
+
+
+
+
+/*
+  conversion
+*/
+
+void init_trans(trans *p)
+{
+       int i;
+
+       p->found = 0;
+       p->pes = 0;
+       p->is_full = 0;
+       p->pes_start = 0;
+       p->pes_started = 0;
+       p->set = 0;
+
+       for (i = 0; i < MASKL*MAXFILT ; i++){
+               p->mask[i] = 0;
+               p->filt[i] = 0;
+       }
+       for (i = 0; i < MAXFILT ; i++){
+               p->sec[i].found = 0;
+               p->sec[i].length = 0;
+       }       
+}
+
+int set_trans_filt(trans *p, int filtn, uint16_t pid, uint8_t *mask, uint8_t *filt, int pes)
+{
+       int i;
+       int off;
+
+       if ( filtn > MAXFILT-1 || filtn<0 ) return -1;
+       p->pid[filtn] = pid;
+       if (pes) p->pes |= (tflags)(1 << filtn);
+       else {
+               off = MASKL*filtn;
+               p->pes &= ~((tflags) (1 << filtn) );
+               for (i = 0; i < MASKL ; i++){
+                       p->mask[off+i] = mask[i];
+                       p->filt[off+i] = filt[i];
+               }
+       }               
+       p->set |= (tflags) (1 << filtn);
+       return 0;
+}
+
+void clear_trans_filt(trans *p,int filtn)
+{
+       int i;
+
+       p->set &= ~((tflags) (1 << filtn) );
+       p->pes &= ~((tflags) (1 << filtn) );
+       p->is_full &= ~((tflags) (1 << filtn) );
+       p->pes_start &= ~((tflags) (1 << filtn) );
+       p->pes_started &= ~((tflags) (1 << filtn) );
+
+       for (i = MASKL*filtn; i < MASKL*(filtn+1) ; i++){
+               p->mask[i] = 0;
+               p->filt[i] = 0;
+       }
+       p->sec[filtn].found = 0;
+       p->sec[filtn].length = 0;
+}
+
+int filt_is_set(trans *p, int filtn)
+{
+       if (p->set & ((tflags)(1 << filtn))) return 1;
+       return 0;
+}
+
+int pes_is_set(trans *p, int filtn)
+{
+       if (p->pes & ((tflags)(1 << filtn))) return 1;
+       return 0;
+}
+
+int pes_is_started(trans *p, int filtn)
+{
+       if (p->pes_started & ((tflags)(1 << filtn))) return 1;
+       return 0;
+}
+
+int pes_is_start(trans *p, int filtn)
+{
+       if (p->pes_start & ((tflags)(1 << filtn))) return 1;
+       return 0;
+}
+
+int filt_is_ready(trans *p,int filtn)
+{
+       if (p->is_full & ((tflags)(1 << filtn))) return 1;
+       return 0;
+}
+
+void trans_filt(uint8_t *buf, int count, trans *p)
+{
+       int c=0;
+       //fprintf(stderr,"trans_filt\n");
+       
+
+       while (c < count && p->found <1 ){
+               if ( buf[c] == 0x47) p->found = 1;
+               c++;
+               p->packet[0] = 0x47;
+       }
+       if (c == count) return;
+       
+       while( c < count && p->found < 188 && p->found > 0 ){
+               p->packet[p->found] = buf[c];
+               c++;
+               p->found++;
+       }
+       if (p->found == 188){
+               p->found = 0;
+               tfilter(p);
+       }
+
+       if (c < count) trans_filt(buf+c,count-c,p);
+} 
+
+
+void tfilter(trans *p)
+{
+       int l,c;
+       int tpid;
+       uint8_t flag,flags;
+       uint8_t adapt_length = 0;
+       uint8_t cpid[2];
+
+
+       //      fprintf(stderr,"tfilter\n");
+
+       cpid[0] = p->packet[1];
+       cpid[1] = p->packet[2];
+       tpid = get_pid(cpid);
+
+       if ( p->packet[1]&0x80){
+               fprintf(stderr,"Error in TS for PID: %d\n", 
+                       tpid);
+       }
+
+       flag = cpid[0];
+       flags = p->packet[3];
+       
+       if ( flags & ADAPT_FIELD ) {
+               // adaption field
+               adapt_length = p->packet[4];
+       }
+
+       c = 5 + adapt_length - (int)(!(flags & ADAPT_FIELD));
+       if (flags & PAYLOAD){
+               for ( l = 0; l < MAXFILT ; l++){
+                       if ( filt_is_set(p,l) ) {
+                               if ( p->pid[l] == tpid) {
+                                       if ( pes_is_set(p,l) ){
+                                               if (cpid[0] & PAY_START){
+                                                       p->pes_started |= 
+                                                               (tflags) 
+                                                               (1 << l);
+                                                       p->pes_start |= 
+                                                               (tflags) 
+                                                               (1 << l);
+                                               } else {
+                                                       p->pes_start &= ~ 
+                                                               ((tflags) 
+                                                               (1 << l));
+                                               }
+                                               pes_filter(p,l,c);
+                                       } else {
+                                               sec_filter(p,l,c);
+                                       }       
+                               }
+                       }
+               }
+       }
+}      
+
+
+void pes_filter(trans *p, int filtn, int off)
+{
+       int count,c;
+       uint8_t *buf;
+
+       if (filtn < 0 || filtn >= MAXFILT) return; 
+
+       count = 188 - off;
+       c = 188*filtn;
+       buf = p->packet+off;
+       if (pes_is_started(p,filtn)){
+               p->is_full |= (tflags) (1 << filtn);
+               memcpy(p->transbuf+c,buf,count);
+               p->transcount[filtn] = count;
+       }
+}
+
+section *get_filt_sec(trans *p, int filtn)
+{
+       section *sec;
+       
+       sec = &p->sec[filtn];
+       p->is_full &= ~((tflags) (1 << filtn) );
+       return sec;
+}
+
+int get_filt_buf(trans *p, int filtn,uint8_t **buf)
+{
+       *buf = p->transbuf+188*filtn;
+       p->is_full &= ~((tflags) (1 << filtn) );
+       return p->transcount[filtn];
+}
+
+
+
+
+void sec_filter(trans *p, int filtn, int off)
+{
+       int i,j;
+       int error;
+       int count,c;
+       uint8_t *buf, *secbuf;
+       section *sec;
+
+       //      fprintf(stderr,"sec_filter\n");
+
+       if (filtn < 0 || filtn >= MAXFILT) return; 
+
+       count = 188 - off;
+       c = 0;
+       buf = p->packet+off;
+       sec = &p->sec[filtn];
+       secbuf = sec->payload;
+       if(!filt_is_ready(p,filtn)){
+               p->is_full &= ~((tflags) (1 << filtn) );
+               sec->found = 0;
+               sec->length = 0;
+       }
+               
+       if ( !sec->found ){
+               c = buf[c]+1;
+               if (c >= count) return;
+               sec->id = buf[c];
+               secbuf[0] = buf[c];
+               c++;
+               sec->found++;
+               sec->length = 0;
+       }
+       
+       while ( c < count && sec->found < 3){
+               secbuf[sec->found] = buf[c];
+               c++;
+               sec->found++;
+       }
+       if (c == count) return;
+       
+       if (!sec->length && sec->found == 3){
+               sec->length |= ((secbuf[1] & 0x0F) << 8); 
+               sec->length |= (secbuf[2] & 0xFF);
+       }
+       
+       while ( c < count && sec->found < sec->length+3){
+               secbuf[sec->found] = buf[c];
+               c++;
+               sec->found++;
+       }
+
+       if ( sec->length && sec->found == sec->length+3 ){
+               error=0;
+               for ( i = 0; i < MASKL; i++){
+                       if (i > 0 ) j=2+i;
+                       else j = 0;
+                       error += (sec->payload[j]&p->mask[MASKL*filtn+i])^
+                               (p->filt[MASKL*filtn+i]&
+                                p->mask[MASKL*filtn+i]);
+               }
+               if (!error){
+                       p->is_full |= (tflags) (1 << filtn);
+               }
+               if (buf[0]+1 < c ) c=count;
+       }
+       
+       if ( c < count ) sec_filter(p, filtn, off);
+
+}
+
+#define MULT 1024
+
+
+void write_ps_headr( ps_packet *p, uint8_t *pts,int fd)
+{
+       long  muxr = 37500;
+       uint8_t    audio_bound = 1;
+       uint8_t    fixed = 0;
+       uint8_t    CSPS = 0;
+       uint8_t    audio_lock = 1;
+       uint8_t    video_lock = 1;
+       uint8_t    video_bound = 1;
+       uint8_t    stream1 = 0XC0;
+       uint8_t    buffer1_scale = 1;
+       uint32_t   buffer1_size = 32;
+       uint8_t    stream2 = 0xE0;
+       uint8_t    buffer2_scale = 1;
+       uint32_t   buffer2_size = 230;
+                    
+       init_ps(p);
+       
+       p->mpeg = 2;
+// SCR = 0
+       p->scr[0] = 0x44;
+       p->scr[1] = 0x00;
+       p->scr[2] = 0x04;
+       p->scr[3] = 0x00;
+       p->scr[4] = 0x04;
+       p->scr[5] = 0x01;
+       
+// SCR = PTS
+       p->scr[0] = 0x44 | ((pts[0] >> 3)&0x18) | ((pts[0] >> 4)&0x03);
+       p->scr[1] = 0x00 | ((pts[0] << 4)&0xF0) | ((pts[1] >> 4)&0x0F);
+       p->scr[2] = 0x04 | ((pts[1] << 4)&0xF0) | ((pts[2] >> 4)&0x08)
+               | ((pts[2] >> 5)&0x03);
+       p->scr[3] = 0x00 | ((pts[2] << 3)&0xF8) | ((pts[3] >> 5)&0x07);
+       p->scr[4] = 0x04 | ((pts[3] << 3)&0xF8);
+       p->scr[5] = 0x01;
+       
+       p->mux_rate[0] = (uint8_t)(muxr >> 14);
+       p->mux_rate[1] = (uint8_t)(0xff & (muxr >> 6));
+       p->mux_rate[2] = (uint8_t)(0x03 | ((muxr & 0x3f) << 2));
+
+       p->stuff_length = 0xF8;
+       
+       p->sheader_llength[0] = 0x00;
+       p->sheader_llength[1] = 0x0c;
+
+       setl_ps(p);
+       
+       p->rate_bound[0] = (uint8_t)(0x80 | (muxr >>15));
+       p->rate_bound[1] = (uint8_t)(0xff & (muxr >> 7));
+       p->rate_bound[2] = (uint8_t)(0x01 | ((muxr & 0x7f)<<1));
+       
+       
+       p->audio_bound = (uint8_t)((audio_bound << 2)|(fixed << 1)|CSPS);
+       p->video_bound = (uint8_t)((audio_lock << 7)|
+                             (video_lock << 6)|0x20|video_bound);
+       p->reserved = (uint8_t)(0xFF);
+       
+       p->data[0] =  stream2;
+       p->data[1] =  (uint8_t) (0xc0 | (buffer2_scale << 5) | 
+                           (buffer2_size >> 8));
+       p->data[2] =  (uint8_t) (buffer2_size & 0xff);
+       p->data[3] =  stream1;
+       p->data[4] =  (uint8_t) (0xc0 | (buffer1_scale << 5) | 
+                           (buffer1_size >> 8));
+       p->data[5] =  (uint8_t) (buffer1_size & 0xff);
+       
+       write_ps(fd, p);
+       kill_ps(p);
+}
+
+
+
+void twrite(uint8_t const *buf)
+{
+       int l = TS_SIZE;
+       int c = 0;
+       int w;
+
+
+       while (l){
+               w = write(STDOUT_FILENO,buf+c,l);
+               if (w>=0){
+                       l-=w;
+                       c+=w;
+               }
+       }
+}
+
+void init_p2t(p2t_t *p, void (*fkt)(uint8_t const *buf))
+{
+       memset(p->pes,0,TS_SIZE);
+       p->counter = 0;
+       p->pos = 0;
+       p->frags = 0;
+       if (fkt) p->t_out = fkt;
+       else p->t_out = twrite;
+}
+
+void clear_p2t(p2t_t *p)
+{
+       memset(p->pes,0,TS_SIZE);
+       p->counter = 0;
+       p->pos = 0;
+       p->frags = 0;
+}
+
+
+long int find_pes_header(uint8_t const *buf, long int length, int *frags)
+{
+       int c = 0;
+       int found = 0;
+
+       *frags = 0;
+
+       while (c < length-3 && !found) {
+               if (buf[c] == 0x00 && buf[c+1] == 0x00 && 
+                   buf[c+2] == 0x01) {
+                       switch ( buf[c+3] ) {
+                       case 0xBA:
+                       case PROG_STREAM_MAP:
+                       case PRIVATE_STREAM2:
+                       case PROG_STREAM_DIR:
+                       case ECM_STREAM     :
+                       case EMM_STREAM     :
+                       case PADDING_STREAM :
+                       case DSM_CC_STREAM  :
+                       case ISO13522_STREAM:
+                       case PRIVATE_STREAM1:
+                       case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+                       case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+                               found = 1;
+                               break;
+                               
+                       default:
+                               c++;
+                               break;
+                       }       
+               } else c++;
+       }
+       if (c == length-3 && !found){
+               if (buf[length-1] == 0x00) *frags = 1;
+               if (buf[length-2] == 0x00 &&
+                   buf[length-1] == 0x00) *frags = 2;
+               if (buf[length-3] == 0x00 &&
+                   buf[length-2] == 0x00 &&
+                   buf[length-1] == 0x01) *frags = 3;
+               return -1;
+       }
+
+       return c;
+}
+
+void pes_to_ts( uint8_t const *buf, long int length, uint16_t pid, p2t_t *p)
+{
+       int c,c2,l,add;
+       int check,rest;
+
+       c = 0;
+       c2 = 0;
+       if (p->frags){
+               check = 0;
+               switch(p->frags){
+               case 1:
+                       if ( buf[c] == 0x00 && buf[c+1] == 0x01 ){
+                               check = 1;
+                               c += 2;
+                       }
+                       break;
+               case 2:
+                       if ( buf[c] == 0x01 ){
+                               check = 1;
+                               c++;
+                       }
+                       break;
+               case 3:
+                       check = 1;
+               }
+               if(check){
+                       switch ( buf[c] ) {
+                               
+                       case PROG_STREAM_MAP:
+                       case PRIVATE_STREAM2:
+                       case PROG_STREAM_DIR:
+                       case ECM_STREAM     :
+                       case EMM_STREAM     :
+                       case PADDING_STREAM :
+                       case DSM_CC_STREAM  :
+                       case ISO13522_STREAM:
+                       case PRIVATE_STREAM1:
+                       case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+                       case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+                               p->pes[0] = 0x00;
+                               p->pes[1] = 0x00;
+                               p->pes[2] = 0x01;
+                               p->pes[3] = buf[c];
+                               p->pos=4;
+                               memcpy(p->pes+p->pos,buf+c,TS_SIZE-4-p->pos);
+                               c += TS_SIZE-4-p->pos;
+                               p_to_t(p->pes,TS_SIZE-4,pid,&p->counter,
+                                      p->t_out);
+                               clear_p2t(p);
+                               break;
+                               
+                       default:
+                               c=0;
+                               break;
+                       }
+               }
+               p->frags = 0;
+       }
+               
+       if (p->pos){
+               c2 = find_pes_header(buf+c,length-c,&p->frags);
+               if (c2 >= 0 && c2 < TS_SIZE-4-p->pos){
+                       l = c2+c;
+               } else l = TS_SIZE-4-p->pos;
+               memcpy(p->pes+p->pos,buf,l);
+               c += l;
+               p->pos += l;
+               p_to_t(p->pes,p->pos,pid,&p->counter,
+                      p->t_out);
+               clear_p2t(p);
+       }
+                       
+       add = 0;
+       while (c < length){
+               c2 = find_pes_header(buf+c+add,length-c-add,&p->frags);
+               if (c2 >= 0) {
+                       c2 += c+add;
+                       if (c2 > c){
+                               p_to_t(buf+c,c2-c,pid,&p->counter,
+                                      p->t_out);
+                               c = c2;
+                               clear_p2t(p);
+                               add = 0;
+                       } else add = 1;
+               } else {
+                       l = length-c;
+                       rest = l % (TS_SIZE-4);
+                       l -= rest;
+                       p_to_t(buf+c,l,pid,&p->counter,
+                              p->t_out);
+                       memcpy(p->pes,buf+c+l,rest);
+                       p->pos = rest;
+                       c = length;
+               }
+       }
+}
+
+
+
+void p_to_t( uint8_t const *buf, long int length, uint16_t pid, uint8_t *counter, 
+           void (*ts_write)(uint8_t const *))
+{
+  
+       int l, pes_start;
+       uint8_t obuf[TS_SIZE];
+       long int c = 0;
+       pes_start = 0;
+       if ( length > 3 && 
+            buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x01 )
+               switch (buf[3]){
+                       case PROG_STREAM_MAP:
+                       case PRIVATE_STREAM2:
+                       case PROG_STREAM_DIR:
+                       case ECM_STREAM     :
+                       case EMM_STREAM     :
+                       case PADDING_STREAM :
+                       case DSM_CC_STREAM  :
+                       case ISO13522_STREAM:
+                       case PRIVATE_STREAM1:
+                       case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+                       case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+                               pes_start = 1;
+                               break;
+                               
+                       default:
+                               break;
+               }                       
+
+       while ( c < length ){
+               memset(obuf,0,TS_SIZE);
+               if (length - c >= TS_SIZE-4){
+                       l = write_ts_header(pid, counter, pes_start
+                                            , obuf, TS_SIZE-4);
+                       memcpy(obuf+l, buf+c, TS_SIZE-l);
+                       c += TS_SIZE-l;
+               } else { 
+                       l = write_ts_header(pid, counter, pes_start
+                                            , obuf, length-c);
+                       memcpy(obuf+l, buf+c, TS_SIZE-l);
+                       c = length;
+               }
+               ts_write(obuf);
+               pes_start = 0;
+       }
+}
+
+
+int write_ps_header(uint8_t *buf, 
+                   uint32_t   SCR, 
+                   long  muxr,
+                   uint8_t    audio_bound,
+                   uint8_t    fixed,
+                   uint8_t    CSPS,
+                   uint8_t    audio_lock,
+                   uint8_t    video_lock,
+                   uint8_t    video_bound,
+                   uint8_t    stream1,
+                   uint8_t    buffer1_scale,
+                   uint32_t   buffer1_size,
+                   uint8_t    stream2,
+                   uint8_t    buffer2_scale,
+                   uint32_t   buffer2_size)                    
+{
+       ps_packet p;
+       uint8_t *pts;
+       long lpts;
+       init_ps(&p);
+       
+       lpts = htonl(SCR);
+       pts = (uint8_t *) &lpts;
+
+       
+       p.mpeg = 2;
+// SCR = 0
+       p.scr[0] = 0x44;
+       p.scr[1] = 0x00;
+       p.scr[2] = 0x04;
+       p.scr[3] = 0x00;
+       p.scr[4] = 0x04;
+       p.scr[5] = 0x01;
+       
+// SCR = PTS
+       p.scr[0] = 0x44 | ((pts[0] >> 3)&0x18) | ((pts[0] >> 4)&0x03);
+       p.scr[1] = 0x00 | ((pts[0] << 4)&0xF0) | ((pts[1] >> 4)&0x0F);
+       p.scr[2] = 0x04 | ((pts[1] << 4)&0xF0) | ((pts[2] >> 4)&0x08)
+               | ((pts[2] >> 5)&0x03);
+       p.scr[3] = 0x00 | ((pts[2] << 3)&0xF8) | ((pts[3] >> 5)&0x07);
+       p.scr[4] = 0x04 | ((pts[3] << 3)&0xF8);
+       p.scr[5] = 0x01;
+       
+       p.mux_rate[0] = (uint8_t)(muxr >> 14);
+       p.mux_rate[1] = (uint8_t)(0xff & (muxr >> 6));
+       p.mux_rate[2] = (uint8_t)(0x03 | ((muxr & 0x3f) << 2));
+
+       p.stuff_length = 0xF8;
+       
+       if (stream1 && stream2){
+               p.sheader_llength[0] = 0x00;
+               p.sheader_llength[1] = 0x0c;
+
+               setl_ps(&p);
+               
+               p.rate_bound[0] = (uint8_t)(0x80 | (muxr >>15));
+               p.rate_bound[1] = (uint8_t)(0xff & (muxr >> 7));
+               p.rate_bound[2] = (uint8_t)(0x01 | ((muxr & 0x7f)<<1));
+
+       
+               p.audio_bound = (uint8_t)((audio_bound << 2)|(fixed << 1)|CSPS);
+               p.video_bound = (uint8_t)((audio_lock << 7)|
+                                    (video_lock << 6)|0x20|video_bound);
+               p.reserved = (uint8_t)(0xFF >> 1);
+               
+               p.data[0] =  stream2;
+               p.data[1] =  (uint8_t) (0xc0 | (buffer2_scale << 5) | 
+                                  (buffer2_size >> 8));
+               p.data[2] =  (uint8_t) (buffer2_size & 0xff);
+               p.data[3] =  stream1;
+               p.data[4] =  (uint8_t) (0xc0 | (buffer1_scale << 5) | 
+                                  (buffer1_size >> 8));
+               p.data[5] =  (uint8_t) (buffer1_size & 0xff);
+               
+               cwrite_ps(buf, &p, PS_HEADER_L2);
+               kill_ps(&p);
+               return PS_HEADER_L2;
+       } else {
+               cwrite_ps(buf, &p, PS_HEADER_L1);
+               kill_ps(&p);
+               return PS_HEADER_L1;
+       }
+}
+
+
+
+#define MAX_BASE 80
+#define MAX_PATH 256
+#define MAX_EXT 10
+
+int break_up_filename(char *name, char *base_name, char *path, char *ext)
+{
+       int l,i,sstop,sstart;
+
+       l = strlen(name);
+       sstop = l;
+       sstart = -1;
+       for( i= l-1; i >= 0; i--){
+               if (sstop == l && name[i] == '.') sstop = i;
+               if (sstart<0 && name[i] == '/') sstart = i+1;
+       }
+       if (sstart < 0) sstart = 0;
+       if (sstop-sstart < MAX_BASE){
+               strncpy(base_name, name+sstart, sstop-sstart);
+               base_name[sstop-sstart]=0;
+               if(sstart > 0){
+                       if( l - sstop + sstart < MAX_PATH){
+                               strncpy(path, name, sstart);
+                               path[sstart] = 0;
+                       } else {
+                               fprintf(stderr,"PATH too long\n");
+                               return -1;
+                       }
+
+               } else {
+                       strcpy(path, "./");
+               }
+
+               if(sstop < l){
+                       if( l - sstop -1 < MAX_EXT){
+                               strncpy(ext, name+sstop+1, l-sstop-1);
+                               ext[l-sstop-1]=0;
+                       } else {
+                               fprintf(stderr,"Extension too long\n");
+                               return -1;
+                       }
+
+               } else {
+                       strcpy(ext, "");
+               }
+
+       } else {
+               fprintf(stderr,"Name too long\n");
+               return -1;
+       }
+/*
+        printf("%d %d\n",sstart, sstop);
+        printf("%s %d\n",name, strlen(name));
+        printf("%s %d\n",base_name, strlen(base_name));
+        printf("%s %d\n",path,strlen(path));
+        printf("%s %d\n",ext,strlen(ext));
+*/  
+       return 0;
+}
+
+
+int seek_mpg_start(uint8_t *buf, int size)
+{
+       int found = 0;
+       int c=0;
+       int seq = 0;
+       int mpeg = 0;
+       int mark = 0;
+
+       while ( !seq ){
+               while (found != 4){
+                       switch (found) {
+                       case 0:
+                               if ( buf[c] == 0x00 ) found++;
+                               c++;
+                               break;
+                       case 1:
+                               if ( buf[c] == 0x00 ) found++;
+                               else found = 0;
+                               c++;
+                               break;                     
+                       case 2:
+                               if ( buf[c] == 0x01 ) found++;
+                               else found = 0;
+                               if ( buf[c] == 0x00 ) found = 2;
+                               c++;
+                               break;
+                       
+                       case 3:
+                               if ( (buf[c] & 0xe0) == 0xe0 ) found++;
+                               else found = 0;
+                               c++;
+                               break;
+                       }
+                       if (c >= size) return -1;
+               }
+               
+               if (found == 4){
+                       mark = c-4;
+                       c+=2;
+                       if (c >= size) return -1;
+
+                       if ( (buf[c] & 0xC0) == 0x80 ){
+                               mpeg = 2;
+                               c += 2;
+                               if (c >= size) return -1;
+                               c += buf[c]+1;
+                               if (c >= size) return -1;
+                       } else {
+                               mpeg = 1;
+                               while( buf[c] == 0xFF ) {
+                                       c++;
+                                       if (c >= size) return -1;
+                               }
+                               if ( (buf[c] & 0xC0) == 0x40) c+=2;
+                               if (c >= size) return -1;
+                               if ( (buf[c] & 0x30) ){
+                                       if ( (buf[c] & 0x30) == 0x20) c+=5;
+                                       else c+=10;
+                               } else c++;
+                               if (c >= size) return -1;
+                       }
+
+                       if ( buf[c] == 0x00 && 
+                            buf[c+1] == 0x00 && 
+                            buf[c+2] == 0x01 && 
+                            buf[c+3] == 0xB3 ) 
+                               seq = 1;
+               }
+               found = 0;
+       }
+
+       return size-mark;
+}
+
+
+void write_mpg(int fstart, uint64_t length, int fdin, int fdout)
+{
+//     uint8_t mpeg_end[4] = { 0x00, 0x00, 0x01, 0xB9 };
+       uint8_t *buf;
+       uint64_t l=0;
+       uint64_t count = 0;
+       struct stat sb;
+       int buf_size;
+
+       fstat (fdout, &sb);
+       buf_size =  sb.st_blksize;
+
+       buf = (char *) alloca (buf_size + sizeof (int));
+       
+       lseek(fdin, fstart, SEEK_SET);
+
+       while ( count < length && (l = read(fdin,buf,buf_size)) >= 0){
+               if (l > 0) count+=l;
+               write(fdout,buf,l);
+               printf("written %02.2f%%\r",(100.*count)/length);
+       }
+       printf("\n");
+
+       //write( fdout, mpeg_end, 4);
+}
+
+
+#define CHECKBUF (1024*1024)
+#define ONE_GIG  (1024UL*1024UL*1024UL)
+void split_mpg(char *name, uint64_t size)
+{
+       char base_name[MAX_BASE];
+       char path[MAX_PATH];
+       char ext[MAX_EXT];
+       char new_name[256];
+       uint8_t buf[CHECKBUF];
+       int fdin;
+       int fdout;
+       uint64_t length = 0;
+       uint64_t last;
+       int i;
+       int mark, csize;
+       struct stat sb;
+
+       if (break_up_filename(name,base_name,path,ext) < 0) exit(1);
+
+
+       if ( (fdin = open(name, O_RDONLY|O_LARGEFILE)) < 0){
+               fprintf(stderr,"Can't open %s\n",name);
+               exit(1);
+       }
+
+       fstat (fdin, &sb);
+
+       length = sb.st_size;
+       if ( length < ONE_GIG )
+               printf("Filelength = %2.2f MB\n", length/1024./1024.);
+       else
+               printf("Filelength = %2.2f GB\n", length/1024./1024./1024.);
+
+       if ( length < size ) length = size;
+       
+       printf("Splitting %s into Files with size <= %2.2f MB\n",name,
+              size/1024./1024.);
+       
+       csize = CHECKBUF;
+       read(fdin, buf, csize);
+       if ( (mark = seek_mpg_start(buf,csize)) < 0){
+               fprintf(stderr,"Couldn't find sequence header\n");
+               exit(1);
+       }
+
+       last = csize-mark;
+
+       for ( i = 0 ; i < length/size; i++){
+               csize = CHECKBUF;
+               
+               if (csize > length-last) csize = length-last;
+               lseek(fdin, last+size-csize, SEEK_SET);
+               read(fdin, buf, csize);
+               if ( (mark = seek_mpg_start(buf,csize)) < 0){
+                       fprintf(stderr,"Couldn't find sequence header\n");
+                       exit(1);
+               }
+
+               sprintf(new_name,"%s-%03d.%s",base_name,i,ext);
+               printf("writing %s\n",new_name);
+
+               if ( (fdout = open(new_name,O_WRONLY|O_CREAT|O_TRUNC
+                                  |O_LARGEFILE,
+                                  S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|
+                                  S_IROTH|S_IWOTH)) < 0){
+                       fprintf(stderr,"Can't open %s\n",new_name);
+                       exit(1);
+               }
+               write_mpg(last, size-mark, fdin, fdout);
+               last = last + size - mark;
+       }
+       sprintf(new_name,"%s-%03d.%s",base_name,i,ext);
+       printf("writing %s\n",new_name);
+
+       if ( (fdout = open(new_name,O_WRONLY|O_CREAT|O_TRUNC
+                          |O_LARGEFILE,
+                          S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|
+                          S_IROTH|S_IWOTH)) < 0){
+               fprintf(stderr,"Can't open %s\n",new_name);
+               exit(1);
+       }
+       write_mpg(last, length-last, fdin, fdout);
+}
+
+
+
+
+void cut_mpg(char *name, uint64_t size)
+{
+       char base_name[MAX_BASE];
+       char path[MAX_PATH];
+       char ext[MAX_EXT];
+       char new_name[256];
+       uint8_t buf[CHECKBUF];
+       int fdin;
+       int fdout;
+       uint64_t length = 0;
+       uint64_t last;
+       int mark, csize;
+       struct stat sb;
+
+       if (break_up_filename(name,base_name,path,ext) < 0) exit(1);
+
+
+       if ( (fdin = open(name, O_RDONLY|O_LARGEFILE)) < 0){
+               fprintf(stderr,"Can't open %s\n",name);
+               exit(1);
+       }
+
+       fstat (fdin, &sb);
+
+       length = sb.st_size;
+       if ( length < ONE_GIG )
+               printf("Filelength = %2.2f MB\n", length/1024./1024.);
+       else
+               printf("Filelength = %2.2f GB\n", length/1024./1024./1024.);
+
+       if ( length < size ) length = size;
+       
+       printf("Splitting %s into 2 Files with length %.2f MB and %.2f MB\n",
+              name, size/1024./1024., (length-size)/1024./1024.);
+       
+       csize = CHECKBUF;
+       read(fdin, buf, csize);
+       if ( (mark = seek_mpg_start(buf,csize)) < 0){
+               fprintf(stderr,"Couldn't find sequence header\n");
+               exit(1);
+       }
+
+       last = csize-mark;
+
+       if (csize > length-last) csize = length-last;
+       lseek(fdin, last+size-csize, SEEK_SET);
+       read(fdin, buf, csize);
+       if ( (mark = seek_mpg_start(buf,csize)) < 0){
+               fprintf(stderr,"Couldn't find sequence header\n");
+               exit(1);
+       }
+
+       sprintf(new_name,"%s-1.%s",base_name,ext);
+       printf("writing %s\n",new_name);
+
+       if ( (fdout = open(new_name,O_WRONLY|O_CREAT|O_TRUNC
+                          |O_LARGEFILE,
+                          S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|
+                          S_IROTH|S_IWOTH)) < 0){
+               fprintf(stderr,"Can't open %s\n",new_name);
+               exit(1);
+       }
+       write_mpg(last, size-mark, fdin, fdout);
+       last = last + size - mark;
+
+       sprintf(new_name,"%s-2.%s",base_name,ext);
+       printf("writing %s\n",new_name);
+
+       if ( (fdout = open(new_name,O_WRONLY|O_CREAT|O_TRUNC
+                          |O_LARGEFILE,
+                          S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|
+                          S_IROTH|S_IWOTH)) < 0){
+               fprintf(stderr,"Can't open %s\n",new_name);
+               exit(1);
+       }
+       write_mpg(last, length-last, fdin, fdout);
+}
+
+
+
+
+void write_all (int fd, uint8_t *data, int length)
+{
+        int r;
+
+        while (length) {
+                if ((r = write(fd, data, length)) > 0) {
+                       data += r;
+                       length -= r;
+                }
+        }
+}
+
+
+
+void read_all (int fd, uint8_t *data, int length)
+{
+        int c = 0;
+
+        while(1) {
+                if( read(fd, data+c, 1) == 1) {
+                        c++;
+                        if(data[c-1] == '\n') {
+                                data[c] = 0;
+                                break;
+                        }
+                }
+                else {
+                       fprintf (stderr, "Error reading socket\n");
+                       exit(1);
+                }
+        }
+}
+
+
+
+char *url2host (uint8_t *url, char **name, uint32_t *ip, uint32_t *port)
+{
+       uint8_t *murl;
+       struct hostent *hoste;
+       struct in_addr haddr;
+       int found_ip = 1;
+       
+       if (!(strncmp(url, "http://", 7)))
+               url += 7;
+
+       *name = strdup(url);
+       if (!(*name)) {
+               *name = NULL;
+               return (NULL);
+       }
+
+       murl = url;
+       while (*murl && *murl != ':' && *murl != '/') {
+               if ((*murl < '0' || *murl > '9') && *murl != '.')
+                       found_ip = 0;
+               murl++;
+       }
+
+       (*name)[murl - url] = 0;
+       if (found_ip) {
+               if ((*ip = inet_addr(*name)) == INADDR_NONE)
+                       return (NULL);
+       } else {
+               if (!(hoste = gethostbyname(*name)))
+                       return (NULL);
+               memcpy (&haddr, hoste->h_addr, sizeof(haddr));
+               *ip = haddr.s_addr;
+       }
+
+       if (!*murl || *murl == '/') {
+               *port = 80;
+               return (murl);
+       }
+       *port = atoi(++murl);
+
+       while (*murl && *murl != '/')
+               murl++;
+       return (murl);
+}
+
+#define ACCEPT "Accept: video/mpeg, video/x-mpegurl, */*\r\n"
+
+int http_open (char *url)
+{
+       char purl[1024], *host, req[1024], *sptr;
+       uint32_t ip;
+       uint32_t port;
+       int sock;
+       int reloc, relocnum = 0;
+       struct sockaddr_in server;
+       int mfd;
+
+       strncpy (purl, url, 1023);
+       purl[1023] = '\0';
+
+       do {
+               host = NULL;
+               strcpy (req, "GET ");
+               if (!(sptr = url2host(purl, &host, &ip, &port))) {
+                       fprintf (stderr, "Unknown host\n");
+                       exit (1);
+               }
+               strcat (req, sptr);
+               sprintf (req + strlen(req),
+                        " HTTP/1.0\r\nUser-Agent: %s/%s\r\n",
+                        "whatever", "you want");
+               if (host) {
+                       sprintf(req + strlen(req),
+                               "Host: %s:%u\r\n", host, port);
+                       free (host);
+               }
+
+               strcat (req, ACCEPT);
+               strcat (req, "\r\n");
+               
+               server.sin_port = htons(port);
+               server.sin_family = AF_INET;
+               server.sin_addr.s_addr = ip;
+
+               if ((sock = socket(PF_INET, SOCK_STREAM, 6)) < 0) {
+                       perror ("socket");
+                       exit (1);
+               }
+
+               if (connect(sock, (struct sockaddr *)&server, 
+                           sizeof(server))) {
+                       perror ("connect");
+                       exit (1);
+               }
+               
+               write_all (sock, req, strlen(req));
+               if (!(mfd = fileno(fdopen(sock, "rb")))) {
+                       perror ("open");
+                       exit (1);
+               }
+               reloc = 0;
+               purl[0] = '\0';
+               read_all (mfd, req, 1023);
+               if ((sptr = strchr(req, ' '))) {
+                       switch (sptr[1]) {
+                               case '2':
+                                       break;
+                               case '3':
+                                       reloc = 1;
+                               default:
+                                       fprintf (stderr, "HTTP req failed:%s",
+                                               sptr+1); 
+                                       exit (1);
+                       }
+               }
+               do {
+                       read_all (mfd,req, 1023);
+                       if (!strncmp(req, "Location:", 9))
+                               strncpy (purl, req+10, 1023);
+               } while (req[0] != '\r' && req[0] != '\n');
+       } while (reloc && purl[0] && relocnum++ < 3);
+       if (reloc) {
+               fprintf (stderr, "Too many HTTP relocations.\n");
+               exit (1);
+       }
+
+       return sock;
+}
+
+extern int errno;
+const char * strerrno (void)
+{
+       return strerror(errno);
+}
diff --git a/libdvbmpeg/ctools.h b/libdvbmpeg/ctools.h
new file mode 100644 (file)
index 0000000..a7b0271
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ *  dvb-mpegtools for the Siemens Fujitsu DVB PCI card
+ *
+ * Copyright (C) 2000, 2001 Marcus Metzler 
+ *            for convergence integrated media GmbH
+ * Copyright (C) 2002, 2003 Marcus Metzler 
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ * 
+
+ * The author can be reached at mocm@metzlerbros.de
+
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <libgen.h>
+#include <stdint.h>
+#include <netdb.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+
+#include "ringbuffy.h"
+#include "transform.h"
+
+#ifndef _CTOOLS_H_
+#define _CTOOLS_H_
+
+#define VIDEO_MODE_PAL         0
+#define VIDEO_MODE_NTSC                1
+
+#ifdef __cplusplus
+extern "C" {
+#endif                         /* __cplusplus */
+       
+       enum {PS_STREAM, TS_STREAM, PES_STREAM};
+       enum {pDUNNO, pPAL, pNTSC};
+       
+       uint64_t trans_pts_dts(uint8_t *pts);
+
+/*
+  PES
+*/
+
+#define PROG_STREAM_MAP  0xBC
+#ifndef PRIVATE_STREAM1
+#define PRIVATE_STREAM1  0xBD
+#endif
+#define PADDING_STREAM   0xBE
+#ifndef PRIVATE_STREAM2
+#define PRIVATE_STREAM2  0xBF
+#endif
+#define AUDIO_STREAM_S   0xC0
+#define AUDIO_STREAM_E   0xDF
+#define VIDEO_STREAM_S   0xE0
+#define VIDEO_STREAM_E   0xEF
+#define ECM_STREAM       0xF0
+#define EMM_STREAM       0xF1
+#define DSM_CC_STREAM    0xF2
+#define ISO13522_STREAM  0xF3
+#define PROG_STREAM_DIR  0xFF
+
+#define BUFFYSIZE    10*MAX_PLENGTH
+#define MAX_PTS      8192
+#define MAX_FRAME    8192
+#define MAX_PACK_L   4096
+#define PS_HEADER_L1    14
+#define PS_HEADER_L2    (PS_HEADER_L1+18)
+#define MAX_H_SIZE   (PES_H_MIN + PS_HEADER_L1 + 5)
+#define PES_MIN         7
+#define PES_H_MIN       9
+
+//flags1
+#define FLAGS            0x40
+#define SCRAMBLE_FLAGS   0x30
+#define PRIORITY_FLAG    0x08
+#define DATA_ALIGN_FLAG  0x04
+#define COPYRIGHT_FLAG   0x02
+#define ORIGINAL_FLAG    0x01
+
+//flags2
+#define PTS_DTS_FLAGS    0xC0
+#define ESCR_FLAG        0x20
+#define ES_RATE_FLAG     0x10
+#define DSM_TRICK_FLAG   0x08
+#define ADD_CPY_FLAG     0x04
+#define PES_CRC_FLAG     0x02
+#define PES_EXT_FLAG     0x01
+
+//pts_dts flags 
+#define PTS_ONLY         0x80
+#define PTS_DTS          0xC0
+
+//private flags
+#define PRIVATE_DATA     0x80
+#define HEADER_FIELD     0x40
+#define PACK_SEQ_CTR     0x20
+#define P_STD_BUFFER     0x10
+#define PES_EXT_FLAG2    0x01
+
+#define MPEG1_2_ID       0x40
+#define STFF_LNGTH_MASK  0x3F
+
+
+       typedef struct pes_packet_{
+               uint8_t stream_id;
+               uint8_t llength[2];
+               uint32_t length;
+               uint8_t flags1;
+               uint8_t flags2;
+               uint8_t pes_hlength;
+               uint8_t pts[5];
+               uint8_t dts[5];
+               uint8_t escr[6];
+               uint8_t es_rate[3];
+               uint8_t trick;
+               uint8_t add_cpy;
+               uint8_t prev_pes_crc[2];
+               uint8_t priv_flags;
+               uint8_t pes_priv_data[16];
+               uint8_t pack_field_length;
+               uint8_t *pack_header;
+               uint8_t pck_sqnc_cntr;
+               uint8_t org_stuff_length;
+               uint8_t p_std[2];
+               uint8_t pes_ext_lngth;
+               uint8_t *pes_ext;
+               uint8_t *pes_pckt_data;
+               int padding;
+               int mpeg;
+               int mpeg1_pad;
+               uint8_t *mpeg1_headr;
+               uint8_t stuffing;
+       } pes_packet;
+
+       void init_pes(pes_packet *p);
+       void kill_pes(pes_packet *p);
+       void setlength_pes(pes_packet *p);
+       void nlength_pes(pes_packet *p);
+       int cwrite_pes(uint8_t *buf, pes_packet *p, long length);
+       void write_pes(int fd, pes_packet *p);
+       int read_pes(int f, pes_packet *p);
+       void cread_pes(char *buf, pes_packet *p);
+
+/*
+   Transport Stream
+*/
+
+#define TS_SIZE        188
+#define TRANS_ERROR    0x80
+#define PAY_START      0x40
+#define TRANS_PRIO     0x20
+#define PID_MASK_HI    0x1F
+//flags
+#define TRANS_SCRMBL1  0x80
+#define TRANS_SCRMBL2  0x40
+#define ADAPT_FIELD    0x20
+#define PAYLOAD        0x10
+#define COUNT_MASK     0x0F
+
+// adaptation flags
+#define DISCON_IND     0x80
+#define RAND_ACC_IND   0x40
+#define ES_PRI_IND     0x20
+#define PCR_FLAG       0x10
+#define OPCR_FLAG      0x08
+#define SPLICE_FLAG    0x04
+#define TRANS_PRIV     0x02
+#define ADAP_EXT_FLAG  0x01
+
+// adaptation extension flags
+#define LTW_FLAG       0x80
+#define PIECE_RATE     0x40
+#define SEAM_SPLICE    0x20
+
+       typedef struct  ts_packet_{
+               uint8_t pid[2];
+               uint8_t flags;
+               uint8_t count;
+               uint8_t data[184];
+               uint8_t adapt_length;
+               uint8_t adapt_flags;
+               uint8_t pcr[6];
+               uint8_t opcr[6];
+               uint8_t splice_count;
+               uint8_t priv_dat_len;
+               uint8_t *priv_dat;
+               uint8_t adapt_ext_len;
+               uint8_t adapt_eflags;
+               uint8_t ltw[2];
+               uint8_t piece_rate[3];
+               uint8_t dts[5];
+               int rest;
+               uint8_t stuffing;
+       } ts_packet;
+
+       void init_ts(ts_packet *p);
+       void kill_ts(ts_packet *p);
+       unsigned short pid_ts(ts_packet *p);
+       int cwrite_ts(uint8_t *buf, ts_packet *p, long length);
+       void write_ts(int fd, ts_packet *p);
+       int read_ts(int f, ts_packet *p);
+       void cread_ts (char *buf, ts_packet *p, long length);
+
+
+/*
+   Program Stream
+*/
+
+#define PACK_STUFF_MASK  0x07
+
+#define FIXED_FLAG       0x02
+#define CSPS_FLAG        0x01
+#define SAUDIO_LOCK_FLAG 0x80
+#define SVIDEO_LOCK_FLAG 0x40
+
+#define PS_MAX 200
+
+       typedef struct ps_packet_{
+               uint8_t scr[6];
+               uint8_t mux_rate[3];
+               uint8_t stuff_length;
+               uint8_t *data;
+               uint8_t sheader_llength[2];
+               int sheader_length;
+               uint8_t rate_bound[3];
+               uint8_t audio_bound;
+               uint8_t video_bound;
+               uint8_t reserved;
+               int npes;
+               int mpeg;
+       } ps_packet;
+
+       void init_ps(ps_packet *p);
+       void kill_ps(ps_packet *p);
+       void setlength_ps(ps_packet *p);
+       uint32_t scr_base_ps(ps_packet *p);
+       uint16_t scr_ext_ps(ps_packet *p);
+       int mux_ps(ps_packet *p);
+       int rate_ps(ps_packet *p);
+       int cwrite_ps(uint8_t *buf, ps_packet *p, long length);
+       void write_ps(int fd, ps_packet *p);
+       int read_ps (int f, ps_packet *p);
+       void cread_ps (char *buf, ps_packet *p, long length);
+
+
+
+#define MAX_PLENGTH 0xFFFF
+
+       typedef struct sectionstruct {
+               int  id;
+               int length;
+               int found;
+               uint8_t payload[4096+3];
+       } section;
+
+
+       typedef uint32_t tflags;
+#define MAXFILT 32
+#define MASKL 16
+       typedef struct trans_struct {
+               int found;
+               uint8_t packet[188];
+               uint16_t pid[MAXFILT];
+               uint8_t mask[MAXFILT*MASKL];
+               uint8_t filt[MAXFILT*MASKL];
+               uint8_t transbuf[MAXFILT*188];
+               int transcount[MAXFILT];
+               section sec[MAXFILT];
+               tflags is_full;
+               tflags pes_start;
+               tflags pes_started;
+               tflags pes;
+               tflags set;
+       } trans;
+
+
+       void init_trans(trans *p);
+       int set_trans_filt(trans *p, int filtn, uint16_t pid, uint8_t *mask, 
+                          uint8_t *filt, int pes);
+
+       void clear_trans_filt(trans *p,int filtn);
+       int filt_is_set(trans *p, int filtn);
+       int pes_is_set(trans *p, int filtn);
+       int pes_is_started(trans *p, int filtn);
+       int pes_is_start(trans *p, int filtn);
+       int filt_is_ready(trans *p,int filtn);
+
+       void trans_filt(uint8_t *buf, int count, trans *p);
+       void tfilter(trans *p);
+       void pes_filter(trans *p, int filtn, int off);
+       void sec_filter(trans *p, int filtn, int off);
+       int get_filt_buf(trans *p, int filtn,uint8_t **buf); 
+       section *get_filt_sec(trans *p, int filtn); 
+
+
+       typedef struct a2pstruct{
+               int type;
+               int fd;
+               int found;
+               int length;
+               int headr;
+               int plength;
+               uint8_t cid;
+               uint8_t flags;
+               uint8_t abuf[MAX_PLENGTH];
+               int alength;
+               uint8_t vbuf[MAX_PLENGTH];
+               int vlength;
+               uint8_t last_av_pts[4];
+               uint8_t av_pts[4];
+               uint8_t scr[4];
+               uint8_t pid0;
+               uint8_t pid1;
+               uint8_t pidv;
+               uint8_t pida;
+       } a2p;
+
+
+
+       void get_pespts(uint8_t *av_pts,uint8_t *pts);
+       void init_a2p(a2p *p);
+       void av_pes_to_pes(uint8_t *buf,int count, a2p *p);
+       int w_pesh(uint8_t id,int length ,uint8_t *pts, uint8_t *obuf);
+       int w_tsh(uint8_t id,int length ,uint8_t *pts, uint8_t *obuf,a2p *p,int startpes);
+       void pts2pts(uint8_t *av_pts, uint8_t *pts);
+       void write_ps_headr(ps_packet *p,uint8_t *pts,int fd);
+
+       typedef struct p2t_s{
+               uint8_t           pes[TS_SIZE];
+               uint8_t           counter;
+               long int     pos;
+               int          frags;
+               void         (*t_out)(uint8_t const *buf);
+       } p2t_t;
+
+       void twrite(uint8_t const *buf);
+       void init_p2t(p2t_t *p, void (*fkt)(uint8_t const *buf));
+       long int find_pes_header(uint8_t const *buf, long int length, int *frags);
+       void pes_to_ts( uint8_t const *buf, long int length, uint16_t pid, p2t_t *p);
+       void p_to_t( uint8_t const *buf, long int length, uint16_t pid, 
+                    uint8_t *counter, void (*ts_write)(uint8_t const *));
+
+
+       int write_pes_header(uint8_t id,int length , long PTS, 
+                            uint8_t *obuf, int stuffing);
+
+       int write_ps_header(uint8_t *buf, 
+                           uint32_t   SCR, 
+                           long  muxr,
+                           uint8_t    audio_bound,
+                           uint8_t    fixed,
+                           uint8_t    CSPS,
+                           uint8_t    audio_lock,
+                           uint8_t    video_lock,
+                           uint8_t    video_bound,
+                           uint8_t    stream1,
+                           uint8_t    buffer1_scale,
+                           uint32_t   buffer1_size,
+                           uint8_t    stream2,
+                           uint8_t    buffer2_scale,
+                           uint32_t   buffer2_size);                    
+       
+
+       int seek_mpg_start(uint8_t *buf, int size);
+
+
+       void split_mpg(char *name, uint64_t size);
+       void cut_mpg(char *name, uint64_t size);
+       int http_open (char *url);
+       ssize_t save_read(int fd, void *buf, size_t count);
+
+       const char * strerrno(void);
+#ifdef __cplusplus
+}
+#endif                         /* __cplusplus */
+
+#endif /*_CTOOLS_H_*/
diff --git a/libdvbmpeg/devices.hh b/libdvbmpeg/devices.hh
new file mode 100644 (file)
index 0000000..02c62cd
--- /dev/null
@@ -0,0 +1,310 @@
+#ifndef _channel_hh
+#define _channel_hh
+
+using namespace std;
+#include <stdint.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+
+#include "DVB.hh"
+
+#define MAXNAM 80
+#define MAXKEY 15
+
+const int maxname=80;
+const int MAXAPIDS=32;
+const uint32_t UNSET=0xffffffff;
+const uint16_t NOID=0xffff;
+const uint16_t NOPID=0xffff;
+
+class Transponder {
+public:
+        uint16_t id;
+        uint16_t onid;
+        uint16_t satid;
+        int type;
+        char name[maxname+1];
+        uint32_t freq;
+        int pol;
+        int qam;
+        uint32_t srate;
+        int fec;
+        int band;
+        int hp_rate;         
+       int lp_rate; 
+        int mod;    
+        int transmode;
+        int guard;
+        int hierarchy;
+
+        struct Sat *sat;
+        
+        Transponder() {
+               name[0]='\0';
+               id = NOID;
+               onid = NOID;
+               satid = NOID;
+               type = 0;
+       }
+
+        friend ostream &operator<<(ostream &stream, Transponder &x);
+        friend istream &operator>>(istream &stream, Transponder &x);
+};
+
+class Sat {
+public:
+        uint16_t id;
+        char name[maxname+1];
+        unsigned int lnbid;
+        struct Lnb *lnb;
+        unsigned int rotorid;
+        unsigned int fmin;
+        unsigned int fmax;
+
+        Sat() {
+               id=NOID;
+               name[0]='\0';
+               lnb=NULL;
+               rotorid=NOID;
+               lnbid=NOID;
+               fmin=fmax=0;
+       };
+       int set(int sid, char *sname, int slnbid, int srotorid) {
+         return 0;
+        }; 
+
+        friend ostream &operator<<(ostream &stream, Sat &x);
+        friend istream &operator>>(istream &stream, Sat &x);
+};
+
+
+class Lnb {
+public:
+        Sat *sat;
+        uint16_t id;
+        struct DVB *dvbd;
+        char name[maxname+1];
+        int type;
+        unsigned int lof1;
+        unsigned int lof2;
+        unsigned int slof;
+        int diseqcnr;
+        uint16_t diseqcid;
+        uint16_t swiid;
+
+
+        void cpy (const Lnb &olnb){
+         this->id=olnb.id;
+         this->type=olnb.type;
+         this->lof1=olnb.lof1;
+         this->lof2=olnb.lof2;
+         this->slof=olnb.slof;
+         this->diseqcnr=olnb.diseqcnr;
+         this->diseqcid=olnb.diseqcid;
+         this->swiid=olnb.swiid;
+         strncpy(this->name,olnb.name,maxname);
+       }
+
+        void init(int t, uint l1, uint l2, uint sl,
+                 int dnr, int disid, int sw) {
+               type=t;
+               lof1=l1;
+               lof2=l2;
+               slof=sl;
+               diseqcnr=dnr;
+               diseqcid=disid;
+               swiid=sw;
+               dvbd=0;
+               name[0]='\0';
+       }
+
+        Lnb () {
+               lof1=lof2=slof=0;
+               swiid=NOID;
+               diseqcid=NOID;
+               diseqcnr=-1;
+               name[0]='\0';
+       }
+  
+        Lnb (const Lnb &olnb){
+          cpy(olnb);
+       }
+
+  
+
+        friend ostream &operator<<(ostream &stream, Lnb &x);
+        friend istream &operator>>(istream &stream, Lnb &x);
+};
+
+struct diseqcmsg {
+        int burst;
+        int len;
+        unsigned char msg[8];
+};
+
+class DiSEqC {
+public:
+        uint16_t id;
+        char name[maxname+1];
+        diseqcmsg msgs[4];
+
+        friend ostream &operator<<(ostream &stream, DiSEqC &x);
+        friend istream &operator>>(istream &stream, DiSEqC &x);
+};
+
+class Rotor {
+public:
+        uint16_t id;
+        char name[maxname+1];
+        diseqcmsg msgs[4];
+
+        friend ostream &operator<<(ostream &stream, Rotor &x);
+        friend istream &operator>>(istream &stream, Rotor &x);
+};
+
+class Switch {
+public:
+        uint16_t id;
+        int switchid;
+        char name[maxname+1];
+        diseqcmsg msg;
+
+        friend ostream &operator<<(ostream &stream, Switch &x);
+        friend istream &operator>>(istream &stream, Switch &x);
+};
+
+class Network {
+public:
+        uint16_t id;
+        char name[maxname+1];
+
+        friend ostream &operator<<(ostream &stream, Network &x);
+        friend istream &operator>>(istream &stream, Network &x);
+};
+
+class Bouquet {
+public:
+        uint16_t id;
+        char name[maxname+1];
+
+        friend ostream &operator<<(ostream &stream, Bouquet &x);
+        friend istream &operator>>(istream &stream, Bouquet &x);
+};
+
+
+#define MAX_ECM 16
+#define MAX_ECM_DESC 256
+typedef struct ecm_struct {
+        int num;
+        uint16_t sysid[MAX_ECM];
+        uint16_t pid[MAX_ECM];
+       uint16_t length[MAX_ECM];
+       uint8_t data[MAX_ECM*MAX_ECM_DESC];
+} ecm_t;
+
+
+
+class Channel{
+public:
+        Channel *next;
+        uint32_t id;
+        char name[maxname+1];
+        int32_t type;
+       int checked;
+  
+        uint16_t pnr;
+        uint16_t vpid;
+        uint16_t apids[MAXAPIDS];
+        char apids_name[MAXAPIDS*4];
+        int32_t  apidnum;
+        int  last_apidn;
+        uint16_t ac3pid;
+        uint16_t ttpid;
+        uint16_t pmtpid;
+        uint16_t pcrpid;
+        uint16_t casystem;
+        uint16_t capid;
+
+       ecm_t  ecm;
+       int (*ecm_callback)(Channel *chan);
+
+       int has_eit;
+       int pres_follow;
+
+        uint16_t satid;
+        uint16_t tpid;
+        uint16_t onid;
+        uint16_t bid;
+       int8_t eit_ver_n;
+       int8_t eit_ver_c;
+
+        void clearall(void) {
+               id=UNSET;
+               name[0]='\0';
+               type=0;
+               checked = 0;
+               has_eit = -1;
+               pres_follow = -1;
+               eit_ver_c = -1;
+               eit_ver_n = -1;
+               
+               pnr=NOPID;
+               vpid=NOPID;
+               memset(apids, 0, sizeof(uint16_t)*MAXAPIDS);
+               memset(apids_name, 0, sizeof(char)*MAXAPIDS*4);
+               apidnum=0;
+               last_apidn=-1;
+               ac3pid=NOPID;
+               ttpid=NOPID;
+               pmtpid=NOPID;
+               pcrpid=NOPID;
+               capid=NOPID;
+
+               satid=NOID;
+               tpid=NOID;
+               onid=NOID;
+               bid=NOID;
+               ecm_callback = NULL;
+               memset(&ecm,0, sizeof(ecm_t));
+       };
+
+        Channel() {
+               clearall();
+       }
+  
+        Channel(int cid, char *nam, int ty, int prognr,
+               int vid, int aid, int tid) {
+               int l=strlen(nam);
+
+               clearall();
+               if (l>maxname){
+                 cerr << "" << endl; 
+                 l=maxname;
+               }
+               strncpy(name, nam, l);
+               name[l]='\0';
+               type=ty;
+               pnr=prognr;
+               vpid=vid;
+               apids[0]=aid;
+       }
+
+#ifdef DEBUG
+        ~Channel(){
+               cerr <<"Channel " << name << "  destroyed" << endl;
+       }
+#endif
+  
+        friend ostream &operator<<(ostream &stream, Channel &x);
+        friend istream &operator>>(istream &stream, Channel &x);
+};
+
+int findkey(char *name, char *keys[]);
+void getname(char *name,istream &ins);
+#endif /*channel.h*/
diff --git a/libdvbmpeg/osd.hh b/libdvbmpeg/osd.hh
new file mode 100644 (file)
index 0000000..9c6b530
--- /dev/null
@@ -0,0 +1,84 @@
+#ifndef _OSD_HH_
+#define _OSD_HH_
+
+extern "C" {
+#include "OSD.h"
+}
+struct OSD {
+        int dev;
+        
+        void init(int d) {
+               dev=d;
+       }
+        int Open(int x0, int y0, int x1, int y1, int BitPerPixel, int mix, int win) {
+               if (OSDSetWindow(dev, win))
+                       return -1;
+               return OSDOpen(dev, x0, y0, x1, y1, BitPerPixel, mix);
+       }
+        int Open(int x0, int y0, int x1, int y1, int BitPerPixel, int mix) {
+               return OSDOpen(dev, x0, y0, x1, y1, BitPerPixel, mix);
+       }
+        int Close(int win) {
+               if (OSDSetWindow(dev, win))
+                       return -1;
+               return OSDClose(dev);
+       }
+        int Close(void) {
+               return OSDClose(dev);
+       }
+        int Show(void) {
+               return OSDShow(dev);
+       }
+        int Hide(void) {
+               return OSDHide(dev);
+       }
+        int Clear(void) {
+               return OSDClear(dev);
+       }
+        int Fill(int color) {
+               return OSDFill(dev, color);
+       }
+        int SetColor(int color, int r, int g, int b, int op) {
+               return OSDSetColor(dev, color, r, g, b, op);
+       }
+        int Text(int x, int y, int size, int color, const char *text) {
+               return OSDText(dev, x, y, size, color, text); 
+       }
+        int SetPalette(int first, int last, unsigned char *data) {
+               return OSDSetPalette(dev, first, last, data);
+
+       }
+        int SetTrans(int trans) {
+               return OSDSetTrans(dev, trans);
+
+       }
+        int SetPixel(int dev, int x, int y, unsigned int color) {
+               return OSDSetPixel(dev, x, y, color); 
+       }
+        int GetPixel(int dev, int x, int y) {
+               return OSDGetPixel(dev, x, y); 
+       }
+        int SetRow(int x, int y, int x1, unsigned char *data) {
+               return OSDSetRow(dev, x, y, x1, data); 
+       }
+        int SetBlock(int x, int y, int x1, int y1, int inc, unsigned char *data) {
+               return OSDSetBlock(dev, x, y, x1, y1, inc, data); 
+       }
+        int FillRow(int x, int y, int x1, int color) {
+               return OSDFillRow(dev, x, y, x1, color); 
+       }
+        int FillBlock(int x, int y, int x1, int y1, int color) {
+               return OSDFillBlock(dev, x, y, x1, y1, color); 
+       }
+        int Line(int x, int y, int x1, int y1, int color) {
+               return OSDLine(dev, x, y, x1, y1, color); 
+       }
+        int Query() {
+               return OSDQuery(dev); 
+       }
+        int SetWindow(int win) {
+               return OSDSetWindow(dev, win); 
+       }
+};
+
+#endif
diff --git a/libdvbmpeg/remux.c b/libdvbmpeg/remux.c
new file mode 100644 (file)
index 0000000..6f8a44f
--- /dev/null
@@ -0,0 +1,1215 @@
+/*
+ *  dvb-mpegtools for the Siemens Fujitsu DVB PCI card
+ *
+ * Copyright (C) 2000, 2001 Marcus Metzler 
+ *            for convergence integrated media GmbH
+ * Copyright (C) 2002 Marcus Metzler 
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ * 
+
+ * The author can be reached at mocm@metzlerbros.de, 
+ */
+
+#include "remux.h"
+
+unsigned int bitrates[3][16] =
+{{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
+ {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0},
+ {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}};
+
+uint32_t freq[4] = {441, 480, 320, 0};
+static uint32_t samples[4] = { 384, 1152, 0, 0};
+char *frames[3] = {"I-Frame","P-Frame","B-Frame"};
+
+
+void copy_ptslm(PTS_List *a, PTS_List *b)
+{
+       a->pos  = b->pos;
+       a->PTS  = b->PTS;
+       a->dts  = b->dts;
+       a->spos = b->spos;
+}
+
+void clear_ptslm(PTS_List *a)
+{
+       a->pos  = 0;
+       a->PTS  = 0;
+       a->dts  = 0;
+       a->spos = 0;    
+}
+
+void init_ptsl(PTS_List *ptsl)
+{
+       int i;
+       for (i=0;i< MAX_PTS;i++){
+               clear_ptslm(&ptsl[i]);
+       }
+}
+
+int del_pts(PTS_List *ptsl, int pos, int nr)
+{
+       int i;
+       int del = 0;
+
+       for( i = 0; i < nr-1; i++){
+               if(pos > ptsl[i].pos && pos >= ptsl[i+1].pos) del++;
+       }
+
+       if(del)
+               for( i = 0; i < nr-del; i++){
+                       copy_ptslm(&ptsl[i], &ptsl[i+del]);
+               }
+
+       return nr-del;
+}
+
+int del_ptss(PTS_List *ptsl, int pts, int *nb)
+{
+       int i;
+       int del = 0;
+       int sum = 0;
+       int nr = *nb;
+
+       for( i = 0; i < nr; i++){
+               if(pts > ptsl[i].PTS){
+                       del++;
+                       sum += ptsl[i].pos;
+               }
+       }
+
+       if(del)
+               for( i = 0; i < nr-del; i++){
+                       copy_ptslm(&ptsl[i], &ptsl[i+del]);
+               }
+
+       *nb = nr-del;
+       return sum;
+}
+
+int add_pts(PTS_List *ptsl, uint32_t pts, int pos, int spos, int nr, uint32_t dts)
+{
+       int i;
+
+       for ( i=0;i < nr; i++) if (spos &&  ptsl[i].pos == pos) return nr;
+       if (nr == MAX_PTS) {
+               nr = del_pts(ptsl, ptsl[1].pos+1, nr);
+       } else nr++;
+       i = nr-1;
+       
+       ptsl[i].pos  = pos;
+       ptsl[i].spos = spos;
+       ptsl[i].PTS  = pts;
+       ptsl[i].dts  = dts;
+       return nr;
+}
+
+void add_vpts(Remux *rem, uint8_t *pts)
+{
+       uint32_t PTS = trans_pts_dts(pts);
+       rem->vptsn = add_pts(rem->vpts_list, PTS, rem->vwrite, rem->awrite,
+                            rem->vptsn, PTS);
+}
+
+void add_apts(Remux *rem, uint8_t *pts)
+{
+       uint32_t PTS = trans_pts_dts(pts);
+       rem->aptsn = add_pts(rem->apts_list, PTS, rem->awrite, rem->vwrite,
+                            rem->aptsn, PTS);
+}
+
+void del_vpts(Remux *rem)
+{
+       rem->vptsn = del_pts(rem->vpts_list, rem->vread, rem->vptsn);
+}
+
+void del_apts(Remux *rem)
+{
+       rem->aptsn = del_pts(rem->apts_list, rem->aread, rem->aptsn);
+}
+
+
+void copy_framelm(FRAME_List *a, FRAME_List *b)
+{
+       a->type  = b->type;
+       a->pos   = b->pos;
+       a->FRAME = b->FRAME;
+       a->time  = b->time;
+       a->pts   = b->pts;
+       a->dts   = b->dts;
+}
+
+void clear_framelm(FRAME_List *a)
+{
+       a->type  = 0;
+       a->pos   = 0;
+       a->FRAME = 0;
+       a->time  = 0; 
+       a->pts   = 0; 
+       a->dts   = 0; 
+}
+
+void init_framel(FRAME_List *framel)
+{
+       int i;
+       for (i=0;i< MAX_FRAME;i++){
+               clear_framelm(&framel[i]);
+       }
+}
+
+int del_frame(FRAME_List *framel, int pos, int nr)
+{
+       int i;
+       int del = 0;
+
+       for( i = 0; i < nr-1; i++){
+               if(pos > framel[i].pos && pos >= framel[i+1].pos) del++;
+       }
+
+       if(del)
+               for( i = 0; i < nr-del; i++){
+                       copy_framelm(&framel[i], &framel[i+del]);
+               }
+
+       return nr-del;
+}
+
+int add_frame(FRAME_List *framel, uint32_t frame, int pos, int type, int nr, 
+             uint32_t time, uint32_t pts, uint32_t dts)
+{
+       int i;
+
+       if (nr == MAX_FRAME) {
+               nr = del_frame(framel, framel[1].pos+1, nr);
+       } else nr++;
+       i = nr-1;
+       
+       framel[i].type  = type;
+       framel[i].pos   = pos;
+       framel[i].FRAME = frame;
+       framel[i].time  = time;
+       framel[i].pts   = pts;
+       framel[i].dts   = dts;
+       return nr;
+}
+
+void add_vframe(Remux *rem, uint32_t frame, long int pos, int type, int time, 
+               uint32_t pts, uint32_t dts)
+{
+       rem->vframen = add_frame(rem->vframe_list, frame, pos, type,
+                                rem->vframen, time, pts, dts);
+}
+
+void add_aframe(Remux *rem, uint32_t frame, long int pos, uint32_t pts)
+{
+       rem->aframen = add_frame(rem->aframe_list, frame, pos, 0, 
+                                rem->aframen, 0, pts, pts);
+}
+
+void del_vframe(Remux *rem)
+{
+       rem->vframen = del_frame(rem->vframe_list, rem->vread, rem->vframen);
+}
+
+void del_aframe(Remux *rem)
+{
+       rem->aframen = del_frame(rem->aframe_list, rem->aread, rem->aframen);
+}
+
+
+void printpts(uint32_t pts)
+{
+       fprintf(stderr,"%2d:%02d:%02d.%03d",
+               (int)(pts/90000.)/3600,
+               ((int)(pts/90000.)%3600)/60,
+               ((int)(pts/90000.)%3600)%60,
+               (((int)(pts/90.)%3600000)%60000)%1000
+               );
+}
+
+
+void find_vframes( Remux *rem, uint8_t *buf, int l)
+{
+       int c = 0;
+       int type;
+       uint32_t time = 0;
+       int hour;
+       int min;
+       int sec;
+       uint64_t pts=0;
+       uint64_t dts=0;
+       uint32_t tempref = 0;
+
+       while ( c < l - 6){
+               if (buf[c] == 0x00 && 
+                   buf[c+1] == 0x00 &&
+                   buf[c+2] == 0x01 && 
+                   buf[c+3] == 0xB8) {
+                       c += 4;
+                       hour = (int)((buf[c]>>2)& 0x1F);
+                       min  = (int)(((buf[c]<<4)& 0x30)| 
+                                    ((buf[c+1]>>4)& 0x0F));
+                       sec  = (int)(((buf[c+1]<<3)& 0x38)|
+                                     ((buf[c+2]>>5)& 0x07));
+  
+                       time = 3600*hour + 60*min + sec;
+                       if ( rem->time_off){
+                               time = (uint32_t)((uint64_t)time - rem->time_off);
+                               hour = time/3600;
+                               min  = (time%3600)/60;
+                               sec  = (time%3600)%60;
+                               /*
+                               buf[c]   |= (hour & 0x1F) << 2;
+                               buf[c]   |= (min & 0x30) >> 4;
+                               buf[c+1] |= (min & 0x0F) << 4;
+                               buf[c+1] |= (sec & 0x38) >> 3;
+                               buf[c+2] |= (sec & 0x07) >> 5;*/
+                       }
+                       rem->group++;
+                       rem->groupframe = 0;
+               }
+               if ( buf[c] == 0x00 && 
+                    buf[c+1] == 0x00 &&
+                    buf[c+2] == 0x01 && 
+                    buf[c+3] == 0x00) {
+                       c += 4;
+                       tempref = (buf[c+1]>>6) & 0x03;
+                       tempref |= buf[c] << 2;
+                       
+                       type = ((buf[c+1]&0x38) >>3);
+                       if ( rem->video_info.framerate){
+                               pts = ((uint64_t)rem->vframe + tempref + 1 
+                                       - rem->groupframe ) * 90000ULL
+                                           /rem->video_info.framerate 
+                                       + rem->vpts_off;
+                               dts = (uint64_t)rem->vframe * 90000ULL/
+                                       rem->video_info.framerate 
+                                       + rem->vpts_off;
+                       
+
+fprintf(stderr,"MYPTS:");
+printpts((uint32_t)pts-rem->vpts_off);
+ fprintf(stderr,"   REALPTS:");
+ printpts(rem->vpts_list[rem->vptsn-1].PTS-rem->vpts_off);
+ fprintf(stderr,"   DIFF:");
+ printpts(pts-(uint64_t)rem->vpts_list[rem->vptsn-1].PTS);
+// fprintf(stderr,"   DIST: %4d",-rem->vpts_list[rem->vptsn-1].pos+(rem->vwrite+c-4));
+ //fprintf(stderr,"   ERR: %3f",(double)(-rem->vpts_list[rem->vptsn-1].PTS+pts)/(rem->vframe+1));
+ fprintf(stderr,"\r");
+
+                               
+                               
+                               rem->vptsn = add_pts(rem->vpts_list,(uint32_t)pts
+                                                    ,rem->vwrite+c-4,
+                                                    rem->awrite,
+                                                    rem->vptsn,
+                                                    (uint32_t)dts);
+
+                               
+                               
+                       }
+                       rem->vframe++;
+                       rem->groupframe++;
+                       add_vframe( rem, rem->vframe, rem->vwrite+c, type, 
+                                   time, pts, dts);
+               } else c++;
+       }
+}
+
+void find_aframes( Remux *rem, uint8_t *buf, int l)
+{
+       int c = 0;
+       uint64_t pts = 0;
+       int sam;
+       uint32_t fr;
+
+
+       while ( c < l - 2){
+               if ( buf[c] == 0xFF && 
+                    (buf[c+1] & 0xF8) == 0xF8) {
+                       c += 2;
+                       if ( rem->audio_info.layer >= 0){
+                               sam = samples[3-rem->audio_info.layer];
+                               fr = freq[rem->audio_info.frequency] ;
+               
+                         pts = ( (uint64_t)rem->aframe * sam * 900ULL)/fr
+                                 + rem->apts_off;
+                               
+
+fprintf(stderr,"MYPTS:");
+printpts((uint32_t)pts-rem->apts_off);
+ fprintf(stderr," REALPTS:");
+ printpts(rem->apts_list[rem->aptsn-1].PTS-rem->apts_off);
+ fprintf(stderr," DIFF:");
+ printpts((uint32_t)((uint64_t)rem->apts_list[rem->aptsn-1].PTS-pts));
+// fprintf(stderr," DIST: %4d",-rem->apts_list[rem->aptsn-1].pos+(rem->awrite+c-2));
+ fprintf(stderr,"\r");
+
+                         rem->aptsn = add_pts(rem->apts_list,(uint32_t)pts
+                                            ,rem->awrite+c-2,
+                                            rem->vwrite,
+                                            rem->aptsn,
+                                            (uint32_t)pts);
+               }
+
+                       rem->aframe++;
+                       add_aframe( rem, rem->aframe, rem->awrite+c, pts);
+                       
+               } else c++;
+       }
+}
+
+int refill_buffy(Remux *rem)
+{
+       pes_packet pes;
+       int count = 0;
+       int acount, vcount;
+       ringbuffy *vbuf = &rem->vid_buffy;
+       ringbuffy *abuf = &rem->aud_buffy;
+       int fin = rem->fin;
+
+       acount = abuf->size-ring_rest(abuf);
+       vcount = vbuf->size-ring_rest(vbuf);
+       
+       
+       while ( acount > MAX_PLENGTH && vcount > MAX_PLENGTH && count < 10){
+               int neof;
+               count++;
+               init_pes(&pes);
+               if ((neof = read_pes(fin,&pes)) <= 0) return -1;
+               switch(pes.stream_id){
+               case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+                       rem->apes++;
+                       if( rem->audio_info.layer < 0 &&
+                           (pes.flags2 & PTS_DTS) )
+                               add_apts(rem, pes.pts);
+                       find_aframes( rem, pes.pes_pckt_data, pes.length);
+                       ring_write(abuf,(char *)pes.pes_pckt_data,pes.length);
+                       rem->awrite += pes.length;
+                       break;
+               case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+                       rem->vpes++;
+                       if( !rem->video_info.framerate &&
+                           (pes.flags2 & PTS_DTS) )
+                               add_vpts(rem, pes.pts);
+
+                       find_vframes( rem, pes.pes_pckt_data, pes.length);
+
+                       ring_write(vbuf,(char *)pes.pes_pckt_data,pes.length);
+                       rem->vwrite += pes.length;
+                       break;
+               }
+               acount = abuf->size-ring_rest(abuf);
+               vcount = vbuf->size-ring_rest(vbuf);
+               kill_pes(&pes);
+       }
+       if (count < 10) return 0;
+       return 1;
+}
+
+int vring_read( Remux *rem, uint8_t *buf, int l)
+{
+       int c = 0;
+       int r = 0;
+
+       if (ring_rest(&rem->vid_buffy) <= l)
+               r = refill_buffy(rem);
+       if (r) return -1;
+
+       c = ring_read(&rem->vid_buffy, (char *) buf, l);
+       rem->vread += c;
+       del_vpts(rem);
+       del_vframe(rem);
+       return c;
+}
+
+int aring_read( Remux *rem, uint8_t *buf, int l)
+{
+       int c = 0;
+       int r = 0;
+
+       if (ring_rest(&rem->aud_buffy) <= l)
+               r = refill_buffy(rem);
+       if (r) return -1;
+       
+       c = ring_read(&rem->aud_buffy, (char *)buf, l);
+       rem->aread += c;
+       del_apts(rem);
+       del_aframe(rem);
+       return c;
+}
+
+int vring_peek( Remux *rem, uint8_t *buf, int l, long off)
+{
+       int c = 0;
+       
+       if (ring_rest(&rem->vid_buffy) <= l)
+               refill_buffy(rem);
+
+       c = ring_peek(&rem->vid_buffy, (char *) buf, l, off);
+       return c;
+}
+
+int aring_peek( Remux *rem, uint8_t *buf, int l, long off)
+{
+       int c = 0;
+
+       if (ring_rest(&rem->aud_buffy) <= l)
+               refill_buffy(rem);
+
+       c = ring_peek(&rem->aud_buffy, (char *)buf, l, off);
+       return c;
+}
+
+
+int get_video_info(Remux *rem)
+{
+       uint8_t buf[12];
+       uint8_t *headr;
+       int found = 0;
+        int sw;
+       long off = 0;
+       int form = -1;
+       ringbuffy *vid_buffy = &rem->vid_buffy;
+       VideoInfo *vi = &rem->video_info;
+
+       while (found < 4 && ring_rest(vid_buffy)){
+               uint8_t b[3];
+
+               vring_peek( rem, b, 4, 0);
+               if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01
+                    && b[3] == 0xb3) found = 4;
+               else {
+                       off++;
+                       vring_read( rem, b, 1);
+               }
+       }
+       rem->vframe = rem->vframen-1;
+
+       if (! found) return -1;
+       buf[0] = 0x00; buf[1] = 0x00; buf[2] = 0x01; buf[3] = 0xb3;
+       headr = buf+4;
+       if(vring_peek(rem, buf, 12, 0) < 12) return -1;
+
+       vi->horizontal_size     = ((headr[1] &0xF0) >> 4) | (headr[0] << 4);
+       vi->vertical_size       = ((headr[1] &0x0F) << 8) | (headr[2]);
+    
+        sw = (int)((headr[3]&0xF0) >> 4) ;
+
+        switch( sw ){
+       case 1:
+               fprintf(stderr,"Videostream: ASPECT: 1:1");
+               vi->aspect_ratio = 100;        
+               break;
+       case 2:
+               fprintf(stderr,"Videostream: ASPECT: 4:3");
+                vi->aspect_ratio = 133;        
+               break;
+       case 3:
+               fprintf(stderr,"Videostream: ASPECT: 16:9");
+                vi->aspect_ratio = 177;        
+               break;
+       case 4:
+               fprintf(stderr,"Videostream: ASPECT: 2.21:1");
+                vi->aspect_ratio = 221;        
+               break;
+
+        case 5 ... 15:
+               fprintf(stderr,"Videostream: ASPECT: reserved");
+                vi->aspect_ratio = 0;        
+               break;
+
+        default:
+                vi->aspect_ratio = 0;        
+                return -1;
+       }
+
+        fprintf(stderr,"  Size = %dx%d",vi->horizontal_size,vi->vertical_size);
+
+        sw = (int)(headr[3]&0x0F);
+
+        switch ( sw ) {
+       case 1:
+               fprintf(stderr,"  FRate: 23.976 fps");
+                vi->framerate = 24000/1001.;
+               form = -1;
+               break;
+       case 2:
+               fprintf(stderr,"  FRate: 24 fps");
+                vi->framerate = 24;
+               form = -1;
+               break;
+       case 3:
+               fprintf(stderr,"  FRate: 25 fps");
+                vi->framerate = 25;
+               form = VIDEO_MODE_PAL;
+               break;
+       case 4:
+               fprintf(stderr,"  FRate: 29.97 fps");
+                vi->framerate = 30000/1001.;
+               form = VIDEO_MODE_NTSC;
+               break;
+       case 5:
+               fprintf(stderr,"  FRate: 30 fps");
+                vi->framerate = 30;
+               form = VIDEO_MODE_NTSC;
+               break;
+       case 6:
+               fprintf(stderr,"  FRate: 50 fps");
+                vi->framerate = 50;
+               form = VIDEO_MODE_PAL;
+               break;
+       case 7:
+               fprintf(stderr,"  FRate: 60 fps");
+                vi->framerate = 60;
+               form = VIDEO_MODE_NTSC;
+               break;
+       }
+
+       rem->dts_delay = (int)(7.0/vi->framerate/2.0*90000);
+
+       vi->bit_rate = 400*(((headr[4] << 10) & 0x0003FC00UL) 
+                           | ((headr[5] << 2) & 0x000003FCUL) | 
+                           (((headr[6] & 0xC0) >> 6) & 0x00000003UL));
+       
+        fprintf(stderr,"  BRate: %.2f Mbit/s",(vi->bit_rate)/1000000.);
+       
+        fprintf(stderr,"\n");
+        vi->video_format = form;
+
+       /*
+       marker_bit (&video_bs, 1);
+       vi->vbv_buffer_size     = getbits (&video_bs, 10);
+       vi->CSPF                = get1bit (&video_bs);
+       */
+       return form;
+}
+
+
+int get_audio_info( Remux *rem)
+{
+       uint8_t *headr;
+       uint8_t buf[3];
+       long off = 0;
+       int found = 0;
+       ringbuffy *aud_buffy = &rem->aud_buffy;
+       AudioInfo *ai = &rem->audio_info;
+       
+       while(!ring_rest(aud_buffy) && !refill_buffy(rem));
+       while (found < 2 && ring_rest(aud_buffy)){
+               uint8_t b[2];
+               refill_buffy(rem);
+               aring_peek( rem, b, 2, 0);
+
+               if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8)
+                       found = 2;
+               else {
+                       off++;
+                       aring_read( rem, b, 1);
+               }
+       }       
+
+       if (!found) return -1;
+       rem->aframe = rem->aframen-1;
+       
+       if (aring_peek(rem, buf, 3, 0) < 1) return -1;
+       headr = buf+2;
+
+       ai->layer = (buf[1] & 0x06) >> 1;
+
+        fprintf(stderr,"Audiostream: Layer: %d", 4-ai->layer);
+
+
+       ai->bit_rate = bitrates[(3-ai->layer)][(headr[0] >> 4 )]*1000;
+
+       if (ai->bit_rate == 0)
+               fprintf (stderr,"  Bit rate: free");
+       else if (ai->bit_rate == 0xf)
+               fprintf (stderr,"  BRate: reserved");
+       else
+               fprintf (stderr,"  BRate: %d kb/s", ai->bit_rate/1000);
+       
+
+       ai->frequency = (headr[0] & 0x0c ) >> 2;
+       if (ai->frequency == 3)
+               fprintf (stderr, "  Freq: reserved\n");
+       else
+               fprintf (stderr,"  Freq: %2.1f kHz\n", 
+                        freq[ai->frequency]/10.);
+
+       return 0;
+}
+
+
+
+void init_remux(Remux *rem, int fin, int fout, int mult)
+{
+       rem->video_info.framerate = 0;
+       rem->audio_info.layer = -1;
+       rem->fin = fin;
+       rem->fout = fout;
+       ring_init(&rem->vid_buffy, 40*BUFFYSIZE*mult);
+       ring_init(&rem->aud_buffy, BUFFYSIZE*mult);
+       init_ptsl(rem->vpts_list);
+       init_ptsl(rem->apts_list);
+       init_framel(rem->vframe_list);
+       init_framel(rem->aframe_list);
+
+       rem->vptsn     = 0;
+       rem->aptsn     = 0;
+       rem->vframen   = 0;
+       rem->aframen   = 0;
+       rem->vframe    = 0;
+       rem->aframe    = 0;
+       rem->vcframe   = 0;
+       rem->acframe   = 0;
+       rem->vpts      = 0;
+       rem->vdts      = 0;
+       rem->apts_off  = 0;
+       rem->vpts_off  = 0;
+       rem->apts_delay= 0;
+       rem->vpts_delay= 0;
+       rem->dts_delay = 0;
+       rem->apts      = 0;
+       rem->vpes      = 0;
+       rem->apes      = 0;
+       rem->vpts_old  = 0;
+       rem->apts_old  = 0;
+       rem->SCR       = 0;
+       rem->vwrite    = 0;
+       rem->awrite    = 0;
+       rem->vread     = 0;
+       rem->aread     = 0;
+       rem->group     = 0;
+       rem->groupframe= 0;
+       rem->pack_size = 0;
+       rem->muxr      = 0;
+       rem->time_off  = 0;
+}
+
+uint32_t bytes2pts(int bytes, int rate)
+{
+       if (bytes < 0xFFFFFFFFUL/720000UL)
+               return (uint32_t)(bytes*720000UL/rate);
+       else
+               return (uint32_t)(bytes/rate*720000UL);
+}
+
+long pts2bytes( uint32_t pts, int rate)
+{
+       if (pts < 0xEFFFFFFFUL/rate)
+               return (pts*rate/720000);
+       else 
+               return (pts* (rate/720000));
+}
+
+int write_audio_pes( Remux *rem, uint8_t *buf, int *alength)
+{
+       int add;
+       int pos = 0;
+       int p   = 0;
+       uint32_t pts = 0;
+       int stuff = 0;
+       int length = *alength;
+
+       if (!length) return 0;
+       p = PS_HEADER_L1+PES_H_MIN;
+
+       if (rem->apts_old != rem->apts){
+               pts = (uint32_t)((uint64_t)rem->apts + rem->apts_delay - rem->apts_off);
+               p += 5;
+       }
+       if ( length+p >= rem->pack_size){
+               length = rem->pack_size;
+       } else {
+               if (rem->pack_size-length-p <= PES_MIN){
+                       stuff = rem->pack_size - length;
+                       length = rem->pack_size;
+               } else 
+                       length = length+p;
+       }
+       pos = write_ps_header(buf,rem->SCR,rem->muxr, 1, 0, 0, 1, 1, 1, 
+                             0, 0, 0, 0, 0, 0);
+
+       pos += write_pes_header( 0xC0, length-pos, pts, buf+pos, stuff);
+       add = aring_read( rem, buf+pos, length-pos);
+       *alength = add;
+       if (add < 0) return -1;
+       pos += add;
+       rem->apts_old = rem->apts;
+       rem->apts = rem->apts_list[0].PTS;
+
+       if (pos+PES_MIN < rem->pack_size){
+               pos += write_pes_header( PADDING_STREAM, rem->pack_size-pos, 0,
+                                        buf+pos, 0);
+               pos = rem->pack_size;
+       }               
+       if (pos != rem->pack_size) {
+               fprintf(stderr,"apos: %d\n",pos);
+               exit(1);
+       }
+
+       return pos;
+}
+
+int write_video_pes( Remux *rem, uint8_t *buf, int *vlength)
+{
+       int add;
+       int pos = 0;
+       int p   = 0;
+       uint32_t pts = 0;
+       uint32_t dts = 0;
+       int stuff = 0;
+       int length = *vlength;
+       long diff = 0;
+
+       if (! length) return 0;
+       p = PS_HEADER_L1+PES_H_MIN;
+
+       if (rem->vpts_old != rem->vpts){
+               pts = (uint32_t)((uint64_t)rem->vpts + rem->vpts_delay - rem->vpts_off);
+               p += 5;
+       }
+       if ( length+p >= rem->pack_size){
+               length = rem->pack_size;
+       } else {
+               if (rem->pack_size - length - p <= PES_MIN){
+                       stuff = rem->pack_size - length;
+                       length = rem->pack_size;
+               } else 
+                       length = length+p;
+       }
+
+       pos = write_ps_header(buf,rem->SCR,rem->muxr, 1, 0, 0, 1, 1, 1, 
+                             0, 0, 0, 0, 0, 0);
+
+       pos += write_pes_header( 0xE0, length-pos, pts, buf+pos, stuff);
+       add = vring_read( rem, buf+pos, length-pos);
+       *vlength = add;
+       if (add < 0) return -1;
+       pos += add;
+       rem->vpts_old = rem->vpts;
+       dts = rem->vdts;
+       rem->vpts = rem->vpts_list[0].PTS;
+       rem->vdts = rem->vpts_list[0].dts;
+       if ( diff > 0) rem->SCR += diff;
+       if (pos+PES_MIN < rem->pack_size){
+               //  fprintf(stderr,"vstuffing: %d   \n",rem->pack_size-pos);
+               pos += write_pes_header( PADDING_STREAM, rem->pack_size-pos, 0,
+                                        buf+pos, 0);
+               pos = rem->pack_size;
+       }               
+       return pos;
+}
+
+void print_info( Remux *rem , int ret)
+{
+       int newtime = 0;
+       static int time = 0;
+       int i = 0;
+
+       while(! newtime && i < rem->vframen) {
+               if( (newtime = rem->vframe_list[i].time)) break;
+               i++;
+       }
+       if (newtime) time = newtime;
+       
+       fprintf(stderr,"SCR:");
+       printpts(rem->SCR);
+       fprintf(stderr," VDTS:");
+       printpts((uint32_t)((uint64_t)rem->vdts - rem->vpts_off + rem->vpts_delay));
+       fprintf(stderr," APTS:");
+       printpts((uint32_t)((uint64_t)rem->apts - rem->apts_off + rem->apts_delay));
+       fprintf(stderr," TIME:%2d:", time/3600);
+       fprintf(stderr,"%02d:", (time%3600)/60);
+       fprintf(stderr,"%02d", (time%3600)%60);
+       if (ret) fprintf(stderr,"\n");
+       else fprintf(stderr,"\r");
+}
+
+void remux(int fin, int fout, int pack_size, int mult)
+{
+       Remux rem;
+       long ptsdiff;
+       uint8_t buf[MAX_PACK_L];
+       long pos = 0;
+       int r = 0;
+       int i, r1, r2;
+       long packets = 0;
+       uint8_t mpeg_end[4] = { 0x00, 0x00, 0x01, 0xB9 };
+       uint32_t SCR_inc = 0;
+       int data_size;
+       long vbuf, abuf;
+       long vbuf_max, abuf_max;
+       PTS_List abufl[MAX_PTS];
+       PTS_List vbufl[MAX_PTS];
+       int abufn = 0;
+       int vbufn = 0;
+       uint64_t pts_d = 0;
+       int ok_audio; 
+       int ok_video; 
+       uint32_t apos = 0;
+       uint32_t vpos = 0;
+       int vpack_size = 0;
+       int apack_size = 0;
+
+       init_ptsl(abufl);
+       init_ptsl(vbufl);
+
+       if (mult < 0 || mult >1000){
+               fprintf(stderr,"Multipler too large\n");
+               exit(1);
+       }
+       init_remux(&rem, fin, fout, mult);
+       rem.pack_size = pack_size;
+       data_size = pack_size - MAX_H_SIZE;
+       fprintf(stderr,"pack_size: %d header_size: %d data size: %d\n",
+               pack_size, MAX_H_SIZE, data_size);
+       refill_buffy(&rem);
+       fprintf(stderr,"Package size: %d\n",pack_size);
+       
+       if ( get_video_info(&rem) < 0 ){
+               fprintf(stderr,"ERROR: Can't find valid video stream\n");
+               exit(1);
+       }
+
+       i = 0;
+       while(! rem.time_off && i < rem.vframen) {
+               if( (rem.time_off = rem.vframe_list[i].time)) break;
+               i++;
+       }
+
+       if ( get_audio_info(&rem) < 0 ){
+               fprintf(stderr,"ERROR: Can't find valid audio stream\n");
+               exit(1);
+       }
+       
+       rem.vpts = rem.vpts_list[0].PTS;
+       rem.vdts = rem.vpts;
+       rem.vpts_off = rem.vpts;
+       fprintf(stderr,"Video start PTS = %fs \n",rem.vpts_off/90000.);
+       rem.apts = rem.apts_list[0].PTS;
+       rem.apts_off = rem.apts;
+       ptsdiff = rem.vpts - rem.apts;
+       if (ptsdiff > 0) rem.vpts_off -= ptsdiff;
+       else rem.apts_off -= -ptsdiff;
+       fprintf(stderr,"Audio start PTS = %fs\n",rem.apts_off/90000.);
+       fprintf(stderr,"Difference Video - Audio = %fs\n",ptsdiff/90000.);
+       fprintf(stderr,"Time offset = %ds\n",rem.time_off);
+
+       rem.muxr = (rem.video_info.bit_rate + 
+                   rem.audio_info.bit_rate)/400;
+       fprintf(stderr,"MUXRATE: %.2f Mb/sec\n",rem.muxr/2500.);
+       SCR_inc = 1800 * pack_size / rem.muxr;
+       
+       r = 0;
+       while ( rem.vptsn < 2 && !r) r = refill_buffy(&rem);
+       r = 0;
+       while ( rem.aptsn < 2 && !r) r = refill_buffy(&rem);
+
+       //rem.vpts_delay =  (uint32_t)(2*90000ULL* (uint64_t)pack_size/rem.muxr);
+       rem.vpts_delay = rem.dts_delay;
+       rem.apts_delay = rem.vpts_delay;
+
+       vbuf_max = 29440;
+       abuf_max = 4096;
+       vbuf = 0;
+       abuf = 0;
+       pos = write_ps_header(buf,rem.SCR,rem.muxr, 1, 0, 0, 1, 1, 1, 
+                             0xC0, 0, 32, 0xE0, 1, 230);
+       pos += write_pes_header( PADDING_STREAM, pack_size-pos, 0, buf+pos,0);
+       pos = rem.pack_size;
+       write( fout, buf, pos);
+
+       apos = rem.aread;
+       vpos = rem.vread;
+       print_info( &rem, 1 );
+
+       while( ring_rest(&rem.aud_buffy) && ring_rest(&rem.vid_buffy) ){
+               uint32_t next_apts;
+               uint32_t next_vdts;
+               int asize, vsize;
+
+               r1 = 0;
+               r2 = 0;
+               while ( rem.aframen < 2 && !r1) 
+                       r1 = refill_buffy(&rem);
+               while ( rem.vframen < 2 && !r2) 
+                       r2 = refill_buffy(&rem);
+               if (r1 && r2) break;
+
+               if ( !r1 && apos <= rem.aread)
+                       apos = rem.aframe_list[1].pos;
+               if ( !r2 && vpos <= rem.vread)
+                       vpos = rem.vframe_list[1].pos;
+               apack_size = apos - rem.aread; 
+               vpack_size = vpos - rem.vread; 
+               
+
+               next_vdts = (uint32_t)((uint64_t)rem.vdts + rem.vpts_delay 
+                                 - rem.vpts_off) ;
+               ok_video = ( rem.SCR < next_vdts);
+
+               next_apts = (uint32_t)((uint64_t)rem.apts + rem.apts_delay 
+                                 - rem.apts_off) ;
+               ok_audio = ( rem.SCR  < next_apts);
+
+               asize = (apack_size > data_size ? data_size: apack_size);
+               vsize = (vpack_size > data_size ? data_size: vpack_size);
+
+               fprintf(stderr,"vframen: %d  aframen: %d  v_ok: %d  a_ok: %d  v_buf: %d  a_buf: %d vpacks: %d  apacks: %d\n",rem.vframen,rem.aframen, ok_video, ok_audio, (int)vbuf,(int)abuf,vsize, asize);
+               
+
+               if( vbuf+vsize  < vbuf_max && vsize && ok_audio ){
+                       fprintf(stderr,"1 ");
+                       pos = write_video_pes( &rem, buf, &vpack_size);
+                       write( fout, buf, pos);
+                       vbuf += vpack_size;
+                       vbufn = add_pts( vbufl, rem.vdts, vpack_size, 
+                                        0, vbufn, 0);
+                       packets++;
+               } else if ( abuf+asize < abuf_max && asize &&
+                           ok_video  ){
+                       fprintf(stderr,"2 ");
+                       pos = write_audio_pes( &rem, buf, &apack_size);
+                       write( fout, buf, pos);
+                       abuf += apack_size;
+                       abufn = add_pts( abufl, rem.apts, apack_size, 
+                                        0, abufn, 0);
+                       packets++;
+               } else if ( abuf+asize < abuf_max && asize &&
+                           !ok_audio){
+                       fprintf(stderr,"3 ");
+                       pos = write_audio_pes( &rem, buf, &apack_size);
+                       write( fout, buf, pos);
+                       abuf += apack_size;
+                       abufn = add_pts( abufl, rem.apts, apack_size, 
+                                        0, abufn, 0);
+                       packets++;
+               } else if (vbuf+vsize  < vbuf_max && vsize &&
+                          !ok_video){
+                       fprintf(stderr,"4 ");
+                       pos = write_video_pes( &rem, buf, &vpack_size);
+                       write( fout, buf, pos);
+                       vbuf += vpack_size;
+                       vbufn = add_pts( vbufl, rem.vdts, vpack_size, 
+                                        0, vbufn, 0);
+                       packets++;
+               } else {
+               fprintf(stderr,"5 ");
+                       pos = write_ps_header(buf,rem.SCR,rem.muxr, 1, 0, 0, 
+                                             1, 1, 1, 0, 0, 0, 0, 0, 0);
+
+                       pos += write_pes_header( PADDING_STREAM, pack_size-pos,
+                                                0, buf+pos, 0);
+                       write( fout, buf, pos);
+               }
+
+
+               //fprintf(stderr,"vbufn: %d  abufn: %d  ", vbufn,abufn);
+               //fprintf(stderr,"vbuf: %5d  abuf: %4d\n", vbuf,abuf);
+
+               if (rem.SCR > rem.vdts+rem.vpts_off -rem.vpts_delay) 
+                       rem.SCR = rem.vdts-rem.vpts_off;
+               rem.SCR = (uint32_t)((uint64_t) rem.SCR + SCR_inc);
+
+               if ( rem.apts_off + rem.SCR < rem.apts_delay ) pts_d = 0;
+               else pts_d = (uint64_t) rem.SCR + rem.apts_off - rem.apts_delay;
+               abuf -= del_ptss( abufl, (uint32_t) pts_d, &abufn);
+
+               if ( rem.vpts_off + rem.SCR < rem.vpts_delay ) pts_d = 0;
+               else pts_d = (uint64_t) rem.SCR + rem.vpts_off - rem.vpts_delay;
+               vbuf -= del_ptss( vbufl, (uint32_t) pts_d, &vbufn);
+
+               print_info( &rem, 1);
+               //fprintf(stderr,"vbufn: %d  abufn: %d  ", vbufn,abufn);
+               //fprintf(stderr,"vbuf: %5d  abuf: %4d\n\n", vbuf,abuf);
+
+
+       }
+       pos = write_ps_header(buf,rem.SCR,rem.muxr, 1, 0, 0, 1, 1, 1, 
+                             0, 0, 0, 0, 0, 0);
+
+       pos += write_pes_header( PADDING_STREAM, pack_size-pos-4, 0, 
+                                buf+pos, 0);
+       pos = rem.pack_size-4;
+       write( fout, buf, pos);
+
+       write( fout, mpeg_end, 4);
+       fprintf(stderr,"\ndone\n");
+}
+
+
+typedef 
+struct pes_buffer_s{
+       ringbuffy   pes_buffy;
+       uint8_t     type;
+       PTS_List    pts_list[MAX_PTS];
+       FRAME_List  frame_list[MAX_FRAME];
+       int         pes_size;
+       uint64_t    written;
+       uint64_t    read;
+} PESBuffer;
+
+
+void init_PESBuffer(PESBuffer *pbuf, int pes_size, int buf_size, uint8_t type)
+{
+       init_framel( pbuf->frame_list);
+       init_ptsl( pbuf->pts_list);
+       ring_init( &pbuf->pes_buffy, buf_size);
+       pbuf->pes_size = pes_size;
+       pbuf->type = type; 
+       pbuf->written = 0;
+       pbuf->read = 0;
+}
+       
+
+#define MAX_PBUF 4
+
+typedef
+struct remux_s{
+       PESBuffer pbuf_list[MAX_PBUF];
+       int num_pbuf;
+} REMUX;
+
+
+void init_REMUX(REMUX *rem)
+{
+       rem->num_pbuf = 0;
+}
+
+
+
+#define REPACK      2048 
+#define ABUF_SIZE   REPACK*1024
+#define VBUF_SIZE   REPACK*10240
+
+void remux_main(uint8_t *buf, int count, void *pr)
+{
+       int i, b;
+       int bufsize = 0;
+       p2p *p = (p2p *) pr;
+       PESBuffer *pbuf;
+       REMUX *rem = (REMUX *) p->data;
+       uint8_t type = buf[3];
+       int *npbuf = &(rem->num_pbuf);
+
+       switch ( type ){
+       case PRIVATE_STREAM1:
+               bufsize = ABUF_SIZE;
+       case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+               if (!bufsize) bufsize = VBUF_SIZE;
+       case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+               if (!bufsize) bufsize = ABUF_SIZE;
+               b = -1;
+               for ( i = 0; i < *npbuf; i++){
+                       if ( type == rem->pbuf_list[i].type ){
+                               b = i;
+                               break;
+                       }
+               }
+               if (b < 0){
+                       if ( *npbuf < MAX_PBUF ){
+                               init_PESBuffer(&rem->pbuf_list[*npbuf], 
+                                              p->repack+6, bufsize, type);
+                               b = *npbuf;
+                               (*npbuf)++;
+                       } else {
+                               fprintf(stderr,"Not enough PES buffers\n");
+                               exit(1);
+                       }
+               }
+               break;
+       default:
+               return;
+       }
+       
+       pbuf = &(rem->pbuf_list[b]);
+       if (ring_write(&(pbuf->pes_buffy),(char *)buf,count) != count){
+               fprintf(stderr,"buffer overflow type 0x%2x\n",type);
+               exit(1);
+       } else {
+               pbuf->written += count;
+               if ((p->flag2 & PTS_DTS_FLAGS)){
+                       uint32_t PTS = trans_pts_dts(p->pts);
+                       add_pts(pbuf->pts_list, PTS, pbuf->written, 
+                               pbuf->written, 0, 0);
+               }
+               p->flag2 = 0;
+       }
+
+}
+
+void output_mux(p2p *p) 
+{
+       int i, filling;
+       PESBuffer *pbuf;
+       ringbuffy   *pes_buffy; 
+       REMUX *rem = (REMUX *) p->data;
+       int repack = p->repack;
+       int npbuf = rem->num_pbuf;
+
+       for ( i = 0; i < npbuf; i++){
+               pbuf = &(rem->pbuf_list[i]);
+               pes_buffy = &pbuf->pes_buffy;
+               filling = pes_buffy->size - ring_rest(pes_buffy);
+               if (filling/(2 *repack)){
+                       pbuf->read += ring_read_file(pes_buffy, p->fd1, 
+                                                    (filling/repack)*repack);
+               }
+       }
+}
+
+
+
+#define SIZE 32768
+
+void remux2(int fdin, int fdout)
+{
+       p2p p;
+       int count = 1;
+       uint8_t buf[SIZE];
+       uint64_t length = 0;
+       uint64_t l = 0;
+       int verb = 0;
+       REMUX rem;
+       
+       init_p2p(&p, remux_main, REPACK);
+       p.fd1 = fdout;
+       p.data = (void *) &rem;
+       
+
+       if (fdin != STDIN_FILENO) verb = 1; 
+
+       if (verb) {
+               length = lseek(fdin, 0, SEEK_END);
+               lseek(fdin,0,SEEK_SET);
+       }
+
+       while (count > 0){
+               count = read(fdin,buf,SIZE);
+               l += count;
+               if (verb)
+                       fprintf(stderr,"Writing  %2.2f %%\r",
+                               100.*l/length);
+
+               get_pes(buf,count,&p,pes_repack);
+               output_mux(&p);
+       }
+               
+}
diff --git a/libdvbmpeg/remux.h b/libdvbmpeg/remux.h
new file mode 100644 (file)
index 0000000..76c128b
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ *  dvb-mpegtools for the Siemens Fujitsu DVB PCI card
+ *
+ * Copyright (C) 2000, 2001 Marcus Metzler 
+ *            for convergence integrated media GmbH
+ * Copyright (C) 2002 Marcus Metzler 
+ * 
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ * 
+
+ * The author can be reached at mocm@metzlerbros.de, 
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+//#include <libgen.h>
+#include <stdint.h>
+
+#include "ringbuffy.h"
+#include "ctools.h"
+
+#ifndef _REMUX_H_
+#define _REMUX_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif                         /* __cplusplus */
+
+       typedef struct video_i{
+               uint32_t horizontal_size;
+               uint32_t vertical_size  ;
+               uint32_t aspect_ratio   ;
+               double framerate        ;
+               uint32_t video_format;
+               uint32_t bit_rate       ;
+               uint32_t comp_bit_rate  ;
+               uint32_t vbv_buffer_size;
+               uint32_t CSPF           ;
+               uint32_t off;
+       } VideoInfo;            
+
+       typedef struct audio_i{
+               int layer;
+               uint32_t bit_rate;
+               uint32_t frequency;
+               uint32_t mode;
+               uint32_t mode_extension;
+               uint32_t emphasis;
+               uint32_t framesize;
+               uint32_t off;
+       } AudioInfo;
+
+
+
+       typedef
+       struct PTS_list_struct{
+               uint32_t PTS;
+               int pos;
+               uint32_t dts;
+               int spos;
+       } PTS_List;
+
+       typedef
+       struct frame_list_struct{
+               int type;
+               int pos;
+               uint32_t FRAME;
+               uint32_t time;
+               uint32_t pts;
+               uint32_t dts;
+       } FRAME_List;
+
+       typedef
+       struct remux_struct{
+               ringbuffy vid_buffy;
+               ringbuffy aud_buffy;
+               PTS_List vpts_list[MAX_PTS];
+               PTS_List apts_list[MAX_PTS];
+               FRAME_List vframe_list[MAX_FRAME];
+               FRAME_List aframe_list[MAX_FRAME];
+               int vptsn;
+               int aptsn;
+               int vframen;
+               int aframen;
+               long apes;
+               long vpes;
+               uint32_t vframe;
+               uint32_t aframe;
+               uint32_t vcframe;
+               uint32_t acframe;
+               uint32_t vpts;
+               uint32_t vdts;
+               uint32_t apts;
+               uint32_t vpts_old;
+               uint32_t apts_old;
+               uint32_t SCR;
+               uint32_t apts_off;
+               uint32_t vpts_off;
+               uint32_t apts_delay;
+               uint32_t vpts_delay;
+               uint32_t dts_delay;
+               AudioInfo audio_info;
+               VideoInfo video_info;
+               int fin;
+               int fout;
+               long int awrite;
+               long int vwrite;
+               long int aread;
+               long int vread;
+               uint32_t group;
+               uint32_t groupframe;
+               uint32_t muxr;
+               int pack_size;
+               uint32_t time_off;
+       } Remux;
+
+       enum { NONE, I_FRAME, P_FRAME, B_FRAME, D_FRAME };
+
+       void remux(int fin, int fout, int pack_size, int mult);
+       void remux2(int fdin, int fdout);
+#ifdef __cplusplus
+}
+#endif                         /* __cplusplus */
+
+#endif /*_REMUX_H_*/
diff --git a/libdvbmpeg/ringbuffy.c b/libdvbmpeg/ringbuffy.c
new file mode 100644 (file)
index 0000000..8451009
--- /dev/null
@@ -0,0 +1,200 @@
+/* 
+    Ringbuffer Implementation for gtvscreen
+
+    Copyright (C) 2000 Marcus Metzler (mocm@metzlerbros.de)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "ringbuffy.h"
+
+int ring_init (ringbuffy *rbuf, int size)
+{
+       if (size > 0){
+               rbuf->size = size;
+               if( !(rbuf->buffy = (char *) malloc(sizeof(char)*size)) ){
+                       fprintf(stderr,"Not enough memory for ringbuffy\n");
+                       return -1;
+               }
+       } else {
+               fprintf(stderr,"Wrong size for ringbuffy\n");
+               return -1;
+       }
+       rbuf->read_pos = 0;     
+       rbuf->write_pos = 0;
+       return 0;
+}
+
+
+void ring_destroy(ringbuffy *rbuf)
+{
+       free(rbuf->buffy);
+}
+
+
+int ring_write(ringbuffy *rbuf, char *data, int count)
+{
+
+       int diff, free, pos, rest;
+
+       if (count <=0 ) return 0;
+               pos  = rbuf->write_pos;
+       rest = rbuf->size - pos;
+       diff = rbuf->read_pos - pos;
+       free = (diff > 0) ? diff-1 : rbuf->size+diff-1;
+
+       if ( free <= 0 ) return FULL_BUFFER;
+       if ( free < count ) count = free;
+       
+       if (count >= rest){
+               memcpy (rbuf->buffy+pos, data, rest);
+               if (count - rest)
+                       memcpy (rbuf->buffy, data+rest, count - rest);
+               rbuf->write_pos = count - rest;
+       } else {
+               memcpy (rbuf->buffy+pos, data, count);
+               rbuf->write_pos += count;
+       }
+
+       return count;
+}
+
+
+
+
+int ring_peek(ringbuffy *rbuf, char *data, int count, long off)
+{
+
+       int diff, free, pos, rest;
+
+       if (count <=0 ) return 0;
+       pos  = rbuf->read_pos+off;
+       rest = rbuf->size - pos ;
+       diff = rbuf->write_pos - pos;
+       free = (diff >= 0) ? diff : rbuf->size+diff;
+
+       if ( free <= 0 ) return FULL_BUFFER;
+       if ( free < count ) count = free;
+       
+       if ( count < rest ){
+               memcpy(data, rbuf->buffy+pos, count);
+       } else {
+               memcpy(data, rbuf->buffy+pos, rest);
+               if ( count - rest)
+                       memcpy(data+rest, rbuf->buffy, count - rest);
+       }
+
+       return count;
+}
+
+int ring_read(ringbuffy *rbuf, char *data, int count)
+{
+
+       int diff, free, pos, rest;
+
+       if (count <=0 ) return 0;
+       pos  = rbuf->read_pos;
+       rest = rbuf->size - pos;
+       diff = rbuf->write_pos - pos;
+       free = (diff >= 0) ? diff : rbuf->size+diff;
+
+       if ( rest <= 0 ) return 0;
+       if ( free < count ) count = free;
+       
+       if ( count < rest ){
+               memcpy(data, rbuf->buffy+pos, count);
+               rbuf->read_pos += count;
+       } else {
+               memcpy(data, rbuf->buffy+pos, rest);
+               if ( count - rest)
+                       memcpy(data+rest, rbuf->buffy, count - rest);
+               rbuf->read_pos = count - rest;
+       }
+
+       return count;
+}
+
+
+
+int ring_write_file(ringbuffy *rbuf, int fd, int count)
+{
+
+       int diff, free, pos, rest, rr;
+
+       if (count <=0 ) return 0;
+               pos  = rbuf->write_pos;
+       rest = rbuf->size - pos;
+       diff = rbuf->read_pos - pos;
+       free = (diff > 0) ? diff-1 : rbuf->size+diff-1;
+
+       if ( rest <= 0 ) return 0;
+       if ( free < count ) count = free;
+       
+       if (count >= rest){
+               rr = read (fd, rbuf->buffy+pos, rest);
+               if (rr == rest && count - rest)
+                       rr += read (fd, rbuf->buffy, count - rest);
+               if (rr >=0)
+                       rbuf->write_pos = (pos + rr) % rbuf->size;
+       } else {
+               rr = read (fd, rbuf->buffy+pos, count);
+               if (rr >=0)
+                       rbuf->write_pos += rr;
+       }
+
+       return rr;
+}
+
+
+
+int ring_read_file(ringbuffy *rbuf, int fd, int count)
+{
+
+       int diff, free, pos, rest, rr;
+
+       if (count <=0 ) return 0;
+       pos  = rbuf->read_pos;
+       rest = rbuf->size - pos;
+       diff = rbuf->write_pos - pos;
+       free = (diff >= 0) ? diff : rbuf->size+diff;
+
+       if ( free <= 0 ) return FULL_BUFFER;
+       if ( free < count ) count = free;
+
+       if (count >= rest){
+               rr = write (fd, rbuf->buffy+pos, rest);
+               if (rr == rest && count - rest)
+                       rr += write (fd, rbuf->buffy, count - rest);
+               if (rr >=0)
+                       rbuf->read_pos = (pos + rr) % rbuf->size;
+       } else {
+               rr = write (fd, rbuf->buffy+pos, count);
+               if (rr >=0)
+                       rbuf->read_pos += rr;
+       }
+
+
+       return rr;
+}
+
+int ring_rest(ringbuffy *rbuf){
+               int diff, free, pos, rest;
+       pos  = rbuf->read_pos;
+       rest = rbuf->size - pos;
+       diff = rbuf->write_pos - pos;
+       free = (diff >= 0) ? diff : rbuf->size+diff;
+       
+       return free;
+}
diff --git a/libdvbmpeg/ringbuffy.h b/libdvbmpeg/ringbuffy.h
new file mode 100644 (file)
index 0000000..16011d7
--- /dev/null
@@ -0,0 +1,52 @@
+/* 
+    Ringbuffer Implementation for gtvscreen
+
+    Copyright (C) 2000 Marcus Metzler (mocm@metzlerbros.de)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef RINGBUFFY_H
+#define RINGBUFFY_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif                         /* __cplusplus */
+
+#define FULL_BUFFER  -1000
+typedef struct ringbuffy{
+       int read_pos;
+       int write_pos;
+       int size;
+       char *buffy;
+} ringbuffy;
+
+int  ring_init (ringbuffy *rbuf, int size);
+void ring_destroy(ringbuffy *rbuf);
+int ring_write(ringbuffy *rbuf, char *data, int count);
+int ring_read(ringbuffy *rbuf, char *data, int count);
+int ring_write_file(ringbuffy *rbuf, int fd, int count);
+int ring_read_file(ringbuffy *rbuf, int fd, int count);
+int ring_rest(ringbuffy *rbuf);
+int ring_peek(ringbuffy *rbuf, char *data, int count, long off);
+
+#ifdef __cplusplus
+}
+#endif                         /* __cplusplus */
+#endif /* RINGBUFFY_H */
diff --git a/libdvbmpeg/transform.c b/libdvbmpeg/transform.c
new file mode 100644 (file)
index 0000000..c53f1fb
--- /dev/null
@@ -0,0 +1,2681 @@
+/*
+ *  dvb-mpegtools for the Siemens Fujitsu DVB PCI card
+ *
+ * Copyright (C) 2000, 2001 Marcus Metzler 
+ *            for convergence integrated media GmbH
+ * Copyright (C) 2002  Marcus Metzler 
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ * 
+
+ * The author can be reached at marcus@convergence.de, 
+
+ * the project's page is at http://linuxtv.org/dvb/
+ */
+
+
+#include "transform.h"
+#include <stdlib.h>
+#include <string.h>
+#include "ctools.h"
+
+static uint8_t tspid0[TS_SIZE] = { 
+       0x47, 0x40, 0x00, 0x10, 0x00, 0x00, 0xb0, 0x11, 
+       0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00, 0xe0, 
+       0x10, 0x00, 0x01, 0xe4, 0x00, 0x2a, 0xd6, 0x1a, 
+       0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff
+};
+
+static uint8_t tspid1[TS_SIZE] = { 
+       0x47, 0x44, 0x00, 0x10, 0x00, 0x02, 0xb0, 0x1c,
+       0x00, 0x01, 0xcb, 0x00, 0x00, 0xe0, 0xa0, 0xf0, 
+       0x05, 0x48, 0x03, 0x01, 0x00, 0x00, 0x02, 0xe0,
+       0xa0, 0xf0, 0x00, 0x03, 0xe0, 0x50, 0xf0, 0x00, 
+       0xae, 0xea, 0x4e, 0x48, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff
+};
+
+// CRC32 lookup table for polynomial 0x04c11db7
+static const uint32_t crc_table[256] = {
+  0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
+  0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+  0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
+  0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+  0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
+  0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+  0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
+  0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+  0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
+  0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+  0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
+  0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+  0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
+  0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+  0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
+  0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+  0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
+  0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+  0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
+  0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+  0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
+  0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+  0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
+  0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+  0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
+  0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+  0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
+  0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+  0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
+  0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+  0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
+  0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+  0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
+  0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+  0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
+  0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+  0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
+  0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+  0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
+  0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+  0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
+  0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+  0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+};
+
+static uint32_t
+calc_crc32 (const uint8_t *sec, uint8_t len)
+{
+  int i;
+  uint32_t crc = 0xffffffff;
+
+  for (i = 0; i < len; i++)
+    crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *sec++) & 0xff];
+
+  return crc;
+}
+
+
+uint64_t trans_pts_dts(uint8_t *pts)
+{
+       uint64_t wts;
+       
+       wts = ((uint64_t)((pts[0] & 0x0E) << 5) | 
+              ((pts[1] & 0xFC) >> 2)) << 24; 
+       wts |= (((pts[1] & 0x03) << 6) |
+               ((pts[2] & 0xFC) >> 2)) << 16; 
+       wts |= (((pts[2] & 0x02) << 6) |
+               ((pts[3] & 0xFE) >> 1)) << 8;
+       wts |= (((pts[3] & 0x01) << 7) |
+               ((pts[4] & 0xFE) >> 1));
+       return wts;
+}
+
+
+void get_pespts(uint8_t *av_pts,uint8_t *pts)
+{
+       
+       pts[0] = 0x21 | 
+               ((av_pts[0] & 0xC0) >>5);
+       pts[1] = ((av_pts[0] & 0x3F) << 2) |
+               ((av_pts[1] & 0xC0) >> 6);
+       pts[2] = 0x01 | ((av_pts[1] & 0x3F) << 2) |
+               ((av_pts[2] & 0x80) >> 6);
+       pts[3] = ((av_pts[2] & 0x7F) << 1) |
+               ((av_pts[3] & 0x80) >> 7);
+       pts[4] = 0x01 | ((av_pts[3] & 0x7F) << 1);
+}
+
+uint16_t get_pid(uint8_t *pid)
+{
+       uint16_t pp = 0;
+
+       pp = (pid[0] & PID_MASK_HI)<<8;
+       pp |= pid[1];
+
+       return pp;
+}
+
+int write_ts_header(uint16_t pid, uint8_t *counter, int pes_start, 
+                   uint8_t *buf, uint8_t length)
+{
+       int i;
+       int c = 0;
+       int fill;
+       uint8_t tshead[4] = { 0x47, 0x00, 0x00, 0x10}; 
+        
+
+       fill = TS_SIZE-4-length;
+        if (pes_start) tshead[1] = 0x40;
+       if (fill) tshead[3] = 0x30;
+        tshead[1] |= (uint8_t)((pid & 0x1F00) >> 8);
+        tshead[2] |= (uint8_t)(pid & 0x00FF);
+        tshead[3] |= ((*counter)++ & 0x0F) ;
+        memcpy(buf,tshead,4);
+       c+=4;
+
+
+       if (fill){
+               buf[4] = fill-1;
+               c++;
+               if (fill >1){
+                       buf[5] = 0x00;
+                       c++;
+               }
+               for ( i = 6; i < fill+4; i++){
+                       buf[i] = 0xFF;
+                       c++;
+               }
+       }
+
+        return c;
+}
+
+
+int write_pes_header(uint8_t id,int length , long PTS, uint8_t *obuf, 
+                    int stuffing)
+{
+       uint8_t le[2];
+       uint8_t dummy[3];
+       uint8_t *pts;
+       uint8_t ppts[5];
+       long lpts;
+       int c;
+       uint8_t headr[3] = {0x00, 0x00, 0x01};
+       
+       lpts = htonl(PTS);
+       pts = (uint8_t *) &lpts;
+       
+       get_pespts(pts,ppts);
+
+       c = 0;
+       memcpy(obuf+c,headr,3);
+       c += 3;
+       memcpy(obuf+c,&id,1);
+       c++;
+
+       le[0] = 0;
+       le[1] = 0;
+       length -= 6+stuffing;
+
+       le[0] |= ((uint8_t)(length >> 8) & 0xFF); 
+       le[1] |= ((uint8_t)(length) & 0xFF); 
+       memcpy(obuf+c,le,2);
+       c += 2;
+
+       if (id == PADDING_STREAM){
+               memset(obuf+c,0xff,length);
+               c+= length;
+               return c;
+       }
+
+       dummy[0] = 0x80;
+       dummy[1] = 0;
+       dummy[2] = 0;
+       if (PTS){
+               dummy[1] |= PTS_ONLY;
+               dummy[2] = 5+stuffing;
+       }
+       memcpy(obuf+c,dummy,3);
+       c += 3;
+       memset(obuf+c,0xFF,stuffing);
+
+       if (PTS){
+               memcpy(obuf+c,ppts,5);
+               c += 5;
+       }
+       
+       return c;
+}
+
+
+void init_p2p(p2p *p, void (*func)(uint8_t *buf, int count, void *p), 
+             int repack){
+       p->found = 0;
+       p->cid = 0;
+       p->mpeg = 0;
+       memset(p->buf,0,MMAX_PLENGTH);
+       p->done = 0;
+       p->fd1 = -1;
+       p->func = func;
+       p->bigend_repack = 0;
+       p->repack = 0; 
+       if ( repack < MAX_PLENGTH && repack > 265 ){
+               p->repack = repack-6;
+               p->bigend_repack = (uint16_t)htons((short)
+                                                  ((repack-6) & 0xFFFF));
+       } else {
+               fprintf(stderr, "Repack size %d is out of range\n",repack);
+               exit(1);
+       }
+}
+
+
+
+void pes_repack(p2p *p)
+{
+       int count = 0;
+       int repack = p->repack;
+       int rest = p->plength;
+       uint8_t buf[MAX_PLENGTH];
+       int bfill = 0;
+       int diff;
+       uint16_t length;
+
+       if (rest < 0) {
+                fprintf(stderr,"Error in repack\n");
+                return;
+        }
+
+        if (!repack){
+                fprintf(stderr,"forgot to set repack size\n");
+                return;
+        }
+
+       if (p->plength == repack){
+               memcpy(p->buf+4,(char *)&p->bigend_repack,2);
+               p->func(p->buf, repack+6, p);
+               return;
+       }
+
+       buf[0] = 0x00;
+       buf[1] = 0x00;
+       buf[2] = 0x01;
+       buf[3] = p->cid;
+       memcpy(buf+4,(char *)&p->bigend_repack,2);
+       memset(buf+6,0,MAX_PLENGTH-6);
+
+       if (p->mpeg == 2){
+
+               if ( rest > repack){
+                       memcpy(p->buf+4,(char *)&p->bigend_repack,2);
+                       p->func(p->buf, repack+6, p);
+                       count += repack+6;
+                       rest -= repack;
+               } else {
+                       memcpy(buf,p->buf,9+p->hlength);
+                       bfill = p->hlength;
+                       count += 9+p->hlength;
+                       rest -= p->hlength+3;
+               }
+
+               while (rest >= repack-3){
+                       memset(buf+6,0,MAX_PLENGTH-6);
+                       buf[6] = 0x80;
+                       buf[7] = 0x00;
+                       buf[8] = 0x00;
+                       memcpy(buf+9,p->buf+count,repack-3);
+                       rest -= repack-3;
+                       count += repack-3;
+                       p->func(buf, repack+6, p);
+               }
+               
+               if (rest){
+                       diff = repack - 3 - rest - bfill;
+                       if (!bfill){
+                               buf[6] = 0x80;
+                               buf[7] = 0x00;
+                               buf[8] = 0x00;
+                       }
+
+                       if ( diff < PES_MIN){
+                               length = rest+ diff + bfill+3; 
+                               buf[4] = (uint8_t)((length & 0xFF00) >> 8);
+                               buf[5] = (uint8_t)(length & 0x00FF);
+                               buf[8] = (uint8_t)(bfill+diff);
+                               memset(buf+9+bfill,0xFF,diff);
+                               memcpy(buf+9+bfill+diff,p->buf+count,rest);
+                       } else {
+                               length = rest+ bfill+3; 
+                               buf[4] = (uint8_t)((length & 0xFF00) >> 8);
+                               buf[5] = (uint8_t)(length & 0x00FF);
+                               memcpy(buf+9+bfill,p->buf+count,rest);
+                               bfill += rest+9;
+                               write_pes_header( PADDING_STREAM, diff, 0,
+                                                 buf+bfill, 0);
+                       }
+                       p->func(buf, repack+6, p);
+               }
+       }       
+
+       if (p->mpeg == 1){
+
+               if ( rest > repack){
+                       memcpy(p->buf+4,(char *)&p->bigend_repack,2);
+                       p->func(p->buf, repack+6, p);
+                       count += repack+6;
+                       rest -= repack;
+               } else {
+                       memcpy(buf,p->buf,6+p->hlength);
+                       bfill = p->hlength;
+                       count += 6;
+                       rest -= p->hlength;
+               }
+
+               while (rest >= repack-1){
+                       memset(buf+6,0,MAX_PLENGTH-6);
+                       buf[6] = 0x0F;
+                       memcpy(buf+7,p->buf+count,repack-1);
+                       rest -= repack-1;
+                       count += repack-1;
+                       p->func(buf, repack+6, p);
+               }
+               
+
+               if (rest){
+                       diff = repack - 1 - rest - bfill;
+
+                       if ( diff < PES_MIN){
+                               length = rest+ diff + bfill+1; 
+                               buf[4] = (uint8_t)((length & 0xFF00) >> 8);
+                               buf[5] = (uint8_t)(length & 0x00FF);
+                               memset(buf+6,0xFF,diff);
+                               if (!bfill){
+                                       buf[6+diff] = 0x0F;
+                               }
+                               memcpy(buf+7+diff,p->buf+count,rest+bfill);
+                       } else {
+                               length = rest+ bfill+1; 
+                               buf[4] = (uint8_t)((length & 0xFF00) >> 8);
+                               buf[5] = (uint8_t)(length & 0x00FF);
+                               if (!bfill){
+                                       buf[6] = 0x0F;
+                                       memcpy(buf+7,p->buf+count,rest);
+                                       bfill = rest+7;
+                               } else {
+                                       memcpy(buf+6,p->buf+count,rest+bfill);
+                                       bfill += rest+6;
+                               }
+                               write_pes_header( PADDING_STREAM, diff, 0,
+                                                 buf+bfill, 0);
+                       }
+                       p->func(buf, repack+6, p);
+               }
+       }       
+}
+
+
+
+
+
+
+
+
+int filter_pes (uint8_t *buf, int count, p2p *p, int (*func)(p2p *p))
+{
+
+       int l;
+       unsigned short *pl;
+       int c=0;
+       int ret = 1;
+
+       uint8_t headr[3] = { 0x00, 0x00, 0x01} ;
+
+       while (c < count && (p->mpeg == 0 ||
+                            (p->mpeg == 1 && p->found < 7) ||
+                            (p->mpeg == 2 && p->found < 9))
+              &&  (p->found < 5 || !p->done)){
+               switch ( p->found ){
+               case 0:
+               case 1:
+                       if (buf[c] == 0x00) p->found++;
+                       else {
+                               if (p->fd1 >= 0)
+                                       write(p->fd1,buf+c,1);
+                               p->found = 0;
+                       }
+                       c++;
+                       break;
+               case 2:
+                       if (buf[c] == 0x01) p->found++;
+                       else if (buf[c] == 0){
+                               p->found = 2;
+                       } else {        
+                               if (p->fd1 >= 0)
+                                       write(p->fd1,buf+c,1);
+                               p->found = 0;
+                       }
+                       c++;
+                       break;
+               case 3:
+                       p->cid = 0;
+                       switch (buf[c]){
+                       case PROG_STREAM_MAP:
+                       case PRIVATE_STREAM2:
+                       case PROG_STREAM_DIR:
+                       case ECM_STREAM     :
+                       case EMM_STREAM     :
+                       case PADDING_STREAM :
+                       case DSM_CC_STREAM  :
+                       case ISO13522_STREAM:
+                               if (p->fd1 >= 0)
+                                       write(p->fd1,buf+c,1);
+                               p->done = 1;
+                       case PRIVATE_STREAM1:
+                       case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+                       case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+                               p->found++;
+                               p->cid = buf[c];
+                               c++;
+                               break;
+                       default:
+                               if (p->fd1 >= 0)
+                                       write(p->fd1,buf+c,1);
+                               p->found = 0;
+                               break;
+                       }
+                       break;
+                       
+
+               case 4:
+                       if (count-c > 1){
+                               pl = (unsigned short *) (buf+c);
+                               p->plength =  ntohs(*pl);
+                               p->plen[0] = buf[c];
+                               c++;
+                               p->plen[1] = buf[c];
+                               c++;
+                               p->found+=2;
+                       } else {
+                               p->plen[0] = buf[c];
+                               p->found++;
+                               return 1;
+                       }
+                       break;
+               case 5:
+                       p->plen[1] = buf[c];
+                       c++;
+                       pl = (unsigned short *) p->plen;
+                       p->plength = ntohs(*pl);
+                       p->found++;
+                       break;
+
+
+               case 6:
+                       if (!p->done){
+                               p->flag1 = buf[c];
+                               c++;
+                               p->found++;
+                               if ( (p->flag1 & 0xC0) == 0x80 ) p->mpeg = 2;
+                               else {
+                                       p->hlength = 0;
+                                       p->which = 0;
+                                       p->mpeg = 1;
+                                       p->flag2 = 0;
+                               }
+                       }
+                       break;
+
+               case 7:
+                       if ( !p->done && p->mpeg == 2){
+                               p->flag2 = buf[c];
+                               c++;
+                               p->found++;
+                       }       
+                       break;
+
+               case 8:
+                       if ( !p->done && p->mpeg == 2){
+                               p->hlength = buf[c];
+                               c++;
+                               p->found++;
+                       }
+                       break;
+                       
+               default:
+
+                       break;
+               }
+       }
+
+       if (!p->plength) p->plength = MMAX_PLENGTH-6;
+
+
+       if ( p->done || ((p->mpeg == 2 && p->found >= 9)  || 
+            (p->mpeg == 1 && p->found >= 7)) ){
+               switch (p->cid){
+                       
+               case AUDIO_STREAM_S ... AUDIO_STREAM_E:                 
+               case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+               case PRIVATE_STREAM1:
+
+                       memcpy(p->buf, headr, 3);
+                       p->buf[3] = p->cid;
+                       memcpy(p->buf+4,p->plen,2);
+
+                       if (p->mpeg == 2 && p->found == 9){
+                               p->buf[6] = p->flag1;
+                               p->buf[7] = p->flag2;
+                               p->buf[8] = p->hlength;
+                       }
+
+                       if (p->mpeg == 1 && p->found == 7){
+                               p->buf[6] = p->flag1;
+                       }
+
+
+                       if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) &&  
+                           p->found < 14){
+                               while (c < count && p->found < 14){
+                                       p->pts[p->found-9] = buf[c];
+                                       p->buf[p->found] = buf[c];
+                                       c++;
+                                       p->found++;
+                               }
+                               if (c == count) return 1;
+                       }
+
+                       if (p->mpeg == 1 && p->which < 2000){
+
+                               if (p->found == 7) {
+                                       p->check = p->flag1;
+                                       p->hlength = 1;
+                               }
+
+                               while (!p->which && c < count && 
+                                      p->check == 0xFF){
+                                       p->check = buf[c];
+                                       p->buf[p->found] = buf[c];
+                                       c++;
+                                       p->found++;
+                                       p->hlength++;
+                               }
+
+                               if ( c == count) return 1;
+                               
+                               if ( (p->check & 0xC0) == 0x40 && !p->which){
+                                       p->check = buf[c];
+                                       p->buf[p->found] = buf[c];
+                                       c++;
+                                       p->found++;
+                                       p->hlength++;
+
+                                       p->which = 1;
+                                       if ( c == count) return 1;
+                                       p->check = buf[c];
+                                       p->buf[p->found] = buf[c];
+                                       c++;
+                                       p->found++;
+                                       p->hlength++;
+                                       p->which = 2;
+                                       if ( c == count) return 1;
+                               }
+
+                               if (p->which == 1){
+                                       p->check = buf[c];
+                                       p->buf[p->found] = buf[c];
+                                       c++;
+                                       p->found++;
+                                       p->hlength++;
+                                       p->which = 2;
+                                       if ( c == count) return 1;
+                               }
+                               
+                               if ( (p->check & 0x30) && p->check != 0xFF){
+                                       p->flag2 = (p->check & 0xF0) << 2;
+                                       p->pts[0] = p->check;
+                                       p->which = 3;
+                               } 
+
+                               if ( c == count) return 1;
+                               if (p->which > 2){
+                                       if ((p->flag2 & PTS_DTS_FLAGS)
+                                           == PTS_ONLY){
+                                               while (c < count && 
+                                                      p->which < 7){
+                                                       p->pts[p->which-2] =
+                                                               buf[c];
+                                                       p->buf[p->found] = 
+                                                               buf[c];
+                                                       c++;
+                                                       p->found++;
+                                                       p->which++;
+                                                       p->hlength++;
+                                               }
+                                               if ( c == count) return 1;
+                                       } else if ((p->flag2 & PTS_DTS_FLAGS) 
+                                                  == PTS_DTS){
+                                               while (c < count && 
+                                                      p->which< 12){
+                                                       if (p->which< 7)
+                                                               p->pts[p->which
+                                                                     -2] =
+                                                                       buf[c];
+                                                       p->buf[p->found] = 
+                                                               buf[c];
+                                                       c++;
+                                                       p->found++;
+                                                       p->which++;
+                                                       p->hlength++;
+                                               }
+                                               if ( c == count) return 1;
+                                       }
+                                       p->which = 2000;
+                               }
+                                                       
+                       }
+
+                       while (c < count && p->found < p->plength+6){
+                               l = count -c;
+                               if (l+p->found > p->plength+6)
+                                       l = p->plength+6-p->found;
+                               memcpy(p->buf+p->found, buf+c, l);
+                               p->found += l;
+                               c += l;
+                       }                       
+                       if(p->found == p->plength+6){
+                               if (func(p)){ 
+                                       if (p->fd1 >= 0){
+                                               write(p->fd1,p->buf,
+                                                     p->plength+6);
+                                       } 
+                               } else ret = 0;
+                       }
+                       break;
+               }
+
+
+               if ( p->done ){
+                       if( p->found + count - c < p->plength+6){
+                               p->found += count-c;
+                               c = count;
+                       } else {
+                               c += p->plength+6 - p->found;
+                               p->found = p->plength+6;
+                       }
+               }
+
+               if (p->plength && p->found == p->plength+6) {
+                       p->found = 0;
+                       p->done = 0;
+                       p->plength = 0;
+                       memset(p->buf, 0, MAX_PLENGTH);
+                       if (c < count)
+                               return filter_pes(buf+c, count-c, p, func);
+               }
+       }
+       return ret;
+}
+
+
+#define SIZE 4096
+
+
+int audio_pes_filt(p2p *p)
+{
+       uint8_t off;
+
+       switch(p->cid){
+       case PRIVATE_STREAM1:
+               if ( p->cid == p->filter) {
+                       off = 9+p->buf[8];
+                       if (p->buf[off] == p->subid){
+                               return 1;
+                       }
+               }
+               break;
+       
+       case AUDIO_STREAM_S ... AUDIO_STREAM_E:                 
+               if ( p->cid == p->filter)
+                       return 1;
+               break;
+
+       default:
+               return 1;
+               break;
+       }
+       return 0;
+}
+
+
+void filter_audio_from_pes(int fdin, int fdout, uint8_t id, uint8_t subid)
+{
+               p2p p;
+               int count = 1;
+               uint8_t buf[2048];
+
+               init_p2p(&p, NULL, 2048);
+               p.fd1 = -1;
+               p.filter = id;
+               p.subid = subid;
+
+               while (count > 0){
+                       count = read(fdin,buf,2048);
+                       if(filter_pes(buf,count,&p,audio_pes_filt))
+                               write(fdout,buf,2048);
+               }
+}
+
+
+void pes_filt(p2p *p)
+{
+       int factor = p->mpeg-1;
+
+       if ( p->cid == p->filter) {
+               if (p->es)
+                       write(p->fd1,p->buf+p->hlength+6+3*factor, 
+                             p->plength-p->hlength-3*factor);
+               else
+                       write(p->fd1,p->buf,p->plength+6);
+       }
+}
+
+void extract_from_pes(int fdin, int fdout, uint8_t id, int es)
+{
+               p2p p;
+               int count = 1;
+               uint8_t buf[SIZE];
+
+               init_p2p(&p, NULL, 2048);
+               p.fd1 = fdout;
+               p.filter = id;
+               p.es = es;
+
+               while (count > 0){
+                       count = read(fdin,buf,SIZE);
+                       get_pes(buf,count,&p,pes_filt);
+               }
+}
+
+
+void pes_dfilt(p2p *p)
+{
+       int factor = p->mpeg-1;
+       int fd =0;
+       int head=0;
+       int type = NOPES;
+       int streamid;
+       int c = 6+p->hlength+3*factor;
+       
+
+       switch ( p->cid ) {
+       case PRIVATE_STREAM1:
+               streamid = p->buf[c];
+               head = 4; 
+               if ((streamid & 0xF8) == 0x80+p->es-1){
+                       fd = p->fd1;
+                       type = AC3;
+               }
+               break;
+       case AUDIO_STREAM_S ... AUDIO_STREAM_E:                 
+               fd = p->fd1;
+               type = AUDIO;
+               break;
+       case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+               fd = p->fd2;
+               type = VIDEO;
+               break;
+       }
+       
+       if (p->es && !p->startv && type == VIDEO){
+               int found = 0;
+               
+               if  ( p->flag2 & PTS_DTS ) 
+                       p->vpts = trans_pts_dts(p->pts); 
+               else return;
+
+               while ( !found && c+3 < p->plength+6 ){
+                       if ( p->buf[c] == 0x00 && 
+                            p->buf[c+1] == 0x00 && 
+                            p->buf[c+2] == 0x01 &&
+                            p->buf[c+3] == 0xb3) 
+                               found = 1;
+                       else c++;
+               }
+               if (found){
+                       p->startv = 1;
+                       write(fd, p->buf+c, p->plength+6-c);
+               }
+               fd = 0;
+       } 
+
+               
+       if ( p->es && !p->starta && type == AUDIO){
+               int found = 0;
+               if  ( p->flag2 & PTS_DTS ) 
+                       p->apts = trans_pts_dts(p->pts);  
+               else return;
+
+               if (p->startv)
+                       while ( !found && c+1 < p->plength+6){
+                               if ( p->buf[c] == 0xFF && 
+                                    (p->buf[c+1] & 0xF8) == 0xF8)
+                                       found = 1;
+                               else c++;
+                       }
+               if (found){
+                       p->starta = 1;
+                       write(fd, p->buf+c, p->plength+6-c);
+               }
+               fd = 0;
+       } 
+
+       if ( p->es && !p->starta && type == AC3){
+               if  ( p->flag2 & PTS_DTS ) 
+                       p->apts = trans_pts_dts(p->pts);  
+               else return;
+
+               if (p->startv){
+                       c+= ((p->buf[c+2] << 8)| p->buf[c+3]);
+                       p->starta = 1;
+                       write(fd, p->buf+c, p->plength+6-c);
+               }
+               fd = 0;
+       } 
+
+
+       if (fd){
+               if (p->es)
+                       write(fd,p->buf+p->hlength+6+3*factor+head, 
+                             p->plength-p->hlength-3*factor-head);
+               else
+                       write(fd,p->buf,p->plength+6);
+       }
+} 
+
+int64_t pes_dmx( int fdin, int fdouta, int fdoutv, int es)
+{
+       p2p p;
+       int count = 1;
+       uint8_t buf[SIZE];
+       uint64_t length = 0;
+       uint64_t l = 0;
+       int verb = 0;
+       int percent, oldPercent = -1;
+       
+       init_p2p(&p, NULL, 2048);
+       p.fd1 = fdouta;
+       p.fd2 = fdoutv;
+       p.es = es;
+       p.startv = 0;
+       p.starta = 0;
+       p.apts=-1;
+       p.vpts=-1;
+       
+       if (fdin != STDIN_FILENO) verb = 1; 
+       
+       if (verb) {
+               length = lseek(fdin, 0, SEEK_END);
+               lseek(fdin,0,SEEK_SET);
+       }
+       
+       while (count > 0){
+               count = read(fdin,buf,SIZE);
+               l += count;
+               if (verb){
+                       percent = 100 * l / length;
+               
+                       if (percent != oldPercent) {
+                               fprintf(stderr, "Demuxing %d %%\r", percent);
+                               oldPercent = percent;
+                       }
+               }
+               get_pes(buf,count,&p,pes_dfilt);
+       }
+       
+       return (int64_t)p.vpts - (int64_t)p.apts;
+       
+}
+
+
+/* SV: made non-static */
+void pes_in_ts(p2p *p)
+{
+       int l, pes_start;
+       uint8_t obuf[TS_SIZE];
+       long int c = 0;
+       int length = p->plength+6;
+       uint16_t pid;
+       uint8_t *counter;
+       pes_start = 1;
+       switch ( p->cid ) {
+       case AUDIO_STREAM_S ... AUDIO_STREAM_E:                 
+               pid = p->pida;
+               counter = &p->acounter;
+               break;
+       case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+               pid = p->pidv;
+               counter = &p->acounter;
+
+               tspid0[3] |= (p->count0++) 
+                       & 0x0F ;
+               tspid1[3] |= (p->count1++) 
+                       & 0x0F ;
+       
+               tspid1[24]  = p->pidv;
+               tspid1[23] |= (p->pidv >> 8) & 0x3F;
+               tspid1[29]  = p->pida;
+               tspid1[28] |= (p->pida >> 8) & 0x3F;
+               
+               p->func(tspid0,188,p);
+               p->func(tspid1,188,p);
+               break;
+       default:
+               return;
+       }
+
+       while ( c < length ){
+               memset(obuf,0,TS_SIZE);
+               if (length - c >= TS_SIZE-4){
+                       l = write_ts_header(pid, counter, pes_start
+                                            , obuf, TS_SIZE-4);
+                       memcpy(obuf+l, p->buf+c, TS_SIZE-l);
+                       c += TS_SIZE-l;
+               } else { 
+                       l = write_ts_header(pid, counter, pes_start
+                                            , obuf, length-c);
+                       memcpy(obuf+l, p->buf+c, TS_SIZE-l);
+                       c = length;
+               }
+               p->func(obuf,188,p);
+               pes_start = 0;
+       }
+}
+
+static
+void write_out(uint8_t *buf, int count,void  *p)
+{
+       write(STDOUT_FILENO, buf, count);
+}
+
+
+void pes_to_ts2( int fdin, int fdout, uint16_t pida, uint16_t pidv)
+{
+       p2p p;
+       int count = 1;
+       uint8_t buf[SIZE];
+       uint64_t length = 0;
+       uint64_t l = 0;
+       int verb = 0;
+       
+       init_p2p(&p, NULL, 2048);
+       p.fd1 = fdout;
+       p.pida = pida;
+       p.pidv = pidv;
+       p.acounter = 0;
+       p.vcounter = 0;
+       p.count1 = 0;
+       p.count0 = 0;
+       p.func = write_out;
+               
+       if (fdin != STDIN_FILENO) verb = 1; 
+
+       if (verb) {
+               length = lseek(fdin, 0, SEEK_END);
+               lseek(fdin,0,SEEK_SET);
+       }
+
+       while (count > 0){
+               count = read(fdin,buf,SIZE);
+               l += count;
+               if (verb)
+                       fprintf(stderr,"Writing TS  %2.2f %%\r",
+                               100.*l/length);
+
+               get_pes(buf,count,&p,pes_in_ts);
+       }
+               
+}
+
+
+#define IN_SIZE TS_SIZE*10
+void find_avpids(int fd, uint16_t *vpid, uint16_t *apid)
+{
+        uint8_t buf[IN_SIZE];
+        int count;
+        int i;  
+        int off =0;
+
+        while ( *apid == 0 || *vpid == 0){
+                count = read(fd, buf, IN_SIZE);
+                for (i = 0; i < count-7; i++){
+                        if (buf[i] == 0x47){
+                                if (buf[i+1] & 0x40){
+                                        off = 0;
+                                        if ( buf[3+i] & 0x20)//adapt field?
+                                                off = buf[4+i] + 1;
+                                        switch(buf[i+7+off]){
+                                        case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+                                                *vpid = get_pid(buf+i+1);
+                                                break;
+                                        case PRIVATE_STREAM1:
+                                        case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+                                                *apid = get_pid(buf+i+1);
+                                                break;
+                                        }
+                                }
+                                i += 187;
+                        }
+                        if (*apid != 0 && *vpid != 0) break;
+                }
+        }
+}
+
+void find_bavpids(uint8_t *buf, int count, uint16_t *vpid, uint16_t *apid)
+{
+        int i;  
+        int founda = 0;
+        int foundb = 0;
+        int off = 0;
+        
+        *vpid = 0;
+        *apid = 0;
+        for (i = 0; i < count-7; i++){
+                if (buf[i] == 0x47){
+                        if ((buf[i+1] & 0xF0) == 0x40){
+                                off = 0;
+                                if ( buf[3+i] & 0x20)  // adaptation field?
+                                        off = buf[4+i] + 1;
+                                
+                                if (buf[off+i+4] == 0x00 && 
+                                    buf[off+i+5] == 0x00 &&
+                                    buf[off+i+6] == 0x01){
+                                        switch(buf[off+i+7]){
+                                        case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+                                                *vpid = get_pid(buf+i+1);
+                                                foundb=1;
+                                                break;
+                                        case PRIVATE_STREAM1:
+                                        case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+                                                *apid = get_pid(buf+i+1);
+                                                founda=1;
+                                                break;
+                                        }
+                                }
+                        }
+                        i += 187;
+                }
+                if (founda && foundb) break;
+        }
+}
+
+
+void ts_to_pes( int fdin, uint16_t pida, uint16_t pidv, int ps)
+{
+       
+       uint8_t buf[IN_SIZE];
+       uint8_t mbuf[TS_SIZE];
+       int i;
+       int count = 1;
+       uint16_t pid;
+       uint16_t dummy;
+       ipack pa, pv;
+       ipack *p;
+
+       if (fdin != STDIN_FILENO && (!pida || !pidv))
+               find_avpids(fdin, &pidv, &pida);
+
+       init_ipack(&pa, IPACKS,write_out, ps);
+       init_ipack(&pv, IPACKS,write_out, ps);
+
+       if ((count = save_read(fdin,mbuf,TS_SIZE))<0)
+           perror("reading");
+
+       for ( i = 0; i < 188 ; i++){
+               if ( mbuf[i] == 0x47 ) break;
+       }
+       if ( i == 188){
+               fprintf(stderr,"Not a TS\n");
+               return;
+       } else {
+               memcpy(buf,mbuf+i,TS_SIZE-i);
+               if ((count = save_read(fdin,mbuf,i))<0)
+                       perror("reading");
+               memcpy(buf+TS_SIZE-i,mbuf,i);
+               i = 188;
+       }
+       count = 1;
+       while (count > 0){
+               if ((count = save_read(fdin,buf+i,IN_SIZE-i)+i)<0)
+                       perror("reading");
+               
+
+               if (!pidv){
+                        find_bavpids(buf+i, IN_SIZE-i, &pidv, &dummy);
+                        if (pidv) fprintf(stderr, "vpid %d (0x%02x)\n",
+                                         pidv,pidv);
+                } 
+
+                if (!pida){
+                        find_bavpids(buf+i, IN_SIZE-i, &dummy, &pida);
+                        if (pida) fprintf(stderr, "apid %d (0x%02x)\n",
+                                         pida,pida);
+                } 
+
+
+               for( i = 0; i < count; i+= TS_SIZE){
+                       uint8_t off = 0;
+
+                       if ( count - i < TS_SIZE) break;
+
+                       pid = get_pid(buf+i+1);
+                       if (!(buf[3+i]&0x10)) // no payload?
+                               continue;
+                       if ( buf[1+i]&0x80){
+                               fprintf(stderr,"Error in TS for PID: %d\n", 
+                                       pid);
+                       }
+                       if (pid == pidv){
+                               p = &pv;
+                       } else {
+                               if (pid == pida){
+                                       p = &pa;
+                               } else continue;
+                       }
+
+                       if ( buf[1+i]&0x40) {
+                               if (p->plength == MMAX_PLENGTH-6){
+                                       p->plength = p->found-6;
+                                       p->found = 0;
+                                       send_ipack(p);
+                                       reset_ipack(p);
+                               }
+                       }
+
+                       if ( buf[3+i] & 0x20) {  // adaptation field?
+                               off = buf[4+i] + 1;
+                       }
+        
+                       instant_repack(buf+4+off+i, TS_SIZE-4-off, p);
+               }
+               i = 0;
+
+       }
+
+}
+
+
+#define INN_SIZE 2*IN_SIZE
+void insert_pat_pmt( int fdin, int fdout)
+{
+       
+       uint8_t buf[INN_SIZE];
+       uint8_t mbuf[TS_SIZE];
+       int i;
+       int count = 1;
+       uint16_t pida = 0;
+       uint16_t pidv = 0;
+       int written,c;
+       uint8_t c0 = 0;
+       uint8_t c1 = 0;
+        uint8_t pmt_len;
+        uint32_t crc32;
+
+
+       find_avpids(fdin, &pidv, &pida);
+       
+       count = save_read(fdin,mbuf,TS_SIZE);
+       for ( i = 0; i < 188 ; i++){
+               if ( mbuf[i] == 0x47 ) break;
+       }
+       if ( i == 188){
+               fprintf(stderr,"Not a TS\n");
+               return;
+       } else {
+               memcpy(buf,mbuf+i,TS_SIZE-i);
+               count = save_read(fdin,mbuf,i);
+               memcpy(buf+TS_SIZE-i,mbuf,i);
+               i = 188;
+       }
+       
+       count = 1;
+        /* length is not correct, but we only create a very small
+         * PMT, so it doesn't matter :-)
+         */
+        pmt_len = tspid1[7] + 3;
+       while (count > 0){
+               tspid1[24]  = pidv;
+               tspid1[23] |= (pidv >> 8) & 0x3F;
+               tspid1[29]  = pida;
+               tspid1[28] |= (pida >> 8) & 0x3F;
+                crc32 = calc_crc32 (&tspid1[5], pmt_len - 4);
+                tspid1[5 + pmt_len - 4] = (crc32 & 0xff000000) >> 24;
+                tspid1[5 + pmt_len - 3] = (crc32 & 0x00ff0000) >> 16;
+                tspid1[5 + pmt_len - 2] = (crc32 & 0x0000ff00) >>  8;
+                tspid1[5 + pmt_len - 1] = (crc32 & 0x000000ff) >>  0;
+               
+               write(fdout,tspid0,188);
+               write(fdout,tspid1,188);
+
+               count = save_read(fdin,buf+i,INN_SIZE-i);
+               
+               written = 0;
+               while (written < IN_SIZE){
+                       c = write(fdout,buf,INN_SIZE);
+                       if (c>0) written += c;
+               }
+               tspid0[3] &= 0xF0 ;
+               tspid0[3] |= (c0++)& 0x0F ;
+
+               tspid1[3] &= 0xF0 ;
+               tspid1[3] |= (c1++)& 0x0F ;
+       
+               i=0;
+       }
+
+}
+
+void get_pes (uint8_t *buf, int count, p2p *p, void (*func)(p2p *p))
+{
+
+       int l;
+       unsigned short *pl;
+       int c=0;
+
+       uint8_t headr[3] = { 0x00, 0x00, 0x01} ;
+
+       while (c < count && (p->mpeg == 0 ||
+                            (p->mpeg == 1 && p->found < 7) ||
+                            (p->mpeg == 2 && p->found < 9))
+              &&  (p->found < 5 || !p->done)){
+               switch ( p->found ){
+               case 0:
+               case 1:
+                       if (buf[c] == 0x00) p->found++;
+                       else p->found = 0;
+                       c++;
+                       break;
+               case 2:
+                       if (buf[c] == 0x01) p->found++;
+                       else if (buf[c] == 0){
+                               p->found = 2;
+                       } else p->found = 0;
+                       c++;
+                       break;
+               case 3:
+                       p->cid = 0;
+                       switch (buf[c]){
+                       case PROG_STREAM_MAP:
+                       case PRIVATE_STREAM2:
+                       case PROG_STREAM_DIR:
+                       case ECM_STREAM     :
+                       case EMM_STREAM     :
+                       case PADDING_STREAM :
+                       case DSM_CC_STREAM  :
+                       case ISO13522_STREAM:
+                               p->done = 1;
+                       case PRIVATE_STREAM1:
+                       case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+                       case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+                               p->found++;
+                               p->cid = buf[c];
+                               c++;
+                               break;
+                       default:
+                               p->found = 0;
+                               break;
+                       }
+                       break;
+                       
+
+               case 4:
+                       if (count-c > 1){
+                               pl = (unsigned short *) (buf+c);
+                               p->plength =  ntohs(*pl);
+                               p->plen[0] = buf[c];
+                               c++;
+                               p->plen[1] = buf[c];
+                               c++;
+                               p->found+=2;
+                       } else {
+                               p->plen[0] = buf[c];
+                               p->found++;
+                               return;
+                       }
+                       break;
+               case 5:
+                       p->plen[1] = buf[c];
+                       c++;
+                       pl = (unsigned short *) p->plen;
+                       p->plength = ntohs(*pl);
+                       p->found++;
+                       break;
+
+
+               case 6:
+                       if (!p->done){
+                               p->flag1 = buf[c];
+                               c++;
+                               p->found++;
+                               if ( (p->flag1 & 0xC0) == 0x80 ) p->mpeg = 2;
+                               else {
+                                       p->hlength = 0;
+                                       p->which = 0;
+                                       p->mpeg = 1;
+                                       p->flag2 = 0;
+                               }
+                       }
+                       break;
+
+               case 7:
+                       if ( !p->done && p->mpeg == 2){
+                               p->flag2 = buf[c];
+                               c++;
+                               p->found++;
+                       }       
+                       break;
+
+               case 8:
+                       if ( !p->done && p->mpeg == 2){
+                               p->hlength = buf[c];
+                               c++;
+                               p->found++;
+                       }
+                       break;
+                       
+               default:
+
+                       break;
+               }
+       }
+
+       if (!p->plength) p->plength = MMAX_PLENGTH-6;
+
+
+       if ( p->done || ((p->mpeg == 2 && p->found >= 9)  || 
+            (p->mpeg == 1 && p->found >= 7)) ){
+               switch (p->cid){
+                       
+               case AUDIO_STREAM_S ... AUDIO_STREAM_E:                 
+               case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+               case PRIVATE_STREAM1:
+
+                       memcpy(p->buf, headr, 3);
+                       p->buf[3] = p->cid;
+                       memcpy(p->buf+4,p->plen,2);
+
+                       if (p->mpeg == 2 && p->found == 9){
+                               p->buf[6] = p->flag1;
+                               p->buf[7] = p->flag2;
+                               p->buf[8] = p->hlength;
+                       }
+
+                       if (p->mpeg == 1 && p->found == 7){
+                               p->buf[6] = p->flag1;
+                       }
+
+
+                       if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) &&  
+                           p->found < 14){
+                               while (c < count && p->found < 14){
+                                       p->pts[p->found-9] = buf[c];
+                                       p->buf[p->found] = buf[c];
+                                       c++;
+                                       p->found++;
+                               }
+                               if (c == count) return;
+                       }
+
+                       if (p->mpeg == 1 && p->which < 2000){
+
+                               if (p->found == 7) {
+                                       p->check = p->flag1;
+                                       p->hlength = 1;
+                               }
+
+                               while (!p->which && c < count && 
+                                      p->check == 0xFF){
+                                       p->check = buf[c];
+                                       p->buf[p->found] = buf[c];
+                                       c++;
+                                       p->found++;
+                                       p->hlength++;
+                               }
+
+                               if ( c == count) return;
+                               
+                               if ( (p->check & 0xC0) == 0x40 && !p->which){
+                                       p->check = buf[c];
+                                       p->buf[p->found] = buf[c];
+                                       c++;
+                                       p->found++;
+                                       p->hlength++;
+
+                                       p->which = 1;
+                                       if ( c == count) return;
+                                       p->check = buf[c];
+                                       p->buf[p->found] = buf[c];
+                                       c++;
+                                       p->found++;
+                                       p->hlength++;
+                                       p->which = 2;
+                                       if ( c == count) return;
+                               }
+
+                               if (p->which == 1){
+                                       p->check = buf[c];
+                                       p->buf[p->found] = buf[c];
+                                       c++;
+                                       p->found++;
+                                       p->hlength++;
+                                       p->which = 2;
+                                       if ( c == count) return;
+                               }
+                               
+                               if ( (p->check & 0x30) && p->check != 0xFF){
+                                       p->flag2 = (p->check & 0xF0) << 2;
+                                       p->pts[0] = p->check;
+                                       p->which = 3;
+                               } 
+
+                               if ( c == count) return;
+                               if (p->which > 2){
+                                       if ((p->flag2 & PTS_DTS_FLAGS)
+                                           == PTS_ONLY){
+                                               while (c < count && 
+                                                      p->which < 7){
+                                                       p->pts[p->which-2] =
+                                                               buf[c];
+                                                       p->buf[p->found] = 
+                                                               buf[c];
+                                                       c++;
+                                                       p->found++;
+                                                       p->which++;
+                                                       p->hlength++;
+                                               }
+                                               if ( c == count) return;
+                                       } else if ((p->flag2 & PTS_DTS_FLAGS) 
+                                                  == PTS_DTS){
+                                               while (c < count && 
+                                                      p->which< 12){
+                                                       if (p->which< 7)
+                                                               p->pts[p->which
+                                                                     -2] =
+                                                                       buf[c];
+                                                       p->buf[p->found] = 
+                                                               buf[c];
+                                                       c++;
+                                                       p->found++;
+                                                       p->which++;
+                                                       p->hlength++;
+                                               }
+                                               if ( c == count) return;
+                                       }
+                                       p->which = 2000;
+                               }
+                                                       
+                       }
+
+                       while (c < count && p->found < p->plength+6){
+                               l = count -c;
+                               if (l+p->found > p->plength+6)
+                                       l = p->plength+6-p->found;
+                               memcpy(p->buf+p->found, buf+c, l);
+                               p->found += l;
+                               c += l;
+                       }                       
+                       if(p->found == p->plength+6)
+                               func(p);
+                       
+                       break;
+               }
+
+
+               if ( p->done ){
+                       if( p->found + count - c < p->plength+6){
+                               p->found += count-c;
+                               c = count;
+                       } else {
+                               c += p->plength+6 - p->found;
+                               p->found = p->plength+6;
+                       }
+               }
+
+               if (p->plength && p->found == p->plength+6) {
+                       p->found = 0;
+                       p->done = 0;
+                       p->plength = 0;
+                       memset(p->buf, 0, MAX_PLENGTH);
+                       if (c < count)
+                               get_pes(buf+c, count-c, p, func);
+               }
+       }
+       return;
+}
+
+
+
+
+void setup_pes2ts( p2p *p, uint32_t pida, uint32_t pidv, 
+                  void (*ts_write)(uint8_t *buf, int count, void *p))
+{
+       init_p2p( p, ts_write, 2048);
+       p->pida = pida;
+       p->pidv = pidv;
+       p->acounter = 0;
+       p->vcounter = 0;
+       p->count1 = 0;
+       p->count0 = 0;
+}
+
+void kpes_to_ts( p2p *p,uint8_t *buf ,int count )
+{
+       get_pes(buf,count, p,pes_in_ts);
+}
+
+
+void setup_ts2pes( p2p *pa, p2p *pv, uint32_t pida, uint32_t pidv, 
+                  void (*pes_write)(uint8_t *buf, int count, void *p))
+{
+       init_p2p( pa, pes_write, 2048);
+       init_p2p( pv, pes_write, 2048);
+       pa->pid = pida;
+       pv->pid = pidv;
+}
+
+void kts_to_pes( p2p *p, uint8_t *buf) // don't need count (=188)
+{
+       uint8_t off = 0;
+       uint16_t pid = 0;
+
+       if (!(buf[3]&PAYLOAD)) // no payload?
+               return;
+
+       pid = get_pid(buf+1);
+                       
+       if (pid != p->pid) return;
+       if ( buf[1]&0x80){
+               fprintf(stderr,"Error in TS for PID: %d\n", 
+                       pid);
+       }
+
+       if ( buf[1]&PAY_START) {
+               if (p->plength == MMAX_PLENGTH-6){
+                       p->plength = p->found-6;
+                       p->found = 0;
+                       pes_repack(p);
+               }
+       }
+
+       if ( buf[3] & ADAPT_FIELD) {  // adaptation field?
+               off = buf[4] + 1;
+               if (off+4 > 187) return;
+       }
+        
+       get_pes(buf+4+off, TS_SIZE-4-off, p , pes_repack);
+}
+
+
+
+
+// instant repack
+
+
+void reset_ipack(ipack *p)
+{
+       p->found = 0;
+       p->cid = 0;
+       p->plength = 0;
+       p->flag1 = 0;
+       p->flag2 = 0;
+       p->hlength = 0;
+       p->mpeg = 0;
+       p->check = 0;
+       p->which = 0;
+       p->done = 0;
+       p->count = 0;
+       p->size = p->size_orig;
+}
+
+void init_ipack(ipack *p, int size,
+               void (*func)(uint8_t *buf,  int size, void *priv), int ps)
+{
+       if ( !(p->buf = malloc(size)) ){
+               fprintf(stderr,"Couldn't allocate memory for ipack\n");
+               exit(1);
+       }
+       p->ps = ps;
+       p->size_orig = size;
+       p->func = func;
+       reset_ipack(p);
+       p->has_ai = 0;
+       p->has_vi = 0;
+       p->start = 0;
+}
+
+void free_ipack(ipack * p)
+{
+       if (p->buf) free(p->buf);
+}
+
+
+
+int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr)
+{
+       uint8_t *headr;
+       int found = 0;
+        int sw;
+       int form = -1;
+       int c = 0;
+
+       while (found < 4 && c+4 < count){
+               uint8_t *b;
+
+               b = mbuf+c;
+               if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01
+                    && b[3] == 0xb3) found = 4;
+               else {
+                       c++;
+               }
+       }
+
+       if (! found) return -1;
+       c += 4;
+       if (c+12 >= count) return -1;
+       headr = mbuf+c;
+
+       vi->horizontal_size     = ((headr[1] &0xF0) >> 4) | (headr[0] << 4);
+       vi->vertical_size       = ((headr[1] &0x0F) << 8) | (headr[2]);
+    
+        sw = (int)((headr[3]&0xF0) >> 4) ;
+
+        switch( sw ){
+       case 1:
+               if (pr)
+                       fprintf(stderr,"Videostream: ASPECT: 1:1");
+               vi->aspect_ratio = 100;        
+               break;
+       case 2:
+               if (pr)
+                       fprintf(stderr,"Videostream: ASPECT: 4:3");
+                vi->aspect_ratio = 133;        
+               break;
+       case 3:
+               if (pr)
+                       fprintf(stderr,"Videostream: ASPECT: 16:9");
+                vi->aspect_ratio = 177;        
+               break;
+       case 4:
+               if (pr)
+                       fprintf(stderr,"Videostream: ASPECT: 2.21:1");
+                vi->aspect_ratio = 221;        
+               break;
+
+        case 5 ... 15:
+               if (pr)
+                       fprintf(stderr,"Videostream: ASPECT: reserved");
+                vi->aspect_ratio = 0;        
+               break;
+
+        default:
+                vi->aspect_ratio = 0;        
+                return -1;
+       }
+
+       if (pr)
+               fprintf(stderr,"  Size = %dx%d",vi->horizontal_size,
+                       vi->vertical_size);
+
+        sw = (int)(headr[3]&0x0F);
+
+        switch ( sw ) {
+       case 1:
+               if (pr)
+                       fprintf(stderr,"  FRate: 23.976 fps");
+                vi->framerate = 24000/1001.;
+               form = -1;
+               break;
+       case 2:
+               if (pr)
+                       fprintf(stderr,"  FRate: 24 fps");
+                vi->framerate = 24;
+               form = -1;
+               break;
+       case 3:
+               if (pr)
+                       fprintf(stderr,"  FRate: 25 fps");
+                vi->framerate = 25;
+               form = VIDEO_MODE_PAL;
+               break;
+       case 4:
+               if (pr)
+                       fprintf(stderr,"  FRate: 29.97 fps");
+                vi->framerate = 30000/1001.;
+               form = VIDEO_MODE_NTSC;
+               break;
+       case 5:
+               if (pr)
+                       fprintf(stderr,"  FRate: 30 fps");
+                vi->framerate = 30;
+               form = VIDEO_MODE_NTSC;
+               break;
+       case 6:
+               if (pr)
+                       fprintf(stderr,"  FRate: 50 fps");
+                vi->framerate = 50;
+               form = VIDEO_MODE_PAL;
+               break;
+       case 7:
+               if (pr)
+                       fprintf(stderr,"  FRate: 60 fps");
+                vi->framerate = 60;
+               form = VIDEO_MODE_NTSC;
+               break;
+       }
+
+       vi->bit_rate = 400*(((headr[4] << 10) & 0x0003FC00UL) 
+                           | ((headr[5] << 2) & 0x000003FCUL) | 
+                           (((headr[6] & 0xC0) >> 6) & 0x00000003UL));
+       
+       if (pr){
+               fprintf(stderr,"  BRate: %.2f Mbit/s",(vi->bit_rate)/1000000.);
+               fprintf(stderr,"\n");
+       }
+        vi->video_format = form;
+
+       vi->off = c-4;
+       return c-4;
+}
+
+extern unsigned int bitrates[3][16];
+extern uint32_t freq[4];
+
+int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr)
+{
+       uint8_t *headr;
+       int found = 0;
+       int c = 0;
+       int fr =0;
+       
+       while (!found && c < count){
+               uint8_t *b = mbuf+c;
+
+               if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8)
+                       found = 1;
+               else {
+                       c++;
+               }
+       }       
+
+       if (!found) return -1;
+
+       if (c+3 >= count) return -1;
+        headr = mbuf+c;
+
+       ai->layer = (headr[1] & 0x06) >> 1;
+
+        if (pr)
+               fprintf(stderr,"Audiostream: Layer: %d", 4-ai->layer);
+
+
+       ai->bit_rate = bitrates[(3-ai->layer)][(headr[2] >> 4 )]*1000;
+
+       if (pr){
+               if (ai->bit_rate == 0)
+                       fprintf (stderr,"  Bit rate: free");
+               else if (ai->bit_rate == 0xf)
+                       fprintf (stderr,"  BRate: reserved");
+               else
+                       fprintf (stderr,"  BRate: %d kb/s", ai->bit_rate/1000);
+       }
+
+       fr = (headr[2] & 0x0c ) >> 2;
+       ai->frequency = freq[fr]*100;
+       
+       if (pr){
+               if (ai->frequency == 3)
+                       fprintf (stderr, "  Freq: reserved\n");
+               else
+                       fprintf (stderr,"  Freq: %2.1f kHz\n", 
+                                ai->frequency/1000.);
+       }
+       ai->off = c;
+       return c;
+}
+
+unsigned int ac3_bitrates[32] =
+    {32,40,48,56,64,80,96,112,128,160,192,224,256,320,384,448,512,576,640,
+     0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+uint32_t ac3_freq[4] = {480, 441, 320, 0};
+uint32_t ac3_frames[3][32] =
+    {{64,80,96,112,128,160,192,224,256,320,384,448,512,640,768,896,1024,
+      1152,1280,0,0,0,0,0,0,0,0,0,0,0,0,0},
+     {69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114,
+      1253,1393,0,0,0,0,0,0,0,0,0,0,0,0,0},
+     {96,120,144,168,192,240,288,336,384,480,576,672,768,960,1152,1344,
+      1536,1728,1920,0,0,0,0,0,0,0,0,0,0,0,0,0}}; 
+
+int get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai, int pr)
+{
+       uint8_t *headr;
+       int found = 0;
+       int c = 0;
+       uint8_t frame;
+       int fr = 0;
+
+       while ( !found  && c < count){
+               uint8_t *b = mbuf+c;
+               if ( b[0] == 0x0b &&  b[1] == 0x77 )
+                       found = 1;
+               else {
+                       c++;
+               }
+       }       
+
+
+       if (!found){
+               return -1;
+       }
+       ai->off = c;
+
+       if (c+5 >= count) return -1;
+
+       ai->layer = 0;  // 0 for AC3
+        headr = mbuf+c+2;
+
+       frame = (headr[2]&0x3f);
+       ai->bit_rate = ac3_bitrates[frame>>1]*1000;
+
+       if (pr) fprintf (stderr,"  BRate: %d kb/s", ai->bit_rate/1000);
+
+       fr = (headr[2] & 0xc0 ) >> 6;
+       ai->frequency = freq[fr]*100;
+       if (pr) fprintf (stderr,"  Freq: %d Hz\n", ai->frequency);
+
+       ai->framesize = ac3_frames[fr][frame >> 1];
+       if ((frame & 1) &&  (fr == 1)) ai->framesize++;
+       ai->framesize = ai->framesize << 1;
+       if (pr) fprintf (stderr,"  Framesize %d\n", ai->framesize);
+
+       return c;
+}
+
+
+void ps_pes(ipack *p)
+{
+       int check;
+       uint8_t pbuf[PS_HEADER_L2];
+       static int muxr = 0;
+       static int ai = 0;
+       static int vi = 0;
+       static int start = 0;
+       static uint32_t SCR = 0;
+
+       if (p->mpeg == 2){
+               switch(p->buf[3]){
+               case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+                       if (!p->has_vi){
+                               if(get_vinfo(p->buf, p->count, &p->vi,1) >=0) {
+                                       p->has_vi = 1;
+                                       vi = p->vi.bit_rate;
+                               }
+                       }                       
+                       break;
+
+               case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+                       if (!p->has_ai){
+                               if(get_ainfo(p->buf, p->count, &p->ai,1) >=0) {
+                                       p->has_ai = 1;
+                                       ai = p->ai.bit_rate;
+                               }
+                       } 
+                       break;
+               }
+
+               if (p->has_vi && vi && !muxr){
+                       muxr = (vi+ai)/400;
+               }
+
+               if ( start && muxr && (p->buf[7] & PTS_ONLY) && (p->has_ai || 
+                                      p->buf[9+p->buf[8]+4] == 0xb3)){  
+                       SCR = trans_pts_dts(p->pts)-3600;
+                       
+                       check = write_ps_header(pbuf,
+                                               SCR,
+                                               muxr, 1, 0, 0, 1, 1, 1, 
+                                               0, 0, 0, 0, 0, 0);
+
+                       p->func(pbuf, check , p->data);
+               }
+
+               if (muxr && !start && vi){
+                       SCR = trans_pts_dts(p->pts)-3600;
+                       check = write_ps_header(pbuf,
+                                               SCR, 
+                                               muxr, 1, 0, 0, 1, 1, 1, 
+                                               0xC0, 0, 64, 0xE0, 1, 460);
+                       start = 1;
+                       p->func(pbuf, check , p->data);
+               }
+
+               if (start)
+                       p->func(p->buf, p->count, p->data);
+       }
+}
+
+void send_ipack(ipack *p)
+{
+       int streamid=0;
+       int off;
+       int ac3_off = 0;
+       AudioInfo ai;
+       int nframes= 0;
+       int f=0;
+
+       if (p->count < 10) return;
+       p->buf[3] = p->cid;
+       p->buf[4] = (uint8_t)(((p->count-6) & 0xFF00) >> 8);
+       p->buf[5] = (uint8_t)((p->count-6) & 0x00FF);
+
+       
+       if (p->cid == PRIVATE_STREAM1){
+
+               off = 9+p->buf[8];
+               streamid = p->buf[off];
+               if ((streamid & 0xF8) == 0x80){
+                       ai.off = 0;
+                       ac3_off = ((p->buf[off+2] << 8)| p->buf[off+3]);
+                       if (ac3_off < p->count)
+                               f=get_ac3info(p->buf+off+3+ac3_off, 
+                                             p->count-ac3_off, &ai,0);
+                       if ( !f ){
+                               nframes = (p->count-off-3-ac3_off)/ 
+                                       ai.framesize + 1;
+                               p->buf[off+1] = nframes;
+                               p->buf[off+2] = (ac3_off >> 8)& 0xFF;
+                               p->buf[off+3] = (ac3_off)& 0xFF;
+                               
+                               ac3_off +=  nframes * ai.framesize - p->count;
+                       }
+               }
+       } 
+       
+       if (p->ps) ps_pes(p);
+       else p->func(p->buf, p->count, p->data);
+
+       switch ( p->mpeg ){
+       case 2:         
+               
+               p->buf[6] = 0x80;
+               p->buf[7] = 0x00;
+               p->buf[8] = 0x00;
+               p->count = 9;
+
+               if (p->cid == PRIVATE_STREAM1 && (streamid & 0xF8)==0x80 ){
+                       p->count += 4;
+                       p->buf[9] = streamid;
+                       p->buf[10] = 0;
+                       p->buf[11] = (ac3_off >> 8)& 0xFF;
+                       p->buf[12] = (ac3_off)& 0xFF;
+               }
+               
+               break;
+       case 1:
+               p->buf[6] = 0x0F;
+               p->count = 7;
+               break;
+       }
+
+}
+
+
+static void write_ipack(ipack *p, uint8_t *data, int count)
+{
+       AudioInfo ai;
+       uint8_t headr[3] = { 0x00, 0x00, 0x01} ;
+       int diff =0;
+
+       if (p->count < 6){
+               if (trans_pts_dts(p->pts) > trans_pts_dts(p->last_pts))
+                       memcpy(p->last_pts, p->pts, 5);
+               p->count = 0;
+               memcpy(p->buf+p->count, headr, 3);
+               p->count += 6;
+       }
+       if ( p->size == p->size_orig && p->plength &&
+            (diff = 6+p->plength - p->found + p->count +count) > p->size &&
+            diff < 3*p->size/2){
+               
+                       p->size = diff/2;
+//                     fprintf(stderr,"size: %d \n",p->size);
+       }
+
+       if (p->cid == PRIVATE_STREAM1 && p->count == p->hlength+9){
+               if ((data[0] & 0xF8) != 0x80){
+                       int ac3_off;
+
+                       ac3_off = get_ac3info(data, count, &ai,0);
+                       if (ac3_off>=0 && ai.framesize){
+                               p->buf[p->count] = 0x80;
+                               p->buf[p->count+1] = (p->size - p->count
+                                                     - 4 - ac3_off)/ 
+                                       ai.framesize + 1;
+                               p->buf[p->count+2] = (ac3_off >> 8)& 0xFF;
+                               p->buf[p->count+3] = (ac3_off)& 0xFF;
+                               p->count+=4;
+                               
+                       }
+               }
+       }
+
+       if (p->count + count < p->size){
+               memcpy(p->buf+p->count, data, count); 
+               p->count += count;
+       } else {
+               int rest = p->size - p->count;
+               if (rest < 0) rest = 0;
+               memcpy(p->buf+p->count, data, rest);
+               p->count += rest;
+//             fprintf(stderr,"count: %d \n",p->count);
+               send_ipack(p);
+               if (count - rest > 0)
+                       write_ipack(p, data+rest, count-rest);
+       }
+}
+
+void instant_repack (uint8_t *buf, int count, ipack *p)
+{
+
+       int l;
+       unsigned short *pl;
+       int c=0;
+
+       while (c < count && (p->mpeg == 0 ||
+                            (p->mpeg == 1 && p->found < 7) ||
+                            (p->mpeg == 2 && p->found < 9))
+              &&  (p->found < 5 || !p->done)){
+               switch ( p->found ){
+               case 0:
+               case 1:
+                       if (buf[c] == 0x00) p->found++;
+                       else p->found = 0;
+                       c++;
+                       break;
+               case 2:
+                       if (buf[c] == 0x01) p->found++;
+                       else if (buf[c] == 0){
+                               p->found = 2;
+                       } else p->found = 0;
+                       c++;
+                       break;
+               case 3:
+                       p->cid = 0;
+                       switch (buf[c]){
+                       case PROG_STREAM_MAP:
+                       case PRIVATE_STREAM2:
+                       case PROG_STREAM_DIR:
+                       case ECM_STREAM     :
+                       case EMM_STREAM     :
+                       case PADDING_STREAM :
+                       case DSM_CC_STREAM  :
+                       case ISO13522_STREAM:
+                               p->done = 1;
+                       case PRIVATE_STREAM1:
+                       case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+                       case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+                               p->found++;
+                               p->cid = buf[c];
+                               c++;
+                               break;
+                       default:
+                               p->found = 0;
+                               break;
+                       }
+                       break;
+                       
+
+               case 4:
+                       if (count-c > 1){
+                               pl = (unsigned short *) (buf+c);
+                               p->plength =  ntohs(*pl);
+                               p->plen[0] = buf[c];
+                               c++;
+                               p->plen[1] = buf[c];
+                               c++;
+                               p->found+=2;
+                       } else {
+                               p->plen[0] = buf[c];
+                               p->found++;
+                               return;
+                       }
+                       break;
+               case 5:
+                       p->plen[1] = buf[c];
+                       c++;
+                       pl = (unsigned short *) p->plen;
+                       p->plength = ntohs(*pl);
+                       p->found++;
+                       break;
+
+
+               case 6:
+                       if (!p->done){
+                               p->flag1 = buf[c];
+                               c++;
+                               p->found++;
+                               if ( (p->flag1 & 0xC0) == 0x80 ) p->mpeg = 2;
+                               else {
+                                       p->hlength = 0;
+                                       p->which = 0;
+                                       p->mpeg = 1;
+                                       p->flag2 = 0;
+                               }
+                       }
+                       break;
+
+               case 7:
+                       if ( !p->done && p->mpeg == 2){
+                               p->flag2 = buf[c];
+                               c++;
+                               p->found++;
+                       }       
+                       break;
+
+               case 8:
+                       if ( !p->done && p->mpeg == 2){
+                               p->hlength = buf[c];
+                               c++;
+                               p->found++;
+                       }
+                       break;
+                       
+               default:
+
+                       break;
+               }
+       }
+
+
+       if (c == count) return;
+
+       if (!p->plength) p->plength = MMAX_PLENGTH-6;
+
+
+       if ( p->done || ((p->mpeg == 2 && p->found >= 9)  || 
+            (p->mpeg == 1 && p->found >= 7)) ){
+               switch (p->cid){
+                       
+               case AUDIO_STREAM_S ... AUDIO_STREAM_E:                 
+               case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+               case PRIVATE_STREAM1:
+                       
+                       if (p->mpeg == 2 && p->found == 9){
+                               write_ipack(p, &p->flag1, 1);
+                               write_ipack(p, &p->flag2, 1);
+                               write_ipack(p, &p->hlength, 1);
+                       }
+
+                       if (p->mpeg == 1 && p->found == 7){
+                               write_ipack(p, &p->flag1, 1);
+                       }
+
+
+                       if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) &&  
+                           p->found < 14){
+                               while (c < count && p->found < 14){
+                                       p->pts[p->found-9] = buf[c];
+                                       write_ipack(p, buf+c, 1);
+                                       c++;
+                                       p->found++;
+                               }
+                               if (c == count) return;
+                       }
+                       
+                       if (p->mpeg == 1 && p->which < 2000){
+
+                               if (p->found == 7) {
+                                       p->check = p->flag1;
+                                       p->hlength = 1;
+                               }
+
+                               while (!p->which && c < count && 
+                                      p->check == 0xFF){
+                                       p->check = buf[c];
+                                       write_ipack(p, buf+c, 1);
+                                       c++;
+                                       p->found++;
+                                       p->hlength++;
+                               }
+
+                               if ( c == count) return;
+                               
+                               if ( (p->check & 0xC0) == 0x40 && !p->which){
+                                       p->check = buf[c];
+                                       write_ipack(p, buf+c, 1);
+                                       c++;
+                                       p->found++;
+                                       p->hlength++;
+
+                                       p->which = 1;
+                                       if ( c == count) return;
+                                       p->check = buf[c];
+                                       write_ipack(p, buf+c, 1);
+                                       c++;
+                                       p->found++;
+                                       p->hlength++;
+                                       p->which = 2;
+                                       if ( c == count) return;
+                               }
+
+                               if (p->which == 1){
+                                       p->check = buf[c];
+                                       write_ipack(p, buf+c, 1);
+                                       c++;
+                                       p->found++;
+                                       p->hlength++;
+                                       p->which = 2;
+                                       if ( c == count) return;
+                               }
+                               
+                               if ( (p->check & 0x30) && p->check != 0xFF){
+                                       p->flag2 = (p->check & 0xF0) << 2;
+                                       p->pts[0] = p->check;
+                                       p->which = 3;
+                               } 
+
+                               if ( c == count) return;
+                               if (p->which > 2){
+                                       if ((p->flag2 & PTS_DTS_FLAGS)
+                                           == PTS_ONLY){
+                                               while (c < count && 
+                                                      p->which < 7){
+                                                       p->pts[p->which-2] =
+                                                               buf[c];
+                                                       write_ipack(p,buf+c,1);
+                                                       c++;
+                                                       p->found++;
+                                                       p->which++;
+                                                       p->hlength++;
+                                               }
+                                               if ( c == count) return;
+                                       } else if ((p->flag2 & PTS_DTS_FLAGS) 
+                                                  == PTS_DTS){
+                                               while (c < count && 
+                                                      p->which< 12){
+                                                       if (p->which< 7)
+                                                               p->pts[p->which
+                                                                     -2] =
+                                                                       buf[c];
+                                                       write_ipack(p,buf+c,1);
+                                                       c++;
+                                                       p->found++;
+                                                       p->which++;
+                                                       p->hlength++;
+                                               }
+                                               if ( c == count) return;
+                                       }
+                                       p->which = 2000;
+                               }
+                                                       
+                       }
+
+                       while (c < count && p->found < p->plength+6){
+                               l = count -c;
+                               if (l+p->found > p->plength+6)
+                                       l = p->plength+6-p->found;
+                               write_ipack(p, buf+c, l);
+                               p->found += l;
+                               c += l;
+                       }       
+               
+                       break;
+               }
+
+
+               if ( p->done ){
+                       if( p->found + count - c < p->plength+6){
+                               p->found += count-c;
+                               c = count;
+                       } else {
+                               c += p->plength+6 - p->found;
+                               p->found = p->plength+6;
+                       }
+               }
+
+               if (p->plength && p->found == p->plength+6) {
+                       send_ipack(p);
+                       reset_ipack(p);
+                       if (c < count)
+                               instant_repack(buf+c, count-c, p);
+               }
+       }
+       return;
+}
+
+void write_out_es(uint8_t *buf, int count,void  *priv)
+{
+       ipack *p = (ipack *) priv;
+       uint8_t payl = buf[8]+9+p->start-1;
+
+       write(p->fd, buf+payl, count-payl);
+       p->start = 1;
+}
+
+void write_out_pes(uint8_t *buf, int count,void  *priv)
+{
+       ipack *p = (ipack *) priv;
+       write(p->fd, buf, count);
+}
+
+
+
+int64_t ts_demux(int fdin, int fdv_out,int fda_out,uint16_t pida,
+                 uint16_t pidv, int es)
+{
+       uint8_t buf[IN_SIZE];
+       uint8_t mbuf[TS_SIZE];
+       int i;
+       int count = 1;
+       uint16_t pid;
+       ipack pa, pv;
+       ipack *p;
+       uint8_t *sb;
+       int64_t apts=0;
+       int64_t vpts=0;
+       int verb = 0;
+       uint64_t length =0;
+       uint64_t l=0;
+       int perc =0;
+       int last_perc =0;
+
+       if (fdin != STDIN_FILENO) verb = 1; 
+
+       if (verb) {
+               length = lseek(fdin, 0, SEEK_END);
+               lseek(fdin,0,SEEK_SET);
+       }
+
+       if (!pida || !pidv)
+               find_avpids(fdin, &pidv, &pida);
+
+       if (es){
+               init_ipack(&pa, IPACKS,write_out_es, 0);
+               init_ipack(&pv, IPACKS,write_out_es, 0);
+       } else {
+               init_ipack(&pa, IPACKS,write_out_pes, 0);
+               init_ipack(&pv, IPACKS,write_out_pes, 0);
+       } 
+       pa.fd = fda_out;
+       pv.fd = fdv_out;
+       pa.data = (void *)&pa;
+       pv.data = (void *)&pv;
+
+       count = save_read(fdin,mbuf,TS_SIZE);
+       if (count) l+=count;
+       for ( i = 0; i < 188 ; i++){
+               if ( mbuf[i] == 0x47 ) break;
+       }
+       if ( i == 188){
+               fprintf(stderr,"Not a TS\n");
+               return 0;
+       } else {
+               memcpy(buf,mbuf+i,TS_SIZE-i);
+               count = save_read(fdin,mbuf,i);
+               if (count) l+=count;
+               memcpy(buf+TS_SIZE-i,mbuf,i);
+               i = 188;
+       }
+       
+       count = 1;
+       while (count > 0){
+               count = save_read(fdin,buf+i,IN_SIZE-i)+i;
+               if (count) l+=count;
+               if (verb && perc >last_perc){
+                       perc = (100*l)/length;
+                       fprintf(stderr,"Reading TS  %d %%\r",perc);
+                       last_perc = perc;
+               }
+               
+               for( i = 0; i < count; i+= TS_SIZE){
+                       uint8_t off = 0;
+
+                       if ( count - i < TS_SIZE) break;
+
+                       pid = get_pid(buf+i+1);
+                       if (!(buf[3+i]&0x10)) // no payload?
+                               continue;
+                       if ( buf[1+i]&0x80){
+                               fprintf(stderr,"Error in TS for PID: %d\n", 
+                                       pid);
+                       }
+                       if (pid == pidv){
+                               p = &pv;
+                       } else {
+                               if (pid == pida){
+                                       p = &pa;
+                               } else continue;
+                       }
+
+                       if ( buf[3+i] & 0x20) {  // adaptation field?
+                               off = buf[4+i] + 1;
+                       }
+
+                       if ( buf[1+i]&0x40) {
+                               if (p->plength == MMAX_PLENGTH-6){
+                                       p->plength = p->found-6;
+                                       p->found = 0;
+                                       send_ipack(p);
+                                       reset_ipack(p);
+                               }
+                               sb = buf+4+off+i;
+                               if( es && 
+                                   !p->start && (sb[7] & PTS_DTS_FLAGS)){
+                                       uint8_t *pay = sb+sb[8]+9; 
+                                       int l = TS_SIZE - 13 - off - sb[8];
+                                       if ( pid == pidv &&   
+                                            (p->start = 
+                                             get_vinfo( pay, l,&p->vi,1)+1) >0
+                                               ){
+                                               vpts = trans_pts_dts(sb+9);
+                                               printf("vpts : %fs\n",
+                                                      vpts/90000.);
+                                       }
+                                       if ( pid == pida && es==1 && 
+                                            (p->start = 
+                                             get_ainfo( pay, l,&p->ai,1)+1) >0
+                                               ){
+                                               apts = trans_pts_dts(sb+9);
+                                               printf("apts : %fs\n",
+                                                      apts/90000.);
+                                       }
+                                       if ( pid == pida && es==2 && 
+                                            (p->start = 
+                                             get_ac3info( pay, l,&p->ai,1)+1) >0
+                                               ){
+                                               apts = trans_pts_dts(sb+9);
+                                               printf("apts : %fs\n",
+                                                      apts/90000.);
+                                       }
+                               }
+                       }
+
+                       if (p->start)
+                               instant_repack(buf+4+off+i, TS_SIZE-4-off, p);
+               }
+               i = 0;
+
+       }
+
+       return (vpts-apts);
+}
+
+void ts2es_opt(int fdin,  uint16_t pidv, ipack *p, int verb)
+{
+       uint8_t buf[IN_SIZE];
+       uint8_t mbuf[TS_SIZE];
+       int i;
+       int count = 1;
+       uint64_t length =0;
+       uint64_t l=0;
+       int perc =0;
+       int last_perc =0;
+       uint16_t pid;
+
+       if (verb) {
+               length = lseek(fdin, 0, SEEK_END);
+               lseek(fdin,0,SEEK_SET);
+       }
+
+       count = save_read(fdin,mbuf,TS_SIZE);
+       if (count) l+=count;
+       for ( i = 0; i < 188 ; i++){
+               if ( mbuf[i] == 0x47 ) break;
+       }
+       if ( i == 188){
+               fprintf(stderr,"Not a TS\n");
+               return;
+       } else {
+               memcpy(buf,mbuf+i,TS_SIZE-i);
+               count = save_read(fdin,mbuf,i);
+               if (count) l+=count;
+               memcpy(buf+TS_SIZE-i,mbuf,i);
+               i = 188;
+       }
+       
+       count = 1;
+       while (count > 0){
+               count = save_read(fdin,buf+i,IN_SIZE-i)+i;
+               if (count) l+=count;
+               if (verb && perc >last_perc){
+                       perc = (100*l)/length;
+                       fprintf(stderr,"Reading TS  %d %%\r",perc);
+                       last_perc = perc;
+               }
+
+               for( i = 0; i < count; i+= TS_SIZE){
+                       uint8_t off = 0;
+
+                       if ( count - i < TS_SIZE) break;
+
+                       pid = get_pid(buf+i+1);
+                       if (!(buf[3+i]&0x10)) // no payload?
+                               continue;
+                       if ( buf[1+i]&0x80){
+                               fprintf(stderr,"Error in TS for PID: %d\n", 
+                                       pid);
+                       }
+                       if (pid != pidv){
+                               continue;
+                       }
+
+                       if ( buf[3+i] & 0x20) {  // adaptation field?
+                               off = buf[4+i] + 1;
+                       }
+
+                       if ( buf[1+i]&0x40) {
+                               if (p->plength == MMAX_PLENGTH-6){
+                                       p->plength = p->found-6;
+                                       p->found = 0;
+                                       send_ipack(p);
+                                       reset_ipack(p);
+                               }
+                       }
+
+                       instant_repack(buf+4+off+i, TS_SIZE-4-off, p);
+               }
+               i = 0;
+
+       }
+}
+
+void ts2es(int fdin,  uint16_t pidv)
+{
+       ipack p;
+       int verb = 0;
+
+       init_ipack(&p, IPACKS,write_out_es, 0);
+       p.fd = STDOUT_FILENO;
+       p.data = (void *)&p;
+
+       if (fdin != STDIN_FILENO) verb = 1; 
+
+       ts2es_opt(fdin, pidv, &p, verb);
+}
+
+
+void change_aspect(int fdin, int fdout, int aspect)
+{
+       ps_packet ps;
+       pes_packet pes;
+       int neof,i;
+
+       do {
+               init_ps(&ps);
+               neof = read_ps(fdin,&ps);
+               write_ps(fdout,&ps);
+               for (i = 0; i < ps.npes; i++){
+                       uint8_t *buf;
+                       int c = 0;
+                       int l;
+
+                       init_pes(&pes);
+                       read_pes(fdin, &pes);
+
+                       buf = pes.pes_pckt_data;
+
+                       switch (pes.stream_id){
+                       case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+                               l=pes.length;
+                               break;
+                       default:
+                               l = 0;
+                               break;
+                       }
+                       while ( c < l - 6){
+                               if (buf[c] == 0x00 && 
+                                   buf[c+1] == 0x00 &&
+                                   buf[c+2] == 0x01 && 
+                                   buf[c+3] == 0xB3) {
+                                       c += 4;
+                                       buf[c+3] &= 0x0f;
+                                       buf[c+3] |= aspect;
+                               }
+                               else c++;
+                       }
+                       write_pes(fdout,&pes);
+               }
+       } while( neof > 0 );
+}
diff --git a/libdvbmpeg/transform.h b/libdvbmpeg/transform.h
new file mode 100644 (file)
index 0000000..ad32706
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ *  dvb-mpegtools for the Siemens Fujitsu DVB PCI card
+ *
+ * Copyright (C) 2000, 2001 Marcus Metzler 
+ *            for convergence integrated media GmbH
+ * Copyright (C) 2002  Marcus Metzler 
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ * 
+
+ * The author can be reached at mocm@metzlerbros.de, 
+
+ */
+
+#ifndef _TS_TRANSFORM_H_
+#define _TS_TRANSFORM_H_
+
+#include <stdint.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "remux.h"
+
+#define PROG_STREAM_MAP  0xBC
+#ifndef PRIVATE_STREAM1
+#define PRIVATE_STREAM1  0xBD
+#endif
+#define PADDING_STREAM   0xBE
+#ifndef PRIVATE_STREAM2
+#define PRIVATE_STREAM2  0xBF
+#endif
+#define AUDIO_STREAM_S   0xC0
+#define AUDIO_STREAM_E   0xDF
+#define VIDEO_STREAM_S   0xE0
+#define VIDEO_STREAM_E   0xEF
+#define ECM_STREAM       0xF0
+#define EMM_STREAM       0xF1
+#define DSM_CC_STREAM    0xF2
+#define ISO13522_STREAM  0xF3
+#define PROG_STREAM_DIR  0xFF
+
+#define BUFFYSIZE    10*MAX_PLENGTH
+#define MAX_PTS      8192
+#define MAX_FRAME    8192
+#define MAX_PACK_L   4096
+#define PS_HEADER_L1    14
+#define PS_HEADER_L2    (PS_HEADER_L1+18)
+#define MAX_H_SIZE   (PES_H_MIN + PS_HEADER_L1 + 5)
+#define PES_MIN         7
+#define PES_H_MIN       9
+
+//flags2
+#define PTS_DTS_FLAGS    0xC0
+#define ESCR_FLAG        0x20
+#define ES_RATE_FLAG     0x10
+#define DSM_TRICK_FLAG   0x08
+#define ADD_CPY_FLAG     0x04
+#define PES_CRC_FLAG     0x02
+#define PES_EXT_FLAG     0x01
+
+//pts_dts flags 
+#define PTS_ONLY         0x80
+#define PTS_DTS          0xC0
+
+#define TS_SIZE        188
+#define TRANS_ERROR    0x80
+#define PAY_START      0x40
+#define TRANS_PRIO     0x20
+#define PID_MASK_HI    0x1F
+//flags
+#define TRANS_SCRMBL1  0x80
+#define TRANS_SCRMBL2  0x40
+#define ADAPT_FIELD    0x20
+#define PAYLOAD        0x10
+#define COUNT_MASK     0x0F
+
+// adaptation flags
+#define DISCON_IND     0x80
+#define RAND_ACC_IND   0x40
+#define ES_PRI_IND     0x20
+#define PCR_FLAG       0x10
+#define OPCR_FLAG      0x08
+#define SPLICE_FLAG    0x04
+#define TRANS_PRIV     0x02
+#define ADAP_EXT_FLAG  0x01
+
+// adaptation extension flags
+#define LTW_FLAG       0x80
+#define PIECE_RATE     0x40
+#define SEAM_SPLICE    0x20
+
+
+#define MAX_PLENGTH 0xFFFF
+#define MMAX_PLENGTH (8*MAX_PLENGTH)
+
+#ifdef __cplusplus
+extern "C" {
+#endif                         /* __cplusplus */
+
+#define P2P_LENGTH 2048
+
+       enum{NOPES, AUDIO, VIDEO, AC3};
+
+       typedef struct p2pstruct {
+               int found;
+               uint8_t buf[MMAX_PLENGTH];
+               uint8_t cid;
+               uint8_t subid;
+               uint32_t plength;
+               uint8_t plen[2];
+               uint8_t flag1;
+               uint8_t flag2;
+               uint8_t hlength;
+               uint8_t pts[5];
+               int mpeg;
+               uint8_t check;
+               int fd1;
+               int fd2;
+               int es;
+               int filter;
+               int which;
+               int done;
+               int repack;
+               uint16_t bigend_repack;
+               void (*func)(uint8_t *buf, int count, void *p);
+               int startv;
+                int starta;
+               int64_t apts;
+                int64_t vpts;
+               uint16_t pid;
+               uint16_t pida;
+               uint16_t pidv;
+               uint8_t acounter;
+               uint8_t vcounter;
+               uint8_t count0;
+               uint8_t count1;
+               void *data;
+       } p2p;
+
+       
+       uint64_t trans_pts_dts(uint8_t *pts);
+       int write_ts_header(uint16_t pid, uint8_t *counter, int pes_start, 
+                           uint8_t *buf, uint8_t length);
+       uint16_t get_pid(uint8_t *pid);
+       void init_p2p(p2p *p, void (*func)(uint8_t *buf, int count, void *p),
+                     int repack);
+       void get_pes (uint8_t *buf, int count, p2p *p, void (*func)(p2p *p));
+       void get_pes (uint8_t *buf, int count, p2p *p, void (*func)(p2p *p));
+       void pes_repack(p2p *p);
+       void setup_pes2ts( p2p *p, uint32_t pida, uint32_t pidv, 
+                          void (*ts_write)(uint8_t *buf, int count, void *p));
+       void kpes_to_ts( p2p *p,uint8_t *buf ,int count );
+       void setup_ts2pes( p2p *pa, p2p *pv, uint32_t pida, uint32_t pidv, 
+                          void (*pes_write)(uint8_t *buf, int count, void *p));
+       void kts_to_pes( p2p *p, uint8_t *buf);
+       void pes_repack(p2p *p);
+       void extract_from_pes(int fdin, int fdout, uint8_t id, int es);
+       int64_t pes_dmx(int fdin, int fdouta, int fdoutv, int es);
+       void pes_to_ts2( int fdin, int fdout, uint16_t pida, uint16_t pidv);
+       void ts_to_pes( int fdin, uint16_t pida, uint16_t pidv, int pad);
+       int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr);
+       int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr);
+       int get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai, int pr);
+       void filter_audio_from_pes(int fdin, int fdout, uint8_t id, 
+                                  uint8_t subid);
+
+
+//instant repack
+
+       typedef struct ipack_s {
+               int size;
+               int size_orig;
+               int found;
+               int ps;
+               int has_ai;
+               int has_vi;
+               AudioInfo ai;
+               VideoInfo vi;
+               uint8_t *buf;
+               uint8_t cid;
+               uint32_t plength;
+               uint8_t plen[2];
+               uint8_t flag1;
+               uint8_t flag2;
+               uint8_t hlength;
+               uint8_t pts[5];
+               uint8_t last_pts[5];
+               int mpeg;
+               uint8_t check;
+               int which;
+               int done;
+               void *data;
+               void *data2;
+               void (*func)(uint8_t *buf,  int size, void *priv);
+               int count;
+               int start;
+               int fd;
+               int fd1;
+               int fd2;
+               int ffd;
+               int playing;
+       } ipack;
+
+       void instant_repack (uint8_t *buf, int count, ipack *p);
+       void init_ipack(ipack *p, int size,
+                       void (*func)(uint8_t *buf,  int size, void *priv),
+                       int pad);
+       void free_ipack(ipack * p);
+       void send_ipack(ipack *p);
+       void reset_ipack(ipack *p);                  
+       void ps_pes(ipack *p);
+       // use with ipack structure, repack size and callback func 
+
+       int64_t ts_demux(int fd_in, int fdv_out,int fda_out,uint16_t pida,
+                         uint16_t pidv, int es);
+
+       void ts2es(int fdin,  uint16_t pidv);
+       void ts2es_opt(int fdin,  uint16_t pidv, ipack *p, int verb);
+       void insert_pat_pmt( int fdin, int fdout);
+       void change_aspect(int fdin, int fdout, int aspect);
+
+// SV: all made non-static:
+       void pes_in_ts(p2p *p);
+
+// SV: moved from .c file:
+#define IPACKS 2048
+
+#ifdef __cplusplus
+}
+#endif                         /* __cplusplus */
+
+#endif /* _TS_TRANSFORM_H_*/
+
+
+
diff --git a/mvpclient.c b/mvpclient.c
new file mode 100644 (file)
index 0000000..74a5380
--- /dev/null
@@ -0,0 +1,750 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mvpclient.h"
+
+MVPClient::MVPClient(int tsocket)
+ : tcp(tsocket)
+{
+  cm = NULL;
+  rp = NULL;
+  recordingManager = NULL;
+
+  // Get IP address of client for config module
+
+  char ipa[20];
+  struct sockaddr_in peer;
+  socklen_t salen = sizeof(struct sockaddr);
+  if(getpeername(tsocket, (struct sockaddr*)&peer, &salen) == 0)
+  {
+    strcpy(ipa, inet_ntoa(peer.sin_addr));
+  }
+  else
+  {
+    ipa[0] = '\0';
+    printf("Cannot get peer name!\n");
+  }
+
+  const char* configDir = cPlugin::ConfigDirectory();
+  if (!configDir)
+  {
+    printf("No config dir!\n");
+    return;
+  }
+
+  char configFileName[PATH_MAX];
+  snprintf(configFileName, PATH_MAX - strlen(configDir) - strlen(ipa) - 20, "%s/vomp-%s.conf", configDir, ipa);
+  config.init(configFileName);
+
+  printf("Config file name: %s\n", configFileName);
+
+//  processGetChannelSchedule(NULL, 0);
+
+//  printf("here\n");
+//test();
+
+}
+
+MVPClient::~MVPClient()
+{
+  printf("MVP client destructor\n");
+  if (cm)
+  {
+    cm->Stop();
+    delete cm;
+    cm = NULL;
+  }
+  else if (rp)
+  {
+    writeResumeData();
+
+    delete rp;
+    delete recordingManager;
+    rp = NULL;
+    recordingManager = NULL;
+  }
+
+  cleanConfig();
+}
+
+cChannel* MVPClient::channelFromNumber(unsigned long channelNumber)
+{
+  cChannel* channel = NULL;
+
+  for (channel = Channels.First(); channel; channel = Channels.Next(channel))
+  {
+    if (!channel->GroupSep())
+    {
+      printf("Looking for channel %lu::: number: %i name: '%s'\n", channelNumber, channel->Number(), channel->Name());
+
+      if (channel->Number() == (int)channelNumber)
+      {
+        int vpid = channel->Vpid();
+        int apid1 = channel->Apid1();
+
+        printf("Found channel number %lu, vpid = %i, apid1 = %i\n", channelNumber, vpid, apid1);
+        return channel;
+      }
+    }
+  }
+
+  if (!channel)
+  {
+    printf("Channel not found\n");
+  }
+
+  return channel;
+}
+
+
+void MVPClient::writeResumeData()
+{
+  config.setValueLongLong("ResumeData", (char*)rp->getCurrentRecording()->FileName(), rp->getLastPosition());
+}
+
+void MVPClient::sendULONG(ULONG ul)
+{
+  unsigned char sendBuffer[8];
+  *(unsigned long*)&sendBuffer[0] = htonl(4);
+  *(unsigned long*)&sendBuffer[4] = htonl(ul);
+
+  tcp.sendPacket(sendBuffer, 8);
+  printf("written ULONG %lu\n", ul);
+}
+
+void MVPClientStartThread(void* arg)
+{
+  MVPClient* m = (MVPClient*)arg;
+  m->run2();
+  // Nothing external to this class has a reference to it
+  // This is the end of the thread.. so delete m
+  delete m;
+  pthread_exit(NULL);
+}
+
+int MVPClient::run()
+{
+  if (pthread_create(&runThread, NULL, (void*(*)(void*))MVPClientStartThread, (void *)this) == -1) return 0;
+  printf("MVPClient run success\n");
+  return 1;
+}
+
+void MVPClient::run2()
+{
+  // Thread stuff
+  sigset_t sigset;
+  sigfillset(&sigset);
+  pthread_sigmask(SIG_BLOCK, &sigset, NULL);
+  pthread_detach(runThread);  // Detach
+
+  tcp.disableReadTimeout();
+
+  tcp.setSoKeepTime(3);
+  tcp.setNonBlocking();
+
+  unsigned char* buffer;
+  unsigned char* data;
+  int packetLength;
+  unsigned long opcode;
+
+  while(1)
+  {
+    printf("starting wait\n");
+    buffer = (unsigned char*)tcp.receivePacket();
+    printf("back from wait\n");
+    if (buffer == NULL)
+    {
+      printf("Detected connection closed\n");
+      break;
+    }
+
+    packetLength = tcp.getDataLength() - 4;
+    opcode = ntohl(*(unsigned long*)buffer);
+    data = buffer + 4;
+
+
+    switch(opcode)
+    {
+      case 1:
+        processLogin(data, packetLength);
+        break;
+      case 2:
+        processGetRecordingsList(data, packetLength);
+        break;
+      case 3:
+        processDeleteRecording(data, packetLength);
+        break;
+      case 4:
+        processGetSummary(data, packetLength);
+        break;
+      case 5:
+        processGetChannelsList(data, packetLength);
+        break;
+      case 6:
+        processStartStreamingChannel(data, packetLength);
+        break;
+      case 7:
+        processGetBlock(data, packetLength);
+        break;
+      case 8:
+        processStopStreaming(data, packetLength);
+        break;
+      case 9:
+        processStartStreamingRecording(data, packetLength);
+        break;
+      case 10:
+        processGetChannelSchedule(data, packetLength);
+        break;
+      case 11:
+        processConfigSave(data, packetLength);
+        break;
+      case 12:
+        processConfigLoad(data, packetLength);
+        break;
+    }
+
+    free(buffer);
+  }
+}
+
+void MVPClient::processLogin(unsigned char* buffer, int length)
+{
+  time_t timeNow = time(NULL);
+  struct tm* timeStruct = localtime(&timeNow);
+  timeOffset = timeStruct->tm_gmtoff;
+
+  // seems dhcp is sending timezone out to mvp
+  // so just supply utc timestamp
+  timeOffset = 0;
+
+  sendULONG(timeNow + timeOffset);
+  printf("written time\n");
+}
+
+void MVPClient::processGetRecordingsList(unsigned char* data, int length)
+{
+  unsigned char* sendBuffer = new unsigned char[50000]; // hope this is enough
+  int count = 4; // leave space for the packet length
+  char* point;
+
+
+  int FreeMB;
+  int Percent = VideoDiskSpace(&FreeMB);
+  int Total = (FreeMB / (100 - Percent)) * 100;
+
+  *(unsigned long*)&sendBuffer[count] = htonl(Total);
+  count += sizeof(unsigned long);
+  *(unsigned long*)&sendBuffer[count] = htonl(FreeMB);
+  count += sizeof(unsigned long);
+  *(unsigned long*)&sendBuffer[count] = htonl(Percent);
+  count += sizeof(unsigned long);
+
+
+  cRecordings Recordings;
+  Recordings.Load();
+
+  for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording))
+  {
+    if (count > 49000) break; // just how big is that hard disk?!
+    *(unsigned long*)&sendBuffer[count] = htonl(recording->start + timeOffset);
+    count += 4;
+
+    point = (char*)recording->Name();
+    strcpy((char*)&sendBuffer[count], point);
+    count += strlen(point) + 1;
+
+    point = (char*)recording->FileName();
+    strcpy((char*)&sendBuffer[count], point);
+    count += strlen(point) + 1;
+  }
+
+  *(unsigned long*)&sendBuffer[0] = htonl(count - 4); // -4 :  take off the size field
+
+  printf("recorded size as %u\n", ntohl(*(unsigned long*)&sendBuffer[0]));
+
+  tcp.sendPacket(sendBuffer, count);
+  delete[] sendBuffer;
+  printf("Written list\n");
+}
+
+void MVPClient::processDeleteRecording(unsigned char* data, int length)
+{
+  // data is a pointer to the fileName string
+
+  cRecordings Recordings;
+  Recordings.Load(); // probably have to do this
+
+  cRecording* recording = Recordings.GetByName((char*)data);
+
+  printf("recording pointer %p\n", recording);
+
+  if (recording)
+  {
+    printf("deleting recording: %s\n", recording->Name());
+    recording->Delete();
+    sendULONG(1);
+  }
+  else
+  {
+    sendULONG(0);
+  }
+}
+
+void MVPClient::processGetSummary(unsigned char* data, int length)
+{
+  // data is a pointer to the fileName string
+
+  cRecordings Recordings;
+  Recordings.Load(); // probably have to do this
+
+  cRecording* recording = Recordings.GetByName((char*)data);
+
+  printf("recording pointer %p\n", recording);
+
+  if (recording)
+  {
+    unsigned char* sendBuffer = new unsigned char[50000]; // hope this is enough
+    int count = 4; // leave space for the packet length
+
+    char* point;
+
+    point = (char*)recording->Summary();
+    strcpy((char*)&sendBuffer[count], point);
+    count += strlen(point) + 1;
+    *(unsigned long*)&sendBuffer[0] = htonl(count - 4); // -4 :  take off the size field
+
+    printf("recorded size as %u\n", ntohl(*(unsigned long*)&sendBuffer[0]));
+
+    tcp.sendPacket(sendBuffer, count);
+    delete[] sendBuffer;
+    printf("Written summary\n");
+
+
+  }
+  else
+  {
+    sendULONG(0);
+  }
+}
+
+void MVPClient::processGetChannelsList(unsigned char* data, int length)
+{
+  unsigned char* sendBuffer = new unsigned char[50000]; // FIXME hope this is enough
+  int count = 4; // leave space for the packet length
+  char* point;
+  unsigned long type;
+
+  for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel))
+  {
+    if (!channel->GroupSep())
+    {
+      printf("name: '%s'\n", channel->Name());
+
+      if (count > 49000) break;
+      *(unsigned long*)&sendBuffer[count] = htonl(channel->Number());
+      count += 4;
+
+      if (channel->Vpid()) type = 1;
+      else type = 2;
+
+      *(unsigned long*)&sendBuffer[count] = htonl(type);
+      count += 4;
+
+      point = (char*)channel->Name();
+      strcpy((char*)&sendBuffer[count], point);
+      count += strlen(point) + 1;
+    }
+  }
+
+  *(unsigned long*)&sendBuffer[0] = htonl(count - 4); // -4 :  take off the size field
+
+  printf("recorded size as %u\n", ntohl(*(unsigned long*)&sendBuffer[0]));
+
+  tcp.sendPacket(sendBuffer, count);
+  delete[] sendBuffer;
+  printf("Written channels list\n");
+}
+
+void MVPClient::processStartStreamingChannel(unsigned char* data, int length)
+{
+  printf("length = %i\n", length);
+  unsigned long channelNumber = ntohl(*(unsigned long*)data);
+
+  cChannel* channel = channelFromNumber(channelNumber);
+  if (!channel)
+  {
+    sendULONG(0);
+    return;
+  }
+
+//  MVPReceiver* m = new MVPReceiver(channel->Vpid(), channel->Apid1());
+  cm = new cMediamvpTransceiver(channel, 0, 0, cDevice::ActualDevice());
+  cDevice::ActualDevice()->AttachReceiver(cm);
+  //cDevice::ActualDevice()->SwitchChannel(channel, false);
+
+  sendULONG(1);
+}
+
+void MVPClient::processStopStreaming(unsigned char* data, int length)
+{
+  printf("STOP STREAMING RECEIVED\n");
+  if (cm)
+  {
+    delete cm;
+    cm = NULL;
+  }
+  else if (rp)
+  {
+    writeResumeData();
+
+    delete rp;
+    delete recordingManager;
+    rp = NULL;
+    recordingManager = NULL;
+  }
+
+  sendULONG(1);
+}
+
+void MVPClient::processGetBlock(unsigned char* data, int length)
+{
+  if (!cm && !rp)
+  {
+    printf("Get block called when no streaming happening!\n");
+    return;
+  }
+
+  ULLONG position = ntohll(*(ULLONG*)data);
+  printf("getblock called for position = %llu\n", position);
+
+  data += sizeof(ULLONG);
+
+  unsigned long amount = ntohl(*(unsigned long*)data);
+  printf("getblock called for length = %lu\n", amount);
+
+  unsigned char sendBuffer[amount + 4];
+  unsigned long amountReceived = 0; // compiler moan.
+  if (cm)
+  {
+    printf("getting from live\n");
+    amountReceived = cm->getBlock(&sendBuffer[4], amount);
+  }
+  else if (rp)
+  {
+    printf("getting from recording\n");
+    amountReceived = rp->getBlock(&sendBuffer[4], position, amount);
+  }
+
+  *(unsigned long*)&sendBuffer[0] = htonl(amountReceived);
+  printf("sendpacket go\n");
+  tcp.sendPacket(sendBuffer, amountReceived + 4);
+  printf("written ok %lu\n", amountReceived);
+}
+
+void MVPClient::processStartStreamingRecording(unsigned char* data, int length)
+{
+  // data is a pointer to the fileName string
+
+  recordingManager = new cRecordings;
+  recordingManager->Load();
+
+  cRecording* recording = recordingManager->GetByName((char*)data);
+
+  printf("recording pointer %p\n", recording);
+
+  if (recording)
+  {
+    rp = new RecPlayer(recording);
+
+    unsigned char sendBuffer[12];
+    *(unsigned long*)&sendBuffer[0] = htonl(8);
+    *(ULLONG*)&sendBuffer[4] = htonll(rp->getTotalLength());
+
+    tcp.sendPacket(sendBuffer, 12);
+    printf("written totalLength\n");
+  }
+  else
+  {
+    delete recordingManager;
+    recordingManager = NULL;
+  }
+}
+
+void MVPClient::processGetChannelSchedule(unsigned char* data, int length)
+{
+  ULONG channelNumber = ntohl(*(ULLONG*)data);
+  printf("get schedule called for channel %lu\n", channelNumber);
+
+  cChannel* channel = channelFromNumber(channelNumber);
+  if (!channel)
+  {
+    unsigned char sendBuffer[4];
+    *(unsigned long*)&sendBuffer[0] = htonl(0);
+    tcp.sendPacket(sendBuffer, 4);
+    printf("written null\n");
+    return;
+  }
+
+  cMutexLock MutexLock;
+  const cSchedules* Schedules = cSIProcessor::Schedules(MutexLock);
+//  const cSchedules* Schedules = cSchedules::Schedules(MutexLock);
+  if (!Schedules)
+  {
+    unsigned char sendBuffer[8];
+    *(unsigned long*)&sendBuffer[0] = htonl(4);
+    *(unsigned long*)&sendBuffer[4] = htonl(0);
+    tcp.sendPacket(sendBuffer, 8);
+    printf("written 0\n");
+    return;
+  }
+
+  unsigned char sendBuffer[8];
+  *(unsigned long*)&sendBuffer[0] = htonl(4);
+  *(unsigned long*)&sendBuffer[4] = htonl(1);
+  tcp.sendPacket(sendBuffer, 8);
+  printf("written 1\n");
+
+
+}
+
+void MVPClient::testChannelSchedule(unsigned char* data, int length)
+{
+  FILE* f = fopen("/tmp/s.txt", "w");
+
+  cMutexLock MutexLock;
+  const cSchedules* Schedules = cSIProcessor::Schedules(MutexLock);
+//  const cSchedules* Schedules = cSchedules::Schedules(MutexLock);
+  if (!Schedules)
+  {
+    fprintf(f, "Schedules = NULL\n");
+    fclose(f);
+    return;
+  }
+
+  fprintf(f, "Schedules dump:\n");
+  Schedules->Dump(f);
+
+
+  const cSchedule *Schedule;
+  int scheduleNumber = 0;
+
+  tChannelID tchid;
+  cChannel *thisChannel;
+
+  const cEventInfo* event;
+  int eventNumber = 0;
+
+//    Schedule = Schedules->GetSchedule(channel->GetChannelID());
+//    Schedule = Schedules->GetSchedule();
+  Schedule = Schedules->First();
+  if (!Schedule)
+  {
+    fprintf(f, "First Schedule = NULL\n");
+    fclose(f);
+    return;
+  }
+
+  while (Schedule)
+  {
+    fprintf(f, "Schedule #%i\n", scheduleNumber);
+    fprintf(f, "-------------\n\n");
+
+    tchid = Schedule->GetChannelID();
+    fprintf(f, "ChannelID.ToString() = %s\n", tchid.ToString());
+    fprintf(f, "NumEvents() = %i\n", Schedule->NumEvents());
+    thisChannel = Channels.GetByChannelID(tchid, true);
+    if (thisChannel)
+    {
+      fprintf(f, "Channel Number: %p %i\n", thisChannel, thisChannel->Number());
+    }
+    else
+    {
+      fprintf(f, "thisChannel = NULL for tchid\n");
+    }
+
+    for (eventNumber = 0; eventNumber < Schedule->NumEvents(); eventNumber++)
+    {
+      event = Schedule->GetEventNumber(eventNumber);
+      fprintf(f, "Event %i tableid = %i timestring = %s endtimestring = %s\n", eventNumber, event->GetTableID(), event->GetTimeString(), event->GetEndTimeString());
+      fprintf(f, "Event %i date = %s isfollowing = %i ispresent = %i\n", eventNumber, event->GetDate(), event->IsFollowing(), event->IsPresent());
+      fprintf(f, "Event %i extendeddescription = %s\n", eventNumber, event->GetExtendedDescription());
+      fprintf(f, "Event %i subtitle = %s title = %s\n", eventNumber, event->GetSubtitle(), event->GetTitle());
+      fprintf(f, "Event %i eventid = %u duration = %li time = %lu channelnumber = %i\n", eventNumber, event->GetEventID(), event->GetDuration(), event->GetTime(), event->GetChannelNumber());
+      fprintf(f, "Event %u dump:\n", eventNumber);
+      event->Dump(f);
+      fprintf(f, "\n\n");
+    }
+
+
+
+    fprintf(f, "\nDump from object:\n");
+    Schedule->Dump(f);
+    fprintf(f, "\nEND\n");
+
+
+
+
+/*
+  const cEventInfo *GetPresentEvent(void) const;
+  const cEventInfo *GetFollowingEvent(void) const;
+  const cEventInfo *GetEvent(unsigned short uEventID, time_t tTime = 0) const;
+  const cEventInfo *GetEventAround(time_t tTime) const;
+  const cEventInfo *GetEventNumber(int n) const { return Events.Get(n); }
+
+
+  const unsigned char GetTableID(void) const;
+  const char *GetTimeString(void) const;
+  const char *GetEndTimeString(void) const;
+  const char *GetDate(void) const;
+  bool IsFollowing(void) const;
+  bool IsPresent(void) const;
+  const char *GetExtendedDescription(void) const;
+  const char *GetSubtitle(void) const;
+  const char *GetTitle(void) const;
+  unsigned short GetEventID(void) const;
+  long GetDuration(void) const;
+  time_t GetTime(void) const;
+  tChannelID GetChannelID(void) const;
+  int GetChannelNumber(void) const { return nChannelNumber; }
+  void SetChannelNumber(int ChannelNumber) const { ((cEventInfo *)this)->nChannelNumber = ChannelNumber; } // doesn't modify the EIT data, so it's ok to make it 'const'
+  void Dump(FILE *f, const char *Prefix = "") const;
+
+*/
+
+
+
+
+
+    fprintf(f, "End of current Schedule\n\n\n");
+
+    Schedule = (const cSchedule *)Schedules->Next(Schedule);
+    scheduleNumber++;
+  }
+
+  fclose(f);
+}
+
+void MVPClient::processConfigSave(unsigned char* buffer, int length)
+{
+  char* section = (char*)buffer;
+  char* key = NULL;
+  char* value = NULL;
+
+  for (int k = 0; k < length; k++)
+  {
+    if (buffer[k] == '\0')
+    {
+      if (!key)
+      {
+        key = (char*)&buffer[k+1];
+      }
+      else
+      {
+        value = (char*)&buffer[k+1];
+        break;
+      }
+    }
+  }
+
+  // if the last string (value) doesnt have null terminator, give up
+  if (buffer[length - 1] != '\0') return;
+
+  printf("Config save:\n%s\n%s\n%s\n", section, key, value);
+  if (config.setValueString(section, key, value))
+  {
+    sendULONG(1);
+  }
+  else
+  {
+    sendULONG(0);
+  }
+}
+
+void MVPClient::processConfigLoad(unsigned char* buffer, int length)
+{
+  char* section = (char*)buffer;
+  char* key = NULL;
+
+  for (int k = 0; k < length; k++)
+  {
+    if (buffer[k] == '\0')
+    {
+      key = (char*)&buffer[k+1];
+      break;
+    }
+  }
+
+  char* value = config.getValueString(section, key);
+
+  if (value)
+  {
+    unsigned char sendBuffer[4 + strlen(value) + 1];
+    *(unsigned long*)&sendBuffer[0] = htonl(strlen(value) + 1);
+    strcpy((char*)&sendBuffer[4], value);
+    tcp.sendPacket(sendBuffer, 4 + strlen(value) + 1);
+
+    printf("Written config load packet\n");
+    delete[] value;
+  }
+  else
+  {
+    unsigned char sendBuffer[8];
+    *(unsigned long*)&sendBuffer[0] = htonl(0);
+    *(unsigned long*)&sendBuffer[4] = htonl(0);
+    tcp.sendPacket(sendBuffer, 8);
+
+    printf("Written config load failed packet\n");
+  }
+}
+
+void MVPClient::cleanConfig()
+{
+  printf("Clean config\n");
+
+  cRecordings Recordings;
+  Recordings.Load();
+
+  int numReturns;
+  int length;
+  char* resumes = config.getSectionKeyNames("ResumeData", numReturns, length);
+  char* position = resumes;
+  for(int k = 0; k < numReturns; k++)
+  {
+    printf("EXAMINING: %i %i %p %s\n", k, numReturns, position, position);
+
+    cRecording* recording = Recordings.GetByName(position);
+    if (!recording)
+    {
+      // doesn't exist anymore
+      printf("Found a recording that doesn't exist anymore\n");
+      config.deleteValue("ResumeData", position);
+    }
+    else
+    {
+      printf("This recording still exists\n");
+    }
+
+    position += strlen(position) + 1;
+  }
+
+  delete[] resumes;
+}
+
+
diff --git a/mvpclient.h b/mvpclient.h
new file mode 100644 (file)
index 0000000..d704314
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MVPCLIENT_H
+#define MVPCLIENT_H
+
+#include <stdio.h>
+#include <pthread.h>
+#include <netinet/in.h>
+#include <signal.h>
+
+#include <unistd.h> // sleep
+
+#include <vdr/recording.h>
+#include <vdr/channels.h>
+#include <vdr/videodir.h>
+#include <vdr/plugin.h>
+
+#include "tcp.h"
+#include "transceiver.h"
+#include "recplayer.h"
+#include "config.h"
+
+class MVPClient
+{
+  public:
+    MVPClient(int tsocket);
+    ~MVPClient();
+
+    int run();
+    // not for external use
+    void run2();
+
+  private:
+    pthread_t runThread;
+    int initted;
+    TCP tcp;
+    Config config;
+    cMediamvpTransceiver* cm;
+    cRecordings* recordingManager;
+    RecPlayer* rp;
+    int timeOffset;
+
+    void processLogin(unsigned char* buffer, int length);
+    void processGetRecordingsList(unsigned char* data, int length);
+    void processDeleteRecording(unsigned char* data, int length);
+    void processGetSummary(unsigned char* data, int length);
+    void processGetChannelsList(unsigned char* data, int length);
+    void processStartStreamingChannel(unsigned char* data, int length);
+    void processGetBlock(unsigned char* data, int length);
+    void processStopStreaming(unsigned char* data, int length);
+    void processStartStreamingRecording(unsigned char* data, int length);
+    void processGetChannelSchedule(unsigned char* data, int length);
+    void processConfigSave(unsigned char* data, int length);
+    void processConfigLoad(unsigned char* data, int length);
+
+    cChannel* channelFromNumber(unsigned long channelNumber);
+    void writeResumeData();
+    void cleanConfig();
+
+    void sendULONG(ULONG ul);
+
+    void testChannelSchedule(unsigned char* data, int length);
+};
+
+#endif
diff --git a/mvpserver.c b/mvpserver.c
new file mode 100644 (file)
index 0000000..35bb3f1
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mvpserver.h"
+
+// undeclared function
+void MVPServerStartThread(void *arg)
+{
+  MVPServer *m = (MVPServer *)arg;
+  m->run2();
+}
+
+
+MVPServer::MVPServer()
+{
+  runThread = 0;
+  running = 0;
+}
+
+MVPServer::~MVPServer()
+{
+  if (running) stop();
+}
+
+int MVPServer::stop()
+{
+  if (!running) return 0;
+
+  udpr.stop();
+
+  pthread_cancel(runThread);
+  pthread_join(runThread, NULL);
+
+  close(listeningSocket);
+
+  return 1;
+}
+
+int MVPServer::run()
+{
+  if (running) return 1;
+
+//  logger.init(Log::DEBUG, "/tmp/vompserver.log");
+
+  if (udpr.run() == 0) return 0;
+
+  if (pthread_create(&runThread, NULL, (void*(*)(void*))MVPServerStartThread, (void *)this) == -1) return 0;
+  printf("MVPServer run success\n");
+  return 1;
+}
+
+void MVPServer::run2()
+{
+  // Thread stuff
+  // I don't want signals and I want to die as soon as I am cancelled because I'll be in accept()
+  sigset_t sigset;
+  sigfillset(&sigset);
+  pthread_sigmask(SIG_BLOCK, &sigset, NULL);
+  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+  pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+
+  struct sockaddr_in address;
+  address.sin_family = AF_INET;
+  address.sin_port = htons(3024);
+  address.sin_addr.s_addr = INADDR_ANY;
+  socklen_t length = sizeof(address);
+
+  listeningSocket = socket(AF_INET, SOCK_STREAM, 0);
+  if (listeningSocket < 0)
+  {
+    printf("Could not get TCP socket in vompserver\n");
+    return;
+  }
+
+  int value=1;
+  setsockopt(listeningSocket,SOL_SOCKET,SO_REUSEADDR,&value,sizeof(value));
+
+  if (bind(listeningSocket,(struct sockaddr *)&address,sizeof(address)) < 0)
+  {
+    printf("Could not bind to socket in vompserver\n");
+    close(listeningSocket);
+    return;
+  }
+
+  listen(listeningSocket, 5);
+
+  int clientSocket;
+
+  while(1)
+  {
+    clientSocket = accept(listeningSocket,(struct sockaddr *)&address, &length);
+    MVPClient* m = new MVPClient(clientSocket);
+    m->run();
+  }
+}
+
+
+ULLONG ntohll(ULLONG a)
+{
+  return htonll(a);
+}
+
+ULLONG htonll(ULLONG a)
+{
+  #if BYTE_ORDER == BIG_ENDIAN
+    return a;
+  #else
+    ULLONG b = 0;
+
+    b = ((a << 56) & 0xFF00000000000000ULL)
+      | ((a << 40) & 0x00FF000000000000ULL)
+      | ((a << 24) & 0x0000FF0000000000ULL)
+      | ((a <<  8) & 0x000000FF00000000ULL)
+      | ((a >>  8) & 0x00000000FF000000ULL)
+      | ((a >> 24) & 0x0000000000FF0000ULL)
+      | ((a >> 40) & 0x000000000000FF00ULL)
+      | ((a >> 56) & 0x00000000000000FFULL) ;
+
+    return b;
+  #endif
+}
diff --git a/mvpserver.h b/mvpserver.h
new file mode 100644 (file)
index 0000000..64caaff
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MVPSERVER_H
+#define MVPSERVER_H
+
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h> // sleep
+#include <endian.h>
+
+#include "defines.h"
+#include "udpreplier.h"
+#include "mvpclient.h"
+
+class MVPServer
+{
+  public:
+    MVPServer();
+    ~MVPServer();
+
+    int run();
+    int stop();
+
+    // not for external use
+    void run2();
+
+  private:
+    pthread_t runThread;
+    int running;
+
+    UDPReplier udpr;
+    int listeningSocket;
+};
+
+#endif
diff --git a/recplayer.c b/recplayer.c
new file mode 100644 (file)
index 0000000..6c24033
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "recplayer.h"
+
+RecPlayer::RecPlayer(cRecording* rec)
+{
+  file = NULL;
+  totalLength = 0;
+  lastPosition = 0;
+  recording = rec;
+
+  // FIXME find out max file path / name lengths
+
+
+  char fileName[2048];
+  for(int i = 1; i < 1001; i++)
+  {
+    snprintf(fileName, 2047, "%s/%03i.vdr", rec->FileName(), i);
+    printf("FILENAME: %s\n", fileName);
+    file = fopen(fileName, "r");
+    if (file)
+    {
+      segments[i] = new Segment();
+      segments[i]->start = totalLength;
+
+      fseek(file, 0, SEEK_END);
+      totalLength += ftell(file);
+      printf("File %i found, totalLength now %llu\n", i, totalLength);
+      segments[i]->end = totalLength;
+      fclose(file);
+    }
+    else
+    {
+      segments[i] = NULL;
+      break;
+    }
+  }
+  openFile(1);
+}
+
+RecPlayer::~RecPlayer()
+{
+  printf("RecPlayer destructor\n");
+  int i = 1;
+  while(segments[i++]) delete segments[i];
+  if (file) fclose(file);
+}
+
+int RecPlayer::openFile(int index)
+{
+  if (file) fclose(file);
+
+  char fileName[2048];
+  snprintf(fileName, 2047, "%s/%03i.vdr", recording->FileName(), index);
+  printf("openFile called for index %i string:%s\n", index, fileName);
+
+  file = fopen(fileName, "r");
+  if (!file)
+  {
+    printf("file failed to open\n");
+    fileOpen = 0;
+    return 0;
+  }
+  fileOpen = index;
+  return 1;
+}
+
+ULLONG RecPlayer::getTotalLength()
+{
+  return totalLength;
+}
+
+unsigned long RecPlayer::getBlock(unsigned char* buffer, ULLONG position, unsigned long amount)
+{
+  if ((amount > totalLength) || (amount > 100000))
+  {
+    printf("Amount %lu requested and rejected\n", amount);
+    return 0;
+  }
+
+  if (position >= totalLength)
+  {
+    printf("Client asked for data starting past end of recording!\n");
+    return 0;
+  }
+
+  if ((position + amount) > totalLength)
+  {
+    printf("Client asked for some data past the end of recording, adjusting amount\n");
+    amount = totalLength - position;
+  }
+
+  // work out what block position is in
+  int segmentNumber;
+  for(segmentNumber = 1; segmentNumber < 1000; segmentNumber++)
+  {
+    if ((position >= segments[segmentNumber]->start) && (position < segments[segmentNumber]->end)) break;
+    // position is in this block
+  }
+
+  // we could be seeking around
+  if (segmentNumber != fileOpen)
+  {
+    if (!openFile(segmentNumber)) return 0;
+  }
+
+  ULLONG currentPosition = position;
+  ULONG yetToGet = amount;
+  ULONG got = 0;
+  ULONG getFromThisSegment = 0;
+  ULONG filePosition;
+
+  while(got < amount)
+  {
+    if (got)
+    {
+      // if(got) then we have already got some and we are back around
+      // advance the file pointer to the next file
+      if (!openFile(++segmentNumber)) return 0;
+    }
+
+    // is the request completely in this block?
+    if ((currentPosition + yetToGet) <= segments[segmentNumber]->end)
+      getFromThisSegment = yetToGet;
+    else
+      getFromThisSegment = segments[segmentNumber]->end - currentPosition;
+
+    filePosition = currentPosition - segments[segmentNumber]->start;
+    fseek(file, filePosition, SEEK_SET);
+    if (fread(&buffer[got], getFromThisSegment, 1, file) != 1) return 0; // umm, big problem.
+
+    got += getFromThisSegment;
+    currentPosition += getFromThisSegment;
+    yetToGet -= getFromThisSegment;
+  }
+
+  lastPosition = position;
+  return got;
+}
+
+ULLONG RecPlayer::getLastPosition()
+{
+  return lastPosition;
+}
+
+cRecording* RecPlayer::getCurrentRecording()
+{
+  return recording;
+}
diff --git a/recplayer.h b/recplayer.h
new file mode 100644 (file)
index 0000000..0a48b41
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef RECPLAYER_H
+#define RECPLAYER_H
+
+#include <stdio.h>
+#include <vdr/recording.h>
+
+#include "defines.h"
+
+class Segment
+{
+  public:
+    ULLONG start;
+    ULLONG end;
+};
+
+class RecPlayer
+{
+  public:
+    RecPlayer(cRecording* rec);
+    ~RecPlayer();
+    ULLONG getTotalLength();
+    unsigned long getBlock(unsigned char* buffer, ULLONG position, unsigned long amount);
+    int openFile(int index);
+    ULLONG getLastPosition();
+    cRecording* getCurrentRecording();
+
+  private:
+    cRecording* recording;
+    FILE* file;
+    int fileOpen;
+    Segment* segments[1001];
+    ULLONG totalLength;
+    ULLONG lastPosition;
+};
+
+#endif
diff --git a/remux/README b/remux/README
new file mode 100644 (file)
index 0000000..0ee66d8
--- /dev/null
@@ -0,0 +1,7 @@
+These remux files are taken from the mediamvp plugin for VDR,
+which takes them from the streamdev plugin for VDR.
+
+So these files are written by, and Copyright, Sascha Volkenandt.
+I think.
+
+
diff --git a/remux/ts2es.c b/remux/ts2es.c
new file mode 100644 (file)
index 0000000..68b41f0
--- /dev/null
@@ -0,0 +1,87 @@
+#include "ts2es.h"
+
+// from VDR's remux.c
+#define MAXNONUSEFULDATA (10*1024*1024)
+
+class cTS2ES: public ipack {
+        friend void PutES(uint8_t *Buffer, int Size, void *Data);
+
+private:
+        uint8_t *m_ResultBuffer;
+        int *m_ResultCount;
+
+public:
+        cTS2ES(uint8_t *ResultBuffer, int *ResultCount);
+        ~cTS2ES();
+
+        void PutTSPacket(const uint8_t *Buffer);
+};
+
+void PutES(uint8_t *Buffer, int Size, void *Data) {
+        cTS2ES *This = (cTS2ES*)Data;
+        uint8_t payl = Buffer[8] + 9 + This->start - 1;
+        int count = Size - payl;
+
+        if (*This->m_ResultCount + count > RESULTBUFFERSIZE) {
+                esyslog("ERROR: result buffer overflow (%d + %d > %d)",
+                                *This->m_ResultCount, count, RESULTBUFFERSIZE);
+                count = RESULTBUFFERSIZE - *This->m_ResultCount;
+        }
+        memcpy(This->m_ResultBuffer + *This->m_ResultCount, Buffer + payl, count);
+        *This->m_ResultCount += count;
+        This->start = 1;
+}
+
+cTS2ES::cTS2ES(uint8_t *ResultBuffer, int *ResultCount) {
+        m_ResultBuffer = ResultBuffer;
+        m_ResultCount = ResultCount;
+
+        init_ipack(this, IPACKS, PutES, 0);
+        data = (void*)this;
+}
+
+cTS2ES::~cTS2ES() {
+}
+
+void cTS2ES::PutTSPacket(const uint8_t *Buffer) {
+  if (!Buffer)
+     return;
+
+  if (Buffer[1] & 0x80) { // ts error
+                // TODO
+        }
+
+  if (Buffer[1] & 0x40) { // payload start
+                if (plength == MMAX_PLENGTH - 6) {
+            plength = found - 6;
+      found = 0;
+      send_ipack(this);
+      reset_ipack(this);
+    }
+  }
+
+        uint8_t off = 0;
+
+  if (Buffer[3] & 0x20) {  // adaptation field?
+                off = Buffer[4] + 1;
+    if (off + 4 > TS_SIZE - 1)
+      return;
+  }
+
+  instant_repack((uint8_t*)(Buffer + 4 + off), TS_SIZE - 4 - off, this);
+}
+
+cTS2ESRemux::cTS2ESRemux(int Pid):
+                cTSRemux(false) {
+        m_Pid = Pid;
+  m_Remux = new cTS2ES(m_ResultBuffer, &m_ResultCount);
+}
+
+cTS2ESRemux::~cTS2ESRemux() {
+        delete m_Remux;
+}
+
+void cTS2ESRemux::PutTSPacket(int Pid, const uint8_t *Data) {
+        if (Pid == m_Pid) m_Remux->PutTSPacket(Data);
+}
+
diff --git a/remux/ts2es.h b/remux/ts2es.h
new file mode 100644 (file)
index 0000000..52e9918
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef VDR_STREAMDEV_TS2ESREMUX_H
+#define VDR_STREAMDEV_TS2ESREMUX_H
+
+#include "tsremux.h"
+
+class cTS2ES;
+
+class cTS2ESRemux: public cTSRemux {
+private:
+        int m_Pid;
+        cTS2ES *m_Remux;
+
+protected:
+        virtual void PutTSPacket(int Pid, const uint8_t *Data);
+
+public:
+        cTS2ESRemux(int Pid);
+        virtual ~cTS2ESRemux();
+};
+
+#endif // VDR_STREAMDEV_TS2ESREMUX_H
diff --git a/remux/ts2ps.c b/remux/ts2ps.c
new file mode 100644 (file)
index 0000000..e23fdca
--- /dev/null
@@ -0,0 +1,108 @@
+#include "ts2ps.h"
+
+class cTS2PS {
+        friend void PutPES(uint8_t *Buffer, int Size, void *Data);
+
+private:
+        ipack m_Ipack;
+        uint8_t *m_ResultBuffer;
+        int *m_ResultCount;
+
+public:
+        cTS2PS(uint8_t *ResultBuffer, int *ResultCount, uint8_t AudioCid = 0x00,
+                        bool PS = false);
+        ~cTS2PS();
+
+        void PutTSPacket(const uint8_t *Buffer);
+};
+
+void PutPES(uint8_t *Buffer, int Size, void *Data) {
+        cTS2PS *This = (cTS2PS*)Data;
+        if (Size <= 0 || !Buffer || !This ) {
+                esyslog("ERROR: negative size or null pointers");
+                return;
+        }
+        if (*This->m_ResultCount + Size > RESULTBUFFERSIZE) {
+                esyslog("ERROR: result buffer overflow (%d + %d > %d)",
+                                *This->m_ResultCount, Size, RESULTBUFFERSIZE);
+                Size = RESULTBUFFERSIZE - *This->m_ResultCount;
+        }
+        memcpy(This->m_ResultBuffer + *This->m_ResultCount, Buffer, Size);
+        *This->m_ResultCount += Size;
+}
+
+cTS2PS::cTS2PS(uint8_t *ResultBuffer, int *ResultCount, uint8_t AudioCid,
+                bool PS) {
+        m_ResultBuffer = ResultBuffer;
+        m_ResultCount = ResultCount;
+
+        init_ipack(&m_Ipack, IPACKS, PutPES, PS);
+        m_Ipack.cid = AudioCid;
+        m_Ipack.data = (void*)this;
+}
+
+cTS2PS::~cTS2PS() {
+}
+
+void cTS2PS::PutTSPacket(const uint8_t *Buffer) {
+  if (!Buffer)
+     return;
+
+  if (Buffer[1] & 0x80) { // ts error
+                // TODO
+        }
+
+  if (Buffer[1] & 0x40) { // payload start
+                if (m_Ipack.plength == MMAX_PLENGTH - 6 && m_Ipack.found > 6) {
+            m_Ipack.plength = m_Ipack.found - 6;
+      m_Ipack.found = 0;
+      send_ipack(&m_Ipack);
+      reset_ipack(&m_Ipack);
+    }
+  }
+
+        uint8_t off = 0;
+
+  if (Buffer[3] & 0x20) {  // adaptation field?
+                off = Buffer[4] + 1;
+    if (off + 4 > TS_SIZE - 1)
+      return;
+  }
+
+  instant_repack((uint8_t*)(Buffer + 4 + off), TS_SIZE - 4 - off, &m_Ipack);
+}
+
+cTS2PSRemux::cTS2PSRemux(int VPid, int APid1, int APid2, int DPid1,
+                int DPid2, bool PS) {
+        m_VPid  = VPid;
+        m_APid1 = APid1;
+        m_APid2 = APid2;
+        m_DPid1 = DPid1;
+        m_DPid2 = DPid2;
+  m_VRemux  =         new cTS2PS(m_ResultBuffer, &m_ResultCount, 0x00, PS);
+  m_ARemux1 =         new cTS2PS(m_ResultBuffer, &m_ResultCount, 0xC0, PS);
+  m_ARemux2 = APid2 ? new cTS2PS(m_ResultBuffer, &m_ResultCount, 0xC1, PS)
+                          : NULL;
+  m_DRemux1 = DPid1 ? new cTS2PS(m_ResultBuffer, &m_ResultCount, 0x00, PS)
+                          : NULL;
+  //XXX don't yet know how to tell apart primary and secondary DD data...
+  m_DRemux2 = /*XXX m_DPid2 ? new cTS2PS(m_ResultBuffer, &m_ResultCount,
+                        0x00, PS) : XXX*/ NULL;
+}
+
+cTS2PSRemux::~cTS2PSRemux() {
+        if (m_DRemux2) delete m_DRemux2;
+        if (m_DRemux1) delete m_DRemux1;
+        if (m_ARemux2) delete m_ARemux2;
+        delete m_ARemux1;
+        delete m_VRemux;
+}
+
+void cTS2PSRemux::PutTSPacket(int Pid, const uint8_t *Data) {
+        if      (Pid == m_VPid)               m_VRemux->PutTSPacket(Data);
+        else if (Pid == m_APid1)              m_ARemux1->PutTSPacket(Data);
+        else if (Pid == m_APid2 && m_ARemux2) m_ARemux2->PutTSPacket(Data);
+        else if (Pid == m_DPid1 && m_DRemux1) m_DRemux1->PutTSPacket(Data);
+        else if (Pid == m_DPid2 && m_DRemux2) m_DRemux2->PutTSPacket(Data);
+}
+
diff --git a/remux/ts2ps.h b/remux/ts2ps.h
new file mode 100644 (file)
index 0000000..5760f09
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef VDR_STREAMDEV_TS2PESREMUX_H
+#define VDR_STREAMDEV_TS2PESREMUX_H
+
+#include "tsremux.h"
+
+class cTS2PS;
+
+class cTS2PSRemux: public cTSRemux {
+private:
+        int m_VPid, m_APid1, m_APid2, m_DPid1, m_DPid2;
+        cTS2PS *m_VRemux, *m_ARemux1, *m_ARemux2, *m_DRemux1, *m_DRemux2;
+
+protected:
+        virtual void PutTSPacket(int Pid, const uint8_t *Data);
+
+public:
+        cTS2PSRemux(int VPid, int APid1, int APid2, int DPid1, int DPid2,
+                        bool PS = false);
+        virtual ~cTS2PSRemux();
+};
+
+#endif // VDR_STREAMDEV_TS2PESREMUX_H
diff --git a/remux/tsremux.c b/remux/tsremux.c
new file mode 100644 (file)
index 0000000..895a435
--- /dev/null
@@ -0,0 +1,209 @@
+#include "tsremux.h"
+
+// from VDR's remux.c
+#define MAXNONUSEFULDATA (10*1024*1024)
+#define SC_PICTURE 0x00  // "picture header"
+#define VIDEO_STREAM_S   0xE0
+
+cTSRemux::cTSRemux(bool Sync) {
+        memset(m_PROTECTION1, 0x20, PROTECTIONSIZE);
+        m_ResultCount = 0;
+        m_ResultDelivered = 0;
+        m_Synced = false;
+        m_Skipped = 0;
+        m_Sync = Sync;
+}
+
+cTSRemux::~cTSRemux(void) {
+}
+
+uchar *cTSRemux::Process(const uchar *Data, int &Count, int &Result) {
+  // Remove any previously delivered data from the result buffer:
+  if (m_ResultDelivered) {
+    if (m_ResultDelivered < m_ResultCount)
+      memmove(m_ResultBuffer, m_ResultBuffer + m_ResultDelivered, m_ResultCount
+                                        - m_ResultDelivered);
+    m_ResultCount -= m_ResultDelivered;
+    m_ResultDelivered = 0;
+        }
+
+  int used = 0;
+
+        // Make sure we are looking at a TS packet:
+  while (Count > TS_SIZE) {
+                if (Data[0] == 0x47 && Data[TS_SIZE] == 0x47)
+                        break;
+    Data++;
+    Count--;
+    used++;
+  }
+  if (used)
+    esyslog("ERROR: skipped %d byte to sync on TS packet", used);
+
+        // Convert incoming TS data
+  for (int i = 0; i < Count; i += TS_SIZE) {
+    if (Count - i < TS_SIZE)
+      break;
+    if (Data[i] != 0x47)
+      break;
+    int pid = get_pid((uint8_t*)(Data + i + 1));
+    if (Data[i + 3] & 0x10) // got payload
+                        PutTSPacket(pid, Data + i);
+    /*if      (pid == m_VPid)               m_VRemux->ConvertTSPacket(Data + i);
+         else if (pid == m_APid1)              m_ARemux1->ConvertTSPacket(Data + i);
+         else if (pid == m_APid2 && m_ARemux2) m_ARemux2->ConvertTSPacket(Data + i);
+         else if (pid == m_DPid1 && m_DRemux1) m_DRemux1->ConvertTSPacket(Data + i);
+         else if (pid == m_DPid2 && m_DRemux2) m_DRemux2->ConvertTSPacket(Data + i);*/
+    used += TS_SIZE;
+    if (m_ResultCount > (int)sizeof(m_ResultBuffer) / 2)
+      break;
+
+#if 0
+    if (memcmp(m_PROTECTION1, m_PROTECTION1+(PROTECTIONSIZE/2), PROTECTIONSIZE/2)) {
+      int ow_from = -1; // counted from _end_ of protection buffer
+      int ow_to = -1; // counted from _end_ of protection buffer
+      for (int pi=0; pi<PROTECTIONSIZE; pi++) {
+        if (ow_from < 0 && m_PROTECTION1[PROTECTIONSIZE-1-pi] != 0x20) {
+          ow_from = pi;
+        }
+        if (ow_to < 0 && m_PROTECTION1[pi] != 0x20) {
+          ow_to = PROTECTIONSIZE-1-pi;
+        }
+      }
+      fprintf(stderr, "OVERWRITE detected !!! from -%d to -%d\n", ow_from, ow_to);
+      fprintf(stderr, " well, hopefully one signal 11 fewer ;-)\n");
+      memset(m_PROTECTION1, 0x20, PROTECTIONSIZE);
+    }
+#endif
+
+  }
+  Count = used;
+
+        // When we don't need to sync, we don't need to sync :-)
+  if (!m_Sync) {
+    Result = m_ResultDelivered = m_ResultCount;
+    return Result ? m_ResultBuffer : NULL;
+  }
+
+        // Check if we're getting anywhere here:
+
+  if (!m_Synced && m_Skipped >= 0) {
+     if (m_Skipped > MAXNONUSEFULDATA) {
+        esyslog("ERROR: no useful data seen within %d byte of video stream", m_Skipped);
+        m_Skipped = -1;
+        //if (exitOnFailure)
+           //cThread::EmergencyExit(true);
+        }
+     else
+        m_Skipped += Count;
+     }
+
+  // Check for frame borders:
+
+  if (m_ResultCount >= MINVIDEODATA) {
+     for (int i = 0; i < m_ResultCount; i++) {
+         if (m_ResultBuffer[i] == 0 && m_ResultBuffer[i + 1] == 0 && m_ResultBuffer[i + 2] == 1) {
+            switch (m_ResultBuffer[i + 3]) {
+              case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+                   {
+                     uchar pt = NO_PICTURE;
+                     int l = ScanVideoPacket(m_ResultBuffer, m_ResultCount, i, pt);
+                     if (l < 0)
+                        return NULL; // no useful data found, wait for more
+                     if (pt != NO_PICTURE) {
+                        if (pt < I_FRAME || B_FRAME < pt)
+                           esyslog("ERROR: unknown picture type '%d'", pt);
+                        else if (!m_Synced) {
+                           if (pt == I_FRAME) {
+                              m_ResultDelivered = i; // will drop everything before this position
+                              SetBrokenLink(m_ResultBuffer + i, l);
+                              m_Synced = true;
+                              }
+                           else {
+                              m_ResultDelivered = i + l; // will drop everything before and including this packet
+                              return NULL;
+                              }
+                           }
+                        }
+                     if (m_Synced) {
+                        Result = l;
+                        uchar *p = m_ResultBuffer + m_ResultDelivered;
+                        m_ResultDelivered += l;
+                        return p;
+                        }
+                     else {
+                        m_ResultDelivered = i + l; // will drop everything before and including this packet
+                        return NULL;
+                        }
+                   }
+                   break;
+              case PRIVATE_STREAM1:
+              case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+                   {
+                     int l = GetPacketLength(m_ResultBuffer, m_ResultCount, i);
+                     if (l < 0)
+                        return NULL; // no useful data found, wait for more
+
+                     /* This shouldn't be happening - why does it for some channels? */
+                     if ( l > m_ResultCount )
+                         return NULL;
+                     if (m_Synced) {
+                        Result = l;
+                        uchar *p = m_ResultBuffer + m_ResultDelivered;
+                        m_ResultDelivered += l;
+                        return p;
+                        }
+                     else {
+                        m_ResultDelivered = i + l; // will drop everything before and including this packet
+                        return NULL;
+                        }
+                   }
+                   break;
+              }
+            }
+         }
+     }
+  return NULL; // no useful data found, wait for more
+}
+
+int cTSRemux::ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &PictureType) {
+  // Scans the video packet starting at Offset and returns its length.
+  // If the return value is -1 the packet was not completely in the buffer.
+
+  int Length = GetPacketLength(Data, Count, Offset);
+  if (Length > 0 && Offset + Length <= Count) {
+     int i = Offset + 8; // the minimum length of the video packet header
+     i += Data[i] + 1;   // possible additional header bytes
+     for (; i < Offset + Length; i++) {
+         if (Data[i] == 0 && Data[i + 1] == 0 && Data[i + 2] == 1) {
+            switch (Data[i + 3]) {
+              case SC_PICTURE: PictureType = (Data[i + 5] >> 3) & 0x07;
+                               return Length;
+              }
+            }
+         }
+     PictureType = NO_PICTURE;
+     return Length;
+     }
+  return -1;
+}
+
+int cTSRemux::GetPacketLength(const uchar *Data, int Count, int Offset) {
+  // Returns the entire length of the packet starting at offset, or -1 in case of error.
+  return (Offset + 5 < Count) ? (Data[Offset + 4] << 8) + Data[Offset + 5] + 6 : -1;
+}
+
+void cTSRemux::SetBrokenLink(uchar *Data, int Length) {
+  if (Length > 9 && Data[0] == 0 && Data[1] == 0 && Data[2] == 1 && (Data[3] & VIDEO_STREAM_S) == VIDEO_STREAM_S) {
+     for (int i = Data[8] + 9; i < Length - 7; i++) { // +9 to skip video packet header
+         if (Data[i] == 0 && Data[i + 1] == 0 && Data[i + 2] == 1 && Data[i + 3] == 0xB8) {
+            if (!(Data[i + 7] & 0x40)) // set flag only if GOP is not closed
+               Data[i + 7] |= 0x20;
+            return;
+            }
+         }
+     dsyslog("SetBrokenLink: no GOP header found in video packet");
+     }
+  else
+     dsyslog("SetBrokenLink: no video packet in frame");
+}
diff --git a/remux/tsremux.h b/remux/tsremux.h
new file mode 100644 (file)
index 0000000..2a28a35
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef VDR_STREAMDEV_TSREMUX_H
+#define VDR_STREAMDEV_TSREMUX_H
+
+#include "transform.h"
+#include <vdr/remux.h>
+
+#define IPACKS 2048
+
+#define PROTECTIONSIZE 32768
+
+#ifndef RESULTBUFFERSIZE
+#define RESULTBUFFERSIZE KILOBYTE(256)
+#endif
+#ifndef MINVIDEODATA
+#define MINVIDEODATA (16*1024)
+#endif
+
+class cTSRemux {
+protected:
+  uchar m_PROTECTION1[PROTECTIONSIZE]; // something sometimes overwrites vtbl without this buffer
+  uchar m_ResultBuffer[RESULTBUFFERSIZE];
+        int m_ResultCount;
+        int m_ResultDelivered;
+        int m_Synced;
+        int m_Skipped;
+        int m_Sync;
+
+  int GetPacketLength(const uchar *Data, int Count, int Offset);
+  int ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &PictureType);
+
+        virtual void PutTSPacket(int Pid, const uint8_t *Data) = 0;
+
+public:
+        cTSRemux(bool Sync = true);
+        virtual ~cTSRemux();
+        
+        virtual uchar *Process(const uchar *Data, int &Count, int &Result);
+
+        static void SetBrokenLink(uchar *Data, int Length);
+};
+
+#endif // VDR_STREAMDEV_TSREMUX_H
diff --git a/ringbuffer.c b/ringbuffer.c
new file mode 100644 (file)
index 0000000..abe7d7d
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "ringbuffer.h"
+
+Ringbuffer::Ringbuffer()
+{
+  capacity = 0;
+  content = 0;
+  buffer = NULL;
+  start = NULL;
+  end = NULL;
+}
+
+Ringbuffer::~Ringbuffer()
+{
+  free(buffer);
+  capacity = 0;
+  content = 0;
+  buffer = NULL;
+  start = NULL;
+  end = NULL;
+}
+
+int Ringbuffer::init(size_t size)
+{
+  capacity = size;
+  buffer = (UCHAR*)malloc(capacity);
+  if (!buffer) return 0;
+  start = buffer;
+  end = buffer;
+  return 1;
+}
+
+int Ringbuffer::put(UCHAR* from, size_t amount)
+{
+  if (amount > capacity) return 0;
+
+  if ((end + amount) <= (buffer + capacity))
+  {
+    memcpy(end, from, amount);
+    end += amount;
+    content += amount;
+
+    if (end == (buffer + capacity)) end = buffer;
+    if (content >= capacity)
+    {
+      start = end;
+      content = capacity;
+    }
+    return 1;
+  }
+  else
+  {
+    size_t firstAmount = buffer + capacity - end;
+    return (put(from, firstAmount) && put(from + firstAmount, amount - firstAmount));
+  }
+}
+
+int Ringbuffer::get(UCHAR* to, size_t amount)
+{
+  if (amount > content) return get(to, content);
+
+  if ((start + amount) <= (buffer + capacity))
+  {
+    memcpy(to, start, amount);
+    start += amount;
+    content -= amount;
+
+    if (start == (buffer + capacity)) start = buffer;
+    return amount;
+  }
+  else
+  {
+    size_t firstAmount = buffer + capacity - start;
+    return (get(to, firstAmount) + get(to + firstAmount, amount - firstAmount));
+  }
+}
+
+int Ringbuffer::getContent()
+{
+  return content;
+}
diff --git a/ringbuffer.h b/ringbuffer.h
new file mode 100644 (file)
index 0000000..568a286
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef RINGBUFFER_H
+#define RINGBUFFER_H
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "defines.h"
+
+class Ringbuffer
+{
+  public:
+    Ringbuffer();
+    ~Ringbuffer();
+    int init(size_t size);
+    int put(UCHAR* from, size_t amount);
+    int get(UCHAR* to, size_t amount);
+    int getContent();
+
+  private:
+    UCHAR* buffer;
+    UCHAR* start;
+    UCHAR* end;
+    size_t capacity;
+    size_t content;
+};
+
+#endif
diff --git a/tcp.c b/tcp.c
new file mode 100644 (file)
index 0000000..b1d09c3
--- /dev/null
+++ b/tcp.c
@@ -0,0 +1,412 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+    Copyright 2003-2004 University Of Bradford
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "tcp.h"
+
+TCP::TCP(int tsocket)
+{
+  sock = -1;
+  connected = 0;
+  readTimeoutEnabled = 1;
+
+  if (tsocket)
+  {
+    sock = tsocket;
+    connected = 1;
+  }
+}
+
+TCP::~TCP()
+{
+  if (connected) cleanup();
+}
+
+void TCP::cleanup()
+{
+  close(sock);
+  sock = -1;
+  connected = 0;
+  printf("TCP has closed socket\n");
+}
+
+
+void TCP::disableReadTimeout()
+{
+  readTimeoutEnabled = 0;
+}
+
+int TCP::connectTo(char* host, unsigned short port)
+{
+  sock = socket(PF_INET, SOCK_STREAM, 0);
+  if (sock == -1) return 0;
+
+  struct sockaddr_in dest_addr;
+  dest_addr.sin_family = AF_INET;
+  dest_addr.sin_port = htons(port);
+
+  if (!inet_aton(host, &dest_addr.sin_addr))
+  {
+    cleanup();
+    return 0;
+  }
+
+  memset(&(dest_addr.sin_zero), '\0', 8);
+
+  int success = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
+  if (success == -1)
+  {
+    cleanup();
+    return 0;
+  }
+
+  connected = 1;
+  return 1;
+}
+
+void TCP::setNonBlocking()
+{
+  int oldflags = fcntl(sock, F_GETFL, 0);
+  oldflags |= O_NONBLOCK;
+  fcntl(sock, F_SETFL, oldflags);
+}
+
+int TCP::setSoKeepTime(int timeOut)
+{
+  int option;
+  int s1, s2, s3, s4;
+
+  option = 1;
+  s1 = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof(option));
+  printf("SO_KEEPALIVE = %i\n", s1);
+
+  option = timeOut;
+  s2 = setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &option, sizeof(option));
+  printf("TCP_KEEPIDLE = %i\n", s2);
+
+  s3 = setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &option, sizeof(option));
+  printf("TCP_KEEPINTVL = %i\n", s3);
+
+  option = 2;
+  s4 = setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &option, sizeof(option));
+  printf("TCP_KEEPCNT = %i\n", s4);
+
+  if (s1 || s2 || s3 || s4) return 0;
+  return 1;
+}
+
+void TCP::assignSocket(int tsocket)
+{
+  sock = tsocket;
+  connected = 1;
+}
+
+int TCP::isConnected()
+{
+  return connected;
+}
+
+UCHAR* TCP::receivePacket()
+{
+  if (!connected) return NULL;
+
+  int packetLength;
+  int success;
+
+  success = readData((UCHAR*)&packetLength, sizeof(int));
+  if (!success)
+  {
+    cleanup();
+    return NULL;
+  }
+
+  packetLength = ntohl(packetLength);
+
+  if (packetLength > 200000) return NULL;
+  UCHAR* buffer = (UCHAR*) malloc(packetLength);
+
+  success = readData(buffer, packetLength);
+  if (!success)
+  {
+    cleanup();
+    free(buffer);
+    return NULL;
+  }
+
+  dump((unsigned char*)buffer, packetLength);
+
+  dataLength = packetLength;
+  return buffer;
+}
+
+int TCP::getDataLength()
+{
+  return dataLength;
+}
+
+int TCP::readData(UCHAR* buffer, int totalBytes)
+{
+  if (!connected) return 0;
+
+  int bytesRead = 0;
+  int thisRead;
+  int readTries = 0;
+  int success;
+  fd_set readSet;
+  struct timeval timeout;
+  struct timeval* passToSelect;
+
+  if (readTimeoutEnabled) passToSelect = &timeout;
+  else passToSelect = NULL;
+
+  while(1)
+  {
+    FD_ZERO(&readSet);
+    FD_SET(sock, &readSet);
+    timeout.tv_sec = 10;
+    timeout.tv_usec = 0;
+    success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
+    if (success < 1)
+    {
+      cleanup();
+      printf("TCP: error or timeout\n");
+      return 0;  // error, or timeout
+    }
+
+    thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
+    if (!thisRead)
+    {
+      // if read returns 0 then connection is closed
+      // in non-blocking mode if read is called with no data available, it returns -1
+      // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
+      cleanup();
+      return 0;
+    }
+    bytesRead += thisRead;
+
+    printf("Bytes read now: %u\n", bytesRead);
+    if (bytesRead == totalBytes)
+    {
+      return 1;
+    }
+    else
+    {
+      if (++readTries == 100)
+      {
+        cleanup();
+        printf("too many reads\n");
+        return 0;
+      }
+    }
+  }
+}
+
+int TCP::sendPacket(UCHAR* buf, size_t count)
+{
+  if (!connected) return 0;
+
+  unsigned int bytesWritten = 0;
+  int thisWrite;
+  int writeTries = 0;
+  int success;
+  fd_set writeSet;
+  struct timeval timeout;
+
+  while(1)
+  {
+    FD_ZERO(&writeSet);
+    FD_SET(sock, &writeSet);
+    timeout.tv_sec = 10;
+    timeout.tv_usec = 0;
+    success = select(sock + 1, NULL, &writeSet, NULL, &timeout);
+    if (success < 1)
+    {
+      cleanup();
+      printf("TCP: error or timeout\n");
+      return 0;  // error, or timeout
+    }
+
+    thisWrite = write(sock, &buf[bytesWritten], count - bytesWritten);
+    if (!thisWrite)
+    {
+      // if write returns 0 then connection is closed ?
+      // in non-blocking mode if read is called with no data available, it returns -1
+      // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
+      cleanup();
+      printf("Detected connection closed\n");
+      return 0;
+    }
+    bytesWritten += thisWrite;
+
+    printf("Bytes written now: %u\n", bytesWritten);
+    if (bytesWritten == count)
+    {
+      return 1;
+    }
+    else
+    {
+      if (++writeTries == 100)
+      {
+        cleanup();
+        printf("too many writes\n");
+        return 0;
+      }
+    }
+  }
+}
+
+
+
+
+void TCP::dump(unsigned char* data, USHORT size)
+{
+  printf("Size = %u\n", size);
+
+  USHORT c = 0;
+  while(c < size)
+  {
+    if ((size - c) > 15)
+    {
+      printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X %02X  %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
+        data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
+        data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
+        dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
+        dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]), dcc(data[c+14]), dcc(data[c+15]));
+      c += 16;
+    }
+    else
+    {
+      switch (size - c)
+      {
+        case 15:
+          printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X     %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
+            data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
+            data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
+            dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
+            dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]), dcc(data[c+14]));
+          c += 15;
+          break;
+        case 14:
+          printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X        %c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
+            data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
+            data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
+            dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
+            dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
+          c += 14;
+          break;
+        case 13:
+          printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X %02X  %02X           %c%c%c%c%c%c%c%c%c%c%c%c%c\n",
+            data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
+            data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
+            dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
+            dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
+          c += 13;
+          break;
+        case 12:
+          printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X %02X               %c%c%c%c%c%c%c%c%c%c%c%c\n",
+            data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
+            data[c+8], data[c+9], data[c+10], data[c+11],
+            dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
+            dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
+          c += 12;
+          break;
+        case 11:
+          printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X                  %c%c%c%c%c%c%c%c%c%c%c\n",
+            data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
+            data[c+8], data[c+9], data[c+10],
+            dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
+            dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
+          c += 11;
+          break;
+        case 10:
+          printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X                     %c%c%c%c%c%c%c%c%c%c\n",
+            data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
+            data[c+8], data[c+9],
+            dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
+            dcc(data[c+8]), dcc(data[c+9]));
+          c += 10;
+          break;
+        case 9:
+          printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X                        %c%c%c%c%c%c%c%c%c\n",
+            data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
+            data[c+8],
+            dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
+            dcc(data[c+8]));
+          c += 9;
+          break;
+        case 8:
+          printf(" %02X %02X %02X %02X  %02X %02X %02X %02X                            %c%c%c%c%c%c%c%c\n",
+            data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
+            dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]));
+          c += 8;
+          break;
+        case 7:
+          printf(" %02X %02X %02X %02X  %02X %02X %02X                               %c%c%c%c%c%c%c\n",
+            data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
+            dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]));
+          c += 7;
+          break;
+        case 6:
+          printf(" %02X %02X %02X %02X  %02X %02X                                  %c%c%c%c%c%c\n",
+            data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
+            dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
+          c += 6;
+          break;
+        case 5:
+          printf(" %02X %02X %02X %02X  %02X                                     %c%c%c%c%c\n",
+            data[c], data[c+1], data[c+2], data[c+3], data[c+4],
+            dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
+          c += 5;
+          break;
+        case 4:
+          printf(" %02X %02X %02X %02X                                         %c%c%c%c\n",
+            data[c], data[c+1], data[c+2], data[c+3],
+            dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
+          c += 4;
+          break;
+        case 3:
+          printf(" %02X %02X %02X                                            %c%c%c\n",
+            data[c], data[c+1], data[c+2],
+            dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
+          c += 3;
+          break;
+        case 2:
+          printf(" %02X %02X                                               %c%c\n",
+            data[c], data[c+1],
+            dcc(data[c]), dcc(data[c+1]));
+          c += 2;
+          break;
+        case 1:
+          printf(" %02X                                                  %c\n",
+            data[c],
+            dcc(data[c]));
+          c += 1;
+          break;
+      }
+    }
+  }
+}
+
+unsigned char TCP::dcc(UCHAR c)
+{
+  if (isspace(c)) return ' ';
+  if (isprint(c)) return c;
+  return '.';
+}
diff --git a/tcp.h b/tcp.h
new file mode 100644 (file)
index 0000000..f736707
--- /dev/null
+++ b/tcp.h
@@ -0,0 +1,78 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+    Copyright 2003-2004 University Of Bradford
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef TCP_H
+#define TCP_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+// For TCP_KEEPIDLE and co
+#include <netinet/tcp.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <ctype.h>
+
+
+typedef unsigned char UCHAR;
+typedef unsigned short USHORT;
+
+class TCP
+{
+  public:
+    // Creation
+    TCP(int tsocket);
+    ~TCP();
+    void assignSocket(int tsocket);
+
+    // Setup
+    void disableReadTimeout();
+    void setNonBlocking();
+    int setSoKeepTime(int timeOut);
+
+    int connectTo(char *host, unsigned short port);
+    int sendPacket(UCHAR*, size_t size);
+    UCHAR* receivePacket();
+
+    // Get methods
+    int isConnected();
+    int getDataLength();
+
+    static void dump(unsigned char* data, USHORT size);
+    static UCHAR dcc(UCHAR c);
+
+  private:
+    int sock;
+    int connected;
+    int readTimeoutEnabled;
+    int dataLength;
+
+    void cleanup();
+    int readData(UCHAR* buffer, int totalBytes);
+};
+
+#endif
diff --git a/transceiver.c b/transceiver.c
new file mode 100644 (file)
index 0000000..8a87fd0
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+     Edited for VOMP by Chris Tallon
+     Edits Copyright 2004-2005 Chris Tallon
+*/
+
+/*
+ *   MediaMVP Server
+ *
+ *   (C) 2003 Dominic Morris
+ *
+ *   $Id$
+ *   $Date$
+ *
+ *   Transceiver stuff - blatantly stolen from streamdev then changed
+ *   a bit..
+ */
+
+
+
+
+
+#include "transceiver.h"
+#include "ts2ps.h"
+#include "ts2es.h"
+//#include "setup.h"
+
+#include <vdr/ringbuffer.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+
+
+#define VIDEOBUFSIZE MEGABYTE(1)
+
+/* Disable logging if BUFCOUNT buffer overflows occur within BUFOVERTIME
+   milliseconds. Enable logging again if there is no error within BUFOVERTIME
+   milliseconds. */
+#define BUFOVERTIME  5000
+#define BUFOVERCOUNT 100
+
+cMediamvpTransceiver::cMediamvpTransceiver(const cChannel *Channel, int Priority, int Socket, cDevice *Device) :
+                cReceiver(Channel->Ca(), Priority, 7, Channel->Vpid(), Channel->Ppid(),
+                                Channel->Apid1(), Channel->Apid2(), Channel->Dpid1(), Channel->Dpid2(),
+                                Channel->Tpid()) {
+        m_Active = false;
+        m_Socket = Socket;
+        m_Remux = NULL;
+        m_Device = Device;
+
+        m_RingBuffer = new cRingBufferLinear(VIDEOBUFSIZE, TS_SIZE * 2, true);
+//        m_RingBuffer = new cRingBufferLinear(VIDEOBUFSIZE, TS_SIZE * 20, true);
+
+    /* Select the correct Muxing depending on whether it's video or not */
+    if ( Channel->Vpid() == 0 || Channel->Vpid() == 1 || Channel->Vpid() == 0x1FFF ) {
+        m_Remux = new cTS2ESRemux(Channel->Apid1());
+    } else {
+                m_Remux = new cTS2PSRemux(Channel->Vpid(), Channel->Apid1(), 0, 0, 0, 0);
+    }
+    printf("Created transceiver at %p, remux @%p ringbuffer %p\n",this,m_Remux,m_RingBuffer);
+
+    /* Suggested by Peter Wagner to assist single DVB card systems */
+#ifdef SINGLE_DEVICE
+        m_Device->SwitchChannel(Channel, true);
+#else
+        m_Device->SwitchChannel(Channel, false);
+#endif
+        Attach();
+
+
+        // CJT
+        rb.init(1000000);
+        pthread_mutex_init(&ringLock, NULL);
+
+}
+
+cMediamvpTransceiver::~cMediamvpTransceiver(void)
+{
+    printf("Deleting transceiver at %p, remux @%p ringbuffer %p\n",this,m_Remux,m_RingBuffer);
+
+        Detach();
+        if (m_Remux)
+        delete m_Remux;
+    m_Remux = NULL;
+    if ( m_RingBuffer)
+        delete m_RingBuffer;
+    m_RingBuffer = NULL;
+}
+
+void cMediamvpTransceiver::Activate(bool On)
+{
+        if (On)
+                Start();
+        else if (m_Active)
+                Stop();
+}
+
+void cMediamvpTransceiver::Stop(void)
+{
+        if (m_Active) {
+                m_Active = false;
+                usleep(50000);
+                Cancel(0);
+        }
+}
+
+void cMediamvpTransceiver::Receive(uchar *Data, int Length)
+{
+        static time_t firsterr = 0;
+        static int errcnt = 0;
+        static bool showerr = true;
+
+        if (m_Active) {
+                int p = m_RingBuffer->Put(Data, Length);
+                if (p != Length) {
+                        ++errcnt;
+                        if (showerr) {
+                                if (firsterr == 0)
+                                        firsterr = time_ms();
+                                else if (firsterr + BUFOVERTIME > time_ms() && errcnt > BUFOVERCOUNT) {
+                                        esyslog("ERROR: too many buffer overflows, logging stopped");
+                                        showerr = false;
+                                        firsterr = time_ms();
+                                }
+                        } else if (firsterr + BUFOVERTIME < time_ms()) {
+                                showerr = true;
+                                firsterr = 0;
+                                errcnt = 0;
+                        }
+
+                        if (showerr)
+                                esyslog("ERROR: ring buffer overflow (%d bytes dropped)", Length - p);
+                        else
+                                firsterr = time_ms();
+                }
+        }
+}
+
+void cMediamvpTransceiver::Action(void)
+{
+        int max = 0;
+
+
+        printf("Mediamvp: Transceiver thread started (pid=%d)", getpid());
+
+
+        m_Active = true;
+
+        while (m_Active) {
+                int recvd;
+                const uchar *block = m_RingBuffer->Get(recvd);
+
+                if (block && recvd > 0) {
+                        const uchar *sendBlock;
+                        int bytes = 0;
+                        int taken = recvd;
+
+            sendBlock = m_Remux->Process(block, taken, bytes);
+
+                        m_RingBuffer->Del(taken);
+
+                        if (bytes > max)
+                                max = bytes;
+      // CJT
+
+       //     write(m_Socket,sendBlock,bytes);
+      //      printf("Written %i bytes\n", bytes);
+
+
+      pthread_mutex_lock(&ringLock);
+      rb.put((unsigned char*)sendBlock, bytes);
+      pthread_mutex_unlock(&ringLock);
+//printf("Put %i into buffer\n", bytes);
+
+
+                } else
+                        usleep(1);
+        }
+
+
+        printf("Mediamvp: Transceiver thread ended");
+}
+
+unsigned long cMediamvpTransceiver::getBlock(unsigned char* buffer, unsigned long amount)
+{
+  pthread_mutex_lock(&ringLock);
+
+  while ((unsigned long)rb.getContent() < amount)
+  {
+    pthread_mutex_unlock(&ringLock);
+    usleep(500000);
+    pthread_mutex_lock(&ringLock);
+  }
+
+  unsigned long amountReceived = rb.get(buffer, amount);
+  pthread_mutex_unlock(&ringLock);
+  return amountReceived;
+}
diff --git a/transceiver.h b/transceiver.h
new file mode 100644 (file)
index 0000000..e9b854c
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+     Edited for VOMP by Chris Tallon
+     Edits Copyright 2004-2005 Chris Tallon
+*/
+
+/*
+ *   MediaMVP Plugin
+ *
+ *   (C) 2003 Dominic Morris
+ *
+ *   $Id$
+ *   $Date$
+ *
+ *
+ *   Transceiver stuff, stolen from streamdev again...
+ */
+
+#ifndef VDR_MEDIAMVP_TRANSCEIVER_H
+#define VDR_MEDIAMVP_TRANSCEIVER_H
+
+#include <vdr/receiver.h>
+
+#include <vdr/thread.h>
+#include <vdr/status.h>
+
+class cRingBufferLinear;
+class cRemux;
+class cTSRemux;
+class cServerConnection;
+class cChannel;
+
+
+#include <pthread.h>
+#include "ringbuffer.h"
+
+class cMediamvpTransceiver: public cReceiver, public cThread {
+//    friend class cMediamvpVdrURL;
+private:
+        cDevice *m_Device;
+        cRingBufferLinear *m_RingBuffer;
+        cTSRemux *m_Remux;
+    int       m_Socket;
+
+        bool m_Active;
+
+        // CJT
+        Ringbuffer rb;
+        pthread_mutex_t ringLock;
+
+
+protected:
+        virtual void Receive(uchar *Data, int Length);
+        virtual void Action(void);
+
+public:
+        cMediamvpTransceiver(const cChannel *Channel, int Priority, int Socket, cDevice *Device);
+        virtual ~cMediamvpTransceiver(void);
+
+        bool Attach(void) { return m_Device->AttachReceiver(this); }
+        void Detach(void) { cReceiver::Detach(); }
+
+        void Stop(void);
+
+
+        // CJT
+        unsigned long getBlock(unsigned char* buffer, unsigned long amount);
+        virtual void Activate(bool On);
+
+};
+
+#endif // VDR_MEDIAMVP_TRANSCEIVER_H
diff --git a/udpreplier.c b/udpreplier.c
new file mode 100644 (file)
index 0000000..d6a352f
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "udpreplier.h"
+
+// undeclared function
+void UDPReplierStartThread(void *arg)
+{
+  UDPReplier *m = (UDPReplier *)arg;
+  m->run2();
+}
+
+
+UDPReplier::UDPReplier()
+ : ds(3024)
+{
+  runThread = 0;
+  running = 0;
+}
+
+UDPReplier::~UDPReplier()
+{
+  if (running) stop();
+}
+
+int UDPReplier::stop()
+{
+  if (!running) return 0;
+
+  running = 0;
+  pthread_cancel(runThread);
+  pthread_join(runThread, NULL);
+
+  return 1;
+}
+
+int UDPReplier::run()
+{
+  if (running) return 1;
+  running = 1;
+  if (pthread_create(&runThread, NULL, (void*(*)(void*))UDPReplierStartThread, (void *)this) == -1) return 0;
+  printf("UDPReplier run success\n");
+  return 1;
+}
+
+void UDPReplier::run2()
+{
+  // I don't want signals
+  sigset_t sigset;
+  sigfillset(&sigset);
+  pthread_sigmask(SIG_BLOCK, &sigset, NULL);
+
+  int retval;
+  while(1)
+  {
+    retval = ds.waitforMessage(0);
+    if (retval == 1) continue;
+
+    if (!strcmp(ds.getData(), "VOMP CLIENT"))
+      ds.send(ds.getFromIPA(), 3024, "VOMP SERVER", 11);
+  }
+}
diff --git a/udpreplier.h b/udpreplier.h
new file mode 100644 (file)
index 0000000..4d82ba8
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef UDPREPLIER_H
+#define UDPREPLIER_H
+
+#include <stdio.h>
+#include <pthread.h>
+#include <signal.h>
+
+#include "dsock.h"
+
+class UDPReplier
+{
+  public:
+    UDPReplier();
+    ~UDPReplier();
+
+    int run();
+    int stop();
+
+    // not for external use
+    void run2();
+
+  private:
+    pthread_t runThread;
+    int running;
+
+    DatagramSocket ds;
+};
+
+#endif
diff --git a/vompserver.c b/vompserver.c
new file mode 100644 (file)
index 0000000..1845937
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/*
+ * vomp-server.c: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id$
+ */
+
+#include <vdr/plugin.h>
+
+#include "mvpserver.h"
+
+static const char *VERSION        = "0.0.1";
+static const char *DESCRIPTION    = "VDR on MVP plugin by Chris Tallon";
+
+class cPluginVompserver : public cPlugin
+{
+public:
+  cPluginVompserver(void);
+  virtual ~cPluginVompserver();
+  virtual const char *Version(void) { return VERSION; }
+  virtual const char *Description(void) { return DESCRIPTION; }
+  virtual const char *CommandLineHelp(void);
+  virtual bool ProcessArgs(int argc, char *argv[]);
+  virtual bool Initialize(void);
+  virtual bool Start(void);
+  virtual bool SetupParse(const char *Name, const char *Value);
+
+private:
+
+  MVPServer mvpserver;
+};
+
+cPluginVompserver::cPluginVompserver(void)
+{
+  // Initialize any member variables here.
+  // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
+  // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
+}
+
+cPluginVompserver::~cPluginVompserver()
+{
+  // Clean up after yourself!
+
+  mvpserver.stop();
+}
+
+const char *cPluginVompserver::CommandLineHelp(void)
+{
+  // Return a string that describes all known command line options.
+  return NULL;
+}
+
+bool cPluginVompserver::ProcessArgs(int argc, char *argv[])
+{
+  // Implement command line argument processing here if applicable.
+  return true;
+}
+
+bool cPluginVompserver::Initialize(void)
+{
+  // Initialize any background activities the plugin shall perform.
+  printf("VOMP Plugin init\n");
+  return true;
+}
+
+bool cPluginVompserver::Start(void)
+{
+  // Start any background activities the plugin shall perform.
+  printf("VOMP Plugin start\n");
+
+  int success = mvpserver.run();
+  if (success) return true;
+  else return false;
+}
+
+bool cPluginVompserver::SetupParse(const char *Name, const char *Value)
+{
+  // Parse your own setup parameters and store their values.
+  return false;
+}
+
+VDRPLUGINCREATOR(cPluginVompserver); // Don't touch this!