diff options
Diffstat (limited to 'mpeglib/lib/mpegplay')
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 */ + + |