summaryrefslogtreecommitdiffstats
path: root/mpeglib/lib/mpegplay
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commite2de64d6f1beb9e492daf5b886e19933c1fa41dd (patch)
tree9047cf9e6b5c43878d5bf82660adae77ceee097a /mpeglib/lib/mpegplay
downloadtdemultimedia-e2de64d6f1beb9e492daf5b886e19933c1fa41dd.tar.gz
tdemultimedia-e2de64d6f1beb9e492daf5b886e19933c1fa41dd.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdemultimedia@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'mpeglib/lib/mpegplay')
-rw-r--r--mpeglib/lib/mpegplay/COPYRIGHT145
-rw-r--r--mpeglib/lib/mpegplay/Makefile.am48
-rw-r--r--mpeglib/lib/mpegplay/README26
-rw-r--r--mpeglib/lib/mpegplay/configure.in.in1
-rw-r--r--mpeglib/lib/mpegplay/copyFunctions.cpp330
-rw-r--r--mpeglib/lib/mpegplay/copyFunctions.h95
-rw-r--r--mpeglib/lib/mpegplay/copyFunctions_asm.cpp90
-rw-r--r--mpeglib/lib/mpegplay/copyFunctions_asm.h61
-rw-r--r--mpeglib/lib/mpegplay/copyFunctions_mmx.cpp313
-rw-r--r--mpeglib/lib/mpegplay/copyFunctions_mmx.h68
-rw-r--r--mpeglib/lib/mpegplay/decoderClass.cpp893
-rw-r--r--mpeglib/lib/mpegplay/decoderClass.h96
-rw-r--r--mpeglib/lib/mpegplay/decoderTables.cpp594
-rw-r--r--mpeglib/lib/mpegplay/decoderTables.h110
-rw-r--r--mpeglib/lib/mpegplay/globals.cpp41
-rw-r--r--mpeglib/lib/mpegplay/gop.cpp170
-rw-r--r--mpeglib/lib/mpegplay/gop.h62
-rw-r--r--mpeglib/lib/mpegplay/jrevdct.cpp1690
-rw-r--r--mpeglib/lib/mpegplay/jrevdct.h57
-rw-r--r--mpeglib/lib/mpegplay/macroBlock.cpp1152
-rw-r--r--mpeglib/lib/mpegplay/macroBlock.h97
-rw-r--r--mpeglib/lib/mpegplay/mainMpegPlay.cpp179
-rw-r--r--mpeglib/lib/mpegplay/mmxidct.cpp27
-rw-r--r--mpeglib/lib/mpegplay/mmxidct.h22
-rw-r--r--mpeglib/lib/mpegplay/mmxidct_asm.S738
-rw-r--r--mpeglib/lib/mpegplay/motionVector.cpp130
-rw-r--r--mpeglib/lib/mpegplay/motionVector.h40
-rw-r--r--mpeglib/lib/mpegplay/mpegExtension.cpp258
-rw-r--r--mpeglib/lib/mpegplay/mpegExtension.h49
-rw-r--r--mpeglib/lib/mpegplay/mpegSystemHeader.cpp786
-rw-r--r--mpeglib/lib/mpegplay/mpegSystemHeader.h484
-rw-r--r--mpeglib/lib/mpegplay/mpegSystemStream.cpp235
-rw-r--r--mpeglib/lib/mpegplay/mpegSystemStream.h53
-rw-r--r--mpeglib/lib/mpegplay/mpegVideoBitWindow.cpp258
-rw-r--r--mpeglib/lib/mpegplay/mpegVideoBitWindow.h108
-rw-r--r--mpeglib/lib/mpegplay/mpegVideoHeader.cpp293
-rw-r--r--mpeglib/lib/mpegplay/mpegVideoHeader.h83
-rw-r--r--mpeglib/lib/mpegplay/mpegVideoLength.cpp424
-rw-r--r--mpeglib/lib/mpegplay/mpegVideoLength.h93
-rw-r--r--mpeglib/lib/mpegplay/mpegVideoStream.cpp224
-rw-r--r--mpeglib/lib/mpegplay/mpegVideoStream.h110
-rw-r--r--mpeglib/lib/mpegplay/pesSystemStream.cpp498
-rw-r--r--mpeglib/lib/mpegplay/pesSystemStream.h57
-rw-r--r--mpeglib/lib/mpegplay/picture.cpp149
-rw-r--r--mpeglib/lib/mpegplay/picture.h82
-rw-r--r--mpeglib/lib/mpegplay/proto.h36
-rw-r--r--mpeglib/lib/mpegplay/psSystemStream.cpp163
-rw-r--r--mpeglib/lib/mpegplay/psSystemStream.h57
-rw-r--r--mpeglib/lib/mpegplay/recon.cpp735
-rw-r--r--mpeglib/lib/mpegplay/recon.h55
-rw-r--r--mpeglib/lib/mpegplay/slice.cpp73
-rw-r--r--mpeglib/lib/mpegplay/slice.h48
-rw-r--r--mpeglib/lib/mpegplay/startCodes.h63
-rw-r--r--mpeglib/lib/mpegplay/tsSystemStream.cpp377
-rw-r--r--mpeglib/lib/mpegplay/tsSystemStream.h68
-rw-r--r--mpeglib/lib/mpegplay/videoDecoder.cpp476
-rw-r--r--mpeglib/lib/mpegplay/videoDecoder.h118
57 files changed, 13788 insertions, 0 deletions
diff --git a/mpeglib/lib/mpegplay/COPYRIGHT b/mpeglib/lib/mpegplay/COPYRIGHT
new file mode 100644
index 00000000..39076276
--- /dev/null
+++ b/mpeglib/lib/mpegplay/COPYRIGHT
@@ -0,0 +1,145 @@
+
+The copyright of this package is a bit interesting.
+
+I release my modification under GPL, although many
+parts (which I only copy&paste) are still the BSD license.
+Thus, if you use this software, you use GPL source with
+all advantages off the GPL license :-)
+
+Martin Vogt <mvogt@rhrk.uni-kl.de>
+
+
+Here is the "history" of this package:
+
+
+The copyrights from mpeg_play:
+===========================================
+
+First the source comes from the Berkeley mpeg_play player.
+and was programmed by:
+
+ MPEG Video Software Decoder
+ (Version 2.3; March 1996)
+
+ Lawrence A. Rowe<Rowe@CS.Berkeley.EDU>, Ketan Patel, Brian Smith, Steve Smoot, and Eugene Hung
+ Computer Science Division-EECS, Univ. of Calif. at Berkeley
+
+mpeg_play related emails:
+ mpeg-bugs@plateau.cs.berkeley.edu
+
+The JPEG code comes from :
+
+ jrevdct.c comes from the IJG libjpeg release,
+The "official" archive site for this software is ftp.uu.net (Internet
+address 192.48.96.9). The most recent released version can always be
+found there in directory graphics/jpeg.
+
+
+
+Many other peoples have contributed to the mpeg_play package:
+
+ACKNOWLEDGEMENTS:
+ We gratefully thank Hewlett-Packard, Fujitsu, the Semiconductor
+ Research Corporation for financial support.
+
+ We also want to thank the following people for their help:
+
+ Tom Lane of the Independent JPEG Group provided us with
+ the basic inverse DCT code used by our player.
+ (tom_lane@g.gp.cs.cmu.edu)
+
+ Reid Judd of Sun Microsystems provided advice and assistance.
+
+ Todd Brunhoff of NVR provided advice and assistance.
+
+ Toshihiko Kawai of Sony provided advice and assistance.
+
+ Portions of this software Copyright (c) 1995 Brown University.
+ All rights reserved.(Loring Holden lsh@cs.brown.edu)
+
+
+
+Here is my work:
+
+The mpeg_play source has become over the years more and more _ugly_.
+When I started the work (I wanted to play my Titanic CD-I with Linux)
+I saw that mpeg_play needed a complete reengineering. This package
+is the result of this work:
+
+* a readable source code
+* better structures (although not real OOP)
+* a few frames/second slower (buy faster cpus!)
+* and usefull input interfaces (for file,http,..)
+
+But my modification (which makes programmers life much easier)
+are done under the GPL!
+Ok, the main part is still under the BSD License (all these
+strange and complicated algorithm, I don't understand) but if you
+use this package (with my modifications) you use GPL source!
+
+And ere are all theses Licences:
+/*
+ * Copyright (c) 1995 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+
+/*
+ * Portions of this software Copyright (c) 1995 Brown University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement
+ * is hereby granted, provided that the above copyright notice and the
+ * following two paragraphs appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
+ * BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
+ * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+
+Copyright (c) 1999 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library 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.
+
+For more information you can conntact me by electronic mail:
+
+ mvogt@rhrk.uni-kl.de
+
+
diff --git a/mpeglib/lib/mpegplay/Makefile.am b/mpeglib/lib/mpegplay/Makefile.am
new file mode 100644
index 00000000..172d4a96
--- /dev/null
+++ b/mpeglib/lib/mpegplay/Makefile.am
@@ -0,0 +1,48 @@
+# libsplay - Makefile.am
+
+EXTRA_DIST = mainMpegPlay.cpp README COPYRIGHT \
+ mmxidct_asm.S copyFunctions.cpp
+
+INCLUDES = $(all_includes)
+
+AM_ASFLAGS = $(DEFS) $(DEFAULT_INCLUDES) $(all_includes) $(INTELCPPFLAG)
+AM_CCASFLAGS = $(AM_ASFLAGS)
+
+
+noinst_LTLIBRARIES = libmpegplay.la
+
+noinst_HEADERS = mpegVideoHeader.h mpegVideoStream.h \
+ decoderTables.h gop.h \
+ proto.h \
+ recon.h startCodes.h \
+ jrevdct.h \
+ motionVector.h slice.h \
+ decoderClass.h \
+ mmxidct.h \
+ picture.h mpegExtension.h macroBlock.h \
+ copyFunctions.h \
+ mpegVideoBitWindow.h videoDecoder.h \
+ copyFunctions_asm.h copyFunctions_mmx.h
+
+mpegutildir = $(includedir)/$(THIS_LIB_NAME)/mpegutil
+
+mpegutil_HEADERS = mpegSystemStream.h mpegVideoLength.h \
+ mpegSystemHeader.h tsSystemStream.h \
+ psSystemStream.h pesSystemStream.h
+
+libmpegplay_la_SOURCES = mpegVideoHeader.cpp mpegVideoStream.cpp \
+ globals.cpp jrevdct.cpp \
+ recon.cpp decoderClass.cpp \
+ decoderTables.cpp motionVector.cpp \
+ slice.cpp gop.cpp \
+ mmxidct.cpp \
+ mpegSystemHeader.cpp mpegSystemStream.cpp \
+ picture.cpp mpegExtension.cpp \
+ macroBlock.cpp \
+ mpegVideoLength.cpp \
+ mpegVideoBitWindow.cpp videoDecoder.cpp \
+ copyFunctions_asm.cpp copyFunctions_mmx.cpp \
+ mmxidct_asm.S copyFunctions.cpp \
+ tsSystemStream.cpp psSystemStream.cpp \
+ pesSystemStream.cpp
+
diff --git a/mpeglib/lib/mpegplay/README b/mpeglib/lib/mpegplay/README
new file mode 100644
index 00000000..5bd23c08
--- /dev/null
+++ b/mpeglib/lib/mpegplay/README
@@ -0,0 +1,26 @@
+
+This directory contains a highly modified version of
+mpeg_play the Berkley mpeg video player.
+
+Please view the file COPYRIGHT for licence questions.
+
+mpeg_play is in its current state (2.4) old and ugly source.
+It's an old software package, which has been ported to too
+many architectures, without keeping the source clean.
+
+(No, #ifdef/#defines is not the way to write cross platform code!)
+
+This is a new approach of an mpeg1 video player.
+
+I think this library is much cleaner and is now really usable
+for mpeg1 video/audio playing.
+
+It needed a lot of work to even come to this (not
+optimal) source code. But if you knew the mpeg_play source, you
+obviously understand :-)
+
+
+For comments or bug reports you can write me an email:
+
+Martin Vogt <mvogt@rhrk.uni-kl.de>
+
diff --git a/mpeglib/lib/mpegplay/configure.in.in b/mpeglib/lib/mpegplay/configure.in.in
new file mode 100644
index 00000000..b2830f33
--- /dev/null
+++ b/mpeglib/lib/mpegplay/configure.in.in
@@ -0,0 +1 @@
+AM_PROG_AS
diff --git a/mpeglib/lib/mpegplay/copyFunctions.cpp b/mpeglib/lib/mpegplay/copyFunctions.cpp
new file mode 100644
index 00000000..e290da50
--- /dev/null
+++ b/mpeglib/lib/mpegplay/copyFunctions.cpp
@@ -0,0 +1,330 @@
+/*
+ stores heavily used copy functions (makes mmx support easier)
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "copyFunctions.h"
+
+
+/*
+ * We use a lookup table to make sure values stay in the 0..255 range.
+ * Since this is cropping (ie, x = (x < 0)?0:(x>255)?255:x; ), wee call this
+ * table the "crop table".
+ * MAX_NEG_CROP is the maximum neg/pos value we can handle.
+ */
+/*
+ * We use a lookup table to make sure values stay in the 0..255 range.
+ * Since this is cropping (ie, x = (x < 0)?0:(x>255)?255:x; ), wee call this
+ * table the "crop table".
+ * MAX_NEG_CROP is the maximum neg/pos value we can handle.
+ */
+
+// Compiler cannot allocate too big arrays.
+
+
+
+
+CopyFunctions::CopyFunctions() {
+ /* Initialize crop table. */
+ cropTbl=new unsigned char[NUM_CROP_ENTRIES];
+
+ int i;
+
+ for (i = (-MAX_NEG_CROP); i < NUM_CROP_ENTRIES - MAX_NEG_CROP; i++) {
+ if (i <= 0) {
+ cropTbl[i + MAX_NEG_CROP] = 0;
+ } else if (i >= 255) {
+ cropTbl[i + MAX_NEG_CROP] = 255;
+ } else {
+ cropTbl[i + MAX_NEG_CROP] = i;
+ }
+ }
+ cm=cropTbl + MAX_NEG_CROP;
+
+ copyFunctions_asm = new CopyFunctions_MMX();
+ lmmx=copyFunctions_asm->support();
+
+
+
+}
+
+
+CopyFunctions::~CopyFunctions() {
+ delete cropTbl;
+}
+
+void CopyFunctions::startNOFloatSection() {
+ // nothing
+ copyFunctions_asm->startNOFloatSection();
+}
+
+
+void CopyFunctions::endNOFloatSection() {
+ copyFunctions_asm->endNOFloatSection();
+
+}
+
+
+void CopyFunctions::copy8_byte(unsigned char* source1,
+ unsigned char* dest,int inc) {
+ if (lmmx == false) {
+ int rr;
+
+ for (rr = 0; rr < 8; rr++) {
+ memcpy(dest,source1,sizeof(char)*8);
+ source1+=inc;
+ dest+=inc;
+ }
+
+ } else {
+ copyFunctions_asm->copy8_byte(source1,dest,inc);
+ }
+
+
+}
+
+void CopyFunctions::copy8_word(unsigned short* source1,
+ unsigned short* dest,int inc) {
+ int rr;
+
+ // Optimisation is slower, leave it in C
+ for (rr = 0; rr < 8; rr++) {
+ memcpy(dest,source1,sizeof(short)*8);
+ source1+=inc;
+ dest+=inc;
+ }
+
+}
+
+
+
+void CopyFunctions::copy8_src1linear_crop(short* source1,
+ unsigned char* dest,int inc) {
+
+ if (lmmx == false) {
+ int rr;
+
+ for (rr = 0; rr < 8; rr++) {
+
+ dest[0] = cm[source1[0]];
+ dest[1] = cm[source1[1]];
+ dest[2] = cm[source1[2]];
+ dest[3] = cm[source1[3]];
+ dest[4] = cm[source1[4]];
+ dest[5] = cm[source1[5]];
+ dest[6] = cm[source1[6]];
+ dest[7] = cm[source1[7]];
+
+
+ dest += inc;
+ source1 += 8;
+
+ }
+ } else {
+ copyFunctions_asm->copy8_src1linear_crop(source1,dest,inc);
+ }
+
+}
+
+void CopyFunctions::copy8_div2_nocrop(unsigned char* source1,
+ unsigned char* source2,
+ unsigned char* dest,int inc) {
+ if (lmmx == false) {
+ int rr;
+ for (rr = 0; rr < 8; rr++) {
+
+ dest[0] = (int) (source1[0] + source2[0]+1) >> 1;
+ dest[1] = (int) (source1[1] + source2[1]+1) >> 1;
+ dest[2] = (int) (source1[2] + source2[2]+1) >> 1;
+ dest[3] = (int) (source1[3] + source2[3]+1) >> 1;
+ dest[4] = (int) (source1[4] + source2[4]+1) >> 1;
+ dest[5] = (int) (source1[5] + source2[5]+1) >> 1;
+ dest[6] = (int) (source1[6] + source2[6]+1) >> 1;
+ dest[7] = (int) (source1[7] + source2[7]+1) >> 1;
+ dest += inc;
+ source1 += inc;
+ source2 += inc;
+ }
+ } else {
+ copyFunctions_asm->copy8_div2_nocrop(source1,source2, dest, inc);
+ }
+
+}
+
+void CopyFunctions::copy8_div2_destlinear_nocrop(unsigned char* source1,
+ unsigned char* source2,
+ unsigned char* dest,int inc) {
+
+ if (lmmx == false) {
+ int rr;
+ for (rr = 0; rr < 8; rr++) {
+ dest[0] = (int) (source1[0] + source2[0]) >> 1;
+ dest[1] = (int) (source1[1] + source2[1]) >> 1;
+ dest[2] = (int) (source1[2] + source2[2]) >> 1;
+ dest[3] = (int) (source1[3] + source2[3]) >> 1;
+ dest[4] = (int) (source1[4] + source2[4]) >> 1;
+ dest[5] = (int) (source1[5] + source2[5]) >> 1;
+ dest[6] = (int) (source1[6] + source2[6]) >> 1;
+ dest[7] = (int) (source1[7] + source2[7]) >> 1;
+ dest += 8;
+ source1 += inc;
+ source2 += inc;
+ }
+ } else {
+ copyFunctions_asm->copy8_div2_destlinear_nocrop(source1,source2,dest,inc);
+ }
+}
+
+
+void CopyFunctions::copy16_div2_destlinear_nocrop(unsigned char* source1,
+ unsigned char* source2,
+ unsigned char* dest,int inc){
+
+ if (lmmx == false) {
+ int rr;
+ for (rr = 0; rr < 16; rr++) {
+ dest[0] = (int) (source1[0] + source2[0]) >> 1;
+ dest[1] = (int) (source1[1] + source2[1]) >> 1;
+ dest[2] = (int) (source1[2] + source2[2]) >> 1;
+ dest[3] = (int) (source1[3] + source2[3]) >> 1;
+ dest[4] = (int) (source1[4] + source2[4]) >> 1;
+ dest[5] = (int) (source1[5] + source2[5]) >> 1;
+ dest[6] = (int) (source1[6] + source2[6]) >> 1;
+ dest[7] = (int) (source1[7] + source2[7]) >> 1;
+ dest[8] = (int) (source1[8] + source2[8]) >> 1;
+ dest[9] = (int) (source1[9] + source2[9]) >> 1;
+ dest[10] = (int) (source1[10] + source2[10]) >> 1;
+ dest[11] = (int) (source1[11] + source2[11]) >> 1;
+ dest[12] = (int) (source1[12] + source2[12]) >> 1;
+ dest[13] = (int) (source1[13] + source2[13]) >> 1;
+ dest[14] = (int) (source1[14] + source2[14]) >> 1;
+ dest[15] = (int) (source1[15] + source2[15]) >> 1;
+ dest += 16;
+ source1 += inc;
+ source2 += inc;
+ }
+ } else {
+ copyFunctions_asm->copy16_div2_destlinear_nocrop(source1,source2,dest,inc);
+ }
+
+}
+
+
+
+void CopyFunctions::copy8_div4_nocrop(unsigned char* source1,
+ unsigned char* source2,
+ unsigned char* source3,
+ unsigned char* source4,
+ unsigned char* dest,int inc) {
+ int rr;
+
+ for (rr = 0; rr < 8; rr++) {
+ dest[0]=(int) (source1[0]+source2[0]+source3[0]+source4[0] + 2) >> 2;
+ dest[1]=(int) (source1[1]+source2[1]+source3[1]+source4[1] + 2) >> 2;
+ dest[2]=(int) (source1[2]+source2[2]+source3[2]+source4[2] + 2) >> 2;
+ dest[3]=(int) (source1[3]+source2[3]+source3[3]+source4[3] + 2) >> 2;
+ dest[4]=(int) (source1[4]+source2[4]+source3[4]+source4[4] + 2) >> 2;
+ dest[5]=(int) (source1[5]+source2[5]+source3[5]+source4[5] + 2) >> 2;
+ dest[6]=(int) (source1[6]+source2[6]+source3[6]+source4[6] + 2) >> 2;
+ dest[7]=(int) (source1[7]+source2[7]+source3[7]+source4[7] + 2) >> 2;
+ dest += inc;
+ source1 += inc;
+ source2 += inc;
+ source3 += inc;
+ source4 += inc;
+ }
+}
+
+// Optimize me!
+// should be mmx perfomance analysis shows: 8 % overall time
+
+void CopyFunctions::copy8_src2linear_crop(unsigned char* source1,
+ short int* source2,
+ unsigned char* dest,int inc) {
+ int rr;
+ if (lmmx == false) {
+ for (rr = 0; rr < 8; rr++) {
+ dest[0] = cm[(int) source1[0] + (int) source2[0]];
+ dest[1] = cm[(int) source1[1] + (int) source2[1]];
+ dest[2] = cm[(int) source1[2] + (int) source2[2]];
+ dest[3] = cm[(int) source1[3] + (int) source2[3]];
+ dest[4] = cm[(int) source1[4] + (int) source2[4]];
+ dest[5] = cm[(int) source1[5] + (int) source2[5]];
+ dest[6] = cm[(int) source1[6] + (int) source2[6]];
+ dest[7] = cm[(int) source1[7] + (int) source2[7]];
+ dest += inc;
+ source1 += inc;
+ source2 += 8;
+ }
+ } else {
+ copyFunctions_asm->copy8_src2linear_crop(source1,source2,dest,inc);
+ }
+
+}
+
+// Optimize me!
+// should be mmx perfomance analysis shows: 13 % overall time
+void CopyFunctions::copy8_div2_src3linear_crop(unsigned char* source1,
+ unsigned char* source2,
+ short int* source3,
+ unsigned char* dest,int inc) {
+ int rr;
+ if (lmmx==false) {
+ for (rr = 0; rr < 8; rr++) {
+ dest[0] = cm[((int) (source1[0] + source2[0]+1) >> 1) + source3[0]];
+ dest[1] = cm[((int) (source1[1] + source2[1]+1) >> 1) + source3[1]];
+ dest[2] = cm[((int) (source1[2] + source2[2]+1) >> 1) + source3[2]];
+ dest[3] = cm[((int) (source1[3] + source2[3]+1) >> 1) + source3[3]];
+ dest[4] = cm[((int) (source1[4] + source2[4]+1) >> 1) + source3[4]];
+ dest[5] = cm[((int) (source1[5] + source2[5]+1) >> 1) + source3[5]];
+ dest[6] = cm[((int) (source1[6] + source2[6]+1) >> 1) + source3[6]];
+ dest[7] = cm[((int) (source1[7] + source2[7]+1) >> 1) + source3[7]];
+ dest += inc;
+ source1 += inc;
+ source2 += inc;
+ source3 += 8;
+
+ }
+ } else {
+ copyFunctions_asm->copy8_div2_src3linear_crop(source1,source2,source3,
+ dest,inc);
+ }
+
+
+}
+
+
+void CopyFunctions::copy8_div4_src5linear_crop(unsigned char* source1,
+ unsigned char* source2,
+ unsigned char* source3,
+ unsigned char* source4,
+ short int* source5,
+ unsigned char* dest,int inc) {
+
+ int rr;
+
+ for (rr = 0; rr < 8; rr++) {
+ dest[0]=cm[((int) (source1[0]+source2[0]+source3[0]+source4[0]+2) >> 2) + source5[0]];
+ dest[1]=cm[((int) (source1[1]+source2[1]+source3[1]+source4[1]+2) >> 2) + source5[1]];
+ dest[2]=cm[((int) (source1[2]+source2[2]+source3[2]+source4[2]+2) >> 2) + source5[2]];
+ dest[3]=cm[((int) (source1[3]+source2[3]+source3[3]+source4[3]+2) >> 2) + source5[3]];
+ dest[4]=cm[((int) (source1[4]+source2[4]+source3[4]+source4[4]+2) >> 2) + source5[4]];
+ dest[5]=cm[((int) (source1[5]+source2[5]+source3[5]+source4[5]+2) >> 2) + source5[5]];
+ dest[6]=cm[((int) (source1[6]+source2[6]+source3[6]+source4[6]+2) >> 2) + source5[6]];
+ dest[7]=cm[((int) (source1[7]+source2[7]+source3[7]+source4[7]+2) >> 2) + source5[7]];
+ dest +=inc;
+ source1 += inc;
+ source2 += inc;
+ source3 += inc;
+ source4 += inc;
+ source5 += 8;
+ }
+}
diff --git a/mpeglib/lib/mpegplay/copyFunctions.h b/mpeglib/lib/mpegplay/copyFunctions.h
new file mode 100644
index 00000000..a1436739
--- /dev/null
+++ b/mpeglib/lib/mpegplay/copyFunctions.h
@@ -0,0 +1,95 @@
+/*
+ stores heavily used copy functions (makes mmx support easier)
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#ifndef __COPYFUNCTIONS_H
+#define __COPYFUNCTIONS_H
+
+#define MAX_NEG_CROP 32768
+#define NUM_CROP_ENTRIES (2048+2*MAX_NEG_CROP)
+
+#include <iostream>
+#include "../util/mmx/mmx.h"
+
+extern "C" {
+#include <string.h>
+}
+
+#include "copyFunctions_mmx.h"
+
+
+class CopyFunctions {
+
+ unsigned char *cm;
+ int lmmx;
+ unsigned char* cropTbl;
+ CopyFunctions_ASM* copyFunctions_asm;
+
+ public:
+ CopyFunctions();
+ ~CopyFunctions();
+
+ /**
+ We make sure, that during the whole construcion block
+ we never (!!!) do float operations, thus we move
+ the time consumin emms call really at the end of
+ the whole reconstrucion/motion compensation
+ */
+
+ void startNOFloatSection();
+ void endNOFloatSection();
+
+ void copy8_byte(unsigned char* source1,
+ unsigned char* dest,int inc);
+
+ void copy8_word(unsigned short* source1,
+ unsigned short* dest,int inc);
+
+
+ void copy8_div2_nocrop(unsigned char* source1,
+ unsigned char* source2,
+ unsigned char* dest,int inc);
+
+ void copy8_div2_destlinear_nocrop(unsigned char* source1,
+ unsigned char* source2,
+ unsigned char* dest,int inc);
+
+ void copy16_div2_destlinear_nocrop(unsigned char* source1,
+ unsigned char* source2,
+ unsigned char* dest,int inc);
+
+
+ void copy8_div4_nocrop(unsigned char* source1,
+ unsigned char* source2,
+ unsigned char* source3,
+ unsigned char* source4,
+ unsigned char* dest,int inc);
+
+ void copy8_src1linear_crop(short* source1,unsigned char* dest,int inc);
+
+ void copy8_src2linear_crop(unsigned char* source1,
+ short int* source2,
+ unsigned char* dest,int inc);
+ void copy8_div2_src3linear_crop(unsigned char* source1,
+ unsigned char* source2,
+ short int* source3,
+ unsigned char* dest,int inc);
+
+ void copy8_div4_src5linear_crop(unsigned char* source1,
+ unsigned char* source2,
+ unsigned char* source3,
+ unsigned char* source4,
+ short int* source5,
+ unsigned char* dest,int inc);
+
+};
+#endif
diff --git a/mpeglib/lib/mpegplay/copyFunctions_asm.cpp b/mpeglib/lib/mpegplay/copyFunctions_asm.cpp
new file mode 100644
index 00000000..40d4580f
--- /dev/null
+++ b/mpeglib/lib/mpegplay/copyFunctions_asm.cpp
@@ -0,0 +1,90 @@
+/*
+ copyfunctions base class
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "copyFunctions_asm.h"
+
+using namespace std;
+
+CopyFunctions_ASM::CopyFunctions_ASM() {
+}
+
+CopyFunctions_ASM::~CopyFunctions_ASM() {
+}
+
+
+int CopyFunctions_ASM::support() {
+ return false;
+}
+
+
+void CopyFunctions_ASM::startNOFloatSection() {
+}
+
+
+void CopyFunctions_ASM::endNOFloatSection() {
+}
+
+void CopyFunctions_ASM::copy8_byte(unsigned char* ,
+ unsigned char* ,int ) {
+ cout << "CopyFunctions_ASM::copy8_byte not implemented"<<endl;
+}
+
+
+void CopyFunctions_ASM::copy8_src1linear_crop(short* ,
+ unsigned char* ,int ) {
+ cout << "CopyFunctions_ASM:: not implemented"<<endl;
+}
+
+
+
+
+void CopyFunctions_ASM::copy8_div2_nocrop(unsigned char* ,
+ unsigned char* ,
+ unsigned char* ,int ) {
+ cout << "CopyFunctions_ASM:: copy8_div2_nocrop not implemented"<<endl;
+}
+
+
+void CopyFunctions_ASM::copy8_div2_destlinear_nocrop(unsigned char* ,
+ unsigned char* ,
+ unsigned char* ,
+ int ) {
+ cout << "CopyFunctions_ASM:: copy8_div2_destlinear_nocrop not implemented"
+ <<endl;
+}
+
+
+void CopyFunctions_ASM::copy16_div2_destlinear_nocrop(unsigned char* ,
+ unsigned char* ,
+ unsigned char* ,
+ int ) {
+ cout << "CopyFunctions_ASM:: copy16_div2_destlinear_nocrop not implemented"
+ <<endl;
+}
+
+
+void CopyFunctions_ASM::copy8_src2linear_crop(unsigned char* ,
+ short int* ,
+ unsigned char* ,int ) {
+ cout << "CopyFunctions_ASM:: copy8_src2linear_crop not implemented"<<endl;
+}
+
+
+void CopyFunctions_ASM::copy8_div2_src3linear_crop(unsigned char* ,
+ unsigned char* ,
+ short int* ,
+ unsigned char* ,
+ int ) {
+ cout << "CopyFunctions_ASM:: copy8_div2_src3linear_crop not implemented"
+ <<endl;
+}
diff --git a/mpeglib/lib/mpegplay/copyFunctions_asm.h b/mpeglib/lib/mpegplay/copyFunctions_asm.h
new file mode 100644
index 00000000..1156345a
--- /dev/null
+++ b/mpeglib/lib/mpegplay/copyFunctions_asm.h
@@ -0,0 +1,61 @@
+/*
+ copyfunctions base class
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#ifndef __COPYFUNCTIONS_ASM_H
+#define __COPYFUNCTIONS_ASM_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <iostream>
+
+class CopyFunctions_ASM {
+
+ public:
+ CopyFunctions_ASM();
+ virtual ~CopyFunctions_ASM();
+
+ virtual int support();
+
+ virtual void startNOFloatSection();
+ virtual void endNOFloatSection();
+
+ virtual void copy8_byte(unsigned char* source1,
+ unsigned char* dest,int inc);
+
+ virtual void copy8_src1linear_crop(short* source1,
+ unsigned char* dest,int inc);
+
+ virtual void copy8_div2_nocrop(unsigned char* source1,
+ unsigned char* source2,
+ unsigned char* dest,int inc);
+
+ virtual void copy8_div2_destlinear_nocrop(unsigned char* source1,
+ unsigned char* source2,
+ unsigned char* dest,int inc);
+
+ virtual void copy16_div2_destlinear_nocrop(unsigned char* source1,
+ unsigned char* source2,
+ unsigned char* dest,int inc);
+
+ virtual void copy8_src2linear_crop(unsigned char* source1,
+ short int* source2,
+ unsigned char* dest,int inc);
+
+ virtual void copy8_div2_src3linear_crop(unsigned char* source1,
+ unsigned char* source2,
+ short int* source3,
+ unsigned char* dest,int inc);
+};
+#endif
diff --git a/mpeglib/lib/mpegplay/copyFunctions_mmx.cpp b/mpeglib/lib/mpegplay/copyFunctions_mmx.cpp
new file mode 100644
index 00000000..3e295e76
--- /dev/null
+++ b/mpeglib/lib/mpegplay/copyFunctions_mmx.cpp
@@ -0,0 +1,313 @@
+/*
+ copyfunctions implementation in mmx
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "copyFunctions_mmx.h"
+
+using namespace std;
+
+// mmx goodies
+static long ADD_1[] = {0x01010101, 0x01010101};
+static long ADDW_1[] = {0x00010001, 0x00010001};
+static long MASK_AND[] = {0x7f7f7f7f, 0x7f7f7f7f};
+
+void dummyCopyFunctions() {
+ cout << "ADD_1:"<<ADD_1<<endl;
+ cout << "ADDW_1:"<<ADDW_1<<endl;
+ cout << "MASK_AND:"<<MASK_AND<<endl;
+}
+
+CopyFunctions_MMX::CopyFunctions_MMX() {
+#ifdef INTEL
+ lmmx=mm_support();
+#else
+ lmmx=false;
+ cout << "no INTEL arch- disable MMX in copyFunctions"<<endl;
+#endif
+}
+
+
+CopyFunctions_MMX::~CopyFunctions_MMX() {
+}
+
+int CopyFunctions_MMX::support() {
+ return lmmx;
+}
+
+
+#if defined (__GNUC__) && defined (INTEL)
+
+void CopyFunctions_MMX::startNOFloatSection() {
+}
+
+
+void CopyFunctions_MMX::endNOFloatSection() {
+ emms();
+}
+
+
+
+void CopyFunctions_MMX::copy8_byte(unsigned char* source1,
+ unsigned char* dest,int inc) {
+ int rr=4;
+
+ asm (
+ "1:\n"
+ "movq (%0) ,%%mm0\n"
+ "leal (%0,%2) ,%0\n"
+ "movq (%0) ,%%mm1\n"
+ "leal (%0,%2) ,%0\n"
+
+ // Write
+ "movq %%mm0 ,(%1)\n"
+ "leal (%1,%2) ,%1\n"
+ "movq %%mm1 ,(%1)\n"
+ "leal (%1,%2) ,%1\n"
+
+ "decl %3\n"
+ "jnz 1b\n"
+ :
+ : "r"(source1),"r"(dest),"r"(inc),"r"(rr)
+ );
+}
+
+
+
+void CopyFunctions_MMX::copy8_src1linear_crop(short* source1,
+ unsigned char* dest,int inc) {
+
+ asm (
+ "movq (%1),%%mm0\n"
+ "packuswb 8(%1),%%mm0\n"
+ "movq %%mm0,(%0)\n"
+ "addl %2,%0\n"
+
+ "movq 16(%1),%%mm0\n"
+ "packuswb 24(%1),%%mm0\n"
+ "movq %%mm0,(%0)\n"
+ "addl %2,%0\n"
+
+ "movq 32(%1),%%mm0\n"
+ "packuswb 40(%1),%%mm0\n"
+ "movq %%mm0,(%0)\n"
+ "addl %2,%0\n"
+
+ "movq 48(%1),%%mm0\n"
+ "packuswb 56(%1),%%mm0\n"
+ "movq %%mm0,(%0)\n"
+ "addl %2,%0\n"
+
+ "movq 64(%1),%%mm0\n"
+ "packuswb 72(%1),%%mm0\n"
+ "movq %%mm0,(%0)\n"
+ "addl %2,%0\n"
+
+ "movq 80(%1),%%mm0\n"
+ "packuswb 88(%1),%%mm0\n"
+ "movq %%mm0,(%0)\n"
+ "addl %2,%0\n"
+
+ "movq 96(%1),%%mm0\n"
+ "packuswb 104(%1),%%mm0\n"
+ "movq %%mm0,(%0)\n"
+ "addl %2,%0\n"
+
+ "movq 112(%1),%%mm0\n"
+ "packuswb 120(%1),%%mm0\n"
+ "movq %%mm0,(%0)\n"
+ :
+ :"r" (dest), "r" (source1),"r" (inc)
+ );
+
+}
+
+
+
+void CopyFunctions_MMX::copy8_div2_nocrop(unsigned char* source1,
+ unsigned char* source2,
+ unsigned char* dest,int inc) {
+ int h=8;
+ asm (
+ "movq MASK_AND, %%mm5\n"
+ "movq ADD_1, %%mm6\n"
+ "1:\t"
+ "movq (%1), %%mm0\n" /* 8 s */
+ "movq (%4), %%mm1\n" /* 8 s +lx */
+ "psrlw $1,%%mm0\n"
+ "psrlw $1,%%mm1\n"
+ "pand %%mm5,%%mm0\n"
+ "pand %%mm5,%%mm1\n"
+ "paddusb %%mm1,%%mm0\n"
+ "addl %3,%1\n"
+ "paddusb %%mm6,%%mm0\n"
+ "addl %3,%4\n"
+ "movq %%mm0,(%2)\n"
+ "decl %0\n"
+ "leal (%2, %3), %2\n"
+ "jnz 1b\n"
+ :
+ : "c"(h), "r"(source1), "r"(dest), "r"(inc), "r"(source2)
+ );
+}
+
+
+void CopyFunctions_MMX::copy8_div2_destlinear_nocrop(unsigned char* source1,
+ unsigned char* source2,
+ unsigned char* dest,
+ int inc) {
+ int h=8;
+ asm (
+ "movq MASK_AND, %%mm5\n"
+ "1:\t"
+ "movq (%1), %%mm0\n" /* 8 s */
+ "movq (%4), %%mm1\n" /* 8 s +lx */
+ "psrlw $1,%%mm0\n"
+ "psrlw $1,%%mm1\n"
+ "pand %%mm5,%%mm0\n"
+ "pand %%mm5,%%mm1\n"
+ "paddusb %%mm1,%%mm0\n"
+ "addl %3,%1\n"
+ "addl %3,%4\n"
+ "movq %%mm0,(%2)\n"
+ "decl %0\n"
+ "leal 8(%2), %2\n"
+ "jnz 1b\n"
+ :
+ : "c"(h), "r"(source1), "r"(dest), "r"(inc), "r"(source2)
+ );
+}
+
+
+
+void CopyFunctions_MMX::copy16_div2_destlinear_nocrop(unsigned char* source1,
+ unsigned char* source2,
+ unsigned char* dest,
+ int inc) {
+ int h=16;
+ inc=inc-8;
+ asm (
+ "movq MASK_AND, %%mm5\n"
+ "1:\t"
+ "movq (%1), %%mm0\n" /* 8 s */
+ "movq (%4), %%mm1\n" /* 8 s +lx */
+ "psrlw $1,%%mm0\n"
+ "psrlw $1,%%mm1\n"
+ "pand %%mm5,%%mm0\n"
+ "pand %%mm5,%%mm1\n"
+ "paddusb %%mm1,%%mm0\n"
+ "leal 8(%1),%1\n"
+ "leal 8(%4),%4\n"
+ "movq %%mm0,(%2)\n"
+ "leal 8(%2),%2\n"
+
+ "movq (%1), %%mm0\n" /* 8 s */
+ "movq (%4), %%mm1\n" /* 8 s +lx */
+ "psrlw $1,%%mm0\n"
+ "psrlw $1,%%mm1\n"
+ "pand %%mm5,%%mm0\n"
+ "pand %%mm5,%%mm1\n"
+ "paddusb %%mm1,%%mm0\n"
+ "leal (%3,%1),%1\n"
+ "leal (%3,%4),%4\n"
+ "movq %%mm0,(%2)\n"
+ "leal 8(%2),%2\n"
+
+ "decl %0\n"
+ "jnz 1b\n"
+ :
+ : "c"(h), "r"(source1), "r"(dest), "r"(inc), "r"(source2)
+ );
+}
+
+
+void CopyFunctions_MMX::copy8_src2linear_crop(unsigned char* source1,
+ short int* source2,
+ unsigned char* dest,int inc) {
+
+ int rr=8;
+ // buggy
+
+ asm (
+ ".align 32\n"
+ "pxor %%mm2 ,%%mm2\n" // 0 0 0 0 0 0 0 0
+ "1:\n"
+ "movq (%0) ,%%mm0\n" // s1_7 s1_6 s1_5 s1_4 s1_3 s1_2 s1_1 s1_0
+ "movq (%0) ,%%mm4\n" // s1_7 s1_6 s1_5 s1_4 s1_3 s1_2 s1_1 s1_0
+ "punpckhbw %%mm2 ,%%mm0\n" // 0 s1_7 0 s1_6 0 s1_5 0 s1_4
+ "punpcklbw %%mm2 ,%%mm4\n" // 0 s1_3 0 s1_2 0 s1_1 0 s1_0
+ "movq (%1) ,%%mm1\n" // s23h s23l s22h s22l s21l s21h s20h s20l
+ "movq 8(%1) ,%%mm5\n" // s27h s27l s26h s26l s25l s25h s24h s24l
+ "paddw %%mm0 ,%%mm5\n" // mm4=mm4 + s3_0..3
+ "paddw %%mm4 ,%%mm1\n" // mm0=mm0 + s3_4..7
+ "packuswb %%mm5 ,%%mm1\n" // cm[...]
+
+ "movq %%mm1 ,(%2)\n" // wrote out
+
+ "leal (%0,%3), %0\n" // source1+=inc
+ "leal 16(%1) , %1\n" // source2+=inc
+ "leal (%2,%3), %2\n" // dest+=inc
+ "decl %4\n"
+ "jnz 1b\n"
+ //"emms\n"
+ :
+ : "r"(source1), "r"(source2), "r"(dest),"r"(inc),"r"(rr)
+ );
+}
+
+
+void CopyFunctions_MMX::copy8_div2_src3linear_crop(unsigned char* source1,
+ unsigned char* source2,
+ short int* source3,
+ unsigned char* dest,
+ int inc){
+ // buggy
+ int rr=8;
+
+ asm (
+ "pxor %%mm2 ,%%mm2\n" // 0 0 0 0 0 0 0 0
+ "pxor %%mm3 ,%%mm3\n" // 0 0 0 0 0 0 0 0
+ "movq ADDW_1,%%mm6\n" // 0 1 0 1 0 1 0 1
+ "1:\n"
+ "movq (%0) ,%%mm0\n" // s1_7 s1_6 s1_5 s1_4 s1_3 s1_2 s1_1 s1_0
+ "movq (%1) ,%%mm1\n" // s2_7 s2_6 s2_5 s2_4 s2_3 s2_2 s2_1 s2_0
+ "movq %%mm0 ,%%mm4\n" // s1_7 s1_6 s1_5 s1_4 s1_3 s1_2 s1_1 s1_0
+ "movq %%mm1 ,%%mm5\n" // s2_7 s2_6 s2_5 s2_4 s2_3 s2_2 s2_1 s2_0
+ "punpckhbw %%mm2 ,%%mm0\n" // 0 s1_7 0 s1_6 0 s1_5 0 s1_4
+ "punpckhbw %%mm3 ,%%mm1\n" // 0 s2_7 0 s2_6 0 s2_5 0 s2_4
+ "punpcklbw %%mm2 ,%%mm4\n" // 0 s1_3 0 s1_2 0 s1_1 0 s1_0
+ "punpcklbw %%mm3 ,%%mm5\n" // 0 s2_3 0 s2_2 0 s2_1 0 s2_0
+ "paddusw %%mm4 ,%%mm5\n" // mm5=s1_0..3 + s2_0..3
+ "paddusw %%mm0 ,%%mm1\n" // mm1=s1_4..7 + s2_4..7
+ "paddusw %%mm6 ,%%mm5\n" // mm5=mm5 + 1
+ "paddusw %%mm6 ,%%mm1\n" // mm1=mm1 + 1
+ "psraw $1 ,%%mm1\n" // mm1=mm1/2
+ "psraw $1 ,%%mm5\n" // mm5=mm5/2
+ "movq (%2) ,%%mm0\n" // s33h s33l s32h s32l s31l s31h s30h s30l
+ "movq 8(%2) ,%%mm4\n" // s37h s37l s36h s36l s35l s35h s34h s34l
+ "paddw %%mm0 ,%%mm5\n" // mm5=mm5 + s3_0..3
+ "paddw %%mm4 ,%%mm1\n" // mm1=mm1 + s3_4..7
+ "packuswb %%mm1 ,%%mm5\n" // cm[...]
+ "movq %%mm5 ,(%3)\n" // wrote out
+ "leal (%0,%4), %0\n" // source1+=inc
+ "leal (%1,%4), %1\n" // source2+=inc
+ "addl $16 ,%2 \n" // source3+8
+ "leal (%3,%4), %3\n" // dest+=inc
+ "decl %5\n"
+ "jnz 1b\n"
+ :
+ : "r"(source1), "r"(source2), "r"(source3),
+ "r"(dest),"r"(inc),"m"(rr)
+ );
+}
+
+
+#endif
diff --git a/mpeglib/lib/mpegplay/copyFunctions_mmx.h b/mpeglib/lib/mpegplay/copyFunctions_mmx.h
new file mode 100644
index 00000000..36e157be
--- /dev/null
+++ b/mpeglib/lib/mpegplay/copyFunctions_mmx.h
@@ -0,0 +1,68 @@
+/*
+ copyfunctions implementation in mmx
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#ifndef __COPYFUNCTIONS_MMX_H
+#define __COPYFUNCTIONS_MMX_H
+
+#include "copyFunctions_asm.h"
+#include "../util/mmx/mmx.h"
+
+
+class CopyFunctions_MMX : public CopyFunctions_ASM {
+
+ int lmmx;
+
+ public:
+ CopyFunctions_MMX();
+ ~CopyFunctions_MMX();
+
+ int support();
+
+#if defined (__GNUC__) && defined (INTEL)
+
+ void startNOFloatSection();
+ void endNOFloatSection();
+
+
+ void copy8_byte(unsigned char* source1,
+ unsigned char* dest,int inc);
+
+ void copy8_src1linear_crop(short* source1,
+ unsigned char* dest,int inc);
+
+ void copy8_div2_nocrop(unsigned char* source1,
+ unsigned char* source2,
+ unsigned char* dest,int inc);
+
+ void copy8_div2_destlinear_nocrop(unsigned char* source1,
+ unsigned char* source2,
+ unsigned char* dest,int inc);
+
+ void copy16_div2_destlinear_nocrop(unsigned char* source1,
+ unsigned char* source2,
+ unsigned char* dest,int inc);
+
+ void copy8_src2linear_crop(unsigned char* source1,
+ short int* source2,
+ unsigned char* dest,int inc);
+
+ void copy8_div2_src3linear_crop(unsigned char* source1,
+ unsigned char* source2,
+ short int* source3,
+ unsigned char* dest,int inc);
+
+#endif
+
+};
+#endif
+
diff --git a/mpeglib/lib/mpegplay/decoderClass.cpp b/mpeglib/lib/mpegplay/decoderClass.cpp
new file mode 100644
index 00000000..e259c8e6
--- /dev/null
+++ b/mpeglib/lib/mpegplay/decoderClass.cpp
@@ -0,0 +1,893 @@
+/*
+ class for decoders
+ Copyright (C) 1999 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "decoderClass.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+
+#ifndef NDEBUG
+#define NDEBUG
+#endif
+#include <assert.h>
+
+
+#define DEBUG_DECODERCLASS(x)
+//#define DEBUG_DECODERCLASS(x) x
+
+/* Array mapping zigzag to array pointer offset. */
+
+
+static const int zigzag_direct_nommx[64] = {
+ 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12,
+ 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35,
+ 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63};
+
+
+static const int zigzag_direct_mmx[64] = {
+
+ 0*8+0/* 0*/, 1*8+0/* 1*/, 0*8+1/* 8*/, 0*8+2/*16*/, 1*8+1/* 9*/, 2*8+0/* 2*/, 3*8+0/* 3*/, 2*8+1/*10*/,
+ 1*8+2/*17*/, 0*8+3/*24*/, 0*8+4/*32*/, 1*8+3/*25*/, 2*8+2/*18*/, 3*8+1/*11*/, 4*8+0/* 4*/, 5*8+0/* 5*/,
+ 4*8+1/*12*/, 5*8+2/*19*/, 2*8+3/*26*/, 1*8+4/*33*/, 0*8+5/*40*/, 0*8+6/*48*/, 1*8+5/*41*/, 2*8+4/*34*/,
+ 3*8+3/*27*/, 4*8+2/*20*/, 5*8+1/*13*/, 6*8+0/* 6*/, 7*8+0/* 7*/, 6*8+1/*14*/, 5*8+2/*21*/, 4*8+3/*28*/,
+ 3*8+4/*35*/, 2*8+5/*42*/, 1*8+6/*49*/, 0*8+7/*56*/, 1*8+7/*57*/, 2*8+6/*50*/, 3*8+5/*43*/, 4*8+4/*36*/,
+ 5*8+3/*29*/, 6*8+2/*22*/, 7*8+1/*15*/, 7*8+2/*23*/, 6*8+3/*30*/, 5*8+4/*37*/, 4*8+5/*44*/, 3*8+6/*51*/,
+ 2*8+7/*58*/, 3*8+7/*59*/, 4*8+6/*52*/, 5*8+5/*45*/, 6*8+4/*38*/, 7*8+3/*31*/, 7*8+4/*39*/, 6*8+5/*46*/,
+ 7*8+6/*53*/, 4*8+7/*60*/, 5*8+7/*61*/, 6*8+6/*54*/, 7*8+5/*47*/, 7*8+6/*55*/, 6*8+7/*62*/, 7*8+7/*63*/
+};
+
+
+
+
+
+/* Bit masks used by bit i/o operations. */
+
+
+
+static unsigned int bitMask[] = {0xffffffff,0x7fffffff,0x3fffffff,0x1fffffff,
+ 0x0fffffff, 0x07ffffff, 0x03ffffff, 0x01ffffff,
+ 0x00ffffff, 0x007fffff, 0x003fffff, 0x001fffff,
+ 0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff,
+ 0x0000ffff, 0x00007fff, 0x00003fff, 0x00001fff,
+ 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff,
+ 0x000000ff, 0x0000007f, 0x0000003f, 0x0000001f,
+ 0x0000000f, 0x00000007, 0x00000003, 0x00000001};
+
+static unsigned int rBitMask[] = {0xffffffff,0xfffffffe,0xfffffffc,0xfffffff8,
+ 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,
+ 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,
+ 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,
+ 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,
+ 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,
+ 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,
+ 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000};
+
+static unsigned int bitTest[] = { 0x80000000,0x40000000,0x20000000,0x10000000,
+ 0x08000000, 0x04000000, 0x02000000, 0x01000000,
+ 0x00800000, 0x00400000, 0x00200000, 0x00100000,
+ 0x00080000, 0x00040000, 0x00020000, 0x00010000,
+ 0x00008000, 0x00004000, 0x00002000, 0x00001000,
+ 0x00000800, 0x00000400, 0x00000200, 0x00000100,
+ 0x00000080, 0x00000040, 0x00000020, 0x00000010,
+ 0x00000008, 0x00000004, 0x00000002, 0x00000001};
+
+
+
+
+
+DecoderClass::DecoderClass(VideoDecoder* vid_stream,
+ MpegVideoStream* mpegVideoStream) {
+
+ this->vid_stream=vid_stream;
+ this->mpegVideoStream=mpegVideoStream;
+
+
+#ifdef INTEL
+ lmmx=mm_support();
+#else
+ lmmx=false;
+ DEBUG_DECODERCLASS(cout << "no INTEL arch- disable MMX in decoderClass"<<endl;)
+
+#endif
+
+ if (lmmx==true) {
+ lmmx=4;
+ }
+
+ int i;
+ for(i=0;i<64;i++) {
+ zigzag_direct[i]=zigzag_direct_nommx[i];
+ }
+ if (lmmx) {
+ for(i=0;i<64;i++) {
+ // they are different !!!
+ zigzag_direct[i]=zigzag_direct_mmx[i];
+ }
+ }
+ for(i=64;i<256;i++) {
+ zigzag_direct[i]=0;
+ }
+ resetDCT();
+ reconptr = dct_recon[0];
+
+}
+
+
+DecoderClass::~DecoderClass() {
+}
+
+
+
+int DecoderClass::decodeDCTDCSizeLum() {
+ unsigned int macro_val;
+ unsigned int index;
+ index=mpegVideoStream->showBits(5);
+ if (index < 31) {
+ macro_val = dct_dc_size_luminance[index].value;
+ mpegVideoStream->flushBits(dct_dc_size_luminance[index].num_bits);
+ } else {
+ index=mpegVideoStream->showBits(9);
+ index -= 0x1f0;
+ macro_val = dct_dc_size_luminance1[index].value;
+ mpegVideoStream->flushBits(dct_dc_size_luminance1[index].num_bits);
+ }
+ return macro_val;
+}
+
+
+int DecoderClass::decodeDCTDCSizeChrom() {
+ unsigned int macro_val;
+ unsigned int index;
+ index=mpegVideoStream->showBits(5);
+ if (index < 31) {
+ macro_val = dct_dc_size_chrominance[index].value;
+ mpegVideoStream->flushBits(dct_dc_size_chrominance[index].num_bits);
+ }else {
+ index=mpegVideoStream->showBits(10);
+ index -= 0x3e0;
+ macro_val = dct_dc_size_chrominance1[index].value;
+ mpegVideoStream->flushBits(dct_dc_size_chrominance1[index].num_bits);
+ }
+ return macro_val;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DecodeMBAddrInc --
+ *
+ * Huffman DecoderClass for macro_block_address_increment; the location
+ * in which the result will be placed is being passed as argument.
+ * The decoded value is obtained by doing a table lookup on
+ * mb_addr_inc.
+ *
+ * Results:
+ * The decoded value for macro_block_address_increment or MPGDECODE_ERROR
+ * for unbound values will be placed in the location specified.
+ *
+ * Side effects:
+ * Bit stream is irreversibly parsed.
+ *
+ *--------------------------------------------------------------
+ */
+int DecoderClass::decodeMBAddrInc() {
+ unsigned int index;
+ int val;
+ index=mpegVideoStream->showBits(11);
+ val = mb_addr_inc[index].value;
+ mpegVideoStream->flushBits(mb_addr_inc[index].num_bits);
+ if (mb_addr_inc[index].num_bits==0) {
+ DEBUG_DECODERCLASS(cout<<"num_bits==0"<<endl;)
+ val=1;
+ }
+
+ if (val == -1) {
+ DEBUG_DECODERCLASS(cout <<"EROR: decodeMBAddrInc"<<endl;)
+ val=MB_STUFFING;
+ }
+ return val;
+
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DecodeMotionVectors --
+ *
+ * Huffman DecoderClass for the various motion vectors, including
+ * motion_horizontal_forward_code, motion_vertical_forward_code,
+ * motion_horizontal_backward_code, motion_vertical_backward_code.
+ * Location where the decoded result will be placed is being passed
+ * as argument. The decoded values are obtained by doing a table
+ * lookup on motion_vectors.
+ *
+ * Results:
+ * The decoded value for the motion vector or MPGDECODE_ERROR for unbound
+ * values will be placed in the location specified.
+ *
+ * Side effects:
+ * Bit stream is irreversibly parsed.
+ *
+ *--------------------------------------------------------------
+ */
+int DecoderClass::decodeMotionVectors() {
+ unsigned int index;
+ int value;
+ index=mpegVideoStream->showBits(11);
+ value = motion_vectors[index].code;
+
+ mpegVideoStream->flushBits(motion_vectors[index].num_bits);
+ return value;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DecodeCBP --
+ *
+ * Huffman DecoderClass for coded_block_pattern; location in which the
+ * decoded result will be placed is being passed as argument. The
+ * decoded values are obtained by doing a table lookup on
+ * coded_block_pattern.
+ *
+ * Results:
+ * The decoded value for coded_block_pattern or MPGDECODE_ERROR for unbound
+ * values will be placed in the location specified.
+ *
+ * Side effects:
+ * Bit stream is irreversibly parsed.
+ *
+ *--------------------------------------------------------------
+ */
+int DecoderClass::decodeCBP() {
+ unsigned int index;
+ unsigned int coded_bp;
+ index=mpegVideoStream->showBits(9);
+ coded_bp = coded_block_pattern[index].cbp;
+ mpegVideoStream->flushBits(coded_block_pattern[index].num_bits);
+ return coded_bp;
+}
+
+
+
+
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DecodeMBTypeB --
+ *
+ * Huffman Decoder for macro_block_type in bidirectionally-coded
+ * pictures;locations in which the decoded results: macroblock_quant,
+ * macroblock_motion_forward, macro_block_motion_backward,
+ * macroblock_pattern, macro_block_intra, will be placed are
+ * being passed as argument. The decoded values are obtained by
+ * doing a table lookup on mb_type_B.
+ *
+ * Results:
+ * The various decoded values for macro_block_type in
+ * bidirectionally-coded pictures or MPGDECODE_ERROR for unbound values will
+ * be placed in the locations specified.
+ *
+ * Side effects:
+ * Bit stream is irreversibly parsed.
+ *
+ *--------------------------------------------------------------
+ */
+void DecoderClass::decodeMBTypeB(int& quant,int& motion_fwd,
+ int& motion_bwd,int& pat,int& intra){
+ unsigned int index;
+
+ index=mpegVideoStream->showBits(6);
+
+ quant = mb_type_B[index].mb_quant;
+ motion_fwd = mb_type_B[index].mb_motion_forward;
+ motion_bwd = mb_type_B[index].mb_motion_backward;
+ pat = mb_type_B[index].mb_pattern;
+ intra = mb_type_B[index].mb_intra;
+ if (index == 0) {
+ DEBUG_DECODERCLASS(cout << "error in decodeMBTypeB"<<endl;)
+ }
+ mpegVideoStream->flushBits(mb_type_B[index].num_bits);
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DecodeMBTypeI --
+ *
+ * Huffman Decoder for macro_block_type in intra-coded pictures;
+ * locations in which the decoded results: macroblock_quant,
+ * macroblock_motion_forward, macro_block_motion_backward,
+ * macroblock_pattern, macro_block_intra, will be placed are
+ * being passed as argument.
+ *
+ * Results:
+ * The various decoded values for macro_block_type in intra-coded
+ * pictures or MPGDECODE_ERROR for unbound values will be placed in the
+ * locations specified.
+ *
+ * Side effects:
+ * Bit stream is irreversibly parsed.
+ *
+ *--------------------------------------------------------------
+ */
+void DecoderClass::decodeMBTypeI(int& quant,int& motion_fwd,
+ int& motion_bwd,int& pat,int& intra) {
+
+ unsigned int index;
+ static int quantTbl[4] = {MPGDECODE_ERROR, 1, 0, 0};
+
+ index=mpegVideoStream->showBits(2);
+
+ motion_fwd = 0;
+ motion_bwd = 0;
+ pat = 0;
+ intra = 1;
+ quant = quantTbl[index];
+ if (quant == MPGDECODE_ERROR) {
+ DEBUG_DECODERCLASS(cout << "decodeMBTypeI Error"<<endl;)
+ }
+ if (index) {
+ mpegVideoStream->flushBits (1 + quant);
+ }
+
+}
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DecodeMBTypeP --
+ *
+ * Huffman Decoder for macro_block_type in predictive-coded pictures;
+ * locations in which the decoded results: macroblock_quant,
+ * macroblock_motion_forward, macro_block_motion_backward,
+ * macroblock_pattern, macro_block_intra, will be placed are
+ * being passed as argument. The decoded values are obtained by
+ * doing a table lookup on mb_type_P.
+ *
+ * Results:
+ * The various decoded values for macro_block_type in
+ * predictive-coded pictures or MPGDECODE_ERROR for unbound values will be
+ * placed in the locations specified.
+ *
+ * Side effects:
+ * Bit stream is irreversibly parsed.
+ *
+ *--------------------------------------------------------------
+ */
+void DecoderClass::decodeMBTypeP(int& quant,int& motion_fwd,
+ int& motion_bwd,int& pat,int& intra) {
+
+ unsigned int index;
+
+ index=mpegVideoStream->showBits(6);
+
+ quant = mb_type_P[index].mb_quant;
+ motion_fwd = mb_type_P[index].mb_motion_forward;
+ motion_bwd = mb_type_P[index].mb_motion_backward;
+ pat = mb_type_P[index].mb_pattern;
+ intra = mb_type_P[index].mb_intra;
+ if (index == 0) {
+ DEBUG_DECODERCLASS(cout << "error in decodeMBTypeP"<<endl;)
+ }
+ mpegVideoStream->flushBits(mb_type_P[index].num_bits);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * decodeDCTCoeff --
+ *
+ * Huffman Decoder for dct_coeff_first and dct_coeff_next;
+ * locations where the results of decoding: run and level, are to
+ * be placed and also the type of DCT coefficients, either
+ * dct_coeff_first or dct_coeff_next, are being passed as argument.
+ *
+ * The decoder first examines the next 8 bits in the input stream,
+ * and perform according to the following cases:
+ *
+ * '0000 0000' - examine 8 more bits (i.e. 16 bits total) and
+ * perform a table lookup on dct_coeff_tbl_0.
+ * One more bit is then examined to determine the sign
+ * of level.
+ *
+ * '0000 0001' - examine 4 more bits (i.e. 12 bits total) and
+ * perform a table lookup on dct_coeff_tbl_1.
+ * One more bit is then examined to determine the sign
+ * of level.
+ *
+ * '0000 0010' - examine 2 more bits (i.e. 10 bits total) and
+ * perform a table lookup on dct_coeff_tbl_2.
+ * One more bit is then examined to determine the sign
+ * of level.
+ *
+ * '0000 0011' - examine 2 more bits (i.e. 10 bits total) and
+ * perform a table lookup on dct_coeff_tbl_3.
+ * One more bit is then examined to determine the sign
+ * of level.
+ *
+ * otherwise - perform a table lookup on dct_coeff_tbl. If the
+ * value of run is not ESCAPE, extract one more bit
+ * to determine the sign of level; otherwise 6 more
+ * bits will be extracted to obtain the actual value
+ * of run , and then 8 or 16 bits to get the value of level.
+ *
+ *
+ *
+ * Results:
+ * The decoded values of run and level or MPGDECODE_ERROR
+ * for unbound values
+ * are placed in the locations specified.
+ *
+ * Side effects:
+ * Bit stream is irreversibly parsed.
+ *
+ *--------------------------------------------------------------
+ */
+
+void DecoderClass::decodeDCTCoeff(unsigned short int* dct_coeff_tbl,
+ unsigned RUNTYPE& run,int& level) {
+
+
+ unsigned int temp, index;
+ unsigned int value, next32bits, flushed;
+
+ /*
+ * Grab the next 32 bits and use it to improve performance of
+ * getting the bits to parse. Thus, calls are translated as:
+ *
+ * show_bitsX <--> next32bits >> (32-X)
+ * get_bitsX <--> val = next32bits >> (32-flushed-X);
+ * flushed += X;
+ * next32bits &= bitMask[flushed];
+ * flush_bitsX <--> flushed += X;
+ * next32bits &= bitMask[flushed];
+ *
+ */
+ next32bits=mpegVideoStream->showBits32();
+
+ flushed = 0;
+
+ /* show_bits8(index); */
+ index = next32bits >> 24;
+
+ if (index > 3) {
+ value = dct_coeff_tbl[index];
+ run = (value & RUN_MASK) >> RUN_SHIFT;
+ if (run == END_OF_BLOCK) {
+ level = END_OF_BLOCK;
+ }
+ else {
+ /* num_bits = (value & NUM_MASK) + 1; */
+ /* flush_bits(num_bits); */
+ flushed = (value & NUM_MASK) + 1;
+ next32bits &= bitMask[flushed];
+ if (run != ESCAPE) {
+ level = (value & LEVEL_MASK) >> LEVEL_SHIFT;
+ /* get_bits1(value); */
+ /* if (value) *level = -*level; */
+ if (next32bits >> (31-flushed)) level = -level;
+ flushed++;
+ /* next32bits &= bitMask[flushed]; last op before update */
+ }
+ else { /* *run == ESCAPE */
+ /* get_bits14(temp); */
+ temp = next32bits >> (18-flushed);
+ flushed += 14;
+ next32bits &= bitMask[flushed];
+ run = temp >> 8;
+ temp &= 0xff;
+ if (temp == 0) {
+ /* get_bits8(*level); */
+ level = next32bits >> (24-flushed);
+ flushed += 8;
+ /* next32bits &= bitMask[flushed]; last op before update */
+ assert(level >= 128);
+ } else if (temp != 128) {
+ /* Grab sign bit */
+ level = ((int) (temp << 24)) >> 24;
+ } else {
+ /* get_bits8(*level); */
+ level = next32bits >> (24-flushed);
+ flushed += 8;
+ /* next32bits &= bitMask[flushed]; last op before update */
+ level = level - 256;
+ assert(level <= -128 && level >= -255);
+ }
+ }
+ /* Update bitstream... */
+ mpegVideoStream->flushBitsDirect(flushed);
+ }
+ }
+ else {
+ if (index == 2) {
+ /* show_bits10(index); */
+ index = next32bits >> 22;
+ value = dct_coeff_tbl_2[index & 3];
+ }
+ else if (index == 3) {
+ /* show_bits10(index); */
+ index = next32bits >> 22;
+ value = dct_coeff_tbl_3[index & 3];
+ }
+ else if (index) { /* index == 1 */
+ /* show_bits12(index); */
+ index = next32bits >> 20;
+ value = dct_coeff_tbl_1[index & 15];
+ }
+ else { /* index == 0 */
+ /* show_bits16(index); */
+ index = next32bits >> 16;
+ value = dct_coeff_tbl_0[index & 255];
+ }
+ run = (value & RUN_MASK) >> RUN_SHIFT;
+ level = (value & LEVEL_MASK) >> LEVEL_SHIFT;
+
+ /*
+ * Fold these operations together to make it fast...
+ */
+ /* num_bits = (value & NUM_MASK) + 1; */
+ /* flush_bits(num_bits); */
+ /* get_bits1(value); */
+ /* if (value) *level = -*level; */
+
+ flushed = (value & NUM_MASK) + 2;
+ if ((next32bits >> (32-flushed)) & 0x1) level = -level;
+
+ /* Update bitstream ... */
+ mpegVideoStream->flushBitsDirect(flushed);
+
+ }
+
+}
+
+
+void DecoderClass::resetDCT() {
+ /* Reset past dct dc y, cr, and cb values. */
+
+ dct_dc_y_past = 1024 << 3;
+ dct_dc_cr_past = 1024 << 3;
+ dct_dc_cb_past = 1024 << 3;
+
+}
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ParseReconBlock --
+ *
+ * Parse values for block structure from bitstream.
+ * n is an indication of the position of the block within
+ * the macroblock (i.e. 0-5) and indicates the type of
+ * block (i.e. luminance or chrominance). Reconstructs
+ * coefficients from values parsed and puts in
+ * block.dct_recon array in vid stream structure.
+ * sparseFlag is set when the block contains only one
+ * coeffictient and is used by the IDCT.
+ *
+ * Results:
+ *
+ *
+ * Side effects:
+ * Bit stream irreversibly parsed.
+ *
+ *--------------------------------------------------------------
+ */
+
+
+void DecoderClass::ParseReconBlock(int& n,int& mb_intra,
+ unsigned int& qscale,
+ int& lflag,
+ unsigned int* iqmatrixptr,
+ unsigned int* niqmatrixptr) {
+
+
+
+
+ int coeffCount=0;
+ if (mpegVideoStream->hasBytes(512) == false) {
+ DEBUG_DECODERCLASS(cout << "cannot get 512 raw bytes"<<endl;)
+ return;
+ }
+
+ {
+ /*
+ * Copy the VideoDecoder fields curBits, bitOffset, and bitBuffer
+ * into local variables with the same names, so the macros use the
+ * local variables instead. This allows register allocation and
+ * can provide 1-2 fps speedup. On machines with not so many registers,
+ * don't do this.
+ */
+ int size, pos, coeff;
+ int level;
+ unsigned RUNTYPE run;
+ unsigned RUNTYPE i;
+
+
+ memset((char *) dct_recon, 0, 64*sizeof(short int));
+
+ if (mb_intra) {
+
+ if (n < 4) {
+
+ /*
+ * Get the luminance bits. This code has been hand optimized to
+ * get by the normal bit parsing routines. We get some speedup
+ * by grabbing the next 16 bits and parsing things locally.
+ * Thus, calls are translated as:
+ *
+ * show_bitsX <--> next16bits >> (16-X)
+ * get_bitsX <--> val = next16bits >> (16-flushed-X);
+ * flushed += X;
+ * next16bits &= bitMask[flushed];
+ * flush_bitsX <--> flushed += X;
+ * next16bits &= bitMask[flushed];
+ *
+ * I've streamlined the code a lot, so that we don't have to mask
+ * out the low order bits and a few of the extra adds are removed.
+ * bsmith
+ */
+ unsigned int next16bits, index, flushed;
+ next16bits=mpegVideoStream->showBits16();
+
+ index = next16bits >> (16-5);
+ if (index < 31) {
+ size = dct_dc_size_luminance[index].value;
+ flushed = dct_dc_size_luminance[index].num_bits;
+ } else {
+ index = next16bits >> (16-9);
+ index -= 0x1f0;
+ size = dct_dc_size_luminance1[index].value;
+ flushed = dct_dc_size_luminance1[index].num_bits;
+ }
+ next16bits &= bitMask[(16+flushed)&0x1f];
+ if (size != 0) {
+ flushed += size;
+ coeff = next16bits >> (16-flushed);
+ if (!(coeff & bitTest[32-size])) {
+ coeff++;
+ coeff|= rBitMask[size&0x1f];
+ }
+ coeff <<= 3;
+ } else {
+ coeff = 0;
+ }
+ mpegVideoStream->flushBitsDirect(flushed);
+
+ if ( (n == 0) && (lflag) ) {
+ coeff += 1024;
+ } else {
+ coeff += dct_dc_y_past;
+ }
+ dct_dc_y_past = coeff;
+
+ } else { /* n = 4 or 5 */
+ /*
+ * Get the chrominance bits. This code has been hand optimized to
+ * as described above
+ */
+
+ unsigned int next16bits, index, flushed;
+ next16bits=mpegVideoStream->showBits16();
+
+ index = next16bits >> (16-5);
+ if (index < 31) {
+ size = dct_dc_size_chrominance[index].value;
+ flushed = dct_dc_size_chrominance[index].num_bits;
+ } else {
+ index = next16bits >> (16-10);
+ index -= 0x3e0;
+ size = dct_dc_size_chrominance1[index].value;
+ flushed = dct_dc_size_chrominance1[index].num_bits;
+ }
+ next16bits &= bitMask[(16+flushed)&0x1f];
+
+ if (size != 0) {
+ flushed += size;
+ coeff = next16bits >> (16-flushed);
+ if (!(coeff & bitTest[32-size])) {
+ coeff++;
+ coeff|=rBitMask[size&0x1f];
+ }
+ coeff <<= 3;
+ } else {
+ coeff = 0;
+ }
+ mpegVideoStream->flushBitsDirect(flushed);
+
+ /* We test 5 first; a result of the mixup of Cr and Cb */
+
+ if (n == 5) {
+ if (lflag) {
+ coeff += 1024;
+ } else {
+ coeff += dct_dc_cr_past;
+ }
+ dct_dc_cr_past = coeff;
+ } else {
+ if (lflag) {
+ coeff += 1024;
+ } else {
+ coeff += dct_dc_cb_past;
+ }
+ dct_dc_cb_past = coeff;
+ }
+ }
+
+ coeff <<= lmmx;
+ reconptr[0] = coeff;
+
+ pos=0;
+ i = 0;
+ coeffCount = (coeff != 0);
+
+
+ // we never have d_types so there is no check
+
+
+ while(1) {
+ decodeDCTCoeff(dct_coeff_next,run,level);
+
+ if (run >=END_OF_BLOCK) {
+ break;
+ }
+ i++;
+ i+=run;
+ pos = zigzag_direct[i&0x3f];
+
+
+ coeff = (level * qscale * iqmatrixptr[pos]) >> 3 ;
+
+ if (level < 0) {
+ coeff += (1 - (coeff & 1));
+ } else {
+ coeff -= (1 - (coeff & 1));
+ }
+
+ coeff <<= lmmx;
+
+ reconptr[pos] = coeff;
+ coeffCount++;
+
+ }
+ mpegVideoStream->flushBitsDirect(2);
+
+ goto end;
+
+ } else { /* non-intra-coded macroblock */
+
+ decodeDCTCoeff(dct_coeff_first,run,level);
+ i = run;
+
+ pos = zigzag_direct[i&0x3f];
+
+ /* quantizes and oddifies each coefficient */
+ if (level < 0) {
+ coeff = ((level - 1) * qscale * niqmatrixptr[pos]) >>3;
+ if ((coeff & 1) == 0) {coeff++;}
+ } else {
+ coeff = ((level + 1) * qscale * niqmatrixptr[pos]) >>3;
+ coeff = (coeff-1) | 1;
+ }
+
+ coeff <<= lmmx;
+
+ reconptr[pos] = coeff;
+ coeffCount = (coeff!=0);
+
+ // we never have d_type pictures here, we do not support them
+
+ while(1) {
+ decodeDCTCoeff(dct_coeff_next,run,level);
+
+ if (run >= END_OF_BLOCK) {
+ break;
+ }
+ i++;
+ i+=run;
+ pos = zigzag_direct[i&0x3f];
+
+ if (level < 0) {
+ coeff = ((level - 1) * qscale * niqmatrixptr[pos]) >>3;
+ if ((coeff & 1) == 0) {coeff++;}
+ } else {
+ coeff = ((level + 1) * qscale * niqmatrixptr[pos]) >> 3;
+ coeff = (coeff-1) | 1;
+ }
+
+ coeff <<= lmmx;
+
+ reconptr[pos] = coeff;
+ coeffCount++;
+ } /* end while */
+
+ mpegVideoStream->flushBitsDirect(2);
+ goto end;
+ }
+
+ end:
+ if (coeffCount == 1) {
+ if (lmmx) {
+ emms();
+ reconptr[pos]>>=lmmx;
+ j_rev_dct_sparse (reconptr, pos);
+ //IDCT_mmx(reconptr);
+ } else {
+ j_rev_dct_sparse (reconptr, pos);
+ }
+
+ } else {
+
+ if (lmmx) {
+ IDCT_mmx(reconptr);
+ } else {
+ j_rev_dct(reconptr);
+ }
+
+ }
+ }
+
+ // we call this at the edn of the "critical sections"
+ /*
+ if (lmmx) {
+ emms();
+ }
+ */
+
+ return;
+
+}
+
+
+
+
+
+void DecoderClass::print() {
+ int i;
+ for(i=0;i<64;i++) {
+ printf(" %d ",zigzag_direct[i]);
+ }
+ printf("\n");
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/mpegplay/decoderClass.h b/mpeglib/lib/mpegplay/decoderClass.h
new file mode 100644
index 00000000..2e969edc
--- /dev/null
+++ b/mpeglib/lib/mpegplay/decoderClass.h
@@ -0,0 +1,96 @@
+/*
+ class for decoders
+ Copyright (C) 1999 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#ifndef __DECODERCLASS_H
+#define __DECODERCLASS_H
+
+
+
+#include "videoDecoder.h"
+#include "mpegVideoStream.h"
+#include "decoderTables.h"
+#include "slice.h"
+#include "proto.h"
+#include "../util/mmx/mmx.h"
+#include "mmxidct.h"
+#include "picture.h"
+
+/* Special values for DCT Coefficients */
+#define END_OF_BLOCK 62
+#define ESCAPE 61
+
+
+/* DCT coeff tables. */
+#define RUN_MASK 0xfc00
+#define LEVEL_MASK 0x03f0
+#define NUM_MASK 0x000f
+#define RUN_SHIFT 10
+#define LEVEL_SHIFT 4
+#define RUNTYPE char
+
+class DecoderClass {
+
+ int lmmx;
+ int zigzag_direct[256];
+
+ /* Block structure. */
+
+ short int dct_recon[8][8]; /* Reconstructed dct coeff matrix. */
+ int dct_dc_y_past; /* Past lum. dc dct coefficient. */
+ int dct_dc_cr_past; /* Past cr dc dct coefficient. */
+ int dct_dc_cb_past; /* Past cb dc dct coefficient. */
+ short int *reconptr; /* reconptr = dct_recon[0]; */
+
+ class VideoDecoder* vid_stream;
+ class MpegVideoStream* mpegVideoStream;
+ public:
+ DecoderClass(class VideoDecoder* vid_stream,
+ class MpegVideoStream* mpegVideoStream);
+ ~DecoderClass();
+ int decodeDCTDCSizeLum();
+ int decodeDCTDCSizeChrom();
+ int decodeMotionVectors();
+ int decodeCBP();
+
+ inline short int* getDCT() { return ((short int*) &(dct_recon[0][0]));}
+ void resetDCT();
+
+ void decodeMBTypeB(int& quant,int& motion_fwd,
+ int& motion_bwd,int& pat,int& intra);
+
+ void decodeMBTypeI(int& quant,int& motion_fwd,
+ int& motion_bwd,int& pat,int& intra);
+
+ void decodeMBTypeP(int& quant,int& motion_fwd,
+ int& motion_bwd,int& pat,int& intra);
+
+ void ParseReconBlock(int& n,int& mb_intra,unsigned int& quant_scale,
+ int& lflag,
+ unsigned int* iqmatrixptr,
+ unsigned int* niqmatrixptr);
+ int decodeMBAddrInc();
+
+
+ void print();
+
+ private:
+
+
+ inline void decodeDCTCoeff(unsigned short int* dct_coeff_tbl,
+ unsigned RUNTYPE& run,
+ int& level);
+
+
+
+};
+#endif
diff --git a/mpeglib/lib/mpegplay/decoderTables.cpp b/mpeglib/lib/mpegplay/decoderTables.cpp
new file mode 100644
index 00000000..9ada4901
--- /dev/null
+++ b/mpeglib/lib/mpegplay/decoderTables.cpp
@@ -0,0 +1,594 @@
+/*
+ * decoders.c
+ *
+ * This file contains all the routines for Huffman decoding required in
+ * MPEG
+ *
+ */
+
+
+#include "decoderTables.h"
+
+using namespace std;
+
+
+/* Decoding table for macroblock_address_increment */
+mb_addr_inc_entry mb_addr_inc[2048];
+
+/* Decoding table for macroblock_type in predictive-coded pictures */
+mb_type_entry mb_type_P[64];
+
+/* Decoding table for macroblock_type in bidirectionally-coded pictures */
+mb_type_entry mb_type_B[64];
+
+/* Decoding table for motion vectors */
+motion_vectors_entry motion_vectors[2048];
+
+/* Decoding table for coded_block_pattern */
+
+coded_block_pattern_entry coded_block_pattern[512] =
+{ {(unsigned int)MPGDECODE_ERROR, 0}, {(unsigned int)MPGDECODE_ERROR, 0}, {39, 9}, {27, 9}, {59, 9}, {55, 9}, {47, 9}, {31, 9},
+ {58, 8}, {58, 8}, {54, 8}, {54, 8}, {46, 8}, {46, 8}, {30, 8}, {30, 8},
+ {57, 8}, {57, 8}, {53, 8}, {53, 8}, {45, 8}, {45, 8}, {29, 8}, {29, 8},
+ {38, 8}, {38, 8}, {26, 8}, {26, 8}, {37, 8}, {37, 8}, {25, 8}, {25, 8},
+ {43, 8}, {43, 8}, {23, 8}, {23, 8}, {51, 8}, {51, 8}, {15, 8}, {15, 8},
+ {42, 8}, {42, 8}, {22, 8}, {22, 8}, {50, 8}, {50, 8}, {14, 8}, {14, 8},
+ {41, 8}, {41, 8}, {21, 8}, {21, 8}, {49, 8}, {49, 8}, {13, 8}, {13, 8},
+ {35, 8}, {35, 8}, {19, 8}, {19, 8}, {11, 8}, {11, 8}, {7, 8}, {7, 8},
+ {34, 7}, {34, 7}, {34, 7}, {34, 7}, {18, 7}, {18, 7}, {18, 7}, {18, 7},
+ {10, 7}, {10, 7}, {10, 7}, {10, 7}, {6, 7}, {6, 7}, {6, 7}, {6, 7},
+ {33, 7}, {33, 7}, {33, 7}, {33, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
+ {9, 7}, {9, 7}, {9, 7}, {9, 7}, {5, 7}, {5, 7}, {5, 7}, {5, 7},
+ {63, 6}, {63, 6}, {63, 6}, {63, 6}, {63, 6}, {63, 6}, {63, 6}, {63, 6},
+ {3, 6}, {3, 6}, {3, 6}, {3, 6}, {3, 6}, {3, 6}, {3, 6}, {3, 6},
+ {36, 6}, {36, 6}, {36, 6}, {36, 6}, {36, 6}, {36, 6}, {36, 6}, {36, 6},
+ {24, 6}, {24, 6}, {24, 6}, {24, 6}, {24, 6}, {24, 6}, {24, 6}, {24, 6},
+ {62, 5}, {62, 5}, {62, 5}, {62, 5}, {62, 5}, {62, 5}, {62, 5}, {62, 5},
+ {62, 5}, {62, 5}, {62, 5}, {62, 5}, {62, 5}, {62, 5}, {62, 5}, {62, 5},
+ {2, 5}, {2, 5}, {2, 5}, {2, 5}, {2, 5}, {2, 5}, {2, 5}, {2, 5},
+ {2, 5}, {2, 5}, {2, 5}, {2, 5}, {2, 5}, {2, 5}, {2, 5}, {2, 5},
+ {61, 5}, {61, 5}, {61, 5}, {61, 5}, {61, 5}, {61, 5}, {61, 5}, {61, 5},
+ {61, 5}, {61, 5}, {61, 5}, {61, 5}, {61, 5}, {61, 5}, {61, 5}, {61, 5},
+ {1, 5}, {1, 5}, {1, 5}, {1, 5}, {1, 5}, {1, 5}, {1, 5}, {1, 5},
+ {1, 5}, {1, 5}, {1, 5}, {1, 5}, {1, 5}, {1, 5}, {1, 5}, {1, 5},
+ {56, 5}, {56, 5}, {56, 5}, {56, 5}, {56, 5}, {56, 5}, {56, 5}, {56, 5},
+ {56, 5}, {56, 5}, {56, 5}, {56, 5}, {56, 5}, {56, 5}, {56, 5}, {56, 5},
+ {52, 5}, {52, 5}, {52, 5}, {52, 5}, {52, 5}, {52, 5}, {52, 5}, {52, 5},
+ {52, 5}, {52, 5}, {52, 5}, {52, 5}, {52, 5}, {52, 5}, {52, 5}, {52, 5},
+ {44, 5}, {44, 5}, {44, 5}, {44, 5}, {44, 5}, {44, 5}, {44, 5}, {44, 5},
+ {44, 5}, {44, 5}, {44, 5}, {44, 5}, {44, 5}, {44, 5}, {44, 5}, {44, 5},
+ {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5},
+ {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5},
+ {40, 5}, {40, 5}, {40, 5}, {40, 5}, {40, 5}, {40, 5}, {40, 5}, {40, 5},
+ {40, 5}, {40, 5}, {40, 5}, {40, 5}, {40, 5}, {40, 5}, {40, 5}, {40, 5},
+ {20, 5}, {20, 5}, {20, 5}, {20, 5}, {20, 5}, {20, 5}, {20, 5}, {20, 5},
+ {20, 5}, {20, 5}, {20, 5}, {20, 5}, {20, 5}, {20, 5}, {20, 5}, {20, 5},
+ {48, 5}, {48, 5}, {48, 5}, {48, 5}, {48, 5}, {48, 5}, {48, 5}, {48, 5},
+ {48, 5}, {48, 5}, {48, 5}, {48, 5}, {48, 5}, {48, 5}, {48, 5}, {48, 5},
+ {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},
+ {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},
+ {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4},
+ {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4},
+ {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4},
+ {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4},
+ {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4},
+ {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4},
+ {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4},
+ {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4},
+ {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4},
+ {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4},
+ {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4},
+ {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4},
+ {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4},
+ {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4},
+ {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4},
+ {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4},
+ {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3},
+ {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3},
+ {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3},
+ {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3},
+ {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3},
+ {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3},
+ {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3},
+ {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}
+};
+
+/* Decoding tables for dct_dc_size_luminance */
+dct_dc_size_entry dct_dc_size_luminance[32] =
+{ {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2},
+ {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2},
+ {0, 3}, {0, 3}, {0, 3}, {0, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3},
+ {4, 3}, {4, 3}, {4, 3}, {4, 3}, {5, 4}, {5, 4}, {6, 5}, {(unsigned int)MPGDECODE_ERROR, 0}
+};
+
+dct_dc_size_entry dct_dc_size_luminance1[16] =
+{ {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6},
+ {8, 7}, {8, 7}, {8, 7}, {8, 7}, {9, 8}, {9, 8}, {10, 9}, {11, 9}
+};
+
+/* Decoding table for dct_dc_size_chrominance */
+dct_dc_size_entry dct_dc_size_chrominance[32] =
+{ {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2},
+ {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2},
+ {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2},
+ {3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 4}, {4, 4}, {5, 5}, {(unsigned int)MPGDECODE_ERROR, 0}
+};
+
+dct_dc_size_entry dct_dc_size_chrominance1[32] =
+{ {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6},
+ {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6},
+ {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7},
+ {8, 8}, {8, 8}, {8, 8}, {8, 8}, {9, 9}, {9, 9}, {10, 10}, {11, 10}
+};
+
+/* DCT coeff tables. */
+
+unsigned short int dct_coeff_tbl_0[256] =
+{
+0xffff, 0xffff, 0xffff, 0xffff,
+0xffff, 0xffff, 0xffff, 0xffff,
+0xffff, 0xffff, 0xffff, 0xffff,
+0xffff, 0xffff, 0xffff, 0xffff,
+0x052f, 0x051f, 0x050f, 0x04ff,
+0x183f, 0x402f, 0x3c2f, 0x382f,
+0x342f, 0x302f, 0x2c2f, 0x7c1f,
+0x781f, 0x741f, 0x701f, 0x6c1f,
+0x028e, 0x028e, 0x027e, 0x027e,
+0x026e, 0x026e, 0x025e, 0x025e,
+0x024e, 0x024e, 0x023e, 0x023e,
+0x022e, 0x022e, 0x021e, 0x021e,
+0x020e, 0x020e, 0x04ee, 0x04ee,
+0x04de, 0x04de, 0x04ce, 0x04ce,
+0x04be, 0x04be, 0x04ae, 0x04ae,
+0x049e, 0x049e, 0x048e, 0x048e,
+0x01fd, 0x01fd, 0x01fd, 0x01fd,
+0x01ed, 0x01ed, 0x01ed, 0x01ed,
+0x01dd, 0x01dd, 0x01dd, 0x01dd,
+0x01cd, 0x01cd, 0x01cd, 0x01cd,
+0x01bd, 0x01bd, 0x01bd, 0x01bd,
+0x01ad, 0x01ad, 0x01ad, 0x01ad,
+0x019d, 0x019d, 0x019d, 0x019d,
+0x018d, 0x018d, 0x018d, 0x018d,
+0x017d, 0x017d, 0x017d, 0x017d,
+0x016d, 0x016d, 0x016d, 0x016d,
+0x015d, 0x015d, 0x015d, 0x015d,
+0x014d, 0x014d, 0x014d, 0x014d,
+0x013d, 0x013d, 0x013d, 0x013d,
+0x012d, 0x012d, 0x012d, 0x012d,
+0x011d, 0x011d, 0x011d, 0x011d,
+0x010d, 0x010d, 0x010d, 0x010d,
+0x282c, 0x282c, 0x282c, 0x282c,
+0x282c, 0x282c, 0x282c, 0x282c,
+0x242c, 0x242c, 0x242c, 0x242c,
+0x242c, 0x242c, 0x242c, 0x242c,
+0x143c, 0x143c, 0x143c, 0x143c,
+0x143c, 0x143c, 0x143c, 0x143c,
+0x0c4c, 0x0c4c, 0x0c4c, 0x0c4c,
+0x0c4c, 0x0c4c, 0x0c4c, 0x0c4c,
+0x085c, 0x085c, 0x085c, 0x085c,
+0x085c, 0x085c, 0x085c, 0x085c,
+0x047c, 0x047c, 0x047c, 0x047c,
+0x047c, 0x047c, 0x047c, 0x047c,
+0x046c, 0x046c, 0x046c, 0x046c,
+0x046c, 0x046c, 0x046c, 0x046c,
+0x00fc, 0x00fc, 0x00fc, 0x00fc,
+0x00fc, 0x00fc, 0x00fc, 0x00fc,
+0x00ec, 0x00ec, 0x00ec, 0x00ec,
+0x00ec, 0x00ec, 0x00ec, 0x00ec,
+0x00dc, 0x00dc, 0x00dc, 0x00dc,
+0x00dc, 0x00dc, 0x00dc, 0x00dc,
+0x00cc, 0x00cc, 0x00cc, 0x00cc,
+0x00cc, 0x00cc, 0x00cc, 0x00cc,
+0x681c, 0x681c, 0x681c, 0x681c,
+0x681c, 0x681c, 0x681c, 0x681c,
+0x641c, 0x641c, 0x641c, 0x641c,
+0x641c, 0x641c, 0x641c, 0x641c,
+0x601c, 0x601c, 0x601c, 0x601c,
+0x601c, 0x601c, 0x601c, 0x601c,
+0x5c1c, 0x5c1c, 0x5c1c, 0x5c1c,
+0x5c1c, 0x5c1c, 0x5c1c, 0x5c1c,
+0x581c, 0x581c, 0x581c, 0x581c,
+0x581c, 0x581c, 0x581c, 0x581c,
+};
+
+unsigned short int dct_coeff_tbl_1[16] =
+{
+0x00bb, 0x202b, 0x103b, 0x00ab,
+0x084b, 0x1c2b, 0x541b, 0x501b,
+0x009b, 0x4c1b, 0x481b, 0x045b,
+0x0c3b, 0x008b, 0x182b, 0x441b,
+};
+
+unsigned short int dct_coeff_tbl_2[4] =
+{
+0x4019, 0x1429, 0x0079, 0x0839,
+};
+
+unsigned short int dct_coeff_tbl_3[4] =
+{
+0x0449, 0x3c19, 0x3819, 0x1029,
+};
+
+unsigned short int dct_coeff_next[256] =
+{
+0xffff, 0xffff, 0xffff, 0xffff,
+0xf7d5, 0xf7d5, 0xf7d5, 0xf7d5,
+0x0826, 0x0826, 0x2416, 0x2416,
+0x0046, 0x0046, 0x2016, 0x2016,
+0x1c15, 0x1c15, 0x1c15, 0x1c15,
+0x1815, 0x1815, 0x1815, 0x1815,
+0x0425, 0x0425, 0x0425, 0x0425,
+0x1415, 0x1415, 0x1415, 0x1415,
+0x3417, 0x0067, 0x3017, 0x2c17,
+0x0c27, 0x0437, 0x0057, 0x2817,
+0x0034, 0x0034, 0x0034, 0x0034,
+0x0034, 0x0034, 0x0034, 0x0034,
+0x1014, 0x1014, 0x1014, 0x1014,
+0x1014, 0x1014, 0x1014, 0x1014,
+0x0c14, 0x0c14, 0x0c14, 0x0c14,
+0x0c14, 0x0c14, 0x0c14, 0x0c14,
+0x0023, 0x0023, 0x0023, 0x0023,
+0x0023, 0x0023, 0x0023, 0x0023,
+0x0023, 0x0023, 0x0023, 0x0023,
+0x0023, 0x0023, 0x0023, 0x0023,
+0x0813, 0x0813, 0x0813, 0x0813,
+0x0813, 0x0813, 0x0813, 0x0813,
+0x0813, 0x0813, 0x0813, 0x0813,
+0x0813, 0x0813, 0x0813, 0x0813,
+0x0412, 0x0412, 0x0412, 0x0412,
+0x0412, 0x0412, 0x0412, 0x0412,
+0x0412, 0x0412, 0x0412, 0x0412,
+0x0412, 0x0412, 0x0412, 0x0412,
+0x0412, 0x0412, 0x0412, 0x0412,
+0x0412, 0x0412, 0x0412, 0x0412,
+0x0412, 0x0412, 0x0412, 0x0412,
+0x0412, 0x0412, 0x0412, 0x0412,
+0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
+0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
+0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
+0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
+0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
+0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
+0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
+0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
+0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
+0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
+0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
+0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
+0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
+0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
+0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
+0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
+0x0011, 0x0011, 0x0011, 0x0011,
+0x0011, 0x0011, 0x0011, 0x0011,
+0x0011, 0x0011, 0x0011, 0x0011,
+0x0011, 0x0011, 0x0011, 0x0011,
+0x0011, 0x0011, 0x0011, 0x0011,
+0x0011, 0x0011, 0x0011, 0x0011,
+0x0011, 0x0011, 0x0011, 0x0011,
+0x0011, 0x0011, 0x0011, 0x0011,
+0x0011, 0x0011, 0x0011, 0x0011,
+0x0011, 0x0011, 0x0011, 0x0011,
+0x0011, 0x0011, 0x0011, 0x0011,
+0x0011, 0x0011, 0x0011, 0x0011,
+0x0011, 0x0011, 0x0011, 0x0011,
+0x0011, 0x0011, 0x0011, 0x0011,
+0x0011, 0x0011, 0x0011, 0x0011,
+0x0011, 0x0011, 0x0011, 0x0011,
+};
+
+unsigned short int dct_coeff_first[256] =
+{
+0xffff, 0xffff, 0xffff, 0xffff,
+0xf7d5, 0xf7d5, 0xf7d5, 0xf7d5,
+0x0826, 0x0826, 0x2416, 0x2416,
+0x0046, 0x0046, 0x2016, 0x2016,
+0x1c15, 0x1c15, 0x1c15, 0x1c15,
+0x1815, 0x1815, 0x1815, 0x1815,
+0x0425, 0x0425, 0x0425, 0x0425,
+0x1415, 0x1415, 0x1415, 0x1415,
+0x3417, 0x0067, 0x3017, 0x2c17,
+0x0c27, 0x0437, 0x0057, 0x2817,
+0x0034, 0x0034, 0x0034, 0x0034,
+0x0034, 0x0034, 0x0034, 0x0034,
+0x1014, 0x1014, 0x1014, 0x1014,
+0x1014, 0x1014, 0x1014, 0x1014,
+0x0c14, 0x0c14, 0x0c14, 0x0c14,
+0x0c14, 0x0c14, 0x0c14, 0x0c14,
+0x0023, 0x0023, 0x0023, 0x0023,
+0x0023, 0x0023, 0x0023, 0x0023,
+0x0023, 0x0023, 0x0023, 0x0023,
+0x0023, 0x0023, 0x0023, 0x0023,
+0x0813, 0x0813, 0x0813, 0x0813,
+0x0813, 0x0813, 0x0813, 0x0813,
+0x0813, 0x0813, 0x0813, 0x0813,
+0x0813, 0x0813, 0x0813, 0x0813,
+0x0412, 0x0412, 0x0412, 0x0412,
+0x0412, 0x0412, 0x0412, 0x0412,
+0x0412, 0x0412, 0x0412, 0x0412,
+0x0412, 0x0412, 0x0412, 0x0412,
+0x0412, 0x0412, 0x0412, 0x0412,
+0x0412, 0x0412, 0x0412, 0x0412,
+0x0412, 0x0412, 0x0412, 0x0412,
+0x0412, 0x0412, 0x0412, 0x0412,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+0x0010, 0x0010, 0x0010, 0x0010,
+};
+
+/* Macro for filling up the decoding table for mb_addr_inc */
+#define ASSIGN1(start, end, step, val, num) \
+ for (i = start; i < end; i+= step) { \
+ for (j = 0; j < step; j++) { \
+ mb_addr_inc[i+j].value = val; \
+ mb_addr_inc[i+j].num_bits = num; \
+ } \
+ val--; \
+ }
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * init_mb_addr_inc --
+ *
+ * Initialize the VLC decoding table for macro_block_address_increment
+ *
+ * Results:
+ * The decoding table for macro_block_address_increment will
+ * be filled; illegal values will be filled as MPGDECODE_ERROR.
+ *
+ * Side effects:
+ * The global array mb_addr_inc will be filled.
+ *
+ *--------------------------------------------------------------
+ */
+static void init_mb_addr_inc()
+{
+ int i, j, val;
+
+ for (i = 0; i < 8; i++) {
+ mb_addr_inc[i].value = MPGDECODE_ERROR;
+ mb_addr_inc[i].num_bits = 0;
+ }
+
+ mb_addr_inc[8].value = MACRO_BLOCK_ESCAPE;
+ mb_addr_inc[8].num_bits = 11;
+
+ for (i = 9; i < 15; i++) {
+ mb_addr_inc[i].value = MPGDECODE_ERROR;
+ mb_addr_inc[i].num_bits = 0;
+ }
+
+ mb_addr_inc[15].value = MACRO_BLOCK_STUFFING;
+ mb_addr_inc[15].num_bits = 11;
+
+ for (i = 16; i < 24; i++) {
+ mb_addr_inc[i].value = MPGDECODE_ERROR;
+ mb_addr_inc[i].num_bits = 0;
+ }
+
+ val = 33;
+
+ ASSIGN1(24, 36, 1, val, 11);
+ ASSIGN1(36, 48, 2, val, 10);
+ ASSIGN1(48, 96, 8, val, 8);
+ ASSIGN1(96, 128, 16, val, 7);
+ ASSIGN1(128, 256, 64, val, 5);
+ ASSIGN1(256, 512, 128, val, 4);
+ ASSIGN1(512, 1024, 256, val, 3);
+ ASSIGN1(1024, 2048, 1024, val, 1);
+}
+
+
+/* Macro for filling up the decoding table for mb_type */
+#define ASSIGN2(start, end, quant, motion_forward, motion_backward, pattern, intra, num, mb_type) \
+ for (i = start; i < end; i ++) { \
+ mb_type[i].mb_quant = quant; \
+ mb_type[i].mb_motion_forward = motion_forward; \
+ mb_type[i].mb_motion_backward = motion_backward; \
+ mb_type[i].mb_pattern = pattern; \
+ mb_type[i].mb_intra = intra; \
+ mb_type[i].num_bits = num; \
+ }
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * init_mb_type_P --
+ *
+ * Initialize the VLC decoding table for macro_block_type in
+ * predictive-coded pictures.
+ *
+ * Results:
+ * The decoding table for macro_block_type in predictive-coded
+ * pictures will be filled; illegal values will be filled as MPGDECODE_ERROR.
+ *
+ * Side effects:
+ * The global array mb_type_P will be filled.
+ *
+ *--------------------------------------------------------------
+ */
+static void init_mb_type_P() {
+ int i;
+
+ mb_type_P[0].mb_quant = mb_type_P[0].mb_motion_forward
+ = mb_type_P[0].mb_motion_backward = mb_type_P[0].mb_pattern
+ = mb_type_P[0].mb_intra = (unsigned int)MPGDECODE_ERROR;
+ mb_type_P[0].num_bits = 0;
+
+ ASSIGN2(1, 2, 1, 0, 0, 0, 1, 6, mb_type_P)
+ ASSIGN2(2, 4, 1, 0, 0, 1, 0, 5, mb_type_P)
+ ASSIGN2(4, 6, 1, 1, 0, 1, 0, 5, mb_type_P);
+ ASSIGN2(6, 8, 0, 0, 0, 0, 1, 5, mb_type_P);
+ ASSIGN2(8, 16, 0, 1, 0, 0, 0, 3, mb_type_P);
+ ASSIGN2(16, 32, 0, 0, 0, 1, 0, 2, mb_type_P);
+ ASSIGN2(32, 64, 0, 1, 0, 1, 0, 1, mb_type_P);
+}
+
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * init_mb_type_B --
+ *
+ * Initialize the VLC decoding table for macro_block_type in
+ * bidirectionally-coded pictures.
+ *
+ * Results:
+ * The decoding table for macro_block_type in bidirectionally-coded
+ * pictures will be filled; illegal values will be filled as MPGDECODE_ERROR.
+ *
+ * Side effects:
+ * The global array mb_type_B will be filled.
+ *
+ *--------------------------------------------------------------
+ */
+static void init_mb_type_B() {
+ int i;
+
+ mb_type_B[0].mb_quant = mb_type_B[0].mb_motion_forward
+ = mb_type_B[0].mb_motion_backward = mb_type_B[0].mb_pattern
+ = mb_type_B[0].mb_intra = (unsigned int) MPGDECODE_ERROR;
+ mb_type_B[0].num_bits = 0;
+
+ ASSIGN2(1, 2, 1, 0, 0, 0, 1, 6, mb_type_B);
+ ASSIGN2(2, 3, 1, 0, 1, 1, 0, 6, mb_type_B);
+ ASSIGN2(3, 4, 1, 1, 0, 1, 0, 6, mb_type_B);
+ ASSIGN2(4, 6, 1, 1, 1, 1, 0, 5, mb_type_B);
+ ASSIGN2(6, 8, 0, 0, 0, 0, 1, 5, mb_type_B);
+ ASSIGN2(8, 12, 0, 1, 0, 0, 0, 4, mb_type_B);
+ ASSIGN2(12, 16, 0, 1, 0, 1, 0, 4, mb_type_B);
+ ASSIGN2(16, 24, 0, 0, 1, 0, 0, 3, mb_type_B);
+ ASSIGN2(24, 32, 0, 0, 1, 1, 0, 3, mb_type_B);
+ ASSIGN2(32, 48, 0, 1, 1, 0, 0, 2, mb_type_B);
+ ASSIGN2(48, 64, 0, 1, 1, 1, 0, 2, mb_type_B);
+}
+
+
+/* Macro for filling up the decoding tables for motion_vectors */
+#define ASSIGN3(start, end, step, val, num) \
+ for (i = start; i < end; i+= step) { \
+ for (j = 0; j < step / 2; j++) { \
+ motion_vectors[i+j].code = val; \
+ motion_vectors[i+j].num_bits = num; \
+ } \
+ for (j = step / 2; j < step; j++) { \
+ motion_vectors[i+j].code = -val; \
+ motion_vectors[i+j].num_bits = num; \
+ } \
+ val--; \
+ }
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * init_motion_vectors --
+ *
+ * Initialize the VLC decoding table for the various motion
+ * vectors, including motion_horizontal_forward_code,
+ * motion_vertical_forward_code, motion_horizontal_backward_code,
+ * and motion_vertical_backward_code.
+ *
+ * Results:
+ * The decoding table for the motion vectors will be filled;
+ * illegal values will be filled as MPGDECODE_ERROR.
+ *
+ * Side effects:
+ * The global array motion_vector will be filled.
+ *
+ *--------------------------------------------------------------
+ */
+static void init_motion_vectors()
+{
+ int i, j, val = 16;
+
+ for (i = 0; i < 24; i++) {
+ motion_vectors[i].code = MPGDECODE_ERROR;
+ motion_vectors[i].num_bits = 0;
+ }
+
+ ASSIGN3(24, 36, 2, val, 11);
+ ASSIGN3(36, 48, 4, val, 10);
+ ASSIGN3(48, 96, 16, val, 8);
+ ASSIGN3(96, 128, 32, val, 7);
+ ASSIGN3(128, 256, 128, val, 5);
+ ASSIGN3(256, 512, 256, val, 4);
+ ASSIGN3(512, 1024, 512, val, 3);
+ ASSIGN3(1024, 2048, 1024, val, 1);
+}
+
+
+
+extern void init_pre_idct();
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * init_tables --
+ *
+ * Initialize all the tables for VLC decoding; this must be
+ * called when the system is set up before any decoding can
+ * take place.
+ *
+ * Results:
+ * All the decoding tables will be filled accordingly.
+ *
+ * Side effects:
+ * The corresponding global array for each decoding table
+ * will be filled.
+ *
+ *--------------------------------------------------------------
+ */
+void init_tables() {
+
+ init_mb_addr_inc();
+ init_mb_type_P();
+ init_mb_type_B();
+ init_motion_vectors();
+
+ if (qualityFlag) {
+ cout << "qualityFlag in init_tables float idct removed"<<endl;
+ }
+ init_pre_idct();
+
+}
+
+
diff --git a/mpeglib/lib/mpegplay/decoderTables.h b/mpeglib/lib/mpegplay/decoderTables.h
new file mode 100644
index 00000000..00b9b4f2
--- /dev/null
+++ b/mpeglib/lib/mpegplay/decoderTables.h
@@ -0,0 +1,110 @@
+/*
+ declares various tables to make things faster
+ Copyright (C) 1999 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+
+#ifndef __DECODERTABLES_H
+#define __DECODERTABLES_H
+
+#include "videoDecoder.h"
+#include "proto.h"
+
+/* Code for unbound values in decoding tables */
+#define MPGDECODE_ERROR (-1)
+
+#define MACRO_BLOCK_STUFFING 34
+#define MACRO_BLOCK_ESCAPE 35
+
+
+/* Structure for an entry in the decoding table of
+ * macroblock_address_increment */
+typedef struct {
+ int value; /* value for macroblock_address_increment */
+ int num_bits; /* length of the Huffman code */
+} mb_addr_inc_entry;
+
+
+/* Structure for an entry in the decoding table of macroblock_type */
+typedef struct {
+ unsigned int mb_quant; /* macroblock_quant */
+ unsigned int mb_motion_forward; /* macroblock_motion_forward */
+ unsigned int mb_motion_backward; /* macroblock_motion_backward */
+ unsigned int mb_pattern; /* macroblock_pattern */
+ unsigned int mb_intra; /* macroblock_intra */
+ unsigned int num_bits; /* length of the Huffman code */
+} mb_type_entry;
+
+
+/* Structures for an entry in the decoding table of coded_block_pattern */
+typedef struct {
+ unsigned int cbp; /* coded_block_pattern */
+ int num_bits; /* length of the Huffman code */
+} coded_block_pattern_entry;
+
+
+/* Structure for an entry in the decoding table of motion vectors */
+typedef struct {
+ int code; /* value for motion_horizontal_forward_code,
+ * motion_vertical_forward_code,
+ * motion_horizontal_backward_code, or
+ * motion_vertical_backward_code.
+ */
+ int num_bits; /* length of the Huffman code */
+} motion_vectors_entry;
+
+
+/* Structure for an entry in the decoding table of dct_dc_size */
+typedef struct {
+ unsigned int value; /* value of dct_dc_size (luminance or chrominance) */
+ int num_bits; /* length of the Huffman code */
+} dct_dc_size_entry;
+
+
+
+/* External declaration of dct coeff tables. */
+
+extern unsigned short int dct_coeff_tbl_0[256];
+extern unsigned short int dct_coeff_tbl_1[16];
+extern unsigned short int dct_coeff_tbl_2[4];
+extern unsigned short int dct_coeff_tbl_3[4];
+extern unsigned short int dct_coeff_next[256];
+extern unsigned short int dct_coeff_first[256];
+
+/* External declaration of dct dc size lumiance table. */
+
+extern dct_dc_size_entry dct_dc_size_luminance[32];
+extern dct_dc_size_entry dct_dc_size_luminance1[16];
+
+/* External declaration of dct dc size chrom table. */
+
+extern dct_dc_size_entry dct_dc_size_chrominance[32];
+extern dct_dc_size_entry dct_dc_size_chrominance1[32];
+
+/* External declaration of coded block pattern table. */
+
+extern coded_block_pattern_entry coded_block_pattern[512];
+
+/* Decoding table for macroblock_type in predictive-coded pictures */
+extern mb_type_entry mb_type_P[64];
+
+/* Decoding table for macroblock_type in bidirectionally-coded pictures */
+extern mb_type_entry mb_type_B[64];
+
+/* Decoding table for macroblock_address_increment */
+extern mb_addr_inc_entry mb_addr_inc[2048];
+
+/* Decoding table for motion vectors */
+extern motion_vectors_entry motion_vectors[2048];
+
+extern void init_tables();
+
+#endif
diff --git a/mpeglib/lib/mpegplay/globals.cpp b/mpeglib/lib/mpegplay/globals.cpp
new file mode 100644
index 00000000..b1e416be
--- /dev/null
+++ b/mpeglib/lib/mpegplay/globals.cpp
@@ -0,0 +1,41 @@
+/*
+ global variable for mpegplay
+ Copyright (C) 1999 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+
+
+
+
+
+
+
+/*
+ if used definetely uses more cpu, but I don't see
+ if the image is better or not.
+*/
+int qualityFlag = 0;
+
+int gXErrorFlag = 0;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/mpegplay/gop.cpp b/mpeglib/lib/mpegplay/gop.cpp
new file mode 100644
index 00000000..b2199070
--- /dev/null
+++ b/mpeglib/lib/mpegplay/gop.cpp
@@ -0,0 +1,170 @@
+/*
+ parse/stores GOP (group of picture) information from a mpegVideoStream
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "gop.h"
+
+#include <iostream>
+
+using namespace std;
+
+GOP::GOP() {
+ drop_flag=false;
+ tc_hours=0;
+ tc_minutes=0;
+ tc_seconds=0;
+ tc_pictures=0;
+ closed_gop=false;
+ broken_link=false;
+
+ mpegExtension=new MpegExtension();
+
+}
+
+
+GOP::~GOP() {
+ delete mpegExtension;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ParseGOP --
+ *
+ * Parses of group of pictures header from bit stream
+ * associated with vid_stream.
+ *
+ * Results:
+ * Values in gop header placed into video stream structure.
+ *
+ * Side effects:
+ * Bit stream irreversibly parsed.
+ *
+ *--------------------------------------------------------------
+ */
+int GOP::processGOP(MpegVideoStream* mpegVideoStream) {
+ unsigned int data;
+
+ /* Flush group of pictures start code. */
+
+ mpegVideoStream->flushBits(32);
+
+ /* Parse off drop frame flag. */
+
+ data=mpegVideoStream->getBits(1);
+
+ if (data) {
+ drop_flag = true;
+ } else
+ drop_flag = false;
+
+ /* Parse off hour component of time code. */
+
+ tc_hours=mpegVideoStream->getBits(5);
+
+ /* Parse off minute component of time code. */
+
+ tc_minutes=mpegVideoStream->getBits(6);
+
+
+ /* Flush marker bit. */
+
+ mpegVideoStream->flushBits(1);
+
+ /* Parse off second component of time code. */
+
+ tc_seconds=mpegVideoStream->getBits(6);
+
+ /* Parse off picture count component of time code. */
+
+ tc_pictures=mpegVideoStream->getBits(6);
+
+ /* Parse off closed gop and broken link flags. */
+ data=mpegVideoStream->getBits(2);
+ if (data > 1) {
+ closed_gop = true;
+ if (data > 2) {
+ broken_link = true;
+ } else
+ broken_link = false;
+ } else {
+ closed_gop = false;
+ if (data) {
+ broken_link = true;
+ } else
+ broken_link = false;
+ }
+
+
+ /*
+ * If next start code is extension/user start code,
+ * parse off extension data.
+ */
+
+ mpegExtension->processExtensionData(mpegVideoStream);
+
+ return true;
+}
+
+
+
+int GOP::substract(GOP* minus,GOP* dest) {
+ int hours;
+ int minutes;
+ int seconds;
+ hours=getHour()-minus->getHour();
+ minutes=getMinutes()-minus->getMinutes();
+ seconds=getSeconds()-minus->getSeconds();
+
+ if (seconds < 0) {
+ seconds+=60;
+ minutes--;
+ }
+ if (minutes < 0) {
+ minutes+=60;
+ hours--;
+ }
+ dest->tc_hours=hours;
+ dest->tc_minutes=minutes;
+ dest->tc_seconds=seconds;
+ if (hours < 0) {
+ return false;
+ }
+ return true;
+}
+
+
+void GOP::copyTo(GOP* dest) {
+ dest->tc_hours=getHour();
+ dest->tc_minutes=getMinutes();
+ dest->tc_seconds=getSeconds();
+ dest->drop_flag=getDropFlag();
+ dest->tc_pictures=getPictures();
+ dest->closed_gop=getClosedGOP();
+ dest->broken_link=getBrokenLink();
+
+ // currently do not copy ext/user data FIX ME
+}
+
+
+void GOP::print(const char* description) {
+ cout << "GOP [START]:"<<description<<endl;
+ cout << "tc_hours:"<<getHour()<<endl;
+ cout << "tc_minutes:"<<getMinutes()<<endl;
+ cout << "tc_seconds:"<<getSeconds()<<endl;
+ cout << "drop_flag:"<<getDropFlag()<<endl;
+ cout << "tc_pictures:"<<getPictures()<<endl;
+ cout << "closed_gop:"<<getClosedGOP()<<endl;
+ cout << "broken_link:"<<getBrokenLink()<<endl;
+ cout << "GOP [END]"<<endl;
+}
diff --git a/mpeglib/lib/mpegplay/gop.h b/mpeglib/lib/mpegplay/gop.h
new file mode 100644
index 00000000..a36d2886
--- /dev/null
+++ b/mpeglib/lib/mpegplay/gop.h
@@ -0,0 +1,62 @@
+/*
+ parse/stores GOP (group of picture) information from a mpegVideoStream
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+
+
+
+#ifndef __GOP_H
+#define __GOP_H
+
+#include "mpegVideoStream.h"
+#include "mpegExtension.h"
+
+class GOP {
+ /* Group of pictures structure. */
+
+ int drop_flag; /* Flag indicating dropped frame. */
+ int tc_hours; /* Hour component of time code. */
+ unsigned int tc_minutes; /* Minute component of time code. */
+ unsigned int tc_seconds; /* Second component of time code. */
+ unsigned int tc_pictures; /* Picture counter of time code. */
+ int closed_gop; /* Indicates no pred. vectors to
+ previous group of pictures. */
+ int broken_link; /* B frame unable to be decoded. */
+ MpegExtension* mpegExtension;
+
+
+ public:
+ GOP();
+ ~GOP();
+
+ int processGOP(MpegVideoStream* mpegVideoStream);
+ void copyTo(GOP* dest);
+
+ inline int getDropFlag() { return drop_flag; }
+ inline unsigned int getHour() { return tc_hours; }
+ inline unsigned int getMinutes() { return tc_minutes; }
+ inline unsigned int getSeconds() { return tc_seconds; }
+ inline unsigned int getPictures() { return tc_pictures; }
+ inline int getClosedGOP() { return closed_gop; }
+ inline int getBrokenLink() { return broken_link; }
+
+
+ inline void setHour(int hour) { this->tc_hours=hour; }
+ inline void setMinute(unsigned int minute) { this->tc_minutes=minute; }
+ inline void setSecond(unsigned int second) { this->tc_seconds=second; }
+
+
+ // returns diff in seconds
+ int substract(GOP* minus,GOP* dest);
+ void print(const char* description);
+};
+#endif
diff --git a/mpeglib/lib/mpegplay/jrevdct.cpp b/mpeglib/lib/mpegplay/jrevdct.cpp
new file mode 100644
index 00000000..4ffe48ab
--- /dev/null
+++ b/mpeglib/lib/mpegplay/jrevdct.cpp
@@ -0,0 +1,1690 @@
+/*
+ * jrevdct.c
+ *
+ * This file is part of the Independent JPEG Group's software.
+ * The IJG code is distributed under the terms reproduced here:
+ *
+ * LEGAL ISSUES
+ * ============
+ *
+ * In plain English:
+ *
+ * 1. We don't promise that this software works. (But if you find any bugs,
+ * please let us know!)
+ * 2. You can use this software for whatever you want. You don't have to
+ * pay us.
+ * 3. You may not pretend that you wrote this software. If you use it in a
+ * program, you must acknowledge somewhere in your documentation that
+ * you've used the IJG code.
+ *
+ * In legalese:
+ *
+ * The authors make NO WARRANTY or representation, either express or implied,
+ * with respect to this software, its quality, accuracy, merchantability, or
+ * fitness for a particular purpose. This software is provided "AS IS", and
+ * you, its user, assume the entire risk as to its quality and accuracy.
+ *
+ * This software is copyright (C) 1991, 1992, Thomas G. Lane.
+ * All Rights Reserved except as specified below.
+ *
+ * Permission is hereby granted to use, copy, modify, and distribute this
+ * software (or portions thereof) for any purpose, without fee, subject to
+ * these conditions:
+ * (1) If any part of the source code for this software is distributed, then
+ * this copyright and no-warranty notice must be included unaltered; and any
+ * additions, deletions, or changes to the original files must be clearly
+ * indicated in accompanying documentation.
+ * (2) If only executable code is distributed, then the accompanying
+ * documentation must state that "this software is based in part on the
+ * work of the Independent JPEG Group".
+ * (3) Permission for use of this software is granted only if the user
+ * accepts full responsibility for any undesirable consequences; the authors
+ * accept NO LIABILITY for damages of any kind.
+ *
+ * These conditions apply to any software derived from or based on the IJG
+ * code, not just to the unmodified library. If you use our work, you ought
+ * to acknowledge us.
+ *
+ * Permission is NOT granted for the use of any IJG author's name or company
+ * name in advertising or publicity relating to this software or products
+ * derived from it. This software may be referred to only as
+ * "the Independent JPEG Group's software".
+ *
+ * We specifically permit and encourage the use of this software as the
+ * basis of commercial products, provided that all warranty or liability
+ * claims are assumed by the product vendor.
+ *
+ *
+ * ARCHIVE LOCATIONS
+ * =================
+ *
+ * The "official" archive site for this software is ftp.uu.net (Internet
+ * address 192.48.96.9). The most recent released version can always be
+ * found there in directory graphics/jpeg. This particular version will
+ * be archived as graphics/jpeg/jpegsrc.v6a.tar.gz. If you are on the
+ * Internet, you can retrieve files from ftp.uu.net by standard anonymous
+ * FTP. If you don't have FTP access, UUNET's archives are also available
+ * via UUCP; contact help@uunet.uu.net for information on retrieving files
+ * that way.
+ *
+ * Numerous Internet sites maintain copies of the UUNET files. However,
+ * only ftp.uu.net is guaranteed to have the latest official version.
+ *
+ * You can also obtain this software in DOS-compatible "zip" archive
+ * format from the SimTel archives (ftp.coast.net:/SimTel/msdos/graphics/),
+ * or on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP),
+ * library 12 "JPEG Tools". Again, these versions may sometimes lag behind
+ * the ftp.uu.net release.
+ *
+ * The JPEG FAQ (Frequently Asked Questions) article is a useful source of
+ * general information about JPEG. It is updated constantly and therefore
+ * is not included in this distribution. The FAQ is posted every two weeks
+ * to Usenet newsgroups comp.graphics.misc, news.answers, and other groups.
+ * You can always obtain the latest version from the news.answers archive
+ * at rtfm.mit.edu. By FTP, fetch /pub/usenet/news.answers/jpeg-faq/part1
+ * and .../part2. If you don't have FTP, send e-mail to
+ * mail-server@rtfm.mit.edu with body
+ * send usenet/news.answers/jpeg-faq/part1
+ * send usenet/news.answers/jpeg-faq/part2
+ *
+ * ==============
+ *
+ *
+ * This file contains the basic inverse-DCT transformation subroutine.
+ *
+ * This implementation is based on an algorithm described in
+ * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
+ * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics,
+ * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991.
+ * The primary algorithm described there uses 11 multiplies and 29 adds.
+ * We use their alternate method with 12 multiplies and 32 adds.
+ * The advantage of this method is that no data path contains more than one
+ * multiplication; this allows a very simple and accurate implementation in
+ * scaled fixed-point arithmetic, with a minimal number of shifts.
+ *
+ *
+ * CHANGES FOR BERKELEY MPEG
+ * =========================
+ *
+ * This file has been altered to use the Berkeley MPEG header files,
+ * to add the capability to handle sparse DCT matrices efficiently,
+ * and to relabel the inverse DCT function as well as the file
+ * (formerly jidctint.c).
+ *
+ * I've made lots of modifications to attempt to take advantage of the
+ * sparse nature of the DCT matrices we're getting. Although the logic
+ * is cumbersome, it's straightforward and the resulting code is much
+ * faster.
+ *
+ * A better way to do this would be to pass in the DCT block as a sparse
+ * matrix, perhaps with the difference cases encoded.
+ */
+
+#include "jrevdct.h"
+
+
+
+
+/* We assume that right shift corresponds to signed division by 2 with
+ * rounding towards minus infinity. This is correct for typical "arithmetic
+ * shift" instructions that shift in copies of the sign bit. But some
+ * C compilers implement >> with an unsigned shift. For these machines you
+ * must define RIGHT_SHIFT_IS_UNSIGNED.
+ * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity.
+ * It is only applied with constant shift counts. SHIFT_TEMPS must be
+ * included in the variables of any routine using RIGHT_SHIFT.
+ */
+
+#ifdef RIGHT_SHIFT_IS_UNSIGNED
+#define SHIFT_TEMPS INT32 shift_temp;
+#define RIGHT_SHIFT(x,shft) \
+ ((shift_temp = (x)) < 0 ? \
+ (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \
+ (shift_temp >> (shft)))
+#else
+#define SHIFT_TEMPS
+#define RIGHT_SHIFT(x,shft) ((x) >> (shft))
+#endif
+
+/*
+ * This routine is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/*
+ * A 2-D IDCT can be done by 1-D IDCT on each row followed by 1-D IDCT
+ * on each column. Direct algorithms are also available, but they are
+ * much more complex and seem not to be any faster when reduced to code.
+ *
+ * The poop on this scaling stuff is as follows:
+ *
+ * Each 1-D IDCT step produces outputs which are a factor of sqrt(N)
+ * larger than the true IDCT outputs. The final outputs are therefore
+ * a factor of N larger than desired; since N=8 this can be cured by
+ * a simple right shift at the end of the algorithm. The advantage of
+ * this arrangement is that we save two multiplications per 1-D IDCT,
+ * because the y0 and y4 inputs need not be divided by sqrt(N).
+ *
+ * We have to do addition and subtraction of the integer inputs, which
+ * is no problem, and multiplication by fractional constants, which is
+ * a problem to do in integer arithmetic. We multiply all the constants
+ * by CONST_SCALE and convert them to integer constants (thus retaining
+ * CONST_BITS bits of precision in the constants). After doing a
+ * multiplication we have to divide the product by CONST_SCALE, with proper
+ * rounding, to produce the correct output. This division can be done
+ * cheaply as a right shift of CONST_BITS bits. We postpone shifting
+ * as long as possible so that partial sums can be added together with
+ * full fractional precision.
+ *
+ * The outputs of the first pass are scaled up by PASS1_BITS bits so that
+ * they are represented to better-than-integral precision. These outputs
+ * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
+ * with the recommended scaling. (To scale up 12-bit sample data further, an
+ * intermediate INT32 array would be needed.)
+ *
+ * To avoid overflow of the 32-bit intermediate results in pass 2, we must
+ * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis
+ * shows that the values given below are the most effective.
+ */
+
+#ifdef EIGHT_BIT_SAMPLES
+#define PASS1_BITS 2
+#else
+#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
+#endif
+
+#define ONE ((INT32) 1)
+
+#define CONST_SCALE (ONE << CONST_BITS)
+
+/* Convert a positive real constant to an integer scaled by CONST_SCALE.
+ * IMPORTANT: if your compiler doesn't do this arithmetic at compile time,
+ * you will pay a significant penalty in run time. In that case, figure
+ * the correct integer constant values and insert them by hand.
+ */
+
+#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5))
+
+/* When adding two opposite-signed fixes, the 0.5 cancels */
+#define FIX2(x) ((INT32) ((x) * CONST_SCALE))
+
+/* Descale and correctly round an INT32 value that's scaled by N bits.
+ * We assume RIGHT_SHIFT rounds towards minus infinity, so adding
+ * the fudge factor is correct for either sign of X.
+ */
+
+#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
+
+/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
+ * For 8-bit samples with the recommended scaling, all the variable
+ * and constant values involved are no more than 16 bits wide, so a
+ * 16x16->32 bit multiply can be used instead of a full 32x32 multiply;
+ * this provides a useful speedup on many machines.
+ * There is no way to specify a 16x16->32 multiply in portable C, but
+ * some C compilers will do the right thing if you provide the correct
+ * combination of casts.
+ * NB: for 12-bit samples, a full 32-bit multiplication will be needed.
+ */
+
+#ifdef EIGHT_BIT_SAMPLES
+#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
+#define MULTIPLY(var,const) (((INT16) (var)) * ((INT16) (const)))
+#endif
+#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */
+#define MULTIPLY(var,const) (((INT16) (var)) * ((INT32) (const)))
+#endif
+#endif
+
+#ifndef MULTIPLY /* default definition */
+#define MULTIPLY(var,const) ((var) * (const))
+#endif
+
+#ifndef NO_SPARSE_DCT
+#define SPARSE_SCALE_FACTOR 8
+#endif
+
+/* Precomputed idct value arrays. */
+
+static DCTELEM PreIDCT[64][64];
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * init_pre_idct --
+ *
+ * Pre-computes singleton coefficient IDCT values.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+void init_pre_idct() {
+ int i;
+
+ for (i=0; i<64; i++) {
+ memset((char *) PreIDCT[i], 0, 64*sizeof(DCTELEM));
+ PreIDCT[i][i] = 1 << SPARSE_SCALE_FACTOR;
+ j_rev_dct(PreIDCT[i]);
+ }
+
+ int pos;
+ int rr;
+ DCTELEM *ndataptr;
+
+ for(pos=0;pos<64;pos++) {
+ ndataptr = PreIDCT[pos];
+
+ for(rr=0; rr<4; rr++) {
+ for(i=0;i<16;i++) {
+ ndataptr[i] = ndataptr[i]/256;
+ }
+ ndataptr += 16;
+
+ }
+ }
+
+
+
+
+
+
+}
+
+#ifndef NO_SPARSE_DCT
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * j_rev_dct_sparse --
+ *
+ * Performs the inverse DCT on one block of coefficients.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void j_rev_dct_sparse (DCTBLOCK data, int pos) {
+ short int val;
+ register int *dp;
+ register int v;
+ int quant;
+
+ // cout << "j_rev_dct_sparse"<<endl;
+
+ /* If DC Coefficient. */
+
+ if (pos == 0) {
+ dp = (int *)data;
+ v = *data;
+ quant = 8;
+
+ /* Compute 32 bit value to assign. This speeds things up a bit */
+ if (v < 0) {
+ val = -v;
+ val += (quant / 2);
+ val /= quant;
+ val = -val;
+ }
+ else {
+ val = (v + (quant / 2)) / quant;
+ }
+
+ v = ((val & 0xffff) | (val << 16));
+
+ dp[0] = v; dp[1] = v; dp[2] = v; dp[3] = v;
+ dp[4] = v; dp[5] = v; dp[6] = v; dp[7] = v;
+ dp[8] = v; dp[9] = v; dp[10] = v; dp[11] = v;
+ dp[12] = v; dp[13] = v; dp[14] = v; dp[15] = v;
+ dp[16] = v; dp[17] = v; dp[18] = v; dp[19] = v;
+ dp[20] = v; dp[21] = v; dp[22] = v; dp[23] = v;
+ dp[24] = v; dp[25] = v; dp[26] = v; dp[27] = v;
+ dp[28] = v; dp[29] = v; dp[30] = v; dp[31] = v;
+
+ return;
+ }
+ //printf("sparse is: %d val:%8x\n",pos,data[pos]);
+
+ /*
+ j_rev_dct(data);
+ return;
+ */
+
+ /* Some other coefficient. */
+
+ DCTELEM *dataptr;
+ DCTELEM *ndataptr;
+ int coeff, rr;
+
+
+
+ dataptr = (DCTELEM *)data;
+ coeff = dataptr[pos];
+ ndataptr = PreIDCT[pos];
+
+ //printf ("COEFFICIENT = %3d, POSITION = %2d\n", coeff, pos);
+ coeff=coeff/256;
+
+ for (rr=0; rr<4; rr++) {
+
+ dataptr[0] = (ndataptr[0] * coeff);
+ dataptr[1] = (ndataptr[1] * coeff);
+ dataptr[2] = (ndataptr[2] * coeff);
+ dataptr[3] = (ndataptr[3] * coeff);
+ dataptr[4] = (ndataptr[4] * coeff);
+ dataptr[5] = (ndataptr[5] * coeff);
+ dataptr[6] = (ndataptr[6] * coeff);
+ dataptr[7] = (ndataptr[7] * coeff);
+ dataptr[8] = (ndataptr[8] * coeff);
+ dataptr[9] = (ndataptr[9] * coeff);
+ dataptr[10] = (ndataptr[10] * coeff);
+ dataptr[11] = (ndataptr[11] * coeff);
+ dataptr[12] = (ndataptr[12] * coeff);
+ dataptr[13] = (ndataptr[13] * coeff);
+ dataptr[14] = (ndataptr[14] * coeff);
+ dataptr[15] = (ndataptr[15] * coeff);
+
+
+ dataptr += 16;
+ ndataptr += 16;
+ }
+
+ dataptr = (DCTELEM *) data;
+
+
+
+ return;
+
+}
+
+#else
+
+/*
+ *--------------------------------------------------------------
+ *
+ * j_rev_dct_sparse --
+ *
+ * Performs the original inverse DCT on one block of
+ * coefficients.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+void j_rev_dct_sparse (DCTBLOCK data,int pos) {
+ j_rev_dct(data);
+}
+#endif /* SPARSE_DCT */
+
+
+#ifndef FIVE_DCT
+
+#ifndef ORIG_DCT
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * j_rev_dct --
+ *
+ * The inverse DCT function.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+void j_rev_dct (DCTBLOCK data) {
+
+
+ INT32 tmp0, tmp1, tmp2, tmp3;
+ INT32 tmp10, tmp11, tmp12, tmp13;
+ INT32 z1, z2, z3, z4, z5;
+ INT32 d0, d1, d2, d3, d4, d5, d6, d7;
+ register DCTELEM *dataptr;
+ int rowctr;
+ SHIFT_TEMPS
+
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true IDCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+
+ dataptr = data;
+
+ for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
+ /* Due to quantization, we will usually find that many of the input
+ * coefficients are zero, especially the AC terms. We can exploit this
+ * by short-circuiting the IDCT calculation for any row in which all
+ * the AC terms are zero. In that case each output is equal to the
+ * DC coefficient (with scale factor as needed).
+ * With typical images and quantization tables, half or more of the
+ * row DCT calculations can be simplified this way.
+ */
+
+ register int *idataptr = (int*)dataptr;
+ d0 = dataptr[0];
+ d1 = dataptr[1];
+ if ((d1 == 0) && (idataptr[1] + idataptr[2] + idataptr[3]) == 0) {
+ /* AC terms all zero */
+ if (d0) {
+ /* Compute a 32 bit value to assign. */
+ DCTELEM dcval = (DCTELEM) (d0 << PASS1_BITS);
+ register int v = (dcval & 0xffff) + (dcval << 16);
+
+ idataptr[0] = v;
+ idataptr[1] = v;
+ idataptr[2] = v;
+ idataptr[3] = v;
+ }
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ continue;
+ }
+ d2 = dataptr[2];
+ d3 = dataptr[3];
+ d4 = dataptr[4];
+ d5 = dataptr[5];
+ d6 = dataptr[6];
+ d7 = dataptr[7];
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+ if (d6) {
+ if (d4) {
+ if (d2) {
+ if (d0) {
+ /* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
+
+ tmp0 = (d0 + d4) << CONST_BITS;
+ tmp1 = (d0 - d4) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+ } else {
+ /* d0 == 0, d2 != 0, d4 != 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
+
+ tmp0 = d4 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp2 - tmp0;
+ tmp12 = -(tmp0 + tmp2);
+ }
+ } else {
+ if (d0) {
+ /* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */
+ tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
+ tmp3 = MULTIPLY(d6, FIX(0.541196100));
+
+ tmp0 = (d0 + d4) << CONST_BITS;
+ tmp1 = (d0 - d4) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+ } else {
+ /* d0 == 0, d2 == 0, d4 != 0, d6 != 0 */
+ tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
+ tmp3 = MULTIPLY(d6, FIX(0.541196100));
+
+ tmp0 = d4 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp2 - tmp0;
+ tmp12 = -(tmp0 + tmp2);
+ }
+ }
+ } else {
+ if (d2) {
+ if (d0) {
+ /* d0 != 0, d2 != 0, d4 == 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
+
+ tmp0 = d0 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+ } else {
+ /* d0 == 0, d2 != 0, d4 == 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
+
+ tmp10 = tmp3;
+ tmp13 = -tmp3;
+ tmp11 = tmp2;
+ tmp12 = -tmp2;
+ }
+ } else {
+ if (d0) {
+ /* d0 != 0, d2 == 0, d4 == 0, d6 != 0 */
+ tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
+ tmp3 = MULTIPLY(d6, FIX(0.541196100));
+
+ tmp0 = d0 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+ } else {
+ /* d0 == 0, d2 == 0, d4 == 0, d6 != 0 */
+ tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
+ tmp3 = MULTIPLY(d6, FIX(0.541196100));
+
+ tmp10 = tmp3;
+ tmp13 = -tmp3;
+ tmp11 = tmp2;
+ tmp12 = -tmp2;
+ }
+ }
+ }
+ } else {
+ if (d4) {
+ if (d2) {
+ if (d0) {
+ /* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX(0.541196100));
+ tmp3 = (INT32) (MULTIPLY(d2, (FIX(1.306562965) + .5)));
+
+ tmp0 = (d0 + d4) << CONST_BITS;
+ tmp1 = (d0 - d4) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+ } else {
+ /* d0 == 0, d2 != 0, d4 != 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX(0.541196100));
+ tmp3 = (INT32) (MULTIPLY(d2, (FIX(1.306562965) + .5)));
+
+ tmp0 = d4 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp2 - tmp0;
+ tmp12 = -(tmp0 + tmp2);
+ }
+ } else {
+ if (d0) {
+ /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */
+ tmp10 = tmp13 = (d0 + d4) << CONST_BITS;
+ tmp11 = tmp12 = (d0 - d4) << CONST_BITS;
+ } else {
+ /* d0 == 0, d2 == 0, d4 != 0, d6 == 0 */
+ tmp10 = tmp13 = d4 << CONST_BITS;
+ tmp11 = tmp12 = -tmp10;
+ }
+ }
+ } else {
+ if (d2) {
+ if (d0) {
+ /* d0 != 0, d2 != 0, d4 == 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX(0.541196100));
+ tmp3 = (INT32) (MULTIPLY(d2, (FIX(1.306562965) + .5)));
+
+ tmp0 = d0 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+ } else {
+ /* d0 == 0, d2 != 0, d4 == 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX(0.541196100));
+ tmp3 = (INT32) (MULTIPLY(d2, (FIX(1.306562965) + .5)));
+
+ tmp10 = tmp3;
+ tmp13 = -tmp3;
+ tmp11 = tmp2;
+ tmp12 = -tmp2;
+ }
+ } else {
+ if (d0) {
+ /* d0 != 0, d2 == 0, d4 == 0, d6 == 0 */
+ tmp10 = tmp13 = tmp11 = tmp12 = d0 << CONST_BITS;
+ } else {
+ /* d0 == 0, d2 == 0, d4 == 0, d6 == 0 */
+ tmp10 = tmp13 = tmp11 = tmp12 = 0;
+ }
+ }
+ }
+ }
+
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+
+ if (d7) {
+ if (d5) {
+ if (d3) {
+ if (d1) {
+ /* d1 != 0, d3 != 0, d5 != 0, d7 != 0 */
+ z1 = d7 + d1;
+ z2 = d5 + d3;
+ z3 = d7 + d3;
+ z4 = d5 + d1;
+ z5 = MULTIPLY(z3 + z4, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, FIX(0.298631336));
+ tmp1 = MULTIPLY(d5, FIX(2.053119869));
+ tmp2 = MULTIPLY(d3, FIX(3.072711026));
+ tmp3 = MULTIPLY(d1, FIX(1.501321110));
+ z1 = MULTIPLY(z1, - FIX(0.899976223));
+ z2 = MULTIPLY(z2, - FIX(2.562915447));
+ z3 = MULTIPLY(z3, - FIX(1.961570560));
+ z4 = MULTIPLY(z4, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+ } else {
+ /* d1 == 0, d3 != 0, d5 != 0, d7 != 0 */
+ z2 = d5 + d3;
+ z3 = d7 + d3;
+ z5 = MULTIPLY(z3 + d5, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, FIX(0.298631336));
+ tmp1 = MULTIPLY(d5, FIX(2.053119869));
+ tmp2 = MULTIPLY(d3, FIX(3.072711026));
+ z1 = MULTIPLY(d7, - FIX(0.899976223));
+ z2 = MULTIPLY(z2, - FIX(2.562915447));
+ z3 = MULTIPLY(z3, - FIX(1.961570560));
+ z4 = MULTIPLY(d5, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 = z1 + z4;
+ }
+ } else {
+ if (d1) {
+ /* d1 != 0, d3 == 0, d5 != 0, d7 != 0 */
+ z1 = d7 + d1;
+ z4 = d5 + d1;
+ z5 = MULTIPLY(d7 + z4, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, FIX(0.298631336));
+ tmp1 = MULTIPLY(d5, FIX(2.053119869));
+ tmp3 = MULTIPLY(d1, FIX(1.501321110));
+ z1 = MULTIPLY(z1, - FIX(0.899976223));
+ z2 = MULTIPLY(d5, - FIX(2.562915447));
+ z3 = MULTIPLY(d7, - FIX(1.961570560));
+ z4 = MULTIPLY(z4, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 = z2 + z3;
+ tmp3 += z1 + z4;
+ } else {
+ /* d1 == 0, d3 == 0, d5 != 0, d7 != 0 */
+ z5 = MULTIPLY(d7 + d5, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, - FIX2(0.601344887));
+ tmp1 = MULTIPLY(d5, - FIX2(0.509795578));
+ z1 = MULTIPLY(d7, - FIX(0.899976223));
+ z3 = MULTIPLY(d7, - FIX(1.961570560));
+ z2 = MULTIPLY(d5, - FIX(2.562915447));
+ z4 = MULTIPLY(d5, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z3;
+ tmp1 += z4;
+ tmp2 = z2 + z3;
+ tmp3 = z1 + z4;
+ }
+ }
+ } else {
+ if (d3) {
+ if (d1) {
+ /* d1 != 0, d3 != 0, d5 == 0, d7 != 0 */
+ z1 = d7 + d1;
+ z3 = d7 + d3;
+ z5 = MULTIPLY(z3 + d1, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, FIX(0.298631336));
+ tmp2 = MULTIPLY(d3, FIX(3.072711026));
+ tmp3 = MULTIPLY(d1, FIX(1.501321110));
+ z1 = MULTIPLY(z1, - FIX(0.899976223));
+ z2 = MULTIPLY(d3, - FIX(2.562915447));
+ z3 = MULTIPLY(z3, - FIX(1.961570560));
+ z4 = MULTIPLY(d1, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 = z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+ } else {
+ /* d1 == 0, d3 != 0, d5 == 0, d7 != 0 */
+ z3 = d7 + d3;
+ z5 = MULTIPLY(z3, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, - FIX2(0.601344887));
+ tmp2 = MULTIPLY(d3, FIX(0.509795579));
+ z1 = MULTIPLY(d7, - FIX(0.899976223));
+ z2 = MULTIPLY(d3, - FIX(2.562915447));
+ z3 = MULTIPLY(z3, - FIX2(0.785694958));
+
+ tmp0 += z3;
+ tmp1 = z2 + z5;
+ tmp2 += z3;
+ tmp3 = z1 + z5;
+ }
+ } else {
+ if (d1) {
+ /* d1 != 0, d3 == 0, d5 == 0, d7 != 0 */
+ z1 = d7 + d1;
+ z5 = MULTIPLY(z1, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, - FIX2(1.662939224));
+ tmp3 = MULTIPLY(d1, FIX2(1.111140466));
+ z1 = MULTIPLY(z1, FIX2(0.275899379));
+ z3 = MULTIPLY(d7, - FIX(1.961570560));
+ z4 = MULTIPLY(d1, - FIX(0.390180644));
+
+ tmp0 += z1;
+ tmp1 = z4 + z5;
+ tmp2 = z3 + z5;
+ tmp3 += z1;
+ } else {
+ /* d1 == 0, d3 == 0, d5 == 0, d7 != 0 */
+ tmp0 = MULTIPLY(d7, - FIX2(1.387039845));
+ tmp1 = MULTIPLY(d7, FIX(1.175875602));
+ tmp2 = MULTIPLY(d7, - FIX2(0.785694958));
+ tmp3 = MULTIPLY(d7, FIX2(0.275899379));
+ }
+ }
+ }
+ } else {
+ if (d5) {
+ if (d3) {
+ if (d1) {
+ /* d1 != 0, d3 != 0, d5 != 0, d7 == 0 */
+ z2 = d5 + d3;
+ z4 = d5 + d1;
+ z5 = MULTIPLY(d3 + z4, FIX(1.175875602));
+
+ tmp1 = MULTIPLY(d5, FIX(2.053119869));
+ tmp2 = MULTIPLY(d3, FIX(3.072711026));
+ tmp3 = MULTIPLY(d1, FIX(1.501321110));
+ z1 = MULTIPLY(d1, - FIX(0.899976223));
+ z2 = MULTIPLY(z2, - FIX(2.562915447));
+ z3 = MULTIPLY(d3, - FIX(1.961570560));
+ z4 = MULTIPLY(z4, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 = z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+ } else {
+ /* d1 == 0, d3 != 0, d5 != 0, d7 == 0 */
+ z2 = d5 + d3;
+ z5 = MULTIPLY(z2, FIX(1.175875602));
+
+ tmp1 = MULTIPLY(d5, FIX2(1.662939225));
+ tmp2 = MULTIPLY(d3, FIX2(1.111140466));
+ z2 = MULTIPLY(z2, - FIX2(1.387039845));
+ z3 = MULTIPLY(d3, - FIX(1.961570560));
+ z4 = MULTIPLY(d5, - FIX(0.390180644));
+
+ tmp0 = z3 + z5;
+ tmp1 += z2;
+ tmp2 += z2;
+ tmp3 = z4 + z5;
+ }
+ } else {
+ if (d1) {
+ /* d1 != 0, d3 == 0, d5 != 0, d7 == 0 */
+ z4 = d5 + d1;
+ z5 = MULTIPLY(z4, FIX(1.175875602));
+
+ tmp1 = MULTIPLY(d5, - FIX2(0.509795578));
+ tmp3 = MULTIPLY(d1, FIX2(0.601344887));
+ z1 = MULTIPLY(d1, - FIX(0.899976223));
+ z2 = MULTIPLY(d5, - FIX(2.562915447));
+ z4 = MULTIPLY(z4, FIX2(0.785694958));
+
+ tmp0 = z1 + z5;
+ tmp2 = z2 + z5;
+ tmp1 += z4;
+ tmp3 += z4;
+ } else {
+ /* d1 == 0, d3 == 0, d5 != 0, d7 == 0 */
+ tmp0 = MULTIPLY(d5, FIX(1.175875602));
+ tmp1 = MULTIPLY(d5, FIX2(0.275899380));
+ tmp2 = MULTIPLY(d5, - FIX2(1.387039845));
+ tmp3 = MULTIPLY(d5, FIX2(0.785694958));
+ }
+ }
+ } else {
+ if (d3) {
+ if (d1) {
+ /* d1 != 0, d3 != 0, d5 == 0, d7 == 0 */
+ z5 = d3 + d1;
+
+ tmp2 = MULTIPLY(d3, - FIX(1.451774981));
+ tmp3 = MULTIPLY(d1, (FIX(0.211164243) - 1));
+ z1 = MULTIPLY(d1, FIX(1.061594337));
+ z2 = MULTIPLY(d3, - FIX(2.172734803));
+ z4 = MULTIPLY(z5, FIX(0.785694958));
+ z5 = MULTIPLY(z5, FIX(1.175875602));
+
+ tmp0 = z1 - z4;
+ tmp1 = z2 + z4;
+ tmp2 += z5;
+ tmp3 += z5;
+ } else {
+ /* d1 == 0, d3 != 0, d5 == 0, d7 == 0 */
+ tmp0 = MULTIPLY(d3, - FIX2(0.785694958));
+ tmp1 = MULTIPLY(d3, - FIX2(1.387039845));
+ tmp2 = MULTIPLY(d3, - FIX2(0.275899379));
+ tmp3 = MULTIPLY(d3, FIX(1.175875602));
+ }
+ } else {
+ if (d1) {
+ /* d1 != 0, d3 == 0, d5 == 0, d7 == 0 */
+ tmp0 = MULTIPLY(d1, FIX2(0.275899379));
+ tmp1 = MULTIPLY(d1, FIX2(0.785694958));
+ tmp2 = MULTIPLY(d1, FIX(1.175875602));
+ tmp3 = MULTIPLY(d1, FIX2(1.387039845));
+ } else {
+ /* d1 == 0, d3 == 0, d5 == 0, d7 == 0 */
+ tmp0 = tmp1 = tmp2 = tmp3 = 0;
+ }
+ }
+ }
+ }
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ dataptr[0] = (DCTELEM) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
+ dataptr[7] = (DCTELEM) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
+ dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
+ dataptr[6] = (DCTELEM) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
+ dataptr[2] = (DCTELEM) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
+ dataptr[5] = (DCTELEM) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
+ dataptr[3] = (DCTELEM) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
+ dataptr[4] = (DCTELEM) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns. */
+ /* Note that we must descale the results by a factor of 8 == 2**3, */
+ /* and also undo the PASS1_BITS scaling. */
+
+ dataptr = data;
+ for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
+ /* Columns of zeroes can be exploited in the same way as we did with rows.
+ * However, the row calculation has created many nonzero AC terms, so the
+ * simplification applies less often (typically 5% to 10% of the time).
+ * On machines with very fast multiplication, it's possible that the
+ * test takes more time than it's worth. In that case this section
+ * may be commented out.
+ */
+
+ d0 = dataptr[DCTSIZE*0];
+ d1 = dataptr[DCTSIZE*1];
+ d2 = dataptr[DCTSIZE*2];
+ d3 = dataptr[DCTSIZE*3];
+ d4 = dataptr[DCTSIZE*4];
+ d5 = dataptr[DCTSIZE*5];
+ d6 = dataptr[DCTSIZE*6];
+ d7 = dataptr[DCTSIZE*7];
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+ if (d6) {
+ if (d4) {
+ if (d2) {
+ if (d0) {
+ /* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
+
+ tmp0 = (d0 + d4) << CONST_BITS;
+ tmp1 = (d0 - d4) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+ } else {
+ /* d0 == 0, d2 != 0, d4 != 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
+
+ tmp0 = d4 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp2 - tmp0;
+ tmp12 = -(tmp0 + tmp2);
+ }
+ } else {
+ if (d0) {
+ /* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */
+ tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
+ tmp3 = MULTIPLY(d6, FIX(0.541196100));
+
+ tmp0 = (d0 + d4) << CONST_BITS;
+ tmp1 = (d0 - d4) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+ } else {
+ /* d0 == 0, d2 == 0, d4 != 0, d6 != 0 */
+ tmp2 = MULTIPLY(d6, -FIX2(1.306562965));
+ tmp3 = MULTIPLY(d6, FIX(0.541196100));
+
+ tmp0 = d4 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp2 - tmp0;
+ tmp12 = -(tmp0 + tmp2);
+ }
+ }
+ } else {
+ if (d2) {
+ if (d0) {
+ /* d0 != 0, d2 != 0, d4 == 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
+
+ tmp0 = d0 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+ } else {
+ /* d0 == 0, d2 != 0, d4 == 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
+
+ tmp10 = tmp3;
+ tmp13 = -tmp3;
+ tmp11 = tmp2;
+ tmp12 = -tmp2;
+ }
+ } else {
+ if (d0) {
+ /* d0 != 0, d2 == 0, d4 == 0, d6 != 0 */
+ tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
+ tmp3 = MULTIPLY(d6, FIX(0.541196100));
+
+ tmp0 = d0 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+ } else {
+ /* d0 == 0, d2 == 0, d4 == 0, d6 != 0 */
+ tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
+ tmp3 = MULTIPLY(d6, FIX(0.541196100));
+
+ tmp10 = tmp3;
+ tmp13 = -tmp3;
+ tmp11 = tmp2;
+ tmp12 = -tmp2;
+ }
+ }
+ }
+ } else {
+ if (d4) {
+ if (d2) {
+ if (d0) {
+ /* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX(0.541196100));
+ tmp3 = (INT32) (MULTIPLY(d2, (FIX(1.306562965) + .5)));
+
+ tmp0 = (d0 + d4) << CONST_BITS;
+ tmp1 = (d0 - d4) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+ } else {
+ /* d0 == 0, d2 != 0, d4 != 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX(0.541196100));
+ tmp3 = (INT32) (MULTIPLY(d2, (FIX(1.306562965) + .5)));
+
+ tmp0 = d4 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp2 - tmp0;
+ tmp12 = -(tmp0 + tmp2);
+ }
+ } else {
+ if (d0) {
+ /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */
+ tmp10 = tmp13 = (d0 + d4) << CONST_BITS;
+ tmp11 = tmp12 = (d0 - d4) << CONST_BITS;
+ } else {
+ /* d0 == 0, d2 == 0, d4 != 0, d6 == 0 */
+ tmp10 = tmp13 = d4 << CONST_BITS;
+ tmp11 = tmp12 = -tmp10;
+ }
+ }
+ } else {
+ if (d2) {
+ if (d0) {
+ /* d0 != 0, d2 != 0, d4 == 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX(0.541196100));
+ tmp3 = (INT32) (MULTIPLY(d2, (FIX(1.306562965) + .5)));
+
+ tmp0 = d0 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+ } else {
+ /* d0 == 0, d2 != 0, d4 == 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX(0.541196100));
+ tmp3 = (INT32) (MULTIPLY(d2, (FIX(1.306562965) + .5)));
+
+ tmp10 = tmp3;
+ tmp13 = -tmp3;
+ tmp11 = tmp2;
+ tmp12 = -tmp2;
+ }
+ } else {
+ if (d0) {
+ /* d0 != 0, d2 == 0, d4 == 0, d6 == 0 */
+ tmp10 = tmp13 = tmp11 = tmp12 = d0 << CONST_BITS;
+ } else {
+ /* d0 == 0, d2 == 0, d4 == 0, d6 == 0 */
+ tmp10 = tmp13 = tmp11 = tmp12 = 0;
+ }
+ }
+ }
+ }
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+ if (d7) {
+ if (d5) {
+ if (d3) {
+ if (d1) {
+ /* d1 != 0, d3 != 0, d5 != 0, d7 != 0 */
+ z1 = d7 + d1;
+ z2 = d5 + d3;
+ z3 = d7 + d3;
+ z4 = d5 + d1;
+ z5 = MULTIPLY(z3 + z4, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, FIX(0.298631336));
+ tmp1 = MULTIPLY(d5, FIX(2.053119869));
+ tmp2 = MULTIPLY(d3, FIX(3.072711026));
+ tmp3 = MULTIPLY(d1, FIX(1.501321110));
+ z1 = MULTIPLY(z1, - FIX(0.899976223));
+ z2 = MULTIPLY(z2, - FIX(2.562915447));
+ z3 = MULTIPLY(z3, - FIX(1.961570560));
+ z4 = MULTIPLY(z4, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+ } else {
+ /* d1 == 0, d3 != 0, d5 != 0, d7 != 0 */
+ z2 = d5 + d3;
+ z3 = d7 + d3;
+ z5 = MULTIPLY(z3 + d5, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, FIX(0.298631336));
+ tmp1 = MULTIPLY(d5, FIX(2.053119869));
+ tmp2 = MULTIPLY(d3, FIX(3.072711026));
+ z1 = MULTIPLY(d7, - FIX(0.899976223));
+ z2 = MULTIPLY(z2, - FIX(2.562915447));
+ z3 = MULTIPLY(z3, - FIX(1.961570560));
+ z4 = MULTIPLY(d5, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 = z1 + z4;
+ }
+ } else {
+ if (d1) {
+ /* d1 != 0, d3 == 0, d5 != 0, d7 != 0 */
+ z1 = d7 + d1;
+ z4 = d5 + d1;
+ z5 = MULTIPLY(d7 + z4, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, FIX(0.298631336));
+ tmp1 = MULTIPLY(d5, FIX(2.053119869));
+ tmp3 = MULTIPLY(d1, FIX(1.501321110));
+ z1 = MULTIPLY(z1, - FIX(0.899976223));
+ z2 = MULTIPLY(d5, - FIX(2.562915447));
+ z3 = MULTIPLY(d7, - FIX(1.961570560));
+ z4 = MULTIPLY(z4, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 = z2 + z3;
+ tmp3 += z1 + z4;
+ } else {
+ /* d1 == 0, d3 == 0, d5 != 0, d7 != 0 */
+ z5 = MULTIPLY(d5 + d7, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, - FIX2(0.601344887));
+ tmp1 = MULTIPLY(d5, - FIX2(0.509795578));
+ z1 = MULTIPLY(d7, - FIX(0.899976223));
+ z3 = MULTIPLY(d7, - FIX(1.961570560));
+ z2 = MULTIPLY(d5, - FIX(2.562915447));
+ z4 = MULTIPLY(d5, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z3;
+ tmp1 += z4;
+ tmp2 = z2 + z3;
+ tmp3 = z1 + z4;
+ }
+ }
+ } else {
+ if (d3) {
+ if (d1) {
+ /* d1 != 0, d3 != 0, d5 == 0, d7 != 0 */
+ z1 = d7 + d1;
+ z3 = d7 + d3;
+ z5 = MULTIPLY(z3 + d1, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, FIX(0.298631336));
+ tmp2 = MULTIPLY(d3, FIX(3.072711026));
+ tmp3 = MULTIPLY(d1, FIX(1.501321110));
+ z1 = MULTIPLY(z1, - FIX(0.899976223));
+ z2 = MULTIPLY(d3, - FIX(2.562915447));
+ z3 = MULTIPLY(z3, - FIX(1.961570560));
+ z4 = MULTIPLY(d1, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 = z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+ } else {
+ /* d1 == 0, d3 != 0, d5 == 0, d7 != 0 */
+ z3 = d7 + d3;
+ z5 = MULTIPLY(z3, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, - FIX2(0.601344887));
+ z1 = MULTIPLY(d7, - FIX(0.899976223));
+ tmp2 = MULTIPLY(d3, FIX(0.509795579));
+ z2 = MULTIPLY(d3, - FIX(2.562915447));
+ z3 = MULTIPLY(z3, - FIX2(0.785694958));
+
+ tmp0 += z3;
+ tmp1 = z2 + z5;
+ tmp2 += z3;
+ tmp3 = z1 + z5;
+ }
+ } else {
+ if (d1) {
+ /* d1 != 0, d3 == 0, d5 == 0, d7 != 0 */
+ z1 = d7 + d1;
+ z5 = MULTIPLY(z1, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, - FIX2(1.662939224));
+ tmp3 = MULTIPLY(d1, FIX2(1.111140466));
+ z1 = MULTIPLY(z1, FIX2(0.275899379));
+ z3 = MULTIPLY(d7, - FIX(1.961570560));
+ z4 = MULTIPLY(d1, - FIX(0.390180644));
+
+ tmp0 += z1;
+ tmp1 = z4 + z5;
+ tmp2 = z3 + z5;
+ tmp3 += z1;
+ } else {
+ /* d1 == 0, d3 == 0, d5 == 0, d7 != 0 */
+ tmp0 = MULTIPLY(d7, - FIX2(1.387039845));
+ tmp1 = MULTIPLY(d7, FIX(1.175875602));
+ tmp2 = MULTIPLY(d7, - FIX2(0.785694958));
+ tmp3 = MULTIPLY(d7, FIX2(0.275899379));
+ }
+ }
+ }
+ } else {
+ if (d5) {
+ if (d3) {
+ if (d1) {
+ /* d1 != 0, d3 != 0, d5 != 0, d7 == 0 */
+ z2 = d5 + d3;
+ z4 = d5 + d1;
+ z5 = MULTIPLY(d3 + z4, FIX(1.175875602));
+
+ tmp1 = MULTIPLY(d5, FIX(2.053119869));
+ tmp2 = MULTIPLY(d3, FIX(3.072711026));
+ tmp3 = MULTIPLY(d1, FIX(1.501321110));
+ z1 = MULTIPLY(d1, - FIX(0.899976223));
+ z2 = MULTIPLY(z2, - FIX(2.562915447));
+ z3 = MULTIPLY(d3, - FIX(1.961570560));
+ z4 = MULTIPLY(z4, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 = z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+ } else {
+ /* d1 == 0, d3 != 0, d5 != 0, d7 == 0 */
+ z2 = d5 + d3;
+ z5 = MULTIPLY(z2, FIX(1.175875602));
+
+ tmp1 = MULTIPLY(d5, FIX2(1.662939225));
+ tmp2 = MULTIPLY(d3, FIX2(1.111140466));
+ z2 = MULTIPLY(z2, - FIX2(1.387039845));
+ z3 = MULTIPLY(d3, - FIX(1.961570560));
+ z4 = MULTIPLY(d5, - FIX(0.390180644));
+
+ tmp0 = z3 + z5;
+ tmp1 += z2;
+ tmp2 += z2;
+ tmp3 = z4 + z5;
+ }
+ } else {
+ if (d1) {
+ /* d1 != 0, d3 == 0, d5 != 0, d7 == 0 */
+ z4 = d5 + d1;
+ z5 = MULTIPLY(z4, FIX(1.175875602));
+
+ tmp1 = MULTIPLY(d5, - FIX2(0.509795578));
+ tmp3 = MULTIPLY(d1, FIX2(0.601344887));
+ z1 = MULTIPLY(d1, - FIX(0.899976223));
+ z2 = MULTIPLY(d5, - FIX(2.562915447));
+ z4 = MULTIPLY(z4, FIX2(0.785694958));
+
+ tmp0 = z1 + z5;
+ tmp1 += z4;
+ tmp2 = z2 + z5;
+ tmp3 += z4;
+ } else {
+ /* d1 == 0, d3 == 0, d5 != 0, d7 == 0 */
+ tmp0 = MULTIPLY(d5, FIX(1.175875602));
+ tmp1 = MULTIPLY(d5, FIX2(0.275899380));
+ tmp2 = MULTIPLY(d5, - FIX2(1.387039845));
+ tmp3 = MULTIPLY(d5, FIX2(0.785694958));
+ }
+ }
+ } else {
+ if (d3) {
+ if (d1) {
+ /* d1 != 0, d3 != 0, d5 == 0, d7 == 0 */
+ z5 = d3 + d1;
+
+ tmp2 = MULTIPLY(d3, - FIX(1.451774981));
+ tmp3 = MULTIPLY(d1, (FIX(0.211164243) - 1));
+ z1 = MULTIPLY(d1, FIX(1.061594337));
+ z2 = MULTIPLY(d3, - FIX(2.172734803));
+ z4 = MULTIPLY(z5, FIX(0.785694958));
+ z5 = MULTIPLY(z5, FIX(1.175875602));
+
+ tmp0 = z1 - z4;
+ tmp1 = z2 + z4;
+ tmp2 += z5;
+ tmp3 += z5;
+ } else {
+ /* d1 == 0, d3 != 0, d5 == 0, d7 == 0 */
+ tmp0 = MULTIPLY(d3, - FIX2(0.785694958));
+ tmp1 = MULTIPLY(d3, - FIX2(1.387039845));
+ tmp2 = MULTIPLY(d3, - FIX2(0.275899379));
+ tmp3 = MULTIPLY(d3, FIX(1.175875602));
+ }
+ } else {
+ if (d1) {
+ /* d1 != 0, d3 == 0, d5 == 0, d7 == 0 */
+ tmp0 = MULTIPLY(d1, FIX2(0.275899379));
+ tmp1 = MULTIPLY(d1, FIX2(0.785694958));
+ tmp2 = MULTIPLY(d1, FIX(1.175875602));
+ tmp3 = MULTIPLY(d1, FIX2(1.387039845));
+ } else {
+ /* d1 == 0, d3 == 0, d5 == 0, d7 == 0 */
+ tmp0 = tmp1 = tmp2 = tmp3 = 0;
+ }
+ }
+ }
+ }
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp3,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp10 - tmp3,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp11 + tmp2,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp11 - tmp2,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp12 + tmp1,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12 - tmp1,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp13 + tmp0,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp13 - tmp0,
+ CONST_BITS+PASS1_BITS+3);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+#else
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * j_rev_dct --
+ *
+ * The original inverse DCT function.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+void j_rev_dct (DCTBLOCK data)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3;
+ INT32 tmp10, tmp11, tmp12, tmp13;
+ INT32 z1, z2, z3, z4, z5;
+ register DCTELEM *dataptr;
+ int rowctr;
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true IDCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+
+ dataptr = data;
+ for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
+ /* Due to quantization, we will usually find that many of the input
+ * coefficients are zero, especially the AC terms. We can exploit this
+ * by short-circuiting the IDCT calculation for any row in which all
+ * the AC terms are zero. In that case each output is equal to the
+ * DC coefficient (with scale factor as needed).
+ * With typical images and quantization tables, half or more of the
+ * row DCT calculations can be simplified this way.
+ */
+
+ if ((dataptr[1] | dataptr[2] | dataptr[3] | dataptr[4] |
+ dataptr[5] | dataptr[6] | dataptr[7]) == 0) {
+ /* AC terms all zero */
+ DCTELEM dcval = (DCTELEM) (dataptr[0] << PASS1_BITS);
+
+ dataptr[0] = dcval;
+ dataptr[1] = dcval;
+ dataptr[2] = dcval;
+ dataptr[3] = dcval;
+ dataptr[4] = dcval;
+ dataptr[5] = dcval;
+ dataptr[6] = dcval;
+ dataptr[7] = dcval;
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ continue;
+ }
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+
+ z2 = (INT32) dataptr[2];
+ z3 = (INT32) dataptr[6];
+
+ z1 = MULTIPLY(z2 + z3, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(z3, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(z2, FIX(0.765366865));
+
+ tmp0 = ((INT32) dataptr[0] + (INT32) dataptr[4]) << CONST_BITS;
+ tmp1 = ((INT32) dataptr[0] - (INT32) dataptr[4]) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+
+ tmp0 = (INT32) dataptr[7];
+ tmp1 = (INT32) dataptr[5];
+ tmp2 = (INT32) dataptr[3];
+ tmp3 = (INT32) dataptr[1];
+
+ z1 = tmp0 + tmp3;
+ z2 = tmp1 + tmp2;
+ z3 = tmp0 + tmp2;
+ z4 = tmp1 + tmp3;
+ z5 = MULTIPLY(z3 + z4, FIX(1.175875602)); /* sqrt(2) * c3 */
+
+ tmp0 = MULTIPLY(tmp0, FIX(0.298631336)); /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp1 = MULTIPLY(tmp1, FIX(2.053119869)); /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp2 = MULTIPLY(tmp2, FIX(3.072711026)); /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp3 = MULTIPLY(tmp3, FIX(1.501321110)); /* sqrt(2) * ( c1+c3-c5-c7) */
+ z1 = MULTIPLY(z1, - FIX(0.899976223)); /* sqrt(2) * (c7-c3) */
+ z2 = MULTIPLY(z2, - FIX(2.562915447)); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, - FIX(1.961570560)); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, - FIX(0.390180644)); /* sqrt(2) * (c5-c3) */
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ dataptr[0] = (DCTELEM) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
+ dataptr[7] = (DCTELEM) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
+ dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
+ dataptr[6] = (DCTELEM) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
+ dataptr[2] = (DCTELEM) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
+ dataptr[5] = (DCTELEM) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
+ dataptr[3] = (DCTELEM) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
+ dataptr[4] = (DCTELEM) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns. */
+ /* Note that we must descale the results by a factor of 8 == 2**3, */
+ /* and also undo the PASS1_BITS scaling. */
+
+ dataptr = data;
+ for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
+ /* Columns of zeroes can be exploited in the same way as we did with rows.
+ * However, the row calculation has created many nonzero AC terms, so the
+ * simplification applies less often (typically 5% to 10% of the time).
+ * On machines with very fast multiplication, it's possible that the
+ * test takes more time than it's worth. In that case this section
+ * may be commented out.
+ */
+
+#ifndef NO_ZERO_COLUMN_TEST
+ if ((dataptr[DCTSIZE*1] | dataptr[DCTSIZE*2] | dataptr[DCTSIZE*3] |
+ dataptr[DCTSIZE*4] | dataptr[DCTSIZE*5] | dataptr[DCTSIZE*6] |
+ dataptr[DCTSIZE*7]) == 0) {
+ /* AC terms all zero */
+ DCTELEM dcval = (DCTELEM) DESCALE((INT32) dataptr[0], PASS1_BITS+3);
+
+ dataptr[DCTSIZE*0] = dcval;
+ dataptr[DCTSIZE*1] = dcval;
+ dataptr[DCTSIZE*2] = dcval;
+ dataptr[DCTSIZE*3] = dcval;
+ dataptr[DCTSIZE*4] = dcval;
+ dataptr[DCTSIZE*5] = dcval;
+ dataptr[DCTSIZE*6] = dcval;
+ dataptr[DCTSIZE*7] = dcval;
+
+ dataptr++; /* advance pointer to next column */
+ continue;
+ }
+#endif
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+
+ z2 = (INT32) dataptr[DCTSIZE*2];
+ z3 = (INT32) dataptr[DCTSIZE*6];
+
+ z1 = MULTIPLY(z2 + z3, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(z3, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(z2, FIX(0.765366865));
+
+ tmp0 = ((INT32) dataptr[DCTSIZE*0] + (INT32) dataptr[DCTSIZE*4]) << CONST_BITS;
+ tmp1 = ((INT32) dataptr[DCTSIZE*0] - (INT32) dataptr[DCTSIZE*4]) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+
+ tmp0 = (INT32) dataptr[DCTSIZE*7];
+ tmp1 = (INT32) dataptr[DCTSIZE*5];
+ tmp2 = (INT32) dataptr[DCTSIZE*3];
+ tmp3 = (INT32) dataptr[DCTSIZE*1];
+
+ z1 = tmp0 + tmp3;
+ z2 = tmp1 + tmp2;
+ z3 = tmp0 + tmp2;
+ z4 = tmp1 + tmp3;
+ z5 = MULTIPLY(z3 + z4, FIX(1.175875602)); /* sqrt(2) * c3 */
+
+ tmp0 = MULTIPLY(tmp0, FIX(0.298631336)); /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp1 = MULTIPLY(tmp1, FIX(2.053119869)); /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp2 = MULTIPLY(tmp2, FIX(3.072711026)); /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp3 = MULTIPLY(tmp3, FIX(1.501321110)); /* sqrt(2) * ( c1+c3-c5-c7) */
+ z1 = MULTIPLY(z1, - FIX(0.899976223)); /* sqrt(2) * (c7-c3) */
+ z2 = MULTIPLY(z2, - FIX(2.562915447)); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, - FIX(1.961570560)); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, - FIX(0.390180644)); /* sqrt(2) * (c5-c3) */
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp3,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp10 - tmp3,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp11 + tmp2,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp11 - tmp2,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp12 + tmp1,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12 - tmp1,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp13 + tmp0,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp13 - tmp0,
+ CONST_BITS+PASS1_BITS+3);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+
+#endif /* ORIG_DCT */
+#endif /* FIVE_DCT */
+
diff --git a/mpeglib/lib/mpegplay/jrevdct.h b/mpeglib/lib/mpegplay/jrevdct.h
new file mode 100644
index 00000000..d280c2ce
--- /dev/null
+++ b/mpeglib/lib/mpegplay/jrevdct.h
@@ -0,0 +1,57 @@
+/*
+ definittion for reverse dct
+ Copyright (C) 1999 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#ifndef __JREVDCT_H
+#define __JREVDCT_H
+
+extern "C" {
+#include <string.h>
+}
+
+#include "proto.h"
+
+
+#ifndef XMD_H
+typedef int INT32;
+typedef short INT16;
+typedef char INT8;
+#endif
+typedef unsigned int UINT32;
+typedef unsigned short UINT16;
+typedef unsigned char UINT8;
+
+
+
+/* Definition of Contant integer scale factor. */
+
+#define CONST_BITS 13
+
+/* Misc DCT definitions */
+#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */
+#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */
+
+#define GLOBAL /* a function referenced thru EXTERNs */
+
+typedef short DCTELEM;
+typedef DCTELEM DCTBLOCK[DCTSIZE2];
+
+
+/* jrevdct.c */
+void init_pre_idct (void);
+void j_rev_dct_sparse (DCTBLOCK data , int pos);
+void j_rev_dct (DCTBLOCK data);
+void j_rev_dct_sparse (DCTBLOCK data , int pos);
+void j_rev_dct (DCTBLOCK data);
+
+
+#endif
diff --git a/mpeglib/lib/mpegplay/macroBlock.cpp b/mpeglib/lib/mpegplay/macroBlock.cpp
new file mode 100644
index 00000000..2e35e551
--- /dev/null
+++ b/mpeglib/lib/mpegplay/macroBlock.cpp
@@ -0,0 +1,1152 @@
+/*
+ stores macroblock infos
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "macroBlock.h"
+
+#define DEBUG_MACROBLOCK(x)
+//#define DEBUG_MACROBLOCK(x) x
+
+
+
+MacroBlock::MacroBlock(VideoDecoder* vid_stream) {
+ this->vid_stream=vid_stream;
+ copyFunctions=new CopyFunctions();
+}
+
+
+MacroBlock::~MacroBlock() {
+ delete copyFunctions;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ParseMacroBlock --
+ *
+ * Parseoff macroblock. Reconstructs DCT values. Applies
+ * inverse DCT, reconstructs motion vectors, calculates and
+ * set pixel values for macroblock in current pict image
+ * structure.
+ *
+ * Results:
+ * Here's where everything really happens. Welcome to the
+ * heart of darkness.
+ *
+ * Side effects:
+ * Bit stream irreversibly parsed off.
+ *
+ *--------------------------------------------------------------
+ */
+
+int MacroBlock::processMacroBlock(PictureArray* pictureArray) {
+ unsigned int data;
+ int recon_right_for, recon_down_for, recon_right_back,
+ recon_down_back;
+ int mb_quant = 0, mb_motion_forw = 0, mb_motion_back = 0,
+ mb_pattern = 0;
+
+ int addr_incr;
+ MpegVideoStream* mpegVideoStream=vid_stream->mpegVideoStream;
+ DecoderClass* decoderClass=vid_stream->decoderClass;
+
+ /*
+ * Parse off macroblock address increment and add to macroblock address.
+ */
+ do {
+ addr_incr=decoderClass->decodeMBAddrInc();
+ if (addr_incr==MB_ESCAPE) {
+ mb_address += 33;
+ addr_incr=MB_STUFFING;
+ }
+
+ } while (addr_incr == MB_STUFFING);
+ mb_address+=addr_incr;
+
+
+
+ if (mb_address > (vid_stream->mpegVideoHeader)->getMB_Size()) {
+
+ DEBUG_MACROBLOCK(cout <<"ParseMacroBlock: SKIP_TO_START_CODE"<<endl;)
+ DEBUG_MACROBLOCK(cout <<"mb_address "<<mb_address<<endl;)
+
+ int h=(vid_stream->mpegVideoHeader)->getMB_Height();
+ int w=(vid_stream->mpegVideoHeader)->getMB_Width();
+
+
+ DEBUG_MACROBLOCK(cout <<"mb_height*mb_width-1:"<<(h*w - 1)<<endl;)
+ return false;
+ }
+
+ /*
+ * If macroblocks have been skipped, process skipped macroblocks.
+ */
+
+ int code_type=(vid_stream->picture)->getCodeType();
+
+ if (mb_address - past_mb_addr > 1) {
+
+ processSkippedPictures(pictureArray,code_type,
+ (vid_stream->mpegVideoHeader)->getMB_Width());
+
+ }
+
+
+ /* Set past macroblock address to current macroblock address. */
+ past_mb_addr = mb_address;
+ /* Based on picture type decode macroblock type. */
+
+
+ switch (code_type) {
+ case I_TYPE:
+ decoderClass->decodeMBTypeI(mb_quant, mb_motion_forw,
+ mb_motion_back, mb_pattern,
+ mb_intra);
+ break;
+
+ case P_TYPE:
+ decoderClass->decodeMBTypeP(mb_quant, mb_motion_forw,
+ mb_motion_back, mb_pattern,
+ mb_intra);
+ break;
+
+ case B_TYPE:
+ decoderClass->decodeMBTypeB(mb_quant, mb_motion_forw,
+ mb_motion_back, mb_pattern,
+ mb_intra);
+ break;
+ case D_TYPE:
+ DEBUG_MACROBLOCK(cout <<"ERROR: MPEG-1 Streams with D-frames are not supported"<<endl;)
+ return false;
+
+ }
+ /* If quantization flag set, parse off new quantization scale. */
+ if (mb_quant == true) {
+ data=mpegVideoStream->getBits(5);
+ (vid_stream->slice)->setQuantScale(data);
+ }
+ /* If forward motion vectors exist... */
+
+ if (mb_motion_forw == true) {
+ // Parse off and decode horizontal forward motion vector.
+ motion_h_forw_code=decoderClass->decodeMotionVectors();
+
+ // If horiz. forward r data exists, parse off.
+
+ if ((vid_stream->picture->getForw_f() != 1) &&
+ (motion_h_forw_code != 0)) {
+ data=vid_stream->picture->geth_forw_r(mpegVideoStream);
+ motion_h_forw_r = data;
+ }
+ // Parse off and decode vertical forward motion vector.
+
+ motion_v_forw_code=decoderClass->decodeMotionVectors();
+
+ // If vert. forw. r data exists, parse off.
+
+ if ((vid_stream->picture->getForw_f() != 1) &&
+ (motion_v_forw_code != 0)) {
+
+ data=vid_stream->picture->getv_forw_r(mpegVideoStream);
+ motion_v_forw_r = data;
+ }
+ }
+
+ /* If back motion vectors exist... */
+
+ if (mb_motion_back == true) {
+ // Parse off and decode horiz. back motion vector.
+ motion_h_back_code=decoderClass->decodeMotionVectors();
+
+ // If horiz. back r data exists, parse off.
+
+ if ((vid_stream->picture->getBack_f() != 1) &&
+ (motion_h_back_code != 0)) {
+ data=vid_stream->picture->geth_back_r(mpegVideoStream);
+ motion_h_back_r = data;
+ }
+ // Parse off and decode vert. back motion vector.
+ motion_v_back_code=decoderClass->decodeMotionVectors();
+
+ // If vert. back r data exists, parse off.
+
+ if ((vid_stream->picture->getBack_f() != 1) &&
+ (motion_v_back_code != 0)) {
+ data=vid_stream->picture->getv_back_r(mpegVideoStream);
+ motion_v_back_r = data;
+ }
+ }
+
+ /* If mblock pattern flag set, parse and decode CBP (code block pattern). */
+ if (mb_pattern == true) {
+ cbp=decoderClass->decodeCBP();
+ }
+ /* Otherwise, set CBP to zero. */
+ else
+ cbp = 0;
+
+
+
+ /* Reconstruct motion vectors depending on picture type. */
+ if (code_type == P_TYPE) {
+
+ /*
+ * If no forw motion vectors, reset previous and current vectors to 0.
+ */
+ if (!mb_motion_forw) {
+ recon_right_for = 0;
+ recon_down_for = 0;
+ recon_right_for_prev = 0;
+ recon_down_for_prev = 0;
+ }
+ /*
+ * Otherwise, compute new forw motion vectors. Reset previous vectors to
+ * current vectors.
+ */
+
+ else {
+ computeForwVector(&recon_right_for, &recon_down_for);
+
+ }
+ }
+ if (code_type == B_TYPE) {
+
+ /* Reset prev. and current vectors to zero if mblock is intracoded. */
+ if (mb_intra) {
+ recon_right_for_prev = 0;
+ recon_down_for_prev = 0;
+ recon_right_back_prev = 0;
+ recon_down_back_prev = 0;
+ } else {
+
+ /* If no forw vectors, current vectors equal prev. vectors. */
+
+ if (!mb_motion_forw) {
+ recon_right_for = recon_right_for_prev;
+ recon_down_for = recon_down_for_prev;
+ }
+ /*
+ * Otherwise compute forw. vectors. Reset prev vectors to new values.
+ */
+
+ else {
+ computeForwVector(&recon_right_for, &recon_down_for);
+
+ }
+
+ /* If no back vectors, set back vectors to prev back vectors. */
+
+ if (!mb_motion_back) {
+ recon_right_back = recon_right_back_prev;
+ recon_down_back = recon_down_back_prev;
+ }
+ /* Otherwise compute new vectors and reset prev. back vectors. */
+
+ else {
+ computeBackVector(&recon_right_back,&recon_down_back);
+
+ }
+
+ /*
+ * Store vector existence flags in structure for possible skipped
+ * macroblocks to follow.
+ */
+
+ bpict_past_forw = mb_motion_forw;
+ bpict_past_back = mb_motion_back;
+ }
+ }
+ int back;
+ back=reconstruct(recon_right_for,
+ recon_down_for,
+ recon_right_back,
+ recon_down_back,
+ mb_motion_forw,
+ mb_motion_back,
+ pictureArray);
+
+
+ /* If D Type picture, flush marker bit. */
+ if (code_type == D_TYPE) {
+ mpegVideoStream->flushBits(1);
+ }
+
+ /* If macroblock was intracoded, set macroblock past intra address. */
+ if (mb_intra) {
+ past_intra_addr=mb_address;
+ }
+ if (back == false) {
+ return false;
+ }
+ return true;
+}
+
+
+int MacroBlock::resetMacroBlock() {
+ /* Reset past intrablock address. */
+ past_intra_addr = -2;
+
+ /* Reset previous recon motion vectors. */
+
+
+ recon_right_for_prev = 0;
+ recon_down_for_prev = 0;
+ recon_right_back_prev = 0;
+ recon_down_back_prev = 0;
+
+ /* Reset macroblock address. */
+ mb_address = (((vid_stream->slice)->getVertPos()-1) *
+ (vid_stream->mpegVideoHeader)->getMB_Width()) - 1;
+ return true;
+
+}
+
+
+int MacroBlock::resetPastMacroBlock() {
+ /* Reset past macroblock address field. */
+
+ past_mb_addr = -1;
+ return true;
+}
+
+
+
+
+int MacroBlock::reconstruct(int& recon_right_for,
+ int& recon_down_for,
+ int& recon_right_back,
+ int& recon_down_back,
+ int& mb_motion_forw,
+ int& mb_motion_back,
+ PictureArray* pictureArray) {
+ int mask, i;
+ int zero_block_flag;
+ int mb_row;
+ int mb_col;
+ int mb_width=(vid_stream->mpegVideoHeader)->getMB_Width();
+ int row_size=pictureArray->getWidth();
+ short int* dct_start=(vid_stream->decoderClass)->getDCT();
+ unsigned int qscale=(vid_stream->slice)->getQuantScale();
+ int codeType=(vid_stream->picture)->getCodeType();
+ DecoderClass* decoderClass=vid_stream->decoderClass;
+ int lflag=false;
+ Recon* recon=vid_stream->recon;
+ unsigned int* iqmatrixptr=
+ (vid_stream->mpegVideoHeader)->getIntra_quant_matrix();
+ unsigned int* niqmatrixptr=
+ (vid_stream->mpegVideoHeader)->getNon_intra_quant_matrix();
+
+
+
+
+
+ if (mb_address-past_intra_addr > 1) {
+ lflag=true;
+ }
+
+ if (mb_width <= 0) {
+ DEBUG_MACROBLOCK(cout << "mb_width <= 0"<<endl;)
+ return false;
+ }
+ /* Calculate macroblock row and column from address. */
+ mb_row=mb_address / mb_width;
+ mb_col=mb_address % mb_width;
+
+ copyFunctions->startNOFloatSection();
+
+ for (mask = 32, i = 0; i < 6; mask >>= 1, i++) {
+
+
+ /* If block exists... */
+ if ((mb_intra) || (cbp & mask)) {
+ zero_block_flag = 0;
+ //copyFunctions->endNOFloatSection();
+ decoderClass->ParseReconBlock(i,mb_intra,
+ qscale,lflag,iqmatrixptr,niqmatrixptr);
+ //copyFunctions->endNOFloatSection();
+ } else {
+ zero_block_flag = 1;
+ }
+
+
+ // If macroblock is intra coded...
+
+
+ if (mb_intra) {
+ recon->ReconIMBlock(i,mb_row,mb_col,row_size,
+ dct_start,pictureArray);
+ //copyFunctions->endNOFloatSection();
+ } else if (mb_motion_forw && mb_motion_back) {
+ recon->ReconBiMBlock(i,recon_right_for,
+ recon_down_for,recon_right_back,
+ recon_down_back,zero_block_flag,
+ mb_row,mb_col,row_size,dct_start,
+ pictureArray);
+ //copyFunctions->endNOFloatSection();
+ } else if (mb_motion_forw || (codeType ==P_TYPE)){
+ recon->ReconPMBlock(i,recon_right_for,
+ recon_down_for,zero_block_flag,
+ mb_row,mb_col,row_size,dct_start,
+ pictureArray, codeType);
+ //copyFunctions->endNOFloatSection();
+ } else if (mb_motion_back) {
+ recon->ReconBMBlock(i,recon_right_back,
+ recon_down_back,zero_block_flag,
+ mb_row,mb_col,row_size,dct_start,
+ pictureArray);
+ //copyFunctions->endNOFloatSection();
+
+ } else {
+ //DEBUG_MACROBLOCK(cout << "nothing"<<endl;)
+ }
+
+ }
+ copyFunctions->endNOFloatSection();
+ return true;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ComputeForwVector --
+ *
+ * Computes forward motion vector by calling ComputeVector
+ * with appropriate parameters.
+ *
+ * Results:
+ * Reconstructed motion vector placed in recon_right_for_ptr and
+ * recon_down_for_ptr.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void MacroBlock::computeForwVector(int* recon_right_for_ptr,
+ int* recon_down_for_ptr) {
+
+ Picture *picture;
+
+
+ picture = vid_stream->picture;
+
+
+ unsigned int forw_f=picture->getForw_f();
+ unsigned int full_pel_forw_vector=picture->getFull_pel_forw_vector();
+ vid_stream->motionVector->computeVector(recon_right_for_ptr,
+ recon_down_for_ptr,
+ recon_right_for_prev,
+ recon_down_for_prev,
+ forw_f,
+ full_pel_forw_vector,
+ motion_h_forw_code,
+ motion_v_forw_code,
+ motion_h_forw_r,
+ motion_v_forw_r);
+ picture->setForw_f(forw_f);
+ picture->setFull_pel_forw_vector(full_pel_forw_vector);
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ComputeBackVector --
+ *
+ * Computes backward motion vector by calling ComputeVector
+ * with appropriate parameters.
+ *
+ * Results:
+ * Reconstructed motion vector placed in recon_right_back_ptr and
+ * recon_down_back_ptr.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void MacroBlock::computeBackVector(int* recon_right_back_ptr,
+ int* recon_down_back_ptr) {
+
+ Picture *picture;
+
+
+ picture = vid_stream->picture;
+
+
+ unsigned int back_f=picture->getBack_f();
+ unsigned int full_pel_back_vector=picture->getFull_pel_back_vector();
+
+ vid_stream->motionVector->computeVector(recon_right_back_ptr,
+ recon_down_back_ptr,
+ recon_right_back_prev,
+ recon_down_back_prev,
+ back_f,
+ full_pel_back_vector,
+ motion_h_back_code,
+ motion_v_back_code,
+ motion_h_back_r,
+ motion_v_back_r);
+ picture->setBack_f(back_f);
+ picture->setFull_pel_back_vector(full_pel_back_vector);
+}
+
+
+
+
+
+int MacroBlock::processSkippedPictures(PictureArray* pictureArray,
+ int code_type,
+ int mb_width) {
+ copyFunctions->startNOFloatSection();
+
+ if (code_type == P_TYPE) {
+
+ ProcessSkippedPFrameMBlocks(pictureArray->getCurrent(),
+ pictureArray->getFuture(),
+ mb_width);
+
+ } else {
+ if (code_type == B_TYPE) {
+ ProcessSkippedBFrameMBlocks(vid_stream->picture,
+ pictureArray->getPast(),
+ pictureArray->getCurrent(),
+ pictureArray->getFuture(),
+ mb_width);
+ }
+ }
+
+ copyFunctions->endNOFloatSection();
+
+ return true;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ProcessSkippedPFrameMBlocks --
+ *
+ * Processes skipped macroblocks in P frames.
+ *
+ * Results:
+ * Calculates pixel values for luminance, Cr, and Cb planes
+ * in current pict image for skipped macroblocks.
+ *
+ * Side effects:
+ * Pixel values in pict image changed.
+ *
+ *--------------------------------------------------------------
+ */
+void MacroBlock::ProcessSkippedPFrameMBlocks(YUVPicture* current,
+ YUVPicture* future,
+ int mb_width) {
+
+ int row_size, half_row, mb_row, mb_col, row, col, rr;
+ int addr, row_incr, half_row_incr, crow, ccol;
+ int *dest, *src, *dest1, *src1;
+
+ /* For each row in macroblock luminance plane... */
+ if (mb_width == 0) {
+ DEBUG_MACROBLOCK(cout << "mb_width in skipped is 0"<<endl;)
+ return;
+ }
+
+
+ /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
+
+ row_size = mb_width << 4;
+ half_row = (row_size >> 1);
+ row_incr = row_size >> 2;
+ half_row_incr = half_row >> 2;
+
+ /* For each skipped macroblock, do... */
+ int lumEnd=current->getLumLength();
+ int colorEnd=current->getColorLength();
+
+ unsigned char *picDest;
+ unsigned char *picSrc;
+
+ unsigned char *picDestStart;
+ unsigned char *picSrcStart;
+
+
+
+ for (addr = past_mb_addr + 1; addr < mb_address; addr++) {
+
+ /* Calculate macroblock row and col. */
+
+ mb_row = addr / mb_width;
+ mb_col = addr % mb_width;
+
+ /* Calculate upper left pixel row,col for luminance plane. */
+
+ row = mb_row << 4;
+ col = mb_col << 4;
+
+ picDest=current->getLuminancePtr();
+ picSrc=future->getLuminancePtr();
+
+ picDestStart=(picDest+(row*row_size)+col);
+ picSrcStart=(picSrc+(row*row_size)+col);
+
+ if ((picDestStart+7*row_size+7 >= picDest+lumEnd) ||
+ (picDestStart < picDest)) {
+ DEBUG_MACROBLOCK(cout << "urg! last resort caught before sigsev skipped -1"<<endl;)
+ break;
+ }
+ if ((picSrcStart+7*row_size+7 >= picSrc+lumEnd) ||
+ (picSrcStart < picSrc)) {
+ DEBUG_MACROBLOCK(cout << "urg! last resort caught before sigsev skipped -2"<<endl;)
+ break;
+ }
+
+ dest=(int*)picDestStart;
+ src=(int*)picSrcStart;
+
+
+
+ for (rr = 0; rr < 8; rr++) {
+
+ /* Copy pixel values from last I or P picture. */
+ memcpy(dest,src,sizeof(int)*4);
+
+ dest += row_incr;
+ src += row_incr;
+ memcpy(dest,src,sizeof(int)*4);
+
+ dest += row_incr;
+ src += row_incr;
+ }
+
+ /*
+ * Divide row,col to get upper left pixel of macroblock in Cr and Cb
+ * planes.
+ */
+
+ crow = row >> 1;
+ ccol = col >> 1;
+
+ /* For each row in Cr, and Cb planes... */
+ picDest=current->getCrPtr();
+ picDestStart=(picDest+(crow*half_row)+ccol);
+ if ((picDestStart+7*half_row_incr+7 >= picDest+colorEnd) ||
+ (picDestStart < picDest)) {
+ DEBUG_MACROBLOCK(cout << "urg! last resort caught before sigsev skipped -3"<<endl;)
+ break;
+ }
+
+
+ dest=(int*)(current->getCrPtr()+(crow*half_row)+ccol);
+ src=(int*)(future->getCrPtr()+(crow*half_row)+ccol);
+ dest1=(int*)(current->getCbPtr()+(crow*half_row)+ccol);
+ src1=(int*)(future->getCbPtr()+(crow*half_row)+ccol);
+
+ for (rr = 0; rr < 4; rr++) {
+
+ /* Copy pixel values from last I or P picture. */
+ memcpy(dest,src,sizeof(int)*2);
+ memcpy(dest1,src1,sizeof(int)*2);
+
+
+ dest += half_row_incr;
+ src += half_row_incr;
+ dest1 += half_row_incr;
+ src1 += half_row_incr;
+
+ memcpy(dest,src,sizeof(int)*2);
+ memcpy(dest1,src1,sizeof(int)*2);
+
+ dest += half_row_incr;
+ src += half_row_incr;
+ dest1 += half_row_incr;
+ src1 += half_row_incr;
+ }
+
+ }
+
+ recon_right_for_prev = 0;
+ recon_down_for_prev = 0;
+
+}
+
+
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ProcessSkippedBFrameMBlocks --
+ *
+ * Processes skipped macroblocks in B frames.
+ *
+ * Results:
+ * Calculates pixel values for luminance, Cr, and Cb planes
+ * in current pict image for skipped macroblocks.
+ *
+ * Side effects:
+ * Pixel values in pict image changed.
+ *
+ *--------------------------------------------------------------
+ */
+
+void MacroBlock::ProcessSkippedBFrameMBlocks(Picture* picture,
+ YUVPicture* past,
+ YUVPicture* current,
+ YUVPicture* future,
+ int mb_width) {
+ int row_size, half_row, mb_row, mb_col, row, col, rr;
+ int right_half_for = 0, down_half_for = 0;
+ int c_right_half_for = 0, c_down_half_for = 0;
+ int right_half_back = 0, down_half_back = 0;
+ int c_right_half_back = 0, c_down_half_back = 0;
+ int addr, right_for = 0, down_for = 0;
+ int recon_right_for, recon_down_for;
+ int recon_right_back, recon_down_back;
+ int right_back = 0, down_back = 0;
+ int c_right_for = 0, c_down_for = 0;
+ int c_right_back = 0, c_down_back = 0;
+ unsigned char forw_lum[256];
+ unsigned char forw_cr[64], forw_cb[64];
+ unsigned char back_lum[256], back_cr[64], back_cb[64];
+ int row_incr, half_row_incr;
+ int ccol, crow;
+
+
+ /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
+
+ if (mb_width == 0) {
+ DEBUG_MACROBLOCK(cout << "mb_width in skipped is 0 (2)"<<endl;)
+ return;
+ }
+
+ row_size = mb_width << 4;
+ half_row = (row_size >> 1);
+ row_incr = row_size >> 2;
+ half_row_incr = half_row >> 2;
+
+ /* Establish motion vector codes based on full pixel flag. */
+
+ if (picture->getFull_pel_forw_vector()) {
+ recon_right_for = recon_right_for_prev << 1;
+ recon_down_for = recon_down_for_prev << 1;
+ } else {
+ recon_right_for = recon_right_for_prev;
+ recon_down_for = recon_down_for_prev;
+ }
+
+ if (picture->getFull_pel_back_vector()) {
+ recon_right_back = recon_right_back_prev << 1;
+ recon_down_back = recon_down_back_prev << 1;
+ } else {
+ recon_right_back = recon_right_back_prev;
+ recon_down_back = recon_down_back_prev;
+ }
+
+
+ /* If only one motion vector, do display copy, else do full
+ calculation.
+ */
+
+ /* Calculate motion vectors. */
+
+ if (bpict_past_forw) {
+ right_for = recon_right_for >> 1;
+ down_for = recon_down_for >> 1;
+ right_half_for = recon_right_for & 0x1;
+ down_half_for = recon_down_for & 0x1;
+
+ recon_right_for /= 2;
+ recon_down_for /= 2;
+ c_right_for = recon_right_for >> 1;
+ c_down_for = recon_down_for >> 1;
+ c_right_half_for = recon_right_for & 0x1;
+ c_down_half_for = recon_down_for & 0x1;
+
+ }
+ if (bpict_past_back) {
+ right_back = recon_right_back >> 1;
+ down_back = recon_down_back >> 1;
+ right_half_back = recon_right_back & 0x1;
+ down_half_back = recon_down_back & 0x1;
+
+ recon_right_back /= 2;
+ recon_down_back /= 2;
+ c_right_back = recon_right_back >> 1;
+ c_down_back = recon_down_back >> 1;
+ c_right_half_back = recon_right_back & 0x1;
+ c_down_half_back = recon_down_back & 0x1;
+
+ }
+ /* For each skipped macroblock, do... */
+
+ for (addr = past_mb_addr + 1;
+ addr < mb_address; addr++) {
+
+ /* Calculate macroblock row and col. */
+
+ mb_row = addr / mb_width;
+ mb_col = addr % mb_width;
+
+ /* Calculate upper left pixel row,col for luminance plane. */
+
+ row = mb_row << 4;
+ col = mb_col << 4;
+ crow = row / 2;
+ ccol = col / 2;
+
+ /* If forward predicted, calculate prediction values. */
+ if (bpict_past_forw) {
+ int lumEnd=current->getLumLength();
+ int colorEnd=current->getColorLength();
+ ReconSkippedBlock(past->getLuminancePtr(),
+ forw_lum,row,col,row_size,
+ right_for,down_for,
+ right_half_for,
+ down_half_for,16,lumEnd);
+ ReconSkippedBlock(past->getCrPtr(),
+ forw_cr,crow,ccol, half_row,
+ c_right_for,c_down_for,
+ c_right_half_for,
+ c_down_half_for,8,colorEnd);
+ ReconSkippedBlock(past->getCbPtr(),
+ forw_cb,crow,ccol,half_row,
+ c_right_for,c_down_for,
+ c_right_half_for,
+ c_down_half_for,8,colorEnd);
+ }
+ /* If back predicted, calculate prediction values. */
+
+ if (bpict_past_back) {
+ int lumEnd=current->getLumLength();
+ int colorEnd=current->getColorLength();
+ ReconSkippedBlock(future->getLuminancePtr(),
+ back_lum,row,col,row_size,
+ right_back,down_back,
+ right_half_back,down_half_back,
+ 16,lumEnd);
+ ReconSkippedBlock(future->getCrPtr(),
+ back_cr,crow,ccol,
+ half_row,c_right_back,
+ c_down_back,c_right_half_back,
+ c_down_half_back,8,colorEnd);
+ ReconSkippedBlock(future->getCbPtr(),
+ back_cb,crow,ccol,half_row,
+ c_right_back,c_down_back,
+ c_right_half_back,
+ c_down_half_back,8,colorEnd);
+ }
+ unsigned char* picDest=current->getLuminancePtr();
+ int lumEnd=current->getLumLength();
+ int colorEnd=current->getColorLength();
+
+ unsigned char* picDestStart=(picDest+(row*row_size)+col);
+
+
+ if ((picDestStart+7*row_size+7 >= picDest+lumEnd) ||
+ (picDestStart < picDest)) {
+ DEBUG_MACROBLOCK(cout << "urg! last resort caught before sigsev skipped -4"<<endl;)
+ return;
+ }
+
+ picDest=current->getCrPtr();
+ picDestStart=(picDest+(crow*half_row)+ccol);
+ if ((picDestStart+7*half_row_incr+7 >= picDest+colorEnd) ||
+ (picDestStart < picDest)) {
+ DEBUG_MACROBLOCK(cout << "urg! last resort caught before sigsev skipped -5"<<endl;)
+ exit(0);
+ }
+
+
+ if (bpict_past_forw && !bpict_past_back) {
+
+ int *dest, *dest1;
+ int *src, *src1;
+ dest=(int*)(current->getLuminancePtr()+(row*row_size)+col);
+ src=(int*)forw_lum;
+
+ for (rr = 0; rr < 16; rr++) {
+
+ /* memcpy(dest, forw_lum+(rr<<4), 16); */
+
+ dest[0] = src[0];
+ dest[1] = src[1];
+ dest[2] = src[2];
+ dest[3] = src[3];
+ dest += row_incr;
+ src += 4;
+ }
+
+ dest = (int*)(current->getCrPtr()+(crow*half_row)+ccol);
+ dest1 = (int*)(current->getCbPtr()+(crow*half_row)+ccol);
+ src = (int*)forw_cr;
+ src1 = (int*)forw_cb;
+
+ for (rr = 0; rr < 8; rr++) {
+ /*
+ * memcpy(dest, forw_cr+(rr<<3), 8); memcpy(dest1, forw_cb+(rr<<3),
+ * 8);
+ */
+
+ dest[0] = src[0];
+ dest[1] = src[1];
+
+ dest1[0] = src1[0];
+ dest1[1] = src1[1];
+
+ dest += half_row_incr;
+ dest1 += half_row_incr;
+ src += 2;
+ src1 += 2;
+ }
+ } else if (bpict_past_back && !bpict_past_forw) {
+
+ int *src, *src1;
+ int *dest, *dest1;
+ dest=(int*)(current->getLuminancePtr()+(row*row_size)+col);
+ src = (int*)back_lum;
+
+ for (rr = 0; rr < 16; rr++) {
+ dest[0] = src[0];
+ dest[1] = src[1];
+ dest[2] = src[2];
+ dest[3] = src[3];
+ dest += row_incr;
+ src += 4;
+ }
+
+
+ dest = (int *)(current->getCrPtr()+(crow*half_row)+ccol);
+ dest1 = (int *)(current->getCbPtr()+(crow*half_row)+ccol);
+ src = (int *)back_cr;
+ src1 = (int *)back_cb;
+
+ for (rr = 0; rr < 8; rr++) {
+ /*
+ * memcpy(dest, back_cr+(rr<<3), 8); memcpy(dest1, back_cb+(rr<<3),
+ * 8);
+ */
+
+ dest[0] = src[0];
+ dest[1] = src[1];
+
+ dest1[0] = src1[0];
+ dest1[1] = src1[1];
+
+ dest += half_row_incr;
+ dest1 += half_row_incr;
+ src += 2;
+ src1 += 2;
+ }
+ } else {
+
+ unsigned char *src1, *src2, *src1a, *src2a;
+ unsigned char *dest, *dest1;
+ dest = current->getLuminancePtr()+(row*row_size)+col;
+ src1 = forw_lum;
+ src2 = back_lum;
+
+ for (rr = 0; rr < 16; rr++) {
+ dest[0] = (int) (src1[0] + src2[0]) >> 1;
+ dest[1] = (int) (src1[1] + src2[1]) >> 1;
+ dest[2] = (int) (src1[2] + src2[2]) >> 1;
+ dest[3] = (int) (src1[3] + src2[3]) >> 1;
+ dest[4] = (int) (src1[4] + src2[4]) >> 1;
+ dest[5] = (int) (src1[5] + src2[5]) >> 1;
+ dest[6] = (int) (src1[6] + src2[6]) >> 1;
+ dest[7] = (int) (src1[7] + src2[7]) >> 1;
+ dest[8] = (int) (src1[8] + src2[8]) >> 1;
+ dest[9] = (int) (src1[9] + src2[9]) >> 1;
+ dest[10] = (int) (src1[10] + src2[10]) >> 1;
+ dest[11] = (int) (src1[11] + src2[11]) >> 1;
+ dest[12] = (int) (src1[12] + src2[12]) >> 1;
+ dest[13] = (int) (src1[13] + src2[13]) >> 1;
+ dest[14] = (int) (src1[14] + src2[14]) >> 1;
+ dest[15] = (int) (src1[15] + src2[15]) >> 1;
+ dest += row_size;
+ src1 += 16;
+ src2 += 16;
+ }
+
+
+ dest = current->getCrPtr() + (crow * half_row) + ccol;
+ dest1 = current->getCbPtr() + (crow * half_row) + ccol;
+ src1 = forw_cr;
+ src2 = back_cr;
+ src1a = forw_cb;
+ src2a = back_cb;
+
+ for (rr = 0; rr < 8; rr++) {
+ dest[0] = (int) (src1[0] + src2[0]) >> 1;
+ dest[1] = (int) (src1[1] + src2[1]) >> 1;
+ dest[2] = (int) (src1[2] + src2[2]) >> 1;
+ dest[3] = (int) (src1[3] + src2[3]) >> 1;
+ dest[4] = (int) (src1[4] + src2[4]) >> 1;
+ dest[5] = (int) (src1[5] + src2[5]) >> 1;
+ dest[6] = (int) (src1[6] + src2[6]) >> 1;
+ dest[7] = (int) (src1[7] + src2[7]) >> 1;
+ dest += half_row;
+ src1 += 8;
+ src2 += 8;
+
+ dest1[0] = (int) (src1a[0] + src2a[0]) >> 1;
+ dest1[1] = (int) (src1a[1] + src2a[1]) >> 1;
+ dest1[2] = (int) (src1a[2] + src2a[2]) >> 1;
+ dest1[3] = (int) (src1a[3] + src2a[3]) >> 1;
+ dest1[4] = (int) (src1a[4] + src2a[4]) >> 1;
+ dest1[5] = (int) (src1a[5] + src2a[5]) >> 1;
+ dest1[6] = (int) (src1a[6] + src2a[6]) >> 1;
+ dest1[7] = (int) (src1a[7] + src2a[7]) >> 1;
+ dest1 += half_row;
+ src1a += 8;
+ src2a += 8;
+ }
+ }
+
+ }
+}
+
+
+
+
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ReconSkippedBlock --
+ *
+ * Reconstructs predictive block for skipped macroblocks
+ * in B Frames.
+ *
+ * Results:
+ * No return values.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+void MacroBlock::ReconSkippedBlock(unsigned char* source,
+ unsigned char* dest,
+ int row,
+ int col,
+ int row_size,
+ int right,
+ int down,
+ int right_half,
+ int down_half,
+ int width,int maxLen) {
+ int rr;
+ unsigned char *source2;
+ unsigned char *tmp;
+
+ tmp = source+((row + down) * row_size) + col + right;
+
+
+ if ((tmp+7*row_size+7 >= source+maxLen) ||
+ (tmp < source)) {
+ DEBUG_MACROBLOCK(cout << "urg! last resort caught before sigsev skipped -6"<<endl;)
+ return;
+ }
+
+ source=tmp;
+ if (width == 16) {
+ if ((!right_half) && (!down_half)) {
+ if (right & 0x1) {
+ /* No alignment, use bye copy */
+ for (rr = 0; rr < 16; rr++) {
+
+ memcpy(dest,source,sizeof(char)*16);
+
+ dest += 16;
+ source += row_size;
+ }
+ } else if (right & 0x2) {
+ /* Half-word bit aligned, use 16 bit copy */
+ short *src = (short *)source;
+ short *d = (short *)dest;
+ row_size >>= 1;
+ for (rr = 0; rr < 16; rr++) {
+
+ memcpy(d,src,sizeof(short)*8);
+
+ d += 8;
+ src += row_size;
+ }
+ } else {
+ /* Word aligned, use 32 bit copy */
+ int *src = (int *)source;
+ int *d = (int *)dest;
+ row_size >>= 2;
+ for (rr = 0; rr < 16; rr++) {
+ d[0] = src[0];
+ d[1] = src[1];
+ d[2] = src[2];
+ d[3] = src[3];
+ d += 4;
+ src += row_size;
+ }
+ }
+ } else {
+ source2 = source + right_half + (row_size * down_half);
+ copyFunctions->copy16_div2_destlinear_nocrop(source,source2,dest,
+ row_size);
+
+
+ }
+ } else { /* (width == 8) */
+ assert(width == 8);
+ if ((!right_half) && (!down_half)) {
+ if (right & 0x1) {
+ for (rr = 0; rr < width; rr++) {
+
+ memcpy(dest,source,sizeof(char)*8);
+
+ dest += 8;
+ source += row_size;
+ }
+ } else if (right & 0x02) {
+ short *d = (short *)dest;
+ short *src = (short *)source;
+ row_size >>= 1;
+ for (rr = 0; rr < width; rr++) {
+ d[0] = src[0];
+ d[1] = src[1];
+ d[2] = src[2];
+ d[3] = src[3];
+ d += 4;
+ src += row_size;
+ }
+ } else {
+ int *d = (int *)dest;
+ int *src = (int *)source;
+ row_size >>= 2;
+ for (rr = 0; rr < width; rr++) {
+ d[0] = src[0];
+ d[1] = src[1];
+ d += 2;
+ src += row_size;
+ }
+ }
+ } else {
+ source2 = source + right_half + (row_size * down_half);
+ copyFunctions->copy8_div2_destlinear_nocrop(source,source2,
+ dest,row_size);
+ }
+ }
+}
+
diff --git a/mpeglib/lib/mpegplay/macroBlock.h b/mpeglib/lib/mpegplay/macroBlock.h
new file mode 100644
index 00000000..db56e7be
--- /dev/null
+++ b/mpeglib/lib/mpegplay/macroBlock.h
@@ -0,0 +1,97 @@
+/*
+ stores macroblock infos
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+
+#ifndef __MACROBLOCK_H
+#define __MACROBLOCK_H
+
+#include "videoDecoder.h"
+#include "decoderClass.h"
+#include "motionVector.h"
+#include "recon.h"
+#include "copyFunctions.h"
+
+class MacroBlock {
+
+ /* Macroblock structure. */
+
+ int mb_address; /* Macroblock address. */
+ int past_mb_addr; /* Previous mblock address. */
+ int motion_h_forw_code; /* Forw. horiz. motion vector code. */
+ unsigned int motion_h_forw_r; /* Used in decoding vectors. */
+ int motion_v_forw_code; /* Forw. vert. motion vector code. */
+ unsigned int motion_v_forw_r; /* Used in decdoinge vectors. */
+ int motion_h_back_code; /* Back horiz. motion vector code. */
+ unsigned int motion_h_back_r; /* Used in decoding vectors. */
+ int motion_v_back_code; /* Back vert. motion vector code. */
+ unsigned int motion_v_back_r; /* Used in decoding vectors. */
+ unsigned int cbp; /* Coded block pattern. */
+ int mb_intra; /* Intracoded mblock flag. */
+ int bpict_past_forw; /* Past B frame forw. vector flag. */
+ int bpict_past_back; /* Past B frame back vector flag. */
+ int past_intra_addr; /* Addr of last intracoded mblock. */
+ int recon_right_for_prev; /* Past right forw. vector. */
+ int recon_down_for_prev; /* Past down forw. vector. */
+ int recon_right_back_prev; /* Past right back vector. */
+ int recon_down_back_prev; /* Past down back vector. */
+
+ class VideoDecoder* vid_stream;
+ CopyFunctions* copyFunctions;
+
+ public:
+ MacroBlock(class VideoDecoder* vid_stream);
+ ~MacroBlock();
+ int processMacroBlock(PictureArray* pictureArray);
+ int resetMacroBlock();
+ int resetPastMacroBlock();
+
+ private:
+ int reconstruct(int& recon_right_for,
+ int& recon_down_for,
+ int& recon_right_back,
+ int& recon_down_back,
+ int& mb_motion_forw,
+ int& mb_motion_back,
+ PictureArray* pictureArray);
+
+ void computeForwVector(int* recon_right_for_ptr,
+ int* recon_down_for_ptr);
+
+ void computeBackVector(int* recon_right_back_ptr,
+ int* recon_down_back_ptr);
+
+ int processSkippedPictures(PictureArray* pictureArray,
+ int code_type,
+ int mb_width);
+
+ void ProcessSkippedPFrameMBlocks(YUVPicture* current,
+ YUVPicture* future,
+ int mb_width);
+
+
+ void ProcessSkippedBFrameMBlocks(Picture* picture,
+ YUVPicture* past,
+ YUVPicture* current,
+ YUVPicture* future,
+ int mb_width);
+
+
+ void ReconSkippedBlock(unsigned char* source,unsigned char* dest,
+ int row, int col,int row_size,
+ int right,int down,
+ int right_half,int down_half,int width,
+ int maxLen);
+
+
+};
+#endif
diff --git a/mpeglib/lib/mpegplay/mainMpegPlay.cpp b/mpeglib/lib/mpegplay/mainMpegPlay.cpp
new file mode 100644
index 00000000..1c3d9659
--- /dev/null
+++ b/mpeglib/lib/mpegplay/mainMpegPlay.cpp
@@ -0,0 +1,179 @@
+/*
+ * main.c --
+ *
+ * Example program for mpegplay library.
+ * Build with :
+ BUILD with:(if you have intel mmx)
+
+
+ g++ -DINTEL -I/usr/X11R6/include -I.. \
+ -o mpegplay mainMpegPlay.cpp -L/usr/X11R6/lib \
+ ../.libs/libmpeg.a -lX11 -lXext -lXv -lXxf86dga \
+ -lXxf86dga -lpthread
+
+ */
+
+
+#include "mpegPlugin.h"
+#include "../output/outPlugin.h"
+#include "mpegVideoLength.h"
+
+// Includes for non plugin version
+#define _NO_PLUGIN_VERSION
+//#define _PLUGIN_VERSION
+
+
+#ifdef _NO_PLUGIN_VERSION
+
+int main(int argc, char** argv) {
+
+
+
+ if (argc <= 1) {
+ printf("Usage:\n\n");
+ printf("%s filename\n\n",argv[0]);
+ exit(0);
+ }
+ cout << "open -s 1"<<endl;
+
+ InputStream* input=InputPlugin::createInputStream(argv[1]);
+ OutputStream* output=OutPlugin::createOutputStream(_OUTPUT_LOCAL);
+
+ output->config("performance","true",NULL);
+ cout << "open -s"<<endl;
+ input->open(argv[1]);
+ //loader->seek(1024*1024*364+1024*600);
+ //loader->seek(1024*1024*333);
+
+ MpegVideoLength* mpegVideoLength=new MpegVideoLength(input);
+
+
+ cout << "START length calc"<<endl;
+ while (mpegVideoLength->firstInitialize()==false) {
+ if (input->eof()) {
+ break;
+ }
+ continue;
+ }
+ int len=mpegVideoLength->getLength();
+ cout << "END length calc"<<endl;
+
+
+ MpegVideoStream* mpegVideoStream=new MpegVideoStream(input);
+ MpegVideoHeader* mpegVideoHeader=new MpegVideoHeader();
+ cout << "start init"<<endl;
+ while (mpegVideoStream->firstInitialize(mpegVideoHeader)==false) {
+
+ if (input->eof()) {
+ break;
+ }
+ }
+
+ VideoDecoder* video;
+ mpegVideoHeader->print("start");
+ cout << "**************"<<endl;
+
+ PictureArray* pictureArray;
+ YUVPicture* pic;
+
+ // now create pictureArray from the sequence
+ int width=mpegVideoHeader->getMB_Width()*16;
+ int height=mpegVideoHeader->getMB_Height()*16;
+ cout << "width:"<<width<<" height:"<<height<<endl;
+
+ output->openWindow(width,height,(char*)"kmpg");
+
+ video= new VideoDecoder(mpegVideoStream,mpegVideoHeader);
+
+
+ // init is true
+ int cnt=0;
+ while (input->eof()==false){
+ pictureArray=output->lockPictureArray();
+ video->mpegVidRsrc(pictureArray);
+ pic=pictureArray->getYUVPictureCallback();
+ if (pic == NULL) {
+ // nothin to display
+ continue;
+ }
+
+ output->unlockPictureArray(pictureArray);
+ pictureArray->setYUVPictureCallback(NULL);
+
+ }
+ cout << "DestroyVideoDecoder"<<endl;
+ delete video;
+
+
+ delete mpegVideoHeader;
+ delete mpegVideoStream;
+ cout << "end"<<endl;
+
+}
+
+#endif
+
+
+/*
+
+ threaded Plugin version
+
+ ( not useful for gprof )
+*/
+
+#ifdef _PLUGIN_VERSION
+
+int main(int argc, char** argv) {
+
+
+
+ if (argc <= 1) {
+ printf("Usage:\n\n");
+ printf("%s filename\n\n",argv[0]);
+ exit(0);
+ }
+
+ //
+ // The order is important !!!!
+ // 1. construct
+ // 2. set Output
+ // 3. open input
+ // 4. set input
+ //
+ // you cannot set the input _before_ the output
+ // in fact you can, but this gives you a segfault!
+
+ MpegPlugin* plugin=new MpegPlugin();
+ OutputStream* out=OutPlugin::createOutputStream(_OUTPUT_LOCAL);
+ InputStream* in=InputPlugin::createInputStream(argv[1]);
+
+ cout << "open -s 1"<<endl;
+
+ // The plugin does not do "open"
+ in->open(argv[1]);
+ cout << "open -s 2"<<endl;
+
+ // watch the order!
+ plugin->setOutputPlugin(out);
+ cout << "open -s 3"<<endl;
+ plugin->setInputPlugin(in);
+ cout << "open -s 4"<<endl;
+
+ plugin->play();
+ int cnt=0;
+ while(plugin->getStreamState() != _STREAM_STATE_EOF) {
+ sleep(1);
+ PluginInfo* pluginInfo=plugin->getPluginInfo();
+ pluginInfo->print();
+ }
+ cout << "plugin eof"<<endl;
+ plugin->close();
+
+ delete plugin;
+ delete in;
+ delete out;
+
+}
+
+#endif
+
diff --git a/mpeglib/lib/mpegplay/mmxidct.cpp b/mpeglib/lib/mpegplay/mmxidct.cpp
new file mode 100644
index 00000000..f6e12409
--- /dev/null
+++ b/mpeglib/lib/mpegplay/mmxidct.cpp
@@ -0,0 +1,27 @@
+/*
+ wapper for other architectures than mmx
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "mmxidct.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifndef INTEL
+ void IDCT_mmx(short int* reconptr) {
+ printf("urgs mmxidct!\n");
+ exit(0);
+ }
+
+#endif
diff --git a/mpeglib/lib/mpegplay/mmxidct.h b/mpeglib/lib/mpegplay/mmxidct.h
new file mode 100644
index 00000000..9cdfe18c
--- /dev/null
+++ b/mpeglib/lib/mpegplay/mmxidct.h
@@ -0,0 +1,22 @@
+/*
+ wapper for other architectures than mmx
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#ifndef __MMXIDCT_H
+#define __MMXIDCT_H
+
+#include <stdio.h>
+#include <stdlib.h>
+
+extern "C" void IDCT_mmx(short int* reconptr);
+
+#endif
diff --git a/mpeglib/lib/mpegplay/mmxidct_asm.S b/mpeglib/lib/mpegplay/mmxidct_asm.S
new file mode 100644
index 00000000..b618c561
--- /dev/null
+++ b/mpeglib/lib/mpegplay/mmxidct_asm.S
@@ -0,0 +1,738 @@
+
+#ifndef INTEL
+
+/**
+ Some compilers cannot compile empty files.
+*/
+
+IDCT_mmx_dummy:
+ .section .note.GNU-stack,"",%progbits
+#endif
+
+
+#ifdef INTEL
+
+
+/*
+ * the input data is tranposed and each 16 bit element in the 8x8 matrix
+ * is left aligned:
+ * for example in 11...1110000 format
+ * If the iDCT is of I macroblock then 0.5 needs to be added to the;
+ * DC Component
+ * (element[0][0] of the matrix)
+ */
+
+/* extrn re_matrix */
+
+.data
+ .align 16
+ .type preSC,@object
+preSC: .short 16384,22725,21407,19266,16384,12873,8867,4520
+ .short 22725,31521,29692,26722,22725,17855,12299,6270
+ .short 21407,29692,27969,25172,21407,16819,11585,5906
+ .short 19266,26722,25172,22654,19266,15137,10426,5315
+ .short 16384,22725,21407,19266,16384,12873,8867,4520
+ .short 12873,17855,16819,15137,25746,20228,13933,7103
+ .short 17734,24598,23170,20853,17734,13933,9597,4892
+ .short 18081,25080,23624,21261,18081,14206,9785,4988
+ .size preSC,128
+ .align 8
+ .type x0005000200010001,@object
+ .size x0005000200010001,8
+x0005000200010001:
+ .long 0x00010001,0x00050002
+ .align 8
+ .type x0040000000000000,@object
+ .size x0040000000000000,8
+x0040000000000000:
+ .long 0, 0x00400000
+ .align 8
+ .type x5a825a825a825a82,@object
+ .size x5a825a825a825a82,8
+x5a825a825a825a82:
+ .long 0x5a825a82, 0x5a825a82
+ .align 8
+ .type x539f539f539f539f,@object
+ .size x539f539f539f539f,8
+x539f539f539f539f:
+ .long 0x539f539f,0x539f539f
+ .align 8
+ .type x4546454645464546,@object
+ .size x4546454645464546,8
+x4546454645464546:
+ .long 0x45464546,0x45464546
+ .align 8
+ .type x61f861f861f861f8,@object
+ .size x61f861f861f861f8,8
+x61f861f861f861f8:
+ .long 0x61f861f8,0x61f861f8
+ .align 8
+ .type scratch1,@object
+ .size scratch1,8
+scratch1:
+ .long 0,0
+ .align 8
+ .type scratch3,@object
+ .size scratch3,8
+scratch3:
+ .long 0,0
+ .align 8
+ .type scratch5,@object
+ .size scratch5,8
+scratch5:
+ .long 0,0
+ .align 8
+ .type scratch7,@object
+ .size scratch7,8
+scratch7:
+ .long 0,0
+ .type x0,@object
+ .size x0,8
+x0:
+ .long 0,0
+ .align 8
+.text
+ .align 4
+.globl IDCT_mmx
+ .type IDCT_mmx,@function
+IDCT_mmx:
+ pushl %ebp
+ movl %esp,%ebp
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ pushl %esi
+ pushl %edi
+ movl 8(%ebp),%esi /* source matrix */
+#if 0
+ movq (%esi), %mm0
+ movq 8(%esi), %mm1
+ psllw $4, %mm0
+ movq 16(%esi), %mm2
+ psllw $4, %mm1
+ movq 24(%esi), %mm3
+ psllw $4, %mm2
+ movq 32(%esi), %mm4
+ psllw $4, %mm3
+ movq 40(%esi), %mm5
+ psllw $4, %mm4
+ movq 48(%esi), %mm6
+ psllw $4, %mm5
+ movq 56(%esi), %mm7
+ psllw $4, %mm6
+ psllw $4, %mm7
+ movq %mm0, (%esi)
+ movq %mm1, 8(%esi)
+ movq %mm2,16(%esi)
+ movq %mm3,24(%esi)
+ movq %mm4,32(%esi)
+ movq %mm5,40(%esi)
+ movq %mm6,48(%esi)
+ movq %mm7,56(%esi)
+ movq 64(%esi), %mm0
+ movq 72(%esi), %mm1
+ psllw $4, %mm0
+ movq 80(%esi), %mm2
+ psllw $4, %mm1
+ movq 88(%esi), %mm3
+ psllw $4, %mm2
+ movq 96(%esi), %mm4
+ psllw $4, %mm3
+ movq 104(%esi), %mm5
+ psllw $4, %mm4
+ movq 112(%esi), %mm6
+ psllw $4, %mm5
+ movq 120(%esi), %mm7
+ psllw $4, %mm6
+ psllw $4, %mm7
+ movq %mm0,64(%esi)
+ movq %mm1,72(%esi)
+ movq %mm2,80(%esi)
+ movq %mm3,88(%esi)
+ movq %mm4,96(%esi)
+ movq %mm5,104(%esi)
+ movq %mm6,112(%esi)
+ movq %mm7,120(%esi)
+#endif
+ leal preSC, %ecx
+/* column 0: even part
+ * use V4, V12, V0, V8 to produce V22..V25
+ */
+ movq 8*12(%ecx), %mm0 /* maybe the first mul can be done together */
+ /* with the dequantization in iHuff module */
+ pmulhw 8*12(%esi), %mm0 /* V12 */
+ movq 8*4(%ecx), %mm1
+ pmulhw 8*4(%esi), %mm1 /* V4 */
+ movq (%ecx), %mm3
+ psraw $1, %mm0 /* t64=t66 */
+ pmulhw (%esi), %mm3 /* V0 */
+ movq 8*8(%ecx), %mm5 /* duplicate V4 */
+ movq %mm1, %mm2 /* added 11/1/96 */
+ pmulhw 8*8(%esi),%mm5 /* V8 */
+ psubsw %mm0, %mm1 /* V16 */
+ pmulhw x5a825a825a825a82, %mm1 /* 23170 ->V18 */
+ paddsw %mm0, %mm2 /* V17 */
+ movq %mm2, %mm0 /* duplicate V17 */
+ psraw $1, %mm2 /* t75=t82 */
+ psraw $2, %mm0 /* t72 */
+ movq %mm3, %mm4 /* duplicate V0 */
+ paddsw %mm5, %mm3 /* V19 */
+ psubsw %mm5, %mm4 /* V20 ;mm5 free */
+/* moved from the block below */
+ movq 8*10(%ecx), %mm7
+ psraw $1, %mm3 /* t74=t81 */
+ movq %mm3, %mm6 /* duplicate t74=t81 */
+ psraw $2, %mm4 /* t77=t79 */
+ psubsw %mm0, %mm1 /* V21 ; mm0 free */
+ paddsw %mm2, %mm3 /* V22 */
+ movq %mm1, %mm5 /* duplicate V21 */
+ paddsw %mm4, %mm1 /* V23 */
+ movq %mm3, 8*4(%esi) /* V22 */
+ psubsw %mm5, %mm4 /* V24; mm5 free */
+ movq %mm1, 8*12(%esi) /* V23 */
+ psubsw %mm2, %mm6 /* V25; mm2 free */
+ movq %mm4, (%esi) /* V24 */
+/* keep mm6 alive all along the next block */
+ /* movq %mm6, 8*8(%esi) V25 */
+/* column 0: odd part
+ * use V2, V6, V10, V14 to produce V31, V39, V40, V41
+ */
+/* moved above: movq 8*10(%ecx), %mm7 */
+
+ pmulhw 8*10(%esi), %mm7 /* V10 */
+ movq 8*6(%ecx), %mm0
+ pmulhw 8*6(%esi), %mm0 /* V6 */
+ movq 8*2(%ecx), %mm5
+ movq %mm7, %mm3 /* duplicate V10 */
+ pmulhw 8*2(%esi), %mm5 /* V2 */
+ movq 8*14(%ecx), %mm4
+ psubsw %mm0, %mm7 /* V26 */
+ pmulhw 8*14(%esi), %mm4 /* V14 */
+ paddsw %mm0, %mm3 /* V29 ; free mm0 */
+ movq %mm7, %mm1 /* duplicate V26 */
+ psraw $1, %mm3 /* t91=t94 */
+ pmulhw x539f539f539f539f,%mm7 /* V33 */
+ psraw $1, %mm1 /* t96 */
+ movq %mm5, %mm0 /* duplicate V2 */
+ psraw $2, %mm4 /* t85=t87 */
+ paddsw %mm4,%mm5 /* V27 */
+ psubsw %mm4, %mm0 /* V28 ; free mm4 */
+ movq %mm0, %mm2 /* duplicate V28 */
+ psraw $1, %mm5 /* t90=t93 */
+ pmulhw x4546454645464546,%mm0 /* V35 */
+ psraw $1, %mm2 /* t97 */
+ movq %mm5, %mm4 /* duplicate t90=t93 */
+ psubsw %mm2, %mm1 /* V32 ; free mm2 */
+ pmulhw x61f861f861f861f8,%mm1 /* V36 */
+ psllw $1, %mm7 /* t107 */
+ paddsw %mm3, %mm5 /* V31 */
+ psubsw %mm3, %mm4 /* V30 ; free mm3 */
+ pmulhw x5a825a825a825a82,%mm4 /* V34 */
+ nop
+ psubsw %mm1, %mm0 /* V38 */
+ psubsw %mm7, %mm1 /* V37 ; free mm7 */
+ psllw $1, %mm1 /* t114 */
+/* move from the next block */
+ movq %mm6, %mm3 /* duplicate V25 */
+/* move from the next block */
+ movq 8*4(%esi), %mm7 /* V22 */
+ psllw $1, %mm0 /* t110 */
+ psubsw %mm5, %mm0 /* V39 (mm5 needed for next block) */
+ psllw $2, %mm4 /* t112 */
+/* moved from the next block */
+ movq 8*12(%esi), %mm2 /* V23 */
+ psubsw %mm0, %mm4 /* V40 */
+ paddsw %mm4, %mm1 /* V41; free mm0 */
+/* moved from the next block */
+ psllw $1, %mm2 /* t117=t125 */
+/* column 0: output butterfly */
+/* moved above:
+ * movq %mm6, %mm3 duplicate V25
+ * movq 8*4(%esi), %mm7 V22
+ * movq 8*12(%esi), %mm2 V23
+ * psllw $1, %mm2 t117=t125
+ */
+ psubsw %mm1, %mm6 /* tm6 */
+ paddsw %mm1, %mm3 /* tm8; free mm1 */
+ movq %mm7, %mm1 /* duplicate V22 */
+ paddsw %mm5, %mm7 /* tm0 */
+ movq %mm3, 8*8(%esi) /* tm8; free mm3 */
+ psubsw %mm5, %mm1 /* tm14; free mm5 */
+ movq %mm6, 8*6(%esi) /* tm6; free mm6 */
+ movq %mm2, %mm3 /* duplicate t117=t125 */
+ movq (%esi), %mm6 /* V24 */
+ paddsw %mm0, %mm2 /* tm2 */
+ movq %mm7, (%esi) /* tm0; free mm7 */
+ psubsw %mm0, %mm3 /* tm12; free mm0 */
+ movq %mm1, 8*14(%esi) /* tm14; free mm1 */
+ psllw $1, %mm6 /* t119=t123 */
+ movq %mm2, 8*2(%esi) /* tm2; free mm2 */
+ movq %mm6, %mm0 /* duplicate t119=t123 */
+ movq %mm3, 8*12(%esi) /* tm12; free mm3 */
+ paddsw %mm4, %mm6 /* tm4 */
+/* moved from next block */
+ movq 8*5(%ecx), %mm1
+ psubsw %mm4, %mm0 /* tm10; free mm4 */
+/* moved from next block */
+ pmulhw 8*5(%esi), %mm1 /* V5 */
+ movq %mm6, 8*4(%esi) /* tm4; free mm6 */
+ movq %mm0, 8*10(%esi) /* tm10; free mm0 */
+/* column 1: even part
+ * use V5, V13, V1, V9 to produce V56..V59
+ */
+/* moved to prev block:
+ * movq 8*5(%ecx), %mm1
+ * pmulhw 8*5(%esi), %mm1 V5
+ */
+ movq 8*13(%ecx), %mm7
+ psllw $1, %mm1 /* t128=t130 */
+ pmulhw 8*13(%esi), %mm7 /* V13 */
+ movq %mm1, %mm2 /* duplicate t128=t130 */
+ movq 8(%ecx), %mm3
+ pmulhw 8(%esi), %mm3 /* V1 */
+ movq 8*9(%ecx), %mm5
+ psubsw %mm7, %mm1 /* V50 */
+ pmulhw 8*9(%esi), %mm5 /* V9 */
+ paddsw %mm7, %mm2 /* V51 */
+ pmulhw x5a825a825a825a82, %mm1 /* 23170 ->V52 */
+ movq %mm2, %mm6 /* duplicate V51 */
+ psraw $1, %mm2 /* t138=t144 */
+ movq %mm3, %mm4 /* duplicate V1 */
+ psraw $2, %mm6 /* t136 */
+ paddsw %mm5, %mm3 /* V53 */
+ psubsw %mm5, %mm4 /* V54 ;mm5 free */
+ movq %mm3, %mm7 /* duplicate V53 */
+/* moved from next block */
+ movq 8*11(%ecx), %mm0
+ psraw $1, %mm4 /* t140=t142 */
+ psubsw %mm6, %mm1 /* V55 ; mm6 free */
+ paddsw %mm2, %mm3 /* V56 */
+ movq %mm4, %mm5 /* duplicate t140=t142 */
+ paddsw %mm1, %mm4 /* V57 */
+ movq %mm3, 8*5(%esi) /* V56 */
+ psubsw %mm1, %mm5 /* V58; mm1 free */
+ movq %mm4, 8*13(%esi) /* V57 */
+ psubsw %mm2, %mm7 /* V59; mm2 free */
+ movq %mm5, 8*9(%esi) /* V58 */
+/* keep mm7 alive all along the next block
+ * movq %mm7, 8(%esi) V59
+ * moved above
+ * movq 8*11(%ecx), %mm0
+ */
+ pmulhw 8*11(%esi), %mm0 /* V11 */
+ movq 8*7(%ecx), %mm6
+ pmulhw 8*7(%esi), %mm6 /* V7 */
+ movq 8*15(%ecx), %mm4
+ movq %mm0, %mm3 /* duplicate V11 */
+ pmulhw 8*15(%esi), %mm4 /* V15 */
+ movq 8*3(%ecx), %mm5
+ psllw $1, %mm6 /* t146=t152 */
+ pmulhw 8*3(%esi), %mm5 /* V3 */
+ paddsw %mm6, %mm0 /* V63 */
+/* note that V15 computation has a correction step:
+ * this is a 'magic' constant that rebiases the results to be closer to the
+ * expected result. this magic constant can be refined to reduce the error
+ * even more by doing the correction step in a later stage when the number
+ * is actually multiplied by 16
+ */
+ paddw x0005000200010001, %mm4
+ psubsw %mm6, %mm3 /* V60 ; free mm6 */
+ psraw $1, %mm0 /* t154=t156 */
+ movq %mm3, %mm1 /* duplicate V60 */
+ pmulhw x539f539f539f539f, %mm1 /* V67 */
+ movq %mm5, %mm6 /* duplicate V3 */
+ psraw $2, %mm4 /* t148=t150 */
+ paddsw %mm4, %mm5 /* V61 */
+ psubsw %mm4, %mm6 /* V62 ; free mm4 */
+ movq %mm5, %mm4 /* duplicate V61 */
+ psllw $1, %mm1 /* t169 */
+ paddsw %mm0, %mm5 /* V65 -> result */
+ psubsw %mm0, %mm4 /* V64 ; free mm0 */
+ pmulhw x5a825a825a825a82, %mm4 /* V68 */
+ psraw $1, %mm3 /* t158 */
+ psubsw %mm6, %mm3 /* V66 */
+ movq %mm5, %mm2 /* duplicate V65 */
+ pmulhw x61f861f861f861f8, %mm3 /* V70 */
+ psllw $1, %mm6 /* t165 */
+ pmulhw x4546454645464546, %mm6 /* V69 */
+ psraw $1, %mm2 /* t172 */
+/* moved from next block */
+ movq 8*5(%esi), %mm0 /* V56 */
+ psllw $1, %mm4 /* t174 */
+/* moved from next block */
+ psraw $1, %mm0 /* t177=t188 */
+ nop
+ psubsw %mm3, %mm6 /* V72 */
+ psubsw %mm1, %mm3 /* V71 ; free mm1 */
+ psubsw %mm2, %mm6 /* V73 ; free mm2 */
+/* moved from next block */
+ psraw $1, %mm5 /* t178=t189 */
+ psubsw %mm6, %mm4 /* V74 */
+/* moved from next block */
+ movq %mm0, %mm1 /* duplicate t177=t188 */
+ paddsw %mm4, %mm3 /* V75 */
+/* moved from next block */
+ paddsw %mm5, %mm0 /* tm1 */
+/* location
+ * 5 - V56
+ * 13 - V57
+ * 9 - V58
+ * X - V59, mm7
+ * X - V65, mm5
+ * X - V73, mm6
+ * X - V74, mm4
+ * X - V75, mm3
+ * free mm0, mm1 & mm2
+ * moved above
+ * movq 8*5(%esi), %mm0 V56
+ * psllw $1, %mm0 t177=t188 ! new !!
+ * psllw $1, %mm5 t178=t189 ! new !!
+ * movq %mm0, %mm1 duplicate t177=t188
+ * paddsw %mm5, %mm0 tm1
+ */
+ movq 8*13(%esi), %mm2 /* V57 */
+ psubsw %mm5, %mm1 /* tm15; free mm5 */
+ movq %mm0, 8(%esi) /* tm1; free mm0 */
+ psraw $1, %mm7 /* t182=t184 ! new !! */
+/* save the store as used directly in the transpose
+ * movq %mm1, 120(%esi) tm15; free mm1
+ */
+ movq %mm7, %mm5 /* duplicate t182=t184 */
+ psubsw %mm3, %mm7 /* tm7 */
+ paddsw %mm3, %mm5 /* tm9; free mm3 */
+ movq 8*9(%esi), %mm0 /* V58 */
+ movq %mm2, %mm3 /* duplicate V57 */
+ movq %mm7, 8*7(%esi) /* tm7; free mm7 */
+ psubsw %mm6, %mm3 /* tm13 */
+ paddsw %mm6, %mm2 /* tm3 ; free mm6 */
+/* moved up from the transpose */
+ movq %mm3, %mm7
+/* moved up from the transpose */
+ punpcklwd %mm1, %mm3
+ movq %mm0, %mm6 /* duplicate V58 */
+ movq %mm2, 8*3(%esi) /* tm3; free mm2 */
+ paddsw %mm4, %mm0 /* tm5 */
+ psubsw %mm4, %mm6 /* tm11; free mm4 */
+/* moved up from the transpose */
+ punpckhwd %mm1, %mm7
+ movq %mm0, 8*5(%esi) /* tm5; free mm0 */
+/* moved up from the transpose */
+ movq %mm5, %mm2
+/* transpose - M4 part
+ * --------- ---------
+ * | M1 | M2 | | M1'| M3'|
+ * --------- --> ---------
+ * | M3 | M4 | | M2'| M4'|
+ * --------- ---------
+ * Two alternatives: use full mmword approach so the following code can be
+ * scheduled before the transpose is done without stores, or use the faster
+ * half mmword stores (when possible)
+ */
+ movd %mm3, 8*9+4(%esi) /* MS part of tmt9 */
+ punpcklwd %mm6, %mm5
+ movd %mm7, 8*13+4(%esi) /* MS part of tmt13 */
+ punpckhwd %mm6, %mm2
+ movd %mm5, 8*9(%esi) /* LS part of tmt9 */
+ punpckhdq %mm3, %mm5 /* free mm3 */
+ movd %mm2, 8*13(%esi) /* LS part of tmt13 */
+ punpckhdq %mm7, %mm2 /* free mm7 */
+/* moved up from the M3 transpose */
+ movq 8*8(%esi), %mm0
+/* moved up from the M3 transpose */
+ movq 8*10(%esi), %mm1
+/* moved up from the M3 transpose */
+ movq %mm0, %mm3
+/* shuffle the rest of the data, and write it with 2 mmword writes */
+ movq %mm5, 8*11(%esi) /* tmt11 */
+/* moved up from the M3 transpose */
+ punpcklwd %mm1, %mm0
+ movq %mm2, 8*15(%esi) /* tmt15 */
+/* moved up from the M3 transpose */
+ punpckhwd %mm1, %mm3
+/* transpose - M3 part
+ * moved up to previous code section
+ * movq 8*8(%esi), %mm0
+ * movq 8*10(%esi), %mm1
+ * movq %mm0, %mm3
+ * punpcklwd %mm1, %mm0
+ * punpckhwd %mm1, %mm3
+ */
+ movq 8*12(%esi), %mm6
+ movq 8*14(%esi), %mm4
+ movq %mm6, %mm2
+/* shuffle the data and write the lower parts of the transposed in 4 dwords */
+ punpcklwd %mm4, %mm6
+ movq %mm0, %mm1
+ punpckhdq %mm6, %mm1
+ movq %mm3, %mm7
+ punpckhwd %mm4, %mm2 /* free mm4 */
+ punpckldq %mm6, %mm0 /* free mm6 */
+/* moved from next block */
+ movq 8*13(%esi), %mm4 /* tmt13 */
+ punpckldq %mm2, %mm3
+ punpckhdq %mm2, %mm7 /* free mm2 */
+/* moved from next block */
+ movq %mm3, %mm5 /* duplicate tmt5 */
+/* column 1: even part (after transpose)
+* moved above
+* movq %mm3, %mm5 duplicate tmt5
+* movq 8*13(%esi), %mm4 tmt13
+*/
+ psubsw %mm4, %mm3 /* V134 */
+ pmulhw x5a825a825a825a82, %mm3 /* 23170 ->V136 */
+ movq 8*9(%esi), %mm6 /* tmt9 */
+ paddsw %mm4, %mm5 /* V135 ; mm4 free */
+ movq %mm0, %mm4 /* duplicate tmt1 */
+ paddsw %mm6, %mm0 /* V137 */
+ psubsw %mm6, %mm4 /* V138 ; mm6 free */
+ psllw $2, %mm3 /* t290 */
+ psubsw %mm5, %mm3 /* V139 */
+ movq %mm0, %mm6 /* duplicate V137 */
+ paddsw %mm5, %mm0 /* V140 */
+ movq %mm4, %mm2 /* duplicate V138 */
+ paddsw %mm3, %mm2 /* V141 */
+ psubsw %mm3, %mm4 /* V142 ; mm3 free */
+ movq %mm0, 8*9(%esi) /* V140 */
+ psubsw %mm5, %mm6 /* V143 ; mm5 free */
+/* moved from next block */
+ movq 8*11(%esi), %mm0 /* tmt11 */
+ movq %mm2, 8*13(%esi) /* V141 */
+/* moved from next block */
+ movq %mm0, %mm2 /* duplicate tmt11 */
+/* column 1: odd part (after transpose) */
+/* moved up to the prev block
+ * movq 8*11(%esi), %mm0 tmt11
+ * movq %mm0, %mm2 duplicate tmt11
+ */
+ movq 8*15(%esi), %mm5 /* tmt15 */
+ psubsw %mm7, %mm0 /* V144 */
+ movq %mm0, %mm3 /* duplicate V144 */
+ paddsw %mm7, %mm2 /* V147 ; free mm7 */
+ pmulhw x539f539f539f539f, %mm0 /* 21407-> V151 */
+ movq %mm1, %mm7 /* duplicate tmt3 */
+ paddsw %mm5, %mm7 /* V145 */
+ psubsw %mm5, %mm1 /* V146 ; free mm5 */
+ psubsw %mm1, %mm3 /* V150 */
+ movq %mm7, %mm5 /* duplicate V145 */
+ pmulhw x4546454645464546, %mm1 /* 17734-> V153 */
+ psubsw %mm2, %mm5 /* V148 */
+ pmulhw x61f861f861f861f8, %mm3 /* 25080-> V154 */
+ psllw $2, %mm0 /* t311 */
+ pmulhw x5a825a825a825a82, %mm5 /* 23170-> V152 */
+ paddsw %mm2, %mm7 /* V149 ; free mm2 */
+ psllw $1, %mm1 /* t313 */
+ nop /* without the nop - freeze here for one clock */
+ movq %mm3, %mm2 /* duplicate V154 */
+ psubsw %mm0, %mm3 /* V155 ; free mm0 */
+ psubsw %mm2, %mm1 /* V156 ; free mm2 */
+/* moved from the next block */
+ movq %mm6, %mm2 /* duplicate V143 */
+/* moved from the next block */
+ movq 8*13(%esi), %mm0 /* V141 */
+ psllw $1, %mm1 /* t315 */
+ psubsw %mm7, %mm1 /* V157 (keep V149) */
+ psllw $2, %mm5 /* t317 */
+ psubsw %mm1, %mm5 /* V158 */
+ psllw $1, %mm3 /* t319 */
+ paddsw %mm5, %mm3 /* V159 */
+/* column 1: output butterfly (after transform)
+ * moved to the prev block
+ * movq %mm6, %mm2 duplicate V143
+ * movq 8*13(%esi), %mm0 V141
+ */
+ psubsw %mm3, %mm2 /* V163 */
+ paddsw %mm3, %mm6 /* V164 ; free mm3 */
+ movq %mm4, %mm3 /* duplicate V142 */
+ psubsw %mm5, %mm4 /* V165 ; free mm5 */
+ movq %mm2, scratch7 /* out7 */
+ psraw $4, %mm6
+ psraw $4, %mm4
+ paddsw %mm5, %mm3 /* V162 */
+ movq 8*9(%esi), %mm2 /* V140 */
+ movq %mm0, %mm5 /* duplicate V141 */
+/* in order not to perculate this line up,
+ * we read 72(%esi) very near to this location
+ */
+ movq %mm6, 8*9(%esi) /* out9 */
+ paddsw %mm1, %mm0 /* V161 */
+ movq %mm3, scratch5 /* out5 */
+ psubsw %mm1, %mm5 /* V166 ; free mm1 */
+ movq %mm4, 8*11(%esi) /* out11 */
+ psraw $4, %mm5
+ movq %mm0, scratch3 /* out3 */
+ movq %mm2, %mm4 /* duplicate V140 */
+ movq %mm5, 8*13(%esi) /* out13 */
+ paddsw %mm7, %mm2 /* V160 */
+/* moved from the next block */
+ movq 8(%esi), %mm0
+ psubsw %mm7, %mm4 /* V167 ; free mm7 */
+/* moved from the next block */
+ movq 8*3(%esi), %mm7
+ psraw $4, %mm4
+ movq %mm2, scratch1 /* out1 */
+/* moved from the next block */
+ movq %mm0, %mm1
+ movq %mm4, 8*15(%esi) /* out15 */
+/* moved from the next block */
+ punpcklwd %mm7, %mm0
+/* transpose - M2 parts
+ * moved up to the prev block
+ * movq 8(%esi), %mm0
+ * movq 8*3(%esi), %mm7
+ * movq %mm0, %mm1
+ * punpcklwd %mm7, %mm0
+ */
+ movq 8*5(%esi), %mm5
+ punpckhwd %mm7, %mm1
+ movq 8*7(%esi), %mm4
+ movq %mm5, %mm3
+/* shuffle the data and write the lower parts of the trasposed in 4 dwords */
+ movd %mm0, 8*8(%esi) /* LS part of tmt8 */
+ punpcklwd %mm4, %mm5
+ movd %mm1, 8*12(%esi) /* LS part of tmt12 */
+ punpckhwd %mm4, %mm3
+ movd %mm5, 8*8+4(%esi) /* MS part of tmt8 */
+ punpckhdq %mm5, %mm0 /* tmt10 */
+ movd %mm3, 8*12+4(%esi) /* MS part of tmt12 */
+ punpckhdq %mm3, %mm1 /* tmt14 */
+/* transpose - M1 parts */
+ movq (%esi), %mm7
+ movq 8*2(%esi), %mm2
+ movq %mm7, %mm6
+ movq 8*4(%esi), %mm5
+ punpcklwd %mm2, %mm7
+ movq 8*6(%esi), %mm4
+ punpckhwd %mm2, %mm6 /* free mm2 */
+ movq %mm5, %mm3
+ punpcklwd %mm4, %mm5
+ punpckhwd %mm4, %mm3 /* free mm4 */
+ movq %mm7, %mm2
+ movq %mm6, %mm4
+ punpckldq %mm5, %mm7 /* tmt0 */
+ punpckhdq %mm5, %mm2 /* tmt2 ; free mm5 */
+/* shuffle the rest of the data, and write it with 2 mmword writes */
+ punpckldq %mm3, %mm6 /* tmt4 */
+/* moved from next block */
+ movq %mm2, %mm5 /* duplicate tmt2 */
+ punpckhdq %mm3, %mm4 /* tmt6 ; free mm3 */
+/* moved from next block */
+ movq %mm0, %mm3 /* duplicate tmt10 */
+/* column 0: odd part (after transpose)
+ *moved up to prev block
+ * movq %mm0, %mm3 duplicate tmt10
+ * movq %mm2, %mm5 duplicate tmt2
+ */
+ psubsw %mm4, %mm0 /* V110 */
+ paddsw %mm4, %mm3 /* V113 ; free mm4 */
+ movq %mm0, %mm4 /* duplicate V110 */
+ paddsw %mm1, %mm2 /* V111 */
+ pmulhw x539f539f539f539f, %mm0 /* 21407-> V117 */
+ psubsw %mm1, %mm5 /* V112 ; free mm1 */
+ psubsw %mm5, %mm4 /* V116 */
+ movq %mm2, %mm1 /* duplicate V111 */
+ pmulhw x4546454645464546, %mm5 /* 17734-> V119 */
+ psubsw %mm3, %mm2 /* V114 */
+ pmulhw x61f861f861f861f8, %mm4 /* 25080-> V120 */
+ paddsw %mm3, %mm1 /* V115 ; free mm3 */
+ pmulhw x5a825a825a825a82, %mm2 /* 23170-> V118 */
+ psllw $2, %mm0 /* t266 */
+ movq %mm1, (%esi) /* save V115 */
+ psllw $1, %mm5 /* t268 */
+ psubsw %mm4, %mm5 /* V122 */
+ psubsw %mm0, %mm4 /* V121 ; free mm0 */
+ psllw $1, %mm5 /* t270 */
+ psubsw %mm1, %mm5 /* V123 ; free mm1 */
+ psllw $2, %mm2 /* t272 */
+ psubsw %mm5, %mm2 /* V124 (keep V123) */
+ psllw $1, %mm4 /* t274 */
+ movq %mm5, 8*2(%esi) /* save V123 ; free mm5 */
+ paddsw %mm2, %mm4 /* V125 (keep V124) */
+/* column 0: even part (after transpose) */
+ movq 8*12(%esi), %mm0 /* tmt12 */
+ movq %mm6, %mm3 /* duplicate tmt4 */
+ psubsw %mm0, %mm6 /* V100 */
+ paddsw %mm0, %mm3 /* V101 ; free mm0 */
+ pmulhw x5a825a825a825a82, %mm6 /* 23170 ->V102 */
+ movq %mm7, %mm5 /* duplicate tmt0 */
+ movq 8*8(%esi), %mm1 /* tmt8 */
+ paddsw %mm1, %mm7 /* V103 */
+ psubsw %mm1, %mm5 /* V104 ; free mm1 */
+ movq %mm7, %mm0 /* duplicate V103 */
+ psllw $2, %mm6 /* t245 */
+ paddsw %mm3, %mm7 /* V106 */
+ movq %mm5, %mm1 /* duplicate V104 */
+ psubsw %mm3, %mm6 /* V105 */
+ psubsw %mm3, %mm0 /* V109; free mm3 */
+ paddsw %mm6, %mm5 /* V107 */
+ psubsw %mm6, %mm1 /* V108 ; free mm6 */
+/* column 0: output butterfly (after transform) */
+ movq %mm1, %mm3 /* duplicate V108 */
+ paddsw %mm2, %mm1 /* out4 */
+ psraw $4, %mm1
+ psubsw %mm2, %mm3 /* out10 ; free mm2 */
+ psraw $4, %mm3
+ movq %mm0, %mm6 /* duplicate V109 */
+ movq %mm1, 8*4(%esi) /* out4 ; free mm1 */
+ psubsw %mm4, %mm0 /* out6 */
+ movq %mm3, 8*10(%esi) /* out10 ; free mm3 */
+ psraw $4, %mm0
+ paddsw %mm4, %mm6 /* out8 ; free mm4 */
+ movq %mm7, %mm1 /* duplicate V106 */
+ movq %mm0, 8*6(%esi) /* out6 ; free mm0 */
+ psraw $4, %mm6
+ movq (%esi), %mm4 /* V115 */
+ movq %mm6, 8*8(%esi) /* out8 ; free mm6 */
+ movq %mm5, %mm2 /* duplicate V107 */
+ movq 8*2(%esi), %mm3 /* V123 */
+ paddsw %mm4, %mm7 /* out0 */
+/* moved up from next block */
+ movq scratch3, %mm0
+ psraw $4, %mm7
+/* moved up from next block */
+ movq scratch5, %mm6
+ psubsw %mm4, %mm1 /* out14 ; free mm4 */
+ paddsw %mm3, %mm5 /* out2 */
+ psraw $4, %mm1
+ movq %mm7, (%esi) /* out0 ; free mm7 */
+ psraw $4, %mm5
+ movq %mm1, 8*14(%esi) /* out14 ; free mm1 */
+ psubsw %mm3, %mm2 /* out12 ; free mm3 */
+ movq %mm5, 8*2(%esi) /* out2 ; free mm5 */
+ psraw $4, %mm2
+/* moved up to the prev block */
+ movq scratch7, %mm4
+/* moved up to the prev block */
+ psraw $4, %mm0
+ movq %mm2, 8*12(%esi) /* out12 ; free mm2 */
+/* moved up to the prev block */
+ psraw $4, %mm6
+/* move back the data to its correct place
+* moved up to the prev block
+ * movq scratch3, %mm0
+ * movq scratch5, %mm6
+ * movq scratch7, %mm4
+ * psraw $4, %mm0
+ * psraw $4, %mm6
+*/
+ movq scratch1, %mm1
+ psraw $4, %mm4
+ movq %mm0, 8*3(%esi) /* out3 */
+ psraw $4, %mm1
+ movq %mm6, 8*5(%esi) /* out5 */
+ movq %mm4, 8*7(%esi) /* out7 */
+ movq %mm1, 8(%esi) /* out1 */
+ popl %edi
+ popl %esi
+ popl %edx
+ popl %ecx
+ popl %ebx
+ movl %ebp,%esp
+ popl %ebp
+ ret
+.Lfe1:
+ .size IDCT_mmx,.Lfe1-IDCT_mmx
+ .section .note.GNU-stack,"",%progbits
+
+
+#endif
+
diff --git a/mpeglib/lib/mpegplay/motionVector.cpp b/mpeglib/lib/mpegplay/motionVector.cpp
new file mode 100644
index 00000000..ebec0369
--- /dev/null
+++ b/mpeglib/lib/mpegplay/motionVector.cpp
@@ -0,0 +1,130 @@
+/*
+ class for motionvectors
+ Copyright (C) 1999 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "motionVector.h"
+
+
+
+
+
+MotionVector::MotionVector() {
+}
+
+
+MotionVector::~MotionVector() {
+}
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ComputeVector --
+ *
+ * Computes motion vector given parameters previously parsed
+ * and reconstructed.
+ *
+ * Results:
+ * Reconstructed motion vector info is put into recon_* parameters
+ * passed to this function. Also updated previous motion vector
+ * information.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+void MotionVector::computeVector(int* recon_right_ptr,
+ int* recon_down_ptr,
+ int& recon_right_prev,
+ int& recon_down_prev,
+ unsigned int& f,
+ unsigned int& full_pel_vector,
+ int& motion_h_code,
+ int& motion_v_code,
+ unsigned int& motion_h_r,
+ unsigned int& motion_v_r) {
+
+
+ int comp_h_r, comp_v_r;
+ int right_little, right_big, down_little, down_big;
+ int max, min, new_vector;
+
+ /* The following procedure for the reconstruction of motion vectors
+ is a direct and simple implementation of the instructions given
+ in the mpeg December 1991 standard draft.
+ */
+
+ if (f == 1 || motion_h_code == 0)
+ comp_h_r = 0;
+ else
+ comp_h_r = f - 1 - motion_h_r;
+
+ if (f == 1 || motion_v_code == 0)
+ comp_v_r = 0;
+ else
+ comp_v_r = f - 1 - motion_v_r;
+
+ right_little = motion_h_code * f;
+ if (right_little == 0)
+ right_big = 0;
+ else {
+ if (right_little > 0) {
+ right_little = right_little - comp_h_r;
+ right_big = right_little - 32 * f;
+ }
+ else {
+ right_little = right_little + comp_h_r;
+ right_big = right_little + 32 * f;
+ }
+ }
+
+ down_little = motion_v_code * f;
+ if (down_little == 0)
+ down_big = 0;
+ else {
+ if (down_little > 0) {
+ down_little = down_little - comp_v_r;
+ down_big = down_little - 32 * f;
+ }
+ else {
+ down_little = down_little + comp_v_r;
+ down_big = down_little + 32 * f;
+ }
+ }
+
+ max = 16 * f - 1;
+ min = -16 * f;
+
+ new_vector = recon_right_prev + right_little;
+
+ if (new_vector <= max && new_vector >= min)
+ *recon_right_ptr = recon_right_prev + right_little;
+ /* just new_vector */
+ else
+ *recon_right_ptr = recon_right_prev + right_big;
+ recon_right_prev = *recon_right_ptr;
+ if (full_pel_vector)
+ *recon_right_ptr = *recon_right_ptr << 1;
+
+ new_vector = recon_down_prev + down_little;
+ if (new_vector <= max && new_vector >= min)
+ *recon_down_ptr = recon_down_prev + down_little;
+ /* just new_vector */
+ else
+ *recon_down_ptr = recon_down_prev + down_big;
+ recon_down_prev = *recon_down_ptr;
+ if (full_pel_vector)
+ *recon_down_ptr = *recon_down_ptr << 1;
+
+}
diff --git a/mpeglib/lib/mpegplay/motionVector.h b/mpeglib/lib/mpegplay/motionVector.h
new file mode 100644
index 00000000..5a58e027
--- /dev/null
+++ b/mpeglib/lib/mpegplay/motionVector.h
@@ -0,0 +1,40 @@
+/*
+ class for motionvectors
+ Copyright (C) 1999 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#ifndef __MOTIONVECTOR_H
+#define __MOTIONVECTOR_H
+
+
+#include "picture.h"
+
+
+class MotionVector {
+
+
+ public:
+ MotionVector();
+ ~MotionVector();
+
+ void computeVector(int* recon_right_ptr,
+ int* recon_down_ptr,
+ int& recon_right_prev,
+ int& recon_down_prev,
+ unsigned int& f,
+ unsigned int& full_pel_vector,
+ int& motion_h_code,
+ int& motion_v_code,
+ unsigned int& motion_h_r,
+ unsigned int& motion_v_r);
+
+};
+#endif
diff --git a/mpeglib/lib/mpegplay/mpegExtension.cpp b/mpeglib/lib/mpegplay/mpegExtension.cpp
new file mode 100644
index 00000000..657fe683
--- /dev/null
+++ b/mpeglib/lib/mpegplay/mpegExtension.cpp
@@ -0,0 +1,258 @@
+/*
+ parses extension data (picture and sequence)
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "mpegExtension.h"
+
+#include <iostream>
+
+using namespace std;
+
+MpegExtension::MpegExtension() {
+ userData=NULL;
+ extData=NULL;
+ extraBit=NULL;
+}
+
+
+MpegExtension::~MpegExtension() {
+ if (userData != NULL) {
+ delete userData;
+ }
+ if (extData != NULL) {
+ delete extData;
+ }
+ if (extraBit != NULL) {
+ delete extraBit;
+ }
+}
+
+
+int MpegExtension::processExtensionData(MpegVideoStream* mpegVideoStream) {
+
+ /* Goto next start code. */
+ mpegVideoStream->next_start_code();
+
+ /*
+ * If next start code is extension/user start code,
+ * parse off extension data.
+ */
+
+ /*
+ * If next start code is extension start code, parse off extension data.
+ */
+ if (next_bits(32, EXT_START_CODE,mpegVideoStream)) {
+ mpegVideoStream->flushBits(32);
+ if (extData != NULL) {
+ delete extData;
+ extData = NULL;
+ }
+ cout << "ext"<<endl;
+ extData = get_ext_data(mpegVideoStream);
+ }
+
+ /*
+ * If next start code is user start code, parse off user data.
+ */
+ if (next_bits(32, USER_START_CODE,mpegVideoStream)) {
+ mpegVideoStream->flushBits(32);
+ if (userData != NULL) {
+ delete userData;
+ userData=NULL;
+ }
+ userData =get_ext_data(mpegVideoStream);
+ }
+
+ return true;
+}
+
+
+
+int MpegExtension::processExtra_bit_info(MpegVideoStream* mpegVideoStream) {
+ if (extraBit != NULL) {
+ delete extraBit;
+ extraBit = NULL;
+ }
+ get_extra_bit_info(mpegVideoStream);
+ return true;
+}
+
+
+
+
+int MpegExtension::next_bits(int num,unsigned int mask,
+ MpegVideoStream* input) {
+ unsigned int data;
+
+ /* Get next num bits, no buffer pointer advance. */
+
+ data=input->showBits(num);
+
+ /* Compare bit stream and mask. Set return value toTRUE if equal, FALSE if
+ differs.
+ */
+
+ if (mask == data) {
+ return true;
+ }
+ return false;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * get_ext_data --
+ *
+ * Assumes that bit stream is at begining of extension
+ * data. Parses off extension data into dynamically
+ * allocated space until start code is hit.
+ *
+ * Results:
+ * Pointer to dynamically allocated memory containing
+ * extension data.
+ *
+ * Side effects:
+ * Bit stream irreversibly parsed.
+ *
+ *--------------------------------------------------------------
+ */
+char* MpegExtension::get_ext_data(MpegVideoStream* mpegVideoStream) {
+ unsigned int size, marker;
+ char *dataPtr;
+ unsigned int data;
+
+ /* Set initial ext data buffer size. */
+
+ size = EXT_BUF_SIZE;
+
+ /* Allocate ext data buffer. */
+
+ dataPtr = (char *) malloc(size);
+
+ /* Initialize marker to keep place in ext data buffer. */
+
+ marker = 0;
+
+ /* While next data is not start code... */
+ while (!next_bits(24, 0x000001,mpegVideoStream )) {
+
+ /* Get next byte of ext data. */
+
+ data=mpegVideoStream->getBits(8);
+
+
+
+ /* Put ext data into ext data buffer. Advance marker. */
+
+ dataPtr[marker] = (char) data;
+ marker++;
+
+ /* If end of ext data buffer reached, resize data buffer. */
+
+ if (marker == size) {
+ size += EXT_BUF_SIZE;
+ dataPtr = (char *) realloc(dataPtr, size);
+ }
+ }
+
+ /* Realloc data buffer to free any extra space. */
+
+ dataPtr = (char *) realloc(dataPtr, marker);
+ delete dataPtr;
+ dataPtr=NULL;
+ /* Return pointer to ext data buffer. */
+ return dataPtr;
+}
+
+void MpegExtension::processExtBuffer(MpegVideoStream* mpegVideoStream){
+ unsigned int size, marker;
+ char *dataPtr;
+ unsigned int data=1;
+
+ /* Initialize size of extra bit info buffer and allocate. */
+
+
+ size = EXT_BUF_SIZE;
+ dataPtr = (char *) malloc(size);
+
+ /* Reset marker to hold place in buffer. */
+
+ marker = 0;
+
+ /* While flag bit is true. */
+
+ while (data) {
+
+ /* Get next 8 bits of data. */
+ data=mpegVideoStream->getBits(8);
+
+ /* Place in extra bit info buffer. */
+
+ dataPtr[marker] = (char) data;
+ marker++;
+
+ /* If buffer is full, reallocate. */
+
+ if (marker == size) {
+ size += EXT_BUF_SIZE;
+ dataPtr = (char *) realloc(dataPtr, size);
+ }
+
+ /* Get next flag bit. */
+ data=mpegVideoStream->getBits(1);
+ }
+
+ /* Reallocate buffer to free extra space. */
+
+ dataPtr = (char *) realloc(dataPtr, marker);
+ delete dataPtr;
+ dataPtr=NULL;
+ /* Return pointer to extra bit info buffer. */
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * get_extra_bit_info --
+ *
+ * Parses off extra bit info stream into dynamically
+ * allocated memory. Extra bit info is indicated by
+ * a flag bit set to 1, followed by 8 bits of data.
+ * This continues until the flag bit is zero. Assumes
+ * that bit stream set to first flag bit in extra
+ * bit info stream.
+ *
+ * Results:
+ * Pointer to dynamically allocated memory with extra
+ * bit info in it. Flag bits are NOT included.
+ *
+ * Side effects:
+ * Bit stream irreversibly parsed.
+ *
+ *--------------------------------------------------------------
+ */
+
+char* MpegExtension::get_extra_bit_info(MpegVideoStream* mpegVideoStream) {
+ unsigned int data;
+
+ /* Get first flag bit. */
+ data=mpegVideoStream->getBits(1);
+
+ /* If flag is false, return NULL pointer (i.e. no extra bit info). */
+
+ if (!data) {
+ return NULL;
+ }
+ processExtBuffer(mpegVideoStream);
+ return NULL;
+}
diff --git a/mpeglib/lib/mpegplay/mpegExtension.h b/mpeglib/lib/mpegplay/mpegExtension.h
new file mode 100644
index 00000000..23b79c5b
--- /dev/null
+++ b/mpeglib/lib/mpegplay/mpegExtension.h
@@ -0,0 +1,49 @@
+/*
+ parses extension data (picture and sequence)
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+
+
+
+#ifndef __MPEGEXTENSION_H
+#define __MPEGEXTENSION_H
+
+#include "mpegVideoStream.h"
+
+#define EXT_BUF_SIZE 1024
+
+class MpegExtension {
+
+ char* userData;
+ char* extData;
+ char* extraBit;
+
+ public:
+ MpegExtension();
+ ~MpegExtension();
+
+ inline char* getExtData() { return extData;}
+ inline char* getUserData() { return userData;}
+ inline char* getExtraBit() { return extraBit;}
+
+ int processExtensionData(class MpegVideoStream* mpegVideoStream);
+ int processExtra_bit_info(class MpegVideoStream* mpegVideoStream);
+ void processExtBuffer(class MpegVideoStream* mpegVideoStream);
+ char* get_ext_data(class MpegVideoStream* mpegVideoStream);
+
+ private:
+ char* get_extra_bit_info(MpegVideoStream* mpegVideoStream);
+
+ int next_bits(int num,unsigned int mask,MpegVideoStream* input);
+
+};
+#endif
diff --git a/mpeglib/lib/mpegplay/mpegSystemHeader.cpp b/mpeglib/lib/mpegplay/mpegSystemHeader.cpp
new file mode 100644
index 00000000..e8fe1d91
--- /dev/null
+++ b/mpeglib/lib/mpegplay/mpegSystemHeader.cpp
@@ -0,0 +1,786 @@
+/*
+ stores info about system stream and sends data to audio/video
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "mpegSystemHeader.h"
+
+#include <iostream>
+
+using namespace std;
+
+// we do a fast mod based lookup pid->Map
+#define MAX_PIDS 23
+
+
+MpegSystemHeader::MpegSystemHeader() {
+
+ packetLen=0;
+ pesPacketLen=0;
+ tsPacketLen=0;
+
+
+ audioLayerSelect=0;
+ videoLayerSelect=0;
+ lmpeg2=false;
+ lPTSFlag=false;
+
+ layer=_PACKET_UNKNOWN_LAYER;
+ lHasPSHeader=false;
+
+ //
+ // MPEG2 Stuff [START]
+ //
+
+ lOriginal=false;
+ lCopyRight=false;
+ lDataAlignmentIndicator=false;
+ lPesPriority=false;
+ lEncrypted=false;
+ startCodePrefix=0;
+
+ lPTSDTSFlag=false;
+ lESCR=false;
+ lESRateFlag=false;
+ lDMSTRICKFLAG=false;
+ lADDITIONAL_COPY_FLAG=false;
+ lPES_CRC_FLAG=false;
+ lPES_EXT_FLAG=false;
+ nPES_HEADER_DATA_LENGTH=0;
+
+ // EXT FILED [START]
+
+ lPrivateDataFlag=false;
+ lPackHeaderFieldFlag=false;
+ lSequenceCounterFlag=false;
+ lSTDBufferFlag=false;
+ lPES_EXT_FLAG_2=false;
+ nPES_EXT_FIELD_LENGTH=0;
+ // EXT FILED [END]
+
+ subStreamID=0;
+ //
+ // MPEG2 Stuff [END]
+ //
+
+ // TS Stuff [START]
+ lHasTSHeader=false;
+ programs=0;
+ programNumber=INVALID_PROGRAM;
+ pmtPID=INVALID_PID;
+
+ mapPidStreamArray=new MapPidStream*[MAX_PIDS];
+ int i;
+ for(i=0;i<MAX_PIDS;i++) {
+ mapPidStreamArray[i]=new MapPidStream();
+ mapPidStreamArray[i]->isValid=false;
+ }
+ currentPos=0;
+
+
+
+ // TS Stuff [END]
+}
+
+
+MpegSystemHeader::~MpegSystemHeader() {
+ int i;
+ for(i=0;i<MAX_PIDS;i++) {
+ delete mapPidStreamArray[i];
+ }
+ delete mapPidStreamArray;
+}
+
+
+void MpegSystemHeader::setHeader(unsigned int header) {
+ setPSHeader(header);
+ setTSHeader(header);
+ this->header=header;
+}
+
+int MpegSystemHeader::hasRAWHeader() {
+ return header==_SEQ_START_CODE;
+}
+
+
+unsigned int MpegSystemHeader::getHeader() {
+ return header;
+}
+
+double MpegSystemHeader::getSCRTimeStamp() {
+ return scrTimeStamp;
+}
+
+
+double MpegSystemHeader::getPTSTimeStamp() {
+ return ptsTimeStamp;
+}
+
+
+int MpegSystemHeader::getPTSFlag() {
+ return lPTSFlag;
+}
+
+
+void MpegSystemHeader::setPTSFlag(int lPTSFlag) {
+ this->lPTSFlag=lPTSFlag;
+}
+
+
+double MpegSystemHeader::getDTSTimeStamp() {
+ return dtsTimeStamp;
+}
+
+
+void MpegSystemHeader::setSCRTimeStamp(double scrTimeStamp) {
+ this->scrTimeStamp=scrTimeStamp;
+}
+
+
+void MpegSystemHeader::setPTSTimeStamp(double ptsTimeStamp) {
+ this->ptsTimeStamp=ptsTimeStamp;
+}
+
+
+void MpegSystemHeader::setDTSTimeStamp(double dtsTimeStamp) {
+ this->dtsTimeStamp=dtsTimeStamp;
+}
+
+
+
+int MpegSystemHeader::getLayer() {
+ return layer;
+}
+
+
+void MpegSystemHeader::setLayer(int layer) {
+ this->layer=layer;
+}
+
+int MpegSystemHeader::hasPSHeader() {
+ return lHasPSHeader;
+}
+
+
+void MpegSystemHeader::addAvailableLayer(int streamID) {
+ switch (streamID>>4){
+ case _PAKET_ID_AUDIO_1>>4:
+ case _PAKET_ID_AUDIO_2>>4:
+ availableAudioLayers |= 1<<(streamID - 0xc0);
+ break;
+ case _PAKET_ID_VIDEO>>4:
+ availableVideoLayers |= 1<<(streamID - 0xe0);
+ break;
+ case _SUBSTREAM_AC3_ID>>4:
+ availableAudioLayers |= 1<<(streamID - 0x80);
+ break;
+ default:
+ cout << "unknown streamID MpegSystemHeader::addAvailableLayer"<<endl;
+ }
+
+
+}
+void MpegSystemHeader::resetAvailableLayers() {
+ availableAudioLayers = 0;
+ availableVideoLayers = 0;
+}
+
+int MpegSystemHeader::getAudioLayerSelect() {
+ if (availableAudioLayers & (1<<audioLayerSelect))
+ return audioLayerSelect;
+ else
+ return 0;
+}
+
+void MpegSystemHeader::setAudioLayerSelect(int layer) {
+ audioLayerSelect = layer;
+}
+
+int MpegSystemHeader::getVideoLayerSelect() {
+ if (availableVideoLayers & (1<<videoLayerSelect))
+ return videoLayerSelect;
+ else
+ return 0;
+}
+
+void MpegSystemHeader::setVideoLayerSelect(int layer) {
+ videoLayerSelect = layer;
+}
+
+
+
+
+
+int MpegSystemHeader::getPacketID() {
+ return packetID;
+}
+
+
+void MpegSystemHeader::setPacketID(int packetID) {
+ this->packetID=packetID;
+}
+
+int MpegSystemHeader::getPacketLen() {
+ return packetLen;
+}
+
+
+void MpegSystemHeader::setPacketLen(int packetLen) {
+ this->packetLen=packetLen;
+}
+
+
+int MpegSystemHeader::getPESPacketLen() {
+ return pesPacketLen;
+}
+
+void MpegSystemHeader::setPESPacketLen(int packetLen) {
+ this->pesPacketLen=packetLen;
+}
+
+
+int MpegSystemHeader::getTSPacketLen() {
+ return tsPacketLen;
+}
+
+
+void MpegSystemHeader::setTSPacketLen(int packetLen) {
+ this->tsPacketLen=packetLen;
+}
+
+
+
+
+int MpegSystemHeader::getRate() {
+ return rate;
+}
+
+
+void MpegSystemHeader::setRate(int rate) {
+ this->rate=rate;
+}
+
+
+int MpegSystemHeader::getStdBufferScale() {
+ return stdBufferScale;
+}
+
+
+void MpegSystemHeader::setStdBufferScale(int stdBufferScale) {
+ this->stdBufferScale=stdBufferScale;
+}
+
+unsigned long MpegSystemHeader::getStdBufferSize() {
+ return stdBufferSize;
+}
+
+
+void MpegSystemHeader::setStdBufferSize(unsigned long stdBufferSize) {
+ this->stdBufferSize=stdBufferSize;
+}
+
+
+int MpegSystemHeader::getMPEG2() {
+ return lmpeg2;
+}
+
+
+//
+// MPEG2 Stuff [START]
+//
+
+
+int MpegSystemHeader::getOriginalOrCopy() {
+ return lOriginal;
+}
+
+
+void MpegSystemHeader::setOriginalOrCopy(int lOriginal) {
+ this->lOriginal=lOriginal;
+}
+
+
+int MpegSystemHeader::getCopyRight() {
+ return lCopyRight;
+}
+
+
+void MpegSystemHeader::setCopyRight(int lCopyRight) {
+ this->lCopyRight=lCopyRight;
+}
+
+
+
+int MpegSystemHeader::getDataAlignmentIndicator() {
+ return lDataAlignmentIndicator;
+}
+
+
+void MpegSystemHeader::setDataAlignmentIndicator(int lDataAlignmentIndicator) {
+ this->lDataAlignmentIndicator=lDataAlignmentIndicator;
+}
+
+
+int MpegSystemHeader::getPesPriority() {
+ return lPesPriority;
+}
+
+
+void MpegSystemHeader::setPesPriority(int lPesPriority) {
+ this->lPesPriority=lPesPriority;
+}
+
+
+
+int MpegSystemHeader::getEncrypted() {
+ return lEncrypted;
+}
+
+
+void MpegSystemHeader::setEncrypted(int lEncrypted) {
+ this->lEncrypted=lEncrypted;
+}
+
+
+int MpegSystemHeader::getStartCodePrefix() {
+ return startCodePrefix;
+}
+
+
+void MpegSystemHeader::setStartCodePrefix(int startCodePrefix) {
+ this->startCodePrefix=startCodePrefix;
+}
+
+
+int MpegSystemHeader::getPTSDTSFlag(){
+ return lPTSDTSFlag;
+}
+
+
+void MpegSystemHeader::setPTSDTSFlag(int lPTSDTSFlag){
+ this->lPTSDTSFlag=lPTSDTSFlag;
+}
+
+
+int MpegSystemHeader::getESCRFlag() {
+ return lESCR;
+}
+
+
+void MpegSystemHeader::setESCRFlag(int lESCR) {
+ this->lESCR=lESCR;
+}
+
+
+int MpegSystemHeader::getES_RATE_Flag() {
+ return lESRateFlag;
+}
+
+
+void MpegSystemHeader::setES_RATE_Flag(int lESRateFlag) {
+ this->lESRateFlag=lESRateFlag;
+}
+
+
+
+int MpegSystemHeader::getDMSTRICKFLAG(){
+ return lDMSTRICKFLAG;
+}
+
+
+void MpegSystemHeader::setDMSTRICKFLAG(int lDMSTRICKFLAG) {
+ this->lDMSTRICKFLAG=lDMSTRICKFLAG;
+}
+
+
+int MpegSystemHeader::getADDITIONAL_COPY_FLAG() {
+ return lADDITIONAL_COPY_FLAG;
+}
+
+
+void MpegSystemHeader::setADDITIONAL_COPY_FLAG(int lADDITIONAL_COPY_FLAG) {
+ this->lADDITIONAL_COPY_FLAG=lADDITIONAL_COPY_FLAG;
+}
+
+
+
+int MpegSystemHeader::getPES_CRC_FLAG() {
+ return lPES_CRC_FLAG;
+}
+
+
+void MpegSystemHeader::setPES_CRC_FLAG(int lPES_CRC_FLAG) {
+ this->lPES_CRC_FLAG=lPES_CRC_FLAG;
+}
+
+
+int MpegSystemHeader::getPES_EXT_FLAG() {
+ return lPES_EXT_FLAG;
+}
+
+
+void MpegSystemHeader::setPES_EXT_FLAG(int lPES_EXT_FLAG) {
+ this->lPES_EXT_FLAG=lPES_EXT_FLAG;
+}
+
+
+ //
+ // PES EXTENSION [START]
+ //
+
+int MpegSystemHeader::getPrivateDataFlag() {
+ return lPrivateDataFlag;
+}
+
+
+void MpegSystemHeader::setPrivateDataFlag(int lPrivateDataFlag) {
+ this->lPrivateDataFlag=lPrivateDataFlag;
+}
+
+
+int MpegSystemHeader::getPackHeaderFieldFlag() {
+ return lPackHeaderFieldFlag;
+}
+
+
+void MpegSystemHeader::setPackHeaderFieldFlag(int lPackHeaderFieldFlag) {
+ this->lPackHeaderFieldFlag=lPackHeaderFieldFlag;
+}
+
+
+int MpegSystemHeader::getSequenceCounterFlag() {
+ return lSequenceCounterFlag;
+}
+
+
+void MpegSystemHeader::setSequenceCounterFlag(int lSequenceCounterFlag) {
+ this->lSequenceCounterFlag=lSequenceCounterFlag;
+}
+
+
+
+int MpegSystemHeader::getSTDBufferFlag() {
+ return lSTDBufferFlag;
+}
+
+
+void MpegSystemHeader::setSTDBufferFlag(int lSTDBufferFlag) {
+ this->lSTDBufferFlag=lSTDBufferFlag;
+}
+
+
+
+int MpegSystemHeader::getPES_EXT_FLAG_2() {
+ return lPES_EXT_FLAG_2;
+}
+
+
+void MpegSystemHeader::setPES_EXT_FLAG_2(int lPES_EXT_FLAG_2) {
+ this->lPES_EXT_FLAG_2=lPES_EXT_FLAG_2;
+}
+
+
+int MpegSystemHeader::getPES_EXT_FIELD_LENGTH() {
+ return nPES_EXT_FIELD_LENGTH;
+}
+
+
+void MpegSystemHeader::setPES_EXT_FIELD_LENGTH(int nPES_EXT_FIELD_LENGTH) {
+ this->nPES_EXT_FIELD_LENGTH=nPES_EXT_FIELD_LENGTH;
+}
+
+
+
+ //
+ // PES EXTENSION [END]
+ //
+
+
+
+int MpegSystemHeader::getPES_HEADER_DATA_LENGTH() {
+ return nPES_HEADER_DATA_LENGTH;
+}
+
+
+void MpegSystemHeader::setPES_HEADER_DATA_LENGTH(int nPES_HEADER_DATA_LENGTH){
+ this->nPES_HEADER_DATA_LENGTH=nPES_HEADER_DATA_LENGTH;
+}
+
+
+int MpegSystemHeader::getSubStreamID() {
+ return subStreamID;
+}
+
+
+void MpegSystemHeader::setSubStreamID(int subStreamID) {
+ this->subStreamID=subStreamID;
+}
+
+//
+// MPEG2 Stuff [END]
+//
+
+
+//
+// Transport Stream Header [START]
+//
+
+int MpegSystemHeader:: hasTSHeader() {
+ return lHasTSHeader;
+}
+
+void MpegSystemHeader::setTSHeader(unsigned int header) {
+
+ lHasTSHeader=false;
+
+ int byte3=header & 0xff;
+ header>>=8;
+ int byte2=header & 0xff;
+ header>>=8;
+ int byte1=header & 0xff;
+ header>>=8;
+ int byte0=header & 0xff;
+
+
+ sync_byte=byte0;
+ header=header >> 8;
+ transport_error_indicator = (byte1 >> 7) & 0x01;
+ payload_unit_start_indicator = (byte1 >> 6) & 0x01;
+ transport_priority = (byte1 >> 5) & 0x01;
+ pid = ((byte1 << 8) | byte2) & 0x1fff;
+ transport_scrambling_control = (byte3 >> 6) & 0x03;
+ adaption_field_control = (byte3 >> 4) & 0x03;
+ continuity_counter = byte3 & 0x0f;
+
+ if (sync_byte != 0x47) {
+ return ;
+ }
+ if (transport_error_indicator) {
+ return ;
+ }
+
+
+ lHasTSHeader=true;
+
+}
+
+unsigned int MpegSystemHeader::getSync_byte() {
+ return sync_byte;
+}
+
+
+unsigned int MpegSystemHeader::getTransport_error_indicator() {
+ return transport_error_indicator;
+}
+
+
+unsigned int MpegSystemHeader::getPayload_unit_start_indicator() {
+ return payload_unit_start_indicator;
+}
+
+
+unsigned int MpegSystemHeader::getTransport_priority() {
+ return transport_priority;
+}
+
+
+unsigned int MpegSystemHeader::getPid() {
+ return pid;
+}
+
+
+unsigned int MpegSystemHeader::getTransport_scrambling_control() {
+ return transport_scrambling_control;
+}
+
+
+unsigned int MpegSystemHeader::getAdaption_field_control() {
+ return adaption_field_control;
+}
+
+
+unsigned int MpegSystemHeader::getContinuity_counter() {
+ return continuity_counter;
+}
+
+unsigned int MpegSystemHeader::getPrograms() {
+ return programs;
+}
+
+
+void MpegSystemHeader::setPrograms(unsigned int programs) {
+ this->programs=programs;
+}
+
+
+unsigned int MpegSystemHeader::getProgramNumber() {
+ return programNumber;
+}
+
+
+void MpegSystemHeader::setProgramNumber(unsigned int programNumber) {
+ this->programNumber=programNumber;
+}
+
+
+unsigned int MpegSystemHeader::getPMTPID() {
+ return pmtPID;
+}
+
+
+void MpegSystemHeader::setPMTPID(unsigned int pmtPID) {
+ this->pmtPID=pmtPID;
+}
+
+
+MapPidStream* MpegSystemHeader::lookup(unsigned int pid) {
+ return mapPidStreamArray[pid % MAX_PIDS];
+}
+
+
+/*
+ Here we do a mapping from the pid to the "meaning" for the
+ pid (defined in the TS spec) and then we map this to
+ a normal mpeg stream ID.
+ (Which is used in the MpegSystemHeder to identify the
+ kind of packet we have)
+*/
+void MpegSystemHeader::insert(unsigned int pid,unsigned int tsType,
+ MpegSystemHeader* mpegHeader) {
+ if (currentPos >= MAX_PIDS) {
+ cout << "error to much pids in stream.TSSystemStream::insert"<<endl;
+ return;
+ }
+ printf("tsType:%x\n",tsType);
+ switch(tsType) {
+ case ISO_11172_VIDEO:
+ case ISO_13818_VIDEO:
+ case ISO_11172_AUDIO:
+ case ISO_13818_AUDIO:
+ case ISO_13818_PRIVATE:
+ case ISO_13818_PES_PRIVATE:
+ case ISO_13522_MHEG:
+ case ISO_13818_DSMCC:
+ case ISO_13818_TYPE_A:
+ case ISO_13818_TYPE_B:
+ case ISO_13818_TYPE_C:
+ case ISO_13818_TYPE_D:
+ case ISO_13818_TYPE_E:
+ case ISO_13818_AUX:
+ break;
+ default:
+ cout << "ignoring unknown tsType in TSSystemStream::insert"<<endl;
+ return;
+ }
+
+ MapPidStream* mapPidStream=lookup(pid);
+ int psType=_PAKET_ID_NUKE;
+
+ mapPidStream->pid=pid;
+ mapPidStream->tsType=tsType;
+ mapPidStream->psType=psType;
+ mapPidStream->isValid=true;
+
+ currentPos++;
+}
+
+
+void MpegSystemHeader::printTSHeader() {
+ if (hasTSHeader() == false) {
+ cout << "MpegSystemHeader::printTSHeader: NO TS HEADER"<<endl;
+ return;
+ }
+
+ printf("sync:%02X TE:%02X PUS:%02X TP:%02X PID:%04X TSC:%02X "
+ "AFC:%02X CC:%02X\n",
+ sync_byte,
+ transport_error_indicator,
+ payload_unit_start_indicator,
+ transport_priority,
+ pid,
+ transport_scrambling_control,
+ adaption_field_control,
+ continuity_counter);
+
+}
+
+
+void MpegSystemHeader::printProgramInfo() {
+ if (programs == 0) {
+ cout << "MpegSystemHeader::printProgramInfo: NO programs"<<endl;
+ } else {
+ cout << "MpegSystemHeader::printProgramInfo: programs:"<<programs<<endl;
+ }
+ printf("MPTS: programNumber=%x pmtPid=%x\n",programNumber, pmtPID);
+
+}
+
+void MpegSystemHeader::printMap(MapPidStream* mapPidStream) {
+ if (mapPidStream->isValid == false) {
+ cout << "TSSystemStream::printMap ** INVALID** "<<endl;
+ return;
+ }
+
+ printf("printMap->isValid:%x\n",mapPidStream->isValid);
+ printf("printMap->pid:%x\n",mapPidStream->pid);
+ printf("printMap->tsType:%x\n",mapPidStream->tsType);
+ printf("printMap->psType:%x\n",mapPidStream->psType);
+
+}
+
+
+//
+// Transport Stream Header [END]
+//
+
+
+
+void MpegSystemHeader::setMPEG2(int lmpeg2) {
+ this->lmpeg2=lmpeg2;
+}
+
+
+void MpegSystemHeader::print() {
+ cout << "MpegSystemHeader [START]"<<endl;
+ cout << "layer:"<<getLayer()<<endl;
+ cout << "MpegSystemHeader [END]"<<endl;
+
+}
+
+
+void MpegSystemHeader::setPSHeader(unsigned int header) {
+ lHasPSHeader=false;
+ if (header == _PACK_START_CODE) {
+ lHasPSHeader=true;
+ }
+ if (header == _SYSTEM_HEADER_START_CODE) {
+ lHasPSHeader=true;
+ }
+}
+
+int MpegSystemHeader::isSystemHeader(unsigned int header) {
+
+ if (header == _PACK_START_CODE) return true;
+ if (header == _SYSTEM_HEADER_START_CODE) return true;
+
+ int byte3=header & 0xff;
+ header>>=8;
+ int byte2=header & 0xff;
+ header>>=8;
+ int byte1=header & 0xff;
+ header>>=8;
+ int byte0=header & 0xff;
+
+ if (byte0 != 0x47) return false;
+ if ((byte1 >> 7) & 0x01) return false;
+
+ return true;
+}
diff --git a/mpeglib/lib/mpegplay/mpegSystemHeader.h b/mpeglib/lib/mpegplay/mpegSystemHeader.h
new file mode 100644
index 00000000..abad3794
--- /dev/null
+++ b/mpeglib/lib/mpegplay/mpegSystemHeader.h
@@ -0,0 +1,484 @@
+/*
+ stores info about system stream and sends data to audio/video
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+
+
+#ifndef __MPEGSYSTEMHEADER_H
+#define __MPEGSYSTEMHEADER_H
+
+
+
+#define _PACKET_SYSLAYER 1
+#define _PACKET_NO_SYSLAYER 0
+#define _PACKET_UNKNOWN_LAYER -1
+#define _PACKET_HEADER_SIZE 8
+
+
+// note: packetid 1 & 2 are normalized to _PAKET_ID_AUDIO
+// see packet.cpp
+
+#define _PAKET_ID_AUDIO_1 ((unsigned char) 0xc0)
+#define _PAKET_ID_AUDIO_2 ((unsigned char) 0xd0)
+#define _PAKET_ID_VIDEO ((unsigned char) 0xe0)
+#define _PAKET_ID_NUKE ((unsigned char) 0x0)
+
+#define _STD_SYSTEM_CLOCK_FREQ (unsigned long)90000
+#define _MUX_RATE_SCALE_FACTOR 50
+#define _MAX_STREAMS 8
+#define _NOT_PACKET_ID ((unsigned char) 0xff)
+#define _KILL_BUFFER ((unsigned char) 0xfe)
+
+
+
+#define _STD_AUDIO_STREAM_ID ((unsigned char) 0xb8)
+#define _STD_VIDEO_STREAM_ID ((unsigned char) 0xb9)
+#define _MIN_STREAM_ID_ID ((unsigned char) 0xbc)
+#define _RESERVED_STREAM_ID ((unsigned char) 0xbc)
+#define _PRIVATE_STREAM_1_ID ((unsigned char) 0xbd)
+#define _PADDING_STREAM_ID ((unsigned char) 0xbe)
+#define _PRIVATE_STREAM_2_ID ((unsigned char) 0xbf)
+#define _ECM_STREAM_ID ((unsigned char) 0xf0)
+#define _EMM_STREAM_ID ((unsigned char) 0xf1)
+#define _PROGRAM_STREAM_DIRECTORY_ID ((unsigned char) 0xff)
+#define _DSMCC_STREAM_ID ((unsigned char) 0xf2)
+#define _ITUTRECH222TYPEE_STREAM_ID ((unsigned char) 0xf8)
+#define _SUBSTREAM_AC3_ID ((unsigned char) 0x80)
+#define _SUBSTREAM_LPCM_ID ((unsigned char) 0xA0)
+#define _SUBSTREAM_SUBPIC_ID ((unsigned char) 0x20)
+
+
+/* Silly Constants.... */
+#define _PACK_START_CODE ((unsigned int)0x000001ba)
+#define _SYSTEM_HEADER_START_CODE ((unsigned int)0x000001bb)
+#define _PACKET_START_CODE_MASK ((unsigned int)0xffffff00)
+#define _PACKET_START_CODE_PREFIX ((unsigned int)0x00000100)
+#define _ISO_11172_END_CODE ((unsigned int)0x000001b9)
+
+#define _SEQ_START_CODE 0x000001b3
+
+
+// More constants for TS streams
+#define NULL_PID 8191
+#define INVALID_PID ((unsigned int)(-1))
+#define INVALID_PROGRAM ((unsigned int)(-1))
+#define INVALID_CC ((unsigned int)(-1))
+
+#define ISO_11172_VIDEO 1
+#define ISO_13818_VIDEO 2
+#define ISO_11172_AUDIO 3
+#define ISO_13818_AUDIO 4
+#define ISO_13818_PRIVATE 5
+#define ISO_13818_PES_PRIVATE 6
+#define ISO_13522_MHEG 7
+#define ISO_13818_DSMCC 8
+#define ISO_13818_TYPE_A 9
+#define ISO_13818_TYPE_B 10
+#define ISO_13818_TYPE_C 11
+#define ISO_13818_TYPE_D 12
+#define ISO_13818_TYPE_E 13
+#define ISO_13818_AUX 14
+
+
+struct MapPidStream_s {
+ // if this structure "is Valid" (association pid->tsType is ok)
+ int isValid;
+ // a not nearer defined int
+ unsigned int pid;
+ // the type for the pid defined in Transportstream
+ unsigned int tsType;
+ // runtime associated "fake" type for PS stream
+ unsigned int psType;
+ // outstanding bytes for PES packet
+ unsigned int pesPacketSize;
+};
+
+typedef MapPidStream_s MapPidStream;
+
+
+
+
+
+// More useful things
+
+#define FLOAT_0x10000 (double)((unsigned long)1 << 16)
+
+
+// MPEG2 PACK HEADER
+// SCRbase and SCRext
+// 32 .......................................0 9.........0
+// [PACK_START_CODE][01---1--][--------][-----1--][--------][-----1--][-------1
+
+#define ui64 unsigned long
+#define ui32 unsigned int
+#define i64 long
+#define i32 int
+
+#define MPEG1_CLK_REF (i64)90000
+#define MPEG2_CLK_REF (i64)27000000
+
+#define ZERO (i64)0
+#define GET_SCRBASE(buf) ( ((ui64)buf[4]&0xF8)>>3 | \
+ (ui64)buf[3]<<5 | \
+ ((ui64)buf[2]&0x03)<<13 | \
+ ((ui64)buf[2]&0xF8)<<12 | \
+ (ui64)buf[1]<<20 | \
+ ((ui64)buf[0]&0x03)<<28 | \
+ (ui64)buf[0]&0x38 <<27 )
+
+#define GET_SCREXT(buf) ( ((ui64)buf[5]&0xFE)>>1 | \
+ ((ui64)buf[4]&0x03)<<7 )
+
+// muxrate
+// 22 ......................0 stl
+// ... [--------][--------][------11][rrrrr---]
+#define GET_MPEG2MUXRATE(buf) ( (ui32)buf[6]<<14 | \
+ ((ui32)buf[7])<<6 | \
+ ((ui32)buf[8]&0x03)>>2) \
+
+#define GET_MPEG2STUFFING(buf) ((buf[9]&0x07))
+
+// MPEG1 PACK HEADER
+// SCR muxrate
+// 32........................................0 22......
+//[PACK_START_CODE][0010---1][--------][-------1][--------][-------1][1-------]
+#define GET_SCR(buf) ( ((ui64)buf[4]&0xFE) >>1 | \
+ ((ui64)buf[3]) <<7 | \
+ ((ui64)buf[2]&0xFE) <<14 | \
+ ((ui64)buf[1]) <<22 | \
+ ((ui64)buf[0]&0x0E) <<29 )
+
+#define GET_MPEG1_PTS(x) (GET_SCR(x)) //they follow the same pattern
+
+#define GET_MPEG1_MUXRATE(x) ( ((ui32)x[7]&0xFE) >>1 | \
+ ((ui32)x[6]) <<7 | \
+ ((ui32)x[5]&0x7F) <<15 )
+
+#define GET_MPEG2_PTS_FLAGS(buf) ( ((ui8)buf[3]&0xC0)>>6 )
+// MPEG2 PES packet (optional parameters)
+// PTS
+// 32........................................0
+// [PACKET_START_CODE][001x---1][--------][-------1][--------][-------1]
+#define GET_MPEG2_PTS(buf) GET_MPEG1_PTS(buf)
+
+
+
+#include <stdio.h>
+
+
+class MpegSystemHeader {
+
+ int lPTSFlag;
+ double scrTimeStamp;
+ double ptsTimeStamp;
+ double dtsTimeStamp;
+
+ int layer;
+ unsigned int header;
+ int lHasPSHeader;
+
+ int lmpeg2;
+
+ int packetID;
+ int packetLen;
+
+ int pesPacketLen;
+ int tsPacketLen;
+
+ unsigned long rate;
+ int stdBufferScale;
+ unsigned long stdBufferSize;
+
+ /* This are bitmaps, if bit x is a 1 the stream number x is
+ available */
+ unsigned long availableAudioLayers;
+ unsigned long availableVideoLayers;
+
+ int audioLayerSelect;
+ int videoLayerSelect;
+
+ //
+ // MPEG2 Header Info [START]
+ //
+ int lOriginal;
+ int lCopyRight;
+ int lDataAlignmentIndicator;
+ int lPesPriority;
+ int lEncrypted;
+ int startCodePrefix;
+
+
+
+ int lPTSDTSFlag;
+ int lESCR;
+ int lESRateFlag;
+ int lDMSTRICKFLAG;
+ int lADDITIONAL_COPY_FLAG;
+ int lPES_CRC_FLAG;
+ int lPES_EXT_FLAG;
+ int nPES_HEADER_DATA_LENGTH;
+
+ // EXT FILED [START]
+
+ int lPrivateDataFlag;
+ int lPackHeaderFieldFlag;
+ int lSequenceCounterFlag;
+ int lSTDBufferFlag;
+ int lPES_EXT_FLAG_2;
+ int nPES_EXT_FIELD_LENGTH;
+ // EXT FILED [END]
+
+ int subStreamID;
+ //
+ // MPEG2 Header Info [END]
+ //
+
+ //
+ // Transport Stream Header [START]
+ //
+
+ int lHasTSHeader;
+
+ unsigned int sync_byte;
+ unsigned int transport_error_indicator;
+ unsigned int payload_unit_start_indicator;
+ unsigned int transport_priority;
+ unsigned int pid;
+ unsigned int transport_scrambling_control;
+ unsigned int adaption_field_control;
+ unsigned int continuity_counter;
+
+ unsigned int programs;
+ unsigned int programNumber;
+ unsigned int pmtPID;
+
+ MapPidStream** mapPidStreamArray;
+ int currentPos;
+
+ //
+ // Transport Stream Header [END]
+ //
+
+ public:
+ MpegSystemHeader();
+ ~MpegSystemHeader();
+
+ void setHeader(unsigned int header);
+ unsigned int getHeader();
+ int hasRAWHeader();
+
+
+ int getPTSFlag();
+ void setPTSFlag(int lPTSFlag);
+
+ double getSCRTimeStamp();
+ double getPTSTimeStamp();
+ double getDTSTimeStamp();
+
+
+ void setSCRTimeStamp(double timeStamp);
+ void setPTSTimeStamp(double ptsTimeStamp);
+ void setDTSTimeStamp(double dtsTimeStamp);
+
+ // returns 1 if it is a syslayer 0 if non syslayer -1 if unknown
+ int getLayer();
+ void setLayer(int layer);
+ int hasPSHeader();
+
+ //
+ // MPEG2 Stuff [START]
+ //
+
+ int getMPEG2();
+ void setMPEG2(int lmpeg2);
+
+ // 1 Byte [Start]
+ int getOriginalOrCopy();
+ void setOriginalOrCopy(int lOriginal);
+
+ int getCopyRight();
+ void setCopyRight(int lCopyRight);
+
+ int getDataAlignmentIndicator();
+ void setDataAlignmentIndicator(int lDataAlignmentIndicator);
+
+ int getPesPriority();
+ void setPesPriority(int lPesPriority);
+
+ int getEncrypted();
+ void setEncrypted(int lEncrypted);
+
+ int getStartCodePrefix();
+ void setStartCodePrefix(int startCodePrefix);
+
+ // 1. Byte [End]
+
+ int getPTSDTSFlag();
+ void setPTSDTSFlag(int lPTSDTSFlag);
+
+ int getESCRFlag();
+ void setESCRFlag(int lESCR);
+
+ int getES_RATE_Flag();
+ void setES_RATE_Flag(int lESRateFlag);
+
+
+ int getDMSTRICKFLAG();
+ void setDMSTRICKFLAG(int lDMSTRICKFLAG);
+
+ int getADDITIONAL_COPY_FLAG();
+ void setADDITIONAL_COPY_FLAG(int lADDITIONAL_COPY_FLAG);
+
+ int getPES_CRC_FLAG();
+ void setPES_CRC_FLAG(int lPES_CRC_FLAG);
+
+ int getPES_EXT_FLAG();
+ void setPES_EXT_FLAG(int lPES_EXT_FLAG);
+
+ //
+ // PES EXTENSION [START]
+ //
+
+ int getPrivateDataFlag();
+ void setPrivateDataFlag(int lPrivateDataFlag);
+
+ int getPackHeaderFieldFlag();
+ void setPackHeaderFieldFlag(int lPackHeaderFieldFlag);
+
+ int getSequenceCounterFlag();
+ void setSequenceCounterFlag(int lSequenceCounterFlag);
+
+ int getSTDBufferFlag();
+ void setSTDBufferFlag(int lSTDBufferFlag);
+
+ int getPES_EXT_FLAG_2();
+ void setPES_EXT_FLAG_2(int lPES_EXT_FLAG_2);
+
+ int getPES_EXT_FIELD_LENGTH();
+ void setPES_EXT_FIELD_LENGTH(int nPES_EXT_FIELD_LENGTH);
+
+
+
+ //
+ // PES EXTENSION [END]
+ //
+
+ int getPES_HEADER_DATA_LENGTH();
+ void setPES_HEADER_DATA_LENGTH(int nPES_HEADER_DATA_LENGTH);
+
+
+ int getSubStreamID();
+ void setSubStreamID(int subStreamID);
+
+
+ //
+ // MPEG2 Stuff [END]
+ //
+
+
+ //
+ // Transport Stream Header [START]
+ //
+
+ // returns true if it is ts header & sets the TS
+ // values in this class.
+ int hasTSHeader();
+
+
+ unsigned int getSync_byte();
+ unsigned int getTransport_error_indicator();
+ unsigned int getPayload_unit_start_indicator();
+ unsigned int getTransport_priority();
+ unsigned int getPid();
+ unsigned int getTransport_scrambling_control();
+ unsigned int getAdaption_field_control();
+ unsigned int getContinuity_counter();
+
+ unsigned int getPrograms();
+ void setPrograms(unsigned int programs);
+
+ unsigned int getProgramNumber();
+ void setProgramNumber(unsigned int programNumber);
+
+ unsigned int getPMTPID();
+ void setPMTPID(unsigned int pmtPID);
+
+ //
+ // manage different pids and their tsTypes and the fake psTypes
+ //
+
+ MapPidStream* lookup(unsigned int pid);
+ void insert(unsigned int pid,unsigned int tsType,
+ MpegSystemHeader* mpegHeader);
+
+
+ void printTSHeader();
+ void printProgramInfo();
+ void printMap(MapPidStream* mapPidStream);
+
+ //
+ // Transport Stream Header [END]
+ //
+
+
+
+ void addAvailableLayer(int streamID);
+ void resetAvailableLayers();
+
+ int getAudioLayerSelect();
+ void setAudioLayerSelect(int layer);
+
+ int getVideoLayerSelect();
+ void setVideoLayerSelect(int layer);
+
+
+ int getPacketID();
+ void setPacketID(int packetID);
+
+ // data which can be safley read and belongs to packetID
+ int getPacketLen();
+ void setPacketLen(int packetLen);
+
+ // length of PES packet (normally == getPacketLent)
+ int getPESPacketLen();
+ void setPESPacketLen(int packetLen);
+
+ // rest lenght of TS packet.
+ int getTSPacketLen();
+ void setTSPacketLen(int packetLen);
+
+
+
+ int getRate();
+ void setRate(int rate);
+
+ int getStdBufferScale();
+ void setStdBufferScale(int stdBufferScale);
+
+ unsigned long getStdBufferSize();
+ void setStdBufferSize(unsigned long stdBufferSize);
+
+ void print();
+
+ // return true is system header in some kind (TS or 1ba/1bb)
+ static int isSystemHeader(unsigned int header);
+
+ private:
+ void setTSHeader(unsigned int header);
+ void setPSHeader(unsigned int header);
+
+};
+
+#endif
+
+
+
diff --git a/mpeglib/lib/mpegplay/mpegSystemStream.cpp b/mpeglib/lib/mpegplay/mpegSystemStream.cpp
new file mode 100644
index 00000000..ca25d7e8
--- /dev/null
+++ b/mpeglib/lib/mpegplay/mpegSystemStream.cpp
@@ -0,0 +1,235 @@
+/*
+ reads paket input data
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "mpegSystemStream.h"
+
+#define _RESYNC_STATE_INIT 0
+#define _RESYNC_STATE_NEED_PACKET 1
+#define _RESYNC_STATE_NEED_START 2
+
+#include <iostream>
+
+using namespace std;
+
+
+MpegSystemStream::MpegSystemStream(InputStream* input) {
+ this->input=input;
+ syncCode=0xff; // invalid
+ lState=_RESYNC_STATE_INIT;
+ tsSystemStream=new TSSystemStream(input);
+ psSystemStream=new PSSystemStream(input);
+ pesSystemStream=new PESSystemStream(input);
+}
+
+
+MpegSystemStream::~MpegSystemStream() {
+ delete tsSystemStream;
+ delete psSystemStream;
+ delete pesSystemStream;
+}
+
+
+int MpegSystemStream::getByteDirect() {
+ unsigned char byte;
+ if (input->read((char*)&byte,1) != 1) {
+ return -1;
+ }
+ return (int)byte;
+}
+
+int MpegSystemStream::readSyncCode() {
+ int byte;
+ byte=getByteDirect();
+ if (byte==-1) {
+ return false;
+ }
+
+ syncCode<<=8;
+ syncCode|=byte;
+ syncCode&=0xffffffff;
+ return true;
+
+}
+
+int MpegSystemStream::firstInitialize(MpegSystemHeader* mpegHeader) {
+
+ if (readSyncCode() == false) {
+ return false;
+ }
+ mpegHeader->setHeader(syncCode);
+
+ // SEQ_START_CODE: 1b3
+ if (mpegHeader->hasRAWHeader()) {
+ // If we found a seq_heade_start code we assume
+ // that we are a video only stream
+ // we must directly insert it.
+
+ // here we set for all future calls fixed
+ // parameter
+ mpegHeader->setLayer(_PACKET_NO_SYSLAYER); // no syslayer
+ mpegHeader->setPacketID(_PAKET_ID_VIDEO);
+ mpegHeader->setPacketLen(8192);
+ mpegHeader->resetAvailableLayers();
+ return true;
+ }
+ // no 1bb
+ if (syncCode == _SYSTEM_HEADER_START_CODE) return false;
+
+ // TS 1ba
+ if (processSystemHeader(mpegHeader) == true) {
+ // have init. we are a syslayer
+ mpegHeader->setLayer(_PACKET_SYSLAYER); // syslayer
+ lState=_RESYNC_STATE_NEED_START;
+ return true;
+ }
+ return false;
+
+}
+
+void MpegSystemStream::reset() {
+ lState=_RESYNC_STATE_NEED_PACKET;
+}
+
+
+int MpegSystemStream::nextPacket(MpegSystemHeader* mpegHeader) {
+ int layer=mpegHeader->getLayer();
+ if (layer == _PACKET_NO_SYSLAYER) {
+ return true;
+ }
+ // seek to packet
+ if (readSyncCode() == false) {
+ return false;
+ }
+
+
+ // default to "HLT" operation
+ mpegHeader->setPacketID(_PAKET_ID_NUKE);
+ mpegHeader->setPacketLen(0);
+
+
+ // here we know that we are a SYSLAYER (TS or 1ba)
+ if (lState == _RESYNC_STATE_NEED_PACKET) {
+ // no 1bb codes in resync state
+ if (syncCode == _SYSTEM_HEADER_START_CODE) return false;
+ }
+
+ // is this a syslayer _STARTCODE_ ?
+ if (MpegSystemHeader::isSystemHeader(syncCode)==true) {
+ // set startcode & process it
+ mpegHeader->setHeader(syncCode);
+ // TS 1ba 1bb
+ if (processSystemHeader(mpegHeader) == true) {
+ lState=_RESYNC_STATE_NEED_START;
+ return true;
+ }
+ reset();
+ return false;
+ }
+
+ if (lState != _RESYNC_STATE_NEED_START) return false;
+
+ // no syslayer startcode. PES processing
+ if ((syncCode & 0xFFFFFF00) == 0x00000100) {
+ int bytes=pesSystemStream->processStartCode(syncCode,mpegHeader);
+ if (bytes == 0) {
+ reset();
+ return false;
+ }
+ // if we are a TS layer we cannot read getPESPacketLength byte
+ // but only the bytes given by getTSPacketLength
+ // additionally we must store the mapping between pid and real packetID.
+ if (mpegHeader->hasTSHeader()) {
+ unsigned int pid=mpegHeader->getPid();
+ unsigned int id =mpegHeader->getPacketID();
+ printf("current PID:%x current PacketID:%x\n",pid,id);
+ MapPidStream* mapPidStream=mpegHeader->lookup(pid);
+ mapPidStream->psType=id;
+ mapPidStream->pesPacketSize=mpegHeader->getPESPacketLen();
+
+ int ts=mpegHeader->getTSPacketLen();
+ if (bytes > ts) {
+ cout << "ERROR PES READ MORE than TS HAS"<<endl;
+ return false;
+ }
+ mpegHeader->setTSPacketLen(ts-bytes);
+ return demux_ts_pes_buffer(mpegHeader);
+ }
+ // 1ba stream
+ mpegHeader->setPacketLen(mpegHeader->getPESPacketLen());
+ return true;
+ }
+
+ // something unknown/else went wrong
+ return false;
+}
+
+int MpegSystemStream::demux_ts_pes_buffer(MpegSystemHeader* mpegHeader) {
+
+
+ if (lState == _RESYNC_STATE_NEED_PACKET) {
+ cout << "NO ts_pes because of resync"<<endl;
+ return false;
+ }
+ MapPidStream* mapPidStream=mpegHeader->lookup(mpegHeader->getPid());
+
+ int pes=mapPidStream->pesPacketSize;
+ int ts=mpegHeader->getTSPacketLen();
+ int wantRead=pes;
+
+ // bug workaround for PES packetlength == 0
+ if (pes > 0) {
+ if (ts < wantRead) {
+ cout << "TS is less setting wantRead:"<<ts<<endl;
+ mapPidStream->pesPacketSize=pes-ts;
+ wantRead=ts;
+ } else {
+ // pes < ts
+ mpegHeader->setTSPacketLen(ts-pes);
+ wantRead=pes;
+ }
+ } else {
+ // in case of bug, always put the whole packet for pid in
+ wantRead=ts;
+ }
+ mpegHeader->setPacketID(mapPidStream->psType);
+ mpegHeader->setPacketLen(wantRead);
+ return true;
+}
+
+
+int MpegSystemStream::processSystemHeader(MpegSystemHeader* mpegHeader) {
+ if (mpegHeader->hasTSHeader()) {
+ if (tsSystemStream->processStartCode(mpegHeader) == true) {
+ if (mpegHeader->getPacketID() == _PAKET_ID_NUKE) {
+ // nuke the data by signalling how much bytes to nuke
+ mpegHeader->setPacketLen(mpegHeader->getTSPacketLen());
+ return true;
+ }
+ unsigned int pus=mpegHeader->getPayload_unit_start_indicator();
+ if (pus == false) {
+ // we need to append data
+ return demux_ts_pes_buffer(mpegHeader);
+ }
+ return true;
+ }
+ return false;
+ }
+ if (mpegHeader->hasPSHeader()) {
+ return (psSystemStream->processStartCode(mpegHeader));
+ }
+ return false;
+
+}
+
+
+
diff --git a/mpeglib/lib/mpegplay/mpegSystemStream.h b/mpeglib/lib/mpegplay/mpegSystemStream.h
new file mode 100644
index 00000000..8c5d5ffa
--- /dev/null
+++ b/mpeglib/lib/mpegplay/mpegSystemStream.h
@@ -0,0 +1,53 @@
+/*
+ reads paket input data
+ Copyright (C) 1999 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+#ifndef __MPEGSYSTEMSTREAM_H
+#define __MPEGSYSTEMSTREAM_H
+
+
+
+#include "tsSystemStream.h"
+#include "psSystemStream.h"
+#include "pesSystemStream.h"
+
+
+class MpegSystemStream {
+
+ InputStream* input;
+ int lHasLength;
+ unsigned int syncCode;
+ int lState;
+ TSSystemStream* tsSystemStream;
+ PSSystemStream* psSystemStream;
+ PESSystemStream* pesSystemStream;
+
+ public:
+ MpegSystemStream(InputStream* input);
+ ~MpegSystemStream();
+
+ // returns true if init successful
+ int firstInitialize(MpegSystemHeader* mpegHeader);
+ int nextPacket(MpegSystemHeader* mpegHeader);
+ inline int eof() { return input->eof(); }
+ void reset();
+
+ private:
+ int readSyncCode();
+ int getByteDirect();
+ int demux_ts_pes_buffer(MpegSystemHeader* mpegHeader);
+
+ int processSystemHeader(MpegSystemHeader* mpegHeader);
+
+
+};
+
+#endif
diff --git a/mpeglib/lib/mpegplay/mpegVideoBitWindow.cpp b/mpeglib/lib/mpegplay/mpegVideoBitWindow.cpp
new file mode 100644
index 00000000..87467a9c
--- /dev/null
+++ b/mpeglib/lib/mpegplay/mpegVideoBitWindow.cpp
@@ -0,0 +1,258 @@
+/*
+ bitwindow mpeg video
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "mpegVideoBitWindow.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+MpegVideoBitWindow::MpegVideoBitWindow() {
+ // Make buffer length multiple of 4.
+
+ this->size=80000;
+
+
+
+ if ((size % 4) != 0) {
+ cout << "MpegVideoStream not multiple of 4"<<endl;
+ exit(-1);
+ }
+
+ /* Create MpegVideoStream. */
+ buf_start = (unsigned int*) malloc (sizeof(unsigned int)*(size*4));
+
+ /*
+ * Set max_buf_length to one less than actual length to deal with messy
+ * data without proper seq. end codes.
+ */
+ max_buf_length=size-1;
+
+
+ /* Initialize bitstream i/o fields. */
+
+ bit_offset = 0;
+ buffer = buf_start;
+ buf_length = 0;
+ num_left=0;
+ leftover_bytes=0;
+ curBits = 0;
+
+
+
+
+ nBitMask[0] = 0x00000000;
+ nBitMask[1] = 0x80000000;
+ nBitMask[2] = 0xc0000000;
+ nBitMask[3] = 0xe0000000;
+ nBitMask[4] = 0xf0000000;
+ nBitMask[5] = 0xf8000000;
+ nBitMask[6] = 0xfc000000;
+ nBitMask[7] = 0xfe000000;
+ nBitMask[8] = 0xff000000;
+ nBitMask[9] = 0xff800000;
+ nBitMask[10] = 0xffc00000;
+ nBitMask[11] = 0xffe00000;
+ nBitMask[12] = 0xfff00000;
+ nBitMask[13] = 0xfff80000;
+ nBitMask[14] = 0xfffc0000;
+ nBitMask[15] = 0xfffe0000;
+ nBitMask[16] = 0xffff0000;
+ nBitMask[17] = 0xffff8000;
+ nBitMask[18] = 0xffffc000;
+ nBitMask[19] = 0xffffe000;
+ nBitMask[20] = 0xfffff000;
+ nBitMask[21] = 0xfffff800;
+ nBitMask[22] = 0xfffffc00;
+ nBitMask[23] = 0xfffffe00;
+ nBitMask[24] = 0xffffff00;
+ nBitMask[25] = 0xffffff80;
+ nBitMask[26] = 0xffffffc0;
+ nBitMask[27] = 0xffffffe0;
+ nBitMask[28] = 0xfffffff0;
+ nBitMask[29] = 0xfffffff8;
+ nBitMask[30] = 0xfffffffc;
+ nBitMask[31] = 0xfffffffe;
+ nBitMask[32] = 0xffffffff;
+
+
+}
+
+
+MpegVideoBitWindow::~MpegVideoBitWindow() {
+ delete buf_start;
+}
+
+
+
+int MpegVideoBitWindow::appendToBuffer(unsigned char* ptr,int len) {
+ int byte_length = getLength()*4;
+
+
+ resizeBuffer(len);
+
+ if (num_left != 0) {
+ byte_length += num_left;
+ *(buffer+buf_length)=leftover_bytes;
+ }
+ memcpy(((unsigned char *)buffer)+byte_length,ptr,len);
+
+ if ((unsigned long int)1 != ntohl(1)) {
+ unsigned int *mark = buffer+buf_length;
+ int i;
+ int n=(len+num_left)&0xfffffffc;
+ for (i=0; i < n; i+=4) {
+ *mark=ntohl(*mark);
+ mark++;
+ }
+ }
+ byte_length = byte_length + len;
+ num_left = byte_length % 4;
+ buf_length = byte_length / 4;
+ updateCurBits();
+
+ leftover_bytes = *(buffer +buf_length);
+ return true;
+}
+
+int MpegVideoBitWindow::getLinearFree() {
+ unsigned int* endPos=buf_start+size;
+ unsigned int* currPos=buffer+buf_length;
+
+ int back=endPos-currPos;
+ return back;
+}
+
+
+
+
+
+void MpegVideoBitWindow::flushByteOffset() {
+ int byteoff;
+
+ byteoff = bit_offset % 8;
+
+ if (byteoff != 0) {
+ flushBitsDirect((8-byteoff));
+ }
+}
+
+
+void MpegVideoBitWindow::appendToBuffer(unsigned int startCode) {
+ unsigned int startCodeRaw=htonl(startCode);
+ resizeBuffer(4);
+ appendToBuffer((unsigned char*)&startCodeRaw,4);
+}
+
+
+void MpegVideoBitWindow::clear() {
+ buffer = buf_start;
+ buf_length = 0;
+ bit_offset = 0;
+ curBits = 0;
+}
+
+
+int MpegVideoBitWindow::getLength() {
+ return buf_length;
+}
+
+
+
+
+
+
+
+void MpegVideoBitWindow::printChar(int bytes) {
+ int i;
+ unsigned char* mark;
+
+ mark=(unsigned char *)buffer;
+
+ for(i=0;i<bytes;i++) {
+ printf("i:%d read=%x\n",i,mark[i]);
+ }
+ printf("*********\n");
+
+}
+
+
+void MpegVideoBitWindow::printInt(int bytes) {
+ int i;
+ int n;
+ unsigned int* mark;
+
+ mark=(unsigned int*)buf_start;
+
+ n=bytes/sizeof(int);
+ for(i=0;i<n;i++) {
+ printf("i:%d read=%x\n",i,mark[i]);
+ }
+ printf("*********\n");
+
+}
+
+
+void MpegVideoBitWindow::print() {
+ int byte_length = getLength()*4;
+
+ printf("bit_offset:%x\n",bit_offset);
+ printf("num_left:%x\n",num_left);
+ printf("leftover_bytes:%x\n",leftover_bytes);
+ printf("buf_length:%x\n",buf_length);
+ printf("curBits:%x\n",curBits);
+ printf("pos:%8x\n",byte_length);
+ printChar(8);
+}
+
+
+void MpegVideoBitWindow::resizeBuffer(int insertBytes) {
+ /* Read all the headers, now make room for packet */
+ if (buf_start+max_buf_length < buffer+insertBytes/4+buf_length) {
+
+ if (max_buf_length - buf_length < (int) insertBytes/4) {
+
+ /* Buffer too small for a packet (plus whats there),
+ * time to enlarge it!
+ */
+
+ unsigned int *old = buf_start;
+ max_buf_length=buf_length+insertBytes/4+1;
+
+ buf_start=(unsigned int*) malloc(sizeof(unsigned int)*max_buf_length);
+ if (buf_start == NULL) {
+ cout << "allocation of:"<<max_buf_length<<" bytes failed"<<endl;
+ exit(0);
+ }
+ memcpy((unsigned char *)buf_start,buffer,(unsigned int)buf_length*4);
+ delete old;
+ buffer = buf_start;
+ cout << "enlarge buffer-1 end***********"<<endl;
+
+ } else {
+ memcpy((unsigned char *)buf_start,
+ buffer, (unsigned int) buf_length*4);
+ buffer = buf_start;
+ }
+ }
+}
+
+
+void MpegVideoBitWindow::fillWithIsoEndCode(int bytes) {
+ int i;
+ int n=bytes/4;
+ for (i=0;i<n;i++) {
+ appendToBuffer(ISO_11172_END_CODE);
+ }
+}
diff --git a/mpeglib/lib/mpegplay/mpegVideoBitWindow.h b/mpeglib/lib/mpegplay/mpegVideoBitWindow.h
new file mode 100644
index 00000000..46abe44e
--- /dev/null
+++ b/mpeglib/lib/mpegplay/mpegVideoBitWindow.h
@@ -0,0 +1,108 @@
+/*
+ bitwindow mpeg video
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+
+#ifndef __MPEGVIDEOBITWINDOW_H
+#define __MPEGVIDEOBITWINDOW_H
+
+#include "../input/inputPlugin.h"
+
+
+#define ISO_11172_END_CODE ((unsigned int)0x000001b9)
+
+class MpegVideoBitWindow {
+ int size; /* size of buffer */
+ unsigned int bit_offset; /* Bit offset in stream. */
+ unsigned int *buffer; /* Pointer to next byte in buffer */
+ int buf_length; /* Length of remaining buffer.*/
+ unsigned int *buf_start; /* Pointer to buffer start. */
+ int max_buf_length; /* Max length of buffer. */
+ unsigned int num_left; /* from ReadPacket - leftover */
+ unsigned int leftover_bytes; /* from ReadPacket - leftover */
+ unsigned int curBits; /* current bits */
+
+
+ unsigned int nBitMask[33];
+
+
+ public:
+ MpegVideoBitWindow();
+ ~MpegVideoBitWindow();
+
+ int appendToBuffer(unsigned char* ptr,int len);
+ int getLinearFree();
+ // true if feof() is true and the buffer is emtpy
+ int isEof();
+ void flushByteOffset();
+ void appendToBuffer(unsigned int startCode);
+
+
+ inline void updateCurBits() {
+ curBits = *buffer << bit_offset;
+ }
+
+ inline unsigned int showBits(int bits) {
+
+ unsigned int mask=nBitMask[bits];
+ int shift=32-(bits);
+ int bO;
+ shift=(curBits & mask)>>shift;
+ bO = bit_offset + bits;
+ if (bO > 32) {
+ return (shift | (*(buffer+1)>>(64-bO)));
+ }
+ return shift;
+ }
+
+ inline unsigned int showBits32() {
+ if (bit_offset) {
+ return (curBits | (*(buffer+1) >> (32 - bit_offset)));
+ }
+ return curBits;
+ }
+
+ inline void flushBitsDirect(unsigned int bits) {
+ bit_offset += bits;
+ if (bit_offset & 0x20) {
+ bit_offset -= 32;
+ bit_offset &= 0x1f;
+ buffer++;
+ updateCurBits();
+ buf_length--;
+ }
+ else {
+ curBits <<= bits;
+ }
+ }
+
+ inline unsigned int getBits(int bits) {
+ unsigned int result=showBits(bits);
+ flushBitsDirect(bits);
+ return result;
+ }
+
+ void clear();
+ int getLength();
+
+ int hasBytes(int bytes);
+
+ void printChar(int bytes);
+ void printInt(int bytes);
+ void print();
+ void resizeBuffer(int insertBytes);
+ void fillWithIsoEndCode(int bytes);
+
+
+
+};
+#endif
diff --git a/mpeglib/lib/mpegplay/mpegVideoHeader.cpp b/mpeglib/lib/mpegplay/mpegVideoHeader.cpp
new file mode 100644
index 00000000..e91401a8
--- /dev/null
+++ b/mpeglib/lib/mpegplay/mpegVideoHeader.cpp
@@ -0,0 +1,293 @@
+/*
+ stores sequence header info, for reinit of stream
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "mpegVideoHeader.h"
+
+#include "mpegExtension.h"
+#include "mpegVideoStream.h"
+
+#include <iostream>
+
+using namespace std;
+
+/* Video rates table */
+/* Cheat on Vid rates, round to 30, and use 30 if illegal value
+ Except for 9, where Xing means 15, and given their popularity, we'll
+ be nice and do it */
+
+static double VidRateNum[16]={29.97, 24, 24, 25, 29.97, 29.97, 50, 59.94,
+ 59.94, 14.985, 29.97, 29.97, 29.97, 29.97,
+ 29.97, 29.97};
+
+
+
+static const unsigned char default_intra_matrix[64] = {
+ 8, 16, 19, 22, 26, 27, 29, 34,
+ 16, 16, 22, 24, 27, 29, 34, 37,
+ 19, 22, 26, 27, 29, 34, 34, 38,
+ 22, 22, 26, 27, 29, 34, 37, 40,
+ 22, 26, 27, 29, 32, 35, 40, 48,
+ 26, 27, 29, 32, 35, 40, 48, 58,
+ 26, 27, 29, 34, 38, 46, 56, 69,
+ 27, 29, 35, 38, 46, 56, 69, 83};
+
+
+
+/* Set up array for fast conversion from zig zag order to row/column
+ coordinates.
+*/
+
+const int zigzag[64][2] = {
+ {0,0},{1,0},{0,1},{0,2},{1,1},{2,0},{3,0},{2,1},{1,2},{0,3},{0,4},{1,3},
+ {2,2},{3,1},{4,0},{5,0},{4,1},{3,2},{2,3},{1,4},{0,5},{0,6},{1,5},{2,4},
+ {3,3},{4,2},{5,1},{6,0},{7,0},{6,1},{5,2},{4,3},{3,4},{2,5},{1,6},{0,7},
+ {1,7},{2,6},{3,5},{4,4},{5,3},{6,2},{7,1},{7,2},{6,3},{5,4},{4,5},{3,6},
+ {2,7},{3,7},{4,6},{5,5},{6,4},{7,3},{7,4},{6,5},{5,6},{4,7},{5,7},{6,6},
+ {7,5},{7,6},{6,7},{7,7} };
+
+
+
+
+
+MpegVideoHeader::MpegVideoHeader() {
+ init();
+
+}
+
+
+void MpegVideoHeader::init() {
+
+ h_size=0;
+ v_size=0;
+ mb_height=0;
+ mb_width=0;
+ mb_size=0;
+ aspect_ratio=0;
+ bit_rate=0;
+ vbv_buffer_size=0;
+ const_param_flag=0;
+ picture_rate=0.0;
+ extension=new MpegExtension();
+ init_quanttables();
+
+}
+
+void MpegVideoHeader::init_quanttables() {
+ int i;
+ int j;
+
+ /* Copy default intra matrix. */
+
+ for (i = 0; i < 8; i++) {
+ for (j = 0; j < 8; j++) {
+ intra_quant_matrix[i][j]=default_intra_matrix[i*8+j];
+ }
+ }
+
+ /* Initialize non intra quantization matrix. */
+
+ for (i = 0; i < 8; i++) {
+ for (j = 0; j < 8; j++) {
+ non_intra_quant_matrix[i][j] = 16;
+ }
+ }
+}
+
+
+MpegVideoHeader::~MpegVideoHeader() {
+
+ delete extension;
+
+}
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ParseSeqHead --
+ *
+ * Assumes bit stream is at the END of the sequence
+ * header start code. Parses off the sequence header.
+ *
+ * Results:
+ * Fills the vid_stream structure with values derived and
+ * decoded from the sequence header. Allocates the pict image
+ * structures based on the dimensions of the image space
+ * found in the sequence header.
+ *
+ * Side effects:
+ * Bit stream irreversibly parsed off.
+ *
+ *--------------------------------------------------------------
+ */
+int MpegVideoHeader::parseSeq(MpegVideoStream* mpegVideoStream) {
+ unsigned int data;
+ int i ;
+
+ // seq_start_code already flushed!!!
+
+ /* Get horizontal size of image space. */
+
+ h_size=mpegVideoStream->getBits(12);
+
+ /* Get vertical size of image space. */
+
+ v_size=mpegVideoStream->getBits(12);
+
+
+ /* Calculate macroblock width and height of image space. */
+
+ mb_width = (h_size + 15) / 16;
+ mb_height = (v_size + 15) / 16;
+ mb_size=mb_height * mb_width-1;
+
+
+
+ /* Parse of aspect ratio code. */
+
+ data=mpegVideoStream->getBits(4);
+
+ aspect_ratio = (unsigned char) data;
+
+ /* Parse off picture rate code. */
+
+ data=mpegVideoStream->getBits(4);
+ picture_rate=VidRateNum[data];
+
+ /* Parse off bit rate. */
+
+ data=mpegVideoStream->getBits(18);
+ bit_rate = data;
+
+ /* Flush marker bit. */
+
+ mpegVideoStream->flushBits(1);
+
+ /* Parse off vbv buffer size. */
+
+ data=mpegVideoStream->getBits(10);
+ vbv_buffer_size = data;
+
+ /* Parse off contrained parameter flag. */
+
+ data=mpegVideoStream->getBits(1);
+ if (data) {
+ const_param_flag = true;
+ } else
+ const_param_flag = false;
+
+ /*
+ * If intra_quant_matrix_flag set, parse off intra quant matrix values.
+ */
+ data=mpegVideoStream->getBits(1);
+ if (data) {
+ for (i = 0; i < 64; i++) {
+ data=mpegVideoStream->getBits(8);
+ intra_quant_matrix[zigzag[i][1]][zigzag[i][0]]=(unsigned char)data;
+ }
+ }
+ /*
+ * If non intra quant matrix flag set, parse off non intra quant matrix
+ * values.
+ */
+
+ data=mpegVideoStream->getBits(1);
+ if (data) {
+ for (i = 0; i < 64; i++) {
+ data=mpegVideoStream->getBits(8);
+
+ non_intra_quant_matrix[zigzag[i&0x3f][1]][zigzag[i&0x3f][0]]=
+ (unsigned char) data;
+ }
+ }
+ /*
+ * If next start code is extension/user start code,
+ * parse off extension data.
+ */
+ extension->processExtensionData(mpegVideoStream);
+
+ return true;
+
+}
+
+
+
+
+void MpegVideoHeader::copyTo(MpegVideoHeader* dest) {
+
+
+ dest->h_size=h_size;
+ dest->v_size=v_size;
+ dest->mb_height=mb_height;
+ dest->mb_width=mb_width;
+ dest->mb_size=mb_size;
+ dest->aspect_ratio=aspect_ratio;
+ dest->bit_rate=bit_rate;
+ dest->vbv_buffer_size=vbv_buffer_size;
+ dest->const_param_flag=const_param_flag;
+ dest->picture_rate=picture_rate;
+
+ int i;
+ int j;
+
+
+ /* Copy default intra matrix. */
+
+ for (i = 0; i < 8; i++) {
+ for (j = 0; j < 8; j++) {
+ dest->intra_quant_matrix[i][j]=intra_quant_matrix[i][j];
+
+ }
+ }
+
+ /* Initialize non intra quantization matrix. */
+
+ for (i = 0; i < 8; i++) {
+ for (j = 0; j < 8; j++) {
+ dest->non_intra_quant_matrix[i][j] =non_intra_quant_matrix[i][j] ;
+ }
+ }
+
+}
+
+
+
+
+double MpegVideoHeader::getPictureTime() {
+ if (picture_rate > 0) {
+ return 1.0/picture_rate;
+ }
+ return 0.0;
+}
+
+
+
+
+
+
+
+void MpegVideoHeader::print(char* description) {
+ cout << "MpegVideoHeader [START]:"<<description<<endl;
+ cout <<"h_size:"<<h_size<<endl;
+ cout <<"v_size:"<<v_size<<endl;
+ cout <<"mb_height:"<<mb_height<<endl;
+ cout <<"mb_width:"<<mb_width<<endl;
+ cout <<"mb_size:"<<mb_size<<endl;
+ cout <<"aspect_ratio:"<<aspect_ratio<<endl;
+ cout <<"bit_rate:"<<bit_rate<<endl;
+ cout <<"vbv_buffer_size:"<<vbv_buffer_size<<endl;
+ cout <<"const_param_flag:"<<const_param_flag<<endl;
+ cout << "MpegVideoHeader [END]:"<<endl;
+
+}
diff --git a/mpeglib/lib/mpegplay/mpegVideoHeader.h b/mpeglib/lib/mpegplay/mpegVideoHeader.h
new file mode 100644
index 00000000..bb3302a1
--- /dev/null
+++ b/mpeglib/lib/mpegplay/mpegVideoHeader.h
@@ -0,0 +1,83 @@
+/*
+ stores sequence header info, for reinit of stream
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+
+
+
+#ifndef __MPEGVIDEOHEADER_H
+#define __MPEGVIDEOHEADER_H
+
+
+
+/**
+ Some vcd do only have one sequence header for the whole
+ cd.
+ This means we must store this info even after a seek
+ which usually destroy the video stream object.
+ We then can re-init the video object with the values
+ we store here.
+
+ Here we have the "header" for an mpeg video stream.
+
+*/
+
+
+class MpegVideoHeader {
+
+ unsigned int h_size; /* Horiz. size in pixels. */
+ unsigned int v_size; /* Vert. size in pixels. */
+ int mb_height; /* Vert. size in mblocks. */
+ int mb_width; /* Horiz. size in mblocks. */
+ int mb_size; /* mb_height*mb_width-1 */
+ unsigned char aspect_ratio; /* Code for aspect ratio. */
+ unsigned int bit_rate; /* Bit rate. */
+ unsigned int vbv_buffer_size; /* Minimum buffer size. */
+ int const_param_flag; /* Contrained parameter flag. */
+ float picture_rate; /* Parse off picture rate code*/
+ unsigned int intra_quant_matrix[8][8]; /* Quantization matrix for
+ intracoded frames. */
+ unsigned int non_intra_quant_matrix[8][8]; /* Quanitization matrix for
+ non intracoded frames. */
+ class MpegExtension* extension;
+
+
+ public:
+
+ MpegVideoHeader();
+ ~MpegVideoHeader();
+
+ int parseSeq(class MpegVideoStream* mpegVideoStream);
+ void copyTo(MpegVideoHeader* dest);
+ void print(char* description);
+ void init_quanttables();
+
+ inline int getMB_Height() { return mb_height;}
+ inline int getMB_Size() { return mb_size;}
+ inline int getMB_Width() { return mb_width;}
+
+ inline float getPictureRate() { return picture_rate ;}
+ double getPictureTime();
+
+ inline unsigned int* getIntra_quant_matrix() {
+ // printf("getI:%p\n",intra_quant_matrix[0]);
+ return intra_quant_matrix[0]; }
+ inline unsigned int* getNon_intra_quant_matrix() {
+ // printf("getN:%p\n",non_intra_quant_matrix[0]);
+ return non_intra_quant_matrix[0]; }
+
+ private:
+ void init();
+
+};
+
+#endif
diff --git a/mpeglib/lib/mpegplay/mpegVideoLength.cpp b/mpeglib/lib/mpegplay/mpegVideoLength.cpp
new file mode 100644
index 00000000..4befa31a
--- /dev/null
+++ b/mpeglib/lib/mpegplay/mpegVideoLength.cpp
@@ -0,0 +1,424 @@
+/*
+ mpg I video/audio player plugin
+ Copyright (C) 1999 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "mpegVideoLength.h"
+
+#include "../mpegplay/mpegVideoStream.h"
+#include "../mpegplay/gop.h"
+
+#include <iostream>
+
+using namespace std;
+
+#define SEARCH_SIZE 1024*1024*6
+#define SEEKWINDOW 1024*1024
+
+MpegVideoLength::MpegVideoLength(InputStream* input) {
+
+ this->input=input;
+ this->mpegVideoStream=new MpegVideoStream(input);
+
+ startGOP=new GOP();
+ endGOP=new GOP();
+ lengthGOP=new GOP();
+ mpegVideoHeader=new MpegVideoHeader();
+
+
+ lHasStart=false;
+ lHasEnd=false;
+ lHasStream=false;
+ lHasResync=false;
+ lHasSystemStream=false;
+ lHasRawStream=false;
+ lSysLayer=false;
+
+ mpegSystemStream=new MpegSystemStream(input);
+ mpegSystemHeader=new MpegSystemHeader();
+
+
+ lCanSeek=input->seek(0);
+ if (lCanSeek == false) {
+ cout << "mpegVideoLength: stream does not support seek"<<endl;
+ }
+ realLength=input->getByteLength();
+ upperEnd=realLength;
+ if (realLength > 1024*1024*600) {
+ upperEnd=1024*1024*600;
+ }
+}
+
+
+MpegVideoLength::~MpegVideoLength() {
+ delete startGOP;
+ delete endGOP;
+ delete lengthGOP;
+ delete mpegVideoStream;
+ delete mpegVideoHeader;
+ delete mpegSystemHeader;
+ delete mpegSystemStream;
+}
+
+
+/**
+ This long and ugly functions initialize a reader from
+ where to get the time informations.
+ All these switches deal with the problem, that we really should
+ have never a while loop, because this makes the decoder
+ thread unresponsive and can lead to deadlocks.
+*/
+
+int MpegVideoLength::firstInitialize() {
+
+ // no seek means no length detection
+ if (lCanSeek==false) {
+ // no detection possible, initialized ready
+ input->seek(0);
+ return true;
+ }
+ // do we have already a reader from where to get time?
+ if (lHasStream == false) {
+ // still init system ?
+ if (lHasSystemStream == false) {
+ if (mpegSystemStream->firstInitialize(mpegSystemHeader) == true) {
+ lHasSystemStream=true;
+
+ // if non system, reset everything and work on raw stream
+ if (mpegSystemHeader->getLayer() == _PACKET_SYSLAYER) {
+ lSysLayer=true;
+ }
+ if (lSysLayer == false) {
+ input->seek(0);
+ }
+ }
+ return false;
+ }
+ // if working on syslayer level we dont need the raw stream
+ // set it to true
+ if (lSysLayer == true) {
+ lHasRawStream=true;
+ }
+ if (lHasRawStream == false) {
+ if (mpegVideoStream->firstInitialize(mpegVideoHeader) == true) {
+ lHasRawStream=true;
+ }
+ return false;
+ }
+ lHasStream=true;
+ return false;
+ }
+ if (lHasStart == false) {
+ if (seekToStart() == true) {
+ lHasStart=true;
+ }
+
+ // clear and jump near the end
+ mpegVideoStream->clear();
+ int success=input->seek(upperEnd-SEARCH_SIZE);
+ if (success == false) {
+ cout << "mpegVideoStreamStream does not support seek"<<endl;
+ // we can't find an upper end, thus we are ready
+ input->seek(0);
+ return true;
+ }
+ return false;
+ }
+ if (lHasResync==false) {
+ if (lSysLayer) {
+ if (mpegSystemStream->nextPacket(mpegSystemHeader) == false) {
+ return false;
+ }
+ } else {
+ if (mpegVideoStream->nextGOP()==false) {
+ return false;
+ }
+ }
+ lHasResync=true;
+ return false;
+ }
+ if (lHasEnd == false) {
+ if (seekToEnd() == true) {
+ lHasEnd=true;
+ if (endGOP->substract(startGOP,lengthGOP) == false) {
+ cout << "substract error in final length detection"<<endl;
+ if (startGOP->substract(endGOP,lengthGOP) == true) {
+ cout << "this stream counts the time backwards"<<endl;
+ } else {
+ cout << "couldnt determine stream length"<<endl;
+ GOP dummy;
+ dummy.copyTo(lengthGOP);
+ }
+ }
+ // ok now we have the length but we must calculate
+ // the length of the whole stream
+ // we do not jump ofer 600 MB because this makes problems
+ // on some cdrom.
+ // here we calculate the real length if upperEnd != realEnd
+ int hour=lengthGOP->getHour();
+ int minute=lengthGOP->getMinutes();
+ long seconds=lengthGOP->getSeconds();
+ seconds=seconds+minute*60+hour*60*60;
+ if (upperEnd > 1) {
+ if (realLength > upperEnd) {
+ float ratio=realLength/upperEnd;
+ float realSeconds=seconds*ratio;
+ hour=(int)(realSeconds/(float)(60*60));
+ realSeconds=realSeconds-hour*60*60;
+ minute=(int)(realSeconds/60.0);
+ realSeconds=realSeconds-minute*60;
+ seconds=(int)realSeconds;
+ lengthGOP->setHour(hour);
+ lengthGOP->setMinute(minute);
+ lengthGOP->setSecond(seconds);
+ }
+ }
+ }
+ }
+ input->seek(0);
+ return true;
+}
+
+
+long MpegVideoLength::getLength() {
+ long back=0;
+ back=lengthGOP->getHour()*60*60;
+ back+=lengthGOP->getMinutes()*60;
+ back+=lengthGOP->getSeconds();
+
+ // length in second
+ return back;
+}
+
+
+long MpegVideoLength::getSeekPos(int seconds) {
+ // calculate from seconds to predicted position in stream
+ long back=0;
+ double ratio;
+
+ ratio=(double)realLength*(double)seconds;
+ ratio=ratio/((double)getLength()+1.0);
+ back=(long)ratio;
+
+ return back;
+
+}
+
+
+// We try to search the first SEARCH_SIZE KB for a valid picture start.
+int MpegVideoLength::seekToStart() {
+ int success;
+
+ /**
+ If we are a system Layer we calculate the startGOP
+ by the system Packets
+ */
+ if (lSysLayer == true) {
+ success=parseToPTS(startGOP);
+ } else {
+
+ mpegVideoStream->hasBytes(100);
+
+ success=parseToGOP(startGOP);
+ }
+
+ if (success == false) {
+ cout << "picture startcode not found [START]"<<endl;
+
+ }
+ // we return always true
+ // if we really have the start, fine, otherwithe we can
+ // nothing do about it, nor yet, nor in future, thus
+ // we have even success (in terms of failure)
+ return true;
+}
+
+
+
+int MpegVideoLength::seekToEnd() {
+ int success;
+
+ if (lSysLayer == true) {
+ success=parseToPTS(endGOP);
+ } else {
+ mpegVideoStream->hasBytes(100);
+ success=parseToGOP(endGOP);
+ }
+ if (success == false) {
+ cout << "picture endcode not found [END]"<<endl;
+ }
+
+ return true;
+}
+
+
+int MpegVideoLength::parseToGOP(GOP* dest) {
+ int success;
+ // we try ten attempts
+ // and the diff between each must be (less) than one second
+
+ int successCnt=0;
+
+
+ long maxArea=0;
+ long area=0;
+
+ GOP lastGOP;
+ GOP currentGOP;
+ GOP diffGOP;
+
+
+ while(successCnt < 4) {
+ if (mpegVideoStream->eof()) {
+ return false;
+ }
+ if (input->eof() == true) {
+ cout << "abort"<<endl;
+ return false;
+ }
+ if (maxArea > SEARCH_SIZE) {
+ return false;
+ }
+
+
+ success=seekValue(GOP_START_CODE,area);
+ maxArea+=area;
+ if (success == false) {
+ continue;
+ }
+
+
+
+ currentGOP.copyTo(&lastGOP);
+ // currentGOP.print("current");
+ successCnt++;
+ currentGOP.processGOP(mpegVideoStream);
+ if (currentGOP.substract(&lastGOP,&diffGOP) == false) {
+ cout << "substract error"<<endl;
+ }
+ /*
+ currentGOP.print("current");
+ lastGOP.print("last");
+ diffGOP.print("diff");
+ */
+ if (diffGOP.getHour() != 0) {
+ successCnt=0;
+ continue;
+ }
+ if (diffGOP.getMinutes() != 0) {
+ successCnt=0;
+ continue;
+ }
+ if (diffGOP.getSeconds() > 8) {
+ successCnt=0;
+ continue;
+ }
+
+ }
+ currentGOP.copyTo(dest);
+ return true;
+}
+
+
+
+
+
+
+int MpegVideoLength::seekValue(unsigned int ,long& valueSeeked) {
+ long start=input->getBytePosition();
+ long cnt=0;
+ long end=start+SEEKWINDOW;
+ long area=0;
+
+ // if we have not enough space we skip
+ // because of the mpeg frame garbage "mb_stuffing,etc..."
+
+ if (end > upperEnd-SEEKWINDOW){
+ valueSeeked=SEEKWINDOW;
+ return false;
+ }
+ area=end-start;
+ while(mpegVideoStream->nextGOP() == false) {
+ if (mpegVideoStream->eof()) {
+ return false;
+ }
+ cnt++;
+ if (cnt >= area) {
+ valueSeeked=cnt;
+ cout << "nothing found"<<area<<endl;
+ return false;
+ }
+ }
+ return true;
+}
+
+
+
+int MpegVideoLength::parseToPTS(GOP* dest) {
+
+ // we try ten attempts
+ // and the diff between each must be (less) than one second
+
+ int successCnt=0;
+
+ long startArea=input->getBytePosition();
+ long maxArea=0;
+
+
+ double lastPTS=0;
+ double currentPTS=0;
+ double diffPTS=0;
+
+
+ while(successCnt < 4) {
+ if (input->eof() == true) {
+ cout << "abort"<<endl;
+ return false;
+ }
+ maxArea=input->getBytePosition()-startArea;
+ if (maxArea > SEARCH_SIZE) {
+ return false;
+ }
+ if (mpegSystemStream->nextPacket(mpegSystemHeader) == false) {
+ continue;
+ }
+ if (mpegSystemHeader->getPTSFlag()==false) {
+ continue;
+ }
+ // we have a packet
+ lastPTS=currentPTS;
+ currentPTS=mpegSystemHeader->getPTSTimeStamp();
+ diffPTS=currentPTS-lastPTS;
+ successCnt++;
+
+ if (diffPTS > 1.0) {
+ successCnt=0;
+ continue;
+ }
+ }
+
+ // now put it into the gop structure
+ // this is the interface for the time.
+ // a little hack here and there....
+ unsigned int hour=((long)currentPTS) / 3600;
+ currentPTS=currentPTS-hour*3600;
+ unsigned int minute=((long)currentPTS) / 60;
+ currentPTS=currentPTS-minute*60;
+ unsigned int seconds=((long)currentPTS);
+
+
+ dest->setHour(hour);
+ dest->setMinute(minute);
+ dest->setSecond(seconds);
+ return true;
+}
+
+
diff --git a/mpeglib/lib/mpegplay/mpegVideoLength.h b/mpeglib/lib/mpegplay/mpegVideoLength.h
new file mode 100644
index 00000000..79bece6a
--- /dev/null
+++ b/mpeglib/lib/mpegplay/mpegVideoLength.h
@@ -0,0 +1,93 @@
+/*
+ mpg I video/audio player plugin
+ Copyright (C) 1999 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#ifndef __MPEGVIDEOLENGTH_H
+#define __MPEGVIDEOLENGTH_H
+
+#include "../input/inputPlugin.h"
+
+
+
+
+
+
+/**
+ This class calculates the length (in seconds) of an mpeg stream.
+ I do not know how to make it right, my approach
+ seeks at the beginning of the stream for the timecode in
+ the picture gop then jumps near the end and does the same.
+ then it substracts the values.
+ It has some limitations, it does not seek higher than 600 MB,
+ because it seems the kernel has some problems with this.
+ (It resets the scsi system, and sometimes hang/crash)
+ Thus it only seek near 600 and assumes linear relation
+ for the rest. (Means: it calculates the length of the rest
+ with the sec/mb value calculates from the 600 mb
+ should be exact enough.
+*/
+
+class MpegVideoStream;
+class MpegVideoHeader;
+class MpegSystemStream;
+class MpegSystemHeader;
+class GOP;
+
+class MpegVideoLength {
+
+ // these are used fo non system streams
+ MpegVideoHeader* mpegVideoHeader;
+ MpegVideoStream* mpegVideoStream;
+
+ // these for system streams
+ MpegSystemHeader* mpegSystemHeader;
+ MpegSystemStream* mpegSystemStream;
+
+
+ InputStream* input;
+ GOP* startGOP;
+ GOP* endGOP;
+ GOP* lengthGOP;
+
+
+ int lHasStart;
+ int lHasEnd;
+ int lCanSeek;
+ int lHasStream;
+ int lHasSystemStream;
+ int lHasRawStream;
+ int lHasResync;
+ int lSysLayer;
+ long upperEnd;
+ long realLength;
+
+ public:
+ MpegVideoLength(InputStream* input);
+ ~MpegVideoLength();
+
+ int firstInitialize();
+
+ long getLength();
+ long getSeekPos(int seconds);
+
+
+ private:
+ int seekToStart();
+ int seekToEnd();
+ int seekValue(unsigned int code,long& endPos);
+ int parseToGOP(GOP* gop);
+ int parseToPTS(GOP* gop);
+
+
+};
+#endif
+
diff --git a/mpeglib/lib/mpegplay/mpegVideoStream.cpp b/mpeglib/lib/mpegplay/mpegVideoStream.cpp
new file mode 100644
index 00000000..5e16b116
--- /dev/null
+++ b/mpeglib/lib/mpegplay/mpegVideoStream.cpp
@@ -0,0 +1,224 @@
+/*
+ a mpegVideoStream buffer
+ Copyright (C) 1999 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "mpegVideoStream.h"
+
+#include <iostream>
+
+using namespace std;
+
+MpegVideoStream::MpegVideoStream(InputStream* input) {
+
+
+ this->input=input;
+ lHasStream=false;
+
+ mpegSystemStream=new MpegSystemStream(input);
+ mpegSystemHeader=new MpegSystemHeader();
+ mpegVideoBitWindow= new MpegVideoBitWindow();
+
+
+}
+
+
+MpegVideoStream::~MpegVideoStream() {
+ delete mpegSystemStream;
+ delete mpegSystemHeader;
+ delete mpegVideoBitWindow;
+}
+
+
+
+
+int MpegVideoStream::firstInitialize(MpegVideoHeader* mpegHeader) {
+ if (lHasStream == false) {
+ if (mpegSystemStream->firstInitialize(mpegSystemHeader)==false) {
+ return false;
+ }
+ fill_videoBuffer(mpegSystemHeader);
+ lHasStream=true;
+ }
+ // now find SEQ_START_CODE
+ hasBytes(4);
+ mpegVideoBitWindow->flushByteOffset();
+
+ if (mpegSystemHeader->getLayer() == _PACKET_SYSLAYER) {
+ unsigned int startCode=showBits(32);
+ if (startCode != _SEQ_START_CODE) {
+ flushBits(8);
+ return false;
+ }
+ flushBits(32);
+ }
+ if (mpegHeader->parseSeq(this)==false) {
+ return false;
+ }
+ return true;
+}
+
+
+int MpegVideoStream::isStartCode(unsigned int data) {
+
+ switch(data) {
+ case SEQ_END_CODE:
+ case SEQ_START_CODE:
+ case GOP_START_CODE:
+ case PICTURE_START_CODE:
+ case SLICE_MIN_START_CODE:
+ case SLICE_MAX_START_CODE:
+ case EXT_START_CODE:
+ case USER_START_CODE:
+ case SEQUENCE_ERROR_CODE:
+ case SYSTEM_HEADER_START_CODE:
+ case ISO_11172_END_CODE:
+ case EOF:
+ return true;
+ }
+ if ((SLICE_MIN_START_CODE < data) && (data < SLICE_MAX_START_CODE)) {
+ return true;
+ }
+ return false;
+}
+
+int MpegVideoStream::next_start_code() {
+ flushByteOffset();
+
+ unsigned int data;
+ data=showBits(32);
+
+
+ while(eof()==false) {
+ data=showBits(32);
+ if (isStartCode(data)) {
+ return true;
+ }
+ flushBits(8);
+ }
+ return true;
+}
+
+
+int MpegVideoStream::nextGOP() {
+
+ mpegVideoBitWindow->flushByteOffset();
+ unsigned int data=showBits(32);
+ if (data != GOP_START_CODE) {
+ flushBits(8);
+ return false;
+ }
+ return true;
+}
+
+
+int MpegVideoStream::nextPIC() {
+ mpegVideoBitWindow->flushByteOffset();
+ unsigned int data=showBits(32);
+ if ( (data != PICTURE_START_CODE) &&
+ (data != GOP_START_CODE) &&
+ (data != SEQ_START_CODE) ) {
+ flushBits(8);
+ return false;
+ }
+ return true;
+}
+
+
+
+
+
+int MpegVideoStream::hasBytes(int byteCnt) {
+ if (mpegVideoBitWindow->getLength() < byteCnt) {
+ get_more_video_data();
+ if (mpegVideoBitWindow->getLength() < byteCnt) {
+ return hasBytes(byteCnt);
+ }
+ }
+ return true;
+}
+
+
+
+
+int MpegVideoStream::eof() {
+ if (input->eof()) {
+ return true;
+ }
+ return false;
+}
+
+
+int MpegVideoStream::getByteDirect() {
+ unsigned char byte;
+ if (input->read((char*)&byte,1) != 1) {
+ return -1;
+ }
+ return (int)byte;
+}
+
+
+int MpegVideoStream::get_more_video_data() {
+
+
+ while(1) {
+ if (mpegSystemStream->nextPacket(mpegSystemHeader)==false) {
+ continue;
+ }
+ if (mpegSystemStream->eof() == true) {
+ printf ("\n");
+ mpegVideoBitWindow->fillWithIsoEndCode(1024);
+ cout <<"Unexpected read error."<<endl;
+ return false;
+ }
+ if (mpegSystemHeader->getPacketID() == _PAKET_ID_VIDEO) {
+ break;
+ }
+
+ }
+
+
+ fill_videoBuffer(mpegSystemHeader);
+ return true;
+}
+
+
+void MpegVideoStream::fill_videoBuffer(MpegSystemHeader* mpegSystemHeader) {
+ int bytes;
+
+ bytes=mpegSystemHeader->getPacketLen();
+ unsigned char* packetBuffer= new unsigned char[bytes];
+ int didRead;
+ didRead=input->read((char*)packetBuffer,bytes);
+ if (bytes==0) {
+ mpegVideoBitWindow->fillWithIsoEndCode(1024);
+ return ;
+ }
+
+ mpegVideoBitWindow->appendToBuffer(packetBuffer,didRead);
+ if (input->eof()) {
+ mpegVideoBitWindow->fillWithIsoEndCode(bytes-didRead);
+ }
+
+ delete packetBuffer;
+}
+
+
+TimeStamp* MpegVideoStream::getCurrentTimeStamp() {
+ long pos=input->getBytePosition();
+ int transfered=4*mpegVideoBitWindow->getLength();
+ pos=pos-transfered;
+
+ TimeStamp* timeStamp=input->getTimeStamp(pos);
+
+ return timeStamp;
+}
+
diff --git a/mpeglib/lib/mpegplay/mpegVideoStream.h b/mpeglib/lib/mpegplay/mpegVideoStream.h
new file mode 100644
index 00000000..86b80553
--- /dev/null
+++ b/mpeglib/lib/mpegplay/mpegVideoStream.h
@@ -0,0 +1,110 @@
+/*
+ a buffer
+ Copyright (C) 1999 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+
+
+
+#ifndef __MPEGVIDEOSTREAM_H
+#define __MPEGVIDEOSTREAM_H
+
+#include "startCodes.h"
+#include "mpegVideoHeader.h"
+#include "mpegSystemStream.h"
+#include "mpegVideoBitWindow.h"
+
+#define _BYTE_TEST 1024
+
+/**
+ A really ugly class. Most of the methods have names
+ which does not make it clear for what they are useful.
+ (Don't touch a running system :-)
+
+ We wrap the inputStream and offer functions for getting
+ bits, appending to the internal buffer, flushing, syncing
+ all this stuff.
+
+
+*/
+
+class MpegVideoStream {
+
+ int size;
+ InputStream* input;
+ MpegSystemStream* mpegSystemStream;
+ MpegSystemHeader* mpegSystemHeader;
+ MpegVideoBitWindow* mpegVideoBitWindow;
+
+ int lHasStream;
+
+ public:
+ MpegVideoStream(InputStream* input);
+ ~MpegVideoStream();
+
+ // returns true if init successful
+ int firstInitialize(MpegVideoHeader* mpegHeader);
+ int nextGOP();
+ int nextPIC();
+ int next_start_code();
+
+ int hasBytes(int bytes);
+ int eof();
+
+ inline void clear() {
+ mpegVideoBitWindow->clear();
+ }
+
+ inline void flushBits(int bits) {
+ hasBytes(_BYTE_TEST);
+ mpegVideoBitWindow->flushBitsDirect(bits);
+ }
+
+ inline unsigned int showBits(int bits) {
+ hasBytes(_BYTE_TEST);
+ return mpegVideoBitWindow->showBits(bits);
+ }
+
+ inline unsigned int showBits32() {
+ return mpegVideoBitWindow->showBits32();
+ }
+
+ inline unsigned int showBits16() {
+ return mpegVideoBitWindow->showBits(16);
+ }
+
+ inline void flushBitsDirect(unsigned int bits) {
+ mpegVideoBitWindow->flushBitsDirect(bits);
+ }
+
+ unsigned int getBits(int bits) {
+ hasBytes(_BYTE_TEST);
+ return mpegVideoBitWindow->getBits(bits);
+ }
+
+ inline void flushByteOffset() {
+ mpegVideoBitWindow->flushByteOffset();
+ }
+
+ TimeStamp* getCurrentTimeStamp();
+
+ private:
+ int getByteDirect();
+ int get_more_video_data();
+ void fill_videoBuffer(MpegSystemHeader* mpegSystemHeader);
+ int isStartCode(unsigned int data);
+
+
+};
+#endif
+
+
+
diff --git a/mpeglib/lib/mpegplay/pesSystemStream.cpp b/mpeglib/lib/mpegplay/pesSystemStream.cpp
new file mode 100644
index 00000000..10787f21
--- /dev/null
+++ b/mpeglib/lib/mpegplay/pesSystemStream.cpp
@@ -0,0 +1,498 @@
+/*
+ demux pes mpeg stream
+ Copyright (C) 2001 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+
+#include "pesSystemStream.h"
+
+#include <iostream>
+
+using namespace std;
+
+PESSystemStream::PESSystemStream(InputStream* input) {
+ this->input=input;
+}
+
+
+PESSystemStream::~PESSystemStream() {
+}
+
+
+
+int PESSystemStream::getByteDirect() {
+ unsigned char byte;
+ if (input->read((char*)&byte,1) != 1) {
+ return -1;
+ }
+ bytes_read++;
+ return (int)byte;
+}
+
+int PESSystemStream::read(char* pointer,int bytes) {
+ if (input->read(pointer,bytes) != bytes) {
+ return false;
+ }
+ bytes_read+=bytes;
+
+ return true;
+}
+
+int PESSystemStream::processStartCode(unsigned int startCode,
+ MpegSystemHeader* mpegHeader) {
+ int lok=true;
+ bytes_read=4; // startcode
+ mpegHeader->setPacketLen(0);
+ mpegHeader->setPacketID(_PAKET_ID_NUKE);
+
+ // handle default
+ bytes_read=processPacket(startCode,mpegHeader);
+ return bytes_read;
+}
+
+
+/* Returns:
+ 0 - no error, but not video packet we want
+ -1 - error
+ >0 - length of packet
+*/
+int PESSystemStream::processPacket(unsigned int startCode,
+ MpegSystemHeader* mpegHeader) {
+
+ int ioBytes;
+ unsigned short packetLength;
+ int packetDataLength;
+
+ /* Leftovers from previous video packets */
+
+ int packetID=startCode & 0xff;
+ mpegHeader->setPacketID(packetID);
+ int lPacket=startCode & _PACKET_START_CODE_MASK &_PACKET_START_CODE_PREFIX;
+ if ((lPacket == false) || (packetID < 0xbc)) {
+ //printf("unknown startcode,packet or packetID:%8x\n",startCode);
+ return false;
+ }
+
+ if (packetID == _NOT_PACKET_ID) {
+ cout << "(vid_stream->mpegVideoStream)->makeEnd()"<<endl;
+ } else if (packetID==_KILL_BUFFER) {
+ printf("packetID==_KILL_BUFFER\n");
+ }
+
+ if (read((char*)&packetLength, 2) == false) return false;
+ packetLength = htons(packetLength);
+
+ mpegHeader->setPTSFlag(false);
+ mpegHeader->setPacketID(packetID);
+ mpegHeader->setPESPacketLen(packetLength);
+ switch (packetID>>4) {
+ case _PAKET_ID_AUDIO_1>>4:
+ case _PAKET_ID_AUDIO_2>>4:
+ case _PAKET_ID_VIDEO>>4:
+ break;
+ default:
+ switch(packetID) {
+ case _PRIVATE_STREAM_1_ID:
+ break;
+ default:
+ switch (packetID) {
+ case _PRIVATE_STREAM_2_ID:
+ case _PADDING_STREAM_ID:
+ case _RESERVED_STREAM_ID:
+ case _ECM_STREAM_ID:
+ case _EMM_STREAM_ID:
+ case _PROGRAM_STREAM_DIRECTORY_ID:
+ case _DSMCC_STREAM_ID:
+ case _ITUTRECH222TYPEE_STREAM_ID:
+ return bytes_read;
+ }
+ printf("\nUnknown packet type. (%x) at %ld\n",
+ packetID,input->getBytePosition());
+ return bytes_read;
+ }
+ }
+ // this is only processed if audio or video found
+
+ if (mpegHeader->getMPEG2()==false) {
+ packetDataLength = packetLength-processPacketHeader(mpegHeader);
+ } else {
+ int len=processMPEG2PacketHeader(mpegHeader);
+
+ if (len < 0) {
+ return false;
+ }
+ packetDataLength = packetLength-len;
+
+ // now check in private stream for AC3
+ if ( packetID == _PRIVATE_STREAM_1_ID ) {
+ packetDataLength = packetDataLength-processPrivateHeader(mpegHeader);
+ }
+ }
+
+ if (packetDataLength <= 0) {
+ if (mpegHeader->hasPSHeader()) return false;
+ // -> buggy TS stream
+ packetDataLength=0;
+ }
+ mpegHeader->setPESPacketLen(packetDataLength);
+
+ return bytes_read;
+
+}
+
+
+int PESSystemStream::processPrivateHeader(MpegSystemHeader* mpegHeader) {
+ char nukeBuffer[30];
+ int pos=0;
+ int one=getByteDirect();
+ pos++;
+ mpegHeader->setSubStreamID(one);
+ switch(one>>4) {
+ case _SUBSTREAM_AC3_ID>>4:
+ if (read(nukeBuffer,3) == false) return false;
+ mpegHeader->addAvailableLayer(one);
+ cout << "addAvailableLayer:"<<one<<endl;
+ pos+=3;
+ break;
+ case _SUBSTREAM_LPCM_ID>>4:
+ if (read(nukeBuffer,6) == false) return false;
+ pos+=6;
+ break;
+ case _SUBSTREAM_SUBPIC_ID>>4:
+ if (read(nukeBuffer,3) == false) return false;
+ pos+=3;
+ break;
+ default:
+ printf("unknown sub id :%8x\n",one);
+ }
+ return pos;
+
+}
+
+
+int PESSystemStream::processMPEG2PacketHeader(MpegSystemHeader* mpegHeader){
+
+ int stdCnt=0;
+ int pos=0;
+
+ // 1. Byte
+ /*
+ FROM FLASK:
+ int getbits(2);
+ encrypted = getbits(2); // PES_scrambling_control
+ getbits(4);
+ //LIVID
+ u_char original_or_copy : 1;
+ u_char copyright : 1;
+ u_char data_alignment_indicator : 1;
+ u_char pes_priority : 1;
+ u_char pes_scrambling_control : 2;
+ u_char start_code_prefix : 2; // 0x02
+
+ */
+ int first=getByteDirect();
+ stdCnt++;
+ mpegHeader->setOriginalOrCopy(first&(128)>>7);
+ mpegHeader->setCopyRight(first&(64)>>6);
+ mpegHeader->setDataAlignmentIndicator(first&(32)>>5);
+ mpegHeader->setPesPriority(first&(16)>>4);
+ mpegHeader->setEncrypted((first&(8+4))>>2);
+ mpegHeader->setStartCodePrefix(first&(1+2));
+
+
+ // 2. Byte
+ /*
+ PTS_DTS_flags = getbits(2);
+ ESCR_flag = get1bit();
+ ES_rate_flag = get1bit();
+ DSM_trick_mode_flag = get1bit();
+ additional_copy_info_flag = get1bit();
+ PES_CRC_flag = get1bit();
+ PES_extension_flag = get1bit();
+ */
+ int second=getByteDirect();
+ stdCnt++;
+
+ mpegHeader->setPTSDTSFlag((second&(128+64))>>6);
+ mpegHeader->setESCRFlag((second&(32))>>5);
+ mpegHeader->setES_RATE_Flag((second%(16))>>4);
+ mpegHeader->setDMSTRICKFLAG((second&(8))>>3);
+ mpegHeader->setADDITIONAL_COPY_FLAG((second&(4))>>2);
+ mpegHeader->setPES_CRC_FLAG((second&(2))>>1);
+ mpegHeader->setPES_EXT_FLAG(second&(1));
+
+
+ // 3. Byte
+ /*
+ PES_header_data_length = getbits(8);
+ */
+ int third=getByteDirect();
+ stdCnt++;
+ mpegHeader->setPES_HEADER_DATA_LENGTH(third);
+
+
+ //
+ // PARSING MPEG 2 HEADER FLAGS [START]
+ //
+ unsigned char nukeBuffer[300];
+
+ int PTS_DTS_flags=mpegHeader->getPTSDTSFlag();
+ if (PTS_DTS_flags == 0) {
+ mpegHeader->setPTSFlag(false);
+ } else {
+ mpegHeader->setPTSFlag(true);
+ }
+
+ if (PTS_DTS_flags > 0x1) {
+ if (read((char*)nukeBuffer,5) == false) return false;
+ double pts=GET_MPEG2_PTS(nukeBuffer);
+ pts=(pts*300.0)/(double)MPEG2_CLK_REF;
+ mpegHeader->setPTSTimeStamp(pts);
+ pos+=5;
+ }
+ if (PTS_DTS_flags > 0x2) {
+ if (read((char*)nukeBuffer,5) == false) return false;
+ double dts=GET_MPEG2_PTS(nukeBuffer);
+ mpegHeader->setDTSTimeStamp((dts*300.0)/(double)MPEG2_CLK_REF);
+ pos+=5;
+ }
+
+ int ESCRFlag=mpegHeader->getESCRFlag();
+ if (ESCRFlag == 1){
+ cout << "ESCRFlag == 1"<<endl;
+ if (read((char*)nukeBuffer,6) == false) return false;
+ pos+=6;
+ }
+
+ int ES_rate_flag=mpegHeader->getES_RATE_Flag();
+ if (ES_rate_flag == 1){
+ cout << "ES_rate_flag == 1"<<endl;
+ if (read((char*)nukeBuffer,3) == false) return false;
+ pos+=3;
+ }
+
+ int DSM_trick_mode_flag=mpegHeader->getDMSTRICKFLAG();
+ if (DSM_trick_mode_flag == 1){
+ cout << "DSM_trick_mode_flag == 1"<<endl;
+ if (read((char*)nukeBuffer,1) == false) return false;
+ pos++;
+ }
+
+ int additional_copy_info_flag=mpegHeader->getADDITIONAL_COPY_FLAG();
+ if (additional_copy_info_flag == 1) {
+ cout << "additional_copy_info_flag == 1"<<endl;
+ if (read((char*)nukeBuffer,1) == false) return false;
+ pos++;
+ }
+
+ int PES_CRC_flag=mpegHeader->getPES_CRC_FLAG();
+ if (PES_CRC_flag == 1) {
+ cout << "PES_CRC_flag == 1"<<endl;
+ if (read((char*)nukeBuffer,2) == false) return false;
+ pos+=2;
+ }
+
+ //
+ // PES Extension [START]
+ //
+
+ int PES_extension_flag=mpegHeader->getPES_EXT_FLAG();
+ if (PES_extension_flag == 1) {
+ /*
+ FLASK:
+ PES_private_data_flag = get1bit();
+ pack_header_field_flag = get1bit();
+ program_packet_sequence_counter_flag = get1bit();
+ PSTD_buffer_flag = get1bit();
+ getbits(3);
+ PES_extension_flag_2 = get1bit();
+ */
+ int extensionByte=getByteDirect();
+
+ pos++;
+ mpegHeader->setPrivateDataFlag((extensionByte&(128))>>7);
+ mpegHeader->setPackHeaderFieldFlag((extensionByte&(64))>>6);
+ mpegHeader->setSequenceCounterFlag((extensionByte&(32))>>5);
+ mpegHeader->setSTDBufferFlag((extensionByte&(16))>>4);
+ mpegHeader->setPES_EXT_FLAG_2(extensionByte&(1));
+
+ int PES_private_data_flag=mpegHeader->getPrivateDataFlag();
+ if (PES_private_data_flag == 1) {
+ if (read((char*)nukeBuffer,128) == false) return false;
+ pos+=128;
+ }
+
+ int pack_header_field_flag=mpegHeader->getPackHeaderFieldFlag();
+ if (pack_header_field_flag == 1) {
+ printf("pack header field flag value not allowed in program streams\n");
+ return false;
+ }
+
+ int sequence_counter_flag=mpegHeader->getSequenceCounterFlag();
+ if (sequence_counter_flag==1) {
+ cout<<"sequence_counter_flag ==1"<<endl;
+ if (read((char*)nukeBuffer,2) == false) return false;
+ pos+=2;
+ }
+
+ int PSTD_buffer_flag=mpegHeader->getSTDBufferFlag();
+ if (PSTD_buffer_flag==1) {
+ if (read((char*)nukeBuffer,2) == false) return false;
+ pos+=2;
+ }
+
+ int PES_extension_flag_2=mpegHeader->getPES_EXT_FLAG_2();
+ if (PES_extension_flag_2 == 1) {
+ int extension2_byte=getByteDirect();
+ pos++;
+ mpegHeader->setPES_EXT_FIELD_LENGTH(extension2_byte&(254));
+
+
+ int PES_field_length=mpegHeader->getPES_EXT_FIELD_LENGTH();
+ int j;
+ for (j=0;j<PES_field_length ; j++) {
+ cout << "PES_field_length (nuke)"<<endl;
+ getByteDirect();
+ pos++;
+ }
+ }
+ }
+ //
+ // PES Extension [END]
+ //
+
+ // now nuke remaining bytes from PES DATA Length
+ int PES_HEADER_DATA_LENGTH=mpegHeader->getPES_HEADER_DATA_LENGTH();
+ int tmp=PES_HEADER_DATA_LENGTH-pos;
+ if (tmp>0) {
+ if (read((char*)nukeBuffer,tmp) == false) return false;
+ pos+=tmp;
+ }
+
+
+
+
+
+ //
+ // PARSING MPEG 2 HEADER FLAGS [START]
+ //
+
+ int parsed=stdCnt+pos;
+ return parsed;
+
+}
+
+
+int PESSystemStream::processPacketHeader(MpegSystemHeader* mpegHeader) {
+ unsigned char nextByte;
+ int pos;
+ int val;
+ unsigned char scratch[10];
+
+
+ nextByte=getByteDirect();
+
+ mpegHeader->setPTSFlag(false);
+
+ pos = 1;
+ while (nextByte & 0x80) {
+ ++pos;
+ val=getByteDirect();
+ if (val == -1) return false;
+ scratch[0]=val;
+
+ nextByte=scratch[0];
+ }
+ if ((nextByte >> 6) == 0x01) {
+ pos += 2;
+ scratch[1]=getByteDirect();
+ scratch[2]=getByteDirect();
+ nextByte=scratch[2];
+ }
+ if ((nextByte >> 4) == 0x02) {
+ scratch[0] = nextByte;
+ if (read((char*)&scratch[1],4) == false) return false;
+ /* presentation time stamps */
+ unsigned char hiBit;
+ unsigned long low4Bytes;
+ double ptsTimeStamp;
+ double dtsTimeStamp=0.0;
+ readTimeStamp((unsigned char*)scratch,&hiBit,&low4Bytes);
+ makeClockTime(hiBit,low4Bytes,&ptsTimeStamp);
+ mpegHeader->setPTSFlag(true);
+ mpegHeader->setPTSTimeStamp(ptsTimeStamp);
+ mpegHeader->setDTSTimeStamp(dtsTimeStamp);
+
+ pos += 4;
+ }
+ else if ((nextByte >> 4) == 0x03) {
+ scratch[0] = nextByte;
+ if (read((char*)&scratch[1],9) == false) return false;
+ /* presentation and decoding time stamps */
+ unsigned char hiBit;
+ unsigned long low4Bytes;
+ double ptsTimeStamp;
+ double dtsTimeStamp;
+ readTimeStamp((unsigned char*)scratch,&hiBit,&low4Bytes);
+ makeClockTime(hiBit,low4Bytes,&ptsTimeStamp);
+
+ readTimeStamp((unsigned char*)&(scratch[5]),&hiBit,&low4Bytes);
+ makeClockTime(hiBit,low4Bytes,&dtsTimeStamp);
+ mpegHeader->setPTSFlag(true);
+ mpegHeader->setPTSTimeStamp(ptsTimeStamp);
+ mpegHeader->setDTSTimeStamp(dtsTimeStamp);
+
+ pos += 9;
+ }
+ return pos;
+}
+
+
+
+void PESSystemStream::readTimeStamp(unsigned char* inputBuffer,
+ unsigned char* hiBit,
+ unsigned long* low4Bytes) {
+ *hiBit = ((unsigned long)inputBuffer[0] >> 3) & 0x01;
+ *low4Bytes = (((unsigned long)inputBuffer[0] >> 1) & 0x03) << 30;
+ *low4Bytes |= (unsigned long)inputBuffer[1] << 22;
+ *low4Bytes |= ((unsigned long)inputBuffer[2] >> 1) << 15;
+ *low4Bytes |= (unsigned long)inputBuffer[3] << 7;
+ *low4Bytes |= ((unsigned long)inputBuffer[4]) >> 1;
+}
+
+
+void PESSystemStream::readSTD(unsigned char* inputBuffer,
+ MpegSystemHeader* mpegHeader) {
+ int stdBufferScale;
+ unsigned long stdBufferSize;
+ stdBufferScale = ((int)(inputBuffer[0] & 0x20) >> 5);
+ stdBufferSize = ((unsigned long)inputBuffer[0] & 0x1f) << 8;
+ stdBufferSize |= (unsigned long)inputBuffer[1];
+ mpegHeader->setStdBufferScale(stdBufferScale);
+ mpegHeader->setStdBufferSize(stdBufferSize);
+}
+
+
+int PESSystemStream::makeClockTime(unsigned char hiBit,
+ unsigned long low4Bytes,
+ double * clockTime) {
+ if (hiBit != 0 && hiBit != 1) {
+ *clockTime = 0.0;
+ return 1;
+ }
+ *clockTime = (double)hiBit*FLOAT_0x10000*FLOAT_0x10000 + (double)low4Bytes;
+ *clockTime /= (double)_STD_SYSTEM_CLOCK_FREQ;
+ return 0;
+}
+
+
+
+
diff --git a/mpeglib/lib/mpegplay/pesSystemStream.h b/mpeglib/lib/mpegplay/pesSystemStream.h
new file mode 100644
index 00000000..f7b650c5
--- /dev/null
+++ b/mpeglib/lib/mpegplay/pesSystemStream.h
@@ -0,0 +1,57 @@
+/*
+ demux pes mpeg stream
+ Copyright (C) 2001 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#ifndef __PESSYSTEMSTREAM_H
+#define __PESSYSTEMSTREAM_H
+
+
+#include <stdlib.h>
+#include "../input/inputPlugin.h"
+#include "mpegSystemHeader.h"
+
+
+class PESSystemStream {
+
+
+ InputStream* input;
+
+ int bytes_read;
+
+ public:
+ PESSystemStream(InputStream* input);
+ ~PESSystemStream();
+
+ // called when we found a valid ts startcode
+ // return number of bytes read from input and zero on error
+ int processStartCode(unsigned int startCode,MpegSystemHeader* mpegHeader);
+
+ private:
+ int getByteDirect();
+ int read(char* prt,int bytes);
+ int processPacket(unsigned int startCode,MpegSystemHeader* mpegHeader);
+ int processPacketHeader(MpegSystemHeader* mpegHeader);
+ int processMPEG2PacketHeader(MpegSystemHeader* mpegHeader);
+ int processPrivateHeader(MpegSystemHeader* mpegHeader);
+
+ int readStartCode(unsigned int startCode,MpegSystemHeader* mpegHeader);
+
+ void readSTD(unsigned char* inputBuffer,MpegSystemHeader* mpegHeader);
+ void readTimeStamp(unsigned char* inputBuffer,unsigned char* hiBit,
+ unsigned long* low4Bytes);
+
+ int makeClockTime(unsigned char hiBit, unsigned long low4Bytes,
+ double * clockTime);
+
+
+};
+#endif
diff --git a/mpeglib/lib/mpegplay/picture.cpp b/mpeglib/lib/mpegplay/picture.cpp
new file mode 100644
index 00000000..6d8c1efe
--- /dev/null
+++ b/mpeglib/lib/mpegplay/picture.cpp
@@ -0,0 +1,149 @@
+/*
+ mpeg video picture
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "picture.h"
+
+
+Picture::Picture() {
+
+ /* Initialize pointers to extension and user data. */
+ extraBit=0;
+ startOfPicStamp=new TimeStamp();
+ extension=new MpegExtension();
+}
+
+
+
+Picture::~Picture() {
+ delete startOfPicStamp;
+ delete extension;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ParsePicture --
+ *
+ * Parses picture header. Marks picture to be presented
+ * at particular time given a time stamp.
+ *
+ * Results:
+ * Values from picture header put into video stream structure.
+ *
+ * Side effects:
+ * Bit stream irreversibly parsed.
+ *
+ *--------------------------------------------------------------
+ */
+int Picture::processPicture(MpegVideoStream* mpegVideoStream) {
+ TimeStamp* stamp;
+
+ /* Flush header start code. */
+ mpegVideoStream->flushBits(32);
+
+ /* Parse off temporal reference. */
+ temp_ref=mpegVideoStream->getBits(10);
+
+ /* Parse of picture type. */
+ code_type=mpegVideoStream->getBits(3);
+
+
+ // get timestamp from stamp queue
+ stamp=mpegVideoStream->getCurrentTimeStamp();
+
+ stamp->copyTo(startOfPicStamp);
+ // now invalidate the PTSFlag
+ stamp->setPTSFlag(false);
+
+
+ /* Parse off vbv buffer delay value. */
+ vbv_delay=mpegVideoStream->getBits(16);
+
+
+ /* If P or B type frame... */
+
+ if ((code_type == P_TYPE) || (code_type == B_TYPE)) {
+
+ /* Parse off forward vector full pixel flag. sets it to true/false*/
+ full_pel_forw_vector=mpegVideoStream->getBits(1);
+
+
+ /* Parse of forw_r_code. */
+ /* Decode forw_r_code into forw_r_size and forw_f. */
+ forw_r_size=mpegVideoStream->getBits(3);
+ forw_r_size--;
+
+
+ forw_f = (1 << forw_r_size);
+ }
+ /* If B type frame... */
+
+ if (code_type == B_TYPE) {
+
+ /* Parse off back vector full pixel flag. */
+ full_pel_back_vector=mpegVideoStream->getBits(1);
+
+
+ /* Parse off back_r_code. */
+ /* Decode back_r_code into back_r_size and back_f. */
+ back_r_size=mpegVideoStream->getBits(3);
+ back_r_size--;
+
+
+ back_f = (1 << back_r_size);
+ }
+ /* Get extra bit picture info. */
+
+
+ /*
+ extraBit=mpegVideoStream->getBits(1);
+ if (extraBit) {
+ cout << "extraBit"<<endl;
+ exit(0);
+ extension->processExtBuffer(mpegVideoStream);
+ }
+ */
+ extension->processExtra_bit_info(mpegVideoStream);
+ extension->processExtensionData(mpegVideoStream);
+
+
+
+
+
+ return true;
+}
+
+int Picture::processPictureCodingExtension(MpegVideoStream* ) {
+ return true;
+}
+
+unsigned int Picture::geth_back_r(MpegVideoStream* mpegVideoStream) {
+ return mpegVideoStream->getBits(back_r_size);
+}
+
+
+unsigned int Picture::getv_back_r(MpegVideoStream* mpegVideoStream) {
+ return mpegVideoStream->getBits(back_r_size);
+}
+
+
+unsigned int Picture::geth_forw_r(MpegVideoStream* mpegVideoStream) {
+ return mpegVideoStream->getBits(forw_r_size);
+}
+
+
+unsigned int Picture::getv_forw_r(MpegVideoStream* mpegVideoStream) {
+ return mpegVideoStream->getBits(forw_r_size);
+}
+
diff --git a/mpeglib/lib/mpegplay/picture.h b/mpeglib/lib/mpegplay/picture.h
new file mode 100644
index 00000000..7be35ab7
--- /dev/null
+++ b/mpeglib/lib/mpegplay/picture.h
@@ -0,0 +1,82 @@
+/*
+ mpeg video picture
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+
+
+
+#ifndef __PICTURE_H
+#define __PICTURE_H
+
+
+#include "mpegExtension.h"
+
+
+class Picture {
+
+/* Picture structure. */
+
+ unsigned int temp_ref; /* Temporal reference. */
+ unsigned int code_type; /* Frame type: P, B, I */
+ unsigned int vbv_delay; /* Buffer delay. */
+ int full_pel_forw_vector; /* Forw. vectors specified in full
+ pixel values flag. */
+ unsigned int forw_r_size; /* Used for vector decoding. */
+ unsigned int forw_f; /* Used for vector decoding. */
+ int full_pel_back_vector; /* Back vectors specified in full
+ pixel values flag. */
+ unsigned int back_r_size; /* Used in decoding. */
+ unsigned int back_f; /* Used in decoding. */
+
+
+ // MPEG 2 [START]
+
+
+ MpegExtension* extension;
+ // sync info
+ class TimeStamp* startOfPicStamp;
+
+ // MPEG 2 things
+ int extraBit;
+
+ public:
+ Picture();
+ ~Picture();
+
+ int processPicture(class MpegVideoStream* mpegVideoStream);
+ int processPictureCodingExtension(class MpegVideoStream* mpegVideoStream);
+
+
+ inline unsigned int getCodeType() { return code_type; }
+ inline unsigned int getForw_f() { return forw_f;}
+ inline unsigned int getBack_f() { return back_f;}
+ inline void setForw_f(unsigned int f) { forw_f=f;}
+ inline void setBack_f(unsigned int f) { back_f=f;}
+
+ inline int getExtraBit() { return extraBit; }
+
+ inline TimeStamp* getStartOfPicStamp() { return startOfPicStamp;}
+ inline unsigned int getFull_pel_forw_vector() {return full_pel_forw_vector;}
+ inline unsigned int getFull_pel_back_vector() {return full_pel_back_vector;}
+
+ inline void setFull_pel_forw_vector(unsigned int v) {full_pel_forw_vector=v;}
+ inline void setFull_pel_back_vector(unsigned int v) {full_pel_back_vector=v;}
+
+ unsigned int geth_back_r(class MpegVideoStream* mpegVideoStream);
+ unsigned int getv_back_r(class MpegVideoStream* mpegVideoStream);
+
+ unsigned int geth_forw_r(class MpegVideoStream* mpegVideoStream);
+ unsigned int getv_forw_r(class MpegVideoStream* mpegVideoStream);
+
+
+};
+#endif
diff --git a/mpeglib/lib/mpegplay/proto.h b/mpeglib/lib/mpegplay/proto.h
new file mode 100644
index 00000000..b9c35c2d
--- /dev/null
+++ b/mpeglib/lib/mpegplay/proto.h
@@ -0,0 +1,36 @@
+
+
+#ifndef __PROTO_H
+#define __PROTO_H
+
+
+
+
+#include "videoDecoder.h"
+#include "mpegVideoHeader.h"
+
+
+
+/* decoders.c */
+void init_tables (void);
+extern "C" void Fast16Dither(unsigned char *lum,
+ unsigned char *cr,
+ unsigned char *cb,
+ unsigned char *out,
+ int rows,
+ int cols,
+ int mod);
+
+
+/* floatdct.c */
+void init_float_idct (void);
+void float_idct (short* block);
+extern "C" void IDCT_mmx(short *);
+
+
+
+
+
+
+#endif
+
diff --git a/mpeglib/lib/mpegplay/psSystemStream.cpp b/mpeglib/lib/mpegplay/psSystemStream.cpp
new file mode 100644
index 00000000..b63843bc
--- /dev/null
+++ b/mpeglib/lib/mpegplay/psSystemStream.cpp
@@ -0,0 +1,163 @@
+/*
+ demux "normal" mpeg stream (does this have a name?)
+ Copyright (C) 2001 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "psSystemStream.h"
+
+#include <iostream>
+
+using namespace std;
+
+PSSystemStream::PSSystemStream(InputStream* input) {
+ this->input=input;
+}
+
+
+PSSystemStream::~PSSystemStream() {
+}
+
+
+int PSSystemStream::read(char* ptr,int bytes) {
+ if (input->read(ptr,bytes) != bytes) {
+ return false;
+ }
+ paket_read+=bytes;
+
+ return true;
+}
+
+int PSSystemStream::getByteDirect() {
+ unsigned char byte;
+ if (input->read((char*)&byte,1) != 1) {
+ return -1;
+ }
+ paket_read++;
+ return (int)byte;
+}
+
+
+// nuke bytes modulo 10
+int PSSystemStream::nukeBytes(int bytes) {
+ // nukebuffer
+ char nuke[10];
+
+ while(bytes > 0) {
+ int doNuke=10;
+ if (bytes < 10) doNuke=bytes;
+ if (input->read((char*)&nuke,doNuke) != doNuke) {
+ return false;
+ }
+ bytes-=doNuke;
+ paket_read+=doNuke;
+ }
+ return true;
+}
+
+
+int PSSystemStream::processStartCode(MpegSystemHeader* mpegHeader) {
+ unsigned int header=mpegHeader->getHeader();
+ mpegHeader->setPacketLen(0);
+ mpegHeader->setPacketID(_PAKET_ID_NUKE);
+
+ switch(header) {
+ case _PACK_START_CODE:
+ return processPackHeader(mpegHeader);
+ case _SYSTEM_HEADER_START_CODE:
+ return processSystemHeader(mpegHeader);
+ default:
+ cout << "PSSystemStream::processStartCode unknown PS header"<<endl;
+ exit(-1);
+ }
+ // never
+ return false;
+}
+
+
+int PSSystemStream::processPackHeader(MpegSystemHeader* mpegHeader) {
+ int back=false;
+ int numRead;
+ unsigned long scrbase;
+ unsigned long scrext;
+ unsigned long rate;
+
+ double timeStamp;
+
+ unsigned char inputBuffer[_PACKET_HEADER_SIZE+2];
+ if (read((char*)inputBuffer, _PACKET_HEADER_SIZE) == false) return false;
+
+
+ // only set this if we do an initialize
+ int layer=mpegHeader->getLayer();
+ if (layer == _PACKET_UNKNOWN_LAYER) {
+ if ((inputBuffer[0]>>6)==1) {
+ mpegHeader->setMPEG2(true);
+ }
+ }
+
+ if (mpegHeader->getMPEG2()) {
+ if (read((char*)inputBuffer+_PACKET_HEADER_SIZE, 2) == false) return false;
+
+ scrbase=GET_SCRBASE(inputBuffer);
+ scrext=GET_SCREXT(inputBuffer);
+
+ // BUGGY:
+ timeStamp = (double)(scrbase*300 + scrext) / (double)MPEG2_CLK_REF;
+
+ rate=GET_MPEG2MUXRATE(inputBuffer);
+
+ int stuffing = GET_MPEG2STUFFING(inputBuffer); // always <= 7
+
+ numRead=stuffing;
+ if (stuffing) {
+ if (read((char*)inputBuffer, stuffing) == false) return false;
+ }
+ } else {
+
+ // MPEG 1
+ scrbase=GET_SCR(inputBuffer);
+ timeStamp=(double)scrbase/MPEG1_CLK_REF;
+ rate=GET_MPEG1_MUXRATE(inputBuffer);
+ rate*=_MUX_RATE_SCALE_FACTOR;
+ }
+ mpegHeader->setSCRTimeStamp(timeStamp);
+ mpegHeader->setRate(rate);
+
+
+ return true;
+}
+
+
+int PSSystemStream::processSystemHeader(MpegSystemHeader* mpegHeader) {
+ unsigned char *inputBuffer = NULL;
+ int numRead;
+ unsigned short headerSize;
+
+
+ if (read((char *)&headerSize, 2) == false) return false;
+ headerSize = ntohs(headerSize);
+
+ inputBuffer = (unsigned char*) malloc (sizeof(unsigned char)*(headerSize+1));
+ inputBuffer[headerSize]=0;
+ if (read((char*)inputBuffer, headerSize) == false) return false;
+
+ mpegHeader->resetAvailableLayers();
+ int i = 6;
+ while (i<headerSize) {
+ if (inputBuffer[i] & 0x80) {
+ mpegHeader->addAvailableLayer(inputBuffer[i]);
+ }
+ i += 3;
+ }
+ free(inputBuffer);
+ return true;
+}
+
diff --git a/mpeglib/lib/mpegplay/psSystemStream.h b/mpeglib/lib/mpegplay/psSystemStream.h
new file mode 100644
index 00000000..bb3b23fd
--- /dev/null
+++ b/mpeglib/lib/mpegplay/psSystemStream.h
@@ -0,0 +1,57 @@
+/*
+ demux "normal" mpeg stream (does this have a name?)
+ Copyright (C) 2001 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#ifndef __PSSYSTEMSTREAM_H
+#define __PSSYSTEMSTREAM_H
+
+
+#include <stdlib.h>
+#include "../input/inputPlugin.h"
+#include "mpegSystemHeader.h"
+
+/**
+ This class is used inside mpegSystemStream.h when we found
+ during initialisation an "normal" mpeg stream.
+ This means: 1ba,1bb startcodes.
+
+
+*/
+
+class PSSystemStream {
+
+ InputStream* input;
+
+ int paket_len;
+ int paket_read;
+
+ public:
+ PSSystemStream(InputStream* input);
+ ~PSSystemStream();
+
+ // called when we found a valid ts startcode
+ int processStartCode(MpegSystemHeader* mpegHeader);
+
+ private:
+
+ // read stream methods
+ int read(char* ptr,int bytes);
+ int getByteDirect();
+ int nukeBytes(int bytes);
+ int skipNextByteInLength();
+
+ int processPackHeader(MpegSystemHeader* mpegHeader);
+ int processSystemHeader(MpegSystemHeader* mpegHeader);
+
+
+};
+#endif
diff --git a/mpeglib/lib/mpegplay/recon.cpp b/mpeglib/lib/mpegplay/recon.cpp
new file mode 100644
index 00000000..6116157a
--- /dev/null
+++ b/mpeglib/lib/mpegplay/recon.cpp
@@ -0,0 +1,735 @@
+/*
+ class for reconstruction
+ Copyright (C) 1999 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "recon.h"
+
+
+#define DEBUG_RECON(x)
+//#define DEBUG_RECON(x) x
+
+
+
+Recon::Recon() {
+ copyFunctions=new CopyFunctions();
+}
+
+
+Recon::~Recon() {
+ delete copyFunctions;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ReconIMBlock --
+ *
+ * Reconstructs intra coded macroblock.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int Recon::ReconIMBlock(int bnum,int mb_row,int mb_col,int row_size,
+ short int* dct_start,PictureArray* pictureArray) {
+ int row, col;
+ unsigned char *dest;
+ unsigned char *picDest;
+ int lumLength=(pictureArray->getCurrent())->getLumLength();
+ int colorLength=(pictureArray->getCurrent())->getColorLength();
+ int endDest=0;
+
+
+
+ /* If block is luminance block... */
+
+ if (bnum < 4) {
+
+ /* Calculate row and col values for upper left pixel of block. */
+
+ row = mb_row << 4;
+ col = mb_col << 4;
+ if (bnum > 1)
+ row += 8;
+ if (bnum % 2)
+ col += 8;
+
+ /* Set dest to luminance plane of current pict image. */
+
+ picDest = (pictureArray->getCurrent())->getLuminancePtr();
+ endDest=lumLength;
+
+ }
+ /* Otherwise if block is Cr block... */
+ /* Cr first because of the earlier mixup */
+
+ else if (bnum == 5) {
+
+ /* Set dest to Cr plane of current pict image. */
+
+ picDest = (pictureArray->getCurrent())->getCrPtr();
+ endDest=colorLength;
+
+ /* Establish row size. yuv color is half of whole size*/
+ row_size >>=1;
+
+ /* Calculate row,col for upper left pixel of block. */
+
+ row = mb_row << 3;
+ col = mb_col << 3;
+ }
+ /* Otherwise block is Cb block, and ... */
+
+ else {
+
+ /* Set dest to Cb plane of current pict image. */
+
+ picDest = (pictureArray->getCurrent())->getCbPtr();
+ endDest=colorLength;
+
+
+ /* Establish row size. yuv color is half of whole size*/
+
+ row_size /=2;
+
+ /* Calculate row,col for upper left pixel value of block. */
+
+ row = mb_row << 3;
+ col = mb_col << 3;
+ }
+
+
+ /*
+ * For each pixel in block, set to cropped reconstructed value from inverse
+ * dct.
+ */
+
+ dest = picDest+row * row_size + col;
+
+
+ if ((dest+7*row_size+7 >= picDest+endDest) || (dest < picDest)) {
+ DEBUG_RECON(cout << "urg! last resort caught before sigsev -4"<<endl;)
+ return false;
+ }
+
+
+ copyFunctions->copy8_src1linear_crop(dct_start,dest,row_size);
+
+
+ return true;
+}
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ReconPMBlock --
+ *
+ * Reconstructs forward predicted macroblocks.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int Recon::ReconPMBlock(int bnum,
+ int recon_right_for,
+ int recon_down_for,
+ int zflag,
+ int mb_row,int mb_col,
+ int row_size,short int* dct_start,
+ PictureArray* pictureArray,int codeType) {
+ int row, col, rr;
+ unsigned char *picDest, *past;
+ unsigned char *rindex1, *rindex2, *rindex3, *rindex4;
+ unsigned char *index;
+ int lumLength=(pictureArray->getCurrent())->getLumLength();
+ int colorLength=(pictureArray->getCurrent())->getColorLength();
+ int endPast=0;
+ int endDest=0;
+
+
+ int right_for;
+ int down_for;
+ int right_half_for;
+ int down_half_for;
+
+
+
+ picDest=0;
+
+ if (bnum < 4) {
+
+
+
+ /* Set dest to luminance plane of current pict image. */
+
+ picDest = (pictureArray->getCurrent())->getLuminancePtr();
+ endDest=lumLength;
+
+ if (codeType == B_TYPE) {
+ past = (pictureArray->getPast())->getLuminancePtr();
+ } else {
+
+ /* Set predictive frame to current future frame. */
+
+ past = (pictureArray->getFuture())->getLuminancePtr();
+ }
+ endPast=lumLength;
+
+
+ /* Calculate row,col of upper left pixel in block. */
+
+ row = mb_row << 4;
+ col = mb_col << 4;
+ if (bnum > 1)
+ row += 8;
+ if (bnum % 2)
+ col += 8;
+
+ /* Otherwise, block is NOT luminance block, ... */
+
+ } else {
+
+ /* Construct motion vectors. */
+
+ recon_right_for >>= 1;
+ recon_down_for >>= 1;
+
+ /* Establish row size. yuv color is half of whole size*/
+
+ row_size /= 2;
+
+
+ /* Calculate row,col of upper left pixel in block. */
+
+ row = mb_row << 3;
+ col = mb_col << 3;
+
+ /* If block is Cr block... */
+ /* 5 first because order was mixed up in earlier versions */
+
+ if (bnum == 5) {
+
+ /* Set dest to Cr plane of current pict image. */
+
+ picDest = (pictureArray->getCurrent())->getCrPtr();
+
+ if (codeType == B_TYPE) {
+
+ past = (pictureArray->getPast())->getCrPtr();
+ } else {
+ past = (pictureArray->getFuture())->getCrPtr();
+ }
+ }
+ /* Otherwise, block is Cb block... */
+
+ else {
+
+ /* Set dest to Cb plane of current pict image. */
+
+ picDest = (pictureArray->getCurrent())->getCbPtr();
+
+ if (codeType == B_TYPE) {
+ past = (pictureArray->getPast())->getCbPtr();
+ } else {
+ past = (pictureArray->getFuture())->getCbPtr();
+ }
+ }
+ endPast=colorLength;
+ endDest=colorLength;
+
+ }
+
+ /* Calculate right_back, down_back motion vectors. */
+ right_for = recon_right_for >> 1;
+ down_for = recon_down_for >> 1;
+ right_half_for = recon_right_for & 0x1;
+ down_half_for = recon_down_for & 0x1;
+
+
+ /* For each pixel in block... */
+
+ index = picDest + (row * row_size) + col;
+ rindex1 = past + (row + down_for) * row_size + col + right_for;
+
+
+
+
+ if ((rindex1+7*row_size+7 >= past+endPast) || (rindex1 < past)) {
+ DEBUG_RECON(cout << "urg! last resort caught before sigsev -1"<<endl;)
+ return false;
+ }
+ if ((index+7*row_size+7 >= picDest+endDest) || (index < picDest)) {
+ DEBUG_RECON(cout << "urg! last resort caught before sigsev -2"<<endl;)
+ return false;
+ }
+
+
+ /*
+ * Calculate predictive pixel value based on motion vectors and copy to
+ * dest plane.
+ */
+
+ if ((!down_half_for) && (!right_half_for)) {
+
+ if (!zflag) {
+ copyFunctions->copy8_src2linear_crop(rindex1,dct_start,index,row_size);
+ } else {
+ if (right_for & 0x1) {
+
+ /* No alignment, used byte copy */
+ copyFunctions->copy8_byte(rindex1,index,row_size);
+
+
+ } else if (right_for & 0x2) {
+ /* Half-word bit aligned, use 16 bit copy */
+ unsigned short *src = (unsigned short *)rindex1;
+ unsigned short *dest = (unsigned short *)index;
+ row_size >>= 1;
+ copyFunctions->copy8_word(src,dest,row_size);
+
+ } else {
+ /* Word aligned, use 32 bit copy */
+ int *src = (int*) rindex1;
+ int *dest = (int*) index;
+
+ row_size >>= 2;
+
+
+ for (rr = 0; rr < 8; rr++) {
+ dest[0] = src[0];
+ dest[1] = src[1];
+ dest += row_size;
+ src += row_size;
+ }
+
+ }
+ }
+ } else {
+ rindex2 = rindex1 + right_half_for + (down_half_for * row_size);
+
+ /* if one of the two is zero, then quality makes no difference */
+ if ((!right_half_for) || (!down_half_for) || (!qualityFlag)) {
+
+ if (!zflag) {
+ // was +1
+ copyFunctions->copy8_div2_src3linear_crop(rindex1,rindex2,dct_start,
+ index,row_size);
+ } else { /* zflag */
+ // was +1
+ copyFunctions->copy8_div2_nocrop(rindex1,rindex2,index,row_size);
+ }
+ } else { /* qualityFlag on and both vectors are non-zero */
+ rindex3 = rindex1 + right_half_for;
+ rindex4 = rindex1 + (down_half_for * row_size);
+ if (!zflag) {
+ copyFunctions->copy8_div4_src5linear_crop(rindex1,rindex2,rindex3,
+ rindex4,dct_start,
+ index,row_size);
+ } else { /* zflag */
+ copyFunctions->copy8_div4_nocrop(rindex1,rindex2,rindex3,rindex4,
+ index,row_size);
+ }
+ }
+
+ }
+
+ return true;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ReconBMBlock --
+ *
+ * Reconstructs back predicted macroblocks.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int Recon::ReconBMBlock(int bnum,
+ int recon_right_back,
+ int recon_down_back,
+ int zflag,
+ int mb_row,int mb_col,
+ int row_size,short int* dct_start,
+ PictureArray* pictureArray) {
+ int row, col, rr;
+ unsigned char *dest, *future;
+ int right_back, down_back, right_half_back, down_half_back;
+ unsigned char *rindex1, *rindex2, *rindex3, *rindex4;
+ unsigned char *index;
+ int lumLength=(pictureArray->getCurrent())->getLumLength();
+ int colorLength=(pictureArray->getCurrent())->getColorLength();
+
+ int endFuture=0;
+ int endDest=0;
+
+
+ /* If block is luminance block... */
+
+ if (bnum < 4) {
+
+
+ /* Set dest to luminance plane of current pict image. */
+
+ dest = (pictureArray->getCurrent())->getLuminancePtr();
+ endDest=lumLength;
+ /*
+ * If future frame exists, set future to luminance plane of future frame.
+ */
+
+ future = (pictureArray->getFuture())->getLuminancePtr();
+ endFuture=lumLength;
+
+ /* Calculate row,col of upper left pixel in block. */
+
+ row = mb_row << 4;
+ col = mb_col << 4;
+ if (bnum > 1)
+ row += 8;
+ if (bnum % 2)
+ col += 8;
+
+
+ }
+ /* Otherwise, block is NOT luminance block, ... */
+
+ else {
+
+ /* Construct motion vectors. */
+
+ recon_right_back >>= 1;
+ recon_down_back >>= 1;
+
+ /* Establish row size. yuv color is half of whole size*/
+
+ row_size >>= 1;
+
+ /* Calculate row,col of upper left pixel in block. */
+
+ row = mb_row << 3;
+ col = mb_col << 3;
+
+
+ /* If block is Cr block... */
+ /* They were switched earlier, so 5 is first - eyhung */
+
+ if (bnum == 5) {
+
+ /* Set dest to Cr plane of current pict image. */
+
+ dest = (pictureArray->getCurrent())->getCrPtr();
+
+ /*
+ * If future frame exists, set future to Cr plane of future image.
+ */
+
+ future = (pictureArray->getFuture())->getCrPtr();
+ }
+ /* Otherwise, block is Cb block... */
+
+ else {
+
+ /* Set dest to Cb plane of current pict image. */
+
+ dest = (pictureArray->getCurrent())->getCbPtr();
+
+ /*
+ * If future frame exists, set future to Cb plane of future frame.
+ */
+
+ future = (pictureArray->getFuture())->getCbPtr();
+ }
+ endDest=colorLength;
+ endFuture=colorLength;
+ }
+
+ /* Calculate right_back, down_back motion vectors. */
+ right_back = recon_right_back >> 1;
+ down_back = recon_down_back >> 1;
+ right_half_back = recon_right_back & 0x1;
+ down_half_back = recon_down_back & 0x1;
+
+ /* For each pixel in block do... */
+
+ index = dest + (row * row_size) + col;
+ rindex1 = future + (row + down_back) * row_size + col + right_back;
+
+ if ((index+7*row_size+7 >= dest+endDest) || (index < dest)) {
+ DEBUG_RECON(cout << "urg! last resort -9"<<endl;)
+ return false;
+ }
+ if ((rindex1+7*row_size+7 >= future+endFuture) || (rindex1 < future)) {
+ DEBUG_RECON(cout << "urg! last resort -8"<<endl;)
+ return false;
+ }
+
+ if ((!right_half_back) && (!down_half_back)) {
+ if (!zflag) {
+ copyFunctions->copy8_src2linear_crop(rindex1,dct_start,index,row_size);
+ } else {
+ if (right_back & 0x1) {
+ /* No alignment, use byte copy */
+
+ copyFunctions->copy8_byte(rindex1,index,row_size);
+
+ } else if (right_back & 0x2) {
+ /* Half-word bit aligned, use 16 bit copy */
+ unsigned short *src = (unsigned short *)rindex1;
+ unsigned short *dest = (unsigned short *)index;
+ row_size >>= 1;
+ copyFunctions->copy8_word(src,dest,row_size);
+
+ } else {
+ /* Word aligned, use 32 bit copy */
+ int *src = (int *)rindex1;
+ int *dest = (int *)index;
+ row_size >>= 2;
+ for (rr = 0; rr < 8; rr++) {
+ dest[0] = src[0];
+ dest[1] = src[1];
+ dest += row_size;
+ src += row_size;
+ }
+ }
+ }
+ } else {
+ rindex2 = rindex1 + right_half_back + (down_half_back * row_size);
+ if (!qualityFlag) {
+
+ if (!zflag) {
+ // was +1
+ copyFunctions->copy8_div2_src3linear_crop(rindex1,rindex2,dct_start,
+ index,row_size);
+ } else { /* zflag */
+ // was +1
+ copyFunctions->copy8_div2_nocrop(rindex1,rindex2,index,row_size);
+ }
+ } else { /* qualityFlag on */
+ rindex3 = rindex1 + right_half_back;
+ rindex4 = rindex1 + (down_half_back * row_size);
+ if (!zflag) {
+ copyFunctions->copy8_div4_src5linear_crop(rindex1,rindex2,rindex3,
+ rindex4,dct_start,
+ index,row_size);
+ } else { /* zflag */
+ copyFunctions->copy8_div4_nocrop(rindex1,rindex2,rindex3,rindex4,
+ index,row_size);
+ }
+ }
+
+ }
+ return true;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ReconBiMBlock --
+ *
+ * Reconstructs bidirectionally predicted macroblocks.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+int Recon::ReconBiMBlock(int bnum,
+ int recon_right_for,
+ int recon_down_for,
+ int recon_right_back,
+ int recon_down_back,
+ int zflag,int mb_row,
+ int mb_col,int row_size,short int* dct_start,
+ PictureArray* pictureArray) {
+ int row, col;
+ unsigned char *dest, *past=NULL, *future=NULL;
+ int right_for, down_for, right_half_for, down_half_for;
+ int right_back, down_back, right_half_back, down_half_back;
+ unsigned char *index, *rindex1, *bindex1;
+ int forw_row_start, back_row_start, forw_col_start, back_col_start;
+ int lumLength=(pictureArray->getCurrent())->getLumLength();
+ int colorLength=(pictureArray->getCurrent())->getColorLength();
+ int endPast=0;
+ int endFuture=0;
+
+
+
+
+ /* If block is luminance block... */
+
+ if (bnum < 4) {
+
+
+ /* Set dest to luminance plane of current pict image. */
+
+ dest = (pictureArray->getCurrent())->getLuminancePtr();
+
+ /* If past frame exists, set past to luminance plane of past frame. */
+
+ past = (pictureArray->getPast())->getLuminancePtr();
+ endPast=lumLength;
+
+ /*
+ * If future frame exists, set future to luminance plane of future frame.
+ */
+
+ future = (pictureArray->getFuture())->getLuminancePtr();
+ endFuture=lumLength;
+
+ /* Calculate row,col of upper left pixel in block. */
+
+ row = (mb_row << 4);
+ col = (mb_col << 4);
+ if (bnum > 1)
+ row += 8;
+ if (bnum & 0x01)
+ col += 8;
+
+
+
+ } else {
+ /* Otherwise, block is NOT luminance block, ... */
+
+ /* Construct motion vectors. */
+ recon_right_for >>= 1;
+ recon_down_for >>= 1;
+ recon_right_back >>= 1;
+ recon_down_back >>= 1;
+
+ /* Establish row size. yuv color is half of whole size*/
+
+ row_size /= 2;
+
+
+ /* Calculate row,col of upper left pixel in block. */
+
+ row = (mb_row << 3);
+ col = (mb_col << 3);
+
+
+
+
+ /* If block is Cr block... */
+ /* Switched earlier, so we test Cr first - eyhung */
+
+ if (bnum == 5) {
+ /* Set dest to Cr plane of current pict image. */
+
+ dest = (pictureArray->getCurrent())->getCrPtr();
+
+ /* If past frame exists, set past to Cr plane of past image. */
+
+ past = (pictureArray->getPast())->getCrPtr();
+ endPast=colorLength;
+ /*
+ * If future frame exists, set future to Cr plane of future image.
+ */
+
+ future = (pictureArray->getFuture())->getCrPtr();
+ endFuture=colorLength;
+ }
+ /* Otherwise, block is Cb block... */
+
+ else {
+ /* Set dest to Cb plane of current pict image. */
+ dest = (pictureArray->getCurrent())->getCbPtr();
+
+ /* If past frame exists, set past to Cb plane of past frame. */
+
+ past = (pictureArray->getPast())->getCbPtr();
+ endPast=colorLength;
+
+ /*
+ * If future frame exists, set future to Cb plane of future frame.
+ */
+
+ future = (pictureArray->getFuture())->getCbPtr();
+ endFuture=colorLength;
+ }
+ }
+ /*
+ * Calculate right_for, down_for, right_half_for, down_half_for,
+ * right_back, down_bakc, right_half_back, and down_half_back, motion
+ * vectors.
+ */
+
+ right_for = recon_right_for >> 1;
+ down_for = recon_down_for >> 1;
+ right_half_for = recon_right_for & 0x1;
+ down_half_for = recon_down_for & 0x1;
+
+ right_back = recon_right_back >> 1;
+ down_back = recon_down_back >> 1;
+ right_half_back = recon_right_back & 0x1;
+ down_half_back = recon_down_back & 0x1;
+
+ forw_col_start = col + right_for;
+ forw_row_start = row + down_for;
+
+ back_col_start = col + right_back;
+ back_row_start = row + down_back;
+
+ /* For each pixel in block... */
+
+ index = dest + (row * row_size) + col;
+
+ rindex1 = past + forw_row_start * row_size + forw_col_start;
+
+ bindex1 = future + back_row_start * row_size + back_col_start;
+
+ if ((rindex1+7*row_size+7 >= past+endPast) || (rindex1 < past)) {
+ DEBUG_RECON(cout << "urg! last resort -1"<<endl;)
+ return false;
+ }
+ if ((bindex1+7*row_size+7 >= future+endFuture) || (bindex1 < future)) {
+ DEBUG_RECON(cout << "urg! last resort -2"<<endl;)
+ return false;
+ }
+
+
+
+ if (!zflag) {
+ copyFunctions->copy8_div2_src3linear_crop(rindex1,bindex1,dct_start,
+ index,row_size);
+ } else {
+ copyFunctions->copy8_div2_nocrop(rindex1,bindex1,index,row_size);
+ }
+
+ return true;
+}
+
+
diff --git a/mpeglib/lib/mpegplay/recon.h b/mpeglib/lib/mpegplay/recon.h
new file mode 100644
index 00000000..26c3e92e
--- /dev/null
+++ b/mpeglib/lib/mpegplay/recon.h
@@ -0,0 +1,55 @@
+/*
+ class for reconstruction
+ Copyright (C) 1999 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#ifndef __RECON_H
+#define __RECON_H
+
+
+#include <iostream>
+#include "../util/render/pictureArray.h"
+#include "copyFunctions.h"
+#include "videoDecoder.h"
+
+class Recon {
+
+
+ CopyFunctions* copyFunctions;
+
+ public:
+ Recon();
+ ~Recon();
+
+ int ReconIMBlock(int bnum,int mb_row,int mb_col,int row_size,
+ short int* dct_start,PictureArray* pictureArray);
+
+ int ReconPMBlock(int bnum,int recon_right_for,
+ int recon_down_for,int zflag,
+ int mb_row,int mb_col,int row_size,
+ short int* dct_start,PictureArray* pictureArray,
+ int codeType);
+
+ int ReconBMBlock(int bnum,int recon_right_back,
+ int recon_down_back,int zflag,
+ int mb_row,int mb_col,int row_size,
+ short int* dct_start,PictureArray* pictureArray);
+
+ int ReconBiMBlock(int bnum,int recon_right_for,
+ int recon_down_for,int recon_right_back,
+ int recon_down_back,int zflag,
+ int mb_row,int mb_col,int row_size,
+ short int* dct_start,PictureArray* pictureArray);
+
+
+
+};
+#endif
diff --git a/mpeglib/lib/mpegplay/slice.cpp b/mpeglib/lib/mpegplay/slice.cpp
new file mode 100644
index 00000000..1a64378f
--- /dev/null
+++ b/mpeglib/lib/mpegplay/slice.cpp
@@ -0,0 +1,73 @@
+/*
+ reads/parse slice infos
+ Copyright (C) 1999 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "slice.h"
+
+
+
+
+Slice::Slice() {
+ mpegExtension=new MpegExtension();
+}
+
+
+Slice::~Slice() {
+ delete mpegExtension;
+
+}
+
+unsigned int Slice::getVertPos() {
+ return vert_pos;
+}
+
+
+
+void Slice::setQuantScale(unsigned int quant_scale) {
+ this->quant_scale=quant_scale;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ParseSlice --
+ *
+ * Parses off slice header.
+ *
+ * Results:
+ * Values found in slice header put into video stream structure.
+ *
+ * Side effects:
+ * Bit stream irreversibly parsed.
+ *
+ *--------------------------------------------------------------
+ */
+int Slice::parseSlice(MpegVideoStream* mpegVideoStream) {
+
+ /* Flush slice start code. */
+ mpegVideoStream->flushBits(24);
+
+ /* Parse off slice vertical position. */
+ /* its the "slice number" */
+ vert_pos=mpegVideoStream->getBits(8);
+
+ /* Parse off quantization scale. */
+ quant_scale=mpegVideoStream->getBits(5);
+
+ /* Parse off extra bit slice info. */
+ mpegExtension->processExtra_bit_info(mpegVideoStream);
+
+ return true;
+}
+
+
+
diff --git a/mpeglib/lib/mpegplay/slice.h b/mpeglib/lib/mpegplay/slice.h
new file mode 100644
index 00000000..10689d34
--- /dev/null
+++ b/mpeglib/lib/mpegplay/slice.h
@@ -0,0 +1,48 @@
+/*
+ reads/parse slice infos
+ Copyright (C) 1999 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+
+#ifndef __SLICE_H
+#define __SLICE_H
+
+#include "jrevdct.h"
+#include "mpegExtension.h"
+
+/* Size increment of extension data buffers. */
+
+#define EXT_BUF_SIZE 1024
+
+class Slice {
+
+
+ public:
+ Slice();
+ ~Slice();
+ int parseSlice(MpegVideoStream* mpegVideoStream);
+ unsigned int getVertPos();
+ inline unsigned int getQuantScale() {return quant_scale;}
+ void setQuantScale(unsigned int quant_scale);
+
+
+ private:
+
+ /* Slice structure. */
+
+ unsigned int vert_pos; /* Vertical position of slice. */
+ unsigned int quant_scale; /* Quantization scale. */
+ MpegExtension* mpegExtension; /* Extra bit slice info. */
+
+};
+
+
+#endif
diff --git a/mpeglib/lib/mpegplay/startCodes.h b/mpeglib/lib/mpegplay/startCodes.h
new file mode 100644
index 00000000..c305a39f
--- /dev/null
+++ b/mpeglib/lib/mpegplay/startCodes.h
@@ -0,0 +1,63 @@
+/*
+ definitions of common startcodes
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+
+
+
+#ifndef __STARTCODES_H
+#define __STARTCODES_H
+
+
+
+/* Macros for picture code type. */
+
+#define I_TYPE 1
+#define P_TYPE 2
+#define B_TYPE 3
+#define D_TYPE 4
+
+/* Start codes. */
+
+
+#define SEQ_END_CODE 0x000001b7
+#define SEQ_START_CODE 0x000001b3
+#define GOP_START_CODE 0x000001b8
+#define PICTURE_START_CODE 0x00000100
+#define SLICE_MIN_START_CODE 0x00000101
+#define SLICE_MAX_START_CODE 0x000001af
+#define EXT_START_CODE 0x000001b5
+#define USER_START_CODE 0x000001b2
+#define SEQUENCE_ERROR_CODE 0x000001b4
+
+//extension start code ids
+#define SEQUENCE_EXTENSION_ID 1
+#define SEQUENCE_DISPLAY_EXTENSION_ID 2
+#define QUANT_MATRIX_EXTENSION_ID 3
+#define COPYRIGHT_EXTENSION_ID 4
+#define SEQUENCE_SCALABLE_EXTENSION_ID 5
+#define PICTURE_DISPLAY_EXTENSION_ID 7
+#define PICTURE_CODING_EXTENSION_ID 8
+#define PICTURE_SPATIAL_SCALABLE_EXTENSION_ID 9
+#define PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID 10
+
+#define ISO_11172_END_CODE ((unsigned int)0x000001b9)
+#define SYSTEM_HEADER_START_CODE ((unsigned int)0x000001bb)
+
+/* Macros used with macroblock address decoding. */
+
+#define MB_STUFFING 34
+#define MB_ESCAPE 35
+
+
+
+#endif
diff --git a/mpeglib/lib/mpegplay/tsSystemStream.cpp b/mpeglib/lib/mpegplay/tsSystemStream.cpp
new file mode 100644
index 00000000..4c9221ac
--- /dev/null
+++ b/mpeglib/lib/mpegplay/tsSystemStream.cpp
@@ -0,0 +1,377 @@
+/*
+ demux transport stream
+ Copyright (C) 2001 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+
+#include "tsSystemStream.h"
+
+
+#define PKT_SIZE 188
+
+
+TSSystemStream::TSSystemStream(InputStream* input) {
+ this->input=input;
+
+}
+
+
+TSSystemStream::~TSSystemStream() {
+}
+
+int TSSystemStream::read(char* ptr,int bytes) {
+ if (input->read(ptr,bytes) != bytes) {
+ return false;
+ }
+ paket_read+=bytes;
+
+ return true;
+}
+
+int TSSystemStream::getByteDirect() {
+ unsigned char byte;
+ if (input->read((char*)&byte,1) != 1) {
+ return -1;
+ }
+ paket_read++;
+ return (int)byte;
+}
+
+
+// nuke bytes modulo 10
+int TSSystemStream::nukeBytes(int bytes) {
+ // nukebuffer
+ char nuke[10];
+
+ while(bytes > 0) {
+ int doNuke=10;
+ if (bytes < 10) doNuke=bytes;
+ if (input->read((char*)&nuke,doNuke) != doNuke) {
+ return false;
+ }
+ bytes-=doNuke;
+ paket_read+=doNuke;
+ }
+ return true;
+}
+
+
+int TSSystemStream::skipNextByteInLength() {
+ int length=getByteDirect();
+ if (length < 0) return false;
+
+ /*
+ * Skip read byte in length, but check paket_size
+ */
+ if (paket_read+length > PKT_SIZE) {
+ printf ("demux error! invalid payload size %d\n",length);
+ return false;
+ }
+ if (nukeBytes(length) == false) return false;
+ return true;
+}
+
+
+
+
+int TSSystemStream::processStartCode(MpegSystemHeader* mpegHeader) {
+ paket_len=PKT_SIZE;
+ paket_read=4; // startcode=4 bytes
+
+ mpegHeader->setTSPacketLen(0);
+ mpegHeader->setPacketID(_PAKET_ID_NUKE);
+
+ unsigned int pid=mpegHeader->getPid();
+ unsigned int pmtPID=mpegHeader->getPMTPID();
+ if ( (pmtPID == INVALID_PID) && (pid != 0)) {
+ return false;
+ }
+
+ if ((mpegHeader->getAdaption_field_control() & 0x1)==0) {
+ return true;
+ }
+
+ /*
+ * Has a payload! Calculate & check payload length.
+ */
+ if (mpegHeader->getAdaption_field_control() & 0x2) {
+ if (skipNextByteInLength() == false) return false;
+ }
+
+ /*
+ * Do the demuxing in based on the pids
+ */
+
+ if (pid == mpegHeader->getPMTPID()) {
+ return demux_ts_pmt_parse(mpegHeader);
+ }
+
+ if (pid == 0) {
+ return demux_ts_pat_parse(mpegHeader);
+ }
+ //
+ // ok, no the only things left to do is the
+ // decision what to do with the packet
+ //
+
+ mpegHeader->setTSPacketLen(paket_len-paket_read);
+
+ if (pid == 0x1fff) {
+ printf("Nuke Packet\n");
+ return true;
+ }
+
+
+ MapPidStream* mapPidStream=mpegHeader->lookup(pid);
+
+ if (mapPidStream->isValid == true) {
+ // set to something different from "NUKE_PAKET"
+ mpegHeader->setPacketID(_PAKET_ID_AUDIO_1);
+ return true;
+ }
+ // well the raw stream has a TS header and a PID, but we have not a valid
+ // mapping pid->tsType.
+ // we return false here to have a recovery if our
+ // previous decision that we actually have a TS stream was wrong.
+
+ // force resync
+ return false;
+}
+
+/*
+ * NAME demux_ts_pmt_parse
+ *
+ * Parse a PMT. The PMT is expected to be exactly one section long,
+ * and that section is expected to be contained in a single TS packet.
+ *
+ * In other words, the PMT is assumed to describe a reasonable number of
+ * video, audio and other streams (with descriptors).
+ */
+
+int TSSystemStream::demux_ts_pmt_parse(MpegSystemHeader* mpegHeader) {
+ int sectionLength=processSection(mpegHeader);
+ if (sectionLength == 0) return false;
+
+ //?
+ if (nukeBytes(2) == false) return false;
+ sectionLength-=2;
+
+ /*
+ * ES definitions start here...we are going to learn upto one video
+ * PID and one audio PID.
+ */
+
+
+ unsigned char pkt[2];
+ if (read((char*)pkt,2) == false) return false;
+ sectionLength-=2;
+
+ unsigned int programInfoLength;
+
+ programInfoLength=(((unsigned int)pkt[0] & 0x0f) << 8) | pkt[1];
+ if (paket_read+programInfoLength > paket_len) {
+ printf ("demux error! PMT with inconsistent progInfo length\n");
+ return false;
+ }
+
+ if (nukeBytes(programInfoLength) == false) return false;
+ sectionLength-=programInfoLength;
+
+ return processElementary(sectionLength,mpegHeader);
+
+
+}
+
+/**
+ return false on error or section length info on success
+*/
+int TSSystemStream::processSection(MpegSystemHeader* mpegHeader) {
+ unsigned int pus=mpegHeader->getPayload_unit_start_indicator();
+
+ /*
+ * A PAT in a single section should start with a payload unit start
+ * indicator set.
+ */
+ if (pus==0) {
+ printf ("demux error! PAT without payload unit start\n");
+ return false;
+ }
+ /*
+ * PAT packets with a pus start with a pointer. Skip it!
+ */
+ if (skipNextByteInLength() == false) return false;
+
+ // ??
+ if (nukeBytes(1) == false) return false;
+
+ // read sectionLength
+ unsigned char pkt[2];
+ if (read((char*)pkt,2) ==false) return false;
+
+
+ int sectionLength=(((unsigned int)pkt[0] & 0x3) << 8) | pkt[1];
+ if (paket_read+sectionLength > PKT_SIZE) {
+ printf ("demux error! invalid section size %d\n",sectionLength);
+ return false;
+ }
+
+ // ??
+ if (nukeBytes(2) == false) return false;
+
+ int byte=getByteDirect();
+ if (byte < 0) return false;
+
+ if ((byte & 0x01) == false) {
+ /*
+ * Not current!
+ */
+ return false;
+ }
+ if (read((char*)pkt,2) == false) return false;
+
+ if ((pkt[0]) || (pkt[1])) {
+ printf ("demux error! PAT with invalid section %02x of %02x\n",
+ pkt[0], pkt[1]);
+ return false;
+ }
+
+ /*
+ * TBD: at this point, we should check the CRC. Its not that expensive, and
+ * the consequences of getting it wrong are dire!
+ */
+ return sectionLength-5;
+}
+
+/*
+ * NAME demux_ts_pat_parse
+ *
+ * Parse a PAT. The PAT is expected to be exactly one section long,
+ * and that section is expected to be contained in a single TS packet.
+ *
+ * The PAT is assumed to contain a single program definition, though
+ * we can cope with the stupidity of SPTSs which contain NITs.
+ */
+
+int TSSystemStream::demux_ts_pat_parse(MpegSystemHeader* mpegHeader) {
+ int sectionLength=processSection(mpegHeader);
+ if (sectionLength == 0) return false;
+
+ return processPrograms(sectionLength,mpegHeader);
+
+}
+
+
+/*
+ * Process all programs in the program loop.
+ */
+int TSSystemStream::processPrograms(int sectionLength,
+ MpegSystemHeader* mpegHeader) {
+ int programs=sectionLength / 4;
+ int i;
+ // what happens with the last 4 byte?
+ // seems they have no meaning?
+ programs--;
+
+ for(i=0;i<programs;i++) {
+ unsigned char program[4];
+ if (read((char*)program,4) == false) return false;
+
+
+ unsigned int programNumber;
+ unsigned int pmtPid;
+ unsigned int programCount;
+ programNumber = ((unsigned int)program[0] << 8) | program[1];
+
+ /*
+ * Skip NITs completely.
+ */
+ if (!programNumber)
+ continue;
+
+ pmtPid = (((unsigned int)program[2] & 0x1f) << 8) | program[3];
+
+
+ /*
+ * If we have yet to learn our program number, then learn it.
+ */
+
+ if (mpegHeader->getProgramNumber() == INVALID_PROGRAM) {
+ mpegHeader->setProgramNumber(programNumber);
+ mpegHeader->setPMTPID(pmtPid);
+ }
+
+ if (mpegHeader->getProgramNumber() != programNumber) {
+ printf("demux error! MPTS: programNumber=%u pmtPid=%04x\n",
+ programNumber, pmtPid);
+ }
+
+ if (mpegHeader->getPMTPID() != pmtPid) {
+ printf("pmtPid changed %04x\n", pmtPid);
+ mpegHeader->setPMTPID(pmtPid);
+ }
+
+ }
+ // nuke last four bytes
+ if (nukeBytes(4) == false) return false;
+
+ //
+ // now we can nuke the rest of the PAKET_SIZE (188 byte)
+ //
+ mpegHeader->setTSPacketLen(paket_len-paket_read);
+ return true;
+}
+
+
+
+int TSSystemStream::processElementary(int sectionLength,
+ MpegSystemHeader* mpegHeader) {
+
+
+ /*
+ * Extract the elementary streams.
+ */
+ int mediaIndex=0;
+ // what happens with the last 4 byte?
+ // seems they have no meaning?
+ while (sectionLength > 4) {
+ unsigned int streamInfoLength;
+ unsigned char stream[5];
+ if (read((char*)stream,5) == false) return false;
+ sectionLength-=5;
+
+ unsigned int pid;
+ pid = (((unsigned int)stream[1] & 0x1f) << 8) | stream[2];
+
+ streamInfoLength = (((unsigned int)stream[3] & 0xf) << 8) | stream[4];
+ if(paket_read+streamInfoLength > paket_len) {
+ printf ("demux error! PMT with inconsistent streamInfo length\n");
+ return false;
+ }
+ mpegHeader->insert(pid,stream[0],mpegHeader);
+
+ }
+
+ // nuke last four bytes
+ if (nukeBytes(4) == false) return false;
+ //
+ // now we can nuke the rest of the PAKET_SIZE (188 byte)
+ //
+ mpegHeader->setTSPacketLen(paket_len-paket_read);
+
+ //
+ // now we can be sure that we have in fact an TS stream
+ // so, switch to MPEG2 PES now
+ mpegHeader->setMPEG2(true);
+
+ return true;
+}
+
+
diff --git a/mpeglib/lib/mpegplay/tsSystemStream.h b/mpeglib/lib/mpegplay/tsSystemStream.h
new file mode 100644
index 00000000..114365c4
--- /dev/null
+++ b/mpeglib/lib/mpegplay/tsSystemStream.h
@@ -0,0 +1,68 @@
+/*
+ demux transport stream
+ Copyright (C) 2001 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+
+#ifndef __TSSYSTEMSTREAM_H
+#define __TSSYSTEMSTREAM_H
+
+
+#include <stdlib.h>
+#include "../input/inputPlugin.h"
+#include "mpegSystemHeader.h"
+
+
+
+/**
+ This class is used inside mpegSystemStream.h when we found
+ during initialisation an transport stream.
+
+
+*/
+
+class TSSystemStream {
+
+ InputStream* input;
+
+ int paket_len;
+ int paket_read;
+
+
+
+ public:
+ TSSystemStream(InputStream* input);
+ ~TSSystemStream();
+
+ // called when we found a valid ts startcode
+ int processStartCode(MpegSystemHeader* mpegHeader);
+
+
+ private:
+
+ // read stream methods
+ int read(char* ptr,int bytes);
+ int getByteDirect();
+ int nukeBytes(int bytes);
+ int skipNextByteInLength();
+
+
+ // process Format methods
+ int processSection(MpegSystemHeader* mpegHeader);
+ int processPrograms(int sectionLength,MpegSystemHeader* mpegHeader);
+ int processElementary(int sectionLength,MpegSystemHeader* mpegHeader);
+
+ int demux_ts_pat_parse(MpegSystemHeader* mpegHeader);
+ int demux_ts_pmt_parse(MpegSystemHeader* mpegHeader);
+
+
+};
+#endif
diff --git a/mpeglib/lib/mpegplay/videoDecoder.cpp b/mpeglib/lib/mpegplay/videoDecoder.cpp
new file mode 100644
index 00000000..b1971795
--- /dev/null
+++ b/mpeglib/lib/mpegplay/videoDecoder.cpp
@@ -0,0 +1,476 @@
+/*
+ mpeg I video decoder (derived from mpeg_play)
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+
+#include "videoDecoder.h"
+
+using namespace std;
+
+
+
+VideoDecoder::VideoDecoder(MpegVideoStream* inputStream,
+ MpegVideoHeader* initSequence) {
+
+ /* Check for legal buffer length. */
+
+ init_tables();
+
+
+ /* Initialize fields that used to be global */
+
+ mpegVideoStream=inputStream;
+ decoderClass=new DecoderClass(this,mpegVideoStream);
+ recon=new Recon();
+ motionVector=new MotionVector();
+ slice=new Slice();
+ group=new GOP();
+ mpegVideoHeader=new MpegVideoHeader();
+ picture=new Picture();
+ macroBlock=new MacroBlock(this);
+
+ // init this stream with the init sequence
+ initSequence->copyTo(mpegVideoHeader);
+
+ syncState=SYNC_TO_CLOSED_GOP;
+ extension=new MpegExtension();
+ frameCounter=0;
+}
+
+
+VideoDecoder::~VideoDecoder() {
+
+ delete mpegVideoHeader;
+ delete picture;
+ delete decoderClass;
+ delete recon;
+ delete motionVector;
+ delete slice;
+ delete group;
+ delete extension;
+ delete macroBlock;
+}
+
+
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * mpegVidRsrc --
+ *
+ * Parses bit stream until MB_QUANTUM number of
+ * macroblocks have been decoded or current slice or
+ * picture ends, whichever comes first. If the start
+ * of a frame is encountered, the frame is time stamped
+ * with the value passed in time_stamp. If the value
+ * passed in buffer is not null, the video stream buffer
+ * is set to buffer and the length of the buffer is
+ * expected in value passed in through length. The current
+ * video stream is set to vid_stream. If vid_stream
+ * is passed as NULL, a new VideoDecoder structure is created
+ * and initialized and used as the current video stream.
+ *
+ * Results:
+ * A pointer to the video stream structure used.
+ *
+ * Side effects:
+ * Bit stream is irreversibly parsed. If a picture is completed,
+ * a function is called to display the frame at the correct time.
+ *
+ *--------------------------------------------------------------
+ */
+
+int VideoDecoder::mpegVidRsrc(PictureArray* pictureArray) {
+ int back=_SYNC_TO_NONE;
+
+ unsigned int data;
+ int i;
+
+
+ /*
+ * If called for the first time, find start code, make sure it is a
+ * sequence start code.
+ */
+
+
+ /* Get next 32 bits (size of start codes). */
+
+ data=mpegVideoStream->showBits(32);
+
+
+ /*
+ * Process according to start code (or parse macroblock if not a start code
+ * at all).
+ */
+ switch (data) {
+ /*
+ case PACK_START_CODE:
+ case SYSTEM_HEADER_START_CODE:
+ cout << "Packet in Loop **************"<<endl;
+ mpegVideoStream->flushBits(32);
+ packet->read_sys(data,vid_stream->bufferReader);
+ */
+ case SEQ_END_CODE:
+ case ISO_11172_END_CODE: /* handle ISO_11172_END_CODE too */
+
+ /* Display last frame. */
+
+ // removed!
+
+ /* Sequence done. Do the right thing. For right now, exit. */
+
+
+ cout << "******** flushin end code"<<endl;
+ mpegVideoStream->flushBits(32);
+ goto done;
+ break;
+ case EXT_START_CODE:
+ cout << "found EXT_START_CODE skipping"<<endl;
+ mpegVideoStream->flushBits(32);
+ /* Goto next start code. */
+ mpegVideoStream->next_start_code();
+
+ break;
+ case USER_START_CODE:
+ mpegVideoStream->flushBits(32);
+ /* Goto next start code. */
+ mpegVideoStream->next_start_code();
+
+ break;
+ case SEQ_START_CODE:
+
+ /* Sequence start code. Parse sequence header. */
+ if (ParseSeqHead() == false) {
+ printf("SEQ_START_CODE 1-error\n");
+ goto error;
+ }
+ goto done;
+
+ case GOP_START_CODE:
+ /* Group of Pictures start code. Parse gop header. */
+ if (ParseGOP() == false) {
+ printf("GOP_START_CODE 1-error\n");
+ goto error;
+ }
+ goto done;
+
+ case PICTURE_START_CODE:
+
+ /* Picture start code. Parse picture header and first slice header. */
+
+
+ back=ParsePicture();
+ if (back != _SYNC_TO_NONE) {
+ //cout << "skip B Frame we are late"<<endl;
+ return back;
+ }
+
+ // parse ok
+ if (ParseSlice() == false) {
+ printf("PICTURE_START_CODE 2-error\n");
+ goto error;
+ }
+ break;
+
+ case SEQUENCE_ERROR_CODE:
+ mpegVideoStream->flushBits(32);
+ mpegVideoStream->next_start_code();
+
+ goto done;
+
+
+ default:
+
+ /* Check for slice start code. */
+ if ((data >= SLICE_MIN_START_CODE) && (data <= SLICE_MAX_START_CODE)) {
+
+ /* Slice start code. Parse slice header. */
+ if (ParseSlice() == false) {
+ printf("default 1-error\n");
+ goto error;
+ }
+ }
+ break;
+ }
+
+ /* Parse next MB_QUANTUM macroblocks. */
+ for (i = 0; i < MB_QUANTUM; i++) {
+
+ /* Check to see if actually a startcode and not a macroblock. */
+ data=mpegVideoStream->showBits(23);
+ if (data != 0x0) {
+ /* Not start code. Parse Macroblock. fill yuv pictures*/
+ if (macroBlock->processMacroBlock(pictureArray) == false) {
+ goto error;
+ }
+ } else {
+ /* Not macroblock, actually start code. Get start code. */
+ mpegVideoStream->next_start_code();
+
+ /*
+ * If start code is outside range of slice start codes, frame is
+ * complete, display frame.
+ */
+ data=mpegVideoStream->showBits(32);
+
+ if (((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) &&
+ (data != SEQUENCE_ERROR_CODE)) {
+ doPictureDisplay(pictureArray);
+ }
+ goto done;
+ }
+ }
+ data=mpegVideoStream->showBits(23);
+ /* Check if we just finished a picture on the MB_QUANTUM macroblock */
+ if (data == 0x0) {
+ mpegVideoStream->next_start_code();
+
+ data=mpegVideoStream->showBits(32);
+ if ((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) {
+ doPictureDisplay(pictureArray);
+ }
+ }
+
+ /* Return pointer to video stream structure. */
+
+ goto done;
+
+error:
+ init_tables();
+ back=_SYNC_TO_GOP;
+ mpegVideoHeader->init_quanttables();
+
+ goto done;
+
+done:
+ return back;
+
+}
+
+
+
+
+
+
+int VideoDecoder::ParseSeqHead() {
+ int back;
+
+ /* Flush off sequence start code. */
+
+ mpegVideoStream->flushBits(32);
+
+ back=mpegVideoHeader->parseSeq(mpegVideoStream);
+
+ return back;
+
+}
+
+
+
+
+int VideoDecoder::ParseGOP() {
+ if (syncState==SYNC_TO_CLOSED_GOP) {
+ syncState=SYNC_HAS_CLOSED_GOP;
+ }
+
+ return group->processGOP(mpegVideoStream);
+}
+
+
+
+
+int VideoDecoder::ParsePicture() {
+ int back;
+ back=picture->processPicture(mpegVideoStream);
+
+ macroBlock->resetPastMacroBlock();
+ if (back == false) {
+ return _SYNC_TO_GOP;
+ }
+
+
+ return _SYNC_TO_NONE;
+}
+
+
+
+int VideoDecoder::ParseSlice() {
+
+
+ slice->parseSlice(mpegVideoStream);
+ macroBlock->resetMacroBlock();
+ decoderClass->resetDCT();
+ return true;
+}
+
+
+
+
+/**
+ After a seek we can only start with an I frame
+*/
+
+void VideoDecoder::resyncToI_Frame() {
+
+ syncState=SYNC_TO_CLOSED_GOP;
+}
+
+
+void VideoDecoder::doPictureDisplay(PictureArray* pictureArray) {
+
+
+ // insert end timestamp to current picture
+ YUVPicture* pic=pictureArray->getCurrent();
+ unsigned int code_type=picture->getCodeType();
+
+ TimeStamp* startTimeStamp=picture->getStartOfPicStamp();
+
+ pic->setStartTimeStamp(startTimeStamp);
+ float rate=mpegVideoHeader->getPictureRate();
+
+ pictureArray->setPicturePerSecond(rate);
+
+
+
+ pic->setMpegPictureType(code_type);
+
+ if (syncState < SYNC_HAS_CLOSED_GOP) {
+ return;
+ }
+ if (syncState < SYNC_HAS_I_FRAME_SYNC) {
+ if (code_type != I_TYPE) {
+ return;
+ }
+ }
+ if (code_type == I_TYPE) {
+ YUVPicture* past=pictureArray->getPast();
+ YUVPicture* future=pictureArray->getFuture();
+ YUVPicture* current=pictureArray->getCurrent();
+
+ YUVPicture* tmp=past;
+ past = future;
+ future = current;
+ current = tmp;
+
+ pic=past;
+
+
+ pictureArray->setPast(past);
+ pictureArray->setCurrent(current);
+ pictureArray->setFuture(future);
+
+ if (syncState < SYNC_HAS_I_FRAME_SYNC) {
+ syncState=SYNC_HAS_I_FRAME_SYNC;
+ return;
+ }
+ if (syncState == SYNC_HAS_P_FRAME_SYNC) {
+ syncState=SYNC_HAS_FRAME_SYNC;
+ return;
+ }
+ if (syncState == SYNC_HAS_I_FRAME_SYNC) {
+ syncState=SYNC_HAS_P_FRAME_SYNC;
+ return;
+ }
+
+
+
+ }
+
+ if (code_type == P_TYPE) {
+ YUVPicture* past=pictureArray->getPast();
+ YUVPicture* future=pictureArray->getFuture();
+ YUVPicture* current=pictureArray->getCurrent();
+
+ YUVPicture* tmp=past;
+ past = future;
+ future = current;
+ current = tmp;
+
+ pic = past;
+
+
+
+ pictureArray->setPast(past);
+ pictureArray->setCurrent(current);
+ pictureArray->setFuture(future);
+
+ if (syncState < SYNC_HAS_P_FRAME_SYNC) {
+ syncState=SYNC_HAS_P_FRAME_SYNC;
+ return;
+ }
+
+ }
+ if (code_type == B_TYPE) {
+ if (syncState == SYNC_HAS_P_FRAME_SYNC) {
+ syncState=SYNC_HAS_FRAME_SYNC;
+ YUVPicture* past=pictureArray->getPast();
+ pic=past;
+ }
+ /**
+ Now check for PTS timeStamp error. It seems some encoders
+ handles this different.
+ If the P frame has a timeStamp earlier than our B stamp
+ we swap them.
+ */
+ YUVPicture* pframe=pictureArray->getFuture();
+ YUVPicture* bframe=pictureArray->getCurrent();
+
+ TimeStamp* pTime=pframe->getStartTimeStamp();
+ TimeStamp* bTime=bframe->getStartTimeStamp();
+
+ double pPTS=pTime->getPTSTimeStamp();
+ double bPTS=bTime->getPTSTimeStamp();
+ if (pPTS < bPTS) {
+ //cout << "********P/B Frame PTS error -> enable swap and pray"<<endl;
+ bTime->copyTo(pTime);
+ }
+
+
+
+ // we display the current picture
+ // (already set)
+ }
+
+
+ if (pic == NULL) {
+ cout << "pic NULL"<<endl;
+ exit(0);
+ return;
+ }
+ if (syncState < SYNC_HAS_FRAME_SYNC) {
+ return;
+ }
+
+ double val=pictureArray->getPicturePerSecond();
+ pic->setPicturePerSecond(val);
+
+ TimeStamp* currentStamp=pic->getStartTimeStamp();
+
+
+ frameCounter++;
+
+ if (currentStamp->getPTSFlag()==true) {
+ frameCounter=0;
+ }
+ currentStamp->setVideoFrameCounter(frameCounter);
+
+
+ // let plugin "rip" the picture
+ pictureArray->setYUVPictureCallback(pic);
+}
+
+
+
+
+
diff --git a/mpeglib/lib/mpegplay/videoDecoder.h b/mpeglib/lib/mpegplay/videoDecoder.h
new file mode 100644
index 00000000..cba45a29
--- /dev/null
+++ b/mpeglib/lib/mpegplay/videoDecoder.h
@@ -0,0 +1,118 @@
+/*
+ mpeg I video decoder (derived from mpeg_play)
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#ifndef __VIDEO_H
+#define __VIDEO_H
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "decoderClass.h"
+#include "recon.h"
+#include "motionVector.h"
+#include "slice.h"
+#include "proto.h"
+#include "../input/inputStream.h"
+#include "../output/outputStream.h"
+#include "../util/timeStamp.h"
+#include "mpegVideoHeader.h"
+#include "gop.h"
+#include "picture.h"
+#include "macroBlock.h"
+#include "startCodes.h"
+
+
+
+/* Define Parsing error codes. */
+
+
+
+#define SYNC_TO_CLOSED_GOP 1
+#define SYNC_HAS_CLOSED_GOP 2
+#define SYNC_HAS_I_FRAME_SYNC 3
+#define SYNC_HAS_P_FRAME_SYNC 4
+#define SYNC_HAS_FRAME_SYNC 5
+
+#define _SYNC_TO_GOP 1
+#define _SYNC_TO_PIC 2
+#define _SYNC_TO_NONE 3
+
+
+
+/* Number of macroblocks to process in one call to mpegVidRsrc. */
+
+#define MB_QUANTUM 100
+
+
+/* Video stream structure. */
+class VideoDecoder {
+
+
+ public:
+ VideoDecoder(MpegVideoStream* mpegVideoStream,
+ MpegVideoHeader* initSequence);
+
+ ~VideoDecoder();
+ int mpegVidRsrc(PictureArray* pictureArray);
+
+
+ // ugly callbacks FIX ME!
+ class MpegVideoStream* mpegVideoStream;
+ class DecoderClass* decoderClass;
+ class Recon* recon;
+ class MotionVector* motionVector;
+ class Slice* slice; /* Current slice. */
+ class MpegVideoHeader* mpegVideoHeader; /* Sequence info in stream */
+ class GOP* group;
+ class Picture* picture; /* Current picture. */
+ class MacroBlock* macroBlock; /* Current macroblock. */
+
+ void resyncToI_Frame();
+
+
+
+ private:
+
+ int syncState;
+
+ int ParseSeqHead();
+ int ParseGOP();
+ int ParsePicture();
+ int ParseSlice();
+ void doPictureDisplay(PictureArray* pictureArray);
+ MpegExtension* extension;
+ int frameCounter;
+
+};
+
+
+
+/* Declaration of global display pointer. */
+
+
+
+extern int qualityFlag;
+
+
+
+
+extern int gXErrorFlag;
+
+
+
+
+#endif /* videoDecoder.h already included */
+
+