summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSascha Volkenandt <sascha@akv-soft.de>2004-01-02 23:13:00 +0100
committerSascha Volkenandt <sascha@akv-soft.de>2004-01-02 23:13:00 +0100
commit4a775c82c82597c65345b3b1fdad71792ef2e486 (patch)
treed3a5fc2a34e6746f8d7ee51e793ff3645bf3e814
downloadvdr-plugin-osdpip-4a775c82c82597c65345b3b1fdad71792ef2e486.tar.gz
vdr-plugin-osdpip-4a775c82c82597c65345b3b1fdad71792ef2e486.tar.bz2
Release version 0.0.1v0.0.1
- Initial revision.
-rw-r--r--COPYING340
-rw-r--r--HISTORY6
-rw-r--r--Makefile88
-rw-r--r--README57
-rw-r--r--i18n.c22
-rw-r--r--i18n.h8
-rw-r--r--libdvbmpeg/.cvsignore1
-rw-r--r--libdvbmpeg/DVB.hh446
-rw-r--r--libdvbmpeg/Makefile33
-rw-r--r--libdvbmpeg/OSD.h30
-rw-r--r--libdvbmpeg/channel.h58
-rw-r--r--libdvbmpeg/ci.hh167
-rw-r--r--libdvbmpeg/cpptools.cc946
-rw-r--r--libdvbmpeg/cpptools.hh330
-rw-r--r--libdvbmpeg/ctools.c2379
-rw-r--r--libdvbmpeg/ctools.h404
-rw-r--r--libdvbmpeg/devices.hh310
-rw-r--r--libdvbmpeg/osd.hh84
-rw-r--r--libdvbmpeg/remux.c1215
-rw-r--r--libdvbmpeg/remux.h149
-rw-r--r--libdvbmpeg/ringbuffy.c200
-rw-r--r--libdvbmpeg/ringbuffy.h52
-rw-r--r--libdvbmpeg/transform.c2681
-rw-r--r--libdvbmpeg/transform.h250
-rw-r--r--osd.c199
-rw-r--r--osd.h38
-rw-r--r--osdpip.c85
-rw-r--r--receiver.c56
-rw-r--r--receiver.h29
-rw-r--r--remux/ts2es.c87
-rw-r--r--remux/ts2es.h21
-rw-r--r--remux/ts2ps.c104
-rw-r--r--remux/ts2ps.h22
-rw-r--r--remux/tsremux.c185
-rw-r--r--remux/tsremux.h30
35 files changed, 11112 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..5b6e7c6
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/HISTORY b/HISTORY
new file mode 100644
index 0000000..765eee3
--- /dev/null
+++ b/HISTORY
@@ -0,0 +1,6 @@
+VDR Plugin 'osdpip' Revision History
+------------------------------------
+
+2004-01-02: Version 0.0.1
+
+- Initial revision.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..619f239
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,88 @@
+#
+# 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 = osdpip
+
+### The version number of this plugin (taken from the main source file):
+
+VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ print $$6 }' | sed -e 's/[";]//g')
+
+### The C++ compiler and options:
+
+CXX ?= g++
+CXXFLAGS ?= -O2 -Wall -Woverloaded-virtual
+
+### The directory environment:
+
+DVBDIR = ../../../../DVB
+VDRDIR = ../../..
+LIBDIR = ../../lib
+TMPDIR = /tmp
+
+### Allow user defined options to overwrite defaults:
+
+-include $(VDRDIR)/Make.config
+
+### The version number of VDR (taken from VDR's "config.h"):
+
+VDRVERSION = $(shell grep 'define VDRVERSION ' $(VDRDIR)/config.h | awk '{ print $$3 }' | sed -e 's/"//g')
+
+### The name of the distribution archive:
+
+ARCHIVE = $(PLUGIN)-$(VERSION)
+PACKAGE = vdr-$(ARCHIVE)
+
+### Includes and Defines (add further entries here):
+
+INCLUDES += -I$(VDRDIR)/include -I$(DVBDIR)/include -I.
+LIBS = -lmpeg2 -lmpeg2convert
+DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
+
+### The object files (add further files here):
+
+OBJS = $(PLUGIN).o osd.o receiver.o i18n.o \
+ \
+ remux/tsremux.o remux/ts2ps.o remux/ts2es.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 -o $@ $^ $(LIBS)
+ @cp $@ $(LIBDIR)/$@.$(VDRVERSION)
+
+dist: clean
+ @-rm -rf $(TMPDIR)/$(ARCHIVE)
+ @mkdir $(TMPDIR)/$(ARCHIVE)
+ @cp -a * $(TMPDIR)/$(ARCHIVE)
+ @tar czf $(PACKAGE).tgz -C $(TMPDIR) $(ARCHIVE)
+ @-rm -rf $(TMPDIR)/$(ARCHIVE)
+ @echo Distribution package created as $(PACKAGE).tgz
+
+clean:
+ @-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~
+ make -C libdvbmpeg clean
diff --git a/README b/README
new file mode 100644
index 0000000..faaeb3b
--- /dev/null
+++ b/README
@@ -0,0 +1,57 @@
+This is a "plugin" for the Video Disk Recorder (VDR).
+
+Written by: Sascha Volkenandt <sascha@akv-soft.de>
+
+Project's homepage: http://www.magoa.net/linux/index.php?view=osdpip
+
+Latest version available at: http://www.magoa.net/linux/index.php?view=osdpip
+
+See the file COPYING for license information.
+
+
+Requirements:
+
+- libmpeg2 (http://libmpeg2.sourceforge.net) version 0.4.0 (OLDER VERSIONS
+ DON'T WORK)
+
+
+Description:
+
+OSD Picture-in-Picture is a PlugIn that displays the current channel in a
+small box on the screen (default upper right corner). You can switch up and
+down now, watching the progress of the previous channel in the box. Quality is
+not too good yet, and only I-Frames are displayed. You'll need to upgrade your
+VDR to support a 256 color OSD with the provided patching instruction.
+
+
+Installation:
+
+Let's say osdpip's version is 0.0.1 and vdr's version is 1.2.6. If you
+use anything else please exchange the version numbers appropriately (this
+way I don't have to update this section all the times;) ).
+
+cd vdr-1.2.6/PLUGINS/src
+tar xvfz vdr-osdpip-0.0.1.tgz
+ln -s osdpip-0.0.1 osdpip
+cd ../..
+
+Now, you have to call your favourite editor to open osdbase.h and jump to line
+number 16. I don't provide a patch here because some patches already touch that
+area. Well this one's easy, though. Just increase the number of colors in this
+line to 256.
+
+#define MAXNUMCOLORS 256
+
+Now, you have to re-build VDR and Plugins.
+
+make [options, if necessary] vdr
+make [options, if necessary] plugins
+
+
+Controls:
+
+Up/Down Switch Channel up/down
+1-9 Set Box Position
+0 Switch back to PiP channel and exit PiP
+Back Exit PiP without switching back
+
diff --git a/i18n.c b/i18n.c
new file mode 100644
index 0000000..2a9bc5e
--- /dev/null
+++ b/i18n.c
@@ -0,0 +1,22 @@
+#include "i18n.h"
+
+const tI18nPhrase Phrases[] = {
+ { "Picture-in-Picture", // English
+ "Bild-in-Bild", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "", // Suomi
+ "", // Polski
+ "", // Español
+ "", // Ellinika
+ "", // Svenska
+ "", // Romaneste
+ "", // Magyar
+ "" // Catala
+ },
+ { NULL }
+};
diff --git a/i18n.h b/i18n.h
new file mode 100644
index 0000000..a2b2d71
--- /dev/null
+++ b/i18n.h
@@ -0,0 +1,8 @@
+#ifndef VDR_OSDPIP_I18N_H
+#define VDR_OSDPIP_I18N_H
+
+#include <vdr/i18n.h>
+
+extern const tI18nPhrase Phrases[];
+
+#endif // VDR_OSDPIP_I18N_H
diff --git a/libdvbmpeg/.cvsignore b/libdvbmpeg/.cvsignore
new file mode 100644
index 0000000..4671378
--- /dev/null
+++ b/libdvbmpeg/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/libdvbmpeg/DVB.hh b/libdvbmpeg/DVB.hh
new file mode 100644
index 0000000..e713bee
--- /dev/null
+++ b/libdvbmpeg/DVB.hh
@@ -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
index 0000000..a56cb6b
--- /dev/null
+++ b/libdvbmpeg/Makefile
@@ -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
index 0000000..385ac78
--- /dev/null
+++ b/libdvbmpeg/OSD.h
@@ -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
index 0000000..c4f62b4
--- /dev/null
+++ b/libdvbmpeg/channel.h
@@ -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
index 0000000..77e7684
--- /dev/null
+++ b/libdvbmpeg/ci.hh
@@ -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
index 0000000..91808cc
--- /dev/null
+++ b/libdvbmpeg/cpptools.cc
@@ -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
index 0000000..49ea5de
--- /dev/null
+++ b/libdvbmpeg/cpptools.hh
@@ -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
index 0000000..dfd1751
--- /dev/null
+++ b/libdvbmpeg/ctools.c
@@ -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
index 0000000..a7b0271
--- /dev/null
+++ b/libdvbmpeg/ctools.h
@@ -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
index 0000000..02c62cd
--- /dev/null
+++ b/libdvbmpeg/devices.hh
@@ -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
index 0000000..9c6b530
--- /dev/null
+++ b/libdvbmpeg/osd.hh
@@ -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
index 0000000..6f8a44f
--- /dev/null
+++ b/libdvbmpeg/remux.c
@@ -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
index 0000000..76c128b
--- /dev/null
+++ b/libdvbmpeg/remux.h
@@ -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
index 0000000..8451009
--- /dev/null
+++ b/libdvbmpeg/ringbuffy.c
@@ -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
index 0000000..16011d7
--- /dev/null
+++ b/libdvbmpeg/ringbuffy.h
@@ -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
index 0000000..c53f1fb
--- /dev/null
+++ b/libdvbmpeg/transform.c
@@ -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
index 0000000..ad32706
--- /dev/null
+++ b/libdvbmpeg/transform.h
@@ -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/osd.c b/osd.c
new file mode 100644
index 0000000..dd6ec21
--- /dev/null
+++ b/osd.c
@@ -0,0 +1,199 @@
+#include "osd.h"
+#include "receiver.h"
+
+#include <vdr/ringbuffer.h>
+#include <vdr/remux.h>
+
+const uint palette[256] = {
+ 0xff000000, 0xff400000, 0xff800000, 0xffc00000, 0xff002000, 0xff402000,
+ 0xff802000, 0xffc02000, 0xff004000, 0xff404000, 0xff804000, 0xffc04000,
+ 0xff006000, 0xff406000, 0xff806000, 0xffc06000, 0xff008000, 0xff408000,
+ 0xff808000, 0xffc08000, 0xff00a000, 0xff40a000, 0xff80a000, 0xffc0a000,
+ 0xff00c000, 0xff40c000, 0xff80c000, 0xffc0c000, 0xff00e000, 0xff40e000,
+ 0xff80e000, 0xffc0e000, 0xff000020, 0xff400020, 0xff800020, 0xffc00020,
+ 0xff002020, 0xff402020, 0xff802020, 0xffc02020, 0xff004020, 0xff404020,
+ 0xff804020, 0xffc04020, 0xff006020, 0xff406020, 0xff806020, 0xffc06020,
+ 0xff008020, 0xff408020, 0xff808020, 0xffc08020, 0xff00a020, 0xff40a020,
+ 0xff80a020, 0xffc0a020, 0xff00c020, 0xff40c020, 0xff80c020, 0xffc0c020,
+ 0xff00e020, 0xff40e020, 0xff80e020, 0xffc0e020, 0xff000040, 0xff400040,
+ 0xff800040, 0xffc00040, 0xff002040, 0xff402040, 0xff802040, 0xffc02040,
+ 0xff004040, 0xff404040, 0xff804040, 0xffc04040, 0xff006040, 0xff406040,
+ 0xff806040, 0xffc06040, 0xff008040, 0xff408040, 0xff808040, 0xffc08040,
+ 0xff00a040, 0xff40a040, 0xff80a040, 0xffc0a040, 0xff00c040, 0xff40c040,
+ 0xff80c040, 0xffc0c040, 0xff00e040, 0xff40e040, 0xff80e040, 0xffc0e040,
+ 0xff000060, 0xff400060, 0xff800060, 0xffc00060, 0xff002060, 0xff402060,
+ 0xff802060, 0xffc02060, 0xff004060, 0xff404060, 0xff804060, 0xffc04060,
+ 0xff006060, 0xff406060, 0xff806060, 0xffc06060, 0xff008060, 0xff408060,
+ 0xff808060, 0xffc08060, 0xff00a060, 0xff40a060, 0xff80a060, 0xffc0a060,
+ 0xff00c060, 0xff40c060, 0xff80c060, 0xffc0c060, 0xff00e060, 0xff40e060,
+ 0xff80e060, 0xffc0e060, 0xff000080, 0xff400080, 0xff800080, 0xffc00080,
+ 0xff002080, 0xff402080, 0xff802080, 0xffc02080, 0xff004080, 0xff404080,
+ 0xff804080, 0xffc04080, 0xff006080, 0xff406080, 0xff806080, 0xffc06080,
+ 0xff008080, 0xff408080, 0xff808080, 0xffc08080, 0xff00a080, 0xff40a080,
+ 0xff80a080, 0xffc0a080, 0xff00c080, 0xff40c080, 0xff80c080, 0xffc0c080,
+ 0xff00e080, 0xff40e080, 0xff80e080, 0xffc0e080, 0xff0000a0, 0xff4000a0,
+ 0xff8000a0, 0xffc000a0, 0xff0020a0, 0xff4020a0, 0xff8020a0, 0xffc020a0,
+ 0xff0040a0, 0xff4040a0, 0xff8040a0, 0xffc040a0, 0xff0060a0, 0xff4060a0,
+ 0xff8060a0, 0xffc060a0, 0xff0080a0, 0xff4080a0, 0xff8080a0, 0xffc080a0,
+ 0xff00a0a0, 0xff40a0a0, 0xff80a0a0, 0xffc0a0a0, 0xff00c0a0, 0xff40c0a0,
+ 0xff80c0a0, 0xffc0c0a0, 0xff00e0a0, 0xff40e0a0, 0xff80e0a0, 0xffc0e0a0,
+ 0xff0000c0, 0xff4000c0, 0xff8000c0, 0xffc000c0, 0xff0020c0, 0xff4020c0,
+ 0xff8020c0, 0xffc020c0, 0xff0040c0, 0xff4040c0, 0xff8040c0, 0xffc040c0,
+ 0xff0060c0, 0xff4060c0, 0xff8060c0, 0xffc060c0, 0xff0080c0, 0xff4080c0,
+ 0xff8080c0, 0xffc080c0, 0xff00a0c0, 0xff40a0c0, 0xff80a0c0, 0xffc0a0c0,
+ 0xff00c0c0, 0xff40c0c0, 0xff80c0c0, 0xffc0c0c0, 0xff00e0c0, 0xff40e0c0,
+ 0xff80e0c0, 0xffc0e0c0, 0xff0000e0, 0xff4000e0, 0xff8000e0, 0xffc000e0,
+ 0xff0020e0, 0xff4020e0, 0xff8020e0, 0xffc020e0, 0xff0040e0, 0xff4040e0,
+ 0xff8040e0, 0xffc040e0, 0xff0060e0, 0xff4060e0, 0xff8060e0, 0xffc060e0,
+ 0xff0080e0, 0xff4080e0, 0xff8080e0, 0xffc080e0, 0xff00a0e0, 0xff40a0e0,
+ 0xff80a0e0, 0xffc0a0e0, 0xff00c0e0, 0xff40c0e0, 0xff80c0e0, 0xffc0c0e0,
+ 0xff00e0e0, 0xff40e0e0, 0xff80e0e0, 0xffc0e0e0,
+};
+
+cOsdPipObject::cOsdPipObject(cDevice *Device, const cChannel *Channel):
+ cOsdObject(true) {
+ m_Channel = Channel;
+ m_Osd = NULL;
+ m_ESBuffer = new cRingBufferLinear(MEGABYTE(3), 0, true);
+
+ m_Xpos = 25;
+ m_Ypos = 25;
+
+ Device->SwitchChannel(m_Channel, false);
+ m_Receiver = new cOsdPipReceiver(m_Channel, m_ESBuffer);
+ Device->AttachReceiver(m_Receiver);
+}
+
+cOsdPipObject::~cOsdPipObject() {
+ if (m_Active) {
+ m_Active = false;
+ Cancel(3);
+ }
+
+ delete m_Receiver;
+ if (m_Osd != NULL)
+ delete m_Osd;
+}
+
+void cOsdPipObject::Action(void) {
+ m_Active = true;
+
+ isyslog("osdpip: decoder thread started (pid = %d)", getpid());
+
+ mpeg2dec_t *handle = mpeg2_init();
+ const mpeg2_info_t *info = mpeg2_info(handle);
+ mpeg2_state_t state;
+
+ while (m_Active) {
+ cBitmap frame(312, 236, 8);
+ const uchar *block;
+ int recvd;
+
+ state = mpeg2_parse(handle);
+ switch (state) {
+ case STATE_BUFFER:
+ block = m_ESBuffer->Get(recvd);
+ if (block && recvd > 0) {
+ mpeg2_buffer(handle, (uint8_t*)block, (uint8_t*)block + recvd);
+ m_ESBuffer->Del(recvd);
+ } else
+ usleep(1);
+ break;
+
+ case STATE_SEQUENCE:
+ mpeg2_convert(handle, mpeg2convert_rgb8, NULL);
+ break;
+
+ case STATE_SLICE:
+ case STATE_END:
+ case STATE_INVALID_END:
+ if (info->display_fbuf && (info->display_picture->flags
+ & PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_I) {
+ for (int x = 0; x < 312; ++x) {
+ for (int y = 0; y < 236; ++y) {
+ uint8_t *ptr = info->display_fbuf->buf[0] + ((50 + y * 2)
+ * info->sequence->width + (50 + x * 2));
+ frame.SetPixel(x, y, (eDvbColor)palette[(int)*ptr]);
+ }
+ }
+ m_Osd->SetBitmap(m_Xpos, m_Ypos, frame);
+ m_Osd->Flush();
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ isyslog("osdpip: decoder thread stopped");
+}
+
+void cOsdPipObject::Show(void) {
+ m_Osd = cOsd::OpenRaw(0, 0);
+ m_Window = m_Osd->Create(m_Xpos, m_Ypos, 312, 236, 8, false);
+ if (m_Osd) {
+ m_Osd->Clear();
+ Start();
+ }
+}
+
+eOSState cOsdPipObject::ProcessKey(eKeys Key) {
+ eOSState state = cOsdObject::ProcessKey(Key);
+ if (state == osUnknown) {
+ switch (Key & ~k_Repeat) {
+ case k0: Channels.SwitchTo(m_Channel->Number());
+ case kBack: return osEnd;
+
+ case k1...k9:
+ switch (Key & ~k_Repeat) {
+ case k1:
+ m_Xpos = 25;
+ m_Ypos = 25;
+ break;
+ case k2:
+ m_Xpos = (Setup.OSDwidth * cOsd::CellWidth()) / 2 - 75;
+ m_Ypos = 25;
+ break;
+ case k3:
+ m_Xpos = (Setup.OSDwidth * cOsd::CellWidth()) - 175;
+ m_Ypos = 25;
+ break;
+ case k4:
+ m_Xpos = 25;
+ m_Ypos = (Setup.OSDheight * cOsd::LineHeight()) / 2 - 55;
+ break;
+ case k5:
+ m_Xpos = (Setup.OSDwidth * cOsd::CellWidth()) / 2 - 75;
+ m_Ypos = (Setup.OSDheight * cOsd::LineHeight()) / 2 - 55;
+ break;
+ case k6:
+ m_Xpos = (Setup.OSDwidth * cOsd::CellWidth()) - 155;
+ m_Ypos = (Setup.OSDheight * cOsd::LineHeight()) / 2 - 55;
+ break;
+ case k7:
+ m_Xpos = 25;
+ m_Ypos = (Setup.OSDheight * cOsd::LineHeight()) - 105;
+ break;
+ case k8:
+ m_Xpos = (Setup.OSDwidth * cOsd::CellWidth()) / 2 - 75;
+ m_Ypos = (Setup.OSDheight * cOsd::LineHeight()) - 105;
+ break;
+ case k9:
+ m_Xpos = (Setup.OSDwidth * cOsd::CellWidth()) - 175;
+ m_Ypos = (Setup.OSDheight * cOsd::LineHeight()) - 105;
+ break;
+ }
+ m_Osd->Relocate(m_Window, m_Xpos, m_Ypos);
+ break;
+
+ case kUp:
+ case kDown: cDevice::SwitchChannel(NORMALKEY(Key) == kUp ? 1 : -1);
+ break;
+
+ default: return state;
+ }
+ state = osContinue;
+ }
+ return state;
+}
diff --git a/osd.h b/osd.h
new file mode 100644
index 0000000..1ff39ea
--- /dev/null
+++ b/osd.h
@@ -0,0 +1,38 @@
+#ifndef VDR_OSDPIP_OSD_H
+#define VDR_OSDPIP_OSD_H
+
+#include <vdr/osd.h>
+#include <vdr/thread.h>
+#include <vdr/receiver.h>
+
+extern "C" {
+#include <mpeg2dec/mpeg2.h>
+#include <mpeg2dec/mpeg2convert.h>
+};
+
+class cRingBufferLinear;
+class cOsdPipReceiver;
+
+class cOsdPipObject: public cOsdObject, public cThread {
+private:
+ cOsdBase *m_Osd;
+ cRingBufferLinear *m_ESBuffer;
+ cOsdPipReceiver *m_Receiver;
+ const cChannel *m_Channel;
+ tWindowHandle m_Window;
+
+ bool m_Active;
+ int m_Xpos, m_Ypos;
+
+protected:
+ virtual void Action(void);
+
+public:
+ cOsdPipObject(cDevice *Device, const cChannel *Channel);
+ virtual ~cOsdPipObject(void);
+
+ virtual void Show(void);
+ eOSState ProcessKey(eKeys k);
+};
+
+#endif // VDR_OSDPIP_OSD_H
diff --git a/osdpip.c b/osdpip.c
new file mode 100644
index 0000000..afa76d1
--- /dev/null
+++ b/osdpip.c
@@ -0,0 +1,85 @@
+/*
+ * osdpip.c: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id$
+ */
+
+#include "osd.h"
+#include "i18n.h"
+
+#include <vdr/plugin.h>
+
+static const char *VERSION = "0.0.1";
+static const char *DESCRIPTION = "OSD Picture-in-Picture";
+static const char *MAINMENUENTRY = "Picture-in-Picture";
+
+class cPluginOsdpip : public cPlugin {
+private:
+
+public:
+ cPluginOsdpip(void);
+ virtual ~cPluginOsdpip();
+ 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 void Housekeeping(void);
+ virtual const char *MainMenuEntry(void) { return tr(MAINMENUENTRY); }
+ virtual cOsdObject *MainMenuAction(void);
+ virtual cMenuSetupPage *SetupMenu(void);
+ virtual bool SetupParse(const char *Name, const char *Value);
+};
+
+cPluginOsdpip::cPluginOsdpip(void) {
+}
+
+cPluginOsdpip::~cPluginOsdpip() {
+}
+
+const char *cPluginOsdpip::CommandLineHelp(void) {
+ return NULL;
+}
+
+bool cPluginOsdpip::ProcessArgs(int argc, char *argv[]) {
+ return true;
+}
+
+bool cPluginOsdpip::Initialize(void) {
+ return true;
+}
+
+bool cPluginOsdpip::Start(void) {
+ RegisterI18n(Phrases);
+ return true;
+}
+
+void cPluginOsdpip::Housekeeping(void) {
+}
+
+cOsdObject *cPluginOsdpip::MainMenuAction(void) {
+ const cChannel *chan;
+ cDevice *dev;
+
+ chan = cDevice::CurrentChannel() != 0
+ ? Channels.GetByNumber(cDevice::CurrentChannel()) : NULL;
+ if (chan != NULL) {
+ dev = cDevice::GetDevice(chan, 1);
+ if (dev)
+ return new cOsdPipObject(dev, chan);
+ }
+ return NULL;
+}
+
+cMenuSetupPage *cPluginOsdpip::SetupMenu(void) {
+ return NULL;
+}
+
+bool cPluginOsdpip::SetupParse(const char *Name, const char *Value) {
+ return false;
+}
+
+VDRPLUGINCREATOR(cPluginOsdpip); // Don't touch this!
diff --git a/receiver.c b/receiver.c
new file mode 100644
index 0000000..22a481c
--- /dev/null
+++ b/receiver.c
@@ -0,0 +1,56 @@
+#include "receiver.h"
+#include "remux/ts2es.h"
+
+#include <vdr/channels.h>
+#include <vdr/ringbuffer.h>
+
+cOsdPipReceiver::cOsdPipReceiver(const cChannel *Channel,
+ cRingBufferLinear *ESBuffer):
+ cReceiver(Channel->Ca(), 0, 2, Channel->Vpid(), Channel->Apid1()) {
+ m_TSBuffer = new cRingBufferLinear(MEGABYTE(3), TS_SIZE * 2, true);
+ m_ESBuffer = ESBuffer;
+ m_Remux = new cTS2ESRemux(Channel->Vpid());
+ m_Active = false;
+}
+
+cOsdPipReceiver::~cOsdPipReceiver() {
+ Detach();
+ delete m_Remux;
+ delete m_TSBuffer;
+}
+
+void cOsdPipReceiver::Activate(bool On) {
+ if (On)
+ Start();
+ else if (m_Active) {
+ m_Active = false;
+ Cancel(3);
+ }
+}
+
+void cOsdPipReceiver::Receive(uchar *Data, int Length) {
+ int put = m_TSBuffer->Put(Data, Length);
+ if (put != Length)
+ esyslog("osdpip: ringbuffer overflow (%d bytes dropped)", Length - put);
+}
+
+void cOsdPipReceiver::Action(void) {
+ dsyslog("osdpip: receiver thread started (pid=%d)", getpid());
+
+ m_Active = true;
+ while (m_Active) {
+ int r;
+ const uchar *b = m_TSBuffer->Get(r);
+ if (b) {
+ int Count = r, Result;
+ uchar *p = m_Remux->Process(b, Count, Result);
+ m_TSBuffer->Del(Count);
+
+ if (p)
+ m_ESBuffer->Put(p, Result);
+ } else
+ usleep(1); // this keeps the CPU load low
+ }
+
+ dsyslog("osdpip: receiver thread ended (pid=%d)", getpid());
+}
diff --git a/receiver.h b/receiver.h
new file mode 100644
index 0000000..7de50db
--- /dev/null
+++ b/receiver.h
@@ -0,0 +1,29 @@
+#ifndef VDR_OSDPIP_RECEIVER_H
+#define VDR_OSDPIP_RECEIVER_H
+
+#include <vdr/receiver.h>
+#include <vdr/thread.h>
+
+class cRingBufferLinear;
+class cTS2ESRemux;
+
+class cOsdPipReceiver: public cReceiver, public cThread {
+private:
+ cRingBufferLinear *m_TSBuffer;
+ cRingBufferLinear *m_ESBuffer;
+ cTS2ESRemux *m_Remux;
+
+ bool m_Active;
+
+protected:
+ virtual void Activate(bool On);
+ virtual void Receive(uchar *Data, int Length);
+ virtual void Action(void);
+
+public:
+ cOsdPipReceiver::cOsdPipReceiver(const cChannel *Channel,
+ cRingBufferLinear *ESBuffer);
+ virtual ~cOsdPipReceiver();
+};
+
+#endif // VDR_OSDPIP_RECEIVER_H
diff --git a/remux/ts2es.c b/remux/ts2es.c
new file mode 100644
index 0000000..2f27d4f
--- /dev/null
+++ b/remux/ts2es.c
@@ -0,0 +1,87 @@
+#include "remux/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
index 0000000..8026a1b
--- /dev/null
+++ b/remux/ts2es.h
@@ -0,0 +1,21 @@
+#ifndef VDR_STREAMDEV_TS2ESREMUX_H
+#define VDR_STREAMDEV_TS2ESREMUX_H
+
+#include "remux/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
index 0000000..222c39a
--- /dev/null
+++ b/remux/ts2ps.c
@@ -0,0 +1,104 @@
+#include "remux/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 (*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
index 0000000..4e43ed2
--- /dev/null
+++ b/remux/ts2ps.h
@@ -0,0 +1,22 @@
+#ifndef VDR_STREAMDEV_TS2PESREMUX_H
+#define VDR_STREAMDEV_TS2PESREMUX_H
+
+#include "remux/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
index 0000000..93f513b
--- /dev/null
+++ b/remux/tsremux.c
@@ -0,0 +1,185 @@
+#include "remux/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) {
+ 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;
+ }
+ 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
+ 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
index 0000000..3e83c73
--- /dev/null
+++ b/remux/tsremux.h
@@ -0,0 +1,30 @@
+#ifndef VDR_STREAMDEV_TSREMUX_H
+#define VDR_STREAMDEV_TSREMUX_H
+
+#include "libdvbmpeg/transform.h"
+#include <vdr/remux.h>
+
+class cTSRemux {
+protected:
+ 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