summaryrefslogtreecommitdiffstats
path: root/mpeglib/lib
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commite2de64d6f1beb9e492daf5b886e19933c1fa41dd (patch)
tree9047cf9e6b5c43878d5bf82660adae77ceee097a /mpeglib/lib
downloadtdemultimedia-e2de64d6f1beb9e492daf5b886e19933c1fa41dd.tar.gz
tdemultimedia-e2de64d6f1beb9e492daf5b886e19933c1fa41dd.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdemultimedia@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'mpeglib/lib')
-rw-r--r--mpeglib/lib/Makefile.am36
-rw-r--r--mpeglib/lib/README80
-rw-r--r--mpeglib/lib/decoder/Makefile.am39
-rw-r--r--mpeglib/lib/decoder/cddaPlugin.cpp150
-rw-r--r--mpeglib/lib/decoder/cddaPlugin.h49
-rw-r--r--mpeglib/lib/decoder/command.cpp85
-rw-r--r--mpeglib/lib/decoder/command.h52
-rw-r--r--mpeglib/lib/decoder/commandPipe.cpp163
-rw-r--r--mpeglib/lib/decoder/commandPipe.h78
-rw-r--r--mpeglib/lib/decoder/decoderPlugin.cpp428
-rw-r--r--mpeglib/lib/decoder/decoderPlugin.h201
-rw-r--r--mpeglib/lib/decoder/mpegPlugin.cpp160
-rw-r--r--mpeglib/lib/decoder/mpegPlugin.h47
-rw-r--r--mpeglib/lib/decoder/mpgPlugin.cpp260
-rw-r--r--mpeglib/lib/decoder/mpgPlugin.h62
-rw-r--r--mpeglib/lib/decoder/nukePlugin.cpp62
-rw-r--r--mpeglib/lib/decoder/nukePlugin.h34
-rw-r--r--mpeglib/lib/decoder/splayPlugin.cpp308
-rw-r--r--mpeglib/lib/decoder/splayPlugin.h67
-rw-r--r--mpeglib/lib/decoder/tplayPlugin.cpp264
-rw-r--r--mpeglib/lib/decoder/tplayPlugin.h47
-rw-r--r--mpeglib/lib/decoder/vorbisPlugin.cpp305
-rw-r--r--mpeglib/lib/decoder/vorbisPlugin.h87
-rw-r--r--mpeglib/lib/dummy.cpp6
-rw-r--r--mpeglib/lib/frame/IOFrameQueue.cpp60
-rw-r--r--mpeglib/lib/frame/IOFrameQueue.h60
-rw-r--r--mpeglib/lib/frame/Makefile.am33
-rw-r--r--mpeglib/lib/frame/README68
-rw-r--r--mpeglib/lib/frame/audioFrame.cpp111
-rw-r--r--mpeglib/lib/frame/audioFrame.h83
-rw-r--r--mpeglib/lib/frame/audioFrameQueue.cpp339
-rw-r--r--mpeglib/lib/frame/audioFrameQueue.h75
-rw-r--r--mpeglib/lib/frame/floatFrame.cpp50
-rw-r--r--mpeglib/lib/frame/floatFrame.h46
-rw-r--r--mpeglib/lib/frame/frame.cpp73
-rw-r--r--mpeglib/lib/frame/frame.h101
-rw-r--r--mpeglib/lib/frame/frameQueue.cpp101
-rw-r--r--mpeglib/lib/frame/frameQueue.h43
-rw-r--r--mpeglib/lib/frame/framer.cpp241
-rw-r--r--mpeglib/lib/frame/framer.h182
-rw-r--r--mpeglib/lib/frame/pcmFrame.cpp140
-rw-r--r--mpeglib/lib/frame/pcmFrame.h45
-rw-r--r--mpeglib/lib/frame/rawDataBuffer.cpp21
-rw-r--r--mpeglib/lib/frame/rawDataBuffer.h48
-rw-r--r--mpeglib/lib/frame/rawFrame.cpp90
-rw-r--r--mpeglib/lib/frame/rawFrame.h75
-rw-r--r--mpeglib/lib/input/Makefile.am37
-rw-r--r--mpeglib/lib/input/README15
-rw-r--r--mpeglib/lib/input/bufferInputStream.cpp288
-rw-r--r--mpeglib/lib/input/bufferInputStream.h88
-rw-r--r--mpeglib/lib/input/cddaInputStream.cpp225
-rw-r--r--mpeglib/lib/input/cddaInputStream.h85
-rw-r--r--mpeglib/lib/input/cdigrap.cpp100
-rw-r--r--mpeglib/lib/input/cdromAccess.cpp54
-rw-r--r--mpeglib/lib/input/cdromAccess_Empty.cpp47
-rw-r--r--mpeglib/lib/input/cdromAccess_Linux.cpp124
-rw-r--r--mpeglib/lib/input/cdromInputStream.cpp309
-rw-r--r--mpeglib/lib/input/cdromInputStream.h88
-rw-r--r--mpeglib/lib/input/cdromRawAccess.cpp113
-rw-r--r--mpeglib/lib/input/cdromRawAccess.h67
-rw-r--r--mpeglib/lib/input/cdromToc.cpp234
-rw-r--r--mpeglib/lib/input/cdromToc.h65
-rw-r--r--mpeglib/lib/input/fileAccessWrapper.cpp65
-rw-r--r--mpeglib/lib/input/fileAccessWrapper.h41
-rw-r--r--mpeglib/lib/input/fileInputStream.cpp148
-rw-r--r--mpeglib/lib/input/fileInputStream.h46
-rw-r--r--mpeglib/lib/input/httpInputStream.cpp327
-rw-r--r--mpeglib/lib/input/httpInputStream.h84
-rw-r--r--mpeglib/lib/input/inputDetector.cpp192
-rw-r--r--mpeglib/lib/input/inputDetector.h56
-rw-r--r--mpeglib/lib/input/inputPlugin.cpp92
-rw-r--r--mpeglib/lib/input/inputPlugin.h45
-rw-r--r--mpeglib/lib/input/inputStream.cpp135
-rw-r--r--mpeglib/lib/input/inputStream.h79
-rw-r--r--mpeglib/lib/input/simpleRingBuffer.cpp420
-rw-r--r--mpeglib/lib/input/simpleRingBuffer.h136
-rw-r--r--mpeglib/lib/input/threadSafeInputStream.cpp137
-rw-r--r--mpeglib/lib/input/threadSafeInputStream.h56
-rw-r--r--mpeglib/lib/mpegplay/COPYRIGHT145
-rw-r--r--mpeglib/lib/mpegplay/Makefile.am48
-rw-r--r--mpeglib/lib/mpegplay/README26
-rw-r--r--mpeglib/lib/mpegplay/configure.in.in1
-rw-r--r--mpeglib/lib/mpegplay/copyFunctions.cpp330
-rw-r--r--mpeglib/lib/mpegplay/copyFunctions.h95
-rw-r--r--mpeglib/lib/mpegplay/copyFunctions_asm.cpp90
-rw-r--r--mpeglib/lib/mpegplay/copyFunctions_asm.h61
-rw-r--r--mpeglib/lib/mpegplay/copyFunctions_mmx.cpp313
-rw-r--r--mpeglib/lib/mpegplay/copyFunctions_mmx.h68
-rw-r--r--mpeglib/lib/mpegplay/decoderClass.cpp893
-rw-r--r--mpeglib/lib/mpegplay/decoderClass.h96
-rw-r--r--mpeglib/lib/mpegplay/decoderTables.cpp594
-rw-r--r--mpeglib/lib/mpegplay/decoderTables.h110
-rw-r--r--mpeglib/lib/mpegplay/globals.cpp41
-rw-r--r--mpeglib/lib/mpegplay/gop.cpp170
-rw-r--r--mpeglib/lib/mpegplay/gop.h62
-rw-r--r--mpeglib/lib/mpegplay/jrevdct.cpp1690
-rw-r--r--mpeglib/lib/mpegplay/jrevdct.h57
-rw-r--r--mpeglib/lib/mpegplay/macroBlock.cpp1152
-rw-r--r--mpeglib/lib/mpegplay/macroBlock.h97
-rw-r--r--mpeglib/lib/mpegplay/mainMpegPlay.cpp179
-rw-r--r--mpeglib/lib/mpegplay/mmxidct.cpp27
-rw-r--r--mpeglib/lib/mpegplay/mmxidct.h22
-rw-r--r--mpeglib/lib/mpegplay/mmxidct_asm.S738
-rw-r--r--mpeglib/lib/mpegplay/motionVector.cpp130
-rw-r--r--mpeglib/lib/mpegplay/motionVector.h40
-rw-r--r--mpeglib/lib/mpegplay/mpegExtension.cpp258
-rw-r--r--mpeglib/lib/mpegplay/mpegExtension.h49
-rw-r--r--mpeglib/lib/mpegplay/mpegSystemHeader.cpp786
-rw-r--r--mpeglib/lib/mpegplay/mpegSystemHeader.h484
-rw-r--r--mpeglib/lib/mpegplay/mpegSystemStream.cpp235
-rw-r--r--mpeglib/lib/mpegplay/mpegSystemStream.h53
-rw-r--r--mpeglib/lib/mpegplay/mpegVideoBitWindow.cpp258
-rw-r--r--mpeglib/lib/mpegplay/mpegVideoBitWindow.h108
-rw-r--r--mpeglib/lib/mpegplay/mpegVideoHeader.cpp293
-rw-r--r--mpeglib/lib/mpegplay/mpegVideoHeader.h83
-rw-r--r--mpeglib/lib/mpegplay/mpegVideoLength.cpp424
-rw-r--r--mpeglib/lib/mpegplay/mpegVideoLength.h93
-rw-r--r--mpeglib/lib/mpegplay/mpegVideoStream.cpp224
-rw-r--r--mpeglib/lib/mpegplay/mpegVideoStream.h110
-rw-r--r--mpeglib/lib/mpegplay/pesSystemStream.cpp498
-rw-r--r--mpeglib/lib/mpegplay/pesSystemStream.h57
-rw-r--r--mpeglib/lib/mpegplay/picture.cpp149
-rw-r--r--mpeglib/lib/mpegplay/picture.h82
-rw-r--r--mpeglib/lib/mpegplay/proto.h36
-rw-r--r--mpeglib/lib/mpegplay/psSystemStream.cpp163
-rw-r--r--mpeglib/lib/mpegplay/psSystemStream.h57
-rw-r--r--mpeglib/lib/mpegplay/recon.cpp735
-rw-r--r--mpeglib/lib/mpegplay/recon.h55
-rw-r--r--mpeglib/lib/mpegplay/slice.cpp73
-rw-r--r--mpeglib/lib/mpegplay/slice.h48
-rw-r--r--mpeglib/lib/mpegplay/startCodes.h63
-rw-r--r--mpeglib/lib/mpegplay/tsSystemStream.cpp377
-rw-r--r--mpeglib/lib/mpegplay/tsSystemStream.h68
-rw-r--r--mpeglib/lib/mpegplay/videoDecoder.cpp476
-rw-r--r--mpeglib/lib/mpegplay/videoDecoder.h118
-rw-r--r--mpeglib/lib/mpgplayer/Makefile.am31
-rw-r--r--mpeglib/lib/mpgplayer/mpegStreamPlayer.cpp431
-rw-r--r--mpeglib/lib/mpgplayer/mpegStreamPlayer.h90
-rw-r--r--mpeglib/lib/oggvorbis/Makefile.am32
-rw-r--r--mpeglib/lib/oggvorbis/oggFrame.cpp29
-rw-r--r--mpeglib/lib/oggvorbis/oggFrame.h50
-rw-r--r--mpeglib/lib/oggvorbis/ovFramer.cpp128
-rw-r--r--mpeglib/lib/oggvorbis/ovFramer.h69
-rw-r--r--mpeglib/lib/oggvorbis/vorbisDecoder.cpp135
-rw-r--r--mpeglib/lib/oggvorbis/vorbisDecoder.h53
-rw-r--r--mpeglib/lib/oggvorbis/vorbisInfo.cpp150
-rw-r--r--mpeglib/lib/oggvorbis/vorbisInfo.h76
-rw-r--r--mpeglib/lib/output/Makefile.am52
-rw-r--r--mpeglib/lib/output/artsOutputStream.cpp205
-rw-r--r--mpeglib/lib/output/artsOutputStream.h123
-rw-r--r--mpeglib/lib/output/audioData.cpp100
-rw-r--r--mpeglib/lib/output/audioData.h71
-rw-r--r--mpeglib/lib/output/audioDataArray.cpp138
-rw-r--r--mpeglib/lib/output/audioDataArray.h55
-rw-r--r--mpeglib/lib/output/audioTime.cpp154
-rw-r--r--mpeglib/lib/output/audioTime.h68
-rw-r--r--mpeglib/lib/output/avSyncer.cpp386
-rw-r--r--mpeglib/lib/output/avSyncer.h96
-rw-r--r--mpeglib/lib/output/dspX11OutputStream.cpp236
-rw-r--r--mpeglib/lib/output/dspX11OutputStream.h89
-rw-r--r--mpeglib/lib/output/outPlugin.cpp71
-rw-r--r--mpeglib/lib/output/outPlugin.h44
-rw-r--r--mpeglib/lib/output/outputStream.cpp238
-rw-r--r--mpeglib/lib/output/outputStream.h151
-rw-r--r--mpeglib/lib/output/performance.cpp50
-rw-r--r--mpeglib/lib/output/performance.h34
-rw-r--r--mpeglib/lib/output/pluginInfo.cpp65
-rw-r--r--mpeglib/lib/output/pluginInfo.h48
-rw-r--r--mpeglib/lib/output/threadSafeOutputStream.cpp153
-rw-r--r--mpeglib/lib/output/threadSafeOutputStream.h67
-rw-r--r--mpeglib/lib/output/windowOut.cpp64
-rw-r--r--mpeglib/lib/output/windowOut.h53
-rw-r--r--mpeglib/lib/output/yuvDumper.cpp81
-rw-r--r--mpeglib/lib/output/yuvDumper.h51
-rw-r--r--mpeglib/lib/splay/Makefile.am53
-rw-r--r--mpeglib/lib/splay/attribute.h33
-rw-r--r--mpeglib/lib/splay/common.h60
-rw-r--r--mpeglib/lib/splay/dct.h33
-rw-r--r--mpeglib/lib/splay/dct36_12.cpp288
-rw-r--r--mpeglib/lib/splay/dct64.cpp202
-rw-r--r--mpeglib/lib/splay/dct64_down.cpp215
-rw-r--r--mpeglib/lib/splay/dump.cpp157
-rw-r--r--mpeglib/lib/splay/dump.h36
-rw-r--r--mpeglib/lib/splay/dxHead.cpp129
-rw-r--r--mpeglib/lib/splay/dxHead.h66
-rw-r--r--mpeglib/lib/splay/huffmanlookup.cpp120
-rw-r--r--mpeglib/lib/splay/huffmanlookup.h57
-rw-r--r--mpeglib/lib/splay/huffmantable.cpp584
-rw-r--r--mpeglib/lib/splay/mpeg2tables.h432
-rw-r--r--mpeglib/lib/splay/mpegAudioBitWindow.cpp41
-rw-r--r--mpeglib/lib/splay/mpegAudioBitWindow.h141
-rw-r--r--mpeglib/lib/splay/mpegAudioFrame.cpp200
-rw-r--r--mpeglib/lib/splay/mpegAudioFrame.h66
-rw-r--r--mpeglib/lib/splay/mpegAudioHeader.cpp268
-rw-r--r--mpeglib/lib/splay/mpegAudioHeader.h101
-rw-r--r--mpeglib/lib/splay/mpegAudioInfo.cpp262
-rw-r--r--mpeglib/lib/splay/mpegAudioInfo.h95
-rw-r--r--mpeglib/lib/splay/mpegAudioStream.cpp43
-rw-r--r--mpeglib/lib/splay/mpegAudioStream.h139
-rw-r--r--mpeglib/lib/splay/mpeglayer1.cpp109
-rw-r--r--mpeglib/lib/splay/mpeglayer2.cpp449
-rw-r--r--mpeglib/lib/splay/mpeglayer3.cpp1761
-rw-r--r--mpeglib/lib/splay/mpegsound.h248
-rw-r--r--mpeglib/lib/splay/mpegtable.cpp35
-rw-r--r--mpeglib/lib/splay/mpegtoraw.cpp127
-rw-r--r--mpeglib/lib/splay/op.h96
-rw-r--r--mpeglib/lib/splay/sigsev.c29
-rw-r--r--mpeglib/lib/splay/splayDecoder.cpp73
-rw-r--r--mpeglib/lib/splay/splayDecoder.h70
-rw-r--r--mpeglib/lib/splay/synth_Down.cpp231
-rw-r--r--mpeglib/lib/splay/synth_Std.cpp330
-rw-r--r--mpeglib/lib/splay/synth_filter.cpp147
-rw-r--r--mpeglib/lib/splay/synthesis.cpp73
-rw-r--r--mpeglib/lib/splay/synthesis.h95
-rw-r--r--mpeglib/lib/splay/window.cpp70
-rw-r--r--mpeglib/lib/tplay/CHANGES154
-rw-r--r--mpeglib/lib/tplay/Makefile.am15
-rw-r--r--mpeglib/lib/tplay/README95
-rw-r--r--mpeglib/lib/tplay/au.cpp100
-rw-r--r--mpeglib/lib/tplay/tplayfunctions.cpp84
-rw-r--r--mpeglib/lib/tplay/tplayfunctions.h128
-rw-r--r--mpeglib/lib/tplay/wav.cpp91
-rw-r--r--mpeglib/lib/util/Makefile.am61
-rw-r--r--mpeglib/lib/util/abstract/Makefile.am14
-rw-r--r--mpeglib/lib/util/abstract/abs_thread.h123
-rw-r--r--mpeglib/lib/util/abstract/abs_thread_sdl.cpp89
-rw-r--r--mpeglib/lib/util/abstract/threadQueue.cpp108
-rw-r--r--mpeglib/lib/util/abstract/threadQueue.h74
-rw-r--r--mpeglib/lib/util/audio/Makefile.am18
-rw-r--r--mpeglib/lib/util/audio/audioIO.cpp49
-rw-r--r--mpeglib/lib/util/audio/audioIO.h80
-rw-r--r--mpeglib/lib/util/audio/audioIO_AIX.cpp533
-rw-r--r--mpeglib/lib/util/audio/audioIO_BeOS.cpp227
-rw-r--r--mpeglib/lib/util/audio/audioIO_HPUX.cpp190
-rw-r--r--mpeglib/lib/util/audio/audioIO_IRIX.cpp157
-rw-r--r--mpeglib/lib/util/audio/audioIO_Linux.cpp220
-rw-r--r--mpeglib/lib/util/audio/audioIO_SDL.cpp164
-rw-r--r--mpeglib/lib/util/audio/audioIO_SunOS.cpp167
-rw-r--r--mpeglib/lib/util/audio/dspWrapper.cpp193
-rw-r--r--mpeglib/lib/util/audio/dspWrapper.h75
-rw-r--r--mpeglib/lib/util/dynBuffer.cpp166
-rw-r--r--mpeglib/lib/util/dynBuffer.h63
-rw-r--r--mpeglib/lib/util/file/Makefile.am25
-rw-r--r--mpeglib/lib/util/file/fileAccess.cpp95
-rw-r--r--mpeglib/lib/util/file/fileAccess.h46
-rw-r--r--mpeglib/lib/util/mmx/Makefile.am46
-rw-r--r--mpeglib/lib/util/mmx/attribute.h33
-rw-r--r--mpeglib/lib/util/mmx/cpu_accel.c162
-rw-r--r--mpeglib/lib/util/mmx/mm_accel.h58
-rw-r--r--mpeglib/lib/util/mmx/mmx.c73
-rw-r--r--mpeglib/lib/util/mmx/mmx.h26
-rw-r--r--mpeglib/lib/util/mmx/mmx_asm.h258
-rw-r--r--mpeglib/lib/util/render/Makefile.am59
-rw-r--r--mpeglib/lib/util/render/dither/Makefile.am40
-rw-r--r--mpeglib/lib/util/render/dither/colorTable8Bit.cpp147
-rw-r--r--mpeglib/lib/util/render/dither/colorTable8Bit.h57
-rw-r--r--mpeglib/lib/util/render/dither/colorTableHighBit.cpp248
-rw-r--r--mpeglib/lib/util/render/dither/colorTableHighBit.h73
-rw-r--r--mpeglib/lib/util/render/dither/dither16Bit.cpp300
-rw-r--r--mpeglib/lib/util/render/dither/dither16Bit.h55
-rw-r--r--mpeglib/lib/util/render/dither/dither32Bit.cpp253
-rw-r--r--mpeglib/lib/util/render/dither/dither32Bit.h55
-rw-r--r--mpeglib/lib/util/render/dither/dither32mmx.cpp272
-rw-r--r--mpeglib/lib/util/render/dither/dither8Bit.cpp306
-rw-r--r--mpeglib/lib/util/render/dither/dither8Bit.h63
-rw-r--r--mpeglib/lib/util/render/dither/ditherDef.h100
-rw-r--r--mpeglib/lib/util/render/dither/ditherMMX.h38
-rw-r--r--mpeglib/lib/util/render/dither/ditherRGB.cpp230
-rw-r--r--mpeglib/lib/util/render/dither/ditherRGB.h45
-rw-r--r--mpeglib/lib/util/render/dither/ditherRGB_flipped.cpp82
-rw-r--r--mpeglib/lib/util/render/dither/ditherRGB_flipped.h34
-rw-r--r--mpeglib/lib/util/render/dither/ditherWrapper.cpp246
-rw-r--r--mpeglib/lib/util/render/dither/ditherWrapper.h80
-rw-r--r--mpeglib/lib/util/render/dither/ditherer_mmx16.cpp256
-rw-r--r--mpeglib/lib/util/render/dither2YUV/Makefile.am22
-rw-r--r--mpeglib/lib/util/render/dither2YUV/README13
-rw-r--r--mpeglib/lib/util/render/dither2YUV/dither2YUV.cpp124
-rw-r--r--mpeglib/lib/util/render/dither2YUV/dither2YUV.h64
-rw-r--r--mpeglib/lib/util/render/dither2YUV/rgb2yuv16.cpp916
-rw-r--r--mpeglib/lib/util/render/dither2YUV/rgb2yuv16.h74
-rw-r--r--mpeglib/lib/util/render/dither2YUV/rgb2yuv32.cpp1143
-rw-r--r--mpeglib/lib/util/render/dither2YUV/rgb2yuv32.h93
-rw-r--r--mpeglib/lib/util/render/dither2YUV/rgb2yuvdefs.h74
-rw-r--r--mpeglib/lib/util/render/imageBase.cpp76
-rw-r--r--mpeglib/lib/util/render/imageBase.h140
-rw-r--r--mpeglib/lib/util/render/pictureArray.cpp101
-rw-r--r--mpeglib/lib/util/render/pictureArray.h76
-rw-r--r--mpeglib/lib/util/render/renderMachine.cpp205
-rw-r--r--mpeglib/lib/util/render/renderMachine.h90
-rw-r--r--mpeglib/lib/util/render/sdl/Makefile.am43
-rw-r--r--mpeglib/lib/util/render/sdl/imageDeskSDL.cpp110
-rw-r--r--mpeglib/lib/util/render/sdl/imageDeskSDL.h65
-rw-r--r--mpeglib/lib/util/render/sdl/sdlSurface.cpp219
-rw-r--r--mpeglib/lib/util/render/sdl/sdlSurface.h78
-rw-r--r--mpeglib/lib/util/render/surface.cpp117
-rw-r--r--mpeglib/lib/util/render/surface.h55
-rw-r--r--mpeglib/lib/util/render/x11/Makefile.am48
-rw-r--r--mpeglib/lib/util/render/x11/imageDGAFull.cpp289
-rw-r--r--mpeglib/lib/util/render/x11/imageDGAFull.h131
-rw-r--r--mpeglib/lib/util/render/x11/imageDeskX11.cpp439
-rw-r--r--mpeglib/lib/util/render/x11/imageDeskX11.h85
-rw-r--r--mpeglib/lib/util/render/x11/imageXVDesk.cpp405
-rw-r--r--mpeglib/lib/util/render/x11/imageXVDesk.h88
-rw-r--r--mpeglib/lib/util/render/x11/initDisplay.cpp255
-rw-r--r--mpeglib/lib/util/render/x11/initDisplay.h34
-rw-r--r--mpeglib/lib/util/render/x11/x11Surface.cpp389
-rw-r--r--mpeglib/lib/util/render/x11/x11Surface.h79
-rw-r--r--mpeglib/lib/util/render/x11/xinit.h99
-rw-r--r--mpeglib/lib/util/render/yuvPicture.cpp253
-rw-r--r--mpeglib/lib/util/render/yuvPicture.h110
-rw-r--r--mpeglib/lib/util/syncClock.cpp59
-rw-r--r--mpeglib/lib/util/syncClock.h61
-rw-r--r--mpeglib/lib/util/syncClockMPEG.cpp221
-rw-r--r--mpeglib/lib/util/syncClockMPEG.h77
-rw-r--r--mpeglib/lib/util/timeStamp.cpp273
-rw-r--r--mpeglib/lib/util/timeStamp.h92
-rw-r--r--mpeglib/lib/util/timeStampArray.cpp178
-rw-r--r--mpeglib/lib/util/timeStampArray.h85
-rw-r--r--mpeglib/lib/util/timeWrapper.cpp77
-rw-r--r--mpeglib/lib/util/timeWrapper.h44
-rw-r--r--mpeglib/lib/yuv/Makefile.am28
-rw-r--r--mpeglib/lib/yuv/yuvPlugin.cpp158
-rw-r--r--mpeglib/lib/yuv/yuvPlugin.h47
323 files changed, 50223 insertions, 0 deletions
diff --git a/mpeglib/lib/Makefile.am b/mpeglib/lib/Makefile.am
new file mode 100644
index 00000000..74a7d181
--- /dev/null
+++ b/mpeglib/lib/Makefile.am
@@ -0,0 +1,36 @@
+# player - Makefile.am
+
+SUBDIRS = frame util input output decoder \
+ splay oggvorbis mpegplay mpgplayer tplay yuv
+
+MMXFILES =
+
+
+EXTRA_DIST = README
+
+
+THIS_EXTRALIBS = mpgplayer/libmpgplayer.la \
+ mpegplay/libmpegplay.la \
+ splay/libsplay.la \
+ oggvorbis/liboggvorbisbase.la \
+ tplay/libtplay.la \
+ decoder/libdecoder.la \
+ output/liboutput.la \
+ input/libinput.la \
+ util/libutil.la \
+ frame/libframe.la \
+ yuv/libyuvPlugin.la
+
+
+
+lib_LTLIBRARIES = libmpeg.la
+
+libmpeg_la_SOURCES = dummy.cpp
+
+
+libmpeg_la_LDFLAGS = $(all_libraries) \
+ -release $(THIS_LIB_VERSION)
+
+
+libmpeg_la_LIBADD = $(THIS_EXTRALIBS) $(MMXFILES) \
+ $(THIS_LIB_LIBS)
diff --git a/mpeglib/lib/README b/mpeglib/lib/README
new file mode 100644
index 00000000..91a3b071
--- /dev/null
+++ b/mpeglib/lib/README
@@ -0,0 +1,80 @@
+
+
+HOW TO WRITE A PLUGIN
+=====================
+
+we need a audio cd player and a grabber and <insert your cool plugin here>
+The Plugin approach is minimalistic.
+
+The plugin interface only supports one thing:
+
+* open a stream play it and then close it.
+
+nothing more.
+
+
+For this you have a class "decoderPlugin.cpp" derive your decoder
+from this class and then overwrite the decoder_loop method.
+Thats it.
+
+The typical structure in decoder loop look like this:
+
+void decoder_loop() {
+
+1. make instance of decoder and connect it to the input/output
+2. go in loop and check sometime a few mutex variables
+3. leave loop and destroy your decoder
+
+}
+
+For this your have 3 examples how it can be done.
+I think splayPlugin.cpp and mpegPlugin.cpp are clean/good
+examples for "education".
+
+
+If your decoder supports "seek" you are a bit on your own.
+You can look in splayPlugin.cpp how it is handled there.
+If your decoder supports seek you must overwrite the seek method.
+
+Ok, now you have your raw plugin.
+If you want to make it a real KDE compliant player with arts integration
+you need to write an arts plugin.
+
+
+
+further readings
+======================
+
+* This interface doesn´t offer a gui based config dialog
+
+ To my mind a configuration dialog does not belong into a decoder plugin.
+ And that´s the main reason why other solutions are not portable:
+ The plugin interface depend on a widget lib.
+
+
+* This version has a completely reworked plugin interface.
+ I removed the C bindings. And now the interface is C++.
+ This made it much more readable.
+ This should make it a bit easier to inlcude new decoders.
+ For example look in the directories for mainXYZ.cpp
+
+inputPlugin:
+ inputInterfaces like file,http,buffered(loopback) ,cdi
+outPlugin :
+ output for audio/video
+playerPlugin:
+ this is the base class fo new decoders
+splay :
+ mpeg I Layer 1,2,3 audio decoder
+mpegplay :
+ mpeg I video decoder
+mpgplayer :
+ mpeg I audio/video decoder
+tplay :
+ wav decoder
+vorbisPlugin:
+ vorbis decoder.(GPLed mp3 replacement, better compression,
+ better sound ->www.xiph.org)
+
+
+ \ No newline at end of file
diff --git a/mpeglib/lib/decoder/Makefile.am b/mpeglib/lib/decoder/Makefile.am
new file mode 100644
index 00000000..9362e851
--- /dev/null
+++ b/mpeglib/lib/decoder/Makefile.am
@@ -0,0 +1,39 @@
+# libplayerplugin - Makefile.am
+
+INCLUDES = $(all_includes)
+
+noinst_LTLIBRARIES = libdecoder.la
+
+kmpgincludedir = $(includedir)/$(THIS_LIB_NAME)/decoder
+
+kmpginclude_HEADERS = decoderPlugin.h command.h \
+ commandPipe.h nukePlugin.h \
+ vorbisPlugin.h cddaPlugin.h \
+ splayPlugin.h mpegPlugin.h \
+ mpgPlugin.h tplayPlugin.h
+
+libdecoder_la_SOURCES = decoderPlugin.cpp command.cpp \
+ commandPipe.cpp nukePlugin.cpp \
+ vorbisPlugin.cpp cddaPlugin.cpp \
+ splayPlugin.cpp mpegPlugin.cpp \
+ mpgPlugin.cpp tplayPlugin.cpp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/decoder/cddaPlugin.cpp b/mpeglib/lib/decoder/cddaPlugin.cpp
new file mode 100644
index 00000000..fe84986b
--- /dev/null
+++ b/mpeglib/lib/decoder/cddaPlugin.cpp
@@ -0,0 +1,150 @@
+/*
+ splay 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 "cddaPlugin.h"
+
+#ifdef CDDA_PARANOIA
+
+#include <sys/types.h>
+
+#include <iostream>
+
+using namespace std;
+
+typedef int16_t size16;
+typedef int32_t size32;
+
+extern "C" {
+#include <cdda_interface.h>
+#include <cdda_paranoia.h>
+}
+
+
+CDDAPlugin::CDDAPlugin() {
+}
+
+
+CDDAPlugin::~CDDAPlugin() {
+}
+
+
+// here we can config our decoder with special flags
+void CDDAPlugin::config(const char* key,const char* value,void* user_data) {
+ DecoderPlugin::config(key,value,user_data);
+}
+
+
+
+void CDDAPlugin::decoder_loop() {
+
+ if (input == NULL) {
+ cout << "CDDAPlugin::decoder_loop input is NULL"<<endl;
+ exit(0);
+ }
+ if (output == NULL) {
+ cout << "CDDAPlugin::decoder_loop output is NULL"<<endl;
+ exit(0);
+ }
+ // init decoder
+ output->audioInit();
+ TimeStamp* stamp;
+ char buf[CD_FRAMESIZE_RAW*4];
+ int len=0;
+ // start decoding
+ while(runCheck()) {
+
+ switch(streamState) {
+ case _STREAM_STATE_FIRST_INIT :
+ output->audioSetup(44100,1,0,0,16);
+ output->audioOpen();
+ setStreamState(_STREAM_STATE_PLAY);
+ len=getTotalLength();
+ pluginInfo->setLength(len);
+ output->writeInfo(pluginInfo);
+ break;
+ case _STREAM_STATE_INIT :
+ setStreamState(_STREAM_STATE_PLAY);
+ break;
+ case _STREAM_STATE_PLAY : {
+ // decode
+ int read=input->read(buf,2*CD_FRAMESIZE_RAW);
+ int pos=input->getBytePosition();
+ stamp=input->getTimeStamp(pos);
+ output->audioPlay(stamp,stamp,buf,read);
+ break;
+ }
+ case _STREAM_STATE_WAIT_FOR_END:
+ // exit while loop
+ lDecoderLoop=false;
+ break;
+ default:
+ cout << "unknown stream state:"<<streamState<<endl;
+ }
+ }
+ // remove decoder
+
+ output->audioFlush();
+}
+
+// splay can seek in streams
+int CDDAPlugin::seek_impl(int second) {
+ int bytes_per_second;
+ int seconds;
+ int back;
+ float frequence=44100;
+ int bits=16;
+ int channels=2;
+
+ bytes_per_second = (int)(frequence * channels * (bits / 8));
+
+
+
+ seconds = bytes_per_second * second;
+ cout << "seek to :"<<seconds<<endl;
+ back=input->seek(seconds);
+
+ return true;
+}
+
+
+int CDDAPlugin::getTotalLength() {
+ shutdownLock();
+ float wavfilesize;
+ int back=0;
+ float frequence=44100;
+ if (input == NULL) {
+ shutdownUnlock();
+ return 0;
+ }
+ wavfilesize = input->getByteLength();
+ int bits=16;
+ int channels=2;
+ if (bits == 16) {
+ wavfilesize=wavfilesize/2;
+ }
+ if (channels==2) {
+ wavfilesize=wavfilesize/2;
+ }
+ if (frequence != 0) {
+ back=(int)(wavfilesize/frequence);
+ }
+ shutdownUnlock();
+ return back;
+}
+
+
+
+
+#endif
+//CDDA_PARANOIA
+
diff --git a/mpeglib/lib/decoder/cddaPlugin.h b/mpeglib/lib/decoder/cddaPlugin.h
new file mode 100644
index 00000000..c0adf5e2
--- /dev/null
+++ b/mpeglib/lib/decoder/cddaPlugin.h
@@ -0,0 +1,49 @@
+/*
+ splay 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 __CDDAPLUGIN_H
+#define __CDDAPLUGIN_H
+
+#include "nukePlugin.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef CDDA_PARANOIA
+class CDDAPlugin : public NukePlugin {
+};
+#else
+
+
+
+class CDDAPlugin : public DecoderPlugin {
+
+ public:
+ CDDAPlugin();
+ ~CDDAPlugin();
+
+ void decoder_loop();
+ int seek_impl(int second);
+ void config(const char* key,const char* value,void* user_data);
+
+ protected:
+ int getTotalLength();
+
+
+};
+
+#endif
+//CDDA_PARANOIA
+
+#endif
diff --git a/mpeglib/lib/decoder/command.cpp b/mpeglib/lib/decoder/command.cpp
new file mode 100644
index 00000000..8b29efe6
--- /dev/null
+++ b/mpeglib/lib/decoder/command.cpp
@@ -0,0 +1,85 @@
+/*
+ describes a command
+ 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 "command.h"
+
+#include <iostream>
+
+using namespace std;
+
+Command::Command(int id) {
+ this->id=id;
+ this->intArg=0;
+}
+
+Command::Command(int id,int arg) {
+ this->id=id;
+ this->intArg=arg;
+}
+
+
+Command::~Command() {
+}
+
+
+int Command::getID() {
+ return id;
+}
+
+
+int Command::getIntArg() {
+ return intArg;
+}
+
+
+void Command::copyTo(Command* dest) {
+ dest->id=this->id;
+ dest->intArg=this->intArg;
+}
+
+void Command::print(const char* text) {
+ cout << "COMMAND:"<<text<<endl;
+ switch(id) {
+ case _COMMAND_NONE:
+ cout << "_COMMAND_NONE";
+ break;
+ case _COMMAND_PING:
+ cout << "_COMMAND_PING";
+ break;
+ case _COMMAND_PAUSE:
+ cout << "_COMMAND_PAUSE";
+ break;
+ case _COMMAND_PLAY:
+ cout << "_COMMAND_PLAY";
+ break;
+ case _COMMAND_SEEK:
+ cout << "_COMMAND_SEEK";
+ cout << " intArg:"<<intArg;
+ break;
+ case _COMMAND_CLOSE:
+ cout << "_COMMAND_CLOSE";
+ break;
+ case _COMMAND_START:
+ cout << "_COMMAND_START";
+ break;
+ case _COMMAND_RESYNC_START:
+ cout << "_COMMAND_RESYNC_START";
+ break;
+ case _COMMAND_RESYNC_END:
+ cout << "_COMMAND_RESYNC_END";
+ break;
+
+ default:
+ cout << "unknown command id in Command::print"<<endl;
+ }
+ cout << endl;
+}
diff --git a/mpeglib/lib/decoder/command.h b/mpeglib/lib/decoder/command.h
new file mode 100644
index 00000000..fc96fd73
--- /dev/null
+++ b/mpeglib/lib/decoder/command.h
@@ -0,0 +1,52 @@
+/*
+ describes a command
+ 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 __COMMAND_H
+#define __COMMAND_H
+
+#include "../util/abstract/abs_thread.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define _COMMAND_NONE 0
+#define _COMMAND_PLAY 1
+#define _COMMAND_PAUSE 2
+#define _COMMAND_SEEK 3
+#define _COMMAND_CLOSE 4
+#define _COMMAND_START 5
+#define _COMMAND_RESYNC_START 6
+#define _COMMAND_RESYNC_END 7
+#define _COMMAND_PING 8
+
+
+
+class Command {
+
+ int id;
+ int intArg;
+
+ public:
+ Command(int id);
+ Command(int id,int arg);
+ ~Command();
+
+ int getID();
+ int getIntArg();
+ void copyTo(Command* dest);
+ void print(const char* text);
+};
+
+#endif
diff --git a/mpeglib/lib/decoder/commandPipe.cpp b/mpeglib/lib/decoder/commandPipe.cpp
new file mode 100644
index 00000000..05991ca5
--- /dev/null
+++ b/mpeglib/lib/decoder/commandPipe.cpp
@@ -0,0 +1,163 @@
+/*
+ thread safe fifo queue for commands
+ 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 "commandPipe.h"
+
+#define _COMMAND_ARRAY_SIZE 100
+
+CommandPipe::CommandPipe() {
+ abs_thread_cond_init(&spaceCond);
+ abs_thread_cond_init(&emptyCond);
+ abs_thread_cond_init(&dataCond);
+ abs_thread_mutex_init(&pipeMut);
+
+ entries=0;
+ readPos=0;
+ writePos=0;
+
+
+ int i;
+
+ commandArray=new Command*[_COMMAND_ARRAY_SIZE];
+
+
+ for(i=0;i<_COMMAND_ARRAY_SIZE;i++) {
+ commandArray[i]=new Command(_COMMAND_NONE,0);
+ }
+}
+
+
+CommandPipe::~CommandPipe() {
+ abs_thread_cond_destroy(&spaceCond);
+ abs_thread_cond_destroy(&emptyCond);
+ abs_thread_cond_destroy(&dataCond);
+ abs_thread_mutex_destroy(&pipeMut);
+
+
+ int i;
+
+ for(i=0;i<_COMMAND_ARRAY_SIZE;i++) {
+ delete commandArray[i];
+ }
+ delete [] commandArray;
+}
+
+void CommandPipe::sendCommand(Command& cmd) {
+ sendCommand(cmd,true);
+}
+
+void CommandPipe::sendCommandNoWait(Command& cmd) {
+ sendCommand(cmd,false);
+}
+
+
+void CommandPipe::sendCommand(Command& cmd,int lWait) {
+ lockCommandPipe();
+ if (entries==_COMMAND_ARRAY_SIZE) {
+ waitForSpace();
+ }
+ cmd.copyTo(commandArray[writePos]);
+ writePos++;
+ if (writePos==_COMMAND_ARRAY_SIZE) {
+ writePos=0;
+ }
+ entries++;
+ // low water signal
+ if (entries==1) {
+ signalData();
+ }
+ unlockCommandPipe();
+ if (lWait) {
+ waitForEmptyQueue();
+ }
+}
+
+
+int CommandPipe::hasCommand(Command* dest) {
+ lockCommandPipe();
+ if (entries==0) {
+ unlockCommandPipe();
+ return false;
+ }
+
+ commandArray[readPos]->copyTo(dest);
+ readPos++;
+ if (readPos==_COMMAND_ARRAY_SIZE) {
+ readPos=0;
+ }
+ entries--;
+ // low water
+ if (entries==0) {
+ signalEmpty();
+ unlockCommandPipe();
+ return true;
+ }
+ // if we are on highwater, signal space
+ if (entries==_COMMAND_ARRAY_SIZE-1) {
+ signalSpace();
+ }
+ unlockCommandPipe();
+ return true;
+}
+
+
+void CommandPipe::waitForEmptyQueue() {
+ lockCommandPipe();
+ while (entries > 0) {
+ waitForEmpty();
+ }
+ unlockCommandPipe();
+}
+
+void CommandPipe::waitForCommand() {
+ lockCommandPipe();
+ while (entries == 0) {
+ waitForData();
+ }
+ unlockCommandPipe();
+}
+
+
+void CommandPipe::lockCommandPipe() {
+ abs_thread_mutex_lock(&pipeMut);
+}
+
+
+void CommandPipe::unlockCommandPipe() {
+ abs_thread_mutex_unlock(&pipeMut);
+}
+
+void CommandPipe::waitForSpace() {
+ abs_thread_cond_wait(&spaceCond,&pipeMut);
+}
+
+void CommandPipe::waitForEmpty() {
+ abs_thread_cond_wait(&emptyCond,&pipeMut);
+}
+
+void CommandPipe::waitForData() {
+ abs_thread_cond_wait(&dataCond,&pipeMut);
+}
+
+
+void CommandPipe::signalSpace() {
+ abs_thread_cond_signal(&spaceCond);
+}
+
+void CommandPipe::signalEmpty() {
+ abs_thread_cond_signal(&emptyCond);
+}
+
+void CommandPipe::signalData() {
+ abs_thread_cond_signal(&dataCond);
+}
diff --git a/mpeglib/lib/decoder/commandPipe.h b/mpeglib/lib/decoder/commandPipe.h
new file mode 100644
index 00000000..4ecf84eb
--- /dev/null
+++ b/mpeglib/lib/decoder/commandPipe.h
@@ -0,0 +1,78 @@
+/*
+ thread safe fifo queue for commands
+ 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 __COMMAND_PIPE_H
+#define __COMMAND_PIPE_H
+
+
+
+#include "command.h"
+
+/**
+ This queue deals with the ugly deadlock problem.
+ We insert all commands in a queue and the thread
+ polls this queue for next commands.
+*/
+
+class CommandPipe {
+
+ Command** commandArray;
+ int entries;
+ int readPos;
+ int writePos;
+
+ abs_thread_mutex_t pipeMut;
+ abs_thread_cond_t spaceCond;
+ abs_thread_cond_t emptyCond;
+ abs_thread_cond_t dataCond;
+
+ public:
+ CommandPipe();
+ ~CommandPipe();
+
+ // writer thread:
+ void sendCommand(Command& cmd);
+ void sendCommandNoWait(Command& cmd);
+
+ void waitForEmptyQueue();
+
+ // reader thread
+ int hasCommand(Command* dest);
+ void waitForCommand();
+
+
+
+
+ private:
+ void sendCommand(Command& cmd,int lWait);
+
+ void lockCommandPipe();
+ void unlockCommandPipe();
+
+
+ // writer thread wait here
+ void waitForSpace();
+ void waitForEmpty();
+ void waitForData();
+
+ // reader thread signals this
+ void signalSpace();
+ void signalEmpty();
+ void signalData();
+
+
+
+
+};
+
+#endif
diff --git a/mpeglib/lib/decoder/decoderPlugin.cpp b/mpeglib/lib/decoder/decoderPlugin.cpp
new file mode 100644
index 00000000..0a45bb42
--- /dev/null
+++ b/mpeglib/lib/decoder/decoderPlugin.cpp
@@ -0,0 +1,428 @@
+/*
+ base class for the 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 "decoderPlugin.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+static void *playerThread(void *arg){
+ ((DecoderPlugin*)arg)->idleThread();
+ return NULL;
+}
+
+static int instanceCnt=0;
+
+DecoderPlugin::DecoderPlugin(){
+ input=NULL;
+ output=NULL;
+ commandPipe=new CommandPipe();
+ threadCommand=new Command(_COMMAND_NONE);
+ abs_thread_cond_init(&streamStateCond);
+ abs_thread_mutex_init(&streamStateMut);
+ abs_thread_mutex_init(&shutdownMut);
+
+ lCreatorLoop=true;
+ lDecoderLoop=false;
+ linDecoderLoop=false;
+ streamState=_STREAM_STATE_EOF;
+ lDecode=false;
+ lhasLength=false;
+ // this default is necessary. if you have a blocking
+ // device and we start automatic the thread
+ // may block on it and all commands (including play)
+ // blocks everything
+ // *you should not use autoplay*
+ lAutoPlay=false;
+
+ pluginInfo=new PluginInfo();
+ runCheck_Counter=0;
+ decode_loopCounter=0;
+ instance=instanceCnt;
+ instanceCnt++;
+ abs_thread_create(&tr,playerThread,this);
+
+ // we send a ping. because this signal is synchron
+ // we block until the thread is started and
+ // has read the ping singnal
+ Command cmd(_COMMAND_PING);
+ insertSyncCommand(&cmd);
+
+
+}
+
+
+DecoderPlugin::~DecoderPlugin(){
+ void* ret;
+ lCreatorLoop=false;
+ Command cmd(_COMMAND_CLOSE);
+ insertAsyncCommand(&cmd);
+
+ abs_thread_join(tr,&ret);
+
+ abs_thread_cond_destroy(&streamStateCond);
+ abs_thread_mutex_destroy(&streamStateMut);
+ abs_thread_mutex_destroy(&shutdownMut);
+
+ delete commandPipe;
+ delete threadCommand;
+ delete pluginInfo;
+}
+
+
+void DecoderPlugin::close(){
+ // from here we can only walk to init or eof
+ // in both cases we sometimes catch out decoderMut :-)
+ Command cmd(_COMMAND_CLOSE);
+ insertAsyncCommand(&cmd);
+ shutdownLock();
+ if (input != NULL) {
+ input->close();
+ }
+ shutdownUnlock();
+ insertSyncCommand(&cmd);
+ waitForStreamState(_STREAM_STATE_EOF);
+ input=NULL;
+}
+
+
+void DecoderPlugin::pause() {
+ Command cmd(_COMMAND_PAUSE);
+ insertSyncCommand(&cmd);
+}
+
+
+
+
+int DecoderPlugin::play() {
+ Command cmd(_COMMAND_PLAY);
+ insertSyncCommand(&cmd);
+
+ return true;
+}
+
+int DecoderPlugin::seek(int second) {
+ Command cmd(_COMMAND_SEEK,second);
+ insertSyncCommand(&cmd);
+
+ return true;
+}
+
+void DecoderPlugin::insertAsyncCommand(Command* cmd) {
+ commandPipe->sendCommandNoWait(*cmd);
+}
+
+void DecoderPlugin::insertSyncCommand(Command* cmd) {
+ commandPipe->sendCommand(*cmd);
+}
+
+
+void DecoderPlugin::shutdownLock() {
+ abs_thread_mutex_lock(&shutdownMut);
+}
+
+
+void DecoderPlugin::shutdownUnlock() {
+ abs_thread_mutex_unlock(&shutdownMut);
+}
+
+int DecoderPlugin::getTime(int lCurrent) {
+ int secLen=getTotalLength();
+
+ if (lCurrent==false) {
+ return secLen;
+ }
+ shutdownLock();
+ int byteLen=1;
+ int pos=1;
+ if (input != NULL) {
+ pos=input->getBytePosition()+1;
+ byteLen=input->getByteLength()+1;
+ }
+ int back=(int)(((double)pos/(double)byteLen) * (double)secLen);
+ shutdownUnlock();
+ return back;
+
+}
+
+int DecoderPlugin::getTotalLength() {
+ cout << "plugin does not support total playtime reporting"<<endl;
+ return 0;
+}
+
+int DecoderPlugin::seek_impl(int) {
+ cout << "plugin does not support seek"<<endl;
+ return false;
+}
+
+
+
+
+void DecoderPlugin::setOutputPlugin(OutputStream* output) {
+ this->output=output;
+}
+
+
+int DecoderPlugin::setInputPlugin(InputStream* input) {
+ this->input=input;
+
+ if (!input) {
+ cout << "input is NULL"<<endl;
+ exit(0);
+ }
+ pluginInfo->setUrl(input->getUrl());
+
+
+ // the command is synchron we block until the
+ // thread has read it
+ Command cmd(_COMMAND_START);
+ insertSyncCommand(&cmd);
+
+
+ // now that we know he has read it, we send another
+ // command, this is only read if the thread is in the
+ // decode_loop, and we then know that the streamState
+ // is FIRST_INIT
+ Command ping(_COMMAND_PING);
+ insertSyncCommand(&ping);
+
+
+ if (lAutoPlay) {
+ play();
+ }
+ return true;
+}
+
+
+void DecoderPlugin::config(const char* key,const char* value,void* ){
+ if (strcmp(key,"-y")==0) {
+ if (strcmp(value,"on")==0) {
+ lAutoPlay=true;
+ } else {
+ lAutoPlay=false;
+ }
+ }
+
+}
+
+/**
+ during shutdown the streamState is undefined until
+ the thread has left the decode_loop().
+ Make sure we wait for this.
+*/
+int DecoderPlugin::getStreamState() {
+ shutdownLock();
+ int back=streamState;
+ shutdownUnlock();
+ return back;
+}
+
+
+int DecoderPlugin::waitForStreamState(int state) {
+ int back;
+ abs_thread_mutex_lock(&streamStateMut);
+ while ((streamState & state) == false) {
+ abs_thread_cond_wait(&streamStateCond,&streamStateMut);
+ }
+ back=streamState;
+ abs_thread_mutex_unlock(&streamStateMut);
+ return back;
+}
+
+
+void DecoderPlugin::setStreamState(int streamState) {
+ abs_thread_mutex_lock(&streamStateMut);
+ this->streamState=streamState;
+ abs_thread_cond_signal(&streamStateCond);
+ abs_thread_mutex_unlock(&streamStateMut);
+}
+
+
+void DecoderPlugin::decoder_loop() {
+ cout << "direct call decoder loop->plugin not found ???"<<endl;
+ TimeWrapper::usleep(100000);
+}
+
+
+void* DecoderPlugin::idleThread() {
+
+ while(lCreatorLoop) {
+ linDecoderLoop=true;
+ commandPipe->waitForCommand();
+ commandPipe->hasCommand(threadCommand);
+ int id=threadCommand->getID();
+ switch(id) {
+ case _COMMAND_START:
+ lDecoderLoop=true;
+ break;
+ case _COMMAND_PING:
+ break;
+ /*
+ default:
+ threadCommand->print("ignoring non START command in idleThread");
+ */
+ }
+
+
+ if (lDecoderLoop) {
+ setStreamState(_STREAM_STATE_FIRST_INIT);
+ linDecoderLoop=false;
+ decode_loopCounter++;
+ runCheck_Counter=0;
+ shutdownLock();
+ decoder_loop();
+ lDecode=false;
+ lDecoderLoop=false;
+ lhasLength=false;
+ setStreamState(_STREAM_STATE_EOF);
+ shutdownUnlock();
+ }
+ }
+ return NULL;
+}
+
+
+PluginInfo* DecoderPlugin::getPluginInfo() {
+ return pluginInfo;
+}
+
+
+int DecoderPlugin::runCheck() {
+ if (runCheck_Counter==0) {
+ shutdownUnlock();
+ }
+ runCheck_Counter++;
+ while (lDecoderLoop && lCreatorLoop) {
+
+ // if we have an eof this always leads to
+ // a shutdown of the decode_loop thread
+ // it has more priority than the resyn request
+ if (input->eof()) {
+ setStreamState(_STREAM_STATE_WAIT_FOR_END);
+ }
+ //
+ // if we are in _STREAM_STATE_RESYNC_COMMIT
+ // we only leave it if command is _COMMAND_RESYNC_END
+ // (or close)
+
+ //
+ // check user commands
+ //
+ if (lDecode==false) {
+ commandPipe->waitForCommand();
+ commandPipe->hasCommand(threadCommand);
+ } else {
+ if (commandPipe->hasCommand(threadCommand)==false) {
+ // no commands and lDecode=true
+ return true;
+ }
+ }
+
+ // here we forward the command to a special
+ // method who can handle everything
+ // (the default method should work fine);
+ int nextCheck= processThreadCommand(threadCommand);
+ switch(nextCheck) {
+ case _RUN_CHECK_CONTINUE:
+ break;
+ case _RUN_CHECK_FALSE:
+ shutdownLock();
+ return false;
+ case _RUN_CHECK_TRUE:
+ return true;
+ default:
+ cout << "unknown runCheck return command"<<endl;
+ exit(0);
+ }
+
+
+ }
+
+ shutdownLock();
+ return false;
+}
+
+int DecoderPlugin::processThreadCommand(Command* command) {
+
+
+ int id=command->getID();
+ int intArg;
+
+ //
+ // if we are in _STREAM_STATE_RESYNC_COMMIT
+ // we only leave it if command is _COMMAND_RESYNC_END
+ //
+ if (streamState==_STREAM_STATE_RESYNC_COMMIT) {
+ switch(id) {
+ case _COMMAND_RESYNC_END:
+ setStreamState(_STREAM_STATE_INIT);
+ input->clear();
+ break;
+ case _COMMAND_CLOSE:
+ //
+ // we return false so that the plugin clears
+ // all its allocated classes
+ // its a _must_ !!
+ // in the next call we exit immediately
+ return _RUN_CHECK_FALSE;
+
+ /*
+ default:
+ command->print("ignore command in _STREAM_STATE_RESYNC_COMMIT");
+ */
+ }
+ return _RUN_CHECK_CONTINUE;
+ }
+
+
+ switch(id) {
+ case _COMMAND_NONE:
+ break;
+ case _COMMAND_PING:
+ break;
+ case _COMMAND_PAUSE:
+ lDecode=false;
+ break;
+ case _COMMAND_PLAY:
+ lDecode=true;
+ break;
+ case _COMMAND_SEEK: {
+ if (streamState==_STREAM_STATE_FIRST_INIT) {
+ command->print("ignore command seek in _STREAM_STATE_FIRST_INIT");
+ } else {
+ intArg=command->getIntArg();
+ seek_impl(intArg);
+ }
+ break;
+ }
+ case _COMMAND_CLOSE:
+ //
+ // we return false so that the plugin clears
+ // all its allocated classes
+ // its a _must_ !!
+ // in the next call we exit immediately
+ return _RUN_CHECK_FALSE;
+ case _COMMAND_RESYNC_START:
+ setStreamState(_STREAM_STATE_RESYNC_COMMIT);
+ input->clear();
+ break;
+ /*
+ default:
+ cout << "unknown command id in Command::print"<<endl;
+ */
+ }
+ return _RUN_CHECK_CONTINUE;
+}
+
+
diff --git a/mpeglib/lib/decoder/decoderPlugin.h b/mpeglib/lib/decoder/decoderPlugin.h
new file mode 100644
index 00000000..b616ed51
--- /dev/null
+++ b/mpeglib/lib/decoder/decoderPlugin.h
@@ -0,0 +1,201 @@
+/*
+ base class for the 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 __DECODERPLUGIN_H
+#define __DECODERPLUGIN_H
+
+
+
+
+
+#include "commandPipe.h"
+#include "../input/inputPlugin.h"
+#include "../output/outPlugin.h"
+#include "../util/timeWrapper.h"
+
+#include <kdemacros.h>
+
+/**
+ Note: streamstate can be "or'ed" for the waitStreamState call
+*/
+
+#define _STREAM_STATE_EOF 1
+#define _STREAM_STATE_FIRST_INIT 4
+#define _STREAM_STATE_INIT 8
+#define _STREAM_STATE_PLAY 16
+#define _STREAM_STATE_WAIT_FOR_END 32
+#define _STREAM_STATE_RESYNC_COMMIT 64
+#define _STREAM_STATE_ALL 1+4+8+16+32+64
+
+
+#define _RUN_CHECK_FALSE 0
+#define _RUN_CHECK_TRUE 1
+#define _RUN_CHECK_CONTINUE 2
+
+
+
+/**
+ Here is the base class for the player plugin.
+ we can set the output of the player, and the input.
+ <p>
+ This class offer you a thread which you have to use
+ in derived class for the decoding work.
+ <p>
+ All calls to your decoder goes through this class
+ which must make sure that there are no races.
+ <p>
+ The life of the decoder thread:
+ ------------------------------
+
+ We start every time a thread if you make an instance of this class.
+ The thread then goes to the idleThread() method and waits
+ until we wake him up.
+ If we wake him um he graps the decoderMut and enters the
+ decode_loop() This method must be used for your plugin.
+ Then this thread "polls" during decoding the decoderChangeMut
+ (see runCheck())
+ if he can get the decoderChangeMut,the thread is authenticated for another
+ decode round if not, he waits until we wake him up again.
+ If the stream ends or the user stops decoding we leave the decoder_loop
+ and go back to the idleThread().
+ If you delete this class the thread is joined.
+
+*/
+
+class KDE_EXPORT DecoderPlugin {
+
+ public:
+
+ DecoderPlugin();
+ virtual ~DecoderPlugin();
+
+ //
+ // you can submit the following commands to the decode_loop thread
+ //
+ virtual void close();
+ virtual void pause();
+ virtual int play();
+ virtual int seek(int second);
+ void insertAsyncCommand(Command* cmd);
+ void insertSyncCommand(Command* cmd);
+
+ // returns total length (lCurrent==false) or current time (true)
+ // Note: you should not call this too often because
+ // it locks the decoder thread.
+ // Should be called only after the initialisation of the stream
+ // no need to override this, overide getTotalLength()
+ int getTime(int lCurrent);
+
+
+
+ virtual void setOutputPlugin(OutputStream* output);
+
+ // This method can only be called _once_ after a "close"
+ virtual int setInputPlugin(InputStream* input);
+ virtual void config(const char* key,const char* value,void* user_data);
+ virtual int getStreamState();
+
+ /**
+ Use this method to wait for a stream signal.
+ For example: after setInputPlugin the thread starts with
+ the state _EOF then the state changes between:
+
+ After setInput you can wait for (INIT | DECODE | WAIT_FOR_END | EOF) this
+ make sure the first init is passed. (successful or not)
+ return value is current streamState, which had a succesfull match.
+ Note: after return the state may already have changed (nature of threads)
+
+ */
+ int waitForStreamState(int state);
+ PluginInfo* getPluginInfo();
+
+ // Needed for Video Embedding
+ int x11WindowId() { return output->x11WindowId(); }
+
+ // never use this!
+ void* idleThread();
+
+ // Note: can only be called by the decode_loop thread !!!
+ void setStreamState(int streamState);
+
+ protected:
+
+ // override this if you have the total length in second
+ virtual int getTotalLength();
+ // implement this if your plugin supports seek
+ // (called by decoder_loop thread
+ virtual int seek_impl(int second);
+
+
+ /**
+ should be called from decoder_loop
+ checks some mutex variables if user want decoder to pause/quit
+ returns:
+ false : quit decoding
+ true : continue decoding
+
+ Note: method blocks if user "pauses" the stream
+ */
+ int runCheck();
+
+ // this mut is set from the start of decoder_loop()
+ // its _not_ set if the thread runs in the while() loop
+ // it it set if the thread leaves the while loop (runCheck->false)
+ // (its used internally to make the getTime() call safe
+ void shutdownLock();
+ void shutdownUnlock();
+
+
+ // this is the method to override in your decoder
+ virtual void decoder_loop();
+
+ // this method handles the commands for the decode_loop thread
+ virtual int processThreadCommand(Command* command);
+
+ OutputStream* output;
+ InputStream* input;
+
+ abs_thread_t tr;
+ abs_thread_mutex_t shutdownMut;
+ abs_thread_mutex_t streamStateMut;
+ abs_thread_cond_t streamStateCond;
+
+
+
+
+ int lDecoderLoop;
+ int lCreatorLoop;
+ int linDecoderLoop;
+ int lDecode;
+ int streamState;
+ int lhasLength;
+ int lAutoPlay;
+ int decode_loopCounter; // count how much we started decode_loop
+ int runCheck_Counter; // count how much we called runCheck
+ int instance;
+ PluginInfo* pluginInfo;
+
+ private:
+
+ CommandPipe* commandPipe;
+ Command* threadCommand;
+
+
+
+};
+
+#endif
+
diff --git a/mpeglib/lib/decoder/mpegPlugin.cpp b/mpeglib/lib/decoder/mpegPlugin.cpp
new file mode 100644
index 00000000..e230adb5
--- /dev/null
+++ b/mpeglib/lib/decoder/mpegPlugin.cpp
@@ -0,0 +1,160 @@
+/*
+ mpeg 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 "mpegPlugin.h"
+
+#include "../mpegplay/mpegVideoStream.h"
+#include "../mpegplay/proto.h"
+#include "../mpegplay/mpegVideoHeader.h"
+
+using namespace std;
+
+
+MpegPlugin::MpegPlugin() {
+ init();
+}
+
+
+MpegPlugin::~MpegPlugin() {
+}
+
+
+void MpegPlugin::init() {
+ lCalcLength=false;
+ mpegVideoHeader=NULL;
+ mpegVideoStream=NULL;
+}
+
+
+void MpegPlugin::decoder_loop() {
+
+
+ VideoDecoder* video=NULL;
+ if (input == NULL) {
+ cout << "MpegPlugin::decoder_loop input is NULL"<<endl;
+ exit(0);
+ }
+ if (output == NULL) {
+ cout << "MpegPlugin::decoder_loop output is NULL"<<endl;
+ exit(0);
+ }
+
+ mpegVideoHeader=new MpegVideoHeader();
+ mpegVideoStream=new MpegVideoStream(input);
+
+ PictureArray* pictureArray;
+ YUVPicture* pic;
+ int skipMode=_SYNC_TO_NONE;
+ // decode loop
+
+ while(runCheck()) {
+ switch(streamState) {
+ case _STREAM_STATE_FIRST_INIT :
+ if (mpegVideoStream->firstInitialize(mpegVideoHeader)==false) {
+
+ } else {
+ pluginInfo->setLength(getSongLength());
+
+ // now create pictureArray from the sequence
+ int width=mpegVideoHeader->getMB_Width()*16;
+ int height=mpegVideoHeader->getMB_Height()*16;
+
+ output->openWindow(width,height,(char*)"kmpg");
+ video=new VideoDecoder(mpegVideoStream,mpegVideoHeader);
+ setStreamState(_STREAM_STATE_INIT);
+ }
+ break;
+ case _STREAM_STATE_INIT :
+ // cout << "mpeg _STREAM_STATE_INI"<<endl;
+ if (skipMode==_SYNC_TO_GOP) {
+ if (mpegVideoStream->nextGOP()==false) {
+ continue;
+ }
+ video->resyncToI_Frame();
+ }
+ if (skipMode==_SYNC_TO_PIC) {
+ if (mpegVideoStream->nextPIC()==false) {
+ continue;
+ }
+ }
+ skipMode=_SYNC_TO_NONE;
+ setStreamState(_STREAM_STATE_PLAY);
+ break;
+ case _STREAM_STATE_PLAY :
+ pictureArray=output->lockPictureArray();
+ skipMode=video->mpegVidRsrc(pictureArray);
+
+ if (skipMode != _SYNC_TO_NONE) {
+ setStreamState(_STREAM_STATE_INIT);
+ }
+ pic=pictureArray->getYUVPictureCallback();
+ if (pic == NULL) {
+ // nothin to display
+ break;
+ }
+
+ output->unlockPictureArray(pictureArray);
+ pictureArray->setYUVPictureCallback(NULL);
+ break;
+ case _STREAM_STATE_WAIT_FOR_END:
+ // exit while loop
+ lDecoderLoop=false;
+ break;
+ default:
+ cout << "unknown stream state:"<<streamState<<endl;
+ }
+ }
+
+ output->flushWindow();
+ // copy sequence back if needed
+ if (video != NULL) {
+ delete video;
+ }
+ delete mpegVideoStream;
+ delete mpegVideoHeader;
+ mpegVideoStream=NULL;
+ mpegVideoHeader=NULL;
+}
+
+
+
+
+
+// here we can config our decoder with special flags
+void MpegPlugin::config(const char* key,const char* value,void* user_data) {
+ if (strcmp(key,"-c")==0) {
+ lCalcLength=false;
+ }
+
+ if (strcmp(key,"decode")==0) {
+ if (strcmp(value,"true")==0) {
+ lDecode=true;
+ } else {
+ lDecode=false;
+ }
+ }
+ DecoderPlugin::config(key,value,user_data);
+}
+
+
+
+int MpegPlugin::getSongLength() {
+ int back=0;
+ return back;
+}
+
+
+
+
+
+
diff --git a/mpeglib/lib/decoder/mpegPlugin.h b/mpeglib/lib/decoder/mpegPlugin.h
new file mode 100644
index 00000000..ff236f9b
--- /dev/null
+++ b/mpeglib/lib/decoder/mpegPlugin.h
@@ -0,0 +1,47 @@
+/*
+ mpeg 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 __MPEGPLUGIN_H
+#define __MPEGPLUGIN_H
+
+#include "../decoder/decoderPlugin.h"
+
+
+class MpegVideoHeader;
+class MpegVideoStream;
+
+
+class MpegPlugin : public DecoderPlugin {
+
+ int lCalcLength;
+
+ MpegVideoHeader* mpegVideoHeader;
+ MpegVideoStream* mpegVideoStream;
+
+ public:
+ MpegPlugin();
+ ~MpegPlugin();
+
+ void decoder_loop();
+ void config(const char* key,const char* value,void* user_data);
+
+
+ private:
+ void init();
+
+ int getSongLength();
+
+
+};
+#endif
+
diff --git a/mpeglib/lib/decoder/mpgPlugin.cpp b/mpeglib/lib/decoder/mpgPlugin.cpp
new file mode 100644
index 00000000..fd7170c8
--- /dev/null
+++ b/mpeglib/lib/decoder/mpgPlugin.cpp
@@ -0,0 +1,260 @@
+/*
+ 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 "mpgPlugin.h"
+
+#include "../mpegplay/mpegSystemStream.h"
+#include "../mpgplayer/mpegStreamPlayer.h"
+#include "../mpegplay/mpegVideoLength.h"
+
+#include "splayPlugin.h"
+#include "mpegPlugin.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+MpgPlugin::MpgPlugin() {
+
+ mpegSystemHeader=NULL;
+ mpegSystemStream=NULL;
+ mpegStreamPlayer=NULL;
+ mpegVideoLength=NULL;
+
+ // make runtime config easier, no NULL check necessary
+ mpegSystemHeader=new MpegSystemHeader();
+ timeStamp=new TimeStamp();
+ lMono=false;
+ lDown=false;
+ lWriteStreams=false;
+ lDoLength=true;
+}
+
+
+MpgPlugin::~MpgPlugin() {
+ delete mpegSystemHeader;
+ delete timeStamp;
+}
+
+
+
+void MpgPlugin::decoder_loop() {
+
+ if (input == NULL) {
+ cout << "MPGPlugin::decoder_loop input is NULL"<<endl;
+ exit(0);
+ }
+ if (output == NULL) {
+ cout << "MPGPlugin::decoder_loop output is NULL"<<endl;
+ exit(0);
+ }
+
+ // decoder
+ SplayPlugin* splayPlugin=new SplayPlugin();
+ splayPlugin->config("-c","true",NULL);
+ if (lMono) {
+ splayPlugin->config("-m","true",NULL);
+ }
+ if (lDown) {
+ splayPlugin->config("-2","true",NULL);
+ }
+
+ MpegPlugin* mpegplayPlugin=new MpegPlugin();
+
+ mpegSystemStream=new MpegSystemStream(input);
+ mpegStreamPlayer=new MpegStreamPlayer(input,output,
+ splayPlugin,mpegplayPlugin);
+ mpegStreamPlayer->setWriteToDisk(lWriteStreams);
+ mpegVideoLength=new MpegVideoLength(input);
+
+
+ int lSysLayer=false;
+ int lHasLength=false;
+
+ while(runCheck()) {
+ switch(streamState) {
+ case _STREAM_STATE_FIRST_INIT :
+ if ((lHasLength==false) && (lDoLength)) {
+ if (mpegVideoLength->firstInitialize()==false) {
+ continue;
+ }
+ lHasLength=true;
+ }
+ if (mpegSystemStream->firstInitialize(mpegSystemHeader)==false) {
+ //cout << "still initializing system stream"<<endl;
+ } else {
+ // if we have found a raw stream,
+ // make sure we pass as first argument a SEQ_START_CODE
+ if (mpegSystemHeader->getLayer() == _PACKET_SYSLAYER) {
+ lSysLayer=true;
+ mpegStreamPlayer->processSystemHeader(mpegSystemHeader);
+ } else {
+ //output->config("-s","false");
+ unsigned int startCodeRaw=htonl(_SEQ_START_CODE);
+ mpegStreamPlayer->
+ insertVideoDataRaw((unsigned char*)&startCodeRaw,4,timeStamp);
+ }
+ pluginInfo->setLength(mpegVideoLength->getLength());
+ output->writeInfo(pluginInfo);
+ setStreamState(_STREAM_STATE_INIT);
+
+ if (mpegSystemHeader->getMPEG2()==true) {
+ cout << "this plugin does not support MPEG2/VOB/DVD"<<endl;
+ lDecoderLoop=false;
+ if (lWriteStreams == true) {
+ cout << "demux is supported"<<endl;
+ lDecoderLoop=true;
+
+ }
+ break;
+ }
+
+ }
+ break;
+ case _STREAM_STATE_INIT :
+ setStreamState(_STREAM_STATE_PLAY);
+ break;
+ case _STREAM_STATE_PLAY :
+ // syslayer
+
+ if (mpegSystemStream->nextPacket(mpegSystemHeader) == false) {
+
+ break;
+ }
+
+ if (mpegStreamPlayer->processSystemHeader(mpegSystemHeader) == false) {
+ mpegSystemStream->reset();
+ setStreamState(_STREAM_STATE_INIT);
+ }
+
+ break;
+ case _STREAM_STATE_WAIT_FOR_END:
+ if (mpegStreamPlayer->hasEnd()==true) {
+ // exit while loop
+ lDecoderLoop=false;
+ }
+ TimeWrapper::usleep(100000);
+ break;
+ default:
+ cout << "unknown stream state:"<<streamState<<endl;
+ }
+ }
+
+ delete mpegStreamPlayer;
+ delete mpegSystemStream;
+ delete mpegVideoLength;
+ delete mpegplayPlugin;
+ delete splayPlugin;
+
+ mpegSystemStream=NULL;
+ mpegStreamPlayer=NULL;
+ mpegVideoLength=NULL;
+
+
+ output->audioFlush();
+ output->flushWindow();
+
+}
+
+
+
+// here we can config our decoder with special flags
+void MpgPlugin::config(const char* key,const char* value,void* user_data) {
+ if(strcmp("VideoLayer", key) == 0) {
+ int videoLayerSelect=atoi(value);
+ mpegSystemHeader->setVideoLayerSelect(videoLayerSelect);
+ }
+
+ if(strcmp("AudioLayer", key) == 0) {
+ int audioLayerSelect=atoi(value);
+ mpegSystemHeader->setAudioLayerSelect(audioLayerSelect);
+ }
+ if (strcmp(key,"-2")==0) {
+ lDown=true;
+ }
+ if (strcmp(key,"-m")==0) {
+ lMono=true;
+ }
+ if (strcmp(key,"-c")==0) {
+ lDoLength=false;
+ }
+ if (strcmp(key,"-w")==0) {
+ if (strcmp(value,"true")==0) {
+ lWriteStreams=true;
+ } else {
+ lWriteStreams=true;
+ }
+ }
+ // now try to set it if stream is running:
+ shutdownLock();
+ if (mpegStreamPlayer != NULL) {
+ mpegStreamPlayer->setWriteToDisk(lWriteStreams);
+ }
+ shutdownUnlock();
+
+
+ DecoderPlugin::config(key,value,user_data);
+}
+
+
+
+
+int MpgPlugin::getTotalLength() {
+ shutdownLock();
+ int back=0;
+ if (mpegVideoLength != NULL) {
+ back=mpegVideoLength->getLength();
+ } else {
+ cout << "cannot report total length, plugin not initialized"<<endl;
+ }
+ shutdownUnlock();
+
+ return back;
+}
+
+
+
+
+
+int MpgPlugin::processThreadCommand(Command* command) {
+
+ int id=command->getID();
+ int arg;
+ switch(id) {
+ case _COMMAND_SEEK: {
+ //
+ // mapping from second to bytePosition
+ //
+ if (mpegStreamPlayer->isInit()==false) {
+ command->print("MPGPLUGIN:ignore command in _STREAM_STATE_FIRST_INIT");
+ } else {
+ arg=command->getIntArg();
+ int pos=mpegVideoLength->getSeekPos(arg);
+ Command seek(_COMMAND_SEEK,pos);
+ // insert correct values
+ mpegStreamPlayer->processThreadCommand(&seek);
+ }
+ return _RUN_CHECK_CONTINUE;
+ }
+
+ default:
+ // we forward the command to the mpegStreamPlayer
+ mpegStreamPlayer->processThreadCommand(command);
+ }
+
+ // use default
+ return (DecoderPlugin::processThreadCommand(command));
+}
+
+
diff --git a/mpeglib/lib/decoder/mpgPlugin.h b/mpeglib/lib/decoder/mpgPlugin.h
new file mode 100644
index 00000000..79d986cc
--- /dev/null
+++ b/mpeglib/lib/decoder/mpgPlugin.h
@@ -0,0 +1,62 @@
+/*
+ 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 __MPGPLUGIN_H
+#define __MPGPLUGIN_H
+
+#include "../decoder/decoderPlugin.h"
+#include <kdemacros.h>
+
+#define _INSERT_NO 0
+#define _INSERT_VIDEO 1
+#define _INSERT_AUDIO 2
+#define _INSERT_ALL 3
+
+class MpegSystemHeader;
+class MpegSystemStream;
+class MpegStreamPlayer;
+class MpegVideoLength;
+
+class KDE_EXPORT MpgPlugin : public DecoderPlugin {
+
+ MpegSystemHeader* mpegSystemHeader;
+ MpegSystemStream* mpegSystemStream;
+ MpegStreamPlayer* mpegStreamPlayer;
+ MpegVideoLength* mpegVideoLength;
+ TimeStamp* timeStamp;
+ int lMono;
+ int lDown;
+ int lWriteStreams;
+ int lDoLength;
+
+ public:
+ MpgPlugin();
+ ~MpgPlugin();
+
+ void decoder_loop();
+ int getTime(int lCurrent);
+
+ void config(const char* key,const char* value,void* user_data);
+
+ int processThreadCommand(Command* command);
+
+
+
+ protected:
+ int getTotalLength();
+
+
+};
+#endif
+
diff --git a/mpeglib/lib/decoder/nukePlugin.cpp b/mpeglib/lib/decoder/nukePlugin.cpp
new file mode 100644
index 00000000..08c8ce89
--- /dev/null
+++ b/mpeglib/lib/decoder/nukePlugin.cpp
@@ -0,0 +1,62 @@
+/*
+ this plugin nukes the 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 "nukePlugin.h"
+
+#include <iostream>
+
+using namespace std;
+
+NukePlugin::NukePlugin() {
+}
+
+
+NukePlugin::~NukePlugin() {
+}
+
+
+
+void NukePlugin::decoder_loop() {
+ if (input == NULL) {
+ cout << "NukePlugin::decoder_loop input is NULL"<<endl;
+ exit(0);
+ }
+ if (output == NULL) {
+ cout << "NukePlugin::decoder_loop output is NULL"<<endl;
+ exit(0);
+ }
+ char nukeBuffer[8192];
+
+ while(runCheck()) {
+
+ switch(streamState) {
+ case _STREAM_STATE_FIRST_INIT :
+ case _STREAM_STATE_INIT :
+ case _STREAM_STATE_PLAY :
+ input->read(nukeBuffer,8192);
+ break;
+ case _STREAM_STATE_WAIT_FOR_END:
+ // exit while loop
+ cout << "nukePlugin _STREAM_STATE_WAIT_FOR_END"<<endl;
+ lDecoderLoop=false;
+ break;
+ default:
+ cout << "unknown stream state:"<<streamState<<endl;
+ }
+ }
+}
+
+
+void NukePlugin::config(const char* key,const char* value,void* user_data) {
+ DecoderPlugin::config(key,value,user_data);
+}
diff --git a/mpeglib/lib/decoder/nukePlugin.h b/mpeglib/lib/decoder/nukePlugin.h
new file mode 100644
index 00000000..8a9aa9a3
--- /dev/null
+++ b/mpeglib/lib/decoder/nukePlugin.h
@@ -0,0 +1,34 @@
+/*
+ this plugin nukes the 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
+
+ */
+
+
+#ifndef __NUKEPLUGIN_H
+#define __NUKEPLUGIN_H
+
+
+#include "../decoder/decoderPlugin.h"
+#include <kdemacros.h>
+
+class KDE_EXPORT NukePlugin : public DecoderPlugin {
+
+ public:
+
+ NukePlugin();
+ ~NukePlugin();
+
+ void decoder_loop();
+ void config(const char* key,const char* value,void* user_data);
+
+ private:
+
+};
+#endif
diff --git a/mpeglib/lib/decoder/splayPlugin.cpp b/mpeglib/lib/decoder/splayPlugin.cpp
new file mode 100644
index 00000000..d0caa077
--- /dev/null
+++ b/mpeglib/lib/decoder/splayPlugin.cpp
@@ -0,0 +1,308 @@
+/*
+ splay 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 "splayPlugin.h"
+#include "../splay/mpegsound.h"
+
+#include "../splay/splayDecoder.h"
+#include "../frame/floatFrame.h"
+#include "../frame/pcmFrame.h"
+#include "../splay/mpegAudioFrame.h"
+#include "../splay/mpegAudioInfo.h"
+#include "../input/fileAccessWrapper.h"
+
+#include <iostream>
+
+using namespace std;
+
+#define INPUTBUFFER_SIZE 8192
+
+SplayPlugin::SplayPlugin() {
+ pow(6.0,3.0); // fixes bug in __math.h
+ doFloat = false;
+ lnoLength=false;
+ inputbuffer=new unsigned char[INPUTBUFFER_SIZE];
+ pcmFrame=new PCMFrame(MP3FRAMESIZE);
+ floatFrame=new FloatFrame(MP3FRAMESIZE);
+ audioFrame=new AudioFrame();
+ framer=new MpegAudioFrame();
+ splay=new SplayDecoder();
+ lenghtInSec=0;
+
+ fileAccess=NULL;
+ info=NULL;
+ lOutput=true;
+}
+
+
+SplayPlugin::~SplayPlugin() {
+ delete [] inputbuffer;
+ delete pcmFrame;
+ delete floatFrame;
+ delete framer;
+ delete splay;
+ delete audioFrame;
+}
+
+
+// here we can config our decoder with special flags
+void SplayPlugin::config(const char* key,const char* value,void* user_data) {
+ if (strcmp(key,"dofloat")==0) {
+ doFloat=true;
+ }
+ if (strcmp(key,"-m")==0) {
+ splay->config("m","0",NULL);
+ }
+ if (strcmp(key,"-2")==0) {
+ splay->config("2","1",NULL);
+ }
+ if (strcmp(key,"-c")==0) {
+ lnoLength=true;
+ }
+ if (strcmp(key,"-d")==0) {
+ lOutput=false;
+ }
+
+ if (strcmp(key,"decode")==0) {
+ if (strcmp(value,"true")==0) {
+ lDecode=true;
+ } else {
+ lDecode=false;
+ }
+ }
+ DecoderPlugin::config(key,value,user_data);
+}
+
+
+
+void SplayPlugin::decoder_loop() {
+
+ if (input == NULL) {
+ cout << "SplayPlugin::decoder_loop input is NULL"<<endl;
+ exit(0);
+ }
+ if (output == NULL) {
+ cout << "SplayPlugin::decoder_loop output is NULL"<<endl;
+ exit(0);
+ }
+ // init decoder
+ output->audioInit();
+
+ // start decoding
+
+ fileAccess=new FileAccessWrapper(input);
+ info= new MpegAudioInfo(fileAccess);
+
+
+
+ framer->reset();
+ lenghtInSec=0;
+ resyncCounter=0;
+
+ AudioFrame* audioFrame=pcmFrame;
+ if (doFloat) {
+ audioFrame=floatFrame;
+ }
+
+ output->audioInit();
+ while(runCheck()) {
+
+ //
+ // check for re-init or for "eof"
+ //
+ switch(streamState) {
+ case _STREAM_STATE_INIT :
+ framer->reset();
+ resyncCounter=5;
+ setStreamState(_STREAM_STATE_PLAY);
+ continue;
+ case _STREAM_STATE_WAIT_FOR_END:
+ // exit while loop
+ lDecoderLoop=false;
+ continue;
+ }
+ if (doFrameFind() == true) {
+ if (splay->decode(framer->outdata(),framer->len(),audioFrame) == false){
+ continue;
+ }
+ // send data out:
+
+ int rest=framer->restBytes();
+ // we have inserted more data already than the
+ // framer has processed. But framer tells us
+ // how much he still needs to process.
+ long pos=input->getBytePosition();
+ TimeStamp* stamp=input->getTimeStamp(pos-rest);
+ processStreamState(stamp,audioFrame);
+
+
+ // make this stamp invalid for further synchronisation
+ stamp->setPTSFlag(false);
+ }
+ }
+
+ output->audioFlush();
+
+ delete fileAccess;
+ delete info;
+ fileAccess=NULL;
+ info=NULL;
+
+
+}
+
+
+int SplayPlugin::doFrameFind() {
+
+ //
+ // fine, we can work on the stream:
+ //
+ int back=false;
+ int framerState=framer->getState();
+ switch(framerState) {
+ case FRAME_NEED: {
+ int bytes=framer->canStore();
+ int read=input->read((char*)inputbuffer,bytes);
+
+ if (read <= 0) {
+ // read error. reset framer, drop frames
+ setStreamState(_STREAM_STATE_INIT);
+ break;
+ }
+ framer->store(inputbuffer,read);
+ break;
+ }
+ case FRAME_WORK:
+ back=framer->work();
+ break;
+ case FRAME_HAS: {
+ break;
+ }
+ default:
+ cout << "unknown state in mpeg audio framing"<<endl;
+ exit(0);
+ }
+ return back;
+}
+
+void SplayPlugin::audioSetup(AudioFrame* setupFrame) {
+ setupFrame->copyFormat(audioFrame);
+ output->audioSetup(audioFrame->getFrequenceHZ(),
+ audioFrame->getStereo(),
+ audioFrame->getSigned(),
+ audioFrame->getBigEndian(),
+ audioFrame->getSampleSize());
+}
+
+
+
+void SplayPlugin::processStreamState(TimeStamp* stamp,AudioFrame* playFrame){
+
+ // we always have a frame here, with the correct timestamp here.
+
+ switch(streamState) {
+ case _STREAM_STATE_FIRST_INIT :
+ output->audioOpen();
+
+ audioSetup(playFrame);
+
+ if (lnoLength==false) {
+ lenghtInSec=getTotalLength();
+ pluginInfo->setLength(lenghtInSec);
+ output->writeInfo(pluginInfo);
+ }
+
+ setStreamState(_STREAM_STATE_PLAY);
+ // yes, here is no break.
+ // we want to send the frame to the output.
+
+ case _STREAM_STATE_PLAY :
+ if (resyncCounter > 0) {
+ resyncCounter--;
+ break;
+ }
+ if (audioFrame->isFormatEqual(playFrame)==false) {
+ audioSetup(playFrame);
+ }
+ if (lOutput == false) {
+ break;
+ }
+ if(doFloat) {
+ FloatFrame* floatFrame=(FloatFrame*)playFrame;
+ output->audioPlay(stamp,stamp,
+ (char*) floatFrame->getData(),
+ playFrame->getLen()*sizeof(float) );
+ } else {
+ PCMFrame* pcmFrame=(PCMFrame*)playFrame;
+ output->audioPlay(stamp,stamp,
+ (char*)pcmFrame->getData(),
+ playFrame->getLen()*sizeof(short int));
+ }
+ break;
+ default:
+ cout << "unknown stream state:"<<streamState<<endl;
+ }
+}
+
+
+
+// splay can seek in streams
+int SplayPlugin::seek_impl(int second) {
+
+
+ if (info != NULL) {
+ int pos=info->getSeekPosition(second);
+ input->seek(pos);
+ setStreamState(_STREAM_STATE_INIT);
+ } else {
+ cout << "cannot seek, plugin not initialized"<<endl;
+ }
+ return true;
+}
+
+
+int SplayPlugin::getTotalLength() {
+ shutdownLock();
+ int back=0;
+
+ if (info->getNeedInit()) {
+ long pos=input->getBytePosition();
+ if (input->seek(0) == true) {
+ int bytes=1024;
+ // try reading all info, but not more
+ // than 1024 iterations.
+ info->reset();
+ while(bytes>0) {
+ if (info->initialize()==true) {
+ break;
+ }
+ bytes--;
+ }
+ input->seek(pos);
+ }
+ // wheter successful or not, never touch
+ // the info thing again.
+ info->setNeedInit(false);
+ }
+
+ back=info->getLength();
+
+
+ shutdownUnlock();
+ return back;
+}
+
+
+
+
+
diff --git a/mpeglib/lib/decoder/splayPlugin.h b/mpeglib/lib/decoder/splayPlugin.h
new file mode 100644
index 00000000..34a9751b
--- /dev/null
+++ b/mpeglib/lib/decoder/splayPlugin.h
@@ -0,0 +1,67 @@
+/*
+ splay 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 __SPLAYPLUGIN_H
+#define __SPLAYPLUGIN_H
+
+#include "../decoder/decoderPlugin.h"
+#include <kdemacros.h>
+
+class SplayDecoder;
+class MpegAudioFrame;
+class AudioFrame;
+class FloatFrame;
+class PCMFrame;
+class FileAccessWrapper;
+class MpegAudioInfo;
+
+class KDE_EXPORT SplayPlugin : public DecoderPlugin {
+
+ int lnoLength;
+ int lfirst;
+ int lOutput;
+ /*
+ * directly writes decoded data as float, instead of converting it to
+ * short int samples first. float->int conversions are _very_
+ * time intensiv!
+ */
+ bool doFloat;
+
+ SplayDecoder* splay;
+ MpegAudioFrame* framer;
+ FloatFrame* floatFrame;
+ PCMFrame* pcmFrame;
+ unsigned char* inputbuffer;
+ int lenghtInSec;
+ MpegAudioInfo* info;
+ FileAccessWrapper* fileAccess;
+ int resyncCounter;
+ AudioFrame* audioFrame;
+
+
+ public:
+ SplayPlugin();
+ ~SplayPlugin();
+
+ void decoder_loop();
+ int seek_impl(int second);
+ void config(const char* key,const char* value,void* user_data);
+
+ protected:
+ int getTotalLength();
+ void processStreamState(TimeStamp* stamp,AudioFrame* audioFrame);
+ void audioSetup(AudioFrame* setupFrame);
+ int doFrameFind();
+
+};
+#endif
diff --git a/mpeglib/lib/decoder/tplayPlugin.cpp b/mpeglib/lib/decoder/tplayPlugin.cpp
new file mode 100644
index 00000000..01c44cbc
--- /dev/null
+++ b/mpeglib/lib/decoder/tplayPlugin.cpp
@@ -0,0 +1,264 @@
+/*
+ tplay 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 "tplayPlugin.h"
+
+#include "../tplay/tplayfunctions.h"
+
+#include <iostream>
+
+using namespace std;
+
+TplayPlugin::TplayPlugin() {
+ info=new info_struct();
+
+ info->progname = NULL;
+ info->loop = FALSE;
+ info->in_seconds = FALSE;
+ info->speed = DEFAULT_SPEED;
+ info->bits = DEFAULT_BITS;
+ info->channels = DEFAULT_CHANNELS;
+ info->buffer_size = BUFFER_SIZE;
+ info->show_usage = FALSE;
+ info->swap = FALSE;
+ info->forceraw = FALSE;
+ info->force = FALSE;
+ info->device = NULL;
+ info->verbose = FALSE;
+ info->optind = 0;
+ info->buffer = NULL;
+ info->firstblock = NULL;
+ info->number_of_blocks = 0;
+ info->readblock = 0;
+ info->writeblock = 0;
+ info->readcount = 0;
+ info->writecount = 0;
+ info->alldone = FALSE;
+ info->overflow = FALSE;
+ info->underflow = FALSE;
+ info->audioset = FALSE;
+ info->headerskip = 0;
+ info->blocksize = 4096;
+ info->bytes_on_last_block = 0;
+
+ startStamp=new TimeStamp();
+ endStamp=new TimeStamp();
+}
+
+
+TplayPlugin::~TplayPlugin() {
+ delete startStamp;
+ delete endStamp;
+ delete info;
+}
+
+
+
+void TplayPlugin::decoder_loop() {
+ int bytesread, count, stereo;
+ char *p, *bufferp;
+
+ if (input == NULL) {
+ cout << "TplayPlugin::decoder_loop input is NULL"<<endl;
+ exit(0);
+ }
+ if (output == NULL) {
+ cout << "TplayPlugin::decoder_loop output is NULL"<<endl;
+ exit(0);
+ }
+
+ TimeStamp* stamp;
+ long pos;
+
+ info->buffer = (char*) malloc(info->buffer_size * sizeof(char));
+
+ while(runCheck()) {
+ switch(streamState) {
+ case _STREAM_STATE_FIRST_INIT : {
+ read_header();
+
+ if (info->channels == 1)
+ stereo = FALSE;
+ else
+ stereo = TRUE;
+
+ info->number_of_blocks = 0;
+ bufferp = info->buffer;
+ pluginInfo->setLength(getTotalLength());
+ output->writeInfo(pluginInfo);
+ lhasLength=true;
+
+ setStreamState(_STREAM_STATE_INIT);
+ break;
+ }
+ case _STREAM_STATE_INIT :
+ setStreamState(_STREAM_STATE_PLAY);
+ cout << "audioSetup call"<<endl;
+ output->audioOpen();
+ output->audioSetup(info->speed, stereo, 1, 0, info->bits);
+ break;
+ case _STREAM_STATE_PLAY :
+ bytesread = 0;
+ count = 0;
+ p = bufferp;
+ while ((bytesread < info->blocksize) && (count != -1) &&
+ ((count = input->read(p,info->blocksize-bytesread))!=0)){
+ p += count;
+ bytesread += count;
+ }
+ if (info->swap) {
+ swap_block(bufferp, bytesread);
+ }
+
+ if (bytesread > 0) {
+ pos=input->getBytePosition();
+ stamp=input->getTimeStamp(pos-bytesread);
+ output->audioPlay(stamp,endStamp,(char *) bufferp, bytesread);
+ }
+
+ if (bytesread < info->blocksize) {
+ info->alldone = TRUE;
+
+ }
+ break;
+ case _STREAM_STATE_WAIT_FOR_END:
+ // exit while loop
+ lDecoderLoop=false;
+ break;
+ default:
+ cout << "unknown stream state:"<<streamState<<endl;
+ }
+ }
+ cout << "tplay exit"<<endl;
+ free(info->buffer);
+ info->buffer = NULL;
+ output->audioFlush();
+}
+
+
+int TplayPlugin::seek_impl(int second) {
+ int bytes_per_second;
+ int seconds;
+ int back;
+
+
+ bytes_per_second = info->speed * info->channels * (info->bits / 8);
+
+
+
+ seconds = bytes_per_second * second;
+ back=input->seek(seconds);
+
+ return back;
+}
+
+
+void TplayPlugin::config(const char* key,const char* value,void* user_data) {
+ DecoderPlugin::config(key,value,user_data);
+}
+
+
+void TplayPlugin::swap_block(char * buffer, int blocksize) {
+ register int i;
+ char c, *p;
+
+ p = buffer;
+ for (i = 0; i < (blocksize / 2); i++) {
+ c = *p;
+ *p = *(p + 1);
+ *++p = c;
+ p++;
+ }
+}
+
+
+void TplayPlugin::read_header() {
+ int bytesread, count;
+ char *p, *bufferp;
+
+ info->firstblock = (char*) malloc(info->blocksize * sizeof(char));
+ bufferp = info->firstblock;
+ if (!info->forceraw) {
+ bytesread = 0;
+ count = 0;
+ p = bufferp;
+ while ((bytesread < info->blocksize) && (count != -1) &&
+ ((count=input->read(p,info->blocksize-bytesread)) != 0)){
+ p += count;
+ bytesread += count;
+ }
+
+ if (bytesread < SUN_HDRSIZE)
+ cout << "Sample size is too small"<<endl;
+
+ if (read_au(info,info->firstblock) && read_wav(info,info->firstblock)) {
+ if (info->verbose)
+ printf("Playing raw data: %ld samples/s, %d bits, %d channels.\n",
+ info->speed, info->bits, info->channels);
+ }
+
+ if (info->swap)
+ swap_block(bufferp, bytesread);
+
+ if (bytesread < info->blocksize) {
+ info->alldone = TRUE;
+ info->bytes_on_last_block = bytesread;
+ return;
+ }
+
+ if (info->headerskip) {
+ count = 0;
+ bytesread = info->blocksize - info->headerskip;
+ p = info->firstblock + (info->blocksize - info->headerskip);
+ while ((bytesread < info->blocksize) && (count != -1) &&
+ ((count = input->read(p,info->blocksize - bytesread)) != 0)) {
+ p += count;
+ bytesread += count;
+ }
+ }
+
+ info->writeblock++;
+ info->writecount++;
+ }
+ else {
+ if (info->verbose)
+ printf("Playing raw data: %ld samples/s, %d bits, %d channels\n",
+ info->speed, info->bits, info->channels);
+ }
+}
+
+/**
+ Nobody is perfect I'm too tired to fix this race
+*/
+
+int TplayPlugin::getTotalLength() {
+ float wavfilesize = input->getByteLength();
+ int back=0;
+
+
+ float frequence=info->speed;
+
+ int bits=info->bits;
+
+
+ if (bits == 16) {
+ wavfilesize=wavfilesize/2;
+ }
+ if (info->channels==2) {
+ wavfilesize=wavfilesize/2;
+ }
+ if (frequence != 0) {
+ back=(int)(wavfilesize/frequence);
+ }
+ return back;
+}
diff --git a/mpeglib/lib/decoder/tplayPlugin.h b/mpeglib/lib/decoder/tplayPlugin.h
new file mode 100644
index 00000000..daa0de74
--- /dev/null
+++ b/mpeglib/lib/decoder/tplayPlugin.h
@@ -0,0 +1,47 @@
+/*
+ tplay 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 __TPLAYPLUGIN_H
+#define __TPLAYPLUGIN_H
+
+#include "../decoder/decoderPlugin.h"
+#include <kdemacros.h>
+/**
+ The tplayPlugin is ugly and needs a rewrite.
+ Im not sure if you can make mutiple instances of it
+*/
+
+class KDE_EXPORT TplayPlugin : public DecoderPlugin {
+
+ struct info_struct* info;
+ class TimeStamp* startStamp;
+ class TimeStamp* endStamp;
+
+ public:
+ TplayPlugin();
+ ~TplayPlugin();
+
+ void decoder_loop();
+ int seek_impl(int second);
+ void config(const char* key,const char* value,void* user_data);
+
+ protected:
+ int getTotalLength();
+
+ private:
+ void swap_block(char* buffer, int blocksize);
+ void read_header();
+
+
+};
+#endif
diff --git a/mpeglib/lib/decoder/vorbisPlugin.cpp b/mpeglib/lib/decoder/vorbisPlugin.cpp
new file mode 100644
index 00000000..b32ba93f
--- /dev/null
+++ b/mpeglib/lib/decoder/vorbisPlugin.cpp
@@ -0,0 +1,305 @@
+/*
+ vorbis player plugin
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "vorbisPlugin.h"
+
+#include <iostream>
+
+using namespace std;
+
+#ifdef OGG_VORBIS
+
+size_t fread_func(void *ptr, size_t size, size_t nmemb, void *stream) {
+ InputStream* input=((VorbisPlugin*)stream)->getInputStream();
+ int bytes=input->read((char*)ptr,size*nmemb);
+ // workaround for RC3, report success during seek
+ /*
+ if (((VorbisPlugin*)stream)->vorbis_seek_bug_active == true) {
+ errno=0;
+ return 0;
+ }
+ */
+ // error on read and no "seek workaround"
+ if (bytes == 0) {
+ //
+ // If different thread close the input we signal
+ // a read error to vorbis
+ //
+ if (input->isOpen() == false) {
+ // note: errno is in this thread another variable, than in
+ // the thread which closed the file.
+ // here we "fake" the errno var.
+ errno=EBADF;
+ return 0;
+ }
+ }
+ // successful read
+ return bytes;
+}
+
+
+int fseek_func(void *stream, ogg_int64_t offset, int whence) {
+ int ret=-1;
+ InputStream* input=((VorbisPlugin*)stream)->getInputStream();
+
+ switch(whence) {
+ case SEEK_SET:
+ ret=input->seek(offset);
+ break;
+ case SEEK_CUR:
+ ret=input->seek(input->getBytePosition()+offset);
+ break;
+ case SEEK_END:
+ ret=input->seek(input->getByteLength());
+ break;
+ default:
+ cout << "fseek_func VorbisPlugn strange call"<<endl;
+ }
+
+ if (ret == false) {
+ // vorbis does not handle errors in seek at all
+ // and if they are handled vorbis segfaults. (RC3)
+ // here we always "success" but set an seek_error_mark
+ //
+ ret=-1;
+ }
+
+ return ret;
+
+}
+
+
+int fclose_func (void *) {
+ //InputStream* input=(InputStream*) stream;
+
+ // its handled different in kmpg
+ // we close the stream if the decoder signals eof.
+ return true;
+
+}
+
+
+long ftell_func (void *stream) {
+ InputStream* input=((VorbisPlugin*)stream)->getInputStream();
+ return input->getBytePosition();
+}
+
+
+VorbisPlugin::VorbisPlugin() {
+
+
+ memset(&vf, 0, sizeof(vf));
+ timeDummy=new TimeStamp();
+ pcmout=new char[4096];
+ lnoLength=false;
+ lshutdown=true;
+
+}
+
+
+VorbisPlugin::~VorbisPlugin() {
+ delete timeDummy;
+ delete pcmout;
+}
+
+
+// here we can config our decoder with special flags
+void VorbisPlugin::config(const char* key,const char* value,void* user_data) {
+
+ if (strcmp(key,"-c")==0) {
+ lnoLength=true;
+ }
+ DecoderPlugin::config(key,value,user_data);
+}
+
+
+int VorbisPlugin::init() {
+ ov_callbacks callbacks;
+
+ callbacks.read_func = fread_func;
+ callbacks.seek_func = fseek_func;
+ callbacks.close_func = fclose_func;
+ callbacks.tell_func = ftell_func;
+
+ // here is the hack to pass the pointer to
+ // our streaming interface.
+
+ if(ov_open_callbacks(this, &vf, NULL, 0, callbacks) < 0) {
+ return false;
+ }
+
+ return true;
+}
+
+
+// called by decoder thread
+int VorbisPlugin::processVorbis(vorbis_info* vi,vorbis_comment* comment) {
+
+ // decode
+ int ret;
+ int current_section=-1; /* A vorbis physical bitstream may
+ consist of many logical sections
+ (information for each of which may be
+ fetched from the vf structure). This
+ value is filled in by ov_read to alert
+ us what section we're currently
+ decoding in case we need to change
+ playback settings at a section
+ boundary */
+ ret=ov_read(&vf,pcmout,4096,0,2,1,&current_section);
+ switch(ret){
+ case 0:
+ /* EOF */
+ lDecoderLoop=false;
+ break;
+ case -1:
+ /* error in the stream. Not a problem, just reporting it in
+ case we (the app) cares. In this case, we don't. */
+ cout << "error found"<<endl;
+ break;
+ default:
+ if(current_section!=last_section){
+ vi=ov_info(&vf,-1); /* The info struct is different in each
+ section. vf holds them all for the
+ given bitstream. This requests the
+ current one */
+
+ double timeoffset=ov_time_tell(&vf);
+
+ comment = ov_comment(&vf, -1);
+ if(comment) {
+ cout << "we have a comment:"<<timeoffset<<endl;
+ }
+ }
+ last_section=current_section;
+ output->audioPlay(timeDummy,timeDummy,pcmout,ret);
+ break;
+ }
+ return true;
+}
+
+
+void VorbisPlugin::decoder_loop() {
+ vorbis_info *vi=NULL;
+ vorbis_comment *comment=NULL;
+ last_section=0;
+ current_section=0;
+
+
+
+ if (input == NULL) {
+ cout << "VorbisPlugin::decoder_loop input is NULL"<<endl;
+ exit(0);
+ }
+ if (output == NULL) {
+ cout << "VorbisPlugin::decoder_loop output is NULL"<<endl;
+ exit(0);
+ }
+ // init audio stream
+ output->audioInit();
+
+ /********** Decode setup ************/
+ // start decoding
+ lshutdown=false;
+ /**
+ Vorbis RC3 introducted a new bug:
+ seek on a closed stream segfaults vorbis.
+ The bugfix in vorbis is (RC3) around line 1190 should be:
+ seek_error:
+ // the caller of this goto may not set a return code
+ ret=OV_ENOSEEK;
+ The workaround is to check if we are in a seek operation
+ and always "fake" successful reads.
+ */
+ vorbis_seek_bug_active=false;
+
+
+ while(runCheck()) {
+
+ switch(streamState) {
+ case _STREAM_STATE_FIRST_INIT :
+ if (init()== false) {
+ // total failure. exit decoding
+ lDecoderLoop=false;
+ break;
+ }
+ // now init stream
+ vi=ov_info(&vf,-1);
+ if (lnoLength==false) {
+ pluginInfo->setLength(getTotalLength());
+ output->writeInfo(pluginInfo);
+ }
+ output->audioOpen();
+ output->audioSetup(vi->rate,vi->channels-1,1,0,16);
+
+
+ lhasLength=true;
+ setStreamState(_STREAM_STATE_PLAY);
+ break;
+ case _STREAM_STATE_INIT :
+ case _STREAM_STATE_PLAY :
+ processVorbis(vi,comment);
+ break;
+ case _STREAM_STATE_WAIT_FOR_END:
+ // exit while loop
+ lDecoderLoop=false;
+ usleep(2000000);
+ break;
+ default:
+ cout << "unknown stream state vorbis decoder:"<<streamState<<endl;
+ }
+
+ }
+
+ lshutdown=true;
+ ov_clear(&vf); /* ov_clear closes the stream if its open. Safe to
+ call on an uninitialized structure as long as
+ we've zeroed it */
+ memset(&vf, 0, sizeof(vf));
+
+ output->audioFlush();
+}
+
+// vorbis can seek in streams
+int VorbisPlugin::seek_impl(int second) {
+ vorbis_seek_bug_active=true;
+ ov_time_seek(&vf,(double) second);
+ vorbis_seek_bug_active=false;
+ return true;
+}
+
+
+
+int VorbisPlugin::getTotalLength() {
+ int back=0;
+ int byteLen=input->getByteLength();
+ if (byteLen == 0) {
+ return 0;
+ }
+ /* Retrieve the length in second*/
+ shutdownLock();
+ if (lshutdown==false) {
+ back = (int) ov_time_total(&vf, -1);
+ }
+ shutdownUnlock();
+
+ return back;
+}
+
+
+
+
+#endif
+//OGG_VORBIS
+
+
diff --git a/mpeglib/lib/decoder/vorbisPlugin.h b/mpeglib/lib/decoder/vorbisPlugin.h
new file mode 100644
index 00000000..b680ed69
--- /dev/null
+++ b/mpeglib/lib/decoder/vorbisPlugin.h
@@ -0,0 +1,87 @@
+/*
+ vorbis player plugin
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#ifndef __VORBISPLUGIN_H
+#define __VORBISPLUGIN_H
+
+#include "nukePlugin.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+
+#ifndef OGG_VORBIS
+class VorbisPlugin : public NukePlugin {
+};
+#else
+
+
+#include <vorbis/codec.h>
+#include <vorbis/vorbisfile.h>
+
+/**
+ callbacks from vorbisfile
+*/
+extern "C" {
+
+extern size_t fread_func (void *ptr,size_t size,size_t nmemb, void *stream);
+extern int fseek_func (void *stream, ogg_int64_t offset, int whence);
+extern int fclose_func (void *stream);
+extern long ftell_func (void *stream);
+
+}
+
+
+class VorbisPlugin : public DecoderPlugin {
+
+ OggVorbis_File vf;
+
+
+ // END vorbis setup
+
+
+ int lnoLength;
+ int lAutoPlay;
+ TimeStamp* timeDummy;
+ char* pcmout; // temporay pcm buffer
+ int last_section;
+ int current_section;
+ int lshutdown;
+
+ public:
+ VorbisPlugin();
+ ~VorbisPlugin();
+
+ void decoder_loop();
+ int seek_impl(int second);
+ void config(const char* key,const char* value,void* user_data);
+
+ // vorbis bug workaround [START]
+ int vorbis_seek_bug_active;
+ ::InputStream* getInputStream() { return input; }
+ // vorbis bug workaround [END]
+
+ private:
+ int processVorbis(vorbis_info* vi,vorbis_comment* comment);
+ int getTotalLength();
+ int init();
+
+};
+
+#endif
+//OGG_VORBIS
+
+#endif
diff --git a/mpeglib/lib/dummy.cpp b/mpeglib/lib/dummy.cpp
new file mode 100644
index 00000000..94bd1cb7
--- /dev/null
+++ b/mpeglib/lib/dummy.cpp
@@ -0,0 +1,6 @@
+
+
+
+static int dummy() {
+ return 0;
+}
diff --git a/mpeglib/lib/frame/IOFrameQueue.cpp b/mpeglib/lib/frame/IOFrameQueue.cpp
new file mode 100644
index 00000000..9a13f1fa
--- /dev/null
+++ b/mpeglib/lib/frame/IOFrameQueue.cpp
@@ -0,0 +1,60 @@
+/*
+ queues frames in a "empty" and "data" queue
+ 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 "IOFrameQueue.h"
+
+
+IOFrameQueue::IOFrameQueue(int size) {
+ empty=new FrameQueue(size);
+ data=new FrameQueue(size);
+
+}
+
+
+IOFrameQueue::~IOFrameQueue() {
+ delete empty;
+ delete data;
+}
+
+
+//
+// empty queue
+//
+int IOFrameQueue::emptyQueueCanRead() {
+ return empty->canRead();
+}
+
+
+int IOFrameQueue::emptyQueueCanWrite() {
+ return empty->canWrite();
+}
+
+
+
+
+//
+// data queue
+//
+int IOFrameQueue::dataQueueCanRead() {
+ return data->canRead();
+}
+
+
+int IOFrameQueue::dataQueueCanWrite() {
+ return data->canWrite();
+}
+
+
+
+
+
diff --git a/mpeglib/lib/frame/IOFrameQueue.h b/mpeglib/lib/frame/IOFrameQueue.h
new file mode 100644
index 00000000..d56f25aa
--- /dev/null
+++ b/mpeglib/lib/frame/IOFrameQueue.h
@@ -0,0 +1,60 @@
+/*
+ queues frames in a "empty" and "data" queue
+ 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 __IOFRAMEQUEUE_H
+#define __IOFRAMEQUEUE_H
+
+#include "frameQueue.h"
+#include <kdemacros.h>
+
+/**
+ This class can store up to <size> frames.
+ The frames are marked "empty" these frames can be re-used
+ and filled with data.
+ The other queue stores "data" frames. These frames can
+ be dequeued and then are be passed to the "empty" queue.
+
+ Note: you need to _fill_ the empty queue with allocated frames,
+ after constructions. The pointers then are owned by this
+ class (== deleted in destructor)
+
+*/
+
+class KDE_EXPORT IOFrameQueue {
+
+
+ public:
+ IOFrameQueue(int size);
+ ~IOFrameQueue();
+
+ //
+ // empty queue
+ //
+ int emptyQueueCanRead();
+ int emptyQueueCanWrite();
+
+
+ //
+ // data queue
+ //
+ int dataQueueCanRead();
+ int dataQueueCanWrite();
+
+
+ protected:
+ FrameQueue* empty;
+ FrameQueue* data;
+
+};
+#endif
diff --git a/mpeglib/lib/frame/Makefile.am b/mpeglib/lib/frame/Makefile.am
new file mode 100644
index 00000000..753b5f18
--- /dev/null
+++ b/mpeglib/lib/frame/Makefile.am
@@ -0,0 +1,33 @@
+
+# ---- @OS_TYPE@/@ARCH_TYPE@ ----
+
+INCLUDES = $(all_includes)
+
+EXTRA_DIST = README
+
+kmpgincludedir = $(includedir)/$(THIS_LIB_NAME)/frame
+
+kmpginclude_HEADERS = pcmFrame.h audioFrame.h \
+ floatFrame.h frameQueue.h frame.h \
+ IOFrameQueue.h audioFrameQueue.h \
+ framer.h rawDataBuffer.h rawFrame.h
+
+noinst_LTLIBRARIES = libframe.la
+
+libframe_la_SOURCES = pcmFrame.cpp \
+ audioFrame.cpp floatFrame.cpp frame.cpp \
+ frameQueue.cpp IOFrameQueue.cpp\
+ audioFrameQueue.cpp framer.cpp \
+ rawDataBuffer.cpp rawFrame.cpp
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/frame/README b/mpeglib/lib/frame/README
new file mode 100644
index 00000000..9e21059f
--- /dev/null
+++ b/mpeglib/lib/frame/README
@@ -0,0 +1,68 @@
+
+
+
+Frames
+======
+
+
+Frames are needed for passing data between decoders around.
+A decoder gets an mpeg audio encoded frame as input and
+writes data to an audioFrame (pcm/float)
+
+ frame
+ |
+ audioFrame
+ / \
+ pcmFrame floatFrame
+
+
+FrameQueues
+===========
+
+FrameQueues are needed for storing some frames. (For example
+you store 100 pre-decoded pcmFrames.)
+A FrameQueue is a queue, simply not more.
+
+IOFrameQueues
+=============
+
+IOFrameQueues deal with the problem, that you first start
+with an empty FrameQueue (this is a FrameQueue which contains
+prealloceated data, but the data is empty (eg:all pcm samples zero)
+Only after converting an "empty" Frame by a decoder (mp3decoder)
+the frame if "full" (== Frame with data)
+So: IOFrameQueues mark frames with
+
+i) empty
+ii) data
+
+You can get an empty Frame from the empty-frame-queue and
+then enqueue it in the data-frame-queue.
+After the frame was used (played) we dequeue it from the
+data queue and put them back in the empty queue.
+You can see IOFrameQueues as a ringbuffer.
+(get free space. write to it. read data. mark space as free,....)
+
+
+ FrameQueue
+ |
+ IOFrameQueue
+ /
+ audioFrameQueue
+
+
+AudioFrameQueue
+===============
+
+A IOFrameQueue, which allows converting "dataFrames back to continous
+stream".
+What is this?
+Lets say an application wants only 20 byte from a dataFrame which
+contains 3KB of data?
+There must be some mechanism to read less or more data from the
+queue. And the data should be written to a continus memory
+segment.
+AudioFrameQueue deals with this problem.You can read data from
+the queue to a given pointer location.
+
+
diff --git a/mpeglib/lib/frame/audioFrame.cpp b/mpeglib/lib/frame/audioFrame.cpp
new file mode 100644
index 00000000..55464afa
--- /dev/null
+++ b/mpeglib/lib/frame/audioFrame.cpp
@@ -0,0 +1,111 @@
+/*
+ abstract definition of an audio frame
+ 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 "audioFrame.h"
+
+#include <iostream>
+
+using namespace std;
+
+AudioFrame::AudioFrame() {
+
+ stereo=-1;
+ frequencyHZ=-1;
+
+ sampleSize=-1;
+ lBigEndian=-1;
+ lSigned=-1;
+ setFrameType(_FRAME_AUDIO_BASE);
+}
+
+
+AudioFrame::~AudioFrame() {
+}
+
+
+int AudioFrame::getLen() {
+ cout << "direct virtual call AudioFrame::getLen"<<endl;
+ return 0;
+}
+
+
+void AudioFrame::setLen(int ) {
+ cout << "direct virtual call AudioFrame::setLen"<<endl;
+}
+
+
+int AudioFrame::getSize() {
+ cout << "direct virtual call AudioFrame::getSize"<<endl;
+ return 0;
+}
+
+
+void AudioFrame::putFloatData(float* ,int ) {
+ cout << "direct virtual call AudioFrame::putFloatData"<<endl;
+}
+
+void AudioFrame::putFloatData(float* ,float* ,int ) {
+ cout << "direct virtual call AudioFrame::putFloatData L/R version"<<endl;
+}
+
+void AudioFrame::clearrawdata() {
+ cout << "direct virtual call AudioFrame::clearrawdata"<<endl;
+}
+
+void AudioFrame::setFrameFormat(int stereo,int freq) {
+ this->stereo=stereo;
+ this->frequencyHZ=freq;
+}
+
+
+
+int AudioFrame::isFormatEqual(AudioFrame* compare) {
+ if(compare->getStereo() != stereo) {
+ return false;
+ }
+ if(compare->getSampleSize() != sampleSize) {
+ return false;
+ }
+ if(compare->getBigEndian() != lBigEndian) {
+ return false;
+ }
+ if(compare->getFrequenceHZ() != frequencyHZ) {
+ return false;
+ }
+ if(compare->getSigned() != lSigned) {
+ return false;
+ }
+ return true;
+}
+
+void AudioFrame::print(const char* msg) {
+ cout << "PCMFrame::print:"<<msg<<endl;
+ cout << "stereo:"<<stereo<<endl;
+ cout << "sampleSize:"<<sampleSize<<endl;
+ cout << "lBigEndian:"<<lBigEndian<<endl;
+ cout << "frequencyHZ:"<<frequencyHZ<<endl;
+ cout << "lSigned:"<<lSigned<<endl;
+}
+
+
+void AudioFrame::copyFormat(AudioFrame* dest) {
+ if (dest->getFrameType() != _FRAME_AUDIO_BASE) {
+ cout << "cannot copy frameFormat into frametype!= _FRAME_AUDIO_BASE"<<endl;
+ exit(0);
+ }
+ dest->setFrameFormat(getStereo(),getFrequenceHZ());
+ dest->sampleSize=getSampleSize();
+ dest->lBigEndian=getBigEndian();
+ dest->lSigned=getSigned();
+}
diff --git a/mpeglib/lib/frame/audioFrame.h b/mpeglib/lib/frame/audioFrame.h
new file mode 100644
index 00000000..b1c586c3
--- /dev/null
+++ b/mpeglib/lib/frame/audioFrame.h
@@ -0,0 +1,83 @@
+/*
+ abstract definition of an audio frame
+ 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 __AUDIOFRAME_H
+#define __AUDIOFRAME_H
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef WORDS_BIGENDIAN
+#define AUDIOFRAME_BIGENDIAN 1
+#else
+#define AUDIOFRAME_BIGENDIAN 0
+#endif
+
+
+#include "frame.h"
+#include <kdemacros.h>
+#define SCALFACTOR SHRT_MAX
+#define MP3FRAMESIZE (2*2*2*32*18)
+
+
+class KDE_EXPORT AudioFrame : public Frame {
+
+ int stereo;
+ int frequencyHZ;
+
+ public:
+ AudioFrame();
+ virtual ~AudioFrame();
+
+ // info about "import" data
+ void setFrameFormat(int stereo,int freq);
+
+ inline int getStereo() { return stereo; }
+ inline int getFrequenceHZ() { return frequencyHZ; }
+
+ // these return values depend on the implementation
+ // how the data is stored internally after "import"
+ inline int getSampleSize() { return sampleSize; }
+ inline int getBigEndian() { return lBigEndian; }
+ inline int getSigned() { return lSigned; }
+
+ // info about output
+ virtual int getLen();
+ virtual void setLen(int len);
+ virtual int getSize();
+ virtual void clearrawdata();
+
+ // data import
+ virtual void putFloatData(float* data,int len);
+ virtual void putFloatData(float* left,float* right,int len);
+
+
+ int isFormatEqual(AudioFrame* compare);
+ // Note: this can only be called with _real_ AudioFrame's as dest
+ void copyFormat(AudioFrame* dest);
+
+ void print(const char* msg);
+
+ protected:
+ int sampleSize;
+ int lBigEndian;
+ int lSigned;
+
+};
+
+
+#endif
diff --git a/mpeglib/lib/frame/audioFrameQueue.cpp b/mpeglib/lib/frame/audioFrameQueue.cpp
new file mode 100644
index 00000000..16488748
--- /dev/null
+++ b/mpeglib/lib/frame/audioFrameQueue.cpp
@@ -0,0 +1,339 @@
+/*
+ queues audio frames in an IOQueue, allows streaming from frames
+ 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 "audioFrameQueue.h"
+
+#define _FLOAT_2_TRANSFER 1
+#define _FLOAT_1_TRANSFER 2
+#define _INT_2_TRANSFER 3
+#define _INT_1_TRANSFER 4
+#define _FORWARD_TRANSFER 5
+
+#include <iostream>
+
+using namespace std;
+
+AudioFrameQueue::AudioFrameQueue(int queueSize,
+ int frameSize,
+ int frameType):IOFrameQueue(queueSize) {
+ switch(frameType) {
+ case _FRAME_AUDIO_PCM: {
+ // fill queue with elements
+ while(emptyQueueCanWrite()) {
+ PCMFrame* pcmFrame=new PCMFrame(frameSize);
+ emptyQueueEnqueue(pcmFrame);
+ }
+ break;
+ }
+ case _FRAME_AUDIO_FLOAT: {
+ // fill queue with elements
+ while(emptyQueueCanWrite()) {
+ FloatFrame* floatFrame=new FloatFrame(frameSize);
+ emptyQueueEnqueue(floatFrame);
+ }
+ break;
+ }
+ default:
+ cout << "unknown frameType:"<<Frame::getFrameName(frameType)
+ <<" in AudioFrameQueue"<<endl;
+ exit(0);
+ }
+ len=0;
+ currentAudioFrame=new AudioFrame();
+ currentRead=0;
+ this->frameType=frameType;
+}
+
+
+AudioFrameQueue::~AudioFrameQueue() {
+ delete currentAudioFrame;
+}
+
+
+void AudioFrameQueue::emptyQueueEnqueue(AudioFrame* frame) {
+ empty->enqueue(frame);
+}
+
+
+AudioFrame* AudioFrameQueue::emptyQueueDequeue() {
+ return (AudioFrame*)empty->dequeue();
+}
+
+
+void AudioFrameQueue::dataQueueEnqueue(AudioFrame* frame) {
+ if (data->getFillgrade() == 0) {
+ frame->copyFormat(currentAudioFrame);
+ }
+
+ len+=frame->getLen();
+ data->enqueue(frame);
+
+}
+
+
+AudioFrame* AudioFrameQueue::dataQueueDequeue() {
+ AudioFrame* back=(AudioFrame*)data->dequeue();
+ currentRead=0;
+ len-=back->getLen();
+ back->copyFormat(currentAudioFrame);
+ return back;
+}
+
+AudioFrame* AudioFrameQueue::getCurrent() {
+ return currentAudioFrame;
+}
+
+
+int AudioFrameQueue::getLen() {
+ return len-currentRead;
+}
+
+
+int AudioFrameQueue::copy(float* left,float* right,int wantLen) {
+ if (frameType != _FRAME_AUDIO_FLOAT) {
+ cout << "AudioFrameQueue::copy class is frameType short int"<<endl;
+ exit(0);
+ }
+ // whats mux?
+ // well the routines are badly broken and need a rewrite
+ // mux deals with the problem that
+ // if the src is stereo we expect the left/right pointers
+ // to have half the size of wantlen*2
+ // ridicouls complex?
+ // right, as I said, this needs a clean solution
+ int mux=1;
+
+ if (currentAudioFrame->getStereo()) {
+ wantLen*=2;
+ mux=2;
+ }
+
+ int back=copygeneric((char*)left,(char*)right,
+ wantLen,_FLOAT_2_TRANSFER,mux);
+ if (currentAudioFrame->getStereo()) back/=2;
+
+ return back;
+}
+
+int AudioFrameQueue::copy(short int* left,short int* right,int wantLen) {
+ if (frameType != _FRAME_AUDIO_PCM) {
+ cout << "AudioFrameQueue::copy class is frameType float"<<endl;
+ exit(0);
+ }
+ // for this mux ugly hack read above
+ int mux=1;
+
+ if (currentAudioFrame->getStereo()) {
+ wantLen*=2;
+ mux=2;
+ }
+ int back=copygeneric((char*)left,(char*)right,
+ wantLen,_INT_2_TRANSFER,mux);
+ if (currentAudioFrame->getStereo()) back/=2;
+
+ return back;
+}
+
+int AudioFrameQueue::copy(short int* dest,int wantLen) {
+ if (frameType != _FRAME_AUDIO_PCM) {
+ cout << "AudioFrameQueue::copy class is frameType int single"<<endl;
+ exit(0);
+ }
+ int back=copygeneric((char*)dest,(char*)NULL,
+ wantLen,_INT_1_TRANSFER,1);
+ return back;
+}
+
+int AudioFrameQueue::copy(float* dest,int wantLen) {
+ if (frameType != _FRAME_AUDIO_FLOAT) {
+ cout << "AudioFrameQueue::copy class is frameType float single"<<endl;
+ exit(0);
+ }
+ int back=copygeneric((char*)dest,(char*)NULL,
+ wantLen,_FLOAT_1_TRANSFER,1);
+ return back;
+}
+
+void AudioFrameQueue::forwardStreamSingle(int forwardLen) {
+ int back=copygeneric((char*)NULL,(char*)NULL,
+ forwardLen,_FORWARD_TRANSFER,1);
+ if (back != forwardLen) {
+ cout << "error while forwarding stream"<<endl;
+ exit(0);
+ }
+}
+
+void AudioFrameQueue::forwardStreamDouble(int forwardLen) {
+
+ int mux=1;
+
+ if (currentAudioFrame->getStereo()) {
+ forwardLen*=2;
+ }
+ int back=copygeneric((char*)NULL,(char*)NULL,
+ forwardLen,_FORWARD_TRANSFER,mux);
+
+ if (back != forwardLen) {
+ cout << "error while forwarding stream"<<endl;
+ exit(0);
+ }
+}
+
+
+int AudioFrameQueue::copygeneric(char* left,char* right,
+ int wantLen,int version,int mux) {
+
+
+ int processed=currentRead;
+
+ if (wantLen > (len-processed)) {
+ wantLen=len-processed;
+ }
+ int pos=0;
+ int doLen=wantLen;
+ while(doLen > 0) {
+ AudioFrame* current=(AudioFrame*)data->peekqueue(pos);
+ int totallen=current->getLen();
+ int restlen=totallen-processed;
+ int copylen=doLen;
+ if (doLen > restlen) {
+ copylen=restlen;
+ }
+ doLen-=copylen;
+
+ switch(version) {
+ case _FLOAT_2_TRANSFER:
+ transferFrame((float*)left,
+ (float*)right,
+ (FloatFrame*) current,processed,copylen);
+ left+=copylen/mux*(sizeof(float));
+ right+=copylen/mux*(sizeof(float));
+ break;
+ case _FLOAT_1_TRANSFER:
+ transferFrame((float*)left,
+ (FloatFrame*) current,processed,copylen);
+ left+=copylen*sizeof(short int);
+ break;
+ case _INT_2_TRANSFER:
+ transferFrame((short int*)left,
+ (short int*)right,
+ (PCMFrame*) current,processed,copylen);
+ left+=copylen/mux*(sizeof(short int));
+ right+=copylen/mux*(sizeof(short int));
+ break;
+ case _INT_1_TRANSFER:
+ transferFrame((short int*)left,
+ (PCMFrame*) current,processed,copylen);
+ left+=copylen*sizeof(short int);
+ break;
+ case _FORWARD_TRANSFER:
+ break;
+ default:
+ cout << "unknown transfer method AudioFrameQueue::copygeneric"<<endl;
+ exit(0);
+ }
+ processed+=copylen;
+ if ( processed == totallen) {
+ processed=0;
+ if (version == _FORWARD_TRANSFER) {
+ current=dataQueueDequeue();
+ emptyQueueEnqueue(current);
+ } else {
+ pos++;
+ }
+ }
+ }
+ if (version == _FORWARD_TRANSFER) {
+ currentRead=processed;
+ }
+ if (doLen < 0) {
+ cout << "error while copy in AudioFrameQueue"<<endl;
+ exit(0);
+ }
+ return wantLen;
+}
+
+
+void AudioFrameQueue::transferFrame(float* left,float* right,
+ FloatFrame* current,int start,int len) {
+ float* ptr=current->getData()+start;
+ switch(currentAudioFrame->getStereo()) {
+ case true:
+ len=len/2;
+ while(len) {
+ *left++=*ptr++;
+ *right++=*ptr++;
+ len--;
+ }
+ break;
+ case false:
+ while(len) {
+ *left++=*ptr;
+ *right++=*ptr++;
+ len--;
+ }
+ break;
+ default:
+ cout << "bad stereo value AudioFrameQueue::transferFrame (float)"<<endl;
+ exit(0);
+ }
+}
+
+void AudioFrameQueue::transferFrame(short int* left,short int* right,
+ PCMFrame* current,int start,int len) {
+ short int* ptr=current->getData()+start;
+ switch(currentAudioFrame->getStereo()) {
+ case true:
+ len=len/2;
+ while(len) {
+ *left++=*ptr++;
+ *right++=*ptr++;
+ len--;
+ }
+ break;
+ case false:
+ while(len) {
+ *left++=*ptr;
+ *right++=*ptr++;
+ len--;
+ }
+ break;
+ default:
+ cout << "bad stereo value AudioFrameQueue::transferFrame (int)"<<endl;
+ exit(0);
+ }
+}
+
+
+void AudioFrameQueue::transferFrame(short int* dest,
+ PCMFrame* current,int start,int len) {
+ short int* ptr=current->getData()+start;
+ memcpy(dest,ptr,len*sizeof(short int));
+
+}
+
+
+void AudioFrameQueue::transferFrame(float* dest,
+ FloatFrame* current,int start,int len) {
+ float* ptr=current->getData()+start;
+ memcpy(dest,ptr,len*sizeof(float));
+
+}
+
+
+void AudioFrameQueue::clear() {
+ while(dataQueueCanRead()) {
+ AudioFrame* current=dataQueueDequeue();
+ emptyQueueEnqueue(current);
+ }
+}
diff --git a/mpeglib/lib/frame/audioFrameQueue.h b/mpeglib/lib/frame/audioFrameQueue.h
new file mode 100644
index 00000000..7e7a01c0
--- /dev/null
+++ b/mpeglib/lib/frame/audioFrameQueue.h
@@ -0,0 +1,75 @@
+/*
+ queues audio frames in an IOQueue, allows streaming from frames
+ 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 __AUDIOFRAMEQUE_H
+#define __AUDIOFRAMEQUE_H
+
+#include "IOFrameQueue.h"
+#include "floatFrame.h"
+#include "pcmFrame.h"
+
+#include <kdemacros.h>
+
+/**
+ This class solves the problem that we produce audioFrames
+ in a packet, but often we want that these packets looks
+ like a stream.
+ This class can convert from packets back to a stream.
+*/
+
+class KDE_EXPORT AudioFrameQueue : public IOFrameQueue {
+
+ int frameType;
+ int len;
+ AudioFrame* currentAudioFrame;
+ int currentRead;
+
+ public:
+ AudioFrameQueue(int queueSize,int frameSize,int frameType);
+ ~AudioFrameQueue();
+
+ void emptyQueueEnqueue(AudioFrame* frame);
+ AudioFrame* emptyQueueDequeue();
+
+ void dataQueueEnqueue(AudioFrame* frame);
+ AudioFrame* dataQueueDequeue();
+
+ // Meta info about stream
+ AudioFrame* getCurrent();
+
+ // Data info about "stream" (calculated from the packets)
+ int getLen();
+
+ // copy from packets to destination
+ int copy(float* left,float* right,int len);
+ int copy(short int* left,short int* right,int len);
+ void forwardStreamDouble(int len);
+
+ int copy(short int* dest,int len);
+ int copy(float* dest,int len);
+ void forwardStreamSingle(int len);
+
+ void clear();
+
+ private:
+ void transferFrame(float* left,float* right,FloatFrame*,int start,int len);
+ void transferFrame(short int* left,short int* right,
+ PCMFrame*,int start,int len);
+ void transferFrame(short int* dest,
+ PCMFrame*,int start,int len);
+ void transferFrame(float* dest,
+ FloatFrame*,int start,int len);
+ int copygeneric(char* left,char* right,int wantLen,int version,int mux);
+};
+#endif
diff --git a/mpeglib/lib/frame/floatFrame.cpp b/mpeglib/lib/frame/floatFrame.cpp
new file mode 100644
index 00000000..5e17d1e1
--- /dev/null
+++ b/mpeglib/lib/frame/floatFrame.cpp
@@ -0,0 +1,50 @@
+/*
+ stores frames as floats.
+ 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 "floatFrame.h"
+
+#include <iostream>
+
+using namespace std;
+
+FloatFrame::FloatFrame(int size) {
+ data=new float[size];
+ len=0;
+ this->size=size;
+ this->sampleSize=sizeof(float)*8;
+ this->lSigned=true;
+ this->lBigEndian=AUDIOFRAME_BIGENDIAN;
+ setFrameType(_FRAME_AUDIO_FLOAT);
+}
+
+
+FloatFrame::~FloatFrame() {
+ delete [] data;
+}
+
+
+void FloatFrame::putFloatData(float* in,int lenCopy) {
+ if ((len+lenCopy) > size) {
+ cout << "cannot copy putFloatData. Does not fit"<<endl;
+ exit(0);
+ }
+ memcpy(data+len,in,lenCopy*sizeof(float));
+ len+=lenCopy;
+
+
+}
+
+
+void FloatFrame::putFloatData(float* left,float* right,int len) {
+ cout << "not yet implemented"<<endl;
+}
diff --git a/mpeglib/lib/frame/floatFrame.h b/mpeglib/lib/frame/floatFrame.h
new file mode 100644
index 00000000..4d817021
--- /dev/null
+++ b/mpeglib/lib/frame/floatFrame.h
@@ -0,0 +1,46 @@
+/*
+ stores frames as floats.
+ 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 __FLOATFRAME_H
+#define __FLOATFRAME_H
+
+#include "audioFrame.h"
+
+// this format has a sampleSize of sizeof(float), signed, endian==machine
+
+class FloatFrame : public AudioFrame {
+
+ float* data;
+ int len;
+ int size;
+
+
+ public:
+ FloatFrame(int size);
+ ~FloatFrame();
+
+ int getLen() { return len; }
+ void setLen(int len) { this->len=len; }
+ int getSize() { return size; }
+ float* getData() { return data; }
+
+ void putFloatData(float* data,int len);
+ void putFloatData(float* left,float* right,int len);
+
+ void clearrawdata() { len=0; }
+
+
+
+};
+#endif
diff --git a/mpeglib/lib/frame/frame.cpp b/mpeglib/lib/frame/frame.cpp
new file mode 100644
index 00000000..c6a43969
--- /dev/null
+++ b/mpeglib/lib/frame/frame.cpp
@@ -0,0 +1,73 @@
+/*
+ base class for frames
+ 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 "frame.h"
+
+
+Frame::Frame() {
+ type=_FRAME_UNK;
+}
+
+
+Frame::~Frame() {
+}
+
+
+const char* Frame::getMajorFrameName(int type) {
+ int majorID=type >> 12;
+ switch(majorID) {
+ case _FRAME_UNK:
+ return "_FRAME_UNK";
+ case _FRAME_RAW:
+ return "_FRAME_RAW";
+ case _FRAME_AUDIO:
+ return "_FRAME_AUDIO";
+ case _FRAME_VIDEO:
+ return "_FRAME_VIDEO";
+ case _FRAME_PAKET:
+ return "_FRAME_PAKET";
+ default:
+ return "unknown major frameType";
+ }
+ return "never happens Frame::getMajorFrameName";
+}
+
+
+
+const char* Frame::getFrameName(int type) {
+ switch(type) {
+ // Raw
+ case _FRAME_RAW_BASE:
+ return "_FRAME_RAW_BASE";
+ case _FRAME_RAW_OGG:
+ return "_FRAME_RAW_OGG";
+
+
+ // Audio
+ case _FRAME_AUDIO_BASE:
+ return "_FRAME_AUDIO_BASE";
+ case _FRAME_AUDIO_PCM:
+ return "_FRAME_AUDIO_PCM";
+ case _FRAME_AUDIO_FLOAT:
+ return "_FRAME_AUDIO_FLOAT";
+
+
+
+ // Rest
+ default:
+ return "cannot find name";
+ }
+ return "never happens Frame::getFrameName";
+}
+
diff --git a/mpeglib/lib/frame/frame.h b/mpeglib/lib/frame/frame.h
new file mode 100644
index 00000000..301b997c
--- /dev/null
+++ b/mpeglib/lib/frame/frame.h
@@ -0,0 +1,101 @@
+/*
+ base class for frames
+ 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 __FRAME_H
+#define __FRAME_H
+
+
+#include <stdio.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+
+/**
+ The base class for frames. Every derived class from this class
+ must belong to some "major" class type and it must have an unique
+ id for itsself. Even if it is a base class it must have a unique id.
+
+ How does this work. We have an int for the Frame id. In the int
+ itsself we but the majorid as well.
+ The Start codes are all multiple of 2 so for example
+ 0..127 belongs to FRAME UNK
+ 128..255 belongs to FRAME RAW
+
+ So we can with a simple shift operation find out the major class
+*/
+#define _FRAME_SHIFT 7
+#define _FRAME_ID_MAX 128 //(2^_FRAME_SHIFT)
+
+
+// Major Frame classes
+#define _FRAME_UNK 0
+#define _FRAME_RAW 1
+#define _FRAME_AUDIO 2
+#define _FRAME_VIDEO 3
+#define _FRAME_PAKET 4
+
+// start ids of minor classes
+
+#define _FRAME_UNK_START (0)
+#define _FRAME_RAW_START (_FRAME_ID_MAX)
+#define _FRAME_AUDIO_START (_FRAME_ID_MAX*2)
+#define _FRAME_VIDEO_START (_FRAME_ID_MAX*2*2)
+#define _FRAME_PAKET_START (_FRAME_ID_MAX*2*2*2)
+
+// Minor Frame type IDs
+
+
+// Raw
+#define _FRAME_RAW_BASE (_FRAME_RAW_START+1)
+#define _FRAME_RAW_OGG (_FRAME_RAW_START+2)
+#define _FRAME_RAW_MPEG_I_VIDEO (_FRAME_RAW_START+3)
+#define _FRAME_RAW_MPEG_SYSTEM (_FRAME_RAW_START+4)
+
+
+// Audio:
+#define _FRAME_AUDIO_BASE (_FRAME_AUDIO_START+1)
+#define _FRAME_AUDIO_PCM (_FRAME_AUDIO_START+2)
+#define _FRAME_AUDIO_FLOAT (_FRAME_AUDIO_START+3)
+
+// Video:
+#define _FRAME_VIDEO_BASE (_FRAME_VIDEO_START+1)
+#define _FRAME_VIDEO_YUV (_FRAME_VIDEO_START+2)
+#define _FRAME_VIDEO_RGB_8 (_FRAME_VIDEO_START+3)
+#define _FRAME_VIDEO_RGB_16 (_FRAME_VIDEO_START+4)
+#define _FRAME_VIDEO_RGB_32 (_FRAME_VIDEO_START+5)
+
+// Packet:
+#define _FRAME_PACKET_SYNC (_FRAME_PAKET_START+1)
+#define _FRAME_PACKET_PACKET_CONTAINER (_FRAME_PAKET_START+2)
+
+
+
+
+class Frame {
+ int type;
+
+ public:
+ Frame();
+ ~Frame();
+ inline int getMajorFrameType() { return (type>>_FRAME_SHIFT);}
+ inline int getFrameType() { return type; }
+ inline void setFrameType(int type) { this->type=type; }
+
+
+ static const char* getMajorFrameName(int type);
+ static const char* getFrameName(int type);
+};
+#endif
diff --git a/mpeglib/lib/frame/frameQueue.cpp b/mpeglib/lib/frame/frameQueue.cpp
new file mode 100644
index 00000000..fe524976
--- /dev/null
+++ b/mpeglib/lib/frame/frameQueue.cpp
@@ -0,0 +1,101 @@
+/*
+ queues frames
+ 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 "frameQueue.h"
+
+#include <iostream>
+
+using namespace std;
+
+FrameQueue::FrameQueue(int maxsize) {
+ this->size=maxsize;
+ entries = new Frame*[size];
+ int i;
+ for(i=0;i<size;i++) {
+ entries[i]=NULL;
+ }
+ fillgrade=0;
+ writepos=0;
+ readpos=0;
+}
+
+
+FrameQueue::~FrameQueue() {
+ int i;
+ for(i=0;i<size;i++) {
+ if (entries[i] != NULL) {
+ delete entries[i];
+ }
+ }
+ delete entries;
+}
+
+int FrameQueue::canRead() {
+ return (fillgrade > 0);
+}
+
+
+int FrameQueue::canWrite() {
+ return (fillgrade < size);
+}
+
+
+int FrameQueue::getFillgrade() {
+ return fillgrade;
+}
+
+
+void FrameQueue::enqueue(Frame* frame) {
+ if(canWrite() == false) {
+ cout << "FrameQueue full cannot enqueue"<<endl;
+ exit(0);
+ }
+ fillgrade++;
+ entries[writepos]=frame;
+ writepos++;
+ if (writepos == size) {
+ writepos=0;
+ }
+}
+
+
+Frame* FrameQueue::dequeue() {
+ if(canRead() == false) {
+ cout << "FrameQueue empty cannot dequeue"<<endl;
+ exit(0);
+ }
+ Frame* back=entries[readpos];
+ // invalide this frame, we do not longer own it!
+ entries[readpos]=NULL;
+ fillgrade--;
+ readpos++;
+ if (readpos == size) {
+ readpos=0;
+ }
+ return back;
+}
+
+Frame* FrameQueue::peekqueue(int pos) {
+ if(fillgrade-pos <= 0) {
+ cout << "FrameQueue : cannot peek this positon"<<endl;
+ cout << "fillgrade:"<<fillgrade<<endl;
+ cout << "pos:"<<pos<<endl;
+ exit(0);
+ }
+ int getpos=(readpos+pos) % size;
+
+
+ Frame* back=entries[getpos];
+ return back;
+}
+
diff --git a/mpeglib/lib/frame/frameQueue.h b/mpeglib/lib/frame/frameQueue.h
new file mode 100644
index 00000000..27747aa3
--- /dev/null
+++ b/mpeglib/lib/frame/frameQueue.h
@@ -0,0 +1,43 @@
+/*
+ queues frames
+ 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 __FRAMEQUEUE_H
+#define __FRAMEQUEUE_H
+
+#include "frame.h"
+
+class FrameQueue {
+
+ Frame** entries;
+ int fillgrade;
+ int size;
+ int writepos;
+ int readpos;
+
+
+ public:
+ FrameQueue(int maxsize);
+ ~FrameQueue();
+
+ int getFillgrade();
+ int canRead();
+ int canWrite();
+ void enqueue(Frame* frame);
+ Frame* dequeue();
+ Frame* peekqueue(int pos);
+
+
+};
+#endif
diff --git a/mpeglib/lib/frame/framer.cpp b/mpeglib/lib/frame/framer.cpp
new file mode 100644
index 00000000..d380b2ec
--- /dev/null
+++ b/mpeglib/lib/frame/framer.cpp
@@ -0,0 +1,241 @@
+/*
+ base class for converting raw data(stream) into some frametype.
+ 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 "framer.h"
+
+
+
+#define PROCESS_FIND 0
+#define PROCESS_READ 1
+
+#include <iostream>
+
+using namespace std;
+
+Framer::Framer(int outsize) {
+ unsigned char* outptr=new unsigned char[outsize];
+ init(outsize,outptr,true);
+}
+
+
+Framer::Framer(int outsize,unsigned char* outptr) {
+ if (outptr == NULL) {
+ cout << "Framer::Framer outptr NULL"<<endl;
+ exit(0);
+ }
+ if (outsize <= 0) {
+ cout << "Framer::Framer size <= 0"<<endl;
+ exit(0);
+ }
+ init(outsize,outptr,false);
+}
+
+
+void Framer::init(int outsize,unsigned char* outptr,int lDeleteOutPtr) {
+ buffer_data=outptr;
+ this->lDeleteOutPtr=lDeleteOutPtr;
+ input_info=new RawDataBuffer(NULL,0);
+ buffer_info=new RawDataBuffer(buffer_data,outsize);
+ lConstruct=true;
+ reset();
+}
+
+
+Framer::~Framer() {
+ if (lDeleteOutPtr) {
+ delete[] buffer_data;
+ }
+ delete buffer_info;
+ delete input_info;
+}
+
+
+int Framer::canStore() {
+ return buffer_info->untilend();
+}
+
+int Framer::restBytes() {
+ return (input_info->size()-input_info->pos());
+}
+
+
+void Framer::store(unsigned char* start,int bytes) {
+ if (buffer_info->pos()+bytes > buffer_info->size()) {
+ cout << "too much bytes inserted. cannot store that"<<endl;
+ exit(0);
+ }
+ if (main_state != FRAME_NEED) {
+ cout << "cannot store data, when not in MPEGAUDIOFRAME_NEED"<<endl;
+ exit(0);
+ }
+ input_info->set(start,bytes,0);
+ int fillgrade=input_info->untilend();
+ if (fillgrade > 0) {
+ main_state=FRAME_WORK;
+ }
+}
+
+
+int Framer::work() {
+ if (main_state != FRAME_WORK) {
+ cout << "cannot find_frame, when not in MPEGAUDIOFRAME_WORK"<<endl;
+ exit(0);
+ }
+ if (lAutoNext) {
+ next();
+ }
+ switch(process_state) {
+ case PROCESS_FIND:
+ if (find_frame(input_info,buffer_info) == true) {
+ setState(PROCESS_READ);
+ }
+ break;
+ case PROCESS_READ:
+ if (read_frame(input_info,buffer_info) == true) {
+ main_state=FRAME_HAS;
+ }
+ break;
+ default:
+ cout << "unknown process state in work. "<<endl;
+ printMainStates("printing states");
+ exit(0);
+ }
+ // do not go to NEED if we have a frame and now the input is empty
+ if (main_state == FRAME_WORK) {
+ if (input_info->eof()) {
+ main_state=FRAME_NEED;
+ }
+ }
+ if (main_state == FRAME_HAS) return true;
+ return false;
+}
+
+
+void Framer::reset() {
+ unsync(buffer_info,true);
+ lAutoNext=false;
+ main_state=FRAME_NEED;
+ input_info->set(NULL,0,0);
+ buffer_info->setpos(0);
+ setState(PROCESS_FIND);
+}
+
+
+void Framer::next() {
+ unsync(buffer_info,false);
+ lAutoNext=false;
+ main_state=FRAME_WORK;
+ setState(PROCESS_FIND);
+}
+
+
+int Framer::getState() {
+ int back=main_state;
+ if (main_state == FRAME_HAS) {
+ // autonext when we devlivered one frame
+ lAutoNext=true;
+ main_state=FRAME_WORK;
+ setState(PROCESS_FIND);
+ }
+ if (lConstruct == true) {
+ lConstruct=false;
+ unsync(buffer_info,true);
+ }
+ return back;
+}
+
+
+void Framer::setState(int state) {
+ this->process_state=state;
+}
+
+
+
+unsigned char* Framer::outdata() {
+ return buffer_info->ptr();
+}
+
+
+unsigned char* Framer::indata() {
+ return buffer_info->current();
+}
+
+int Framer::len() {
+ return buffer_info->pos();
+}
+
+
+
+void Framer::printMainStates(const char* msg) {
+ cout << msg<<endl;
+ switch(main_state) {
+ case FRAME_NEED:
+ cout << "main_state: FRAME_NEED"<<endl;
+ break;
+ case FRAME_WORK:
+ cout << "main_state: FRAME_WORK"<<endl;
+ break;
+ case FRAME_HAS:
+ cout << "main_state: FRAME_HAS"<<endl;
+ break;
+ default:
+ cout << "unknown illegal main_state:"<<main_state<<endl;
+ }
+
+ switch(process_state) {
+ case PROCESS_FIND:
+ cout << "process_state: PROCESS_FIND"<<endl;
+ break;
+ case PROCESS_READ:
+ cout << "process_state: PROCESS_READ"<<endl;
+ break;
+ default:
+ cout << "unknown illegal process_state:"<<process_state<<endl;
+ }
+ printPrivateStates();
+
+
+}
+
+
+
+
+int Framer::find_frame(RawDataBuffer* ,RawDataBuffer* ) {
+ cout << "direct virtual call Framer::find_frame"<<endl;
+ return false;
+}
+
+
+int Framer::read_frame(RawDataBuffer* ,RawDataBuffer* ) {
+ cout << "direct virtual call Framer::read_frame"<<endl;
+ return false;
+}
+
+void Framer::unsync(RawDataBuffer* ,int ) {
+ if (lConstruct == false) {
+ // invalidate header in buffer
+ cout << "direct virtual call Framer::unsync"<<endl;
+ }
+}
+
+
+void Framer::printPrivateStates() {
+ cout << "direct virtual call Framer::printPrivateStates"<<endl;
+}
+
+
+void Framer::setRemoteFrameBuffer(unsigned char* outptr,int size) {
+
+ input_info->set(NULL,0,0);
+ buffer_info->set(outptr,size,0);
+}
diff --git a/mpeglib/lib/frame/framer.h b/mpeglib/lib/frame/framer.h
new file mode 100644
index 00000000..51c4b26e
--- /dev/null
+++ b/mpeglib/lib/frame/framer.h
@@ -0,0 +1,182 @@
+/*
+ base class for converting raw data(stream) into some frametype.
+ 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 __FRAMER_H
+#define __FRAMER_H
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <kdemacros.h>
+
+#define FRAME_NEED 0
+#define FRAME_WORK 1
+#define FRAME_HAS 2
+
+
+#include "rawDataBuffer.h"
+
+
+/**
+ If we want to have a "push" interface, this means the decoder
+ does not read from an input interface, we must be sure
+ that we have a valid mpeg audio frame, before we feed
+ this whole frame to the decoder.
+
+ This class tells you how many bytes it can read and
+ gives you information wether we have a valid frame or not.
+
+ This class has three public states:
+
+ FRAME_NEED
+ / \
+ / \
+ / \
+ FRAME_WORK <----------> FRAME_HAS
+
+
+ after the "FRAME_HAS" state we devliver _excatly_ one time
+ this state, and then automatically go to "FRAME_WORK" state.
+
+
+ You can reset() the class which empties the buffer and then
+ starts searching for a new sync code, or you can
+ do a next() which searches for the sync code, without
+ emptying the buffer (this is done automatically,
+ after the first call, when we was ins state "FRAME_HAS"
+
+ Note: i) You need a reset() if a "seek" occurs in your stream
+ ii) First call to the class must be "getState" which does the
+ Post-Constructor setup in derived classes!
+
+ The FRAME_NEED state is entered if the input buffer is empty
+ you then need to "push" data in this class.
+ The FRAME_NEED state is necessary to avoid an additonal memcpy
+ and a ringbuffer.(This safes "overhead"/"cpu cycles")
+*/
+
+
+
+
+class KDE_EXPORT Framer {
+
+ // this is our destination buffer for the output frame
+ // this buffer must be able to store the maximum size
+ // a frame of this type can have.
+ // Examples:
+ // avi-Chunk : 65KB
+ // mpeg audio: 4KB is always enough
+ // mpeg video: 224K (spec says this)
+
+ // this can be a remote buffer or a local one
+ unsigned char* buffer_data;
+ RawDataBuffer* buffer_info;
+
+ // state from FIND->READ->HAS
+ int process_state;
+ // state between NEED <-> PROCESS
+ int main_state;
+
+ RawDataBuffer* input_info;
+ int lAutoNext;
+
+ // stores if we have alloceated outdata or not
+ int lDeleteOutPtr;
+ // internal: unsync not done
+ int lConstruct;
+
+ public:
+ // allocate local output buffer
+ Framer(int outsize);
+
+ // outbuffer is remote.
+ Framer(int outsize,unsigned char* outptr);
+
+ virtual ~Framer();
+
+ //
+ // process states (transitions) [START]
+ //
+
+ // stores pointer to input and len
+ void store(unsigned char* start,int bytes);
+ int work();
+ void reset();
+ void next();
+ // returns pointer to outbuffer (frameheader+data)
+ unsigned char* outdata();
+
+ // returns pointer to inbuffer (raw data)
+ // Note: this ptr is not fixed! It may vary from time to time
+ // Cannot be stores in a variable!
+ unsigned char* indata();
+
+
+ //
+ // process states (transitions) [END]
+ //
+
+
+ //
+ // state helper functions [START]
+ //
+ int getState();
+ // returns number of bytes.
+ int canStore();
+
+ // returns length of frame == len(frameheader+data)
+ int len();
+
+ // returns number of bytes still in input(needed for a/v sync)
+ int restBytes();
+ //
+ // state helper functions [END]
+ //
+
+ // debugging
+ void printMainStates(const char* msg);
+
+ private:
+ void init(int outsize,unsigned char* outptr,int lDeleteOutptr);
+
+ void setState(int state);
+
+ //
+ // Overload functions for specialized framers [START]
+ //
+
+ // return true, if frame header found
+ virtual int find_frame(RawDataBuffer* input,RawDataBuffer* store);
+ // return true, if frame data read.
+ virtual int read_frame(RawDataBuffer* input,RawDataBuffer* store);
+ // makes buffer invalid, reset to begin of "find_frame"
+ virtual void unsync(RawDataBuffer* store,int lReset);
+ // debugging
+ virtual void printPrivateStates();
+
+ //
+ // Overload functions for specialized framers [END]
+ //
+
+ protected:
+ // this can be used, if the outptr come from a different framer
+ // (eg: OGG framer). You then need to call the construtor with
+ // some "dummy" size.
+ void setRemoteFrameBuffer(unsigned char* outptr,int size);
+
+};
+
+
+#endif
diff --git a/mpeglib/lib/frame/pcmFrame.cpp b/mpeglib/lib/frame/pcmFrame.cpp
new file mode 100644
index 00000000..24ab9792
--- /dev/null
+++ b/mpeglib/lib/frame/pcmFrame.cpp
@@ -0,0 +1,140 @@
+/*
+ pcm frame description.
+ 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 "pcmFrame.h"
+
+#include <iostream>
+
+using namespace std;
+
+#ifndef WORDS_BIGENDIAN
+// this is fast on INTEL, but maybe not work on other little
+// endian machines. (are there any?)
+#define convMacro(in,dtemp,tmp) \
+ in[0]*=SCALFACTOR; \
+ dtemp = ((((65536.0 * 65536.0 * 16)+(65536.0 * 0.5))* 65536.0))+(in[0]); \
+ tmp = ((*(int *)&dtemp) - 0x80000000); \
+ in++; \
+ if(tmp>32767) { \
+ tmp=32767; \
+ } else if (tmp<-32768) { \
+ tmp =-0x8000; \
+ }
+
+#else /* big endian conversion: _AIX */
+static inline void convMacro(float*& in, double dtemp, int& tmp)
+{
+ in[0]*=SCALFACTOR;
+ tmp = (int)*in;
+ in++;
+ if(tmp>32767) {
+ tmp=32767;
+ } else if (tmp<-32768) {
+ tmp =-0x8000;
+ }
+ tmp = ((tmp & 0xff) << 8) | ((tmp >> 8) & 0xff);
+}
+#endif /* _AIX */
+
+
+PCMFrame::PCMFrame(int size) {
+ data=new short int[size];
+ len=0;
+ this->size=size;
+ // this format has a sampleSize of 16, signed, endian==machine
+ this->sampleSize=sizeof(short int)*8;
+ this->lSigned=true;
+ this->lBigEndian=AUDIOFRAME_BIGENDIAN;
+ setFrameType(_FRAME_AUDIO_PCM);
+}
+
+
+PCMFrame::~PCMFrame() {
+ delete [] data;
+}
+
+
+void PCMFrame::putFloatData(float* left,float* right,int copyLen) {
+ int destSize=0;
+ if (left != NULL) destSize++;
+ if (right != NULL) destSize++;
+ destSize*=copyLen;
+ if ((len+destSize) > size) {
+ cout << "cannot copy putFloatData L/R version . Does not fit"<<endl;
+ cout << "size:"<<size<<endl;
+ cout << "len:"<<len<<endl;
+ cout << "destSize:"<<destSize<<endl;
+ exit(0);
+ }
+ double dtemp;
+ int tmp;
+ int i=copyLen;
+ switch(getStereo()) {
+ case 1:
+ while(i > 0) {
+ convMacro(left,dtemp,tmp);
+ data[len++]=(short int)tmp;
+ convMacro(right,dtemp,tmp);
+ data[len++]=(short int)tmp;
+ i--;
+ }
+ break;
+ case 0:
+ if (left != NULL) {
+ int i=copyLen;
+ while(i > 0) {
+ convMacro(left,dtemp,tmp);
+ data[len++]=(short int)tmp;
+ i--;
+ // right channel empty
+ len++;
+ }
+ }
+ if (right != NULL) {
+ int i=copyLen;
+ len=len-destSize;
+ while(i > 0) {
+ // select right channel
+ len++;
+ convMacro(right,dtemp,tmp);
+ data[len++]=(short int)tmp;
+ i--;
+ // left channel already copied
+ }
+ }
+ break;
+ default:
+ cout << "unknown stereo value in pcmFrame"<<endl;
+ exit(0);
+ }
+}
+
+void PCMFrame::putFloatData(float* in,int lenCopy) {
+
+ if ((len+lenCopy) > size) {
+ cout << "cannot copy putFloatData. Does not fit"<<endl;
+ exit(0);
+ }
+ double dtemp;
+ int tmp;
+ while(lenCopy > 0) {
+ convMacro(in,dtemp,tmp);
+ data[len++]=(short int)tmp;
+ lenCopy--;
+ }
+
+}
+
+
+
diff --git a/mpeglib/lib/frame/pcmFrame.h b/mpeglib/lib/frame/pcmFrame.h
new file mode 100644
index 00000000..a19941bc
--- /dev/null
+++ b/mpeglib/lib/frame/pcmFrame.h
@@ -0,0 +1,45 @@
+/*
+ pcm frame description.
+ 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 __PCMFRAME_H
+#define __PCMFRAME_H
+
+
+#include "audioFrame.h"
+#include <kdemacros.h>
+// this format has a sampleSize of 16, signed, endian==machine
+
+class KDE_EXPORT PCMFrame : public AudioFrame {
+
+ short int* data;
+ int len;
+ int size;
+
+ public:
+ PCMFrame(int size);
+ ~PCMFrame();
+
+ int getLen() { return len; }
+ void setLen(int len) { this->len=len; }
+ int getSize() { return size; }
+ short int* getData() { return data; }
+
+ void putFloatData(float* data,int len);
+ void putFloatData(float* left,float* right,int len);
+
+ void clearrawdata() { len=0; }
+
+
+};
+#endif
diff --git a/mpeglib/lib/frame/rawDataBuffer.cpp b/mpeglib/lib/frame/rawDataBuffer.cpp
new file mode 100644
index 00000000..f8635211
--- /dev/null
+++ b/mpeglib/lib/frame/rawDataBuffer.cpp
@@ -0,0 +1,21 @@
+/*
+ stores simple buffer information. does not allocate anything
+ 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 "rawDataBuffer.h"
+
+// hm
+
+RawDataBuffer::~RawDataBuffer() {
+}
+
+
diff --git a/mpeglib/lib/frame/rawDataBuffer.h b/mpeglib/lib/frame/rawDataBuffer.h
new file mode 100644
index 00000000..755818ea
--- /dev/null
+++ b/mpeglib/lib/frame/rawDataBuffer.h
@@ -0,0 +1,48 @@
+/*
+ stores simple buffer information. does not allocate anything
+ 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 __RAWDATABUFFER_H
+#define __RAWDATABUFFER_H
+
+
+class RawDataBuffer {
+
+ int _size;
+ unsigned char* _ptr;
+ int _pos;
+
+ public:
+ RawDataBuffer(unsigned char* ptr,int size) { set(ptr,size,0); }
+ ~RawDataBuffer();
+
+
+
+ unsigned char* ptr() { return _ptr; }
+ unsigned char* current() { return _ptr+_pos; }
+ int size() { return _size; }
+ int pos() { return _pos; }
+ int untilend() { return _size-_pos; }
+ int eof() { return _pos>=_size; }
+
+ void inc() { this->_pos++; }
+ void inc(int val) { this->_pos+=val; }
+ void setpos(int val) { this->_pos=val; }
+ void setptr(unsigned char* ptr) { this->_ptr=ptr; }
+ void setsize(int size) { this->_size=size; }
+
+ void set(unsigned char* ptr,
+ int size,int pos) { setpos(pos);setptr(ptr);setsize(size);}
+
+};
+#endif
diff --git a/mpeglib/lib/frame/rawFrame.cpp b/mpeglib/lib/frame/rawFrame.cpp
new file mode 100644
index 00000000..fbe662c5
--- /dev/null
+++ b/mpeglib/lib/frame/rawFrame.cpp
@@ -0,0 +1,90 @@
+/*
+ base class for raw frames (encoded data, where only the type is known)
+ 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 "rawFrame.h"
+
+#include <iostream>
+
+using namespace std;
+
+RawFrame::RawFrame(int size) {
+ init(_FRAME_RAW_BASE,size);
+}
+
+
+RawFrame::RawFrame(int type,int size) {
+ init(type,size);
+}
+
+
+RawFrame::~RawFrame() {
+ if (data != NULL) {
+ if (lRemoteData==false) {
+ delete data;
+ }
+ }
+}
+
+
+void RawFrame::print(const char* msg) {
+ cout << msg<<endl;
+ cout << "major Frametype:"<<Frame::getFrameName(getFrameType());
+ cout << "size:"<<getSize();
+ cout << "len:"<<getLen();
+
+}
+
+
+void RawFrame::init(int type,int size) {
+
+ if (size < 0) {
+ cout << "size <= 0 in RawFrame::RawFrame"<<endl;
+ exit(-1);
+ }
+ setFrameType(type);
+ int majorType=getMajorFrameType();
+ if (majorType != _FRAME_RAW) {
+ cout << "invalid Major Frametype:"<<Frame::getFrameName(getFrameType())
+ << " for this class"<<endl;
+ printf("ID:0x%x dec:%d majorID:%d\n",type,type,majorType);
+ cout << "RawFrame::init"<<endl;
+ exit(-1);
+ }
+ if (size == 0) {
+ data=NULL;
+ this->size=0;
+ }
+ if (size > 0) {
+ data=new unsigned char[size];
+ if (data != NULL) {
+ cout <<"malloc error RawFrame"<<endl;
+ exit(-1);
+ }
+ this->size=size;
+ }
+ setLen(0);
+ lRemoteData=false;
+}
+
+
+void RawFrame::setRemoteData(unsigned char* data,int size) {
+ if (this->data != NULL) {
+ if (lRemoteData==false) {
+ delete this->data;
+ }
+ }
+ lRemoteData=true;
+ this->data=data;
+ this->size=size;
+}
diff --git a/mpeglib/lib/frame/rawFrame.h b/mpeglib/lib/frame/rawFrame.h
new file mode 100644
index 00000000..e1a05e9e
--- /dev/null
+++ b/mpeglib/lib/frame/rawFrame.h
@@ -0,0 +1,75 @@
+/*
+ base class for raw frames (encoded data, where only the type is known)
+ 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 __RAW_FRAME_H
+#define __RAW_FRAME_H
+
+#include "frame.h"
+
+/**
+ Raw frames represents bitstreams. They most likely have have now
+ real value for anyone but a decoder.
+ In general you simply allocate a rawFrame with a given size, This
+ size should make sure, that the bitstream packet does fit into
+ the frame. Sometime, in derived classes you can set thes pointer
+ to the allocated directly by calling the protected method: setRemoteData.
+*/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef WORDS_BIGENDIAN
+#define RAWFRAME_BIGENDIAN 1
+#else
+#define RAWFRAME_BIGENDIAN 0
+#endif
+
+
+class RawFrame : public Frame {
+
+ unsigned char* data;
+ int size;
+ int len;
+ int lRemoteData;
+
+ public:
+ RawFrame(int size);
+ RawFrame(int type,int size);
+ ~RawFrame();
+
+ // access start of frameData
+ unsigned char* getData() { return data; }
+
+ // current size in byte
+ int getLen() { return len; }
+ void setLen(int bytes) { this->len=bytes; }
+
+ // maximum size of allocated memory
+ int getSize() { return size; }
+
+
+ void print(const char* msg);
+
+ private:
+ void init(int type,int size);
+
+ protected:
+ void setRemoteData(unsigned char* data,int size);
+};
+
+
+
+#endif
diff --git a/mpeglib/lib/input/Makefile.am b/mpeglib/lib/input/Makefile.am
new file mode 100644
index 00000000..f7e849eb
--- /dev/null
+++ b/mpeglib/lib/input/Makefile.am
@@ -0,0 +1,37 @@
+# libinputplugin - Makefile.am
+
+EXTRA_DIST = cdromAccess_Linux.cpp cdromAccess_Empty.cpp \
+ cdigrap.cpp README
+
+INCLUDES = $(all_includes)
+
+noinst_LTLIBRARIES = libinput.la
+
+noinst_HEADERS = cdromToc.h cdromRawAccess.h \
+ simpleRingBuffer.h fileAccessWrapper.h
+
+kmpgincludedir = $(includedir)/$(THIS_LIB_NAME)/input
+
+kmpginclude_HEADERS = inputStream.h fileInputStream.h \
+ inputPlugin.h \
+ cdromInputStream.h bufferInputStream.h \
+ inputDetector.h httpInputStream.h \
+ threadSafeInputStream.h cddaInputStream.h
+
+
+
+libinput_la_SOURCES = inputStream.cpp fileInputStream.cpp \
+ inputPlugin.cpp \
+ cdromToc.cpp cdromRawAccess.cpp \
+ cdromInputStream.cpp \
+ bufferInputStream.cpp \
+ simpleRingBuffer.cpp \
+ cdromAccess.cpp inputDetector.cpp \
+ httpInputStream.cpp \
+ threadSafeInputStream.cpp \
+ cddaInputStream.cpp \
+ fileAccessWrapper.cpp
+
+# workaround for compile errors caused by linux/cdrom.h.
+# Linux kernel headers suck donkeyballs.
+KDE_CXXFLAGS = $(ENABLE_PERMISSIVE_FLAG)
diff --git a/mpeglib/lib/input/README b/mpeglib/lib/input/README
new file mode 100644
index 00000000..844a17bb
--- /dev/null
+++ b/mpeglib/lib/input/README
@@ -0,0 +1,15 @@
+
+
+Here is the abstraction of the inputplugin.
+Its a base class, with the usual open/seek/read methods.
+The only nice thing is the factory inputPlugin which
+creates you for a given url the correct class.
+
+
+All inputStreams can take a timeStamp. Its necessary for
+audio/video sync, but this must be supported
+by the outputplugin and the playerPlugin!
+Video is not that easy as audio :(
+
+
+
diff --git a/mpeglib/lib/input/bufferInputStream.cpp b/mpeglib/lib/input/bufferInputStream.cpp
new file mode 100644
index 00000000..68e502ff
--- /dev/null
+++ b/mpeglib/lib/input/bufferInputStream.cpp
@@ -0,0 +1,288 @@
+/*
+ reads 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
+
+ */
+
+
+#include "bufferInputStream.h"
+#include "simpleRingBuffer.h"
+
+
+BufferInputStream::BufferInputStream(int size,int minlinSize,
+ const char* name) {
+ ringBuffer=new SimpleRingBuffer(size,minlinSize);
+ leof=false;
+ bytePos=0;
+ fillgrade=0;
+ setUrl(name);
+ lLock=false;
+ abs_thread_mutex_init(&writeInMut);
+}
+
+
+BufferInputStream::~BufferInputStream() {
+ delete ringBuffer;
+ abs_thread_mutex_destroy(&writeInMut);
+}
+
+
+int BufferInputStream::open(const char*) {
+ leof=false;
+ setBlocking(true);
+ return true;
+}
+
+void BufferInputStream::close() {
+ leof=true;
+ setBlocking(false);
+}
+
+int BufferInputStream::eof() {
+ return (leof && (fillgrade==0));
+}
+
+int BufferInputStream::isOpen() {
+ return !leof;
+}
+
+void BufferInputStream::setBlocking(int lblock) {
+ ringBuffer->setCanWaitForSpace(lblock);
+ ringBuffer->setCanWaitForData(lblock);
+}
+
+int BufferInputStream::getHold() {
+ return lLock;
+}
+
+
+void BufferInputStream::setHold(int lLock) {
+ if (lLock) {
+ lockBuffer();
+ } else {
+ unlockBuffer();
+ }
+ this->lLock=lLock;
+}
+
+int BufferInputStream::read(char* ptr,int size) {
+ int i=0;
+ int n=size;
+ int canCopy=n;
+ char* readPtr;
+ // here we read even if leof is true
+ // we make sure that we empty the whole buffer!
+ while((eof()==false) && (n > 0)) {
+ canCopy=n;
+ ringBuffer->getReadArea(readPtr,canCopy);
+ if (canCopy <= 0){
+ ringBuffer->waitForData(1);
+ continue;
+ }
+ if (n < canCopy) {
+ canCopy=n;
+ }
+ memcpy((char*)ptr+i,readPtr,canCopy);
+ i=i+canCopy;
+ n=n-canCopy;
+ ringBuffer->forwardReadPtr(canCopy);
+ ringBuffer->forwardLockPtr(canCopy);
+ lockBuffer();
+ bytePos+=canCopy;
+ fillgrade-=canCopy;
+ unlockBuffer();
+ }
+ return i;
+}
+
+
+int BufferInputStream::write(char* ptr,int len,TimeStamp* stamp) {
+ int i=0;
+ int n=len;
+ int canWrite=n;
+ char* writePtr;
+
+ if (stamp) {
+ lockBuffer();
+ long key;
+ key=bytePos+fillgrade;
+ InputStream::insertTimeStamp(stamp,key,len);
+ unlockBuffer();
+ }
+ // if eof is set we do not insert any more data
+ // we do not call eof() !!!
+ while((leof==false) && (n > 0)) {
+ canWrite=n;
+ ringBuffer->getWriteArea(writePtr,canWrite);
+ if (canWrite <= 0){
+ ringBuffer->waitForSpace(1);
+ continue;
+ }
+ if (canWrite > n) {
+ canWrite=n;
+ }
+ memcpy(writePtr,(char*)ptr+i,canWrite);
+ i=i+canWrite;
+ n=n-canWrite;
+ ringBuffer->forwardWritePtr(canWrite);
+ lockBuffer();
+ fillgrade+=canWrite;
+ unlockBuffer();
+ }
+
+ return i;
+}
+
+
+
+int BufferInputStream::write(InputStream* input,int len,TimeStamp* stamp) {
+ int i=0;
+ int n=len;
+ int canWrite=n;
+ int didWrite;
+ char* writePtr;
+
+ if (stamp) {
+ lockBuffer();
+ long key;
+ key=bytePos+fillgrade;
+ InputStream::insertTimeStamp(stamp,key,len);
+ unlockBuffer();
+ }
+ // if eof is set we do not insert any more data
+ // we do not call eof() !!!
+ while((leof==false) && (n > 0)) {
+ canWrite=n;
+ ringBuffer->getWriteArea(writePtr,canWrite);
+ if (canWrite <= 0){
+ ringBuffer->waitForSpace(1);
+ continue;
+ }
+ if (canWrite > n) {
+ canWrite=n;
+ }
+ didWrite=input->read(writePtr,canWrite);
+ if (input->eof()) break;
+ i=i+didWrite;
+ n=n-didWrite;
+ ringBuffer->forwardWritePtr(didWrite);
+ lockBuffer();
+ fillgrade+=canWrite;
+ unlockBuffer();
+ }
+
+ return i;
+}
+
+
+
+long BufferInputStream::getByteLength() {
+ return ringBuffer->getFillgrade();
+}
+
+int BufferInputStream::getFillgrade() {
+ return ringBuffer->getFillgrade();
+}
+
+
+int BufferInputStream::getFreeRead() {
+ return ringBuffer->getFreeRead();
+}
+
+
+int BufferInputStream::getFreeSpace() {
+ return ringBuffer->getFreeWrite();
+}
+
+
+
+long BufferInputStream::getBytePosition() {
+ return bytePos;
+}
+
+void BufferInputStream::setBytePosition(long bytePos) {
+ this->bytePos=bytePos;
+}
+
+
+int BufferInputStream::seek(long) {
+ return false;
+}
+
+
+void BufferInputStream::clear() {
+
+ ringBuffer->emptyBuffer();
+ ringBuffer->exitWaitForData();
+ ringBuffer->exitWaitForSpace();
+ timeStampArray->clear();
+
+ lockBuffer();
+ bytePos=0;
+ fillgrade=0;
+ unlockBuffer();
+
+}
+
+
+
+
+// remote read extension
+int BufferInputStream::readRemote(char** ptr,int size) {
+ int n=0;
+ char* readPtr;
+ while((eof()==false)) {
+ n=size;
+ ringBuffer->getReadArea(readPtr,n);
+ if (n < size){
+ ringBuffer->waitForData(size);
+ if (ringBuffer->getCanWaitForData()==false) {
+ break;
+ }
+ continue;
+ }
+ break;
+ }
+ *ptr=readPtr;
+ return n;
+}
+
+
+void BufferInputStream::forwardReadPtr(int bytes) {
+
+ ringBuffer->forwardReadPtr(bytes);
+ ringBuffer->forwardLockPtr(bytes);
+ lockBuffer();
+ bytePos+=bytes;
+ fillgrade-=bytes;
+ unlockBuffer();
+ getTimeStamp(bytePos);
+}
+
+
+void BufferInputStream::setCanWaitForData(int lBlock) {
+ ringBuffer->setCanWaitForData(lBlock);
+}
+
+
+void BufferInputStream::lockBuffer() {
+ abs_thread_mutex_lock(&writeInMut);
+}
+
+
+void BufferInputStream::unlockBuffer() {
+ abs_thread_mutex_unlock(&writeInMut);
+}
+
+
+int BufferInputStream::getSize() {
+ return ringBuffer->getSize();
+}
+
+
diff --git a/mpeglib/lib/input/bufferInputStream.h b/mpeglib/lib/input/bufferInputStream.h
new file mode 100644
index 00000000..3bd3e691
--- /dev/null
+++ b/mpeglib/lib/input/bufferInputStream.h
@@ -0,0 +1,88 @@
+/*
+ reads 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 __BUFFERINPUTSTREAM_H
+#define __BUFFERINPUTSTREAM_H
+
+#include "../util/abstract/abs_thread.h"
+
+#include "inputStream.h"
+
+
+class SimpleRingBuffer;
+
+class BufferInputStream : public InputStream {
+
+ SimpleRingBuffer* ringBuffer;
+ int leof;
+ long bytePos;
+ int fillgrade;
+ int lLock;
+ abs_thread_mutex_t writeInMut;
+
+ public:
+ BufferInputStream(int size,int minlinSize,const char* name);
+ ~BufferInputStream();
+
+ int open(const char* name);
+ void close();
+
+ int isOpen();
+
+
+ int eof();
+ void setBlocking(int lblock);
+ int read(char* ptr,int size);
+
+ // reads from a buffer
+ int write(char* ptr,int len,TimeStamp* stamp);
+
+ // this method directy read from another inputstream (faster);
+ int write(InputStream* ptr,int len,TimeStamp* stamp);
+
+ int seek(long bytePos);
+
+
+ long getByteLength();
+ long getBytePosition();
+
+ void setBytePosition(long bytePos);
+ int getFillgrade();
+ int getSize();
+ int getFreeRead();
+ int getFreeSpace();
+
+ void clear();
+
+ // remote read extension
+ // Note you _need_ to call always both methods
+ // readRemote and forwardReadPtr even if bytes==0!!!
+ // (we hold a resizeLock during this operation)
+ int readRemote(char** ptr,int size);
+ void forwardReadPtr(int bytes);
+ void setCanWaitForData(int lBlock);
+
+
+ // this method is only safe to call by the writer in the buffer
+ // a reader never should call this (segfault possible)
+ void resizeBuffer(int changeSize);
+
+ // for pause/play over loopback
+ int getHold();
+ void setHold(int lLock);
+
+ private:
+ void lockBuffer();
+ void unlockBuffer();
+
+};
+#endif
diff --git a/mpeglib/lib/input/cddaInputStream.cpp b/mpeglib/lib/input/cddaInputStream.cpp
new file mode 100644
index 00000000..9bc8f5f2
--- /dev/null
+++ b/mpeglib/lib/input/cddaInputStream.cpp
@@ -0,0 +1,225 @@
+/*
+ cdda input class based on cdparanoia
+ 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
+
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef CDDA_PARANOIA
+
+#include <iostream>
+
+using namespace std;
+
+#include "cddaInputStream.h"
+#include "inputDetector.h"
+
+
+void paranoiaCallback(long, int) {
+ //cout << "long:"<<a<<" int:"<<b<<endl;
+}
+
+CDDAInputStream::CDDAInputStream() {
+ drive = NULL;
+ paranoia=NULL;
+ device=NULL;
+ track=1;
+}
+
+
+CDDAInputStream::~CDDAInputStream() {
+ close();
+}
+
+// here we should encdoe the track Nr. as well
+// eg: /dev/cdrom#1
+int CDDAInputStream::getTrackAndDevice(const char* url) {
+ int matches=0;
+ // dest = "cdda:/dev/cdrom/track01.cda"
+ char* noprotoString=InputDetector::removeProtocol(url);
+ // noprotoString="/dev/cdrom/track01.cda"
+ char* filename=InputDetector::getFilename(noprotoString);
+ // filename="track01.cda"
+ char* filenameNoExt=InputDetector::getWithoutExtension(filename);
+ // filenameNoExt="track01"
+ char* dir=InputDetector::removeExtension(noprotoString,filename);
+ // dir="/dev/cdrom/"
+ device=InputDetector::removeSlash(dir);
+ track=1;
+ if (filenameNoExt != NULL) {
+ matches=sscanf(filenameNoExt,"track%02d",&track);
+ }
+ if (matches == 0) {
+ cout << "no trackNumber found using default"<<endl;
+ }
+ cout << "device:"<<device<<" track:"<<track<<endl;
+
+ if (noprotoString != NULL) {
+ delete noprotoString;
+ }
+ if (filename != NULL) {
+ delete filename;
+ }
+ if (filenameNoExt != NULL) {
+ delete filenameNoExt;
+ }
+ if (dir != NULL) {
+ delete dir;
+ }
+ if (device == NULL) {
+ cout << "no device found, using any"<<endl;
+ return false;
+ }
+ return true;
+}
+
+int CDDAInputStream::open(const char* dest) {
+ if (getTrackAndDevice(dest) == true) {
+ drive = cdda_identify(device, CDDA_MESSAGE_PRINTIT, 0);
+ }
+
+ if (drive == NULL) {
+ cout << "cdda_identify failed trying to find a device"<<endl;
+ drive=cdda_find_a_cdrom(CDDA_MESSAGE_PRINTIT, 0);
+ }
+ if (drive == NULL) {
+ cout << "nope. nothing found. give up"<<endl;
+ return false;
+ }
+ cout << "cdda_open -s"<<endl;
+ if (cdda_open(drive) != 0) {
+ cout << "cdda_open(drive) failed"<<endl;
+ close();
+ return false;
+ }
+ cout << "cdda_open -e"<<endl;
+
+ // debug things a bit
+ int trackCount = drive->tracks;
+ for (int i = 1; i <= trackCount; i++) {
+ if (IS_AUDIO(drive, i)) {
+ printf("track%02d.cda\n", i);
+ } else {
+ printf("no audio:%d\n",i);
+ }
+ }
+
+ paranoia = paranoia_init(drive);
+ if (paranoia == NULL) {
+ cout << "paranoia init failed"<<endl;
+ close();
+ return false;
+ }
+
+ firstSector=cdda_track_firstsector(drive, track);
+ lastSector=cdda_track_lastsector(drive, track);
+ currentSector=firstSector;
+ // paranoia && drive != NULL -> initialized!
+
+ int paranoiaLevel = PARANOIA_MODE_FULL ^ PARANOIA_MODE_NEVERSKIP;
+ paranoia_modeset(paranoia, paranoiaLevel);
+ cdda_verbose_set(drive, CDDA_MESSAGE_PRINTIT, CDDA_MESSAGE_PRINTIT);
+ paranoia_seek(paranoia, firstSector, SEEK_SET);
+
+ return true;
+}
+
+
+void CDDAInputStream::close() {
+ if (isOpen() == false) {
+ return;
+ }
+ cdda_close(drive);
+ drive=NULL;
+ if (paranoia != NULL) {
+ paranoia_free(paranoia);
+ paranoia = 0;
+ }
+ if (device != NULL) {
+ delete device;
+ device=NULL;
+ }
+}
+
+
+int CDDAInputStream::isOpen() {
+ return (drive != NULL);
+}
+
+
+int CDDAInputStream::eof() {
+ if (isOpen()==false) {
+ return true;
+ }
+ if (currentSector >= lastSector) {
+ return true;
+ }
+ return false;
+}
+
+
+int CDDAInputStream::read(char* dest,int len) {
+ if (len != 2*CD_FRAMESIZE_RAW) {
+ cout << "len must be 2*CD_FRAMESIZE_RAW"<<endl;
+ exit(0);
+ }
+ int16_t * buf = paranoia_read(paranoia, paranoiaCallback);
+ currentSector++;
+ if (buf == NULL) {
+ cout << "paranoia_read failed"<<endl;
+ close();
+ return 0;
+ }
+ memcpy(dest,buf,sizeof(int16_t)*CD_FRAMESIZE_RAW);
+ return CD_FRAMESIZE_RAW;
+}
+
+
+int CDDAInputStream::seek(long bytePos) {
+ int byteLength=getByteLength();
+ float ratio=(float)bytePos/(float)(byteLength+1);
+ float wantSector=ratio*(float)((lastSector-firstSector));
+ if (isOpen()) {
+ currentSector=(int)wantSector;
+ cout << "paranoia_seek:"<<currentSector<<endl;
+ paranoia_seek(paranoia, currentSector, SEEK_SET);
+ }
+ return true;
+}
+
+void CDDAInputStream::clear() {
+ cout << "direct virtual call CDDAInputStream::clear:"<<endl;
+}
+
+
+long CDDAInputStream::getByteLength() {
+ int sectors=lastSector-firstSector;
+ int bytes=sectors*CD_FRAMESIZE_RAW*sizeof(int16_t);
+ cout << "getByteLength:"<<bytes<<endl;
+ return bytes;
+}
+
+
+long CDDAInputStream::getBytePosition() {
+ int readSectors=currentSector-firstSector;
+ int bytes=readSectors*CD_FRAMESIZE_RAW*sizeof(int16_t);
+ return bytes;
+}
+
+#endif
+//CDDA_PARANOIA
+
+
+
+
+
diff --git a/mpeglib/lib/input/cddaInputStream.h b/mpeglib/lib/input/cddaInputStream.h
new file mode 100644
index 00000000..55989c65
--- /dev/null
+++ b/mpeglib/lib/input/cddaInputStream.h
@@ -0,0 +1,85 @@
+/*
+ cdda input class based on cdparanoia
+ 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 __CDDAINPUTSTREAM_H
+#define __CDDAINPUTSTREAM_H
+
+
+#include "inputStream.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef CDDA_PARANOIA
+class CDDAInputStream : public InputStream {
+};
+#else
+
+#include <sys/types.h>
+typedef int16_t size16;
+typedef int32_t size32;
+
+extern "C" {
+#include <cdda_interface.h>
+#include <cdda_paranoia.h>
+void paranoiaCallback(long, int);
+}
+//#define CDDA_INCLUDE
+
+
+class CDDAInputStream : public InputStream {
+
+//#ifdef CDDA_INCLUDE
+ cdrom_paranoia * paranoia;
+ struct cdrom_drive * drive;
+//#else
+// void * drive;
+// void * paranoia;
+//#endif
+
+
+ char* device;
+ int track;
+
+ int firstSector;
+ int lastSector;
+ int currentSector;
+
+ public:
+ CDDAInputStream();
+ ~CDDAInputStream();
+
+ int open(const char* dest);
+ void close();
+ int isOpen();
+
+ int eof();
+ int read(char* ptr,int size);
+ int seek(long bytePos);
+ // clears possible input buffers
+ // (called by the decoderPlugin after a resyncCommit)
+ void clear();
+
+ long getByteLength();
+ long getBytePosition();
+ private:
+ int getTrackAndDevice(const char* url);
+
+};
+#endif
+//CDDA_PARANOIA
+
+#endif
diff --git a/mpeglib/lib/input/cdigrap.cpp b/mpeglib/lib/input/cdigrap.cpp
new file mode 100644
index 00000000..37d9de0e
--- /dev/null
+++ b/mpeglib/lib/input/cdigrap.cpp
@@ -0,0 +1,100 @@
+/**
+ graps cdis
+
+ Compile with
+
+ g++ -o cdigrap cdigrap.cpp -lmpeg
+
+*/
+#ifdef CONFIG_H
+#include "config.h"
+#endif
+#include "inputPlugin.h"
+
+#if defined(HAVE_GETOPT_H)
+#include <getopt.h>
+#endif
+
+void usage() {
+ cout << "cdigrab grabs video cds"<<endl;
+ cout << "Usage : cdigrab [s:b:f:h] cdi:/device"<<endl;
+ cout << endl;
+ cout << "-s : bytes start a positions <bytes>"<<endl;
+ cout << "-b : set block size (default: 32768)"<<endl;
+ cout << "-f : set filename (default: a.cdi)"<<endl;
+ cout << "-h : help"<<endl;
+ cout << "THIS SOFTWARE COMES WITH ABSOLUTELY NO WARRANTY! " \
+ << "USE AT YOUR OWN RISK!"<<endl;
+ cout << endl;
+}
+
+
+int main(int argn,char** args) {
+
+
+ if (argn <= 1) {
+ usage();
+ exit(0);
+ }
+ long startBytes=0;
+ int len=32768;
+ char *fname = strdup("a.cdi");
+ int c;
+
+ while(1) {
+ c = getopt (argn, args, "s:b:f:h");
+ if (c == -1) break;
+ switch(c) {
+ case 'h': {
+ usage();
+ exit(0);
+ }
+ case 's': {
+ startBytes=atoi(optarg);
+ break;
+ }
+ case 'b': {
+ len=atoi(optarg);
+ break;
+ }
+ case 'f': {
+ fname = strdup(optarg);
+ break;
+ }
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ usage();
+ exit(-1);
+ }
+ }
+ if (optind >= argn ) {
+ usage();
+ exit(-1);
+ }
+
+ InputStream* in=InputPlugin::createInputStream(args[optind]);
+
+ in->open(args[optind]);
+
+ if (startBytes != 0) {
+ cout << "seeking to :"<<startBytes<<endl;
+ in->seek(startBytes);
+ }
+ char* buffer=new char[len];
+ int cnt=0;
+ FILE* f=fopen(fname,"a+");
+ while(1) {
+ if (in->eof() == true) {
+ cout << "******* plugin->getStreamState() EOF"<<endl;
+ break;
+ }
+ in->read(buffer,len);
+ fwrite(buffer,len,1,f);
+ cnt++;
+ cout << "grapped:"<<cnt*len<<endl;
+ }
+ fclose(f);
+}
+
+
+
diff --git a/mpeglib/lib/input/cdromAccess.cpp b/mpeglib/lib/input/cdromAccess.cpp
new file mode 100644
index 00000000..98d49779
--- /dev/null
+++ b/mpeglib/lib/input/cdromAccess.cpp
@@ -0,0 +1,54 @@
+/*
+ * system dependent wrapper for access to cdrom
+ * 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
+ *
+ * $Id$
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+ #include <config.h>
+#endif
+
+
+
+#ifdef OS_AIX
+ #include "cdromAccess_Empty.cpp"
+#endif
+
+#ifdef OS_Linux
+ #include <sys/types.h>
+ #include "cdromAccess_Linux.cpp"
+#endif
+
+#ifdef OS_BSD
+ #include "cdromAccess_Empty.cpp"
+#endif
+
+#if defined(OS_IRIX) || defined(OS_IRIX64)
+ #include "cdromAccess_Empty.cpp"
+#endif
+
+#ifdef OS_HPUX
+ #include "cdromAccess_Empty.cpp"
+#endif
+
+#ifdef OS_SunOS
+ #include "cdromAccess_Empty.cpp"
+#endif
+
+#ifdef __BEOS__
+ #include "cdromAccess_Empty.cpp"
+#endif
+
+#ifdef WIN32
+ #include "cdromAccess_Empty.cpp"
+#endif
+
+
diff --git a/mpeglib/lib/input/cdromAccess_Empty.cpp b/mpeglib/lib/input/cdromAccess_Empty.cpp
new file mode 100644
index 00000000..63da4b69
--- /dev/null
+++ b/mpeglib/lib/input/cdromAccess_Empty.cpp
@@ -0,0 +1,47 @@
+/*
+ system dependent wrapper for access to cdrom (no system)
+ 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 "cdromToc.h"
+#include "cdromRawAccess.h"
+
+#include <iostream>
+using namespace std;
+
+
+int CDRomToc::getStartEnd(FILE* file,int& startToc,int& endToc) {
+ cout << "CDRomToc::getStartEnd not implemented on your system"<<endl;
+ return false;
+}
+
+
+int CDRomToc::readToc(FILE* file,int num,int& min,int& sec, int& frame) {
+ cout << "CDRomToc::readToc not implemented on your system"<<endl;
+ return false;
+}
+
+
+int CDRomToc::readLeadOut(FILE* file,int& min,int& sec, int& frame) {
+ cout << "CDRomToc::reatLeadOut not implemented on your system"<<endl;
+ return false;
+}
+
+
+
+int CDRomRawAccess::readDirect(int minute,int second, int frame) {
+
+
+ cout << "no CDRomRawAccess::read implemented for your system"<<endl;
+ lData=false;
+ return true;
+}
+
diff --git a/mpeglib/lib/input/cdromAccess_Linux.cpp b/mpeglib/lib/input/cdromAccess_Linux.cpp
new file mode 100644
index 00000000..a3bde622
--- /dev/null
+++ b/mpeglib/lib/input/cdromAccess_Linux.cpp
@@ -0,0 +1,124 @@
+/*
+ system dependent wrapper for access to cdrom (Linux)
+ 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
+
+ */
+
+#ifdef __STRICT_ANSI__
+#undef __STRICT_ANSI__
+#define _ANSI_WAS_HERE_
+#endif
+#include <linux/types.h>
+#include <linux/cdrom.h>
+#ifdef _ANSI_WAS_HERE_
+#define __STRICT_ANSI__
+#endif
+#include <sys/ioctl.h>
+
+#include "cdromToc.h"
+#include "cdromRawAccess.h"
+
+#include <iostream>
+
+using namespace std;
+
+/**
+ here you find an example how to port the access method
+ to your system.
+*/
+
+
+int CDRomToc::getStartEnd(FILE* file,int& startToc,int& endToc) {
+ struct cdrom_tochdr tochdr;
+ int fd=fileno(file);
+ if (ioctl(fd, CDROMREADTOCHDR, &tochdr) == -1) {
+ perror("ioctl cdromreadtochdr");
+ return false;
+ }
+
+ startToc=tochdr.cdth_trk0;
+ endToc=tochdr.cdth_trk1;
+ return true;
+}
+
+
+int CDRomToc::readToc(FILE* file,int num,int& min,int& sec, int& frame) {
+ struct cdrom_tocentry tocent;
+ int fd=fileno(file);
+ tocent.cdte_track = num;
+ tocent.cdte_format = CDROM_MSF;
+ if (ioctl(fd, CDROMREADTOCENTRY, &tocent) == -1 ) {
+ perror("ioctl cdromreadtocentry");
+ return false;
+ }
+ min=tocent.cdte_addr.msf.minute;
+ sec=tocent.cdte_addr.msf.second;
+ frame=tocent.cdte_addr.msf.frame;
+ return true;
+}
+
+
+int CDRomToc::readLeadOut(FILE* file,int& min,int& sec, int& frame) {
+ struct cdrom_tocentry tocent;
+ int fd=fileno(file);
+ tocent.cdte_track = CDROM_LEADOUT;
+ tocent.cdte_format = CDROM_MSF;
+ if (ioctl(fd, CDROMREADTOCENTRY, &tocent) == -1 ) {
+ perror("ioctl cdromreadLeadoutn");
+ return false;
+ }
+ min=tocent.cdte_addr.msf.minute;
+ sec=tocent.cdte_addr.msf.second;
+ frame=tocent.cdte_addr.msf.frame;
+ return true;
+}
+
+
+
+int CDRomRawAccess::readDirect(int minute,int second, int frame) {
+
+ // this comes from smpeg
+ // smpeg is an mpeg I player from lokigames www.lokigames.com
+
+ struct cdrom_msf *msf;
+ int fd=fileno(cdfile);
+
+ msf = (struct cdrom_msf*) data;
+ msf->cdmsf_min0 = minute;
+ msf->cdmsf_sec0 = second;
+ msf->cdmsf_frame0 = frame;
+ if (ioctl(fd, CDROMREADMODE2, msf) == -1) {
+ perror("ioctl cdromreadmode2");
+ cout << "min:"<<minute
+ << " sec:"<<second
+ << " frame:"<<frame<<endl;
+ return false;
+ } else {
+ //cout << "read success ****************"<<endl;
+ }
+
+ char* subheader=data+sizeof(int);
+
+
+ if ((subheader[1]==1) &&
+ (((subheader[2]==0x62) &&
+ (subheader[3]==0x0f)) || ((subheader[2]==0x64) &&
+ (subheader[3]==0x7f)))) {
+ lData=true;
+ dataStart=sizeof(int)+4;
+ } else {
+ lData=false;
+ }
+
+ len=2324;
+
+
+ return true;
+}
+
diff --git a/mpeglib/lib/input/cdromInputStream.cpp b/mpeglib/lib/input/cdromInputStream.cpp
new file mode 100644
index 00000000..1cf3f905
--- /dev/null
+++ b/mpeglib/lib/input/cdromInputStream.cpp
@@ -0,0 +1,309 @@
+/*
+ reads input data from cdrom
+ 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 "cdromInputStream.h"
+#include "cdromRawAccess.h"
+#include "cdromToc.h"
+#include <string.h>
+#include "inputDetector.h"
+
+#include <iostream>
+
+using namespace std;
+
+CDRomInputStream::CDRomInputStream() {
+ cdRomToc=new CDRomToc();
+ cdRomRawAccess=new CDRomRawAccess(cdRomToc);
+
+ buflen=0;
+ bufCurrent=NULL;
+
+ currentMinute=0;
+ currentSecond=2;
+ currentFrame=0;
+ byteCounter=0;
+}
+
+
+CDRomInputStream::~CDRomInputStream() {
+ delete cdRomRawAccess;
+ delete cdRomToc;
+}
+
+
+int CDRomInputStream::readCurrent() {
+ int ok=cdRomRawAccess->read(currentMinute,currentSecond,currentFrame);
+ if (ok==false) {
+ if (cdRomRawAccess->eof() == false) {
+ int pos=cdRomToc->getNextTocEntryPos(currentMinute,
+ currentSecond,
+ currentFrame);
+
+ // now try to read a few sectors
+ int cnt=0;
+ int back=false;
+
+ while(1) {
+ // jump forward
+ int i;
+ for(i=0;i<_CDROM_FRAMES-currentFrame;i++) {
+ next_sector();
+ }
+ cout << "trying next ..."<<endl;
+ ok=cdRomRawAccess->read(currentMinute,currentSecond,currentFrame);
+ if (ok) {
+ bufCurrent=cdRomRawAccess->getBufferStart();
+ buflen=cdRomRawAccess->getBufferLen();
+ return true;
+ }
+ cnt++;
+ if (cnt > 100) {
+ break;
+ }
+ }
+ cout << "last possible jump"<<endl;
+ if (pos > 1) {
+ TocEntry* tocEntry=cdRomToc->getTocEntry(pos-1);
+ currentMinute=tocEntry->minute;
+ currentSecond=tocEntry->second;
+ currentFrame=tocEntry->frame;
+ back=cdRomRawAccess->read(currentMinute,currentSecond,currentFrame);
+ if (back) {
+ bufCurrent=cdRomRawAccess->getBufferStart();
+ buflen=cdRomRawAccess->getBufferLen();
+ }
+ }
+ return back;
+ }
+ return false;
+ }
+ bufCurrent=cdRomRawAccess->getBufferStart();
+ buflen=cdRomRawAccess->getBufferLen();
+ return true;
+}
+
+
+int CDRomInputStream::getByteDirect() {
+ int back;
+ if (buflen==0) {
+ fillBuffer();
+ }
+ if (buflen==0){
+ return EOF;
+ }
+ back=*bufCurrent;
+ buflen--;
+ bufCurrent++;
+ byteCounter++;
+ return back;
+}
+
+
+int CDRomInputStream::read(char* ptr,int size) {
+ char* dest=(char*)ptr;
+ int bytesRead=0;
+ int doRead=size;
+ int canRead;
+
+ while(eof() == false) {
+ if (buflen == 0) {
+ if (fillBuffer() == false) {
+ return 0;
+ }
+ continue;
+ }
+ canRead=buflen;
+ if (doRead < canRead) {
+ canRead=doRead;
+ }
+ memcpy((void*)dest,(void*)bufCurrent,canRead);
+ buflen-=canRead;
+ bufCurrent+=canRead;
+ bytesRead+=canRead;
+ dest+=canRead;
+ doRead-=canRead;
+ if (doRead == 0) {
+ byteCounter+=bytesRead;
+ return bytesRead;
+ }
+ }
+ return 0;
+}
+
+int CDRomInputStream::eof() {
+ return cdRomRawAccess->eof();
+}
+
+
+
+
+long CDRomInputStream::getBytePosition() {
+ return byteCounter;
+}
+
+
+void CDRomInputStream::print() {
+}
+
+
+void CDRomInputStream::next_sector() {
+ currentFrame++;
+ if (currentFrame>=_CDROM_FRAMES) {
+ currentFrame = 0;
+ currentSecond++;
+ if (currentSecond>=_CDROM_SECS) {
+ currentSecond = 0;
+ currentMinute++;
+ }
+ }
+}
+
+int CDRomInputStream::open(const char* file) {
+ cout << "CDRomInputStream::open:"<<file<<endl;
+ char* noExtension=InputDetector::getWithoutExtension(file);
+ cout << "CDRomInputStream::noExt:"<<noExtension<<endl;
+ if (noExtension == NULL) {
+ return false;
+ }
+ cdRomToc->open(noExtension);
+ cdRomRawAccess->open(noExtension);
+ if (isOpen()==false) {
+ return false;
+ }
+ setUrl(noExtension);
+ int entries=cdRomToc->getTocEntries();
+ cdRomToc->print();
+ if (entries == 1) {
+ cerr << "only lead out"<<endl;
+ }
+
+ // cdRomRawAccess->insertTocEntry(0,2,0);
+ //cdRomToc->insertTocEntry(1,13,5);
+
+ TocEntry* tocEntry=cdRomToc->getTocEntry(0);
+ currentMinute=tocEntry->minute;
+ currentSecond=tocEntry->second;
+ currentFrame=tocEntry->frame;
+ delete noExtension;
+
+ return readCurrent();
+}
+
+
+void CDRomInputStream::close() {
+ cdRomRawAccess->close();
+ byteCounter=0;
+ setUrl(NULL);
+}
+
+
+int CDRomInputStream::isOpen() {
+ return cdRomRawAccess->isOpen();
+}
+
+
+
+
+long CDRomInputStream::getBytePos(int min,int sec) {
+ long back;
+ // 2324 is the size of a cdfram
+ back=sec*_CDROM_FRAMES*2324;
+ back=back+min*60*_CDROM_FRAMES*2324;
+ cout << "CDRomInputStream::getByteLength"<<back<<endl;
+ return back;
+}
+
+long CDRomInputStream::getByteLength() {
+ // we get the length out of the toc and then multiply like hell
+ long totalSecs=cdRomToc->getEndSecond();
+ long min=totalSecs/60;
+ long sec=totalSecs-60*min;
+
+ long back=getBytePos(min,sec);
+
+ return back;
+}
+
+
+int CDRomInputStream::seek(long posInBytes) {
+ int entries=cdRomToc->getTocEntries();
+
+ TocEntry* firstEntry;
+ if (entries == 0) {
+ return false;
+ }
+ if (posInBytes < 0) {
+ return false;
+ }
+ firstEntry=cdRomToc->getTocEntry(0);
+
+ long startByte=getBytePos(firstEntry->minute,firstEntry->second+1);
+
+ posInBytes=posInBytes+startByte;
+
+
+ float fmin=(float)posInBytes/(float)(60*_CDROM_FRAMES*2324);
+ int min=(int)fmin;
+
+
+ long sec=posInBytes-min*(60*_CDROM_FRAMES*2324);
+ sec=sec/(_CDROM_FRAMES*2324);
+
+ byteCounter=posInBytes;
+ if (cdRomRawAccess->read(min,sec,0)==false) {
+ return false;
+ }
+ setTimePos(min*60+sec);
+
+ return true;
+}
+
+
+int CDRomInputStream::setTimePos(int second) {
+ currentFrame=0;
+ currentMinute=second/60;
+ currentSecond=second%60;
+
+ return fillBuffer();
+}
+
+
+
+
+
+int CDRomInputStream::fillBuffer() {
+ int maxNoData=30;
+ int cnt=0;
+ if (buflen==0) {
+ while (cnt < maxNoData) {
+ next_sector();
+ if (readCurrent() == false) {
+ return false;
+ }
+ if (cdRomRawAccess->isData() == false) {
+ // cerr << "no data"<<endl;
+ cnt++;
+ } else {
+ return true;
+ }
+ }
+ return false;
+ }
+ return true;
+}
+
+
+
+
+
+
diff --git a/mpeglib/lib/input/cdromInputStream.h b/mpeglib/lib/input/cdromInputStream.h
new file mode 100644
index 00000000..cda18efe
--- /dev/null
+++ b/mpeglib/lib/input/cdromInputStream.h
@@ -0,0 +1,88 @@
+/*
+ reads input data from cdrom
+ 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 __VIDEOCDINPUTSTREAM_H
+#define __VIDEOCDINPUTSTREAM_H
+
+
+
+#include "inputStream.h"
+
+
+
+#define _CDROM_FRAMES 75
+#define _CDROM_SECS 60
+
+
+/**
+ This is necessary because CD-I or VCD disks are not correctly
+ mounted by the linux kernel.
+ Windows seems to do it correct (sometimes, the other time it nearly crash)
+ During my test I found out that CD-I and VCD seems to be different.
+ One works with the CD-I loader the other with the VCD loader.
+
+ This class tries to find out if its a CD-I / VCD stream.
+ Then you can set the interface and load from this interface.
+
+ This class depends on the reader routines from xreadcdi/ xreadvcd,
+ Author: Ales Makarov <xmakarov@sun.felk.cvut.cz>
+ FTP : ftp://mca.sh.cvut.cz/pub/readvcd/
+
+ The code is used in a few other packages, in which I looked as well.
+
+*/
+
+class CDRomRawAccess;
+class CDRomToc;
+
+class CDRomInputStream : public InputStream{
+
+ CDRomRawAccess* cdRomRawAccess;
+ CDRomToc* cdRomToc;
+
+ int buflen;
+ char* bufCurrent;
+
+ int currentFrame;
+ int currentMinute;
+ int currentSecond;
+ long byteCounter;
+
+ public:
+ CDRomInputStream();
+ ~CDRomInputStream();
+
+ int open(const char* dest);
+ void close();
+ int isOpen();
+
+ int eof();
+ int read(char* ptr,int size);
+ int seek(long bytePos);
+
+ long getByteLength();
+ long getBytePosition();
+
+ void print();
+
+ private:
+ long getBytePos(int min,int sec);
+
+ int setTimePos(int posInTime);
+ int getByteDirect();
+ void next_sector();
+ int readCurrent();
+ int fillBuffer();
+};
+#endif
diff --git a/mpeglib/lib/input/cdromRawAccess.cpp b/mpeglib/lib/input/cdromRawAccess.cpp
new file mode 100644
index 00000000..b0df4747
--- /dev/null
+++ b/mpeglib/lib/input/cdromRawAccess.cpp
@@ -0,0 +1,113 @@
+/*
+ reads raw input data from cdrom (system dependent)
+ 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 <iostream>
+
+#include "cdromRawAccess.h"
+
+using namespace std;
+
+CDRomRawAccess::CDRomRawAccess(CDRomToc* cdromToc) {
+ cdfile=NULL;
+ lOpen=false;
+ leof=true;
+ this->cdromToc=cdromToc;
+ lData=false;
+ dataStart=0;
+ len=0;
+}
+
+
+CDRomRawAccess::~CDRomRawAccess() {
+ close();
+}
+
+
+
+char* CDRomRawAccess::getBufferStart() {
+ return (char*)(data+dataStart);
+}
+
+int CDRomRawAccess::getBufferLen() {
+ if (eof()) {
+ return 0;
+ }
+ return len;
+}
+
+int CDRomRawAccess::open(const char* filename) {
+ if (isOpen()) {
+ close();
+ }
+ if (filename==NULL) {
+ filename=(char*)"/dev/cdrom";
+ }
+ if (strlen(filename) <= 1) {
+ filename="/dev/cdrom";
+ }
+ char* openfile=strchr(filename,'/');
+ cout << "openfile:"<<openfile<<endl;
+ cdfile=fopen(openfile, "rb");
+ lOpen=false;
+
+ if (cdfile == NULL) {
+ perror("open CDRomRawAccess");
+ } else {
+ lOpen=true;
+ leof=false;
+ }
+ return lOpen;
+}
+
+
+int CDRomRawAccess::eof() {
+ return leof;
+}
+
+
+int CDRomRawAccess::read(int minute,int second, int frame) {
+ if (isOpen()==false) {
+ cerr << "CDRomRawAccess not open"<<endl;
+ return false;
+ }
+
+ int lInRange=cdromToc->isInRange(minute,second,frame);
+ if (lInRange == false) {
+ if (minute*60+second+1 > cdromToc->getEndSecond()) {
+ leof=true;
+ }
+ return false;
+ }
+ return readDirect(minute,second,frame);
+}
+
+
+void CDRomRawAccess::close() {
+ if (isOpen()) {
+ fclose(cdfile);
+ lOpen=false;
+ leof=true;
+ }
+}
+
+int CDRomRawAccess::isData() {
+ return lData;
+}
+
+int CDRomRawAccess::isOpen() {
+ return lOpen;
+}
+
+
+
+
diff --git a/mpeglib/lib/input/cdromRawAccess.h b/mpeglib/lib/input/cdromRawAccess.h
new file mode 100644
index 00000000..d089a85b
--- /dev/null
+++ b/mpeglib/lib/input/cdromRawAccess.h
@@ -0,0 +1,67 @@
+/*
+ reads raw input data from cdrom (system dependent)
+ 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 __CDROMRAWACCESS_H
+#define __CDROMRAWACCESS_H
+
+#include "cdromToc.h"
+#include "inputStream.h"
+
+
+/**
+ Here we have a system wrapper for raw cdrom access.
+ Currently this is tested on Linux.
+*/
+
+
+
+
+
+class CDRomRawAccess {
+
+ CDRomToc* cdromToc;
+ char data[2352];
+ int dataStart;
+ int len;
+ int lData;
+
+ public:
+ CDRomRawAccess(CDRomToc* cdromToc);
+ virtual ~CDRomRawAccess();
+
+ // overload this for new Systems
+ virtual int readDirect(int minute,int second, int frame);
+
+ // wrapper for readDirect
+ int read(int minute,int second, int frame);
+
+ char* getBufferStart();
+ int getBufferLen();
+
+ int open(const char* filename);
+ int eof();
+ void close();
+ int isOpen();
+
+ int isData();
+
+ private:
+ FILE* cdfile;
+ int lOpen;
+ int leof;
+ int buflen;
+};
+
+#endif
+
+
diff --git a/mpeglib/lib/input/cdromToc.cpp b/mpeglib/lib/input/cdromToc.cpp
new file mode 100644
index 00000000..919ecdc8
--- /dev/null
+++ b/mpeglib/lib/input/cdromToc.cpp
@@ -0,0 +1,234 @@
+/*
+ reads toc from cdrom (system dependent)
+ 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 "cdromToc.h"
+
+#include <iostream>
+
+using namespace std;
+
+CDRomToc::CDRomToc() {
+ maxEntries=0;
+}
+
+
+CDRomToc::~CDRomToc() {
+}
+
+
+void CDRomToc::insertTocEntry(int minute,int second,int frame) {
+ int i;
+ int j;
+ if (isElement(minute,second,frame)) {
+ return;
+ }
+
+ i=getNextTocEntryPos(minute,second,frame);
+
+ // now shift from i to end
+ if (maxEntries == 100) {
+ cerr << "maximum of toc entries reached"<<endl;
+ exit(0);
+ }
+ for (j=maxEntries;j>i;j--) {
+ tocEntries[j].minute=tocEntries[j-1].minute;
+ tocEntries[j].second=tocEntries[j-1].second;
+ tocEntries[j].frame=tocEntries[j-1].frame;
+ }
+ maxEntries++;
+
+ tocEntries[i].minute=minute;
+ tocEntries[i].second=second;
+ tocEntries[i].frame=frame;
+ calculateRange();
+}
+
+
+int CDRomToc::getNextTocEntryPos(int minute,int second,int frame) {
+ int i;
+ if (maxEntries == 0) {
+ return 0;
+ }
+
+ for (i=0;i<maxEntries;i++) {
+ if (tocEntries[i].minute <= minute) {
+ continue;
+ } else {
+ break;
+ }
+ if (tocEntries[i].second <= second) {
+ continue;
+ } else {
+ break;
+ }
+ if (tocEntries[i].frame <= frame) {
+ continue;
+ }
+ break;
+ }
+ return i;
+}
+
+
+
+int CDRomToc::isElement(int minute,int second,int frame) {
+ int i;
+
+ for (i=0;i<maxEntries;i++) {
+ if (tocEntries[i].minute == minute) {
+ if (tocEntries[i].second == second) {
+ if (tocEntries[i].frame == frame) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+
+
+
+
+
+int CDRomToc::getTocEntries() {
+ return maxEntries;
+}
+
+
+TocEntry* CDRomToc::getTocEntry(int entry) {
+ return &(tocEntries[entry]);
+}
+
+
+void CDRomToc::print() {
+ int i;
+ cerr << "******* printing TOC [START]"<<endl;
+ for(i=0;i<maxEntries;i++) {
+ cerr << "i:"<<i
+ <<" M:"<<tocEntries[i].minute
+ <<" S:"<<tocEntries[i].second
+ <<" F:"<<tocEntries[i].frame<<endl;
+ }
+ cerr << "******* printing TOC [END}"<<endl;
+}
+
+
+int CDRomToc::isInRange(int minute,int second,int) {
+ long val=minute*60+second;
+ if (val < startByte) {
+ return false;
+ }
+ if (val > endByte) {
+ return false;
+ }
+ return true;
+}
+
+int CDRomToc::calculateRange() {
+
+
+ if (maxEntries < 2) {
+ cout << "no two elemts in toc"<<endl;
+ return false;
+ }
+ startByte=tocEntries[0].minute*60*+tocEntries[0].second;
+
+ // do a safty end because of the kernel bug
+ int minute=tocEntries[maxEntries-1].minute;
+ int second=tocEntries[maxEntries-1].second-20;
+ if (second < 0) {
+ minute--;
+ second=60+second;
+ }
+ if (minute < 0) {
+ endByte=0;
+ return true;
+ }
+
+ endByte=minute*60+second;
+
+ return true;
+
+}
+
+
+int CDRomToc::getEndSecond() {
+ return endByte;
+}
+
+
+
+
+int CDRomToc::open(const char* openfile) {
+ int i;
+ int pos=0;
+ maxEntries=0;
+ const char* filename=strchr(openfile,'/');
+ FILE* file =fopen(filename, "rb");
+ if (file == NULL) {
+ perror("open");
+ return false;
+ }
+ cout << "reading toc on:"<<filename<<" openfile:"<<openfile<<endl;
+
+ int startToc=0;
+ int endToc=0;
+
+ if (getStartEnd(file,startToc,endToc) == false) {
+ cout << "getStartEnd in CDRomToc failed"<<endl;
+ fclose(file);
+ return false;
+ }
+ cout << "startToc:"<<startToc<<" endToc:"<<endToc<<endl;
+ cout << "reading toc -2"<<endl;
+ /* read individual tracks */
+ int min;
+ int sec;
+ int frame;
+
+ for (i=startToc; i<=endToc; i++) {
+ int min;
+ int sec;
+ int frame;
+
+ if (readToc(file,i,min,sec,frame) == false) {
+ cout << "error in CDRomToc::readToc"<<endl;
+ fclose(file);
+ return false;
+ }
+ cout << "min:"<<min<<endl;
+ cout << "sec:"<<sec<<endl;
+ cout << "frame:"<<frame<<endl;
+
+ insertTocEntry(min,sec,frame);
+ pos++;
+ }
+
+
+ /* read the lead-out track */
+ if (readLeadOut(file,min,sec,frame) == false) {
+ cout << "error in CDRomToc::reatLeadOut"<<endl;
+ return false;
+ }
+ pos++;
+ insertTocEntry(min,sec,frame);
+
+ maxEntries=pos;
+
+ fclose(file);
+
+ return true;
+}
+
diff --git a/mpeglib/lib/input/cdromToc.h b/mpeglib/lib/input/cdromToc.h
new file mode 100644
index 00000000..20b60e10
--- /dev/null
+++ b/mpeglib/lib/input/cdromToc.h
@@ -0,0 +1,65 @@
+/*
+ reads toc from cdrom (system dependent)
+ 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 __CDROMTOC_H
+#define __CDROMTOC_H
+
+extern "C" {
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+}
+
+struct TocEntry {
+ int minute;
+ int second;
+ int frame;
+};
+
+
+class CDRomToc {
+
+ TocEntry tocEntries[100];
+ int maxEntries;
+ int startByte;
+ int endByte;
+
+ public:
+ CDRomToc();
+ virtual ~CDRomToc();
+ int open(const char* device);
+ int getTocEntries();
+ TocEntry* getTocEntry(int entry);
+ void insertTocEntry(int minute,int second,int frame);
+ int getNextTocEntryPos(int minute,int second,int frame);
+ int isInRange(int minute,int second,int frame);
+ int isElement(int minute,int second,int frame);
+
+ int getEndSecond();
+
+ void print();
+
+ private:
+ // platform specific calls.
+ int getStartEnd(FILE* file,int& start, int& end);
+ int readToc(FILE* file,int num,int& min,int& sec, int& frame);
+ int readLeadOut(FILE* file,int& min,int& sec, int& frame);
+
+
+
+
+ int calculateRange();
+
+};
+
+#endif
diff --git a/mpeglib/lib/input/fileAccessWrapper.cpp b/mpeglib/lib/input/fileAccessWrapper.cpp
new file mode 100644
index 00000000..246807a8
--- /dev/null
+++ b/mpeglib/lib/input/fileAccessWrapper.cpp
@@ -0,0 +1,65 @@
+/*
+ wraps an inputStream for the splayFileBuffer.
+ 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 "fileAccessWrapper.h"
+
+#include <iostream>
+
+using namespace std;
+
+FileAccessWrapper::FileAccessWrapper(InputStream* input) {
+ this->input=input;
+}
+
+
+FileAccessWrapper::~FileAccessWrapper() {
+
+}
+
+
+int FileAccessWrapper::open(const char*) {
+ cout << "FileAccessWrapper open not implemented"<<endl;
+ exit(0);
+}
+
+
+void FileAccessWrapper::close() {
+ cout << "FileAccessWrapper close not implemented"<<endl;
+ exit(0);
+}
+
+
+int FileAccessWrapper::read(char* dest,int len) {
+ return input->read(dest,len);
+}
+
+int FileAccessWrapper::eof() {
+ return input->eof();
+}
+
+
+int FileAccessWrapper::seek(long pos) {
+ return input->seek(pos);
+}
+
+
+long FileAccessWrapper::getBytePosition() {
+ return input->getBytePosition();
+}
+
+
+long FileAccessWrapper::getByteLength() {
+ return input->getByteLength();
+}
+
diff --git a/mpeglib/lib/input/fileAccessWrapper.h b/mpeglib/lib/input/fileAccessWrapper.h
new file mode 100644
index 00000000..d7882abb
--- /dev/null
+++ b/mpeglib/lib/input/fileAccessWrapper.h
@@ -0,0 +1,41 @@
+/*
+ wraps an inputStream for the splayFileBuffer.
+ 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 __FILEACCESSWRAPPER_H
+#define __FILEACCESSWRAPPER_H
+
+
+#include "../util/file/fileAccess.h"
+#include "inputStream.h"
+
+
+class FileAccessWrapper : public FileAccess {
+
+ InputStream* input;
+
+ public:
+ FileAccessWrapper(InputStream* input);
+ virtual ~FileAccessWrapper();
+
+ int open(const char* file);
+ void close();
+ int read(char* dest,int len);
+ int eof();
+ int seek(long pos);
+ long getBytePosition();
+ long getByteLength();
+
+};
+
+
+#endif
diff --git a/mpeglib/lib/input/fileInputStream.cpp b/mpeglib/lib/input/fileInputStream.cpp
new file mode 100644
index 00000000..77c31ed6
--- /dev/null
+++ b/mpeglib/lib/input/fileInputStream.cpp
@@ -0,0 +1,148 @@
+/*
+ reads 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
+
+ */
+
+
+
+#include "fileInputStream.h"
+
+#include <iostream>
+
+using namespace std;
+
+FileInputStream::FileInputStream() {
+ file=NULL;
+ lopen=false;
+ fileLen=0;
+}
+
+
+FileInputStream::~FileInputStream() {
+ close();
+}
+
+
+int FileInputStream::open(const char* dest) {
+
+ close();
+ if (dest == NULL) {
+ return false;
+ }
+ setUrl(dest);
+ if (strlen(dest) == 1) {
+ if (strncmp(dest,"-",1)==0) {
+ file=::fdopen(0,"rb");
+ }
+ }
+ // load out of current dir if no full path is given
+ if (file == NULL) {
+ file=fopen(dest,"rb");
+ }
+ fileLen=0;
+ if (file == NULL) {
+ cout <<"cannot open file:"<< dest<<endl;
+
+ } else {
+ lopen=true;
+ struct stat fileStat;
+ stat(dest,&fileStat);
+ fileLen=(long)fileStat.st_size;
+ }
+ int back=(file!=NULL);
+ return back;
+}
+
+
+void FileInputStream::close() {
+ if (isOpen()) {
+ ::fclose(file);
+ file=NULL;
+ lopen=false;
+ }
+}
+
+
+int FileInputStream::isOpen() {
+ return lopen;
+}
+
+
+int FileInputStream::eof() {
+ if (isOpen()==false){
+ return true;
+ }
+ int back=true;
+ if (file != NULL) {
+ back=feof(file);
+ }
+
+ return back;
+}
+
+
+int FileInputStream::read(char* ptr,int size) {
+ int bytesRead=-1;
+ if (isOpen()) {
+ if (size <= 0) {
+ cout << "size is <= 0!"<<endl;
+ return 0;
+ }
+ if (file != NULL) {
+ bytesRead=fread(ptr,1,size,file);
+ }
+ } else {
+ cerr << "read on not open file want:"<<size<<endl;
+ return 0;
+ }
+ return bytesRead;
+}
+
+
+int FileInputStream::seek(long posInBytes) {
+ int back=true;
+ if (isOpen()==false) {
+ return false;
+ }
+ long pos=-1;
+ if (file != NULL) {
+ pos=fseek(file,posInBytes,SEEK_SET);
+ }
+
+ if (pos < 0) {
+ cout <<"seek error in FileInputStream::seek"<<endl;
+ back=false;
+ }
+ return back;
+}
+
+
+long FileInputStream::getByteLength() {
+ return fileLen;
+}
+
+
+long FileInputStream::getBytePosition() {
+ int back=0;
+ if (isOpen()) {
+ if (file != NULL) {
+ back=ftell(file);
+ }
+ }
+ return back;
+}
+
+
+
+void FileInputStream::print() {
+ printf("pos in file:%8x\n",(int)getBytePosition());
+}
+
+
diff --git a/mpeglib/lib/input/fileInputStream.h b/mpeglib/lib/input/fileInputStream.h
new file mode 100644
index 00000000..ea421a55
--- /dev/null
+++ b/mpeglib/lib/input/fileInputStream.h
@@ -0,0 +1,46 @@
+/*
+ reads 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 __FILEINPUTSTREAM_H
+#define __FILEINPUTSTREAM_H
+
+
+
+#include "inputStream.h"
+
+
+
+class FileInputStream : public InputStream{
+
+ FILE* file;
+ int lopen;
+ long fileLen;
+ public:
+ FileInputStream();
+ ~FileInputStream();
+
+ int open(const char* dest);
+ void close();
+ int isOpen();
+
+ int eof();
+ int read(char* ptr,int size);
+ int seek(long bytePos);
+
+ long getByteLength();
+ long getBytePosition();
+
+ void print();
+
+};
+#endif
diff --git a/mpeglib/lib/input/httpInputStream.cpp b/mpeglib/lib/input/httpInputStream.cpp
new file mode 100644
index 00000000..df2f09c4
--- /dev/null
+++ b/mpeglib/lib/input/httpInputStream.cpp
@@ -0,0 +1,327 @@
+/*
+ reads 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
+
+ */
+
+
+
+#include "httpInputStream.h"
+
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xffffffff
+#endif
+
+#include <iostream>
+
+using namespace std;
+
+static const char *httpstr="http://";
+
+
+
+static char *strndup(char *src,int num) {
+ char *dst;
+
+ if(!(dst=(char *)malloc(num+1)))return NULL;
+ dst[num]='\0';
+
+ return strncpy(dst, src, num);
+}
+
+static char *url2hostport(char *url,char **hname,
+ unsigned long *hip,unsigned int *port) {
+ char *cptr;
+ struct hostent *myhostent;
+ struct in_addr myaddr;
+ int isip=1;
+
+ if(!(strncmp(url,httpstr,7)))url+=7;
+ cptr=url;
+ while(*cptr && *cptr!=':' && *cptr!='/') {
+ if((*cptr<'0' || *cptr>'9') && *cptr!='.')isip=0;
+ cptr++;
+ }
+ if(!(*hname=strndup(url,cptr-url))) {
+ *hname=NULL;
+ return NULL;
+ }
+ if(!isip)
+ {
+ if (!(myhostent=gethostbyname(*hname)))return NULL;
+ memcpy(&myaddr,myhostent->h_addr,sizeof(myaddr));
+ *hip=myaddr.s_addr;
+ }
+ else if((*hip=inet_addr(*hname))==INADDR_NONE)return NULL;
+ if(!*cptr || *cptr=='/') {
+ *port=80;
+ return cptr;
+ }
+ *port=atoi(++cptr);
+ while(*cptr && *cptr!='/')cptr++;
+ return cptr;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+HttpInputStream::HttpInputStream() {
+
+ proxyurl=NULL;
+ proxyip=0;
+ lopen=false;
+ byteCnt=0;
+}
+
+
+HttpInputStream::~HttpInputStream() {
+ close();
+}
+
+
+int HttpInputStream::open(const char* filename) {
+ close();
+ if (filename == NULL) {
+ return false;
+ }
+ /*
+ int matchPos=InputStream::getPath(filename,"http");
+ if (matchPos=0) {
+ return false;
+ }
+ */
+
+ char* filename2=strdup(filename);
+ if((fp=http_open(filename2))==NULL) {
+ cout << "seterrorcode(SOUND_ERROR_FILEOPENFAIL)"<<endl;
+ delete filename2;
+ return false;
+ }
+ delete filename2;
+ lopen=true;
+ setUrl(filename);
+ return lopen;
+}
+
+
+void HttpInputStream::close() {
+ if (isOpen()) {
+ ::fclose(fp);
+ }
+ lopen=false;
+ setUrl(NULL);
+}
+
+
+int HttpInputStream::isOpen() {
+ return lopen;
+}
+
+
+int HttpInputStream::eof() {
+ if (isOpen()==false){
+ return true;
+ }
+ return feof(fp);
+}
+
+
+int HttpInputStream::read(char* ptr,int size) {
+ int bytesRead=0;
+ if (isOpen()) {
+ bytesRead=fread(ptr, 1,size, fp);
+ if (ferror(fp) != 0){
+ cout <<"http fread error"<<endl;
+ } else {
+ byteCnt+=bytesRead;
+ }
+ }
+ return bytesRead;
+}
+
+int HttpInputStream::seek(long posInBytes) {
+ cout << "HttpInputStream::setBytePos not implemented:"<<posInBytes<<endl;
+ return false;
+}
+
+
+
+long HttpInputStream::getByteLength() {
+ cout << "HttpInputStream::getByteLength not implemented"<<endl;
+ return 0;
+}
+
+
+
+void HttpInputStream::print() {
+ printf("pos in file:%8x\n",(int)ftell(fp));
+}
+
+
+int HttpInputStream::writestring(int fd, char *string) {
+ int result,bytes=strlen(string);
+
+ while (bytes) {
+ if((result=SOCKETWRITEFUNC(fd,string,bytes))<0 && errno!=EINTR) {
+ cout << "writestring fail -1"<<endl;
+ return false;
+ }
+ else if(result==0) {
+ cout << "writestring fail -2"<<endl;
+ return false;
+ }
+ string += result;
+ bytes -= result;
+ }
+ return true;
+}
+
+
+
+FILE* HttpInputStream::http_open(char *url) {
+ char *purl=NULL,*host,*request,*sptr;
+ char agent[50];
+ int linelength;
+ unsigned long myip;
+ unsigned int myport;
+ int sock;
+ int relocate=0,numrelocs=0;
+ struct sockaddr_in server;
+ FILE *myfile;
+ if (url == NULL) {
+ cout << "cannot open NULL http_open"<<endl;
+ return NULL;
+ }
+ if (strlen(url)==0) {
+ cout << "zero length http_open"<<endl;
+ return NULL;
+ }
+
+ if(!proxyip)
+ {
+ if(!proxyurl)
+ if(!(proxyurl=getenv("MP3_HTTP_PROXY")))
+ if(!(proxyurl=getenv("http_proxy")))
+ proxyurl = getenv("HTTP_PROXY");
+ if (proxyurl && proxyurl[0] && strcmp(proxyurl, "none"))
+ {
+ if (!(url2hostport(proxyurl, &host, &proxyip, &proxyport)))
+ {
+ cout << "seterrorcode(SOUND_ERROR_UNKNOWNPROXY)"<<endl;;
+ return NULL;
+ }
+ if(host)free(host);
+ }
+ else
+ proxyip = INADDR_NONE;
+ }
+
+ if((linelength=strlen(url)+100)<1024)
+ linelength=1024;
+ if(!(request=(char *)malloc(linelength)) || !(purl=(char *)malloc(1024)))
+ {
+ cout << "seterrorcode(SOUND_ERROR_MEMORYNOTENOUGH)"<<endl;
+ return NULL;
+ }
+ strncpy(purl,url,1023);
+ purl[1023]='\0';
+ do{
+ strcpy(request,"GET ");
+ if(proxyip!=INADDR_NONE)
+ {
+ if(strncmp(url,httpstr,7))
+ strcat(request,httpstr);
+ strcat(request,purl);
+ myport=proxyport;
+ myip=proxyip;
+ }
+ else
+ {
+ if(!(sptr=url2hostport(purl,&host,&myip,&myport)))
+ {
+ cout << "seterrorcode(SOUND_ERROR_UNKNOWNHOST)"<<endl;;
+ return NULL;
+ }
+ if (host)
+ free (host);
+ strcat (request, sptr);
+ }
+ sprintf (agent, " HTTP/1.0\r\nUser-Agent: %s/%s\r\n\r\n",
+ "Splay","0.6");
+ strcat (request, agent);
+ server.sin_family = AF_INET;
+ server.sin_port = htons(myport);
+ server.sin_addr.s_addr = myip;
+ if((sock=socket(PF_INET,SOCK_STREAM,6))<0) {
+ cout <<"seterrorcode(SOUND_ERROR_SOCKET)"<<endl;
+ return NULL;
+ }
+ if(connect(sock,(struct sockaddr *)&server,sizeof(server))) {
+ cout <<"seterrorcode(SOUND_ERROR_CONNECT)"<<endl;
+ return NULL;
+ }
+ if(!writestring(sock,request))return NULL;
+ if(!(myfile=::fdopen(sock, "rb"))) {
+ cout << "seterrorcode(SOUND_ERROR_FDOPEN)"<<endl;
+ return NULL;
+ };
+ relocate=false;
+ purl[0]='\0';
+ if(!readstring(request,linelength-1,myfile))return NULL;
+ if((sptr=strchr(request,' '))) {
+ switch(sptr[1]) {
+ case '3':relocate=true;
+ case '2':break;
+ default:
+ cout <<"seterrorcode(SOUND_ERROR_HTTPFAIL)"<<endl;
+ return NULL;
+ }
+ }
+ do {
+ if(!readstring(request,linelength-1,myfile))return NULL;
+ if(!strncmp(request,"Location:",9))
+ strncpy (purl,request+10,1023);
+ } while (request[0]!='\r' && request[0]!='n');
+ } while(relocate && purl[0] && numrelocs++<5);
+ if(relocate) {
+ cout << "seterrorcode(SOUND_ERROR_TOOMANYRELOC)"<<endl;
+ return NULL;
+ }
+ free(purl);
+ free(request);
+ return myfile;
+}
+
+long HttpInputStream::getBytePosition() {
+ return 0;
+}
+
+int HttpInputStream::readstring(char *string,int maxlen,FILE *f) {
+ char *result;
+
+ do{
+ result=fgets(string,maxlen,f);
+ }while(!result && errno==EINTR);
+ if(!result)
+ {
+ cout << "seterrorcode(SOUND_ERROR_FILEREADFAIL)"<<endl;
+ return false;
+ }
+
+ return true;
+}
diff --git a/mpeglib/lib/input/httpInputStream.h b/mpeglib/lib/input/httpInputStream.h
new file mode 100644
index 00000000..78ec10f0
--- /dev/null
+++ b/mpeglib/lib/input/httpInputStream.h
@@ -0,0 +1,84 @@
+/*
+ reads 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 __HTTPINPUTSTREAM_H
+#define __HTTPINPUTSTREAM_H
+
+
+#include "inputStream.h"
+
+#ifndef __STRICT_ANSI__
+#define __STRICT_ANSI__
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+
+
+#if defined WIN32
+#include <io.h>
+#define SOCKETWRITEFUNC _write
+#else
+
+extern "C" {
+#include <netdb.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+ }
+#define SOCKETWRITEFUNC write
+#endif
+
+#include <sys/types.h>
+#include <errno.h>
+
+class HttpInputStream : public InputStream{
+
+ long byteCnt;
+
+ public:
+ HttpInputStream();
+ ~HttpInputStream();
+
+ int open(const char* dest);
+ void close();
+ int isOpen();
+
+ int eof();
+ int read(char* ptr,int size);
+ int seek(long bytePos);
+
+ long getByteLength();
+ long getBytePosition();
+
+ void print();
+
+ private:
+
+ FILE* fp;
+ int size;
+
+ int writestring(int fd,char *string);
+ int readstring(char *string,int maxlen,FILE *f);
+ FILE* http_open(char *url);
+
+ char* proxyurl;
+ unsigned long proxyip;
+ unsigned int proxyport;
+
+ int lopen;
+
+};
+#endif
diff --git a/mpeglib/lib/input/inputDetector.cpp b/mpeglib/lib/input/inputDetector.cpp
new file mode 100644
index 00000000..28bcad5c
--- /dev/null
+++ b/mpeglib/lib/input/inputDetector.cpp
@@ -0,0 +1,192 @@
+/*
+ returns inputtype for a given string
+ 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 "inputDetector.h"
+
+#include <iostream>
+
+using namespace std;
+
+static const char *filestrglobal1="/";
+static const char *filestrglobal2="./";
+
+typedef struct prot2type_s {
+ const char* name;
+ int type;
+} prot2type;
+
+static prot2type protocols[]= { {"http:" , __INPUT_HTTP },
+ {"cdi:" , __INPUT_CDI },
+ {"vcd:" , __INPUT_CDI },
+ {"file:" , __INPUT_FILE },
+ {"cdda:" , __INPUT_CDDA },
+ {"audiocd:", __INPUT_CDDA },
+ {NULL , __INPUT_UNKNOWN} };
+
+
+InputDetector::InputDetector() {
+}
+
+
+InputDetector::~InputDetector() {
+}
+
+int InputDetector::getProtocolPos(int type,const char* url) {
+ prot2type* current=protocols;
+ int i=0;
+ while(current->name != NULL) {
+ if (current->type == type) {
+ int len=strlen(current->name);
+ if (strncmp(url,current->name,len)==0) {
+ return i;
+ }
+ }
+ i++;
+ current++;
+ }
+ return -1;
+}
+
+int InputDetector::getProtocolType(const char* url) {
+ prot2type* current=protocols;
+ int n=strlen(url);
+ if (n > 0) {
+ while(current->name != NULL) {
+ int k=strlen(current->name);
+ if (n >= k) {
+ if (strncmp(url,current->name,k)==0) {
+ return current->type;
+ }
+ }
+ current++;
+ }
+ }
+ return __INPUT_UNKNOWN;
+}
+
+int InputDetector::getInputType(const char* url) {
+ int back=__INPUT_FILE;
+
+ if (url == NULL) {
+ return back;
+ }
+
+ back=InputDetector::getProtocolType(url);
+ if (back == __INPUT_UNKNOWN) {
+ back = __INPUT_FILE;
+ }
+
+ return back;
+
+}
+
+char* InputDetector::removeProtocol(const char* url) {
+ int type=InputDetector::getProtocolType(url);
+ int n=strlen(url);
+ if (n == 0) {
+ return NULL;
+ }
+ if (type == __INPUT_UNKNOWN) {
+ return strdup(url);
+ }
+ int pos=InputDetector::getProtocolPos(type,url);
+ if (pos == -1) {
+ return NULL;
+ }
+ const char* name=protocols[pos].name;
+ int k=strlen(name);
+ if (n >= k) {
+ return strdup(url+k);
+ }
+ return NULL;
+
+}
+
+char* InputDetector::getExtension(const char* url) {
+ if (url == NULL) {
+ cout << "get url NULL"<<endl;
+ return NULL;
+ }
+ char* back=NULL;
+ char* extStart=strrchr(url,'.');
+ if (extStart != NULL) {
+ cout << "extStart:"<<extStart<<endl;
+ back=strdup(extStart);
+ }
+ return back;
+}
+
+char* InputDetector::removeExtension(const char* url,char* extension) {
+ if (url == NULL) {
+ cout << "removeExtension url NULL"<<endl;
+ return NULL;
+ }
+ if (extension == NULL) {
+ cout << "removeExtension extension NULL"<<endl;
+ return strdup(url);
+ }
+ char* back=NULL;
+ int nExt=strlen(extension);
+ int nUrl=strlen(url);
+ cout << "extension:"<<extension<<" url:"<<url<<endl;
+ if (nUrl >= nExt) {
+ if(strncmp(url+nUrl-nExt,extension,nExt)==0) {
+ back=new char[nUrl-nExt+1];
+ back[nUrl-nExt]=0;
+ strncpy(back,url,nUrl-nExt);
+ }
+ }
+ cout << "removeExt:"<<back<<endl;
+ return back;
+
+}
+
+char* InputDetector::getWithoutExtension(const char* url) {
+ char* extension=NULL;
+ char* back=NULL;
+ if (url == NULL) {
+ return NULL;
+ }
+ extension=InputDetector::getExtension(url);
+ if (extension == NULL) {
+ back=strdup(url);
+ } else {
+ back=InputDetector::removeExtension(url,extension);
+ delete extension;
+ }
+ return back;
+}
+
+char* InputDetector::getFilename(const char* url) {
+ if (url == NULL) {
+ return NULL;
+ }
+ char* startSlash=strrchr(url,'/');
+ if (startSlash == NULL) {
+ return NULL;
+ }
+ if (strlen(startSlash) == 1) {
+ return NULL;
+ }
+ startSlash++;
+ if (*startSlash == 0) {
+ return NULL;
+ }
+ return strdup(startSlash);
+}
+
+
+char* InputDetector::removeSlash(const char* url) {
+ return InputDetector::removeExtension(url,(char*)"/");
+}
diff --git a/mpeglib/lib/input/inputDetector.h b/mpeglib/lib/input/inputDetector.h
new file mode 100644
index 00000000..f4c3e47d
--- /dev/null
+++ b/mpeglib/lib/input/inputDetector.h
@@ -0,0 +1,56 @@
+/*
+ returns inputtype for a given string
+ 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 __INPUTDETECTOR_H
+#define __INPUTDETECTOR_H
+
+
+
+#define __INPUT_UNKNOWN 0
+#define __INPUT_FILE 1
+#define __INPUT_HTTP 2
+#define __INPUT_CDI 3
+#define __INPUT_BUFFER 4
+#define __INPUT_CDDA 5
+
+extern "C" {
+#include <string.h>
+}
+
+
+class InputDetector {
+
+
+ public:
+ InputDetector();
+ ~InputDetector();
+
+ static int getInputType(const char* url);
+
+ static int getProtocolType(const char* url);
+ // returns new allocated string without protocol specifier
+ static char* removeProtocol(const char* url);
+ static char* getWithoutExtension(const char* url);
+ static char* getExtension(const char* url);
+ static char* removeExtension(const char* url,char* extension);
+ static char* removeSlash(const char* url);
+ static char* getFilename(const char* url);
+
+ private:
+ static int getProtocolPos(int type,const char* url);
+
+};
+
+#endif
+
diff --git a/mpeglib/lib/input/inputPlugin.cpp b/mpeglib/lib/input/inputPlugin.cpp
new file mode 100644
index 00000000..f3a33002
--- /dev/null
+++ b/mpeglib/lib/input/inputPlugin.cpp
@@ -0,0 +1,92 @@
+/*
+ C interface creator for input_plugins
+ 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 "inputPlugin.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+InputPlugin::InputPlugin() {
+}
+
+
+InputPlugin::~InputPlugin() {
+}
+
+
+
+int InputPlugin::getInputType(const char* dest) {
+ return InputDetector::getInputType(dest);
+}
+
+
+InputStream* InputPlugin::createInputStream(int inputType) {
+ // make checks which input routine to use
+ InputStream* inputStream;
+ int method;
+
+ inputStream=NULL;
+ method=inputType;
+
+ switch(method) {
+ case __INPUT_FILE: {
+ inputStream=new FileInputStream();
+ break;
+ }
+ case __INPUT_CDDA: {
+ inputStream=new CDDAInputStream();
+ break;
+ }
+
+ case __INPUT_HTTP: {
+ inputStream=new HttpInputStream();
+ break;
+ }
+ case __INPUT_CDI: {
+ inputStream=new CDRomInputStream();
+ break;
+ }
+ default:
+ cout << "error cannot create default input stream"<<endl;
+ exit(0);
+ }
+
+ return inputStream;
+}
+
+InputStream* InputPlugin::createInputStream(int inputType,int lThreadSafe) {
+ InputStream* input=InputPlugin::createInputStream(inputType);
+ if (lThreadSafe == false) {
+ return input;
+ }
+ InputStream* tsInput=new ThreadSafeInputStream(input);
+ return tsInput;
+}
+
+
+InputStream* InputPlugin::createInputStream(const char* dest) {
+ int method;
+
+ method=InputPlugin::getInputType(dest);
+ return (InputPlugin::createInputStream(method));
+}
+
+
+InputStream* InputPlugin::createInputStream(const char* dest,int lThreadSafe) {
+ int method;
+
+ method=InputPlugin::getInputType(dest);
+ return (InputPlugin::createInputStream(method,lThreadSafe));
+}
diff --git a/mpeglib/lib/input/inputPlugin.h b/mpeglib/lib/input/inputPlugin.h
new file mode 100644
index 00000000..5ac68307
--- /dev/null
+++ b/mpeglib/lib/input/inputPlugin.h
@@ -0,0 +1,45 @@
+/*
+ C interface creator for input_plugins
+ 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 __INPUTPLUGIN_H
+#define __INPUTPLUGIN_H
+
+#include "httpInputStream.h"
+#include "fileInputStream.h"
+#include "cdromInputStream.h"
+#include "bufferInputStream.h"
+#include "threadSafeInputStream.h"
+#include "cddaInputStream.h"
+#include <string.h>
+
+#include "inputDetector.h"
+#include <kdemacros.h>
+
+#define _INPUT_THREADSAFE 1
+
+class KDE_EXPORT InputPlugin {
+
+ public:
+ InputPlugin();
+ ~InputPlugin();
+
+ static InputStream* createInputStream(int inputType);
+ static InputStream* createInputStream(int inputType,int lThreadSafe);
+ static InputStream* createInputStream(const char* dest);
+ static InputStream* createInputStream(const char* dest,int lThreadSafe);
+ static int getInputType(const char* dest);
+
+};
+#endif
diff --git a/mpeglib/lib/input/inputStream.cpp b/mpeglib/lib/input/inputStream.cpp
new file mode 100644
index 00000000..7eb9943b
--- /dev/null
+++ b/mpeglib/lib/input/inputStream.cpp
@@ -0,0 +1,135 @@
+/*
+ generic input class
+ 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 "inputStream.h"
+#include "../util/mmx/mmx.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+InputStream::InputStream() {
+ timeStampArray=new TimeStampArray((char*)"Input",3000);
+ urlBuffer=new DynBuffer(20);
+ // we call mm_support() here because it is the only position
+ // where we gurantee that not threads are
+ // running (the call is not thread safe)
+ // afer the call we never execute the asm part again
+ // and everything is fine
+ mm_support();
+}
+
+
+
+InputStream::~InputStream() {
+ delete timeStampArray;
+ delete urlBuffer;
+
+}
+
+
+int InputStream::open(const char* dest) {
+ cout << "direct virtual call InputStream::open:"<<dest<<endl;
+ return false;
+}
+
+
+void InputStream::close() {
+ cout << "direct virtual call InputStream::close"<<endl;
+ exit(0);
+}
+
+
+int InputStream::isOpen() {
+ cout << "direct virtual call InputStream::isOpen"<<endl;
+ exit(0);
+ return false;
+}
+
+
+int InputStream::eof() {
+ cout << "direct virtual call InputStream::eof"<<endl;
+ exit(0);
+ return true;
+}
+
+
+int InputStream::read(char* ,int ) {
+ cout << "direct virtual call InputStream::read"<<endl;
+ exit(0);
+ return 0;
+}
+
+
+int InputStream::seek(long bytePos) {
+ cout << "direct virtual call InputStream::seek:"<<bytePos<<endl;
+ exit(0);
+ return false;
+}
+
+void InputStream::clear() {
+ cout << "direct virtual call InputStream::clear:"<<endl;
+ exit(0);
+}
+
+
+long InputStream::getByteLength() {
+ cout << "direct virtual call InputStream::getByteLength"<<endl;
+ return 0;
+}
+
+
+long InputStream::getBytePosition() {
+ cout << "direct virtual call InputStream::getBytePosition"<<endl;
+ return 0;
+}
+
+
+void InputStream::insertTimeStamp(TimeStamp* src,long key,int len) {
+ timeStampArray->insertTimeStamp(src,key,len);
+}
+
+TimeStamp* InputStream::getTimeStamp(long key) {
+ return timeStampArray->getTimeStamp(key);
+}
+
+
+int InputStream::bytesUntilNext(long key) {
+ return timeStampArray->bytesUntilNext(key);
+}
+
+void InputStream::print() {
+ cout << "direct virtual call InputStream::print"<<endl;
+}
+
+
+
+
+
+char* InputStream::getUrl() {
+ return urlBuffer->getData();
+}
+
+
+void InputStream::setUrl(const char* url) {
+ urlBuffer->clear();
+ if (url != NULL) {
+ urlBuffer->append(url);
+ }
+}
+
+
+
+
+
diff --git a/mpeglib/lib/input/inputStream.h b/mpeglib/lib/input/inputStream.h
new file mode 100644
index 00000000..e232e99b
--- /dev/null
+++ b/mpeglib/lib/input/inputStream.h
@@ -0,0 +1,79 @@
+/*
+ generic input class
+ 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 __MPEGLIBINPUTSTREAM_H
+#define __MPEGLIBINPUTSTREAM_H
+
+
+extern "C" {
+#include <string.h>
+#include <stdio.h>
+#include <sys/stat.h>
+}
+
+#include "../util/timeStampArray.h"
+#include "../util/dynBuffer.h"
+
+
+
+
+/**
+ The abstraction for the input stream. In derived classes
+ we implement http,file and cdi access.
+*/
+
+
+class InputStream {
+
+
+
+ public:
+ InputStream();
+
+
+ virtual ~InputStream();
+
+ virtual int open(const char* dest);
+ virtual void close();
+ virtual int isOpen();
+
+ virtual int eof();
+ virtual int read(char* ptr,int size);
+ virtual int seek(long bytePos);
+ // clears possible input buffers
+ // (called by the decoderPlugin after a resyncCommit)
+ virtual void clear();
+
+ virtual long getByteLength();
+ virtual long getBytePosition();
+
+ virtual void insertTimeStamp(TimeStamp* src,long key,int len);
+ virtual TimeStamp* getTimeStamp(long key);
+ virtual int bytesUntilNext(long key);
+ virtual void print();
+ char* getUrl();
+
+
+
+ protected:
+ DynBuffer* urlBuffer;
+
+
+ class TimeStampArray* timeStampArray;
+ void setUrl(const char* url);
+
+
+};
+#endif
diff --git a/mpeglib/lib/input/simpleRingBuffer.cpp b/mpeglib/lib/input/simpleRingBuffer.cpp
new file mode 100644
index 00000000..71c92329
--- /dev/null
+++ b/mpeglib/lib/input/simpleRingBuffer.cpp
@@ -0,0 +1,420 @@
+/*
+ a thread safe ring buffer without dependencies
+ 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 "simpleRingBuffer.h"
+#include <string.h>
+
+#include <iostream>
+
+using namespace std;
+
+static int instanceCnt=0;
+
+SimpleRingBuffer::SimpleRingBuffer(int size,int minLinSize) {
+ abs_thread_mutex_init(&mut);
+ abs_thread_cond_init(&dataCond);
+ abs_thread_cond_init(&spaceCond);
+
+ instance=instanceCnt;
+ instanceCnt++;
+ this->size=size;
+ startPos=(char*)malloc(size);
+ readPos=startPos;
+ writePos=startPos;
+ lockPos=startPos;
+
+ lockgrade=0;
+ fillgrade=0;
+ linAvail=size;
+ lastPos=(startPos+size-1);
+ eofPos=lastPos+1;
+
+ canWrite=size;
+ canRead=0;
+
+ minLinBuf=new char[minLinSize];
+ this->minLinBufSize=minLinSize;
+ waitMinData=0;
+ waitMinSpace=0;
+ lWaitForData=false;
+ lWaitForSpace=false;
+
+ readBytes=0;
+ writeBytes=0;
+
+ lCanWaitForData=true;
+ lCanWaitForSpace=true;
+}
+
+
+SimpleRingBuffer::~SimpleRingBuffer() {
+ // The user of this class must take care that the threads
+ // have exited!
+ free(startPos);
+ delete [] minLinBuf;
+ abs_thread_mutex_destroy(&mut);
+ abs_thread_cond_destroy(&dataCond);
+ abs_thread_cond_destroy(&spaceCond);
+}
+
+
+int SimpleRingBuffer::getSize() {
+ return size;
+}
+
+
+int SimpleRingBuffer::getWriteArea(char* &ptr,int &size) {
+
+ // When we are in this area the following
+ // can happen by the other thread
+ // fillgrade is decreased (because reader fowards)
+ // readPos is changed.
+
+ ptr=writePos;
+ size=canWrite;
+
+ return size;
+}
+
+
+void SimpleRingBuffer::updateCanWrite() {
+ if (lockPos < writePos) {
+ canWrite=eofPos-writePos;
+ //printf("1 c:%d l:%p w:%p",canWrite,lockPos,writePos);
+ } else if (lockPos > writePos) {
+ canWrite=lockPos-writePos;
+ //printf("2 c:%d l:%p w:%p",canWrite,lockPos,writePos);
+ } else {
+ if (fillgrade > 0) {
+ canWrite=0;
+ } else {
+ canWrite=eofPos-writePos;
+ }
+ //printf("2 c:%d ",canWrite);
+
+ }
+ if (canWrite < 0) {
+ printf("error canWrite:%d fill:%d lock:%p start:%p eof:%p write:%p\n",
+ canWrite,fillgrade,lockPos,startPos,eofPos,writePos);
+ }
+
+}
+
+
+void SimpleRingBuffer::updateCanRead() {
+ canRead=fillgrade-lockgrade;
+ int currentSpace=size-fillgrade;
+ if (currentSpace >= waitMinSpace) {
+ abs_thread_cond_signal(&spaceCond);
+ }
+ if (canRead < 0) {
+ printf("error canRead:%d fillgrade:%d lockgrade:%d \n",
+ canRead,fillgrade,lockgrade);
+ }
+
+}
+
+
+void SimpleRingBuffer::forwardLockPtr(int nBytes) {
+ abs_thread_mutex_lock(&mut);
+
+ if (fillgrade < lockgrade) {
+ printf("1:fillgrade:%d < lockgrade:%d\n",fillgrade,lockgrade);
+ }
+ fillgrade-=nBytes;
+ lockgrade-=nBytes;
+ if (fillgrade < lockgrade) {
+ printf("2:fillgrade:%d < lockgrade:%d nBytes:%d\n",
+ fillgrade,lockgrade,nBytes);
+ }
+ lockPos=lockPos+nBytes;
+ if (lockPos > lastPos) { // we expects that we had a linAvail part
+ // if user forwards more than buffer boundary
+ nBytes=lockPos-lastPos;
+ lockPos=startPos+nBytes-1;
+ }
+ updateCanWrite();
+ updateCanRead();
+
+ abs_thread_mutex_unlock(&mut);
+ return;
+}
+
+
+void SimpleRingBuffer::forwardWritePtr(int nBytes) {
+ abs_thread_mutex_lock(&mut);
+
+ fillgrade=fillgrade+nBytes;
+ if (fillgrade < lockgrade) {
+ printf("3:fillgrade:%d < lockgrade:%d nBytes:%d\n",
+ fillgrade,lockgrade,nBytes);
+ }
+ writeBytes+=nBytes;
+ writePos=writePos+nBytes;
+ if(writePos >= eofPos) {
+ if (writePos == eofPos) {
+ writePos=startPos;
+ } else {
+ cout << "writePos > eofPos ! forward error:"<<(eofPos-writePos)
+ <<" bytes"<<endl;
+ }
+ }
+
+ updateCanWrite();
+ updateCanRead();
+ if (fillgrade >= waitMinData) {
+ abs_thread_cond_signal(&dataCond);
+ }
+ abs_thread_mutex_unlock(&mut);
+}
+
+
+int SimpleRingBuffer::waitForSpace(int bytes){
+ abs_thread_mutex_lock(&mut);
+ int back=0;
+ waitMinSpace=bytes;
+ if (waitMinSpace > size) {
+ waitMinSpace=size;
+ }
+ if (waitMinSpace < 0) {
+ cout << "negative waitForSpace"<<endl;
+ waitMinSpace=0;
+ }
+ int currentSpace=size-fillgrade;
+ if (lCanWaitForSpace) {
+ if (currentSpace < waitMinSpace) {
+ lWaitForSpace=true;
+ // it is not possible to wait for data/space simultanously
+ if (lWaitForData == true) {
+ abs_thread_cond_signal(&dataCond);
+ }
+ abs_thread_cond_wait(&spaceCond,&mut);
+ lWaitForSpace=false;
+ }
+ }
+ if (size-fillgrade >= waitMinSpace) {
+ back=1;
+ }
+ abs_thread_mutex_unlock(&mut);
+ return back;
+}
+
+
+void SimpleRingBuffer::exitWaitForSpace(){
+ abs_thread_mutex_lock(&mut);
+ abs_thread_cond_signal(&spaceCond);
+ abs_thread_mutex_unlock(&mut);
+}
+
+void SimpleRingBuffer::setCanWaitForSpace(int lCanWaitForSpace) {
+ abs_thread_mutex_lock(&mut);
+ this->lCanWaitForSpace=lCanWaitForSpace;
+ abs_thread_cond_signal(&spaceCond);
+ abs_thread_mutex_unlock(&mut);
+
+}
+
+
+
+void SimpleRingBuffer::forwardReadPtr(int nBytes) {
+ abs_thread_mutex_lock(&mut);
+ readBytes+=nBytes;
+ readPos+=nBytes;
+ linAvail=linAvail-nBytes;
+ lockgrade+=nBytes;
+ if (readPos > lastPos) { // we expects that we had a linAvail part
+ // if user forwards more than buffer boundary
+ nBytes=readPos-lastPos;
+ readPos=startPos+nBytes-1;
+ linAvail=lastPos+1-readPos;
+ }
+ if (fillgrade < lockgrade) {
+ printf("5:fillgrade:%d < lockgrade:%d nBytes:%d\n",
+ fillgrade,lockgrade,nBytes);
+ }
+ updateCanRead();
+ abs_thread_mutex_unlock(&mut);
+}
+
+
+
+int SimpleRingBuffer::getReadArea(char* &ptr,int &readSize) {
+ int pSize=readSize;
+ ptr=readPos;
+
+ if (canRead == 0) {
+ readSize=0;
+ return 0;
+ }
+ if (pSize < 0) {
+ cout << "Generic Memory Info invalid"<<endl;
+ pSize=size/2;
+ }
+ //
+ // Now the part the we deliver a minimum buffer if it is
+ // possible
+ //
+
+ if ( (pSize > linAvail) &&
+ (minLinBufSize >linAvail) &&
+ (canRead > linAvail) ) {
+ int copySize;
+ copySize=canRead; // we cannot copy more than this
+ if (copySize > pSize) { // if it is too much reduche it
+ copySize=pSize;
+ }
+ if (copySize > minLinBufSize) { // if it does not fit in buffer->reduce
+ copySize=minLinBufSize;
+ }
+ memcpy(minLinBuf,readPos,linAvail);
+ memcpy(minLinBuf+linAvail,startPos,copySize-linAvail);
+ readSize=copySize;
+ ptr=minLinBuf;
+ return copySize;
+ }
+
+ // linAvail part end
+
+ int copyBytes=linAvail;
+ if (canRead < copyBytes) {
+ copyBytes=canRead;
+ }
+ if (copyBytes >= pSize) {
+ readSize=pSize;
+ } else {
+ readSize=copyBytes;
+ }
+ return readSize;
+}
+
+
+
+void SimpleRingBuffer::exitWaitForData(){
+ abs_thread_mutex_lock(&mut);
+ abs_thread_cond_signal(&dataCond);
+ abs_thread_mutex_unlock(&mut);
+}
+
+
+
+int SimpleRingBuffer::waitForData(int bytes){
+ abs_thread_mutex_lock(&mut);
+ int back=0;
+ waitMinData=bytes;
+ if (waitMinData > size) {
+ waitMinData=size;
+ }
+ if (waitMinData < 0) {
+ cout << "negative waitForData"<<endl;
+ waitMinData=0;
+ }
+ if (lCanWaitForData) {
+ if (fillgrade < waitMinData) {
+ lWaitForData=true;
+ // it is not possible to wait for data space simultanously
+ if (lWaitForSpace == true) {
+ abs_thread_cond_signal(&spaceCond);
+ }
+ abs_thread_cond_wait(&dataCond,&mut);
+ lWaitForData=false;
+ }
+ }
+ if (fillgrade >= waitMinData) {
+ back=1;
+ }
+ abs_thread_mutex_unlock(&mut);
+ return back;
+}
+
+int SimpleRingBuffer::getCanWaitForData() {
+ return lCanWaitForData;
+}
+
+
+void SimpleRingBuffer::setCanWaitForData(int lCanWaitForData) {
+ abs_thread_mutex_lock(&mut);
+ this->lCanWaitForData=lCanWaitForData;
+ abs_thread_cond_signal(&dataCond);
+ abs_thread_mutex_unlock(&mut);
+
+}
+
+void SimpleRingBuffer::emptyBuffer() {
+ abs_thread_mutex_lock(&mut);
+ writePos=readPos;
+ if (fillgrade < lockgrade) {
+ printf("4:fillgrade:%d < lockgrade:%d\n",fillgrade,lockgrade);
+ }
+ linAvail=lastPos+1-writePos;
+ fillgrade=lockgrade;
+ updateCanRead();
+ updateCanWrite();
+ readBytes=0;
+ writeBytes=0;
+ if (size-fillgrade >= waitMinSpace) {
+ abs_thread_cond_signal(&spaceCond);
+ }
+ if (fillgrade >= waitMinData) {
+ abs_thread_cond_signal(&dataCond);
+ }
+ abs_thread_mutex_unlock(&mut);
+}
+
+
+int SimpleRingBuffer::getFillgrade() {
+ return fillgrade;
+}
+
+
+int SimpleRingBuffer::getReadBytes() {
+ return readBytes;
+}
+
+
+int SimpleRingBuffer::getWriteBytes() {
+ return writeBytes;
+}
+
+
+int SimpleRingBuffer::getFreeRead() {
+ return fillgrade;
+}
+
+int SimpleRingBuffer::getFreeWrite() {
+ return size-fillgrade;
+}
+
+void SimpleRingBuffer::resizeBuffer(int changeSize) {
+ abs_thread_mutex_lock(&mut);
+ int lPos=lockPos-startPos;
+ int wPos=writePos-startPos;
+ int rPos=readPos-startPos;
+ startPos=(char *)realloc(startPos,changeSize);
+ size=changeSize;
+ readPos=startPos+lPos;
+ writePos=startPos+wPos;
+ lockPos=startPos+rPos;
+
+ lastPos=(startPos+size-1);
+ eofPos=lastPos+1;
+
+ linAvail=lastPos+1-readPos;
+
+ updateCanWrite();
+ updateCanRead();
+ abs_thread_mutex_unlock(&mut);
+
+
+}
diff --git a/mpeglib/lib/input/simpleRingBuffer.h b/mpeglib/lib/input/simpleRingBuffer.h
new file mode 100644
index 00000000..101725bf
--- /dev/null
+++ b/mpeglib/lib/input/simpleRingBuffer.h
@@ -0,0 +1,136 @@
+/*
+ a thread safe ring buffer without dependencies
+ 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 _SIMPLERINGBUFFER_H
+#define _SIMPLERINGBUFFER_H
+
+#include "../util/abstract/abs_thread.h"
+
+extern "C" {
+ #include <stdio.h>
+}
+
+/**
+ Note to parameter minLinBufSize in Constructor:
+ <p>
+ If the fillgrade is sufficient we can delivier at least
+ this amount of bytes with one "fill"
+ (If the fillgrade is not suffficient we can only deliever fillgrade)
+ This values adresses the problem that a ring buffer cannot
+ deliever linear memory the whole time(eg. if you read near the
+ upper end)
+ <p>
+ If the requested Buffersize by the device is smaller than
+ this number you can be sure that you get exactly
+ your preferred buffersize. not more not less.(but
+ only if the fillgrade allows this)
+*/
+
+
+
+
+class SimpleRingBuffer {
+
+
+ public:
+
+ SimpleRingBuffer(int ringBufferSize, int minLinBufferSize);
+ virtual ~SimpleRingBuffer();
+
+ // Writer thread can call these:
+
+ int getWriteArea(char* &ptr,int &size);
+ void forwardWritePtr(int bytes);
+ int waitForSpace(int minSpace);
+ void exitWaitForSpace();
+ void setCanWaitForSpace(int lCanWaitForSpace);
+
+
+ // Reader thread these:
+
+ void forwardReadPtr(int bytes);
+ int getReadArea(char* &ptr,int &size);
+ int waitForData(int minData);
+ void exitWaitForData();
+ void setCanWaitForData(int lCanWaitForData);
+ int getCanWaitForData();
+
+
+ // and the lockPos
+ void forwardLockPtr(int bytes);
+
+
+ // both:
+
+ int getFillgrade(); // return how much buffer between reader/writer
+ void emptyBuffer(); // frees the space between them
+ int getFreeRead();
+ int getFreeWrite();
+
+ int getSize();
+ int getReadBytes();
+ int getWriteBytes();
+
+ // make sure that no one calls getReadArea/getWriteArea
+ void resizeBuffer(int changeSize);
+ private:
+ void updateCanWrite();
+ void updateCanRead();
+
+ int size;
+
+ int lockgrade;
+ int fillgrade;
+
+ char* readPos;
+ char* writePos;
+ char* lockPos;
+
+ char* startPos;
+
+ char* lastPos;
+ char* eofPos;
+ int canWrite;
+ int canRead;
+
+ int waitMinData;
+ int waitMinSpace;
+
+ abs_thread_mutex_t mut;
+ abs_thread_cond_t dataCond;
+ abs_thread_cond_t spaceCond;
+
+ int insertBlock;
+ int readBlock;
+ int linAvail;
+
+ char* minLinBuf;
+ int minLinBufSize;
+ int lWaitForData;
+ int lWaitForSpace;
+
+ // statistic purpose:
+ int readBytes;
+ int writeBytes;
+
+ int lCanWaitForSpace;
+ int lCanWaitForData;
+ int instance;
+};
+
+#endif
+
+
+
diff --git a/mpeglib/lib/input/threadSafeInputStream.cpp b/mpeglib/lib/input/threadSafeInputStream.cpp
new file mode 100644
index 00000000..8b18a4c5
--- /dev/null
+++ b/mpeglib/lib/input/threadSafeInputStream.cpp
@@ -0,0 +1,137 @@
+/*
+ thread safe wrapper for input 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 "threadSafeInputStream.h"
+
+
+ThreadSafeInputStream::ThreadSafeInputStream(InputStream* input) {
+ threadQueue=new ThreadQueue();
+ this->input=input;
+}
+
+
+ThreadSafeInputStream::~ThreadSafeInputStream() {
+ delete threadQueue;
+ delete input;
+}
+
+
+
+int ThreadSafeInputStream::open(const char* dest) {
+ int back;
+ threadQueue->waitForExclusiveAccess();
+ back=input->open(dest);
+ threadQueue->releaseExclusiveAccess();
+ return back;
+}
+
+
+void ThreadSafeInputStream::close() {
+ threadQueue->waitForExclusiveAccess();
+ input->close();
+ threadQueue->releaseExclusiveAccess();
+}
+
+
+int ThreadSafeInputStream::isOpen() {
+ int back;
+ threadQueue->waitForExclusiveAccess();
+ back=input->isOpen();
+ threadQueue->releaseExclusiveAccess();
+ return back;
+}
+
+
+int ThreadSafeInputStream::eof() {
+ int back;
+ threadQueue->waitForExclusiveAccess();
+ back=input->eof();
+ threadQueue->releaseExclusiveAccess();
+ return back;
+}
+
+
+int ThreadSafeInputStream::read(char* buf,int len) {
+ int back;
+ threadQueue->waitForExclusiveAccess();
+ back=input->read(buf,len);
+ threadQueue->releaseExclusiveAccess();
+ return back;
+}
+
+
+int ThreadSafeInputStream::seek(long bytePos) {
+ int back;
+ threadQueue->waitForExclusiveAccess();
+ back=input->seek(bytePos);
+ threadQueue->releaseExclusiveAccess();
+ return back;
+}
+
+void ThreadSafeInputStream::clear() {
+ threadQueue->waitForExclusiveAccess();
+ input->clear();
+ threadQueue->releaseExclusiveAccess();
+}
+
+
+long ThreadSafeInputStream::getByteLength() {
+ long back;
+ threadQueue->waitForExclusiveAccess();
+ back=input->getByteLength();
+ threadQueue->releaseExclusiveAccess();
+ return back;
+}
+
+
+long ThreadSafeInputStream::getBytePosition() {
+ long back;
+ threadQueue->waitForExclusiveAccess();
+ back=input->getBytePosition();
+ threadQueue->releaseExclusiveAccess();
+ return back;
+}
+
+
+void ThreadSafeInputStream::insertTimeStamp(TimeStamp* src,long key,int len) {
+ threadQueue->waitForExclusiveAccess();
+ input->insertTimeStamp(src,key,len);
+ threadQueue->releaseExclusiveAccess();
+}
+
+
+TimeStamp* ThreadSafeInputStream::getTimeStamp(long key) {
+ TimeStamp* back;
+ threadQueue->waitForExclusiveAccess();
+ back=input->getTimeStamp(key);
+ threadQueue->releaseExclusiveAccess();
+ return back;
+}
+
+
+int ThreadSafeInputStream::bytesUntilNext(long key) {
+ int back;
+ threadQueue->waitForExclusiveAccess();
+ back=input->bytesUntilNext(key);
+ threadQueue->releaseExclusiveAccess();
+ return back;
+}
+
+void ThreadSafeInputStream::print() {
+ threadQueue->waitForExclusiveAccess();
+ input->print();
+ threadQueue->releaseExclusiveAccess();
+}
+
+
+
diff --git a/mpeglib/lib/input/threadSafeInputStream.h b/mpeglib/lib/input/threadSafeInputStream.h
new file mode 100644
index 00000000..0a29637b
--- /dev/null
+++ b/mpeglib/lib/input/threadSafeInputStream.h
@@ -0,0 +1,56 @@
+/*
+ thread safe wrapper for input 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 __THREADSAFEINPUTSTREAM_H
+#define __THREADSAFEINPUTSTREAM_H
+
+// read INTRO in threadQueue.h
+// This class makes the inputStream (given in constructor)
+// threadsafe by wrapping each call with a threadqueue.
+//
+// Important NOTE: the input pointer is the owned by this class !!!
+// which means: we call delete on it!
+
+#include "../util/abstract/threadQueue.h"
+#include "inputStream.h"
+
+
+class ThreadSafeInputStream : public InputStream {
+
+ ThreadQueue* threadQueue;
+ InputStream* input;
+
+ public:
+ ThreadSafeInputStream(InputStream* input);
+ ~ThreadSafeInputStream();
+
+
+ int open(const char* dest);
+ void close();
+ int isOpen();
+
+ int eof();
+ int read(char* ptr,int size);
+ int seek(long bytePos);
+ void clear();
+
+ long getByteLength();
+ long getBytePosition();
+
+ void insertTimeStamp(TimeStamp* src,long key,int len);
+ TimeStamp* getTimeStamp(long key);
+ int bytesUntilNext(long key);
+ void print();
+
+};
+#endif
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 */
+
+
diff --git a/mpeglib/lib/mpgplayer/Makefile.am b/mpeglib/lib/mpgplayer/Makefile.am
new file mode 100644
index 00000000..b10b247a
--- /dev/null
+++ b/mpeglib/lib/mpgplayer/Makefile.am
@@ -0,0 +1,31 @@
+# libsplay - Makefile.am
+
+INCLUDES = $(all_includes)
+
+
+noinst_LTLIBRARIES = libmpgplayer.la
+
+mpegutildir = $(includedir)/$(THIS_LIB_NAME)/mpegutil
+
+mpegutil_HEADERS = mpegStreamPlayer.h
+
+libmpgplayer_la_SOURCES = mpegStreamPlayer.cpp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/mpgplayer/mpegStreamPlayer.cpp b/mpeglib/lib/mpgplayer/mpegStreamPlayer.cpp
new file mode 100644
index 00000000..133e6319
--- /dev/null
+++ b/mpeglib/lib/mpgplayer/mpegStreamPlayer.cpp
@@ -0,0 +1,431 @@
+/*
+ feeds audio/video streams to the decoders
+ 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 "mpegStreamPlayer.h"
+#include "../mpegplay/mpegSystemHeader.h"
+#include "../util/syncClockMPEG.h"
+
+#define _NUKE_BUFFER_SIZE 1024
+
+#define _BUFFER_HIGH_WATER 0.8
+#define _BUFFER_LOW_WATER 0.2
+
+#define _BUFFER_CHUNK_SIZE 1500
+
+#include <iostream>
+
+using namespace std;
+
+
+MpegStreamPlayer::MpegStreamPlayer(InputStream* input,
+ OutputStream* output,
+ DecoderPlugin* audioDecoder,
+ DecoderPlugin* videoDecoder) {
+ this->input=input;
+ this->output=output;
+ this->audioDecoder=audioDecoder;
+ this->videoDecoder=videoDecoder;
+
+ /**
+ here we set the plugins in autoPlay mode.
+ because we handle all commands over the loopback buffer.
+ This is necessary, because on start we send play()
+ but this does not mean that we already have
+ build this class (divxplugin for example)
+ See this switch as an implicit play command
+ */
+
+ audioDecoder->config("-y","on",NULL);
+ videoDecoder->config("-y","on",NULL);
+
+
+ audioInput=new BufferInputStream(1024*_BUFFER_CHUNK_SIZE,
+ 1024*200,"audioInput");
+ videoInput=new BufferInputStream(1024*_BUFFER_CHUNK_SIZE,
+ 1024*200,"videoInput");
+ audioInput->open("audio loopback");
+ videoInput->open("video loopback");
+
+ audioDecoder->setOutputPlugin(output);
+ audioDecoder->setInputPlugin(audioInput);
+
+ videoDecoder->setOutputPlugin(output);
+ videoDecoder->setInputPlugin(videoInput);
+
+ timeStampVideo=new TimeStamp();
+ timeStampAudio=new TimeStamp();
+
+ packetCnt=0;
+ audioPacketCnt=0;
+ videoPacketCnt=0;
+ seekPos=-1;
+ nukeBuffer=new char[_NUKE_BUFFER_SIZE];
+
+ syncClock=new SyncClockMPEG();
+ syncClock->setSyncMode(__SYNC_AUDIO);
+ writeToDisk=false;
+}
+
+
+MpegStreamPlayer::~MpegStreamPlayer() {
+ audioInput->close();
+ videoInput->close();
+
+ // everything is prepared for future shutdown
+ // restart any waiting decoders
+ // (they exit immediately)
+ audioDecoder->close();
+ videoDecoder->close();
+ audioDecoder->waitForStreamState(_STREAM_STATE_EOF);
+ videoDecoder->waitForStreamState(_STREAM_STATE_EOF);
+
+ delete videoInput;
+ delete audioInput;
+ delete nukeBuffer;
+ delete timeStampVideo;
+ delete timeStampAudio;
+ delete syncClock;
+}
+
+int MpegStreamPlayer::getByteDirect() {
+ unsigned char byte;
+ if (input->read((char*)&byte,1) != 1) {
+ return -1;
+ }
+ return (int)byte;
+}
+
+int MpegStreamPlayer::processResyncRequest() {
+ // here is our protocol for resync over the loopback stream
+ // if out clients are in sync and we set the resync method on the
+ // stream he sometimes set a "commit" in the stream
+ // we check if both stream are committed (== clients are in sync and paused)
+ // if both are in _STREAM_STATE_RESYNC_COMMIT
+ // we can safley do a seek
+ // and restart them
+
+ if (seekPos != -1) {
+ int audioDecoderState=audioDecoder->getStreamState();
+ int videoDecoderState=videoDecoder->getStreamState();
+ if (audioDecoderState == _STREAM_STATE_RESYNC_COMMIT) {
+ if (videoDecoderState == _STREAM_STATE_RESYNC_COMMIT) {
+ Command restart(_COMMAND_RESYNC_END);
+ input->seek(seekPos);
+ seekPos=-1;
+ audioDecoder->insertSyncCommand(&restart);
+ videoDecoder->insertSyncCommand(&restart);
+ Command play(_COMMAND_PLAY);
+ audioDecoder->insertAsyncCommand(&play);
+ videoDecoder->insertAsyncCommand(&play);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+/**
+ according to the header info we read the packets
+*/
+int MpegStreamPlayer::processSystemHeader(MpegSystemHeader* mpegSystemHeader) {
+ int layer=mpegSystemHeader->getLayer();
+
+
+ if (processResyncRequest() == true) {
+ return false;
+ }
+
+ if (layer==_PACKET_NO_SYSLAYER) {
+ syncClock->setSyncMode(__SYNC_NONE);
+ return insertVideoData(mpegSystemHeader,8192);
+ }
+ if (layer==_PACKET_SYSLAYER) {
+ int packetID=mpegSystemHeader->getPacketID();
+ int packetLength=mpegSystemHeader->getPacketLen();
+ int subStreamID=mpegSystemHeader->getSubStreamID();
+
+ switch(packetID>>4) {
+ case _PAKET_ID_VIDEO>>4:
+ if((packetID - _PAKET_ID_VIDEO) !=
+ mpegSystemHeader->getVideoLayerSelect()) {
+ break;
+ }
+
+ insertVideoData(mpegSystemHeader,packetLength);
+ //dumpData(mpegSystemHeader);
+ return true;
+ //break;
+ case _PAKET_ID_AUDIO_1>>4:
+ case _PAKET_ID_AUDIO_2>>4:
+ if((packetID - _PAKET_ID_AUDIO_1) !=
+ mpegSystemHeader->getAudioLayerSelect()) {
+ break;
+ }
+ insertAudioData(mpegSystemHeader,packetLength);
+ return true;
+ }
+ switch(packetID) {
+ case _PRIVATE_STREAM_1_ID:
+ switch(subStreamID) {
+ case _SUBSTREAM_AC3_ID:
+ insertAudioData(mpegSystemHeader,packetLength);
+ //dumpData(mpegSystemHeader);
+ return true;
+ default:
+ printf("unknown private stream id:%8x\n",subStreamID);
+ }
+ }
+
+ // if we got here the packet is not useful
+ // nuke it
+ nuke(packetLength);
+ return true;
+
+
+ }
+ cout << "unknown layer"<<endl;
+ return false;
+}
+
+
+void MpegStreamPlayer::nuke(int packetLength) {
+ int nukeSize;
+ while(packetLength > 0) {
+ nukeSize=packetLength;
+ if (nukeSize > _NUKE_BUFFER_SIZE) {
+ nukeSize=_NUKE_BUFFER_SIZE;
+ }
+ input->read(nukeBuffer,nukeSize);
+ packetLength-=nukeSize;
+ }
+}
+
+
+
+int MpegStreamPlayer::isInit() {
+ int audioDecoderState=audioDecoder->getStreamState();
+ int videoDecoderState=videoDecoder->getStreamState();
+ if ( (audioDecoderState != _STREAM_STATE_FIRST_INIT) &&
+ (videoDecoderState != _STREAM_STATE_FIRST_INIT) ) {
+ return true;
+ }
+ return false;
+}
+
+/**
+ here we make sure that our plugins make
+ a clean shutdown for a seek request.
+*/
+void MpegStreamPlayer::processThreadCommand(Command* command) {
+
+ int id=command->getID();
+
+ switch(id) {
+ case _COMMAND_NONE:
+ break;
+ case _COMMAND_PAUSE:
+ case _COMMAND_PLAY:
+ audioDecoder->insertAsyncCommand(command);
+ videoDecoder->insertAsyncCommand(command);
+ break;
+ case _COMMAND_CLOSE:
+ audioDecoder->close();
+ videoDecoder->close();
+ break;
+ case _COMMAND_SEEK: {
+ Command cmd1(_COMMAND_PAUSE);
+ audioDecoder->insertAsyncCommand(&cmd1);
+ videoDecoder->insertAsyncCommand(&cmd1);
+
+ Command cmd2(_COMMAND_RESYNC_START);
+ audioDecoder->insertAsyncCommand(&cmd2);
+ videoDecoder->insertAsyncCommand(&cmd2);
+
+ seekPos=command->getIntArg();
+ break;
+ }
+ default:
+ cout << "unknown command id in Command::print"<<endl;
+ }
+}
+
+
+void MpegStreamPlayer::setWriteToDisk(int lwriteToDisk) {
+ this->writeToDisk=lwriteToDisk;
+}
+
+
+int MpegStreamPlayer::getWriteToDisk() {
+ return writeToDisk;
+}
+
+
+int MpegStreamPlayer::hasEnd() {
+ audioInput->close();
+ videoInput->close();
+ TimeWrapper::usleep(100000);
+ if (audioInput->getFillgrade()>0) {
+ return false;
+ }
+ if (videoInput->getFillgrade()>0) {
+ return false;
+ }
+ return true;
+}
+
+
+
+int MpegStreamPlayer::insertAudioData(MpegSystemHeader* header,int len) {
+
+ audioPacketCnt++;
+ packetCnt++;
+ timeStampAudio->setVideoFrameCounter(0);
+
+ timeStampAudio->setPTSFlag(false);
+ if (header->getPTSFlag()==true) {
+
+ timeStampAudio->setPTSFlag(true);
+
+ double pts=header->getPTSTimeStamp();
+ double scr=header->getSCRTimeStamp();
+
+ if (pts==timeStampAudio->getPTSTimeStamp()) {
+ cout << "(audio) old PTS == NEW PTS"<<pts<<endl;
+ }
+
+ timeStampAudio->setSCRTimeStamp(scr);
+ timeStampAudio->setPTSTimeStamp(pts);
+ }
+
+ timeStampAudio->setSyncClock(syncClock);
+
+
+ finishAudio(len);
+
+ return true;
+}
+
+
+int MpegStreamPlayer::insertVideoData(MpegSystemHeader* header,int len) {
+
+ videoPacketCnt++;
+ packetCnt++;
+ timeStampVideo->setVideoFrameCounter(0);
+ timeStampVideo->setPTSFlag(false);
+ if (header->getPTSFlag()==true) {
+ timeStampVideo->setPTSFlag(true);
+
+ double pts=header->getPTSTimeStamp();
+ double scr=header->getSCRTimeStamp();
+ double dts=header->getDTSTimeStamp();
+
+ if (pts==timeStampVideo->getPTSTimeStamp()) {
+ cout << "(video) old PTS == NEW PTS"<<pts<<endl;
+ }
+
+ timeStampVideo->setSCRTimeStamp(scr);
+ timeStampVideo->setPTSTimeStamp(pts);
+ timeStampVideo->setDTSTimeStamp(dts);
+ }
+
+
+ timeStampVideo->setSyncClock(syncClock);
+
+ finishVideo(len);
+
+ return true;
+}
+
+int MpegStreamPlayer::insertAudioDataRaw(unsigned char* input,
+ int len,TimeStamp* stamp) {
+ audioInput->write((char*)input,len,stamp);
+ if (writeToDisk==true) {
+ FILE* audio=fopen("audio.mpg","a+");
+ fwrite(input,1,len,audio);
+ fclose(audio);
+ }
+ return true;
+}
+
+
+int MpegStreamPlayer::insertVideoDataRaw(unsigned char* input,
+ int len,TimeStamp* stamp) {
+
+ videoInput->write((char*)input,len,stamp);
+ if (writeToDisk==true) {
+ FILE* video=fopen("video.mpg","a+");
+ fwrite(input,1,len,video);
+ fclose(video);
+ }
+
+ return true;
+}
+
+
+void MpegStreamPlayer::dumpData(MpegSystemHeader* mpegSystemHeader) {
+
+ int packetLength=mpegSystemHeader->getPacketLen();
+
+ unsigned char* packetBuffer= new unsigned char[packetLength];
+ input->read((char*)packetBuffer,packetLength);
+ int cnt;
+ for(cnt=0;cnt < packetLength;cnt++) {
+ printf(" %2x ",packetBuffer[cnt]);
+ if ((cnt+1)%16 == 0) {
+ printf("\n");
+ }
+ }
+
+ printf("\n");
+ cout << "**************************************** packt Dump"<<endl;
+}
+
+
+
+int MpegStreamPlayer::finishAudio(int len) {
+ int resyncState=audioDecoder->getStreamState();
+ if (resyncState != _STREAM_STATE_RESYNC_COMMIT) {
+ if (writeToDisk==true) {
+ char* buf=new char[len];
+ len=input->read(buf,len);
+ insertAudioDataRaw((unsigned char*) buf,len,timeStampAudio);
+ delete buf;
+ } else {
+ audioInput->write(input,len,timeStampAudio);
+ }
+
+ } else {
+ //cout << "throw away audio"<<endl;
+ }
+ return true;
+}
+
+
+int MpegStreamPlayer::finishVideo(int len) {
+ int resyncState=videoDecoder->getStreamState();
+ if (resyncState != _STREAM_STATE_RESYNC_COMMIT) {
+ if (writeToDisk==true) {
+ char* buf=new char[len];
+ len=input->read(buf,len);
+ insertVideoDataRaw((unsigned char*)buf,len,timeStampVideo);
+ delete buf;
+ } else {
+ videoInput->write(input,len,timeStampVideo);
+ }
+
+ } else {
+ //cout <<"throw away video"<<endl;
+ }
+ return true;
+}
+
diff --git a/mpeglib/lib/mpgplayer/mpegStreamPlayer.h b/mpeglib/lib/mpgplayer/mpegStreamPlayer.h
new file mode 100644
index 00000000..584e0a22
--- /dev/null
+++ b/mpeglib/lib/mpgplayer/mpegStreamPlayer.h
@@ -0,0 +1,90 @@
+/*
+ feeds audio/video streams to the decoders
+ 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 __MPEGSTREAMPLAYER_H
+#define __MPEGSTREAMPLAYER_H
+
+#include "../decoder/decoderPlugin.h"
+#include "../util/syncClock.h"
+
+class MpegSystemHeader;
+
+class MpegStreamPlayer {
+
+ protected:
+ SyncClock* syncClock;
+ DecoderPlugin* audioDecoder;
+ DecoderPlugin* videoDecoder;
+ BufferInputStream* audioInput;
+ BufferInputStream* videoInput;
+ OutputStream* output;
+ InputStream* input;
+ TimeStamp* timeStampVideo;
+ TimeStamp* timeStampAudio;
+
+ int packetCnt;
+ int audioPacketCnt;
+ int videoPacketCnt;
+ int seekPos;
+ int writeToDisk;
+
+ char* nukeBuffer;
+
+ public:
+ MpegStreamPlayer(InputStream* input,
+ OutputStream* output,
+ DecoderPlugin* audioDecoder,
+ DecoderPlugin* videoDecoder);
+ ~MpegStreamPlayer();
+
+ int isInit();
+ void processThreadCommand(Command* command);
+
+ //
+ // Mpeg special functions [START]
+ //
+
+ int processSystemHeader(MpegSystemHeader* mpegSystemHeader);
+ int insertAudioData(MpegSystemHeader* header,int len);
+ int insertVideoData(MpegSystemHeader* header,int len);
+
+ //
+ // Mpeg special functions [END]
+ //
+
+
+
+ int insertAudioDataRaw(unsigned char* input,int len,TimeStamp* stamp);
+ int insertVideoDataRaw(unsigned char* input,int len,TimeStamp* stamp);
+
+ void dumpData(MpegSystemHeader* mpegSystemHeader);
+
+ void setWriteToDisk(int lwriteToDisk);
+ int getWriteToDisk();
+
+ int hasEnd();
+ protected:
+ int processResyncRequest();
+
+ int getByteDirect();
+ void nuke(int byte);
+
+ // useful methods
+ int finishAudio(int len);
+ int finishVideo(int len);
+
+};
+
+#endif
diff --git a/mpeglib/lib/oggvorbis/Makefile.am b/mpeglib/lib/oggvorbis/Makefile.am
new file mode 100644
index 00000000..2fe00b72
--- /dev/null
+++ b/mpeglib/lib/oggvorbis/Makefile.am
@@ -0,0 +1,32 @@
+# liboggvorbis - Makefile.am
+
+
+INCLUDES = $(all_includes)
+
+
+noinst_LTLIBRARIES = liboggvorbisbase.la
+
+kmpgincludedir = $(includedir)/$(THIS_LIB_NAME)/oggvorbis
+
+kmpginclude_HEADERS = ovFramer.h vorbisDecoder.h oggFrame.h \
+ vorbisInfo.h
+
+
+liboggvorbisbase_la_SOURCES = ovFramer.cpp vorbisDecoder.cpp \
+ oggFrame.cpp vorbisInfo.cpp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/oggvorbis/oggFrame.cpp b/mpeglib/lib/oggvorbis/oggFrame.cpp
new file mode 100644
index 00000000..ace7dadc
--- /dev/null
+++ b/mpeglib/lib/oggvorbis/oggFrame.cpp
@@ -0,0 +1,29 @@
+/*
+ here we have an ogg frame. Its still a raw frame.
+ 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 "oggFrame.h"
+
+#ifdef OGG_VORBIS
+
+
+OGGFrame::OGGFrame() : RawFrame(_FRAME_RAW_OGG,0) {
+ setRemoteData((unsigned char*) &op,sizeof(op));
+
+}
+
+OGGFrame::~OGGFrame() {
+}
+
+
+
+#endif
diff --git a/mpeglib/lib/oggvorbis/oggFrame.h b/mpeglib/lib/oggvorbis/oggFrame.h
new file mode 100644
index 00000000..a069a33e
--- /dev/null
+++ b/mpeglib/lib/oggvorbis/oggFrame.h
@@ -0,0 +1,50 @@
+/*
+ here we have an ogg frame. Its still a raw frame.
+ 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 __OGG_FRAME_H
+#define __OGG_FRAME_H
+
+
+/**
+ One Ogg Paket as frame. We pass the datapointer and the size
+ to the rawFrame and of course, set the PaktedID to:
+ _FRAME_RAW_OGG
+*/
+
+#include "../frame/rawFrame.h"
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef OGG_VORBIS
+
+#include <vorbis/codec.h>
+
+class OGGFrame : public RawFrame {
+
+ ogg_packet op;
+
+ public:
+ OGGFrame();
+ ~OGGFrame();
+
+
+};
+
+#endif
+
+#endif
+
diff --git a/mpeglib/lib/oggvorbis/ovFramer.cpp b/mpeglib/lib/oggvorbis/ovFramer.cpp
new file mode 100644
index 00000000..ca3506af
--- /dev/null
+++ b/mpeglib/lib/oggvorbis/ovFramer.cpp
@@ -0,0 +1,128 @@
+/*
+ frames raw data into Ogg/Vorbis frames.
+ 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 "ovFramer.h"
+
+#define OGG_SYNC_BUFF_SIZE 4096
+
+
+#define _OV_SETSERIAL 1
+#define _OV_STREAMIN 2
+#define _OV_STREAMOUT 3
+
+#include <iostream>
+
+using namespace std;
+
+
+#ifdef OGG_VORBIS
+
+OVFramer::OVFramer(OGGFrame* dest):Framer(1) {
+ if (dest == NULL) {
+ cout << "OGGFrame NULL in OVFramer"<<endl;
+ exit(-1);
+ }
+ this->dest=dest;
+ /********** Decode setup ************/
+ ogg_sync_init(&oy); /* Now we can read pages */
+
+ vorbis_state=_OV_SETSERIAL;
+}
+
+
+OVFramer::~OVFramer() {
+ /* OK, clean up the framer */
+ ogg_sync_clear(&oy);
+}
+
+
+int OVFramer::find_frame(RawDataBuffer* input,RawDataBuffer* store) {
+ while(input->eof()==true) {
+ cout << "input eof"<<endl;
+ return false;
+ }
+
+ if (vorbis_state == _OV_STREAMOUT) {
+ if(ogg_stream_packetout(&os,(ogg_packet*)dest->getData())!=1){
+ vorbis_state=_OV_STREAMIN;
+ return false;
+ }
+ return true;
+ }
+
+ // do we have ogg packets in the ogg framer?
+ if (ogg_sync_pageout(&oy,&og) == 0) {
+ // no, ok insert some.
+ int bytes=input->untilend();
+ input->inc(bytes);
+ store->inc(bytes);
+ ogg_sync_wrote(&oy,bytes);
+ // and setup the next buffer
+ /* submit a 4k block to libvorbis' Ogg layer */
+ buffer=ogg_sync_buffer(&oy,OGG_SYNC_BUFF_SIZE);
+ /* override our own dummy buffer with size 1 */
+ setRemoteFrameBuffer((unsigned char*)buffer,OGG_SYNC_BUFF_SIZE);
+ return false;
+ }
+ // we have an ogg page
+ // now try to build an ogg packet
+ switch(vorbis_state) {
+ case _OV_SETSERIAL:
+ /* Get the serial number and set up the rest of decode. */
+ /* serialno first; use it to set up a logical stream */
+ ogg_stream_init(&os,ogg_page_serialno(&og));
+ vorbis_state=_OV_STREAMIN;
+ // yes we need to put this into the "pager"
+ // no break.
+ case _OV_STREAMIN:
+ if(ogg_stream_pagein(&os,&og)<0){
+ /* error; stream version mismatch perhaps */
+ fprintf(stderr,"Error reading first page of Ogg bitstream data.\n");
+ exit(1);
+ }
+ vorbis_state=_OV_STREAMOUT;
+ break;
+ default:
+ cout << "unknow vorbis_state"<<endl;
+ exit(-1);
+ }
+
+ return false;
+}
+
+int OVFramer::read_frame(RawDataBuffer* ,RawDataBuffer* ) {
+ return true;
+}
+
+
+
+void OVFramer::unsync(RawDataBuffer* store,int lReset) {
+ if (lReset) {
+ store->setpos(0);
+ ogg_sync_reset(&oy);
+ /* submit a 4k block to libvorbis' Ogg layer */
+ buffer=ogg_sync_buffer(&oy,OGG_SYNC_BUFF_SIZE);
+ /* override our own dummy buffer with size 1 */
+ setRemoteFrameBuffer((unsigned char*)buffer,OGG_SYNC_BUFF_SIZE);
+ }
+
+}
+
+
+void OVFramer::printPrivateStates() {
+ cout << "OVFramer::printPrivateStates"<<endl;
+}
+
+
+#endif
diff --git a/mpeglib/lib/oggvorbis/ovFramer.h b/mpeglib/lib/oggvorbis/ovFramer.h
new file mode 100644
index 00000000..4845fddb
--- /dev/null
+++ b/mpeglib/lib/oggvorbis/ovFramer.h
@@ -0,0 +1,69 @@
+/*
+ frames raw data into Ogg/Vorbis frames.
+ 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 __OVFRAMER_H
+#define __OVFRAMER_H
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef OGG_VORBIS
+
+#include <vorbis/codec.h>
+#include "../frame/framer.h"
+#include "oggFrame.h"
+
+/**
+
+ This framer works directly on the raw ogg_packet as output
+ Note: the internal setup makes sure, that we initialize
+ the ogg stream to the first found logical bitstream.
+ (For now this should mean: we found vorbis)
+ When the frame goes into the "HAS" state, you have the ogg
+ packet in the in the dest struct from the constructor.
+*/
+
+class OVFramer : public Framer {
+
+ int vorbis_state;
+
+ ogg_sync_state oy; /* sync and verify incoming physical bitstream */
+ ogg_stream_state os; /* take physical pages, weld into a logical
+ stream of packets */
+ ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */
+
+ char *buffer; /* sync buffer from ogg */
+
+ OGGFrame* dest; /* one raw packet of data for decode */
+
+ public:
+ // IMPORTANT: because we use this ptr internally the
+ // data to op cannot be on the stack!
+ OVFramer(OGGFrame* dest);
+ ~OVFramer();
+
+
+ private:
+
+ int find_frame(RawDataBuffer* input,RawDataBuffer* store);
+ int read_frame(RawDataBuffer* input,RawDataBuffer* store);
+
+ void unsync(RawDataBuffer* store,int lReset);
+ void printPrivateStates();
+
+};
+#endif
+
+#endif
diff --git a/mpeglib/lib/oggvorbis/vorbisDecoder.cpp b/mpeglib/lib/oggvorbis/vorbisDecoder.cpp
new file mode 100644
index 00000000..24e9370d
--- /dev/null
+++ b/mpeglib/lib/oggvorbis/vorbisDecoder.cpp
@@ -0,0 +1,135 @@
+/*
+ converts ogg frames into audioFrames
+ 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 "vorbisDecoder.h"
+
+#ifdef OGG_VORBIS
+
+#define _VORBIS_NEED_SYNTHHEADER_1 1
+#define _VORBIS_NEED_SYNTHHEADER_2 2
+#define _VORBIS_NEED_SYNTHHEADER_3 3
+
+#define _VORBIS_DECODE_SETUP 4
+#define _VORBIS_DECODE_LOOP 5
+
+#include <iostream>
+
+using namespace std;
+
+
+VorbisDecoder::VorbisDecoder() {
+ vorbis_info_init(&vi);
+ vorbis_comment_init(&vc);
+ reset();
+}
+
+
+VorbisDecoder::~VorbisDecoder() {
+}
+
+int VorbisDecoder::hasHeader() {
+ return (initState>=_VORBIS_DECODE_LOOP);
+}
+
+int VorbisDecoder::decode(RawFrame* rawFrame,AudioFrame* dest) {
+
+ if ((rawFrame == NULL) || (dest == NULL)) {
+ cout << "VorbisDecoder::decode NULL pointer!"<<endl;
+ exit(-1);
+ }
+ if (rawFrame->getFrameType() != _FRAME_RAW_OGG) {
+ cout << "VorbisDecoder::decode not _FRAME_RAW_OGG"<<endl;
+ exit(-1);
+ }
+
+ ogg_packet* op=(ogg_packet*) rawFrame->getData();
+ switch(initState) {
+ case _VORBIS_NEED_SYNTHHEADER_1:
+ case _VORBIS_NEED_SYNTHHEADER_2:
+ case _VORBIS_NEED_SYNTHHEADER_3:
+ cout << "_VORBIS_NEED_SYNTHHEADER:"<<initState<<endl;
+ if(vorbis_synthesis_headerin(&vi,&vc,op)<0){
+ /* error case; not a vorbis header */
+ fprintf(stderr,"This Ogg bitstream does not contain Vorbis "
+ "audio data.\n");
+ exit(1);
+ }
+ initState++;
+ break;
+ case _VORBIS_DECODE_SETUP:
+ cout << "_VORBIS_DECODE_SETUP"<<endl;
+ vorbis_synthesis_init(&vd,&vi); /* central decode state */
+ vorbis_block_init(&vd,&vb); /* local state for most of the decode
+ so multiple block decodes can
+ proceed in parallel. We could init
+ multiple vorbis_block structures
+ for vd here */
+ initState=_VORBIS_DECODE_LOOP;
+ // yes right, we must decode the packet!
+ // so there is no break here.
+ case _VORBIS_DECODE_LOOP: {
+ if(vorbis_synthesis(&vb,op)==0) {/* test for success! */
+ vorbis_synthesis_blockin(&vd,&vb);
+ } else {
+ cout << "vorbis_synthesis error"<<endl;
+ exit(0);
+ }
+ float **pcm;
+ /*
+
+ **pcm is a multichannel float vector. In stereo, for
+ example, pcm[0] is left, and pcm[1] is right. samples is
+ the size of each channel. Convert the float values
+ (-1.<=range<=1.) to whatever PCM format and write it out
+
+ */
+ int samples=vorbis_synthesis_pcmout(&vd,&pcm);
+ if (samples > 0) {
+ int maxSamples=dest->getSize();
+ if (samples > maxSamples) {
+ cout << "more samples in vorbis than we can store"<<endl;
+ exit(0);
+ }
+ dest->clearrawdata();
+ dest->setFrameFormat(vi.channels-1,vi.rate);
+
+ if (vi.channels == 2) {
+ dest->putFloatData(pcm[0],pcm[1],samples);
+ } else {
+ dest->putFloatData(pcm[0],NULL,samples);
+ }
+
+ vorbis_synthesis_read(&vd,samples); /* tell libvorbis how
+ many samples we
+ actually consumed */
+ return true;
+ }
+
+ return false;
+ }
+ default:
+ cout << "unknown state in vorbis decoder"<<endl;
+ exit(0);
+ }
+ return false;
+}
+
+void VorbisDecoder::reset() {
+ initState=_VORBIS_NEED_SYNTHHEADER_1;
+}
+
+void VorbisDecoder::config(const char* ,const char* ,void* ) {
+
+}
+
+#endif
diff --git a/mpeglib/lib/oggvorbis/vorbisDecoder.h b/mpeglib/lib/oggvorbis/vorbisDecoder.h
new file mode 100644
index 00000000..e67a94bb
--- /dev/null
+++ b/mpeglib/lib/oggvorbis/vorbisDecoder.h
@@ -0,0 +1,53 @@
+/*
+ converts ogg frames into audioFrames
+ 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 __VORBISDECODER_H
+#define __VORBISDECODER_H
+
+#include "../frame/audioFrame.h"
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef OGG_VORBIS
+
+#include <vorbis/codec.h>
+#include "oggFrame.h"
+
+class VorbisDecoder {
+
+ vorbis_info vi; /* struct that stores all the static vorbis bitstream
+ settings */
+ vorbis_comment vc; /* struct that stores all the bitstream user comments */
+ vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
+ vorbis_block vb; /* local working space for packet->PCM decode */
+
+ int initState;
+
+ public:
+ VorbisDecoder();
+ ~VorbisDecoder();
+
+ void reset();
+ int hasHeader();
+
+ int decode(RawFrame* rawFrame,AudioFrame* dest);
+ void config(const char* key,const char* val,void* ret);
+};
+
+#endif
+
+#endif
diff --git a/mpeglib/lib/oggvorbis/vorbisInfo.cpp b/mpeglib/lib/oggvorbis/vorbisInfo.cpp
new file mode 100644
index 00000000..b71f99c3
--- /dev/null
+++ b/mpeglib/lib/oggvorbis/vorbisInfo.cpp
@@ -0,0 +1,150 @@
+/*
+ info about vorbis files.
+ 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 "vorbisInfo.h"
+
+#include <iostream>
+
+using namespace std;
+
+#ifdef OGG_VORBIS
+#define CHUNKSIZE 4096
+
+#define GETINPUT(stream,input) \
+ VorbisInfo* info=(VorbisInfo*) stream; \
+ FileAccess* input=info->getInput();
+
+
+size_t fread_func2(void *ptr, size_t size, size_t nmemb, void *stream) {
+ GETINPUT(stream,input);
+
+ size_t want=size*nmemb;
+ size_t back=input->read((char*)ptr,want);
+ return back;
+}
+
+
+int fseek_func2(void *stream, ogg_int64_t offset, int whence) {
+ int ret;
+ GETINPUT(stream,input);
+
+ if (whence==SEEK_SET) {
+ ret=input->seek(offset);
+ info->setSeekPos(offset);
+ return ret;
+ }
+ if (whence==SEEK_CUR) {
+ ret=input->seek(input->getBytePosition()+offset);
+ return ret;
+ }
+ if (whence==SEEK_END) {
+ ret=input->seek(input->getByteLength());
+ return ret;
+ }
+ cout << "hm, strange call"<<endl;
+ return -1;
+}
+
+
+int fclose_func2 (void * stream) {
+ cout << "fclose_func"<<endl;
+ GETINPUT(stream,input);
+ // its handled different in kmpg
+ // we close the stream if the decoder signals eof.
+ return true;
+
+}
+
+
+long ftell_func2 (void *stream) {
+ GETINPUT(stream,input);
+ return input->getBytePosition();
+}
+
+
+
+
+VorbisInfo::VorbisInfo(FileAccess* input) {
+ this->input=input;
+ vf=new OggVorbis_File();
+
+ ov_callbacks callbacks;
+
+ callbacks.read_func = fread_func2;
+ callbacks.seek_func = fseek_func2;
+ callbacks.close_func = fclose_func2;
+ callbacks.tell_func = ftell_func2;
+
+ if(ov_open_callbacks(this, vf, NULL, 0, callbacks) < 0) {
+ cout << "error ov_open_callbacks"<<endl;
+ }
+
+ // now init stream
+ vi=ov_info(vf,-1);
+ lastSeekPos=0;
+}
+
+
+VorbisInfo::~VorbisInfo() {
+ delete vf;
+ if (vi != NULL) {
+ //?
+ }
+}
+
+
+long VorbisInfo::getSeekPosition(int seconds) {
+ int back=0;
+ if (vi != NULL) {
+ lastSeekPos=0;
+ ov_time_seek(vf,seconds);
+ back=lastSeekPos;
+ }
+ return back;
+}
+
+
+long VorbisInfo::getLength() {
+ int back=0;
+ if (vi != NULL) {
+ back = (int) ov_time_total(vf, -1);
+ }
+ return back;
+}
+
+
+
+
+void VorbisInfo::print(const char* msg) {
+ cout << "VorbisInfo:"<<msg<<endl;
+ cout << "Length (sec):"<<getLength()<<endl;
+
+}
+
+
+void VorbisInfo::setSeekPos(long pos) {
+ this->lastSeekPos=pos;
+}
+
+
+long VorbisInfo::getSeekPos() {
+ return lastSeekPos;
+}
+
+FileAccess* VorbisInfo::getInput() {
+ return input;
+}
+
+
+
+#endif
diff --git a/mpeglib/lib/oggvorbis/vorbisInfo.h b/mpeglib/lib/oggvorbis/vorbisInfo.h
new file mode 100644
index 00000000..70c1dc8a
--- /dev/null
+++ b/mpeglib/lib/oggvorbis/vorbisInfo.h
@@ -0,0 +1,76 @@
+/*
+ info about vorbis files.
+ 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 __VORBISINFO_H
+#define __VORBISINFO_H
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef OGG_VORBIS
+
+#include <vorbis/codec.h>
+#include <vorbis/vorbisfile.h>
+#include "../util/file/fileAccess.h"
+
+/**
+ callbacks from vorbisfile
+*/
+extern "C" {
+
+extern size_t fread_func2 (void *ptr,size_t size,size_t nmemb, void *stream);
+extern int fseek_func2 (void *stream, ogg_int64_t offset, int whence);
+extern int fclose_func2 (void *stream);
+extern long ftell_func2 (void *stream);
+
+}
+
+
+
+class VorbisInfo {
+
+ FileAccess* input;
+ OggVorbis_File* vf;
+ vorbis_info *vi;
+
+ long lastSeekPos;
+
+ public:
+ VorbisInfo(FileAccess* input);
+ ~VorbisInfo();
+
+ // returns byte positions
+ long getSeekPosition(int second);
+ // returns length in seconds
+ long getLength();
+
+ void print(const char* msg);
+
+ void setSeekPos(long pos);
+ long getSeekPos();
+
+ FileAccess* getInput();
+
+
+};
+
+#endif
+
+#endif
diff --git a/mpeglib/lib/output/Makefile.am b/mpeglib/lib/output/Makefile.am
new file mode 100644
index 00000000..e430550e
--- /dev/null
+++ b/mpeglib/lib/output/Makefile.am
@@ -0,0 +1,52 @@
+# liboutplugin - Makefile.am
+
+INCLUDES = $(all_includes)
+
+
+noinst_LTLIBRARIES = liboutput.la
+
+noinst_HEADERS = windowOut.h \
+ audioData.h audioDataArray.h \
+ performance.h yuvDumper.h
+
+kmpgincludedir = $(includedir)/$(THIS_LIB_NAME)/output
+
+kmpginclude_HEADERS = outputStream.h pluginInfo.h \
+ outPlugin.h dspX11OutputStream.h \
+ artsOutputStream.h audioTime.h \
+ avSyncer.h threadSafeOutputStream.h
+
+
+liboutput_la_SOURCES = outPlugin.cpp outputStream.cpp \
+ dspX11OutputStream.cpp \
+ windowOut.cpp \
+ audioTime.cpp \
+ audioData.cpp audioDataArray.cpp \
+ avSyncer.cpp performance.cpp \
+ artsOutputStream.cpp \
+ pluginInfo.cpp yuvDumper.cpp \
+ threadSafeOutputStream.cpp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/output/artsOutputStream.cpp b/mpeglib/lib/output/artsOutputStream.cpp
new file mode 100644
index 00000000..571dd258
--- /dev/null
+++ b/mpeglib/lib/output/artsOutputStream.cpp
@@ -0,0 +1,205 @@
+/*
+ output to arts
+ 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 "artsOutputStream.h"
+#include "windowOut.h"
+#include "avSyncer.h"
+#include "../util/abstract/threadQueue.h"
+
+
+ArtsOutputStream::ArtsOutputStream(void (*streamStateChangeCallback)(void*)) {
+
+ audioTime=new AudioTime();
+ x11Window=new WindowOut();
+ privateBufferSize=1024*32;
+
+ // we can dynamically change the buffer size,
+ // over a config switch in avSyncer
+ // but for now this should be ok
+ // Arts must pass the total size of the audiobuffer
+ // from /dev/dsp + connected nodes
+ // or arts need a video interface
+ stream=new BufferInputStream(privateBufferSize,1024*64,"artsLoopback");
+ avSyncer=new AVSyncer(privateBufferSize);
+
+ // with the ThreadQueue we protect all calls to the
+ // x11 output. This is necessary, because arts may call
+ // in the future "config" entries to switch the video
+ // mode (full,double,desktop)
+ threadQueue=new ThreadQueue();
+ // we set it, but its never used !
+ this->streamStateChangeCallback=streamStateChangeCallback;
+}
+
+
+ArtsOutputStream::~ArtsOutputStream() {
+ delete stream;
+ delete audioTime;
+ delete x11Window;
+ delete avSyncer;
+ delete threadQueue;
+}
+
+
+
+
+int ArtsOutputStream::audioSetup(int freq,int stereo,
+ int sign,int big,int sampleSize) {
+ audioTime->setFormat(stereo,sampleSize,freq,sign,big);
+ avSyncer->audioSetup(freq,stereo,sign,big,sampleSize);
+
+ OutputStream::audioSetup(freq,stereo,sign,big,sampleSize);
+
+ return true;
+}
+
+AudioTime* ArtsOutputStream::getAudioTime() {
+ return audioTime;
+}
+
+
+void ArtsOutputStream::audioClose() {
+ audioTime->setTime(0.0);
+ // if we close this stream the thread is kicked out.
+ stream->close();
+ stream->clear();
+ avSyncer->audioClose();
+}
+
+void ArtsOutputStream::audioFlush() {
+ OutputStream::audioFlush();
+ audioClose();
+}
+
+
+void ArtsOutputStream::audioOpen() {
+ audioTime->setTime(0.0);
+ // if we close this stream the thread is kicked out.
+ stream->open("artsLoopback");
+}
+
+
+int ArtsOutputStream::audioPlay(TimeStamp* startStamp,
+ TimeStamp* endStamp,char *buffer, int size) {
+ int write=size;
+
+
+ // we call this for stream state handling
+ OutputStream::audioPlay(startStamp,endStamp,buffer,size);
+
+ // store sync information
+ avSyncer->audioPlay(startStamp,endStamp,buffer,size);
+
+
+ // here we simulate our own blocking audio device
+ if (stream->isOpen()==false) {
+ audioTime->sleepWrite(size);
+ } else {
+ write=stream->write(buffer,size,startStamp);
+ }
+ return write;
+
+}
+
+
+int ArtsOutputStream::read(char** buffer,int bytes) {
+ int back=stream->readRemote(buffer,bytes);
+ return back;
+}
+
+
+void ArtsOutputStream::forwardReadPtr(int bytes) {
+ audioTime->forwardTime(bytes);
+ stream->forwardReadPtr(bytes);
+
+}
+
+
+
+
+int ArtsOutputStream::getPreferredDeliverSize() {
+ return avSyncer->getPreferredDeliverSize();
+}
+
+
+int ArtsOutputStream::openWindow(int width, int height,const char *title) {
+ threadQueue->waitForExclusiveAccess();
+ int back=x11Window->openWindow(width,height,title);
+ threadQueue->releaseExclusiveAccess();
+
+ return back;
+}
+
+int ArtsOutputStream::x11WindowId() {
+ return x11Window->x11WindowId();
+}
+
+void ArtsOutputStream::closeWindow() {
+ threadQueue->waitForExclusiveAccess();
+ x11Window->closeWindow();
+ threadQueue->releaseExclusiveAccess();
+}
+
+void ArtsOutputStream::flushWindow() {
+ threadQueue->waitForExclusiveAccess();
+ x11Window->flushWindow();
+ threadQueue->releaseExclusiveAccess();
+}
+
+
+PictureArray* ArtsOutputStream::lockPictureArray() {
+ PictureArray* back;
+ threadQueue->waitForExclusiveAccess();
+ back=x11Window->lockPictureArray();
+ threadQueue->releaseExclusiveAccess();
+ return back;
+}
+
+
+void ArtsOutputStream::unlockPictureArray(PictureArray* pictureArray) {
+
+
+ YUVPicture* pic=pictureArray->getYUVPictureCallback();
+ if (avSyncer->syncPicture(pic)==false) {
+ return;
+ }
+ threadQueue->waitForExclusiveAccess();
+ x11Window->unlockPictureArray(pictureArray);
+ threadQueue->releaseExclusiveAccess();
+
+}
+
+int ArtsOutputStream::getBufferFillgrade() {
+ return stream->getFillgrade();
+}
+
+int ArtsOutputStream::getFrameusec() {
+ return avSyncer->getFrameusec();
+}
+
+
+
+void ArtsOutputStream::setAudioBufferSize(int size) {
+ avSyncer->setAudioBufferSize(privateBufferSize+size);
+}
+
+
+void ArtsOutputStream::config(const char* key,const char* value,
+ void* user_data) {
+
+ threadQueue->waitForExclusiveAccess();
+ avSyncer->config(key,value,user_data);
+ x11Window->config(key,value,user_data);
+ threadQueue->releaseExclusiveAccess();
+}
diff --git a/mpeglib/lib/output/artsOutputStream.h b/mpeglib/lib/output/artsOutputStream.h
new file mode 100644
index 00000000..757022fd
--- /dev/null
+++ b/mpeglib/lib/output/artsOutputStream.h
@@ -0,0 +1,123 @@
+/*
+ output to arts
+ 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 __ARTSOUTPUTSTREAM_H
+#define __ARTSOUTPUTSTREAM_H
+
+#include "outputStream.h"
+#include "../input/bufferInputStream.h"
+#include "audioTime.h"
+
+
+class WindowOut;
+class AVSyncer;
+
+
+
+
+/**
+ a word about synchronisation: Arts currently has not asynchronous
+ starting of stream, which means, poll if stream is initialized
+ or set a callbackfunction.
+
+ mpeglib is threaded and would not have much problems
+ with a "callback" but currently we only support blocking wait
+ for initilisation.
+
+ I think, if people realize that smooth mixing of streams
+ is impossible(because of the blocking start behaviour),
+ this will become a desired feature :-)
+
+*/
+
+
+/**
+ This class offers a blocking device, its behaviour is similar
+ to /dev/dsp we use a buffer to store the pcm data, if
+ we open/close the buffer the stored data is removed
+ and the blocking thread is "kicked"
+
+ Arts must first wait for an init signal. it has its own
+ method to check for eof. during seek we close this
+ device, after seek we reopen it.
+
+ close and open have the same functionality, they simply
+ clear the buffer.
+*/
+
+
+
+class ArtsOutputStream : public OutputStream {
+
+ BufferInputStream* stream;
+ AudioTime* audioTime;
+
+ void (*streamStateChangeCallback)(void*);
+
+ WindowOut* x11Window;
+ AVSyncer* avSyncer;
+ int privateBufferSize;
+ class ThreadQueue* threadQueue;
+
+ public:
+ ArtsOutputStream(void (*streamStateChangeCallback)(void*));
+ ~ArtsOutputStream();
+
+ // Audio part
+
+ int audioSetup(int freq,int stereo,int sign,int big,int sampleSize);
+ void audioClose();
+ void audioOpen();
+ void audioFlush();
+
+ int audioPlay(TimeStamp* startStamp,
+ TimeStamp* endStamp,char *buffer, int size);
+
+
+ AudioTime* getAudioTime();
+
+ int getPreferredDeliverSize();
+
+ // Video part
+
+ int openWindow(int width, int height,const char *title);
+ int x11WindowId();
+ void closeWindow();
+ void flushWindow();
+
+ PictureArray* lockPictureArray();
+ void unlockPictureArray(PictureArray* pictureArray);
+
+ int getFrameusec();
+
+ void config(const char* key,const char* value,void* user_data);
+
+ // Remote read extension
+
+ int read(char** buffer,int bytes);
+ void forwardReadPtr(int bytes);
+
+ // buffer control
+ int getBufferFillgrade();
+
+ // sync control
+ void setAudioBufferSize(int size);
+
+ private:
+ void sendSignal(int state,int value);
+ void initStream();
+
+};
+#endif
diff --git a/mpeglib/lib/output/audioData.cpp b/mpeglib/lib/output/audioData.cpp
new file mode 100644
index 00000000..d28e74cf
--- /dev/null
+++ b/mpeglib/lib/output/audioData.cpp
@@ -0,0 +1,100 @@
+/*
+ describes a paket oriented audioData, because Im fed up
+ 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 "audioData.h"
+
+#include <iostream>
+
+using namespace std;
+
+AudioData::AudioData() {
+ pcmLen=0;
+ audioTime=new AudioTime();
+ start=new TimeStamp();
+ end=new TimeStamp();
+ writeStamp=new TimeStamp();
+}
+
+
+AudioData::~AudioData() {
+ delete audioTime;
+ delete start;
+ delete end;
+ delete writeStamp;
+}
+
+
+void AudioData::copyTo(AudioData* dest) {
+ dest->setAudioTime(getAudioTime());
+ dest->setStart(getStart());
+ dest->setEnd(getEnd());
+ dest->setWrite(getWrite());
+ dest->setPCMLen(getPCMLen());
+}
+
+
+int AudioData::getPCMLen(){
+ return pcmLen;
+}
+
+void AudioData::setPCMLen(int pcmLen) {
+ this->pcmLen=pcmLen;
+}
+
+void AudioData::setAudioTime(AudioTime* aTime) {
+ aTime->copyTo(audioTime);
+}
+
+AudioTime* AudioData::getAudioTime() {
+ return audioTime;
+}
+
+
+void AudioData::setStart(TimeStamp* s) {
+ s->copyTo(start);
+}
+
+
+TimeStamp* AudioData::getStart() {
+ return start;
+}
+
+void AudioData::setEnd(TimeStamp* e) {
+ e->copyTo(end);
+}
+
+
+TimeStamp* AudioData::getEnd() {
+ return end;
+}
+
+void AudioData::setWrite(TimeStamp* e) {
+ e->copyTo(writeStamp);
+}
+
+
+TimeStamp* AudioData::getWrite() {
+ return writeStamp;
+}
+
+
+
+void AudioData::print() {
+ cout << "AudioData::print [START]"<<endl;
+ start->print("audioData start");
+ end->print("audioData end");
+ cout << "pcmlen:"<<pcmLen<<endl;
+ cout << "AudioData::print [END]"<<endl;
+}
diff --git a/mpeglib/lib/output/audioData.h b/mpeglib/lib/output/audioData.h
new file mode 100644
index 00000000..ff6c8242
--- /dev/null
+++ b/mpeglib/lib/output/audioData.h
@@ -0,0 +1,71 @@
+/*
+ describes a paket oriented audioData, because Im fed up
+ 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 __AUDIODATA_H
+#define __AUDIODATA_H
+
+#include "../util/timeStamp.h"
+#include "audioTime.h"
+
+
+#define _AUDIODATA_MAX_SIZE 8192
+
+
+/**
+ My attempt to encapsulate all this stupid things which deals
+ with timing, synchronisation, length, stamps and everything
+ unimaginable else.
+*/
+
+
+
+class AudioData {
+
+
+ AudioTime* audioTime;
+ TimeStamp* start;
+ TimeStamp* end;
+ TimeStamp* writeStamp;
+
+ int pcmLen;
+
+ public:
+ AudioData();
+ ~AudioData();
+
+ void copyTo(AudioData* dest);
+
+
+ int getPCMLen();
+ void setPCMLen(int pcmLen);
+
+ void setAudioTime(AudioTime* audioTime);
+ AudioTime* getAudioTime();
+
+ void setStart(TimeStamp* start);
+ TimeStamp* getStart();
+
+ void setWrite(TimeStamp* writeStamp);
+ TimeStamp* getWrite();
+
+
+ void setEnd(TimeStamp* end);
+ TimeStamp* getEnd();
+
+ void print();
+};
+#endif
+
+
+
diff --git a/mpeglib/lib/output/audioDataArray.cpp b/mpeglib/lib/output/audioDataArray.cpp
new file mode 100644
index 00000000..a0b91ec1
--- /dev/null
+++ b/mpeglib/lib/output/audioDataArray.cpp
@@ -0,0 +1,138 @@
+/*
+ fifo for audioData
+ 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 "audioDataArray.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+AudioDataArray::AudioDataArray(int entries) {
+
+ this->entries=entries;
+ fillgrade=0;
+ readPos=0;
+ writePos=0;
+ pcmSum=0;
+ abs_thread_mutex_init(&writeInMut);
+ abs_thread_mutex_init(&changeMut);
+
+ audioDataArray=new AudioData*[entries];
+
+ int i;
+ for(i=0;i<entries;i++) {
+ audioDataArray[i]=new AudioData();
+ }
+
+ abs_thread_mutex_init(&writeInMut);
+ abs_thread_mutex_init(&changeMut);
+
+}
+
+AudioDataArray::~AudioDataArray() {
+
+ int i;
+ for(i=0;i<entries;i++) {
+ delete audioDataArray[i];
+ }
+
+ delete audioDataArray;
+
+ abs_thread_mutex_destroy(&writeInMut);
+ abs_thread_mutex_destroy(&changeMut);
+
+}
+
+
+
+
+void AudioDataArray::lockStampArray() {
+
+ abs_thread_mutex_lock(&changeMut);
+ abs_thread_mutex_lock(&writeInMut);
+ abs_thread_mutex_unlock(&changeMut);
+
+}
+
+
+void AudioDataArray::unlockStampArray() {
+ abs_thread_mutex_unlock(&writeInMut);
+}
+
+
+void AudioDataArray::internalForward() {
+ pcmSum=pcmSum-readAudioData()->getPCMLen();
+ readPos++;
+ fillgrade--;
+ if (readPos == entries-1) {
+ readPos=0;
+ }
+}
+
+int AudioDataArray::getPCMSum() {
+ return pcmSum;
+}
+
+
+
+int AudioDataArray::insertAudioData(AudioData* src) {
+ lockStampArray();
+
+ int back=true;
+ src->copyTo(audioDataArray[writePos]);
+ pcmSum+=src->getPCMLen();
+
+ writePos++;
+ fillgrade++;
+ if (writePos == entries-1) {
+ writePos=0;
+ }
+ if (fillgrade == entries) {
+ cout <<" Audiodata::array overfull forward"<<endl;
+ internalForward();
+ back=false;
+ }
+ unlockStampArray();
+ return back;
+}
+
+
+AudioData* AudioDataArray::readAudioData() {
+ return audioDataArray[readPos];
+}
+
+
+int AudioDataArray::getFillgrade() {
+ return fillgrade;
+}
+
+
+void AudioDataArray::forward() {
+ lockStampArray();
+ internalForward();
+ unlockStampArray();
+}
+
+
+void AudioDataArray::clear() {
+ lockStampArray();
+ fillgrade=0;
+ readPos=0;
+ writePos=0;
+ pcmSum=0;
+ unlockStampArray();
+}
+
+
diff --git a/mpeglib/lib/output/audioDataArray.h b/mpeglib/lib/output/audioDataArray.h
new file mode 100644
index 00000000..81cebfee
--- /dev/null
+++ b/mpeglib/lib/output/audioDataArray.h
@@ -0,0 +1,55 @@
+/*
+ fifo for audioData
+ 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 __AUDIODATAARRAY_H
+#define __AUDIODATAARRAY_H
+
+#include "../util/abstract/abs_thread.h"
+#include "audioData.h"
+
+
+class AudioDataArray {
+
+ AudioData** audioDataArray;
+ int fillgrade;
+ int entries;
+
+ int writePos;
+ int readPos;
+ int pcmSum;
+
+ public:
+ AudioDataArray(int entries);
+ ~AudioDataArray();
+
+ int insertAudioData(AudioData* src);
+ AudioData* readAudioData();
+
+ int getFillgrade();
+ int getPCMSum();
+ void forward();
+ void clear();
+
+ private:
+ void lockStampArray();
+ void unlockStampArray();
+ void internalForward();
+
+ abs_thread_mutex_t writeInMut;
+ abs_thread_mutex_t changeMut;
+
+
+
+};
+#endif
diff --git a/mpeglib/lib/output/audioTime.cpp b/mpeglib/lib/output/audioTime.cpp
new file mode 100644
index 00000000..f4ed2e9c
--- /dev/null
+++ b/mpeglib/lib/output/audioTime.cpp
@@ -0,0 +1,154 @@
+/*
+ defines the format of an audio stream
+ 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 "audioTime.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+AudioTime::AudioTime(){
+ time=0.0;
+}
+
+
+AudioTime::~AudioTime() {
+}
+
+
+void AudioTime::setFormat(int stereo,int samplesize,int speed,int sign, int bigendian) {
+ setStereo(stereo);
+ setSampleSize(samplesize);
+ setSpeed(speed);
+ setSign(sign);
+ setBigendian(bigendian);
+}
+
+
+int AudioTime::getStereo() {
+ return stereo;
+}
+
+
+int AudioTime::getSampleSize() {
+ return samplesize;
+}
+
+
+int AudioTime::getSpeed() {
+ return speed;
+}
+
+int AudioTime::getSign() {
+ return _sign;
+}
+
+int AudioTime::getBigendian() {
+ return _bigendian;
+}
+
+void AudioTime::setStereo(int stereo) {
+ this->stereo=stereo;
+}
+
+
+void AudioTime::setSampleSize(int samplesize) {
+ this->samplesize=samplesize;
+}
+
+
+void AudioTime::setSpeed(int speed) {
+ this->speed=speed;
+}
+
+void AudioTime::setSign(int sign) {
+ this->_sign=sign;
+}
+
+void AudioTime::setBigendian(int bigendian) {
+ this->_bigendian = bigendian;
+}
+
+float AudioTime::getTime() {
+ return time;
+}
+
+
+void AudioTime::setTime(float time) {
+ this->time=time;
+}
+
+
+void AudioTime::forwardTime(int bytes){
+ time+=calculateTime(bytes);
+}
+
+
+float AudioTime::calculateTime(int bytes) {
+ float back=0;
+
+ bytes=bytes/(samplesize/8);
+ if (stereo==1) {
+ bytes=bytes/2;
+ }
+ if (speed != 0) {
+ back=(float)bytes/(float)speed;
+ }
+ return back;
+}
+
+
+/**
+ How much byte we need for time usecs?
+*/
+int AudioTime::calculateBytes(float time) {
+ float back=time;
+
+ if (speed != 0) {
+ back=back*(float)speed;
+ }
+ back=back*(float)(samplesize/8);
+ if (stereo==1) {
+ back=back*2.0;
+ }
+ return (int)back;
+}
+
+
+
+void AudioTime::sleepWrite(int size) {
+ timeval_t time;
+ float timeLength=calculateTime(size);
+ time.tv_sec=(long)timeLength;
+ time.tv_usec=(long)(1000000*(timeLength-time.tv_sec));
+ TimeWrapper::usleep(&time);
+}
+
+
+void AudioTime::print() {
+ cout << "AudioTime-begin-"<<endl;
+ cout << "stereo:"<<getStereo()<<" sampleSize:"<<getSampleSize()
+ << " speed: "<<getSpeed()<<endl;
+
+ cout << "AudioTime-end-"<<endl;
+
+}
+
+
+void AudioTime::copyTo(AudioTime* dest) {
+ dest->setStereo(getStereo());
+ dest->setSampleSize(getSampleSize());
+ dest->setSpeed(getSpeed());
+}
+
diff --git a/mpeglib/lib/output/audioTime.h b/mpeglib/lib/output/audioTime.h
new file mode 100644
index 00000000..3b16bb02
--- /dev/null
+++ b/mpeglib/lib/output/audioTime.h
@@ -0,0 +1,68 @@
+/*
+ defines the format of an audio stream
+ 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 __AUDIOTIME_H
+#define __AUDIOTIME_H
+
+#include "../util/timeWrapper.h"
+
+class AudioTime {
+
+ int stereo;
+ int samplesize;
+ int speed;
+ int _sign;
+ int _bigendian;
+ float time;
+
+ public:
+ AudioTime();
+ ~AudioTime();
+
+ //cd-quality:true,16,44100
+ void setFormat(int stereo,int samplesize,int speed,int sign=true, int bigendian=false);
+
+ int getStereo();
+ int getSampleSize();
+ int getSpeed();
+ int getSign();
+ int getBigendian();
+
+ void setStereo(int stereo);
+ void setSampleSize(int samplesize);
+ void setSpeed(int speed);
+ void setSign(int sign);
+ void setBigendian(int bigendian);
+
+
+ float getTime();
+ void setTime(float time);
+ void forwardTime(int bytes);
+
+ // do not modify the internal time
+ float calculateTime(int bytes);
+ int calculateBytes(float time);
+
+ void sleepWrite(int size);
+
+
+ void copyTo(AudioTime* audioTime);
+ void print();
+
+};
+
+
+
+#endif
diff --git a/mpeglib/lib/output/avSyncer.cpp b/mpeglib/lib/output/avSyncer.cpp
new file mode 100644
index 00000000..ca12a21e
--- /dev/null
+++ b/mpeglib/lib/output/avSyncer.cpp
@@ -0,0 +1,386 @@
+/*
+ encapsulates the syncing methods, to use it in other classes
+ 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 "avSyncer.h"
+
+#include "audioDataArray.h"
+#include "performance.h"
+
+#include <iostream>
+
+using namespace std;
+
+AVSyncer::AVSyncer(int bufferSize) {
+ oneFrameTime=0;
+ onePicFrameInAudioBytes=8192;
+ this->bufferSize=bufferSize;
+
+ abs_thread_mutex_init(&writeInMut);
+ abs_thread_mutex_init(&changeMut);
+
+
+ audioDataInsert=new AudioData();
+ audioDataArray=new AudioDataArray(400);
+ audioDataCurrent=audioDataArray->readAudioData();
+
+ startAudio=new TimeStamp();
+ endAudio=new TimeStamp();
+ audioTime=new AudioTime();
+ lAudioRunning=false;
+ performance=new Performance();
+
+ waitTime=new TimeStamp();
+ diffTime=new TimeStamp();
+ videoTimeStamp=new TimeStamp();
+
+ lPerformance=false;
+ lavSync=true;
+
+
+}
+
+
+AVSyncer::~AVSyncer() {
+ delete audioDataArray;
+ delete audioDataInsert;
+ delete audioTime;
+ delete startAudio;
+ delete endAudio;
+ abs_thread_mutex_destroy(&writeInMut);
+ abs_thread_mutex_destroy(&changeMut);
+ delete waitTime;
+ delete diffTime;
+ delete performance;
+ delete videoTimeStamp;
+}
+
+
+
+int AVSyncer::audioSetup(int frequency,int stereo,int sign,
+ int big,int sixteen) {
+ audioTime->setFormat(stereo,sixteen,frequency,sign,big);
+ setAudioRunning(true);
+ return true;
+}
+
+
+int AVSyncer::audioPlay(TimeStamp* startStamp,
+ TimeStamp* endStamp,char* , int size) {
+
+
+
+
+ audioDataInsert->setStart(startStamp);
+ audioDataInsert->setEnd(endStamp);
+ audioDataInsert->setAudioTime(audioTime);
+ audioDataInsert->setPCMLen(size);
+
+ setAudioSync(audioDataInsert);
+ return size;
+}
+
+
+
+void AVSyncer::audioClose(void) {
+ lockSyncData();
+ setAudioRunning(false);
+ audioDataArray->clear();
+ unlockSyncData();
+}
+
+
+
+
+
+int AVSyncer::getPreferredDeliverSize() {
+ return onePicFrameInAudioBytes;
+}
+
+
+
+int AVSyncer::getFrameusec() {
+ lockSyncData();
+ int back=oneFrameTime;
+ unlockSyncData();
+ return back;
+}
+
+void AVSyncer::setAudioBufferSize(int size) {
+ bufferSize=size;
+}
+
+
+void AVSyncer::config(const char* key,const char* value,void*) {
+ if (strcmp(key,"-s")==0) {
+ if (strcmp(value,"on")==0) {
+ lavSync=true;
+ cout << "******** lavSync on"<<endl;
+ } else {
+ lavSync=false;
+ cout << "******** lavSync off"<<endl;
+ }
+ }
+ if (strcmp(key,"-p")==0) {
+ cout << "setting perfomance test true"<<endl;
+ lPerformance=true;
+ }
+
+}
+
+
+
+void AVSyncer::setAudioSync(AudioData* audioData) {
+
+ lockSyncData();
+
+ if (onePicFrameInAudioBytes <= 0) {
+ // no video present, we cannot calculate audio
+ // pcm length
+ //cout << "no video present, we cannot calculate audio pcm length"<<endl;
+ unlockSyncData();
+ return;
+ }
+ // buffersize is the simulated size of /dev/dsp
+
+
+
+ // we implement a fifo hopefully
+ // we check the right audio pts time out
+ // when /dev/dsp acutally plays it.
+ audioDataArray->insertAudioData(audioData);
+ int pcmSum=audioDataArray->getPCMSum();
+ if (pcmSum >= bufferSize) {
+ audioDataCurrent=audioDataArray->readAudioData();
+ setAudioRunning(true);
+ audioDataArray->forward();
+ }
+ TimeStamp* startAudio=audioDataCurrent->getStart();
+ int lpts=startAudio->getPTSFlag();
+
+ if (lpts==true) {
+ SyncClock* syncClock=startAudio->getSyncClock();
+ if (syncClock != NULL) {
+ double pts=startAudio->getPTSTimeStamp();
+ double scr=startAudio->getSCRTimeStamp();
+
+ syncClock->syncAudio(pts,scr);
+
+ } else {
+ cout <<"syncClock == NULL (audio)"<<endl;
+ }
+ } else {
+ //cout << "lpts is false"<<endl;
+ }
+ unlockSyncData();
+
+}
+
+
+
+int AVSyncer::syncPicture(YUVPicture* syncPic) {
+ if (syncPic == NULL) {
+ cout << "syncPic == NULL"<<endl;
+ return false;
+ }
+
+ float picPerSec=syncPic->getPicturePerSecond();
+ int oneFrameTime=0;
+
+ if (picPerSec > 0.0) {
+ oneFrameTime=(int) (1000000.0/picPerSec);
+ } else {
+ syncPic->print("picPersec is 0");
+ return true;
+ }
+
+ if (lPerformance==true) {
+ waitTime->set(0,0);
+ syncPic->setWaitTime(waitTime);
+ performance->incPictureCount();
+ return true;
+ }
+
+ int lpacketSync=true;
+
+ videoTimeStamp->gettimeofday();
+ diffTime->minus(videoTimeStamp,videoTimeStamp);
+
+
+ if (lavSync==false) {
+ if (videoTimeStamp->isNegative()) {
+ diffTime->gettimeofday();
+ diffTime->addOffset(0,oneFrameTime);
+ cout << "skip time based"<<endl;
+ return false;
+ }
+ }
+
+
+
+ videoTimeStamp->copyTo(waitTime);
+
+ TimeStamp* earlyTime=syncPic->getEarlyTime();
+ earlyTime->set(0,0);
+
+
+ if (lavSync) {
+
+ lpacketSync=avSync(syncPic->getStartTimeStamp(),
+ waitTime,
+ earlyTime,
+ syncPic->getPicturePerSecond());
+
+ }
+
+
+
+
+ if (lpacketSync == false) {
+ //cout << "skip"<<endl;
+ diffTime->gettimeofday();
+ diffTime->addOffset(0,oneFrameTime);
+ return false;
+ }
+
+ syncPic->setWaitTime(waitTime);
+
+ if (lavSync) {
+ waitTime->minus(videoTimeStamp,waitTime);
+ if (waitTime->isPositive()) {
+ diffTime->addOffset(waitTime);
+ }
+ }
+ diffTime->addOffset(0,oneFrameTime);
+ return true;
+
+
+}
+
+
+
+/**
+ Heart of the sync routine is here!
+
+ Currently its more in a state of "try/test"
+
+
+*/
+int AVSyncer::avSync(TimeStamp* startVideo,
+ TimeStamp* waitTime,
+ TimeStamp* earlyTime,
+ float picPerSec ) {
+
+
+ double videoStartPTSTime=startVideo->getPTSTimeStamp();
+ double videoStartSCRTime=startVideo->getSCRTimeStamp();
+ int videoFrameCounter=startVideo->getVideoFrameCounter();
+ double frameTime=0.0;
+
+
+
+ lockSyncData();
+ if (picPerSec > 0) {
+ oneFrameTime=(long)(1000000.0/picPerSec);
+ frameTime=1.0/picPerSec;
+ onePicFrameInAudioBytes=audioTime->calculateBytes(1.0/picPerSec);
+
+ }
+ if (lAudioRunning==false) {
+ waitTime->set(0,oneFrameTime);
+
+ unlockSyncData();
+ return true;
+ }
+
+
+ /*
+ startAudio->print("audio");
+ startVideo->print("video");
+ */
+
+
+
+
+
+
+ /*
+ cout << "audioStartAudioPacketNrMinor:"<<audioStartAudioPacketNrMinor<<endl;
+ cout << "audioStartPTSTime:"<<audioStartPTSTime<<endl;
+ cout << "audioStartEndPTSTime:"<<audioStartEndPTSTime<<endl;
+ cout << "videoStartPTSTime:"<<videoStartPTSTime<<endl;
+ */
+
+
+ /**
+ Here we make sure that we sync over an audio packet only one
+ time.
+ */
+
+ waitTime->set(0,0);
+ SyncClock* syncClock=startVideo->getSyncClock();
+ int back=false;
+ double addPts=videoFrameCounter*frameTime;
+ double pts=videoStartPTSTime+addPts;
+
+ if (syncClock != NULL) {
+
+ back=syncClock->syncVideo(pts,
+ videoStartSCRTime,earlyTime,waitTime);
+ } else {
+ cout << "syncClock == NULL (video)"<<endl;
+ }
+ unlockSyncData();
+
+ if (back==true) {
+ //earlyTime->print("earlyTime");
+ earlyTime->waitForIt();
+ /*
+ double tmp;
+ double time=syncClock->getPTSTime(&tmp);
+ cout << "time after wait:"<<time<<endl;
+ */
+ }
+ /*
+ if (back == false) {
+ cout <<"real pts:"<<videoStartPTSTime
+ <<" calc pts"<<pts
+ <<" frameNo:"<<videoFrameCounter
+ <<" frameTime:"<<frameTime<<endl;
+ }
+ */
+
+
+
+ return back;
+
+}
+
+int AVSyncer::getAudioRunning() {
+ return lAudioRunning;
+}
+
+
+void AVSyncer::setAudioRunning(int lAudioRunning) {
+ this->lAudioRunning=lAudioRunning;
+}
+
+
+void AVSyncer::lockSyncData() {
+ abs_thread_mutex_lock(&changeMut);
+ abs_thread_mutex_lock(&writeInMut);
+ abs_thread_mutex_unlock(&changeMut);
+}
+
+void AVSyncer::unlockSyncData() {
+ abs_thread_mutex_unlock(&writeInMut);
+}
diff --git a/mpeglib/lib/output/avSyncer.h b/mpeglib/lib/output/avSyncer.h
new file mode 100644
index 00000000..b5a7ae7d
--- /dev/null
+++ b/mpeglib/lib/output/avSyncer.h
@@ -0,0 +1,96 @@
+/*
+ encapsulates the syncing methods, to use it in other classes
+ 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 __AVSYNCER_H
+#define __AVSYNCER_H
+
+#include <stdlib.h>
+
+#include "../util/render/yuvPicture.h"
+#include "../util/syncClock.h"
+#include "audioTime.h"
+
+class Performance;
+class AudioDataArray;
+class AudioData;
+
+class AVSyncer {
+
+ AudioData* audioDataInsert;
+ AudioData* audioDataCurrent;
+ AudioDataArray* audioDataArray;
+ Performance* performance;
+
+ AudioTime* audioTime;
+ int onePicFrameInAudioBytes;
+ int oneFrameTime;
+
+ int lAudioRunning;
+
+ abs_thread_mutex_t writeInMut;
+ abs_thread_mutex_t changeMut;
+
+
+ int bufferSize;
+
+ TimeStamp* startAudio;
+ TimeStamp* endAudio;
+
+ TimeStamp* videoTimeStamp;
+ TimeStamp* diffTime;
+ TimeStamp* waitTime;
+
+ int lPerformance;
+ int lavSync;
+ int lastAudioPacket;
+ double pts_jitter;
+
+
+ public:
+ AVSyncer(int bufferSize);
+ ~AVSyncer();
+
+ // audio
+ int audioSetup(int frequency,int stereo,int sign,int big,int sixteen);
+ int audioPlay(TimeStamp* startStamp,
+ TimeStamp* endStamp,char *buffer, int size);
+ void audioClose(void);
+ void setAudioBufferSize(int size);
+
+ int getPreferredDeliverSize();
+
+ // video
+ int getFrameusec();
+ int syncPicture(YUVPicture* syncPic);
+
+ void config(const char* key,const char* value,void* user_data);
+
+
+
+ private:
+ int getAudioRunning();
+ void setAudioRunning(int lAudioRunning);
+
+ void lockSyncData();
+ void unlockSyncData();
+ void setAudioSync(AudioData* audioData);
+
+ // methods which belong not to the OutputStream interface
+ int avSync(TimeStamp* startVideoStamp,
+ TimeStamp* waitTime,
+ TimeStamp* earlyTime,
+ float picPerSec);
+
+};
+#endif
diff --git a/mpeglib/lib/output/dspX11OutputStream.cpp b/mpeglib/lib/output/dspX11OutputStream.cpp
new file mode 100644
index 00000000..05503ffa
--- /dev/null
+++ b/mpeglib/lib/output/dspX11OutputStream.cpp
@@ -0,0 +1,236 @@
+/*
+ concret OutputClass
+ 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 "dspX11OutputStream.h"
+#include "../util/audio/dspWrapper.h"
+#include "windowOut.h"
+#include "avSyncer.h"
+#include "yuvDumper.h"
+
+#include <iostream>
+
+using namespace std;
+
+DspX11OutputStream::DspX11OutputStream(int bufferSize) {
+ dspWrapper=new DSPWrapper();
+ x11Window=new WindowOut();
+ avSyncer=new AVSyncer(bufferSize);
+ yuvDumper=new YUVDumper();
+
+ audioTime=new AudioTime();
+
+ lPerformance=false;
+ lneedInit=false;
+ lVideoInit=false;
+ lBufferSet=false;
+ lYUVDump=false;
+}
+
+
+DspX11OutputStream::~DspX11OutputStream() {
+ delete dspWrapper;
+ delete x11Window;
+
+ delete avSyncer;
+ delete audioTime;
+ delete yuvDumper;
+}
+
+
+
+int DspX11OutputStream::audioSetup(int frequency,int stereo,
+ int sign,int big,int sixteen) {
+
+ dspWrapper->audioSetup(stereo,sixteen,sign,big,frequency);
+ audioTime->setFormat(stereo,sixteen,frequency,sign,big);
+ avSyncer->audioSetup(frequency,stereo,sign,big,sixteen);
+ if (dspWrapper->isOpenDevice() == true) {
+ if (lBufferSet==false) {
+ int size=dspWrapper->getAudioBufferSize();
+ avSyncer->setAudioBufferSize(size);
+ }
+ }
+ return true;
+}
+
+
+void DspX11OutputStream::audioClose(void) {
+ avSyncer->audioClose();
+ dspWrapper->closeDevice();
+}
+
+
+void DspX11OutputStream::audioOpen() {
+ if (dspWrapper->isOpenDevice() == false) {
+ dspWrapper->openDevice();
+ if (lBufferSet==false) {
+ int size=dspWrapper->getAudioBufferSize();
+ avSyncer->setAudioBufferSize(size);
+ }
+ }
+}
+
+
+
+
+int DspX11OutputStream::audioPlay(TimeStamp* startStamp,
+ TimeStamp* endStamp,char *buffer, int size) {
+
+ if (lneedInit) {
+ cout << "FIXME. work on audioFrames!!"<<endl;
+ lneedInit=false;
+ }
+
+ if (lPerformance==false) {
+ //
+ // Now feed data smoothly into the dsp/avSyncer
+ //
+ int pos=0;
+ int rest=size;
+ int inc=getPreferredDeliverSize();
+ int len;
+
+ while (rest > 0) {
+ len=rest;
+ if (len>inc) {
+ len=inc;
+ }
+ if (dspWrapper->isOpenDevice()) {
+ if (dspWrapper->audioPlay(buffer,len) != len) {
+ cout << "write error to dsp"<<endl;
+ lneedInit=true;
+ return size-rest;
+ }
+ }
+
+ avSyncer->audioPlay(startStamp,endStamp,buffer,len);
+ buffer+=len;
+ rest-=len;
+ }
+ return size;
+ } else {
+ return size;
+ }
+}
+
+
+int DspX11OutputStream::getPreferredDeliverSize() {
+ if (avSyncer->getPreferredDeliverSize() <= 500) {
+ return 500;
+ }
+ return avSyncer->getPreferredDeliverSize();
+}
+
+
+int DspX11OutputStream::openWindow(int width, int height,const char *title) {
+ int back=x11Window->openWindow(width,height,title);
+ setOutputInit(true);
+ if (lYUVDump) {
+ yuvDumper->openWindow(width,height,title);
+ }
+ return back;
+}
+
+int DspX11OutputStream::x11WindowId() {
+ return x11Window->x11WindowId();
+}
+
+
+void DspX11OutputStream::closeWindow() {
+ x11Window->closeWindow();
+}
+
+void DspX11OutputStream::flushWindow() {
+ x11Window->flushWindow();
+}
+
+
+PictureArray* DspX11OutputStream::lockPictureArray() {
+ return x11Window->lockPictureArray();
+}
+
+
+void DspX11OutputStream::unlockPictureArray(PictureArray* pictureArray) {
+
+
+
+ YUVPicture* pic=pictureArray->getYUVPictureCallback();
+
+ if (lYUVDump) {
+ yuvDumper->unlockPictureArray(pictureArray);
+ }
+ if (avSyncer->syncPicture(pic)==false) {
+ return;
+ }
+
+ x11Window->unlockPictureArray(pictureArray);
+
+
+}
+
+int DspX11OutputStream::getFrameusec() {
+ return avSyncer->getFrameusec();
+}
+
+
+
+int DspX11OutputStream::getOutputInit() {
+ return lVideoInit;
+}
+
+
+void DspX11OutputStream::setOutputInit(int lInit) {
+ this->lVideoInit=lInit;
+}
+
+
+
+void DspX11OutputStream::config(const char* key,
+ const char* value,void* user_data) {
+
+ cout << "key:"<<key<<endl;
+ if (strcmp(key,"-s")==0) {
+ avSyncer->config(key,value,user_data);
+ }
+ if (strcmp(key,"-b")==0) {
+ lBufferSet=true;
+ int size=strtol(value,(char **)NULL,10);
+ cout << "simulated audio buffersize:"<<size<<" bytes"<<endl;
+ avSyncer->setAudioBufferSize(size);
+ }
+ if (strcmp(key,"-p")==0) {
+ lPerformance=true;
+ avSyncer->config(key,value,user_data);
+ }
+ if (strcmp(key,"yufDump")==0) {
+ int method=atoi(value);
+ switch(method) {
+ case 2:
+ yuvDumper->setMethod(_DUMP_YUV_AS_STREAM);
+ break;
+ default:
+ cout << "unknown dump method"<<endl;
+ }
+ lYUVDump=true;
+ }
+ x11Window->config(key,value,user_data);
+}
+
+
+AVSyncer* DspX11OutputStream::getAVSyncer() {
+ return avSyncer;
+}
+
+
+
diff --git a/mpeglib/lib/output/dspX11OutputStream.h b/mpeglib/lib/output/dspX11OutputStream.h
new file mode 100644
index 00000000..9b3eb859
--- /dev/null
+++ b/mpeglib/lib/output/dspX11OutputStream.h
@@ -0,0 +1,89 @@
+/*
+ concret OutputClass
+ 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 __DSPX11OUTPUTSTREAM_H
+#define __DSPX11OUTPUTSTREAM_H
+
+#include "outputStream.h"
+
+
+
+class DSPWrapper;
+class WindowOut;
+class AVSyncer;
+class AudioTime;
+class Performance;
+class YUVDumper;
+
+class DspX11OutputStream : public OutputStream {
+
+ DSPWrapper* dspWrapper;
+ WindowOut* x11Window;
+ AVSyncer* avSyncer;
+
+
+ int lBufferSet;
+ int lVideoInit;
+ int lavSync;
+ int lneedInit;
+ int lPerformance;
+ int lYUVDump;
+
+ AudioTime* audioTime;
+ YUVDumper* yuvDumper;
+
+ public:
+ DspX11OutputStream(int bufferSize);
+ ~DspX11OutputStream();
+
+ // Audio Output
+
+ int audioSetup(int frequency,int stereo,int sign,int big,int sixteen);
+ void audioClose();
+ void audioOpen();
+ int audioPlay(TimeStamp* startStamp,
+ TimeStamp* endStamp,char *buffer, int size);
+
+
+ int getPreferredDeliverSize();
+
+
+ // Video Output
+
+ int openWindow(int width, int height,const char *title);
+ int x11WindowId();
+ void closeWindow();
+ void flushWindow();
+
+ PictureArray* lockPictureArray();
+ void unlockPictureArray(PictureArray* pictureArray);
+
+ int getFrameusec();
+
+ int getDepth();
+ int getOutputInit();
+ void setOutputInit(int lInit);
+
+ void config(const char* key,const char* value,void* user_data);
+
+ // methods which do not belong to the outputStream intferface;
+ AVSyncer* getAVSyncer();
+
+
+};
+
+
+
+#endif
diff --git a/mpeglib/lib/output/outPlugin.cpp b/mpeglib/lib/output/outPlugin.cpp
new file mode 100644
index 00000000..cbae10ec
--- /dev/null
+++ b/mpeglib/lib/output/outPlugin.cpp
@@ -0,0 +1,71 @@
+/*
+ generic output 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 "outPlugin.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+OutPlugin::OutPlugin() {
+}
+
+
+OutPlugin::~OutPlugin() {
+}
+
+
+
+OutputStream* OutPlugin::createOutputStream(int outputType) {
+
+ // make checks which input routine to use
+ OutputStream* outputStream;
+ int method;
+
+ outputStream=NULL;
+ method=outputType;
+
+ switch(method) {
+ case _OUTPUT_LOCAL: {
+ outputStream=new DspX11OutputStream(1024*64);
+ break;
+ }
+ case _OUTPUT_ARTS: {
+ outputStream=new ArtsOutputStream(NULL);
+ break;
+ }
+ case _OUTPUT_EMPTY: {
+ outputStream=new OutputStream();
+ break;
+ }
+ default:
+ cout << "error cannot create default output stream"<<endl;
+ exit(0);
+ }
+
+ return outputStream;
+
+
+}
+
+OutputStream* OutPlugin::createOutputStream(int outputType,int lThreadSafe) {
+ OutputStream* output=OutPlugin::createOutputStream(outputType);
+ if (lThreadSafe==false) {
+ return output;
+ }
+ OutputStream* tsOutput=new ThreadSafeOutputStream(output);
+ return tsOutput;
+}
+
diff --git a/mpeglib/lib/output/outPlugin.h b/mpeglib/lib/output/outPlugin.h
new file mode 100644
index 00000000..b70620a6
--- /dev/null
+++ b/mpeglib/lib/output/outPlugin.h
@@ -0,0 +1,44 @@
+/*
+ generic output 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 __OUTPLUGIN_H
+#define __OUTPLUGIN_H
+
+
+#include "dspX11OutputStream.h"
+#include "artsOutputStream.h"
+#include "threadSafeOutputStream.h"
+#include <kdemacros.h>
+
+#define _OUTPUT_LOCAL 1
+#define _OUTPUT_EMPTY 2
+#define _OUTPUT_YAF 3
+#define _OUTPUT_ARTS 4
+
+#define _OUTPUT_THREADSAFE 1
+
+class KDE_EXPORT OutPlugin {
+
+ public:
+ OutPlugin();
+ ~OutPlugin();
+
+ static OutputStream* createOutputStream(int outputType);
+ static OutputStream* createOutputStream(int outputType,int lThreadSafe);
+
+};
+#endif
+
+
+
+
diff --git a/mpeglib/lib/output/outputStream.cpp b/mpeglib/lib/output/outputStream.cpp
new file mode 100644
index 00000000..ef209cbc
--- /dev/null
+++ b/mpeglib/lib/output/outputStream.cpp
@@ -0,0 +1,238 @@
+/*
+ generic output class
+ 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 "outputStream.h"
+#include "../util/mmx/mmx.h"
+
+#include <iostream>
+
+using namespace std;
+
+OutputStream::OutputStream() {
+ // we call mm_support() here because it is the only position
+ // where we gurantee that not threads are
+ // running (the call is not thread safe)
+ // afer the call we never execute the asm part again
+ // and everything is fine
+ mm_support();
+ abs_thread_mutex_init(&stateChangeMut);
+ abs_thread_cond_init(&stateChangeCond);
+
+ audioState=0;
+ videoState=0;
+ audioInit();
+ videoInit();
+}
+
+
+OutputStream::~OutputStream() {
+ audioInit();
+ videoInit();
+ abs_thread_cond_destroy(&stateChangeCond);
+ abs_thread_mutex_destroy(&stateChangeMut);
+}
+
+
+int OutputStream::audioInit() {
+ sendSignal(_STREAM_MASK_IS_INIT,false,_STREAMTYPE_AUDIO);
+ sendSignal(_STREAM_MASK_IS_EOF,false,_STREAMTYPE_AUDIO);
+ sendSignal(_STREAM_MASK_IS_DATA,false,_STREAMTYPE_AUDIO);
+ return true;
+}
+
+
+int OutputStream::audioSetup(int ,int ,
+ int ,int ,int ) {
+ sendSignal(_STREAM_MASK_IS_INIT,true,_STREAMTYPE_AUDIO);
+ return true;
+}
+
+
+int OutputStream::audioPlay(TimeStamp* ,
+ TimeStamp* ,char* , int len) {
+ sendSignal(_STREAM_MASK_IS_DATA,true,_STREAMTYPE_AUDIO);
+ return len;
+}
+
+void OutputStream::audioFlush() {
+ sendSignal(_STREAM_MASK_IS_EOF,true,_STREAMTYPE_AUDIO);
+}
+
+
+void OutputStream::audioClose() {
+ cerr << "direct virtual call OutputStream::audioClose"<<endl;
+ exit(0);
+}
+
+void OutputStream::audioOpen() {
+ cerr << "direct virtual call OutputStream::audioOpen"<<endl;
+ exit(0);
+}
+
+
+
+void OutputStream::sendSignal(int signal,int value,int streamType) {
+ abs_thread_mutex_lock(&stateChangeMut);
+ int* modifyState=NULL;
+ switch(streamType) {
+ case _STREAMTYPE_AUDIO:
+ modifyState=&audioState;
+ break;
+ case _STREAMTYPE_VIDEO:
+ modifyState=&videoState;
+ break;
+ default:
+ cout << "unknown streamType:"<<streamType
+ <<" in OutputStream::sendSignal"<<endl;
+ exit(0);
+ }
+ // should we set the bit?
+ if (value==true) {
+ // set it with "or"
+ *modifyState|=signal;
+ } else {
+ // we should remove the bit
+ // is it currently set?
+ if (*modifyState & signal) {
+ // remove it
+ *modifyState-=signal;
+ }
+ }
+
+
+ abs_thread_cond_signal(&stateChangeCond);
+ abs_thread_mutex_unlock(&stateChangeMut);
+
+}
+
+
+int OutputStream::getPreferredDeliverSize() {
+ cerr << "direct virtual call OutputStream::getPreferredDeliverSize()"<<endl;
+ return 4096;
+}
+
+int OutputStream::videoInit() {
+ sendSignal(_STREAM_MASK_IS_INIT,false,_STREAMTYPE_VIDEO);
+ sendSignal(_STREAM_MASK_IS_EOF,false,_STREAMTYPE_VIDEO);
+ sendSignal(_STREAM_MASK_IS_DATA,false,_STREAMTYPE_VIDEO);
+ return true;
+}
+
+int OutputStream::openWindow(int , int ,const char* ) {
+ sendSignal(_STREAM_MASK_IS_INIT,true,_STREAMTYPE_VIDEO);
+ return true;
+}
+
+int OutputStream::x11WindowId() {
+ cout << "direct virtual call OutputStream::x11WindowId()" << endl;
+ return -1;
+}
+
+void OutputStream::closeWindow() {
+ cerr << "direct virtual call OutputStream::closeWindow"<<endl;
+ exit(0);
+}
+
+void OutputStream::flushWindow() {
+ sendSignal(_STREAM_MASK_IS_EOF,true,_STREAMTYPE_VIDEO);
+}
+
+
+PictureArray* OutputStream::lockPictureArray() {
+ cerr << "direct virtual call OutputStream::lockPictureArray"<<endl;
+ exit(0);
+ return NULL;
+}
+
+
+void OutputStream::unlockPictureArray(PictureArray* ) {
+ sendSignal(_STREAM_MASK_IS_DATA,true,_STREAMTYPE_VIDEO);
+}
+
+
+
+
+
+int OutputStream::getOutputInit() {
+ cerr << "direct virtual call OutputStream::getOutputInit"<<endl;
+ exit(0);
+ return false;
+}
+
+
+void OutputStream::setOutputInit(int lInit) {
+ cerr << "direct virtual call OutputStream::setOutputInit:"<<lInit<<endl;
+ exit(0);
+}
+
+
+
+void OutputStream::writeInfo(PluginInfo* ) {
+
+}
+
+
+void OutputStream::config(const char* key,
+ const char* value,void* user_data) {
+ cerr << "direct virtual call OutputStream::config"<<endl;
+ printf("key:%s\n",key);
+ printf("value:%s\n",value);
+ printf("user_data:%p\n",user_data);
+ exit(0);
+}
+
+int OutputStream::getFrameusec() {
+ cerr << "direct virtual call OutputStream::getFrameusec"<<endl;
+ return 0;
+}
+
+
+
+int OutputStream::waitStreamState(int method,int mask,int streamType) {
+
+ int* waitState=NULL;
+ switch(streamType) {
+ case _STREAMTYPE_AUDIO:
+ waitState=&audioState;
+ break;
+ case _STREAMTYPE_VIDEO:
+ waitState=&videoState;
+ break;
+ default:
+ cout << "unknown streamType:"<<streamType
+ <<" in OutputStream::waitStreamState"<<endl;
+ exit(0);
+ }
+
+ if (method == _OUTPUT_WAIT_METHOD_BLOCK) {
+ abs_thread_mutex_lock(&stateChangeMut);
+ while ((*waitState &= mask)==0) {
+ cout << "waitStreamState:"<<waitState<<endl;
+ cout << "mask:"<<mask<<endl;
+ abs_thread_cond_wait(&stateChangeCond,&stateChangeMut);
+ }
+ abs_thread_mutex_unlock(&stateChangeMut);
+ return true;
+ }
+
+ int back=false;
+ if (method == _OUTPUT_WAIT_METHOD_POLL) {
+ abs_thread_mutex_lock(&stateChangeMut);
+ back=*waitState;
+ abs_thread_mutex_unlock(&stateChangeMut);
+ return back;
+ }
+ cout << " OutputStream::waitStreamState method not implemented"<<endl;
+ exit(0);
+ return 0;
+}
diff --git a/mpeglib/lib/output/outputStream.h b/mpeglib/lib/output/outputStream.h
new file mode 100644
index 00000000..9ef538fd
--- /dev/null
+++ b/mpeglib/lib/output/outputStream.h
@@ -0,0 +1,151 @@
+/*
+ generic output class
+ 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 __OUTPUTSTREAM_H
+#define __OUTPUTSTREAM_H
+
+#include "../util/timeStamp.h"
+#include "pluginInfo.h"
+#include "../util/render/pictureArray.h"
+#include "../util/abstract/abs_thread.h"
+#include <kdemacros.h>
+
+#define _OUTPUT_WAIT_METHOD_BLOCK 1
+#define _OUTPUT_WAIT_METHOD_POLL 2
+#define _OUTPUT_WAIT_METHOD_CALLBACK 3
+
+
+#define _STREAM_MASK_IS_INIT 1
+#define _STREAM_MASK_IS_EOF 2
+#define _STREAM_MASK_IS_DATA 4
+
+#define _STREAM_MASK_ALL 1+2+4
+
+#define _STREAMTYPE_AUDIO 1
+#define _STREAMTYPE_VIDEO 2
+
+
+/**
+ Outputstream. A nice base class. Mostly obvious methods,
+ except PictureArray.
+ write your picture into this structure
+ and then put it on the surface with the unlock call.
+
+*/
+
+
+/**
+ life of stream states:
+ --------------
+ method flag additional calls
+ construct audioInit()
+
+
+
+ destruct audioInit()
+
+ audioInit isInit=false
+ isEof=false
+ isData=false
+
+ audioSetup isInit=true
+ audioFlush isEof=true
+ audioPlay isData=true
+
+
+ Note: after a call of streamInit we have an "invalid" state
+ obviously there is no stream where eof==false but
+ and has not been initialised.
+
+ another invalid state is audioInit->audioPlay
+
+*/
+
+
+
+
+class KDE_EXPORT OutputStream {
+
+ int audioState;
+ int videoState;
+ abs_thread_mutex_t stateChangeMut;
+ abs_thread_cond_t stateChangeCond;
+
+ public:
+ OutputStream();
+
+ virtual ~OutputStream();
+
+ // Audio Stream handling
+ virtual int audioInit();
+ virtual int audioSetup(int freq,int stereo,int sign,int big,int sampleSize);
+ virtual int audioPlay(TimeStamp* startStamp,
+ TimeStamp* endStamp,char *buffer, int size);
+ virtual void audioFlush();
+
+ // Audio device "/dev/dsp" handling
+ virtual void audioClose();
+ virtual void audioOpen();
+
+ // hack: FIX it
+ virtual int getPreferredDeliverSize();
+
+
+ // stream State handling
+
+ // we return the mask which triggerd (by "AND")
+ // or the current polled mask when method is POLL
+ // Note: you can only wait for "true" signals
+ virtual int waitStreamState(int method,int mask,int streamType);
+
+
+
+
+ // Video Output
+ virtual int videoInit();
+ virtual int openWindow(int width, int height,const char *title);
+ virtual int x11WindowId();
+ virtual void closeWindow();
+ virtual void flushWindow();
+
+
+ // get the current surfaces to draw into
+ virtual PictureArray* lockPictureArray();
+ virtual void unlockPictureArray(PictureArray* pictureArray);
+
+
+
+ // maybe not needed:
+ virtual int getFrameusec();
+ virtual int getOutputInit();
+ virtual void setOutputInit(int lInit);
+
+ // Info Output
+ virtual void writeInfo(class PluginInfo* pluginInfo);
+
+
+ // config Output
+ virtual void config(const char* key,
+ const char* value,void* user_data);
+
+ private:
+ void initStream();
+
+ protected:
+ // sometimes useful, but use with care
+ void sendSignal(int signal,int value,int streamType);
+
+};
+#endif
diff --git a/mpeglib/lib/output/performance.cpp b/mpeglib/lib/output/performance.cpp
new file mode 100644
index 00000000..9e2b7f92
--- /dev/null
+++ b/mpeglib/lib/output/performance.cpp
@@ -0,0 +1,50 @@
+/*
+ measures picture/second
+ 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 "performance.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+Performance::Performance() {
+ picCnt=0;
+ startTime=new TimeStamp();
+ endTime=new TimeStamp();
+
+}
+
+
+Performance::~Performance() {
+ delete startTime;
+ delete endTime;
+}
+
+
+void Performance::incPictureCount() {
+ if (picCnt==0) {
+ startTime->gettimeofday();
+ }
+ picCnt++;
+ if (picCnt==200) {
+ endTime->gettimeofday();
+ TimeStamp diffTime;
+ endTime->minus(startTime,&diffTime);
+ double secs=(double)diffTime.getAsSeconds();
+
+ double picSec=(double)picCnt/secs;
+ cout << "picPerSec:"<<picSec<<" secs:"<<secs<<endl;
+ picCnt=0;
+ }
+}
diff --git a/mpeglib/lib/output/performance.h b/mpeglib/lib/output/performance.h
new file mode 100644
index 00000000..d7d54572
--- /dev/null
+++ b/mpeglib/lib/output/performance.h
@@ -0,0 +1,34 @@
+/*
+ measures picture/second
+ 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 __PERFORMANCE_H
+#define __PERFORMANCE_H
+
+#include "../util/timeStamp.h"
+
+class Performance {
+
+ int picCnt;
+ TimeStamp* startTime;
+ TimeStamp* endTime;
+
+
+ public:
+
+ Performance();
+ ~Performance();
+ void incPictureCount();
+
+};
+#endif
diff --git a/mpeglib/lib/output/pluginInfo.cpp b/mpeglib/lib/output/pluginInfo.cpp
new file mode 100644
index 00000000..c741852c
--- /dev/null
+++ b/mpeglib/lib/output/pluginInfo.cpp
@@ -0,0 +1,65 @@
+/*
+ add on information about 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 "pluginInfo.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+PluginInfo::PluginInfo() {
+ musicName=new DynBuffer(20);
+
+ reset();
+
+}
+
+
+PluginInfo::~PluginInfo() {
+ delete musicName;
+}
+
+void PluginInfo::setLength(int sec) {
+ this->sec=sec;
+}
+
+
+int PluginInfo::getLength() {
+ return sec;
+}
+
+
+void PluginInfo::reset(){
+ sec=0;
+ musicName->clear();
+ musicName->append("none");
+}
+
+void PluginInfo::print() {
+ cerr << "length in sec:"<<sec<<endl;
+ cerr << "url:"<<getUrl()<<endl;
+}
+
+
+void PluginInfo::setUrl(char* name) {
+ musicName->clear();
+ if (name != NULL) {
+ musicName->append(name);
+ }
+}
+
+
+char* PluginInfo::getUrl() {
+ return musicName->getData();
+}
diff --git a/mpeglib/lib/output/pluginInfo.h b/mpeglib/lib/output/pluginInfo.h
new file mode 100644
index 00000000..7026fce9
--- /dev/null
+++ b/mpeglib/lib/output/pluginInfo.h
@@ -0,0 +1,48 @@
+/*
+ add on information about 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 __PLUGININFO_H
+#define __PLUGININFO_H
+
+#include "../util/dynBuffer.h"
+#include <kdemacros.h>
+
+/**
+ Here we have the base class for all additional information
+ about a plugin.
+ The len in time of the current song belongs here, as
+ well as the author, version number etc..
+*/
+
+
+class KDE_EXPORT PluginInfo {
+
+ int sec;
+ DynBuffer* musicName;
+
+
+ public:
+ PluginInfo();
+ ~PluginInfo();
+
+ void setLength(int sec);
+ int getLength();
+
+ void setUrl(char* name);
+ char* getUrl();
+
+ void reset();
+ void print();
+};
+#endif
diff --git a/mpeglib/lib/output/threadSafeOutputStream.cpp b/mpeglib/lib/output/threadSafeOutputStream.cpp
new file mode 100644
index 00000000..ec7ab510
--- /dev/null
+++ b/mpeglib/lib/output/threadSafeOutputStream.cpp
@@ -0,0 +1,153 @@
+/*
+ thread safe wrapper for output 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 "threadSafeOutputStream.h"
+
+
+ThreadSafeOutputStream::ThreadSafeOutputStream(OutputStream* output) {
+ threadQueueAudio=new ThreadQueue();
+ threadQueueVideo=new ThreadQueue();
+ this->output=output;
+}
+
+
+ThreadSafeOutputStream::~ThreadSafeOutputStream() {
+ delete threadQueueAudio;
+ delete threadQueueVideo;
+ delete output;
+}
+
+int ThreadSafeOutputStream::audioInit() {
+ int back;
+ threadQueueAudio->waitForExclusiveAccess();
+ back=output->audioInit();
+ threadQueueAudio->releaseExclusiveAccess();
+ return back;
+}
+
+
+int ThreadSafeOutputStream::audioSetup(int freq,int stereo,
+ int sign,int big,int sampleSize) {
+ int back;
+ threadQueueAudio->waitForExclusiveAccess();
+ back=output->audioSetup(freq,stereo,sign,big,sampleSize);
+ threadQueueAudio->releaseExclusiveAccess();
+ return back;
+}
+
+
+int ThreadSafeOutputStream::audioPlay(TimeStamp* start,
+ TimeStamp* end,char* buf, int len) {
+ int back;
+ threadQueueAudio->waitForExclusiveAccess();
+ back=output->audioPlay(start,end,buf,len);
+ threadQueueAudio->releaseExclusiveAccess();
+ return back;
+}
+
+void ThreadSafeOutputStream::audioFlush() {
+ threadQueueAudio->waitForExclusiveAccess();
+ output->audioFlush();
+ threadQueueAudio->releaseExclusiveAccess();
+}
+
+
+void ThreadSafeOutputStream::audioClose() {
+ threadQueueAudio->waitForExclusiveAccess();
+ output->audioClose();
+ threadQueueAudio->releaseExclusiveAccess();
+}
+
+void ThreadSafeOutputStream::audioOpen() {
+ threadQueueAudio->waitForExclusiveAccess();
+ output->audioOpen();
+ threadQueueAudio->releaseExclusiveAccess();
+}
+
+
+
+int ThreadSafeOutputStream::getPreferredDeliverSize() {
+ int back;
+ threadQueueAudio->waitForExclusiveAccess();
+ back=output->getPreferredDeliverSize();
+ threadQueueAudio->releaseExclusiveAccess();
+ return back;
+}
+
+int ThreadSafeOutputStream::videoInit() {
+ int back;
+ threadQueueVideo->waitForExclusiveAccess();
+ back=output->videoInit();
+ threadQueueVideo->releaseExclusiveAccess();
+ return back;
+}
+
+int ThreadSafeOutputStream::openWindow(int w, int h,const char* title) {
+ int back;
+ threadQueueVideo->waitForExclusiveAccess();
+ back=output->openWindow(w,h,title);
+ threadQueueVideo->releaseExclusiveAccess();
+ return back;
+}
+
+
+void ThreadSafeOutputStream::closeWindow() {
+ threadQueueVideo->waitForExclusiveAccess();
+ output->closeWindow();
+ threadQueueVideo->releaseExclusiveAccess();
+}
+
+void ThreadSafeOutputStream::flushWindow() {
+ threadQueueVideo->waitForExclusiveAccess();
+ output->flushWindow();
+ threadQueueVideo->releaseExclusiveAccess();
+}
+
+
+PictureArray* ThreadSafeOutputStream::lockPictureArray() {
+ PictureArray* back;
+ threadQueueVideo->waitForExclusiveAccess();
+ back=output->lockPictureArray();
+ threadQueueVideo->releaseExclusiveAccess();
+ return back;
+}
+
+
+void ThreadSafeOutputStream::unlockPictureArray(PictureArray* array) {
+ threadQueueVideo->waitForExclusiveAccess();
+ output->unlockPictureArray(array);
+ threadQueueVideo->releaseExclusiveAccess();
+}
+
+
+int ThreadSafeOutputStream::getFrameusec() {
+ int back;
+ threadQueueVideo->waitForExclusiveAccess();
+ back=output->getFrameusec();
+ threadQueueVideo->releaseExclusiveAccess();
+ return back;
+}
+
+void ThreadSafeOutputStream::config(const char* key,
+ const char* value,void* user_data) {
+
+ threadQueueVideo->waitForExclusiveAccess();
+ threadQueueAudio->waitForExclusiveAccess();
+ output->config(key,value,user_data);
+ threadQueueVideo->releaseExclusiveAccess();
+ threadQueueAudio->releaseExclusiveAccess();
+
+}
+
+
+
diff --git a/mpeglib/lib/output/threadSafeOutputStream.h b/mpeglib/lib/output/threadSafeOutputStream.h
new file mode 100644
index 00000000..c9852a37
--- /dev/null
+++ b/mpeglib/lib/output/threadSafeOutputStream.h
@@ -0,0 +1,67 @@
+/*
+ thread safe wrapper for output 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 __THREADSAFEOUTPUTSTREAM_H
+#define __THREADSAFEOUTPUTSTREAM_H
+
+// read INTRO in threadQueue.h
+// This class makes the outputStream (given in constructor)
+// threadsafe by wrapping each call with a threadqueue.
+//
+// Important NOTE: the output pointer is the owned by this class !!!
+// which means: we call delete on it!
+// More Important NOTES:
+//
+// We make the audio and video calls seperate threadsafe
+// and ONLY the config call threadsafe to both!
+
+#include "../util/abstract/threadQueue.h"
+#include "outputStream.h"
+
+
+class ThreadSafeOutputStream : public OutputStream {
+
+ ThreadQueue* threadQueueAudio;
+ ThreadQueue* threadQueueVideo;
+ OutputStream* output;
+
+ public:
+ ThreadSafeOutputStream(OutputStream* output);
+ ~ThreadSafeOutputStream();
+
+ // Thread safe Audio Stream handling
+ int audioInit();
+ int audioSetup(int freq,int stereo,int sign,int big,int sampleSize);
+ int audioPlay(TimeStamp* startStamp,
+ TimeStamp* endStamp,char *buffer, int size);
+ void audioFlush();
+ void audioClose();
+ void audioOpen();
+ int getPreferredDeliverSize();
+
+
+ // Video Output
+ int videoInit();
+ int openWindow(int width, int height,const char *title);
+ void closeWindow();
+ void flushWindow();
+ PictureArray* lockPictureArray();
+ void unlockPictureArray(PictureArray* pictureArray);
+ int getFrameusec();
+
+ // config Output
+ void config(const char* key,
+ const char* value,void* user_data);
+
+
+};
+#endif
diff --git a/mpeglib/lib/output/windowOut.cpp b/mpeglib/lib/output/windowOut.cpp
new file mode 100644
index 00000000..3e199095
--- /dev/null
+++ b/mpeglib/lib/output/windowOut.cpp
@@ -0,0 +1,64 @@
+/*
+ wrapper for X11 Window
+ 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 "windowOut.h"
+
+
+
+
+
+
+
+WindowOut::WindowOut() {
+
+ renderMachine=new RenderMachine();
+
+}
+
+
+WindowOut::~WindowOut() {
+ delete renderMachine;
+}
+
+int WindowOut::openWindow(int width, int height,const char *title){
+ return renderMachine->openWindow(width,height,title);
+}
+
+int WindowOut::x11WindowId() {
+ return renderMachine->x11WindowId();
+}
+
+void WindowOut::flushWindow() {
+ renderMachine->flushWindow();
+}
+
+
+void WindowOut::closeWindow() {
+ renderMachine->closeWindow();
+}
+
+
+PictureArray* WindowOut::lockPictureArray() {
+ return renderMachine->lockPictureArray();
+}
+
+
+void WindowOut::unlockPictureArray(PictureArray* pictureArray) {
+ renderMachine->unlockPictureArray(pictureArray);
+}
+
+
+
+void WindowOut::config(const char* key, const char* value,void* user_data) {
+ renderMachine->config(key,value,user_data);
+}
diff --git a/mpeglib/lib/output/windowOut.h b/mpeglib/lib/output/windowOut.h
new file mode 100644
index 00000000..648d1dc4
--- /dev/null
+++ b/mpeglib/lib/output/windowOut.h
@@ -0,0 +1,53 @@
+/*
+ wrapper for X11 Window
+ 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 __WINDOWOUT_H
+#define __WINDOWOUT_H
+
+
+#include "../util/abstract/abs_thread.h"
+#include "../util/timeStamp.h"
+#include "../util/render/renderMachine.h"
+
+/**
+ Stupid class. survivor of ancient days.
+*/
+
+
+class WindowOut {
+
+
+ RenderMachine* renderMachine;
+
+ public:
+ WindowOut();
+ ~WindowOut();
+
+ int openWindow(int width, int height,const char *title);
+ int x11WindowId();
+ void closeWindow();
+ void flushWindow();
+
+ // get the current surfaces to draw into
+ PictureArray* lockPictureArray();
+ void unlockPictureArray(PictureArray* pictureArray);
+
+ void config(const char* key, const char* value,void* user_data);
+
+
+ private:
+
+
+};
+#endif
diff --git a/mpeglib/lib/output/yuvDumper.cpp b/mpeglib/lib/output/yuvDumper.cpp
new file mode 100644
index 00000000..1962b151
--- /dev/null
+++ b/mpeglib/lib/output/yuvDumper.cpp
@@ -0,0 +1,81 @@
+/*
+ writes yuv images on HD
+ 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 "yuvDumper.h"
+
+YUVDumper::YUVDumper() {
+ picCnt=1;
+ method=_DUMP_YUV_AS_STREAM;
+}
+
+YUVDumper::~YUVDumper() {
+}
+
+
+int YUVDumper::openWindow(int w, int h,const char*) {
+
+ FILE* formatFile=fopen("stream.yuv.format","w+");
+ fprintf(formatFile,"Version 0.1\nw:%dh:%d\n",w,h);
+ fclose(formatFile);
+
+
+
+ if (method == _DUMP_YUV_AS_STREAM) {
+ FILE* outFile=fopen("stream.yuv","w+");
+ fclose(outFile);
+ }
+ return true;
+}
+
+void YUVDumper::closeWindow() {
+}
+
+
+void YUVDumper::flushWindow() {
+}
+
+
+int YUVDumper::getMethod() {
+ return method;
+}
+
+
+void YUVDumper::setMethod(int method) {
+ this->method=method;
+}
+
+void YUVDumper::unlockPictureArray(PictureArray* pictureArray) {
+ YUVPicture* pic=pictureArray->getYUVPictureCallback();
+ if (pic == NULL) {
+ return;
+ }
+
+ FILE* outFile=NULL;
+
+ if (method == _DUMP_YUV_AS_STREAM) {
+ outFile=fopen("stream.yuv","a+");
+ }
+
+ if (outFile == NULL) {
+ perror("fopen");
+ return;
+ }
+
+ int lumSize=pic->getLumLength();
+ int colorSize=pic->getColorLength();
+ fwrite(pic->getLuminancePtr(),1,lumSize,outFile);
+ fwrite(pic->getCrPtr(),1,colorSize,outFile);
+ fwrite(pic->getCbPtr(),1,colorSize,outFile);
+ fclose(outFile);
+
+}
diff --git a/mpeglib/lib/output/yuvDumper.h b/mpeglib/lib/output/yuvDumper.h
new file mode 100644
index 00000000..2e4880b0
--- /dev/null
+++ b/mpeglib/lib/output/yuvDumper.h
@@ -0,0 +1,51 @@
+/*
+ writes yuv images on HD
+ 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 __YUVDUMPER_H
+#define __YUVDUMPER_H
+
+#include "outputStream.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+
+#define _DUMP_YUV_AS_STREAM 2
+
+
+class YUVDumper : public OutputStream {
+
+
+ int picCnt;
+ int method;
+
+ public:
+ YUVDumper();
+ ~YUVDumper();
+
+ // Video Output
+
+ int openWindow(int width, int height,const char *title);
+ void closeWindow();
+ void flushWindow();
+
+ void unlockPictureArray(PictureArray* pictureArray);
+ int getMethod();
+ void setMethod(int method);
+
+
+};
+
+#endif
diff --git a/mpeglib/lib/splay/Makefile.am b/mpeglib/lib/splay/Makefile.am
new file mode 100644
index 00000000..70fdc105
--- /dev/null
+++ b/mpeglib/lib/splay/Makefile.am
@@ -0,0 +1,53 @@
+# libsplay - Makefile.am
+
+
+INCLUDES = $(all_includes)
+
+
+EXTRA_DIST = dct64.cpp dct64_down.cpp dct36_12.cpp \
+ window.cpp dct.h
+
+
+noinst_LTLIBRARIES = libsplay.la
+
+noinst_HEADERS = mpegAudioHeader.h mpegAudioStream.h \
+ mpegsound.h op.h \
+ sigsev.c dump.h \
+ dxHead.h mpeg2tables.h \
+ mpegAudioBitWindow.h huffmanlookup.h \
+ common.h attribute.h synthesis.h
+
+kmpgincludedir = $(includedir)/$(THIS_LIB_NAME)/splay
+
+kmpginclude_HEADERS = splayDecoder.h mpegAudioInfo.h \
+ mpegAudioFrame.h
+
+
+libsplay_la_SOURCES = mpegAudioHeader.cpp mpegAudioStream.cpp \
+ huffmantable.cpp \
+ mpeglayer1.cpp \
+ mpeglayer2.cpp \
+ mpeglayer3.cpp \
+ mpegtable.cpp \
+ mpegtoraw.cpp \
+ dxHead.cpp \
+ mpegAudioBitWindow.cpp huffmanlookup.cpp \
+ splayDecoder.cpp \
+ dump.cpp synth_filter.cpp \
+ synthesis.cpp synth_Std.cpp synth_Down.cpp \
+ mpegAudioFrame.cpp \
+ mpegAudioInfo.cpp
+
+
+
+#CXXFLAGS += -fno-strength-reduce
+# -funroll-all-loops -finline-functions -ffast-math -m486
+
+
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/splay/attribute.h b/mpeglib/lib/splay/attribute.h
new file mode 100644
index 00000000..9e6bf0e6
--- /dev/null
+++ b/mpeglib/lib/splay/attribute.h
@@ -0,0 +1,33 @@
+/*
+ align attribut definition (g++)
+ 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 __ATTRIBUTE_H
+#define __ATTRIBUTE_H
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* use gcc attribs to align critical data structures */
+
+#ifdef ATTRIBUTE_ALIGNED_MAX
+#define ATTR_ALIGN(align) __attribute__ \
+ ((__aligned__ ((ATTRIBUTE_ALIGNED_MAX <align) ? \
+ ATTRIBUTE_ALIGNED_MAX : align)))
+#else
+#define ATTR_ALIGN(align)
+#endif
+
+
+#endif
diff --git a/mpeglib/lib/splay/common.h b/mpeglib/lib/splay/common.h
new file mode 100644
index 00000000..df0945b8
--- /dev/null
+++ b/mpeglib/lib/splay/common.h
@@ -0,0 +1,60 @@
+/*
+ include header for dcts/windows
+ 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 __COMMON_H
+#define __COMMON_H
+
+#include "attribute.h"
+#include <stdio.h>
+
+#define SSLIMIT 18
+#define SBLIMIT 32
+
+
+#define LS 0
+#define RS 1
+
+
+typedef float REAL;
+
+// The inline code works on intel only with egcs >= 1.1
+#ifdef __GNUC__
+#if (__GNUC__ < 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ < 91 ) )
+#ifndef _AIX
+#warning "inline code disabled! (buggy egcs version)"
+#undef __NO_MATH_INLINES
+#define __NO_MATH_INLINES 1
+#endif
+#endif
+#endif
+#include <math.h>
+#include <stdlib.h>
+
+#ifndef M_PI
+#define MY_PI 3.14159265358979323846
+#else
+#define MY_PI M_PI
+#endif
+
+#ifdef PI
+#undef PI
+#endif
+#define PI MY_PI
+#define PI_12 (PI/12.0)
+#define PI_18 (PI/18.0)
+#define PI_24 (PI/24.0)
+#define PI_36 (PI/36.0)
+#define PI_72 (PI/72.0)
+
+
+#endif
diff --git a/mpeglib/lib/splay/dct.h b/mpeglib/lib/splay/dct.h
new file mode 100644
index 00000000..ad707a19
--- /dev/null
+++ b/mpeglib/lib/splay/dct.h
@@ -0,0 +1,33 @@
+/*
+ wrapper for dcts
+ 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 __DCT_HEADER_H
+#define __DCT_HEADER_H
+
+// one source:
+extern void initialize_dct64();
+
+//extern void dct64(REAL* out1,REAL* out2,REAL *fraction);
+
+// one source:
+extern void initialize_dct64_downsample();
+//extern void dct64_downsample(REAL* out1,REAL* out2,REAL *fraction);
+
+// one source file:
+extern void initialize_dct12_dct36();
+
+//extern void dct12(REAL *in,REAL *prevblk1,REAL *prevblk2,REAL *wi,REAL *out);
+//extern void dct36(REAL *inbuf,REAL *prevblk1,REAL *prevblk2,REAL *wi,REAL *out);
+
+extern void initialize_win();
+#endif
diff --git a/mpeglib/lib/splay/dct36_12.cpp b/mpeglib/lib/splay/dct36_12.cpp
new file mode 100644
index 00000000..b9978d7d
--- /dev/null
+++ b/mpeglib/lib/splay/dct36_12.cpp
@@ -0,0 +1,288 @@
+/*
+ wrapper for dcts
+ 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 "dct.h"
+#include "common.h"
+
+
+
+ATTR_ALIGN(64) static REAL hsec_12[3];
+ATTR_ALIGN(64) static REAL cos2_6=cos(PI/6.0*2.0);
+ATTR_ALIGN(64) static REAL cos1_6=cos(PI/6.0*1.0);
+ATTR_ALIGN(64) static REAL hsec_36[9];
+ATTR_ALIGN(64) static REAL cos_18[9];
+
+
+/**
+ This was some time ago a standalone dct class,
+ but to get more speed I made it an inline dct
+ int the filter classes
+*/
+
+static int dct36_12Init=false;
+
+void initialize_dct12_dct36() {
+ if (dct36_12Init==true) {
+ return;
+ }
+ dct36_12Init=true;
+
+
+ int i;
+
+ for(i=0;i<3;i++)
+ hsec_12[i]=0.5/cos(double(i*2+1)* PI_12);
+
+ for(i=0;i<9;i++)
+ hsec_36[i]=0.5/cos(double(i*2+1)* PI_36);
+
+ for(i=0;i<9;i++)
+ cos_18[i]=cos(PI_18*double(i));
+
+}
+
+
+inline void dct36(REAL *inbuf,REAL *prevblk1,
+ REAL *prevblk2,REAL *wi,REAL *out){
+
+#define MACRO0(v) { \
+ REAL tmp; \
+ out2[9+(v)]=(tmp=sum0+sum1)*wi[27+(v)]; \
+ out2[8-(v)]=tmp * wi[26-(v)]; } \
+ sum0-=sum1; \
+ ts[SBLIMIT*(8-(v))]=out1[8-(v)]+sum0*wi[8-(v)]; \
+ ts[SBLIMIT*(9+(v))]=out1[9+(v)]+sum0*wi[9+(v)];
+#define MACRO1(v) { \
+ REAL sum0,sum1; \
+ sum0=tmp1a+tmp2a; \
+ sum1=(tmp1b+tmp2b)*hsec_36[(v)]; \
+ MACRO0(v); }
+#define MACRO2(v) { \
+ REAL sum0,sum1; \
+ sum0=tmp2a-tmp1a; \
+ sum1=(tmp2b-tmp1b) * hsec_36[(v)]; \
+ MACRO0(v); }
+
+ {
+ REAL *in = inbuf;
+
+ in[17]+=in[16];in[16]+=in[15];in[15]+=in[14];in[14]+=in[13];
+ in[13]+=in[12];in[12]+=in[11];in[11]+=in[10];in[10]+=in[ 9];
+ in[ 9]+=in[ 8];in[ 8]+=in[ 7];in[ 7]+=in[ 6];in[ 6]+=in[ 5];
+ in[ 5]+=in[ 4];in[ 4]+=in[ 3];in[ 3]+=in[ 2];in[ 2]+=in[ 1];
+ in[ 1]+=in[ 0];
+
+
+ in[17]+=in[15];in[15]+=in[13];in[13]+=in[11];in[11]+=in[ 9];
+ in[ 9]+=in[ 7];in[7] +=in[ 5];in[ 5]+=in[ 3];in[ 3]+=in[ 1];
+
+ {
+ REAL *c = cos_18;
+ REAL *out2 = prevblk2;
+ REAL *out1 = prevblk1;
+ REAL *ts = out;
+
+ REAL ta33,ta66,tb33,tb66;
+
+ ta33=in[2*3+0]*c[3];
+ ta66=in[2*6+0]*c[6];
+ tb33=in[2*3+1]*c[3];
+ tb66=in[2*6+1]*c[6];
+
+ {
+ REAL tmp1a,tmp2a,tmp1b,tmp2b;
+ tmp1a= in[2*1+0]*c[1]+ta33 +in[2*5+0]*c[5]+in[2*7+0]*c[7];
+ tmp1b= in[2*1+1]*c[1]+tb33 +in[2*5+1]*c[5]+in[2*7+1]*c[7];
+ tmp2a=in[2*0+0]+in[2*2+0]*c[2]+in[2*4+0]*c[4]+ta66 +in[2*8+0]*c[8];
+ tmp2b=in[2*0+1]+in[2*2+1]*c[2]+in[2*4+1]*c[4]+tb66 +in[2*8+1]*c[8];
+ MACRO1(0);
+ MACRO2(8);
+ }
+
+ {
+ REAL tmp1a,tmp2a,tmp1b,tmp2b;
+ tmp1a=(in[2*1+0]-in[2*5+0]-in[2*7+0])*c[3];
+ tmp1b=(in[2*1+1]-in[2*5+1]-in[2*7+1])*c[3];
+ tmp2a=(in[2*2+0]-in[2*4+0]-in[2*8+0])*c[6]-in[2*6+0]+in[2*0+0];
+ tmp2b=(in[2*2+1]-in[2*4+1]-in[2*8+1])*c[6]-in[2*6+1]+in[2*0+1];
+ MACRO1(1);
+ MACRO2(7);
+ }
+
+ {
+ REAL tmp1a,tmp2a,tmp1b,tmp2b;
+ tmp1a= in[2*1+0]*c[5]-ta33 -in[2*5+0]*c[7]+in[2*7+0]*c[1];
+ tmp1b= in[2*1+1]*c[5]-tb33 -in[2*5+1]*c[7]+in[2*7+1]*c[1];
+ tmp2a=in[2*0+0]-in[2*2+0]*c[8]-in[2*4+0]*c[2]+ta66 +in[2*8+0]*c[4];
+ tmp2b=in[2*0+1]-in[2*2+1]*c[8]-in[2*4+1]*c[2]+tb66 +in[2*8+1]*c[4];
+ MACRO1(2);
+ MACRO2(6);
+ }
+
+ {
+ REAL tmp1a,tmp2a,tmp1b,tmp2b;
+ tmp1a= in[2*1+0]*c[7]-ta33 +in[2*5+0]*c[1]-in[2*7+0]*c[5];
+ tmp1b= in[2*1+1]*c[7]-tb33 +in[2*5+1]*c[1]-in[2*7+1]*c[5];
+ tmp2a=in[2*0+0]-in[2*2+0]*c[4]+in[2*4+0]*c[8]+ta66 -in[2*8+0]*c[2];
+ tmp2b=in[2*0+1]-in[2*2+1]*c[4]+in[2*4+1]*c[8]+tb66 -in[2*8+1]*c[2];
+ MACRO1(3);
+ MACRO2(5);
+ }
+
+ {
+ REAL sum0,sum1;
+ sum0= in[2*0+0]-in[2*2+0]+in[2*4+0]-in[2*6+0]+in[2*8+0];
+ sum1=(in[2*0+1]-in[2*2+1]+in[2*4+1]-in[2*6+1]+in[2*8+1])*hsec_36[4];
+ MACRO0(4);
+ }
+ }
+ }
+
+
+}
+
+
+inline void dct12(REAL *in,REAL *prevblk1,REAL *prevblk2,REAL *wi,REAL *out) {
+
+#define DCT12_PART1 \
+ in5=in[5*3]; \
+ in5+=(in4=in[4*3]); \
+ in4+=(in3=in[3*3]); \
+ in3+=(in2=in[2*3]); \
+ in2+=(in1=in[1*3]); \
+ in1+=(in0=in[0*3]); \
+ \
+ in5+=in3;in3+=in1; \
+ \
+ in2*=cos1_6; \
+ in3*=cos1_6;
+
+#define DCT12_PART2 \
+ in0+=in4*cos2_6; \
+ \
+ in4=in0+in2; \
+ in0-=in2; \
+ \
+ in1+=in5*cos2_6; \
+ \
+ in5=(in1+in3)*hsec_12[0]; \
+ in1=(in1-in3)*hsec_12[2]; \
+ \
+ in3=in4+in5; \
+ in4-=in5; \
+ \
+ in2=in0+in1; \
+ in0-=in1;
+
+ {
+ REAL in0,in1,in2,in3,in4,in5;
+ register REAL *pb1=prevblk1;
+ out[SBLIMIT*0]=pb1[0];out[SBLIMIT*1]=pb1[1];out[SBLIMIT*2]=pb1[2];
+ out[SBLIMIT*3]=pb1[3];out[SBLIMIT*4]=pb1[4];out[SBLIMIT*5]=pb1[5];
+
+ DCT12_PART1;
+
+ {
+ REAL tmp0,tmp1=(in0-in4);
+ {
+ register REAL tmp2=(in1-in5)*hsec_12[1];
+ tmp0=tmp1+tmp2;
+ tmp1-=tmp2;
+ }
+ out[(17-1)*SBLIMIT]=pb1[17-1]+tmp0*wi[11-1];
+ out[(12+1)*SBLIMIT]=pb1[12+1]+tmp0*wi[ 6+1];
+ out[(6 +1)*SBLIMIT]=pb1[6 +1]+tmp1*wi[ 1 ];
+ out[(11-1)*SBLIMIT]=pb1[11-1]+tmp1*wi[ 5-1];
+ }
+
+ DCT12_PART2;
+ out[(17-0)*SBLIMIT]=pb1[17-0]+in2*wi[11-0];
+ out[(12+0)*SBLIMIT]=pb1[12+0]+in2*wi[ 6+0];
+ out[(12+2)*SBLIMIT]=pb1[12+2]+in3*wi[ 6+2];
+ out[(17-2)*SBLIMIT]=pb1[17-2]+in3*wi[11-2];
+
+ out[( 6+0)*SBLIMIT]=pb1[ 6+0]+in0*wi[0];
+ out[(11-0)*SBLIMIT]=pb1[11-0]+in0*wi[5-0];
+ out[( 6+2)*SBLIMIT]=pb1[ 6+2]+in4*wi[2];
+ out[(11-2)*SBLIMIT]=pb1[11-2]+in4*wi[5-2];
+ }
+
+ in++;
+ {
+ REAL in0,in1,in2,in3,in4,in5;
+ register REAL *pb2 = prevblk2;
+
+ DCT12_PART1;
+
+ {
+ REAL tmp0,tmp1=(in0-in4);
+ {
+ REAL tmp2=(in1-in5)*hsec_12[1];
+ tmp0=tmp1+tmp2;
+ tmp1-=tmp2;
+ }
+ pb2[5-1]=tmp0*wi[11-1];
+ pb2[0+1]=tmp0*wi[6+1];
+ out[(12+1)*SBLIMIT]+=tmp1*wi[1];
+ out[(17-1)*SBLIMIT]+=tmp1*wi[5-1];
+ }
+
+ DCT12_PART2;
+
+ pb2[5-0]=in2*wi[11-0];
+ pb2[0+0]=in2*wi[6+0];
+ pb2[0+2]=in3*wi[6+2];
+ pb2[5-2]=in3*wi[11-2];
+
+ out[(12+0)*SBLIMIT]+=in0*wi[0];
+ out[(17-0)*SBLIMIT]+=in0*wi[5-0];
+ out[(12+2)*SBLIMIT]+=in4*wi[2];
+ out[(17-2)*SBLIMIT]+=in4*wi[5-2];
+ }
+
+ in++;
+ {
+ REAL in0,in1,in2,in3,in4,in5;
+ register REAL *pb2 = prevblk2;
+ pb2[12]=pb2[13]=pb2[14]=pb2[15]=pb2[16]=pb2[17]=0.0;
+
+ DCT12_PART1;
+
+ {
+ REAL tmp0,tmp1=(in0-in4);
+ {
+ REAL tmp2=(in1-in5)*hsec_12[1];
+ tmp0=tmp1+tmp2;
+ tmp1-=tmp2;
+ }
+ pb2[11-1]=tmp0*wi[11-1];
+ pb2[ 6+1]=tmp0*wi[6+1];
+ pb2[ 0+1]+=tmp1*wi[1];
+ pb2[ 5-1]+=tmp1*wi[5-1];
+ }
+
+ DCT12_PART2;
+ pb2[11-0]=in2*wi[11-0];
+ pb2[ 6+0]=in2*wi[ 6+0];
+ pb2[ 6+2]=in3*wi[ 6+2];
+ pb2[11-2]=in3*wi[11-2];
+
+ pb2[ 0+0]+=in0*wi[0 ];
+ pb2[ 5-0]+=in0*wi[5-0];
+ pb2[ 0+2]+=in4*wi[2 ];
+ pb2[ 5-2]+=in4*wi[5-2];
+ }
+
+
+}
+
+
diff --git a/mpeglib/lib/splay/dct64.cpp b/mpeglib/lib/splay/dct64.cpp
new file mode 100644
index 00000000..14241651
--- /dev/null
+++ b/mpeglib/lib/splay/dct64.cpp
@@ -0,0 +1,202 @@
+/*
+ wrapper for dcts
+ 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 "dct.h"
+#include "common.h"
+
+ATTR_ALIGN(64) static REAL hcos_64[16];
+ATTR_ALIGN(64) static REAL hcos_32[8];
+ATTR_ALIGN(64) static REAL hcos_16[4];
+ATTR_ALIGN(64) static REAL hcos_8[2];
+ATTR_ALIGN(64) static REAL hcos_4;
+
+/**
+ This was some time ago a standalone dct class,
+ but to get more speed I made it an inline dct
+ int the filter classes
+*/
+
+static int dct64Init=false;
+
+void initialize_dct64() {
+ if (dct64Init==true) {
+ return;
+ }
+ dct64Init=true;
+
+ int i;
+
+ for(i=0;i<16;i++) {
+ hcos_64[i]=1.0/(2.0*cos(MY_PI*double(i*2+1)/64.0));
+ }
+ for(i=0;i< 8;i++) {
+ hcos_32[i]=1.0/(2.0*cos(MY_PI*double(i*2+1)/32.0));
+ }
+ for(i=0;i< 4;i++) {
+ hcos_16[i]=1.0/(2.0*cos(MY_PI*double(i*2+1)/16.0));
+ }
+ for(i=0;i< 2;i++) {
+ hcos_8[i]=1.0/(2.0*cos(MY_PI*double(i*2+1)/ 8.0));
+ }
+ hcos_4=1.0/(2.0*cos(MY_PI*1.0/4.0));
+
+}
+
+
+
+
+//
+// splay dct64 , faster than mpeg123 dct. (from decode.c)
+//
+inline void dct64(REAL* out1,REAL* out2,REAL *fraction) {
+ ATTR_ALIGN(64) REAL p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,pa,pb,pc,pd,pe,pf;
+ ATTR_ALIGN(64) REAL q0,q1,q2,q3,q4,q5,q6,q7,q8,q9,qa,qb,qc,qd,qe,qf;
+
+#define OUT1(v,t) out1[(32-(v))*16] =(-(out1[(v)*16]=t))
+#define OUT2(v) out2[(96-(v)-32)*16]=out2[((v)-32)*16]
+
+ // compute new values via a fast cosine transform:
+ {
+ // put to buffer 0..15
+ register REAL* x=fraction;
+
+ p0=x[ 0]+x[31];p1=x[ 1]+x[30];p2=x[ 2]+x[29];p3=x[ 3]+x[28];
+ p4=x[ 4]+x[27];p5=x[ 5]+x[26];p6=x[ 6]+x[25];p7=x[ 7]+x[24];
+ p8=x[ 8]+x[23];p9=x[ 9]+x[22];pa=x[10]+x[21];pb=x[11]+x[20];
+ pc=x[12]+x[19];pd=x[13]+x[18];pe=x[14]+x[17];pf=x[15]+x[16];
+ }
+
+ // put to buffer 32..39
+ q0=p0+pf;q1=p1+pe;q2=p2+pd;q3=p3+pc;
+ q4=p4+pb;q5=p5+pa;q6=p6+p9;q7=p7+p8;
+ // put to buffer 40..47
+ q8=hcos_32[0]*(p0-pf);q9=hcos_32[1]*(p1-pe);
+ qa=hcos_32[2]*(p2-pd);qb=hcos_32[3]*(p3-pc);
+ qc=hcos_32[4]*(p4-pb);qd=hcos_32[5]*(p5-pa);
+ qe=hcos_32[6]*(p6-p9);qf=hcos_32[7]*(p7-p8);
+
+ p0=q0+q7;p1=q1+q6;p2=q2+q5;p3=q3+q4;
+ p4=hcos_16[0]*(q0-q7);p5=hcos_16[1]*(q1-q6);
+ p6=hcos_16[2]*(q2-q5);p7=hcos_16[3]*(q3-q4);
+ p8=q8+qf;p9=q9+qe;pa=qa+qd;pb=qb+qc;
+ pc=hcos_16[0]*(q8-qf);pd=hcos_16[1]*(q9-qe);
+ pe=hcos_16[2]*(qa-qd);pf=hcos_16[3]*(qb-qc);
+
+ q0=p0+p3;q1=p1+p2;q2=hcos_8[0]*(p0-p3);q3=hcos_8[1]*(p1-p2);
+ q4=p4+p7;q5=p5+p6;q6=hcos_8[0]*(p4-p7);q7=hcos_8[1]*(p5-p6);
+ q8=p8+pb;q9=p9+pa;qa=hcos_8[0]*(p8-pb);qb=hcos_8[1]*(p9-pa);
+ qc=pc+pf;qd=pd+pe;qe=hcos_8[0]*(pc-pf);qf=hcos_8[1]*(pd-pe);
+
+ p0=q0+q1;p1=hcos_4*(q0-q1);p2=q2+q3;p3=hcos_4*(q2-q3);
+ p4=q4+q5;p5=hcos_4*(q4-q5);p6=q6+q7;p7=hcos_4*(q6-q7);
+ p8=q8+q9;p9=hcos_4*(q8-q9);pa=qa+qb;pb=hcos_4*(qa-qb);
+ pc=qc+qd;pd=hcos_4*(qc-qd);pe=qe+qf;pf=hcos_4*(qe-qf);
+
+ {
+ register REAL tmp;
+
+ tmp=p6+p7;
+ OUT2(36)=-(p5+tmp);
+ OUT2(44)=-(p4+tmp);
+ tmp=pb+pf;
+ OUT1(10,tmp);
+ OUT1(6,pd+tmp);
+ tmp=pe+pf;
+ OUT2(46)=-(p8+pc+tmp);
+ OUT2(34)=-(p9+pd+tmp);
+ tmp+=pa+pb;
+ OUT2(38)=-(pd+tmp);
+ OUT2(42)=-(pc+tmp);
+ OUT1(2,p9+pd+pf);
+ OUT1(4,p5+p7);
+ OUT2(48)=-p0;
+ out2[0]=-(out1[0]=p1);
+ OUT1( 8,p3);
+ OUT1(12,p7);
+ OUT1(14,pf);
+ OUT2(40)=-(p2+p3);
+ }
+
+ {
+ // put to buffer 16..31
+ register REAL *x=fraction;
+
+ p0=hcos_64[ 0]*(x[ 0]-x[31]);p1=hcos_64[ 1]*(x[ 1]-x[30]);
+ p2=hcos_64[ 2]*(x[ 2]-x[29]);p3=hcos_64[ 3]*(x[ 3]-x[28]);
+ p4=hcos_64[ 4]*(x[ 4]-x[27]);p5=hcos_64[ 5]*(x[ 5]-x[26]);
+ p6=hcos_64[ 6]*(x[ 6]-x[25]);p7=hcos_64[ 7]*(x[ 7]-x[24]);
+ p8=hcos_64[ 8]*(x[ 8]-x[23]);p9=hcos_64[ 9]*(x[ 9]-x[22]);
+ pa=hcos_64[10]*(x[10]-x[21]);pb=hcos_64[11]*(x[11]-x[20]);
+ pc=hcos_64[12]*(x[12]-x[19]);pd=hcos_64[13]*(x[13]-x[18]);
+ pe=hcos_64[14]*(x[14]-x[17]);pf=hcos_64[15]*(x[15]-x[16]);
+ }
+
+ // put to 48..63
+ q0=p0+pf;q1=p1+pe;q2=p2+pd;q3=p3+pc;
+ q4=p4+pb;q5=p5+pa;q6=p6+p9;q7=p7+p8;
+ q8=hcos_32[0]*(p0-pf);q9=hcos_32[1]*(p1-pe);
+ qa=hcos_32[2]*(p2-pd);qb=hcos_32[3]*(p3-pc);
+ qc=hcos_32[4]*(p4-pb);qd=hcos_32[5]*(p5-pa);
+ qe=hcos_32[6]*(p6-p9);qf=hcos_32[7]*(p7-p8);
+
+ p0=q0+q7;p1=q1+q6;p2=q2+q5;p3=q3+q4;
+ p4=hcos_16[0]*(q0-q7);p5=hcos_16[1]*(q1-q6);
+ p6=hcos_16[2]*(q2-q5);p7=hcos_16[3]*(q3-q4);
+ p8=q8+qf;p9=q9+qe;pa=qa+qd;pb=qb+qc;
+ pc=hcos_16[0]*(q8-qf);pd=hcos_16[1]*(q9-qe);
+ pe=hcos_16[2]*(qa-qd);pf=hcos_16[3]*(qb-qc);
+
+ q0=p0+p3;q1=p1+p2;q2=hcos_8[0]*(p0-p3);q3=hcos_8[1]*(p1-p2);
+ q4=p4+p7;q5=p5+p6;q6=hcos_8[0]*(p4-p7);q7=hcos_8[1]*(p5-p6);
+ q8=p8+pb;q9=p9+pa;qa=hcos_8[0]*(p8-pb);qb=hcos_8[1]*(p9-pa);
+ qc=pc+pf;qd=pd+pe;qe=hcos_8[0]*(pc-pf);qf=hcos_8[1]*(pd-pe);
+
+ p0=q0+q1;p1=hcos_4*(q0-q1);
+ p2=q2+q3;p3=hcos_4*(q2-q3);
+ p4=q4+q5;p5=hcos_4*(q4-q5);
+ p6=q6+q7;p7=hcos_4*(q6-q7);
+ p8=q8+q9;p9=hcos_4*(q8-q9);
+ pa=qa+qb;pb=hcos_4*(qa-qb);
+ pc=qc+qd;pd=hcos_4*(qc-qd);
+ pe=qe+qf;pf=hcos_4*(qe-qf);
+
+ {
+ REAL tmp;
+
+ tmp=pd+pf;
+ OUT1(5,p5+p7+pb+tmp);
+ tmp+=p9;
+ OUT1(1,p1+tmp);
+ OUT2(33)=-(p1+pe+tmp);
+ tmp+=p5+p7;
+ OUT1(3,tmp);
+ OUT2(35)=-(p6+pe+tmp);
+ tmp=pa+pb+pc+pd+pe+pf;
+ OUT2(39)=-(p2+p3+tmp-pc);
+ OUT2(43)=-(p4+p6+p7+tmp-pd);
+ OUT2(37)=-(p5+p6+p7+tmp-pc);
+ OUT2(41)=-(p2+p3+tmp-pd);
+ tmp=p8+pc+pe+pf;
+ OUT2(47)=-(p0+tmp);
+ OUT2(45)=-(p4+p6+p7+tmp);
+ tmp=pb+pf;
+ OUT1(11,p7+tmp);
+ tmp+=p3;
+ OUT1( 9,tmp);
+ OUT1( 7,pd+tmp);
+ OUT1(13,p7+pf);
+ OUT1(15,pf);
+ }
+
+}
+
+
diff --git a/mpeglib/lib/splay/dct64_down.cpp b/mpeglib/lib/splay/dct64_down.cpp
new file mode 100644
index 00000000..7137664c
--- /dev/null
+++ b/mpeglib/lib/splay/dct64_down.cpp
@@ -0,0 +1,215 @@
+/*
+ wrapper for dcts
+ 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 "dct.h"
+#include "common.h"
+
+#include <iostream>
+
+using namespace std;
+
+ATTR_ALIGN(64) static REAL hcos_64_down[16];
+ATTR_ALIGN(64) static REAL hcos_32_down[8];
+ATTR_ALIGN(64) static REAL hcos_16_down[4];
+ATTR_ALIGN(64) static REAL hcos_8_down[2];
+ATTR_ALIGN(64) static REAL hcos_4_down;
+
+/**
+ This was some time ago a standalone dct class,
+ but to get more speed I made it an inline dct
+ int the filter classes
+*/
+
+static int dctInit=false;
+
+void initialize_dct64_downsample() {
+ if (dctInit==true) {
+ return;
+ }
+ dctInit=true;
+
+ int i;
+
+ for(i=0;i<16;i++) {
+ hcos_64_down[i]=1.0/(2.0*cos(MY_PI*double(i*2+1)/64.0));
+ }
+ for(i=0;i< 8;i++) {
+ hcos_32_down[i]=1.0/(2.0*cos(MY_PI*double(i*2+1)/32.0));
+ }
+ for(i=0;i< 4;i++) {
+ hcos_16_down[i]=1.0/(2.0*cos(MY_PI*double(i*2+1)/16.0));
+ }
+ for(i=0;i< 2;i++) {
+ hcos_8_down[i]=1.0/(2.0*cos(MY_PI*double(i*2+1)/ 8.0));
+ }
+ hcos_4_down=1.0/(2.0*cos(MY_PI*1.0/4.0));
+
+}
+
+inline void dct64_downsample(REAL* out1,REAL* out2,REAL *fraction) {
+ REAL p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,pa,pb,pc,pd,pe,pf;
+ REAL q0,q1,q2,q3,q4,q5,q6,q7,q8,q9,qa,qb,qc,qd,qe,qf;
+
+#define OUT1(v,t) out1[(32-(v))*16] =(-(out1[(v)*16]=t))
+#define OUT2(v) out2[(96-(v)-32)*16]=out2[((v)-32)*16]
+
+ // compute new values via a fast cosine transform:
+ /* {
+ register REAL *x=fraction;
+
+ p0=x[ 0]+x[31];p1=x[ 1]+x[30];p2=x[ 2]+x[29];p3=x[ 3]+x[28];
+ p4=x[ 4]+x[27];p5=x[ 5]+x[26];p6=x[ 6]+x[25];p7=x[ 7]+x[24];
+ p8=x[ 8]+x[23];p9=x[ 9]+x[22];pa=x[10]+x[21];pb=x[11]+x[20];
+ pc=x[12]+x[19];pd=x[13]+x[18];pe=x[14]+x[17];pf=x[15]+x[16];
+ }
+
+ q0=p0+pf;q1=p1+pe;q2=p2+pd;q3=p3+pc;
+ q4=p4+pb;q5=p5+pa;q6=p6+p9;q7=p7+p8;
+ q8=hcos_32_down[0]*(p0-pf);q9=hcos_32_down[1]*(p1-pe);
+ qa=hcos_32_down[2]*(p2-pd);qb=hcos_32_down[3]*(p3-pc);
+ qc=hcos_32_down[4]*(p4-pb);qd=hcos_32_down[5]*(p5-pa);
+ qe=hcos_32_down[6]*(p6-p9);qf=hcos_32_down[7]*(p7-p8); */
+
+ {
+
+ register REAL *x=fraction;
+
+ q0=x[ 0]+x[15];q1=x[ 1]+x[14];q2=x[ 2]+x[13];q3=x[ 3]+x[12];
+ q4=x[ 4]+x[11];q5=x[ 5]+x[10];q6=x[ 6]+x[ 9];q7=x[ 7]+x[ 8];
+
+ q8=hcos_32_down[0]*(x[ 0]-x[15]);q9=hcos_32_down[1]*(x[ 1]-x[14]);
+ qa=hcos_32_down[2]*(x[ 2]-x[13]);qb=hcos_32_down[3]*(x[ 3]-x[12]);
+ qc=hcos_32_down[4]*(x[ 4]-x[11]);qd=hcos_32_down[5]*(x[ 5]-x[10]);
+ qe=hcos_32_down[6]*(x[ 6]-x[ 9]);qf=hcos_32_down[7]*(x[ 7]-x[ 8]);
+ }
+
+ p0=q0+q7;p1=q1+q6;p2=q2+q5;p3=q3+q4;
+ p4=hcos_16_down[0]*(q0-q7);p5=hcos_16_down[1]*(q1-q6);
+ p6=hcos_16_down[2]*(q2-q5);p7=hcos_16_down[3]*(q3-q4);
+ p8=q8+qf;p9=q9+qe;pa=qa+qd;pb=qb+qc;
+ pc=hcos_16_down[0]*(q8-qf);pd=hcos_16_down[1]*(q9-qe);
+ pe=hcos_16_down[2]*(qa-qd);pf=hcos_16_down[3]*(qb-qc);
+
+ q0=p0+p3;q1=p1+p2;q2=hcos_8_down[0]*(p0-p3);q3=hcos_8_down[1]*(p1-p2);
+ q4=p4+p7;q5=p5+p6;q6=hcos_8_down[0]*(p4-p7);q7=hcos_8_down[1]*(p5-p6);
+ q8=p8+pb;q9=p9+pa;qa=hcos_8_down[0]*(p8-pb);qb=hcos_8_down[1]*(p9-pa);
+ qc=pc+pf;qd=pd+pe;qe=hcos_8_down[0]*(pc-pf);qf=hcos_8_down[1]*(pd-pe);
+
+ p0=q0+q1;p1=hcos_4_down*(q0-q1);p2=q2+q3;p3=hcos_4_down*(q2-q3);
+ p4=q4+q5;p5=hcos_4_down*(q4-q5);p6=q6+q7;p7=hcos_4_down*(q6-q7);
+ p8=q8+q9;p9=hcos_4_down*(q8-q9);pa=qa+qb;pb=hcos_4_down*(qa-qb);
+ pc=qc+qd;pd=hcos_4_down*(qc-qd);pe=qe+qf;pf=hcos_4_down*(qe-qf);
+
+ {
+ register REAL tmp;
+
+ tmp=p6+p7;
+ OUT2(36)=-(p5+tmp);
+ OUT2(44)=-(p4+tmp);
+ tmp=pb+pf;
+ OUT1(10,tmp);
+ OUT1(6,pd+tmp);
+ tmp=pe+pf;
+ OUT2(46)=-(p8+pc+tmp);
+ OUT2(34)=-(p9+pd+tmp);
+ tmp+=pa+pb;
+ OUT2(38)=-(pd+tmp);
+ OUT2(42)=-(pc+tmp);
+ OUT1(2,p9+pd+pf);
+ OUT1(4,p5+p7);
+ OUT2(48)=-p0;
+ out2[0]=-(out1[0]=p1);
+ OUT1( 8,p3);
+ OUT1(12,p7);
+ OUT1(14,pf);
+ OUT2(40)=-(p2+p3);
+ }
+
+ {
+ register REAL *x=fraction;
+
+ /* p0=hcos_64_down[ 0]*(x[ 0]-x[31]);p1=hcos_64_down[ 1]*(x[ 1]-x[30]);
+ p2=hcos_64_down[ 2]*(x[ 2]-x[29]);p3=hcos_64_down[ 3]*(x[ 3]-x[28]);
+ p4=hcos_64_down[ 4]*(x[ 4]-x[27]);p5=hcos_64_down[ 5]*(x[ 5]-x[26]);
+ p6=hcos_64_down[ 6]*(x[ 6]-x[25]);p7=hcos_64_down[ 7]*(x[ 7]-x[24]);
+ p8=hcos_64_down[ 8]*(x[ 8]-x[23]);p9=hcos_64_down[ 9]*(x[ 9]-x[22]);
+ pa=hcos_64_down[10]*(x[10]-x[21]);pb=hcos_64_down[11]*(x[11]-x[20]);
+ pc=hcos_64_down[12]*(x[12]-x[19]);pd=hcos_64_down[13]*(x[13]-x[18]);
+ pe=hcos_64_down[14]*(x[14]-x[17]);pf=hcos_64_down[15]*(x[15]-x[16]); */
+
+ p0=hcos_64_down[ 0]*x[ 0];p1=hcos_64_down[ 1]*x[ 1];
+ p2=hcos_64_down[ 2]*x[ 2];p3=hcos_64_down[ 3]*x[ 3];
+ p4=hcos_64_down[ 4]*x[ 4];p5=hcos_64_down[ 5]*x[ 5];
+ p6=hcos_64_down[ 6]*x[ 6];p7=hcos_64_down[ 7]*x[ 7];
+ p8=hcos_64_down[ 8]*x[ 8];p9=hcos_64_down[ 9]*x[ 9];
+ pa=hcos_64_down[10]*x[10];pb=hcos_64_down[11]*x[11];
+ pc=hcos_64_down[12]*x[12];pd=hcos_64_down[13]*x[13];
+ pe=hcos_64_down[14]*x[14];pf=hcos_64_down[15]*x[15];
+ }
+
+ q0=p0+pf;q1=p1+pe;q2=p2+pd;q3=p3+pc;
+ q4=p4+pb;q5=p5+pa;q6=p6+p9;q7=p7+p8;
+ q8=hcos_32_down[0]*(p0-pf);q9=hcos_32_down[1]*(p1-pe);
+ qa=hcos_32_down[2]*(p2-pd);qb=hcos_32_down[3]*(p3-pc);
+ qc=hcos_32_down[4]*(p4-pb);qd=hcos_32_down[5]*(p5-pa);
+ qe=hcos_32_down[6]*(p6-p9);qf=hcos_32_down[7]*(p7-p8);
+
+ p0=q0+q7;p1=q1+q6;p2=q2+q5;p3=q3+q4;
+ p4=hcos_16_down[0]*(q0-q7);p5=hcos_16_down[1]*(q1-q6);
+ p6=hcos_16_down[2]*(q2-q5);p7=hcos_16_down[3]*(q3-q4);
+ p8=q8+qf;p9=q9+qe;pa=qa+qd;pb=qb+qc;
+ pc=hcos_16_down[0]*(q8-qf);pd=hcos_16_down[1]*(q9-qe);
+ pe=hcos_16_down[2]*(qa-qd);pf=hcos_16_down[3]*(qb-qc);
+
+ q0=p0+p3;q1=p1+p2;q2=hcos_8_down[0]*(p0-p3);q3=hcos_8_down[1]*(p1-p2);
+ q4=p4+p7;q5=p5+p6;q6=hcos_8_down[0]*(p4-p7);q7=hcos_8_down[1]*(p5-p6);
+ q8=p8+pb;q9=p9+pa;qa=hcos_8_down[0]*(p8-pb);qb=hcos_8_down[1]*(p9-pa);
+ qc=pc+pf;qd=pd+pe;qe=hcos_8_down[0]*(pc-pf);qf=hcos_8_down[1]*(pd-pe);
+
+ p0=q0+q1;p1=hcos_4_down*(q0-q1);
+ p2=q2+q3;p3=hcos_4_down*(q2-q3);
+ p4=q4+q5;p5=hcos_4_down*(q4-q5);
+ p6=q6+q7;p7=hcos_4_down*(q6-q7);
+ p8=q8+q9;p9=hcos_4_down*(q8-q9);
+ pa=qa+qb;pb=hcos_4_down*(qa-qb);
+ pc=qc+qd;pd=hcos_4_down*(qc-qd);
+ pe=qe+qf;pf=hcos_4_down*(qe-qf);
+
+ {
+ REAL tmp;
+
+ tmp=pd+pf;
+ OUT1(5,p5+p7+pb+tmp);
+ tmp+=p9;
+ OUT1(1,p1+tmp);
+ OUT2(33)=-(p1+pe+tmp);
+ tmp+=p5+p7;
+ OUT1(3,tmp);
+ OUT2(35)=-(p6+pe+tmp);
+ tmp=pa+pb+pc+pd+pe+pf;
+ OUT2(39)=-(p2+p3+tmp-pc);
+ OUT2(43)=-(p4+p6+p7+tmp-pd);
+ OUT2(37)=-(p5+p6+p7+tmp-pc);
+ OUT2(41)=-(p2+p3+tmp-pd);
+ tmp=p8+pc+pe+pf;
+ OUT2(47)=-(p0+tmp);
+ OUT2(45)=-(p4+p6+p7+tmp);
+ tmp=pb+pf;
+ OUT1(11,p7+tmp);
+ tmp+=p3;
+ OUT1( 9,tmp);
+ OUT1( 7,pd+tmp);
+ OUT1(13,p7+pf);
+ OUT1(15,pf);
+ }
+}
+
diff --git a/mpeglib/lib/splay/dump.cpp b/mpeglib/lib/splay/dump.cpp
new file mode 100644
index 00000000..62551194
--- /dev/null
+++ b/mpeglib/lib/splay/dump.cpp
@@ -0,0 +1,157 @@
+/*
+ frame dumper
+ 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
+
+ */
+
+
+typedef float REAL;
+
+#define SSLIMIT 18
+#define SBLIMIT 32
+
+
+
+#include "dump.h"
+#include <stdio.h>
+
+
+Dump::Dump() {
+
+}
+
+
+Dump::~Dump() {
+}
+
+
+void Dump::dump(REAL out[SBLIMIT][SSLIMIT]) {
+ FILE* f=fopen("dump.raw","a+");
+ int i;
+ int j;
+ for(i=0;i<SBLIMIT;i++) {
+ fprintf(f,"Line:%d\n",i);
+ for(j=0;j<SSLIMIT;j++) {
+ fprintf(f,"%.25f\n",out[i][j]);
+ }
+ }
+ fclose(f);
+}
+
+void Dump::dump(REAL out[SBLIMIT*SSLIMIT]) {
+ FILE* f=fopen("dump.raw","a+");
+ int i;
+ int line=0;
+ for(i=0;i<SBLIMIT*SSLIMIT;i++) {
+ if ( (i % SSLIMIT) == 0) {
+ fprintf(f,"Line:%d\n",line++);
+ }
+ fprintf(f,"%.25f\n",out[i]);
+ }
+ fclose(f);
+}
+
+void Dump::dump2(REAL out[SSLIMIT*SBLIMIT]) {
+ FILE* f=fopen("dump.raw","a+");
+ int i;
+ int j;
+ int line=0;
+ for(i=0;i<SSLIMIT;i++) {
+ fprintf(f,"Line:%d\n",line++);
+ for(j=0;j<SBLIMIT;j++) {
+ fprintf(f,"%.25f\n",out[i*SBLIMIT+j]);
+ }
+ }
+ fclose(f);
+}
+
+void Dump::dump(REAL out[SSLIMIT][SBLIMIT]) {
+ FILE* f=fopen("dump.raw","a+");
+ int i;
+ int j;
+ for(i=0;i<SBLIMIT;i++) {
+ fprintf(f,"Line:%d\n",i);
+ for(j=0;j<SSLIMIT;j++) {
+ fprintf(f,"%.25f\n",out[j][i]);
+ }
+ }
+ fclose(f);
+}
+
+void Dump::dump(int out[SBLIMIT][SSLIMIT]) {
+ FILE* f=fopen("dump.raw","a+");
+ int i;
+ int j;
+ for(i=0;i<SBLIMIT;i++) {
+ fprintf(f,"Line:%d\n",i);
+ for(j=0;j<SSLIMIT;j++) {
+ if (out[i][j] == 0) {
+ fprintf(f," %d ",out[i][j]);
+ continue;
+ }
+ if (out[i][j] < 0) {
+ fprintf(f," -x");
+ continue;
+ }
+ fprintf(f," +x");
+
+ }
+ fprintf(f," \n");
+
+ }
+ fclose(f);
+}
+
+void Dump::dump(char* ptr,int len,int ldelete) {
+ FILE* f;
+ if (ldelete) {
+ f=fopen("/tmp/dump.raw","w+");
+ } else {
+ f=fopen("/tmp/dump.raw","a+");
+ }
+ fwrite(ptr,len,1,f);
+ fclose(f);
+}
+
+
+void Dump::scale_zero(layer3scalefactor* out) {
+
+ int i;
+ int j;
+
+ for(i=0;i<23;i++) {
+ out->l[i]=0;
+ }
+
+ for(i=0;i<3;i++) {
+ for(j=0;j<13;j++) {
+ out->s[i][j]=0;
+ }
+ }
+}
+
+
+void Dump::dump(layer3scalefactor* out) {
+ FILE* f=fopen("dump.raw","a+");
+ int i;
+ int j;
+
+ for(i=0;i<23;i++) {
+ fprintf(f,"l[%d]=%d\n",i,out->l[i]);
+ }
+
+ for(i=0;i<3;i++) {
+ for(j=0;j<13;j++) {
+ fprintf(f,"s[%d][%d]=%d\n",i,j,out->s[i][j]);
+ }
+ }
+ fprintf(f,"---------\n");
+
+ fclose(f);
+}
diff --git a/mpeglib/lib/splay/dump.h b/mpeglib/lib/splay/dump.h
new file mode 100644
index 00000000..47ef4d48
--- /dev/null
+++ b/mpeglib/lib/splay/dump.h
@@ -0,0 +1,36 @@
+/*
+ frame dumper
+ 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 __DUMP_H
+#define __DUMP_H
+
+#include "mpegsound.h"
+
+class Dump {
+
+ public:
+ Dump();
+ ~Dump();
+
+ void dump(REAL out[SBLIMIT][SSLIMIT]);
+ void dump(REAL out[SBLIMIT*SSLIMIT]);
+ void dump2(REAL out[SSLIMIT*SBLIMIT]);
+ void dump(REAL out[SSLIMIT][SBLIMIT]);
+ void dump(int out[SBLIMIT][SSLIMIT]);
+ void dump(layer3scalefactor* out);
+ void dump(char* prt,int len,int ldelete=false);
+ void scale_zero(layer3scalefactor* out);
+
+
+};
+#endif
diff --git a/mpeglib/lib/splay/dxHead.cpp b/mpeglib/lib/splay/dxHead.cpp
new file mode 100644
index 00000000..a96bb553
--- /dev/null
+++ b/mpeglib/lib/splay/dxHead.cpp
@@ -0,0 +1,129 @@
+/*---- DXhead.c --------------------------------------------
+
+decoder MPEG Layer III
+handle Xing header
+mod 12/7/98 add vbr scale
+
+Copyright 1998 Xing Technology Corp.
+-----------------------------------------------------------*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <float.h>
+#include <math.h>
+#include "dxHead.h"
+
+// 4 Xing
+// 4 flags
+// 4 frames
+// 4 bytes
+// 100 toc
+
+/*-------------------------------------------------------------*/
+static int ExtractI4(unsigned char *buf)
+{
+int x;
+// big endian extract
+
+x = buf[0];
+x <<= 8;
+x |= buf[1];
+x <<= 8;
+x |= buf[2];
+x <<= 8;
+x |= buf[3];
+
+return x;
+}
+/*-------------------------------------------------------------*/
+int GetXingHeader(XHEADDATA *X, unsigned char *buf)
+{
+int i, head_flags;
+int h_id, h_mode, h_sr_index;
+static const int sr_table[4] = { 44100, 48000, 32000, 99999 };
+
+// get Xing header data
+
+
+X->flags = 0; // clear to null incase fail
+
+
+// get selected MPEG header data
+h_id = (buf[1] >> 3) & 1;
+h_sr_index = (buf[2] >> 2) & 3;
+h_mode = (buf[3] >> 6) & 3;
+
+
+// determine offset of header
+if( h_id ) { // mpeg1
+ if( h_mode != 3 ) buf+=(32+4);
+ else buf+=(17+4);
+}
+else { // mpeg2
+ if( h_mode != 3 ) buf+=(17+4);
+ else buf+=(9+4);
+}
+
+if( buf[0] != 'X' ) return 0; // fail
+if( buf[1] != 'i' ) return 0; // header not found
+if( buf[2] != 'n' ) return 0;
+if( buf[3] != 'g' ) return 0;
+buf+=4;
+
+X->h_id = h_id;
+X->samprate = sr_table[h_sr_index];
+if( h_id == 0 ) X->samprate >>= 1;
+
+head_flags = X->flags = ExtractI4(buf); buf+=4; // get flags
+
+if( head_flags & FRAMES_FLAG ) {X->frames = ExtractI4(buf); buf+=4;}
+if( head_flags & BYTES_FLAG ) {X->bytes = ExtractI4(buf); buf+=4;}
+
+if( head_flags & TOC_FLAG ) {
+ if( X->toc != NULL ) {
+ for(i=0;i<100;i++) X->toc[i] = buf[i];
+ }
+ buf+=100;
+}
+
+X->vbr_scale = -1;
+if( head_flags & VBR_SCALE_FLAG ) {X->vbr_scale = ExtractI4(buf); buf+=4;}
+
+//if( X->toc != NULL ) {
+//for(i=0;i<100;i++) {
+// if( (i%10) == 0 ) printf("\n");
+// printf(" %3d", (int)(X->toc[i]));
+//}
+//}
+
+return 1; // success
+}
+/*-------------------------------------------------------------*/
+int SeekPoint(unsigned char TOC[100], int file_bytes, float percent)
+{
+// interpolate in TOC to get file seek point in bytes
+int a, seekpoint;
+float fa, fb, fx;
+
+
+if( percent < 0.0f ) percent = 0.0f;
+if( percent > 100.0f ) percent = 100.0f;
+
+a = (int)percent;
+if( a > 99 ) a = 99;
+fa = TOC[a];
+if( a < 99 ) {
+ fb = TOC[a+1];
+}
+else {
+ fb = 256.0f;
+}
+
+fx = fa + (fb-fa)*(percent-a);
+//printf("%f ....... %f ...... %f\n",fa,fb,fx);
+
+seekpoint = (int)((1.0f/256.0f)*fx*file_bytes);
+
+
+return seekpoint;
+}
+/*-------------------------------------------------------------*/
diff --git a/mpeglib/lib/splay/dxHead.h b/mpeglib/lib/splay/dxHead.h
new file mode 100644
index 00000000..da0f2eff
--- /dev/null
+++ b/mpeglib/lib/splay/dxHead.h
@@ -0,0 +1,66 @@
+/*---- DXhead.h -------------------------------------------
+
+
+decoder MPEG Layer III
+
+handle Xing header
+
+
+Copyright 1998 Xing Technology Corp.
+-----------------------------------------------------------*/
+// A Xing header may be present in the ancillary
+// data field of the first frame of an mp3 bitstream
+// The Xing header (optionally) contains
+// frames total number of audio frames in the bitstream
+// bytes total number of bytes in the bitstream
+// toc table of contents
+
+// toc (table of contents^) gives seek points
+// for random access
+// the ith entry determines the seek point for
+// i-percent duration
+// seek point in bytes = (toc[i]/256.0) * total_bitstream_bytes
+// e.g. half duration seek point = (toc[50]/256.0) * total_bitstream_bytes
+
+#ifndef __DXHEAD_H
+#define __DXHEAD_H
+
+#define FRAMES_FLAG 0x0001
+#define BYTES_FLAG 0x0002
+#define TOC_FLAG 0x0004
+#define VBR_SCALE_FLAG 0x0008
+
+#define FRAMES_AND_BYTES (FRAMES_FLAG | BYTES_FLAG)
+
+// structure to receive extracted header
+// toc may be NULL
+
+typedef struct XHEADDATA_s {
+ int h_id; // from MPEG header, 0=MPEG2, 1=MPEG1
+ int samprate; // determined from MPEG header
+ int flags; // from Xing header data
+ int frames; // total bit stream frames from Xing header data
+ int bytes; // total bit stream bytes from Xing header data
+ int vbr_scale; // encoded vbr scale from Xing header data
+ unsigned char *toc; // pointer to unsigned char toc_buffer[100]
+ // may be NULL if toc not desired
+} XHEADDATA;
+
+int GetXingHeader(XHEADDATA *X, unsigned char *buf);
+
+// return 0=fail, 1=success
+// X structure to receive header data (output)
+// buf bitstream input
+
+
+int SeekPoint(unsigned char TOC[100], int file_bytes, float percent);
+// return seekpoint in bytes (may be at eof if percent=100.0)
+// TOC = table of contents from Xing header
+// file_bytes = number of bytes in mp3 file
+// percent = play time percentage of total playtime. May be
+// fractional (e.g. 87.245)
+
+
+#endif
+
+
diff --git a/mpeglib/lib/splay/huffmanlookup.cpp b/mpeglib/lib/splay/huffmanlookup.cpp
new file mode 100644
index 00000000..e4b37453
--- /dev/null
+++ b/mpeglib/lib/splay/huffmanlookup.cpp
@@ -0,0 +1,120 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library 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 library 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 library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "huffmanlookup.h"
+#include <assert.h>
+
+
+
+
+struct HuffmanLookup::decodeData HuffmanLookup::qdecode[32][256];
+/* for initialization */
+static HuffmanLookup l;
+
+HuffmanLookup::HuffmanLookup()
+{
+ int table,p,x,y;
+
+ for(table = 0; table < 32; table++)
+ {
+ // 8 bits pattern
+ for(p = 0; p < 256; p++)
+ {
+ bits = 24;
+ pattern = (p << 16);
+
+ huffmandecoder_1(&Mpegtoraw::ht[table], &x,&y);
+
+ int used = 24 - bits;
+ qdecode[table][p].skip = (used <= 8)?used:0;
+ qdecode[table][p].x = x;
+ qdecode[table][p].y = y;
+ }
+ }
+}
+
+int HuffmanLookup::wgetbit()
+{
+ return (pattern >> --bits) & 1;
+}
+
+int HuffmanLookup::wgetbits (int b)
+{
+ bits -= b;
+ return (pattern >> bits) & ((1 << b) - 1);
+}
+
+void HuffmanLookup::huffmandecoder_1(const HUFFMANCODETABLE *h, int *x, int *y)
+{
+ typedef unsigned int HUFFBITS;
+
+ HUFFBITS level=(1<<(sizeof(HUFFBITS)*8-1));
+ int point=0;
+ /* Lookup in Huffman table. */
+ for(;;)
+ {
+ if(h->val[point][0]==0)
+ { /*end of tree*/
+ int xx,yy;
+
+ xx=h->val[point][1]>>4;
+ yy=h->val[point][1]&0xf;
+
+ if(h->linbits)
+ {
+ if((h->xlen)==(unsigned)xx)xx+=wgetbits(h->linbits);
+ if(xx)if(wgetbit())xx=-xx;
+ if((h->ylen)==(unsigned)yy)yy+=wgetbits(h->linbits);
+ if(yy)if(wgetbit())yy=-yy;
+ }
+ else
+ {
+ if(xx)if(wgetbit())xx=-xx;
+ if(yy)if(wgetbit())yy=-yy;
+ }
+ *x=xx;*y=yy;
+ break;
+ }
+
+ point+=h->val[point][wgetbit()];
+
+ level>>=1;
+ if(!(level || ((unsigned)point<Mpegtoraw::ht->treelen)))
+ {
+ register int xx,yy;
+
+ xx=(h->xlen<<1);// set x and y to a medium value as a simple concealment
+ yy=(h->ylen<<1);
+
+ // h->xlen and h->ylen can't be 1 under tablename 32
+ // if(xx)
+ if(wgetbit())xx=-xx;
+ // if(yy)
+ if(wgetbit())yy=-yy;
+
+ *x=xx;*y=yy;
+ break;
+ }
+ }
+}
+
+
diff --git a/mpeglib/lib/splay/huffmanlookup.h b/mpeglib/lib/splay/huffmanlookup.h
new file mode 100644
index 00000000..a5bdb26c
--- /dev/null
+++ b/mpeglib/lib/splay/huffmanlookup.h
@@ -0,0 +1,57 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library 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 library 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 library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef __HUFFMANLOOKUP_H
+#define __HUFFMANLOOKUP_H
+#include "mpegsound.h"
+
+/*
+ * This class speeds up the huffman table decoding by largely replacing it
+ * by a table lookup. It uses the fact that the huffman tables don't change,
+ * and that given a byte of the bitstream, we can predict what the result
+ * will be (without reading it bit by bit).
+ */
+
+class HuffmanLookup {
+private:
+ long pattern, bits;
+ int wgetbit();
+ int wgetbits (int b);
+ void huffmandecoder_1(const HUFFMANCODETABLE *h,int *x, int *y);
+
+ ATTR_ALIGN(64) static struct decodeData {
+ int x : 8;
+ int y : 8;
+ int skip : 16;
+ } qdecode[32][256];
+public:
+ HuffmanLookup();
+
+ static int decode(int table, int pattern, int* x, int* y)
+ {
+ *x = qdecode[table][pattern].x;
+ *y = qdecode[table][pattern].y;
+ return qdecode[table][pattern].skip;
+ }
+};
+
+#endif
diff --git a/mpeglib/lib/splay/huffmantable.cpp b/mpeglib/lib/splay/huffmantable.cpp
new file mode 100644
index 00000000..a1fe20e5
--- /dev/null
+++ b/mpeglib/lib/splay/huffmantable.cpp
@@ -0,0 +1,584 @@
+/* MPEG/WAVE Sound library
+
+ (C) 1997 by Jung woo-jae */
+
+// Huffmantable.cc
+// It contains initialized huffman table for MPEG layer 3
+
+
+#include "mpegsound.h"
+
+static const unsigned int
+htd01[ 7][2]={{ 2, 1},{ 0, 0},{ 2, 1},{ 0, 16},{ 2, 1},{ 0, 1},
+ { 0, 17}},
+
+htd02[ 17][2]={{ 2, 1},{ 0, 0},{ 4, 1},{ 2, 1},{ 0, 16},{ 0, 1},
+ { 2, 1},{ 0, 17},{ 4, 1},{ 2, 1},{ 0, 32},{ 0, 33},
+ { 2, 1},{ 0, 18},{ 2, 1},{ 0, 2},{ 0, 34}},
+
+htd03[ 17][2]={{ 4, 1},{ 2, 1},{ 0, 0},{ 0, 1},{ 2, 1},{ 0, 17},
+ { 2, 1},{ 0, 16},{ 4, 1},{ 2, 1},{ 0, 32},{ 0, 33},
+ { 2, 1},{ 0, 18},{ 2, 1},{ 0, 2},{ 0, 34}},
+
+htd05[ 31][2]={{ 2, 1},{ 0, 0},{ 4, 1},{ 2, 1},{ 0, 16},{ 0, 1},
+ { 2, 1},{ 0, 17},{ 8, 1},{ 4, 1},{ 2, 1},{ 0, 32},
+ { 0, 2},{ 2, 1},{ 0, 33},{ 0, 18},{ 8, 1},{ 4, 1},
+ { 2, 1},{ 0, 34},{ 0, 48},{ 2, 1},{ 0, 3},{ 0, 19},
+ { 2, 1},{ 0, 49},{ 2, 1},{ 0, 50},{ 2, 1},{ 0, 35},
+ { 0, 51}},
+
+htd06[ 31][2]={{ 6, 1},{ 4, 1},{ 2, 1},{ 0, 0},{ 0, 16},{ 0, 17},
+ { 6, 1},{ 2, 1},{ 0, 1},{ 2, 1},{ 0, 32},{ 0, 33},
+ { 6, 1},{ 2, 1},{ 0, 18},{ 2, 1},{ 0, 2},{ 0, 34},
+ { 4, 1},{ 2, 1},{ 0, 49},{ 0, 19},{ 4, 1},{ 2, 1},
+ { 0, 48},{ 0, 50},{ 2, 1},{ 0, 35},{ 2, 1},{ 0, 3},
+ { 0, 51}},
+
+htd07[ 71][2]={{ 2, 1},{ 0, 0},{ 4, 1},{ 2, 1},{ 0, 16},{ 0, 1},
+ { 8, 1},{ 2, 1},{ 0, 17},{ 4, 1},{ 2, 1},{ 0, 32},
+ { 0, 2},{ 0, 33},{ 18, 1},{ 6, 1},{ 2, 1},{ 0, 18},
+ { 2, 1},{ 0, 34},{ 0, 48},{ 4, 1},{ 2, 1},{ 0, 49},
+ { 0, 19},{ 4, 1},{ 2, 1},{ 0, 3},{ 0, 50},{ 2, 1},
+ { 0, 35},{ 0, 4},{ 10, 1},{ 4, 1},{ 2, 1},{ 0, 64},
+ { 0, 65},{ 2, 1},{ 0, 20},{ 2, 1},{ 0, 66},{ 0, 36},
+ { 12, 1},{ 6, 1},{ 4, 1},{ 2, 1},{ 0, 51},{ 0, 67},
+ { 0, 80},{ 4, 1},{ 2, 1},{ 0, 52},{ 0, 5},{ 0, 81},
+ { 6, 1},{ 2, 1},{ 0, 21},{ 2, 1},{ 0, 82},{ 0, 37},
+
+ { 4, 1},{ 2, 1},{ 0, 68},{ 0, 53},{ 4, 1},{ 2, 1},
+ { 0, 83},{ 0, 84},{ 2, 1},{ 0, 69},{ 0, 85}},
+
+htd08[ 71][2]={{ 6, 1},{ 2, 1},{ 0, 0},{ 2, 1},{ 0, 16},{ 0, 1},
+ { 2, 1},{ 0, 17},{ 4, 1},{ 2, 1},{ 0, 33},{ 0, 18},
+ { 14, 1},{ 4, 1},{ 2, 1},{ 0, 32},{ 0, 2},{ 2, 1},
+ { 0, 34},{ 4, 1},{ 2, 1},{ 0, 48},{ 0, 3},{ 2, 1},
+ { 0, 49},{ 0, 19},{ 14, 1},{ 8, 1},{ 4, 1},{ 2, 1},
+ { 0, 50},{ 0, 35},{ 2, 1},{ 0, 64},{ 0, 4},{ 2, 1},
+ { 0, 65},{ 2, 1},{ 0, 20},{ 0, 66},{ 12, 1},{ 6, 1},
+ { 2, 1},{ 0, 36},{ 2, 1},{ 0, 51},{ 0, 80},{ 4, 1},
+ { 2, 1},{ 0, 67},{ 0, 52},{ 0, 81},{ 6, 1},{ 2, 1},
+ { 0, 21},{ 2, 1},{ 0, 5},{ 0, 82},{ 6, 1},{ 2, 1},
+
+ { 0, 37},{ 2, 1},{ 0, 68},{ 0, 53},{ 2, 1},{ 0, 83},
+ { 2, 1},{ 0, 69},{ 2, 1},{ 0, 84},{ 0, 85}},
+
+htd09[ 71][2]={{ 8, 1},{ 4, 1},{ 2, 1},{ 0, 0},{ 0, 16},{ 2, 1},
+ { 0, 1},{ 0, 17},{ 10, 1},{ 4, 1},{ 2, 1},{ 0, 32},
+ { 0, 33},{ 2, 1},{ 0, 18},{ 2, 1},{ 0, 2},{ 0, 34},
+ { 12, 1},{ 6, 1},{ 4, 1},{ 2, 1},{ 0, 48},{ 0, 3},
+ { 0, 49},{ 2, 1},{ 0, 19},{ 2, 1},{ 0, 50},{ 0, 35},
+ { 12, 1},{ 4, 1},{ 2, 1},{ 0, 65},{ 0, 20},{ 4, 1},
+ { 2, 1},{ 0, 64},{ 0, 51},{ 2, 1},{ 0, 66},{ 0, 36},
+ { 10, 1},{ 6, 1},{ 4, 1},{ 2, 1},{ 0, 4},{ 0, 80},
+ { 0, 67},{ 2, 1},{ 0, 52},{ 0, 81},{ 8, 1},{ 4, 1},
+ { 2, 1},{ 0, 21},{ 0, 82},{ 2, 1},{ 0, 37},{ 0, 68},
+
+ { 6, 1},{ 4, 1},{ 2, 1},{ 0, 5},{ 0, 84},{ 0, 83},
+ { 2, 1},{ 0, 53},{ 2, 1},{ 0, 69},{ 0, 85}},
+
+htd10[127][2]={{ 2, 1},{ 0, 0},{ 4, 1},{ 2, 1},{ 0, 16},{ 0, 1},
+ { 10, 1},{ 2, 1},{ 0, 17},{ 4, 1},{ 2, 1},{ 0, 32},
+ { 0, 2},{ 2, 1},{ 0, 33},{ 0, 18},{ 28, 1},{ 8, 1},
+ { 4, 1},{ 2, 1},{ 0, 34},{ 0, 48},{ 2, 1},{ 0, 49},
+ { 0, 19},{ 8, 1},{ 4, 1},{ 2, 1},{ 0, 3},{ 0, 50},
+ { 2, 1},{ 0, 35},{ 0, 64},{ 4, 1},{ 2, 1},{ 0, 65},
+ { 0, 20},{ 4, 1},{ 2, 1},{ 0, 4},{ 0, 51},{ 2, 1},
+ { 0, 66},{ 0, 36},{ 28, 1},{ 10, 1},{ 6, 1},{ 4, 1},
+ { 2, 1},{ 0, 80},{ 0, 5},{ 0, 96},{ 2, 1},{ 0, 97},
+ { 0, 22},{ 12, 1},{ 6, 1},{ 4, 1},{ 2, 1},{ 0, 67},
+
+ { 0, 52},{ 0, 81},{ 2, 1},{ 0, 21},{ 2, 1},{ 0, 82},
+ { 0, 37},{ 4, 1},{ 2, 1},{ 0, 38},{ 0, 54},{ 0,113},
+ { 20, 1},{ 8, 1},{ 2, 1},{ 0, 23},{ 4, 1},{ 2, 1},
+ { 0, 68},{ 0, 83},{ 0, 6},{ 6, 1},{ 4, 1},{ 2, 1},
+ { 0, 53},{ 0, 69},{ 0, 98},{ 2, 1},{ 0,112},{ 2, 1},
+ { 0, 7},{ 0,100},{ 14, 1},{ 4, 1},{ 2, 1},{ 0,114},
+ { 0, 39},{ 6, 1},{ 2, 1},{ 0, 99},{ 2, 1},{ 0, 84},
+ { 0, 85},{ 2, 1},{ 0, 70},{ 0,115},{ 8, 1},{ 4, 1},
+ { 2, 1},{ 0, 55},{ 0,101},{ 2, 1},{ 0, 86},{ 0,116},
+ { 6, 1},{ 2, 1},{ 0, 71},{ 2, 1},{ 0,102},{ 0,117},
+
+ { 4, 1},{ 2, 1},{ 0, 87},{ 0,118},{ 2, 1},{ 0,103},
+ { 0,119}},
+
+htd11[127][2]={{ 6, 1},{ 2, 1},{ 0, 0},{ 2, 1},{ 0, 16},{ 0, 1},
+ { 8, 1},{ 2, 1},{ 0, 17},{ 4, 1},{ 2, 1},{ 0, 32},
+ { 0, 2},{ 0, 18},{ 24, 1},{ 8, 1},{ 2, 1},{ 0, 33},
+ { 2, 1},{ 0, 34},{ 2, 1},{ 0, 48},{ 0, 3},{ 4, 1},
+ { 2, 1},{ 0, 49},{ 0, 19},{ 4, 1},{ 2, 1},{ 0, 50},
+ { 0, 35},{ 4, 1},{ 2, 1},{ 0, 64},{ 0, 4},{ 2, 1},
+ { 0, 65},{ 0, 20},{ 30, 1},{ 16, 1},{ 10, 1},{ 4, 1},
+ { 2, 1},{ 0, 66},{ 0, 36},{ 4, 1},{ 2, 1},{ 0, 51},
+ { 0, 67},{ 0, 80},{ 4, 1},{ 2, 1},{ 0, 52},{ 0, 81},
+ { 0, 97},{ 6, 1},{ 2, 1},{ 0, 22},{ 2, 1},{ 0, 6},
+
+ { 0, 38},{ 2, 1},{ 0, 98},{ 2, 1},{ 0, 21},{ 2, 1},
+ { 0, 5},{ 0, 82},{ 16, 1},{ 10, 1},{ 6, 1},{ 4, 1},
+ { 2, 1},{ 0, 37},{ 0, 68},{ 0, 96},{ 2, 1},{ 0, 99},
+ { 0, 54},{ 4, 1},{ 2, 1},{ 0,112},{ 0, 23},{ 0,113},
+ { 16, 1},{ 6, 1},{ 4, 1},{ 2, 1},{ 0, 7},{ 0,100},
+ { 0,114},{ 2, 1},{ 0, 39},{ 4, 1},{ 2, 1},{ 0, 83},
+ { 0, 53},{ 2, 1},{ 0, 84},{ 0, 69},{ 10, 1},{ 4, 1},
+ { 2, 1},{ 0, 70},{ 0,115},{ 2, 1},{ 0, 55},{ 2, 1},
+ { 0,101},{ 0, 86},{ 10, 1},{ 6, 1},{ 4, 1},{ 2, 1},
+ { 0, 85},{ 0, 87},{ 0,116},{ 2, 1},{ 0, 71},{ 0,102},
+
+ { 4, 1},{ 2, 1},{ 0,117},{ 0,118},{ 2, 1},{ 0,103},
+ { 0,119}},
+
+htd12[127][2]={{ 12, 1},{ 4, 1},{ 2, 1},{ 0, 16},{ 0, 1},{ 2, 1},
+ { 0, 17},{ 2, 1},{ 0, 0},{ 2, 1},{ 0, 32},{ 0, 2},
+ { 16, 1},{ 4, 1},{ 2, 1},{ 0, 33},{ 0, 18},{ 4, 1},
+ { 2, 1},{ 0, 34},{ 0, 49},{ 2, 1},{ 0, 19},{ 2, 1},
+ { 0, 48},{ 2, 1},{ 0, 3},{ 0, 64},{ 26, 1},{ 8, 1},
+ { 4, 1},{ 2, 1},{ 0, 50},{ 0, 35},{ 2, 1},{ 0, 65},
+ { 0, 51},{ 10, 1},{ 4, 1},{ 2, 1},{ 0, 20},{ 0, 66},
+ { 2, 1},{ 0, 36},{ 2, 1},{ 0, 4},{ 0, 80},{ 4, 1},
+ { 2, 1},{ 0, 67},{ 0, 52},{ 2, 1},{ 0, 81},{ 0, 21},
+ { 28, 1},{ 14, 1},{ 8, 1},{ 4, 1},{ 2, 1},{ 0, 82},
+
+ { 0, 37},{ 2, 1},{ 0, 83},{ 0, 53},{ 4, 1},{ 2, 1},
+ { 0, 96},{ 0, 22},{ 0, 97},{ 4, 1},{ 2, 1},{ 0, 98},
+ { 0, 38},{ 6, 1},{ 4, 1},{ 2, 1},{ 0, 5},{ 0, 6},
+ { 0, 68},{ 2, 1},{ 0, 84},{ 0, 69},{ 18, 1},{ 10, 1},
+ { 4, 1},{ 2, 1},{ 0, 99},{ 0, 54},{ 4, 1},{ 2, 1},
+ { 0,112},{ 0, 7},{ 0,113},{ 4, 1},{ 2, 1},{ 0, 23},
+ { 0,100},{ 2, 1},{ 0, 70},{ 0,114},{ 10, 1},{ 6, 1},
+ { 2, 1},{ 0, 39},{ 2, 1},{ 0, 85},{ 0,115},{ 2, 1},
+ { 0, 55},{ 0, 86},{ 8, 1},{ 4, 1},{ 2, 1},{ 0,101},
+ { 0,116},{ 2, 1},{ 0, 71},{ 0,102},{ 4, 1},{ 2, 1},
+
+ { 0,117},{ 0, 87},{ 2, 1},{ 0,118},{ 2, 1},{ 0,103},
+ { 0,119}},
+
+htd13[511][2]={{ 2, 1},{ 0, 0},{ 6, 1},{ 2, 1},{ 0, 16},{ 2, 1},
+ { 0, 1},{ 0, 17},{ 28, 1},{ 8, 1},{ 4, 1},{ 2, 1},
+ { 0, 32},{ 0, 2},{ 2, 1},{ 0, 33},{ 0, 18},{ 8, 1},
+ { 4, 1},{ 2, 1},{ 0, 34},{ 0, 48},{ 2, 1},{ 0, 3},
+ { 0, 49},{ 6, 1},{ 2, 1},{ 0, 19},{ 2, 1},{ 0, 50},
+ { 0, 35},{ 4, 1},{ 2, 1},{ 0, 64},{ 0, 4},{ 0, 65},
+ { 70, 1},{ 28, 1},{ 14, 1},{ 6, 1},{ 2, 1},{ 0, 20},
+ { 2, 1},{ 0, 51},{ 0, 66},{ 4, 1},{ 2, 1},{ 0, 36},
+ { 0, 80},{ 2, 1},{ 0, 67},{ 0, 52},{ 4, 1},{ 2, 1},
+ { 0, 81},{ 0, 21},{ 4, 1},{ 2, 1},{ 0, 5},{ 0, 82}, // 60
+
+ { 2, 1},{ 0, 37},{ 2, 1},{ 0, 68},{ 0, 83},{ 14, 1},
+ { 8, 1},{ 4, 1},{ 2, 1},{ 0, 96},{ 0, 6},{ 2, 1},
+ { 0, 97},{ 0, 22},{ 4, 1},{ 2, 1},{ 0,128},{ 0, 8},
+ { 0,129},{ 16, 1},{ 8, 1},{ 4, 1},{ 2, 1},{ 0, 53},
+ { 0, 98},{ 2, 1},{ 0, 38},{ 0, 84},{ 4, 1},{ 2, 1},
+ { 0, 69},{ 0, 99},{ 2, 1},{ 0, 54},{ 0,112},{ 6, 1},
+ { 4, 1},{ 2, 1},{ 0, 7},{ 0, 85},{ 0,113},{ 2, 1},
+ { 0, 23},{ 2, 1},{ 0, 39},{ 0, 55},{ 72, 1},{ 24, 1},
+ { 12, 1},{ 4, 1},{ 2, 1},{ 0, 24},{ 0,130},{ 2, 1},
+ { 0, 40},{ 4, 1},{ 2, 1},{ 0,100},{ 0, 70},{ 0,114}, // 120
+
+ { 8, 1},{ 4, 1},{ 2, 1},{ 0,132},{ 0, 72},{ 2, 1},
+ { 0,144},{ 0, 9},{ 2, 1},{ 0,145},{ 0, 25},{ 24, 1},
+ { 14, 1},{ 8, 1},{ 4, 1},{ 2, 1},{ 0,115},{ 0,101},
+ { 2, 1},{ 0, 86},{ 0,116},{ 4, 1},{ 2, 1},{ 0, 71},
+ { 0,102},{ 0,131},{ 6, 1},{ 2, 1},{ 0, 56},{ 2, 1},
+ { 0,117},{ 0, 87},{ 2, 1},{ 0,146},{ 0, 41},{ 14, 1},
+ { 8, 1},{ 4, 1},{ 2, 1},{ 0,103},{ 0,133},{ 2, 1},
+ { 0, 88},{ 0, 57},{ 2, 1},{ 0,147},{ 2, 1},{ 0, 73},
+ { 0,134},{ 6, 1},{ 2, 1},{ 0,160},{ 2, 1},{ 0,104},
+ { 0, 10},{ 2, 1},{ 0,161},{ 0, 26},{ 68, 1},{ 24, 1}, // 180
+
+ { 12, 1},{ 4, 1},{ 2, 1},{ 0,162},{ 0, 42},{ 4, 1},
+ { 2, 1},{ 0,149},{ 0, 89},{ 2, 1},{ 0,163},{ 0, 58},
+ { 8, 1},{ 4, 1},{ 2, 1},{ 0, 74},{ 0,150},{ 2, 1},
+ { 0,176},{ 0, 11},{ 2, 1},{ 0,177},{ 0, 27},{ 20, 1},
+ { 8, 1},{ 2, 1},{ 0,178},{ 4, 1},{ 2, 1},{ 0,118},
+ { 0,119},{ 0,148},{ 6, 1},{ 4, 1},{ 2, 1},{ 0,135},
+ { 0,120},{ 0,164},{ 4, 1},{ 2, 1},{ 0,105},{ 0,165},
+ { 0, 43},{ 12, 1},{ 6, 1},{ 4, 1},{ 2, 1},{ 0, 90},
+ { 0,136},{ 0,179},{ 2, 1},{ 0, 59},{ 2, 1},{ 0,121},
+ { 0,166},{ 6, 1},{ 4, 1},{ 2, 1},{ 0,106},{ 0,180}, // 240
+
+ { 0,192},{ 4, 1},{ 2, 1},{ 0, 12},{ 0,152},{ 0,193},
+ { 60, 1},{ 22, 1},{ 10, 1},{ 6, 1},{ 2, 1},{ 0, 28},
+ { 2, 1},{ 0,137},{ 0,181},{ 2, 1},{ 0, 91},{ 0,194},
+ { 4, 1},{ 2, 1},{ 0, 44},{ 0, 60},{ 4, 1},{ 2, 1},
+ { 0,182},{ 0,107},{ 2, 1},{ 0,196},{ 0, 76},{ 16, 1},
+ { 8, 1},{ 4, 1},{ 2, 1},{ 0,168},{ 0,138},{ 2, 1},
+ { 0,208},{ 0, 13},{ 2, 1},{ 0,209},{ 2, 1},{ 0, 75},
+ { 2, 1},{ 0,151},{ 0,167},{ 12, 1},{ 6, 1},{ 2, 1},
+ { 0,195},{ 2, 1},{ 0,122},{ 0,153},{ 4, 1},{ 2, 1},
+ { 0,197},{ 0, 92},{ 0,183},{ 4, 1},{ 2, 1},{ 0, 29}, // 300
+
+ { 0,210},{ 2, 1},{ 0, 45},{ 2, 1},{ 0,123},{ 0,211},
+ { 52, 1},{ 28, 1},{ 12, 1},{ 4, 1},{ 2, 1},{ 0, 61},
+ { 0,198},{ 4, 1},{ 2, 1},{ 0,108},{ 0,169},{ 2, 1},
+ { 0,154},{ 0,212},{ 8, 1},{ 4, 1},{ 2, 1},{ 0,184},
+ { 0,139},{ 2, 1},{ 0, 77},{ 0,199},{ 4, 1},{ 2, 1},
+ { 0,124},{ 0,213},{ 2, 1},{ 0, 93},{ 0,224},{ 10, 1},
+ { 4, 1},{ 2, 1},{ 0,225},{ 0, 30},{ 4, 1},{ 2, 1},
+ { 0, 14},{ 0, 46},{ 0,226},{ 8, 1},{ 4, 1},{ 2, 1},
+ { 0,227},{ 0,109},{ 2, 1},{ 0,140},{ 0,228},{ 4, 1},
+ { 2, 1},{ 0,229},{ 0,186},{ 0,240},{ 38, 1},{ 16, 1}, // 360
+
+ { 4, 1},{ 2, 1},{ 0,241},{ 0, 31},{ 6, 1},{ 4, 1},
+ { 2, 1},{ 0,170},{ 0,155},{ 0,185},{ 2, 1},{ 0, 62},
+ { 2, 1},{ 0,214},{ 0,200},{ 12, 1},{ 6, 1},{ 2, 1},
+ { 0, 78},{ 2, 1},{ 0,215},{ 0,125},{ 2, 1},{ 0,171},
+ { 2, 1},{ 0, 94},{ 0,201},{ 6, 1},{ 2, 1},{ 0, 15},
+ { 2, 1},{ 0,156},{ 0,110},{ 2, 1},{ 0,242},{ 0, 47},
+ { 32, 1},{ 16, 1},{ 6, 1},{ 4, 1},{ 2, 1},{ 0,216},
+ { 0,141},{ 0, 63},{ 6, 1},{ 2, 1},{ 0,243},{ 2, 1},
+ { 0,230},{ 0,202},{ 2, 1},{ 0,244},{ 0, 79},{ 8, 1},
+ { 4, 1},{ 2, 1},{ 0,187},{ 0,172},{ 2, 1},{ 0,231}, // 420
+
+ { 0,245},{ 4, 1},{ 2, 1},{ 0,217},{ 0,157},{ 2, 1},
+ { 0, 95},{ 0,232},{ 30, 1},{ 12, 1},{ 6, 1},{ 2, 1},
+ { 0,111},{ 2, 1},{ 0,246},{ 0,203},{ 4, 1},{ 2, 1},
+ { 0,188},{ 0,173},{ 0,218},{ 8, 1},{ 2, 1},{ 0,247},
+ { 4, 1},{ 2, 1},{ 0,126},{ 0,127},{ 0,142},{ 6, 1},
+ { 4, 1},{ 2, 1},{ 0,158},{ 0,174},{ 0,204},{ 2, 1},
+ { 0,248},{ 0,143},{ 18, 1},{ 8, 1},{ 4, 1},{ 2, 1},
+ { 0,219},{ 0,189},{ 2, 1},{ 0,234},{ 0,249},{ 4, 1},
+ { 2, 1},{ 0,159},{ 0,235},{ 2, 1},{ 0,190},{ 2, 1},
+ { 0,205},{ 0,250},{ 14, 1},{ 4, 1},{ 2, 1},{ 0,221}, // 480
+
+ { 0,236},{ 6, 1},{ 4, 1},{ 2, 1},{ 0,233},{ 0,175},
+ { 0,220},{ 2, 1},{ 0,206},{ 0,251},{ 8, 1},{ 4, 1},
+ { 2, 1},{ 0,191},{ 0,222},{ 2, 1},{ 0,207},{ 0,238},
+ { 4, 1},{ 2, 1},{ 0,223},{ 0,239},{ 2, 1},{ 0,255},
+ { 2, 1},{ 0,237},{ 2, 1},{ 0,253},{ 2, 1},{ 0,252},
+ { 0,254}},
+
+htd15[511][2]={{ 16, 1},{ 6, 1},{ 2, 1},{ 0, 0},{ 2, 1},{ 0, 16},
+ { 0, 1},{ 2, 1},{ 0, 17},{ 4, 1},{ 2, 1},{ 0, 32},
+ { 0, 2},{ 2, 1},{ 0, 33},{ 0, 18},{ 50, 1},{ 16, 1},
+ { 6, 1},{ 2, 1},{ 0, 34},{ 2, 1},{ 0, 48},{ 0, 49},
+ { 6, 1},{ 2, 1},{ 0, 19},{ 2, 1},{ 0, 3},{ 0, 64},
+ { 2, 1},{ 0, 50},{ 0, 35},{ 14, 1},{ 6, 1},{ 4, 1},
+ { 2, 1},{ 0, 4},{ 0, 20},{ 0, 65},{ 4, 1},{ 2, 1},
+ { 0, 51},{ 0, 66},{ 2, 1},{ 0, 36},{ 0, 67},{ 10, 1},
+ { 6, 1},{ 2, 1},{ 0, 52},{ 2, 1},{ 0, 80},{ 0, 5},
+ { 2, 1},{ 0, 81},{ 0, 21},{ 4, 1},{ 2, 1},{ 0, 82}, // 60
+
+ { 0, 37},{ 4, 1},{ 2, 1},{ 0, 68},{ 0, 83},{ 0, 97},
+ { 90, 1},{ 36, 1},{ 18, 1},{ 10, 1},{ 6, 1},{ 2, 1},
+ { 0, 53},{ 2, 1},{ 0, 96},{ 0, 6},{ 2, 1},{ 0, 22},
+ { 0, 98},{ 4, 1},{ 2, 1},{ 0, 38},{ 0, 84},{ 2, 1},
+ { 0, 69},{ 0, 99},{ 10, 1},{ 6, 1},{ 2, 1},{ 0, 54},
+ { 2, 1},{ 0,112},{ 0, 7},{ 2, 1},{ 0,113},{ 0, 85},
+ { 4, 1},{ 2, 1},{ 0, 23},{ 0,100},{ 2, 1},{ 0,114},
+ { 0, 39},{ 24, 1},{ 16, 1},{ 8, 1},{ 4, 1},{ 2, 1},
+ { 0, 70},{ 0,115},{ 2, 1},{ 0, 55},{ 0,101},{ 4, 1},
+ { 2, 1},{ 0, 86},{ 0,128},{ 2, 1},{ 0, 8},{ 0,116}, // 120
+
+ { 4, 1},{ 2, 1},{ 0,129},{ 0, 24},{ 2, 1},{ 0,130},
+ { 0, 40},{ 16, 1},{ 8, 1},{ 4, 1},{ 2, 1},{ 0, 71},
+ { 0,102},{ 2, 1},{ 0,131},{ 0, 56},{ 4, 1},{ 2, 1},
+ { 0,117},{ 0, 87},{ 2, 1},{ 0,132},{ 0, 72},{ 6, 1},
+ { 4, 1},{ 2, 1},{ 0,144},{ 0, 25},{ 0,145},{ 4, 1},
+ { 2, 1},{ 0,146},{ 0,118},{ 2, 1},{ 0,103},{ 0, 41},
+ { 92, 1},{ 36, 1},{ 18, 1},{ 10, 1},{ 4, 1},{ 2, 1},
+ { 0,133},{ 0, 88},{ 4, 1},{ 2, 1},{ 0, 9},{ 0,119},
+ { 0,147},{ 4, 1},{ 2, 1},{ 0, 57},{ 0,148},{ 2, 1},
+ { 0, 73},{ 0,134},{ 10, 1},{ 6, 1},{ 2, 1},{ 0,104}, // 180
+
+ { 2, 1},{ 0,160},{ 0, 10},{ 2, 1},{ 0,161},{ 0, 26},
+ { 4, 1},{ 2, 1},{ 0,162},{ 0, 42},{ 2, 1},{ 0,149},
+ { 0, 89},{ 26, 1},{ 14, 1},{ 6, 1},{ 2, 1},{ 0,163},
+ { 2, 1},{ 0, 58},{ 0,135},{ 4, 1},{ 2, 1},{ 0,120},
+ { 0,164},{ 2, 1},{ 0, 74},{ 0,150},{ 6, 1},{ 4, 1},
+ { 2, 1},{ 0,105},{ 0,176},{ 0,177},{ 4, 1},{ 2, 1},
+ { 0, 27},{ 0,165},{ 0,178},{ 14, 1},{ 8, 1},{ 4, 1},
+ { 2, 1},{ 0, 90},{ 0, 43},{ 2, 1},{ 0,136},{ 0,151},
+ { 2, 1},{ 0,179},{ 2, 1},{ 0,121},{ 0, 59},{ 8, 1},
+ { 4, 1},{ 2, 1},{ 0,106},{ 0,180},{ 2, 1},{ 0, 75}, // 240
+
+ { 0,193},{ 4, 1},{ 2, 1},{ 0,152},{ 0,137},{ 2, 1},
+ { 0, 28},{ 0,181},{ 80, 1},{ 34, 1},{ 16, 1},{ 6, 1},
+ { 4, 1},{ 2, 1},{ 0, 91},{ 0, 44},{ 0,194},{ 6, 1},
+ { 4, 1},{ 2, 1},{ 0, 11},{ 0,192},{ 0,166},{ 2, 1},
+ { 0,167},{ 0,122},{ 10, 1},{ 4, 1},{ 2, 1},{ 0,195},
+ { 0, 60},{ 4, 1},{ 2, 1},{ 0, 12},{ 0,153},{ 0,182},
+ { 4, 1},{ 2, 1},{ 0,107},{ 0,196},{ 2, 1},{ 0, 76},
+ { 0,168},{ 20, 1},{ 10, 1},{ 4, 1},{ 2, 1},{ 0,138},
+ { 0,197},{ 4, 1},{ 2, 1},{ 0,208},{ 0, 92},{ 0,209},
+ { 4, 1},{ 2, 1},{ 0,183},{ 0,123},{ 2, 1},{ 0, 29}, // 300
+
+ { 2, 1},{ 0, 13},{ 0, 45},{ 12, 1},{ 4, 1},{ 2, 1},
+ { 0,210},{ 0,211},{ 4, 1},{ 2, 1},{ 0, 61},{ 0,198},
+ { 2, 1},{ 0,108},{ 0,169},{ 6, 1},{ 4, 1},{ 2, 1},
+ { 0,154},{ 0,184},{ 0,212},{ 4, 1},{ 2, 1},{ 0,139},
+ { 0, 77},{ 2, 1},{ 0,199},{ 0,124},{ 68, 1},{ 34, 1},
+ { 18, 1},{ 10, 1},{ 4, 1},{ 2, 1},{ 0,213},{ 0, 93},
+ { 4, 1},{ 2, 1},{ 0,224},{ 0, 14},{ 0,225},{ 4, 1},
+ { 2, 1},{ 0, 30},{ 0,226},{ 2, 1},{ 0,170},{ 0, 46},
+ { 8, 1},{ 4, 1},{ 2, 1},{ 0,185},{ 0,155},{ 2, 1},
+ { 0,227},{ 0,214},{ 4, 1},{ 2, 1},{ 0,109},{ 0, 62}, // 360
+
+ { 2, 1},{ 0,200},{ 0,140},{ 16, 1},{ 8, 1},{ 4, 1},
+ { 2, 1},{ 0,228},{ 0, 78},{ 2, 1},{ 0,215},{ 0,125},
+ { 4, 1},{ 2, 1},{ 0,229},{ 0,186},{ 2, 1},{ 0,171},
+ { 0, 94},{ 8, 1},{ 4, 1},{ 2, 1},{ 0,201},{ 0,156},
+ { 2, 1},{ 0,241},{ 0, 31},{ 6, 1},{ 4, 1},{ 2, 1},
+ { 0,240},{ 0,110},{ 0,242},{ 2, 1},{ 0, 47},{ 0,230},
+ { 38, 1},{ 18, 1},{ 8, 1},{ 4, 1},{ 2, 1},{ 0,216},
+ { 0,243},{ 2, 1},{ 0, 63},{ 0,244},{ 6, 1},{ 2, 1},
+ { 0, 79},{ 2, 1},{ 0,141},{ 0,217},{ 2, 1},{ 0,187},
+ { 0,202},{ 8, 1},{ 4, 1},{ 2, 1},{ 0,172},{ 0,231}, // 420
+
+ { 2, 1},{ 0,126},{ 0,245},{ 8, 1},{ 4, 1},{ 2, 1},
+ { 0,157},{ 0, 95},{ 2, 1},{ 0,232},{ 0,142},{ 2, 1},
+ { 0,246},{ 0,203},{ 34, 1},{ 18, 1},{ 10, 1},{ 6, 1},
+ { 4, 1},{ 2, 1},{ 0, 15},{ 0,174},{ 0,111},{ 2, 1},
+ { 0,188},{ 0,218},{ 4, 1},{ 2, 1},{ 0,173},{ 0,247},
+ { 2, 1},{ 0,127},{ 0,233},{ 8, 1},{ 4, 1},{ 2, 1},
+ { 0,158},{ 0,204},{ 2, 1},{ 0,248},{ 0,143},{ 4, 1},
+ { 2, 1},{ 0,219},{ 0,189},{ 2, 1},{ 0,234},{ 0,249},
+ { 16, 1},{ 8, 1},{ 4, 1},{ 2, 1},{ 0,159},{ 0,220},
+ { 2, 1},{ 0,205},{ 0,235},{ 4, 1},{ 2, 1},{ 0,190}, // 480
+
+ { 0,250},{ 2, 1},{ 0,175},{ 0,221},{ 14, 1},{ 6, 1},
+ { 4, 1},{ 2, 1},{ 0,236},{ 0,206},{ 0,251},{ 4, 1},
+ { 2, 1},{ 0,191},{ 0,237},{ 2, 1},{ 0,222},{ 0,252},
+ { 6, 1},{ 4, 1},{ 2, 1},{ 0,207},{ 0,253},{ 0,238},
+ { 4, 1},{ 2, 1},{ 0,223},{ 0,254},{ 2, 1},{ 0,239},
+ { 0,255}},
+
+htd16[511][2]={{ 2, 1},{ 0, 0},{ 6, 1},{ 2, 1},{ 0, 16},{ 2, 1},
+ { 0, 1},{ 0, 17},{ 42, 1},{ 8, 1},{ 4, 1},{ 2, 1},
+ { 0, 32},{ 0, 2},{ 2, 1},{ 0, 33},{ 0, 18},{ 10, 1},
+ { 6, 1},{ 2, 1},{ 0, 34},{ 2, 1},{ 0, 48},{ 0, 3},
+ { 2, 1},{ 0, 49},{ 0, 19},{ 10, 1},{ 4, 1},{ 2, 1},
+ { 0, 50},{ 0, 35},{ 4, 1},{ 2, 1},{ 0, 64},{ 0, 4},
+ { 0, 65},{ 6, 1},{ 2, 1},{ 0, 20},{ 2, 1},{ 0, 51},
+ { 0, 66},{ 4, 1},{ 2, 1},{ 0, 36},{ 0, 80},{ 2, 1},
+ { 0, 67},{ 0, 52},{138, 1},{ 40, 1},{ 16, 1},{ 6, 1},
+ { 4, 1},{ 2, 1},{ 0, 5},{ 0, 21},{ 0, 81},{ 4, 1}, // 60
+
+ { 2, 1},{ 0, 82},{ 0, 37},{ 4, 1},{ 2, 1},{ 0, 68},
+ { 0, 53},{ 0, 83},{ 10, 1},{ 6, 1},{ 4, 1},{ 2, 1},
+ { 0, 96},{ 0, 6},{ 0, 97},{ 2, 1},{ 0, 22},{ 0, 98},
+ { 8, 1},{ 4, 1},{ 2, 1},{ 0, 38},{ 0, 84},{ 2, 1},
+ { 0, 69},{ 0, 99},{ 4, 1},{ 2, 1},{ 0, 54},{ 0,112},
+ { 0,113},{ 40, 1},{ 18, 1},{ 8, 1},{ 2, 1},{ 0, 23},
+ { 2, 1},{ 0, 7},{ 2, 1},{ 0, 85},{ 0,100},{ 4, 1},
+ { 2, 1},{ 0,114},{ 0, 39},{ 4, 1},{ 2, 1},{ 0, 70},
+ { 0,101},{ 0,115},{ 10, 1},{ 6, 1},{ 2, 1},{ 0, 55},
+ { 2, 1},{ 0, 86},{ 0, 8},{ 2, 1},{ 0,128},{ 0,129}, // 120
+
+ { 6, 1},{ 2, 1},{ 0, 24},{ 2, 1},{ 0,116},{ 0, 71},
+ { 2, 1},{ 0,130},{ 2, 1},{ 0, 40},{ 0,102},{ 24, 1},
+ { 14, 1},{ 8, 1},{ 4, 1},{ 2, 1},{ 0,131},{ 0, 56},
+ { 2, 1},{ 0,117},{ 0,132},{ 4, 1},{ 2, 1},{ 0, 72},
+ { 0,144},{ 0,145},{ 6, 1},{ 2, 1},{ 0, 25},{ 2, 1},
+ { 0, 9},{ 0,118},{ 2, 1},{ 0,146},{ 0, 41},{ 14, 1},
+ { 8, 1},{ 4, 1},{ 2, 1},{ 0,133},{ 0, 88},{ 2, 1},
+ { 0,147},{ 0, 57},{ 4, 1},{ 2, 1},{ 0,160},{ 0, 10},
+ { 0, 26},{ 8, 1},{ 2, 1},{ 0,162},{ 2, 1},{ 0,103},
+ { 2, 1},{ 0, 87},{ 0, 73},{ 6, 1},{ 2, 1},{ 0,148}, // 180
+
+ { 2, 1},{ 0,119},{ 0,134},{ 2, 1},{ 0,161},{ 2, 1},
+ { 0,104},{ 0,149},{220, 1},{126, 1},{ 50, 1},{ 26, 1},
+ { 12, 1},{ 6, 1},{ 2, 1},{ 0, 42},{ 2, 1},{ 0, 89},
+ { 0, 58},{ 2, 1},{ 0,163},{ 2, 1},{ 0,135},{ 0,120},
+ { 8, 1},{ 4, 1},{ 2, 1},{ 0,164},{ 0, 74},{ 2, 1},
+ { 0,150},{ 0,105},{ 4, 1},{ 2, 1},{ 0,176},{ 0, 11},
+ { 0,177},{ 10, 1},{ 4, 1},{ 2, 1},{ 0, 27},{ 0,178},
+ { 2, 1},{ 0, 43},{ 2, 1},{ 0,165},{ 0, 90},{ 6, 1},
+ { 2, 1},{ 0,179},{ 2, 1},{ 0,166},{ 0,106},{ 4, 1},
+ { 2, 1},{ 0,180},{ 0, 75},{ 2, 1},{ 0, 12},{ 0,193}, // 240
+
+ { 30, 1},{ 14, 1},{ 6, 1},{ 4, 1},{ 2, 1},{ 0,181},
+ { 0,194},{ 0, 44},{ 4, 1},{ 2, 1},{ 0,167},{ 0,195},
+ { 2, 1},{ 0,107},{ 0,196},{ 8, 1},{ 2, 1},{ 0, 29},
+ { 4, 1},{ 2, 1},{ 0,136},{ 0,151},{ 0, 59},{ 4, 1},
+ { 2, 1},{ 0,209},{ 0,210},{ 2, 1},{ 0, 45},{ 0,211},
+ { 18, 1},{ 6, 1},{ 4, 1},{ 2, 1},{ 0, 30},{ 0, 46},
+ { 0,226},{ 6, 1},{ 4, 1},{ 2, 1},{ 0,121},{ 0,152},
+ { 0,192},{ 2, 1},{ 0, 28},{ 2, 1},{ 0,137},{ 0, 91},
+ { 14, 1},{ 6, 1},{ 2, 1},{ 0, 60},{ 2, 1},{ 0,122},
+ { 0,182},{ 4, 1},{ 2, 1},{ 0, 76},{ 0,153},{ 2, 1}, // 300
+
+ { 0,168},{ 0,138},{ 6, 1},{ 2, 1},{ 0, 13},{ 2, 1},
+ { 0,197},{ 0, 92},{ 4, 1},{ 2, 1},{ 0, 61},{ 0,198},
+ { 2, 1},{ 0,108},{ 0,154},{ 88, 1},{ 86, 1},{ 36, 1},
+ { 16, 1},{ 8, 1},{ 4, 1},{ 2, 1},{ 0,139},{ 0, 77},
+ { 2, 1},{ 0,199},{ 0,124},{ 4, 1},{ 2, 1},{ 0,213},
+ { 0, 93},{ 2, 1},{ 0,224},{ 0, 14},{ 8, 1},{ 2, 1},
+ { 0,227},{ 4, 1},{ 2, 1},{ 0,208},{ 0,183},{ 0,123},
+ { 6, 1},{ 4, 1},{ 2, 1},{ 0,169},{ 0,184},{ 0,212},
+ { 2, 1},{ 0,225},{ 2, 1},{ 0,170},{ 0,185},{ 24, 1},
+ { 10, 1},{ 6, 1},{ 4, 1},{ 2, 1},{ 0,155},{ 0,214}, // 360
+
+ { 0,109},{ 2, 1},{ 0, 62},{ 0,200},{ 6, 1},{ 4, 1},
+ { 2, 1},{ 0,140},{ 0,228},{ 0, 78},{ 4, 1},{ 2, 1},
+ { 0,215},{ 0,229},{ 2, 1},{ 0,186},{ 0,171},{ 12, 1},
+ { 4, 1},{ 2, 1},{ 0,156},{ 0,230},{ 4, 1},{ 2, 1},
+ { 0,110},{ 0,216},{ 2, 1},{ 0,141},{ 0,187},{ 8, 1},
+ { 4, 1},{ 2, 1},{ 0,231},{ 0,157},{ 2, 1},{ 0,232},
+ { 0,142},{ 4, 1},{ 2, 1},{ 0,203},{ 0,188},{ 0,158},
+ { 0,241},{ 2, 1},{ 0, 31},{ 2, 1},{ 0, 15},{ 0, 47},
+ { 66, 1},{ 56, 1},{ 2, 1},{ 0,242},{ 52, 1},{ 50, 1},
+ { 20, 1},{ 8, 1},{ 2, 1},{ 0,189},{ 2, 1},{ 0, 94}, // 420
+
+ { 2, 1},{ 0,125},{ 0,201},{ 6, 1},{ 2, 1},{ 0,202},
+ { 2, 1},{ 0,172},{ 0,126},{ 4, 1},{ 2, 1},{ 0,218},
+ { 0,173},{ 0,204},{ 10, 1},{ 6, 1},{ 2, 1},{ 0,174},
+ { 2, 1},{ 0,219},{ 0,220},{ 2, 1},{ 0,205},{ 0,190},
+ { 6, 1},{ 4, 1},{ 2, 1},{ 0,235},{ 0,237},{ 0,238},
+ { 6, 1},{ 4, 1},{ 2, 1},{ 0,217},{ 0,234},{ 0,233},
+ { 2, 1},{ 0,222},{ 4, 1},{ 2, 1},{ 0,221},{ 0,236},
+ { 0,206},{ 0, 63},{ 0,240},{ 4, 1},{ 2, 1},{ 0,243},
+ { 0,244},{ 2, 1},{ 0, 79},{ 2, 1},{ 0,245},{ 0, 95},
+ { 10, 1},{ 2, 1},{ 0,255},{ 4, 1},{ 2, 1},{ 0,246}, // 480
+
+ { 0,111},{ 2, 1},{ 0,247},{ 0,127},{ 12, 1},{ 6, 1},
+ { 2, 1},{ 0,143},{ 2, 1},{ 0,248},{ 0,249},{ 4, 1},
+ { 2, 1},{ 0,159},{ 0,250},{ 0,175},{ 8, 1},{ 4, 1},
+ { 2, 1},{ 0,251},{ 0,191},{ 2, 1},{ 0,252},{ 0,207},
+ { 4, 1},{ 2, 1},{ 0,253},{ 0,223},{ 2, 1},{ 0,254},
+ { 0,239}},
+
+htd24[512][2]={{ 60, 1},{ 8, 1},{ 4, 1},{ 2, 1},{ 0, 0},{ 0, 16},
+ { 2, 1},{ 0, 1},{ 0, 17},{ 14, 1},{ 6, 1},{ 4, 1},
+ { 2, 1},{ 0, 32},{ 0, 2},{ 0, 33},{ 2, 1},{ 0, 18},
+ { 2, 1},{ 0, 34},{ 2, 1},{ 0, 48},{ 0, 3},{ 14, 1},
+ { 4, 1},{ 2, 1},{ 0, 49},{ 0, 19},{ 4, 1},{ 2, 1},
+ { 0, 50},{ 0, 35},{ 4, 1},{ 2, 1},{ 0, 64},{ 0, 4},
+ { 0, 65},{ 8, 1},{ 4, 1},{ 2, 1},{ 0, 20},{ 0, 51},
+ { 2, 1},{ 0, 66},{ 0, 36},{ 6, 1},{ 4, 1},{ 2, 1},
+ { 0, 67},{ 0, 52},{ 0, 81},{ 6, 1},{ 4, 1},{ 2, 1},
+ { 0, 80},{ 0, 5},{ 0, 21},{ 2, 1},{ 0, 82},{ 0, 37}, // 60
+
+ {250+85, 1},{ 98, 1},{ 34, 1},{ 18, 1},{ 10, 1},{ 4, 1},
+ { 2, 1},{ 0, 68},{ 0, 83},{ 2, 1},{ 0, 53},{ 2, 1},
+ { 0, 96},{ 0, 6},{ 4, 1},{ 2, 1},{ 0, 97},{ 0, 22},
+ { 2, 1},{ 0, 98},{ 0, 38},{ 8, 1},{ 4, 1},{ 2, 1},
+ { 0, 84},{ 0, 69},{ 2, 1},{ 0, 99},{ 0, 54},{ 4, 1},
+ { 2, 1},{ 0,113},{ 0, 85},{ 2, 1},{ 0,100},{ 0, 70},
+ { 32, 1},{ 14, 1},{ 6, 1},{ 2, 1},{ 0,114},{ 2, 1},
+ { 0, 39},{ 0, 55},{ 2, 1},{ 0,115},{ 4, 1},{ 2, 1},
+ { 0,112},{ 0, 7},{ 0, 23},{ 10, 1},{ 4, 1},{ 2, 1},
+ { 0,101},{ 0, 86},{ 4, 1},{ 2, 1},{ 0,128},{ 0, 8}, // 120
+
+ { 0,129},{ 4, 1},{ 2, 1},{ 0,116},{ 0, 71},{ 2, 1},
+ { 0, 24},{ 0,130},{ 16, 1},{ 8, 1},{ 4, 1},{ 2, 1},
+ { 0, 40},{ 0,102},{ 2, 1},{ 0,131},{ 0, 56},{ 4, 1},
+ { 2, 1},{ 0,117},{ 0, 87},{ 2, 1},{ 0,132},{ 0, 72},
+ { 8, 1},{ 4, 1},{ 2, 1},{ 0,145},{ 0, 25},{ 2, 1},
+ { 0,146},{ 0,118},{ 4, 1},{ 2, 1},{ 0,103},{ 0, 41},
+ { 2, 1},{ 0,133},{ 0, 88},{ 92, 1},{ 34, 1},{ 16, 1},
+ { 8, 1},{ 4, 1},{ 2, 1},{ 0,147},{ 0, 57},{ 2, 1},
+ { 0,148},{ 0, 73},{ 4, 1},{ 2, 1},{ 0,119},{ 0,134},
+ { 2, 1},{ 0,104},{ 0,161},{ 8, 1},{ 4, 1},{ 2, 1}, // 180
+
+ { 0,162},{ 0, 42},{ 2, 1},{ 0,149},{ 0, 89},{ 4, 1},
+ { 2, 1},{ 0,163},{ 0, 58},{ 2, 1},{ 0,135},{ 2, 1},
+ { 0,120},{ 0, 74},{ 22, 1},{ 12, 1},{ 4, 1},{ 2, 1},
+ { 0,164},{ 0,150},{ 4, 1},{ 2, 1},{ 0,105},{ 0,177},
+ { 2, 1},{ 0, 27},{ 0,165},{ 6, 1},{ 2, 1},{ 0,178},
+ { 2, 1},{ 0, 90},{ 0, 43},{ 2, 1},{ 0,136},{ 0,179},
+ { 16, 1},{ 10, 1},{ 6, 1},{ 2, 1},{ 0,144},{ 2, 1},
+ { 0, 9},{ 0,160},{ 2, 1},{ 0,151},{ 0,121},{ 4, 1},
+ { 2, 1},{ 0,166},{ 0,106},{ 0,180},{ 12, 1},{ 6, 1},
+ { 2, 1},{ 0, 26},{ 2, 1},{ 0, 10},{ 0,176},{ 2, 1}, // 240
+
+ { 0, 59},{ 2, 1},{ 0, 11},{ 0,192},{ 4, 1},{ 2, 1},
+ { 0, 75},{ 0,193},{ 2, 1},{ 0,152},{ 0,137},{ 67, 1},
+ { 34, 1},{ 16, 1},{ 8, 1},{ 4, 1},{ 2, 1},{ 0, 28},
+ { 0,181},{ 2, 1},{ 0, 91},{ 0,194},{ 4, 1},{ 2, 1},
+ { 0, 44},{ 0,167},{ 2, 1},{ 0,122},{ 0,195},{ 10, 1},
+ { 6, 1},{ 2, 1},{ 0, 60},{ 2, 1},{ 0, 12},{ 0,208},
+ { 2, 1},{ 0,182},{ 0,107},{ 4, 1},{ 2, 1},{ 0,196},
+ { 0, 76},{ 2, 1},{ 0,153},{ 0,168},{ 16, 1},{ 8, 1},
+ { 4, 1},{ 2, 1},{ 0,138},{ 0,197},{ 2, 1},{ 0, 92},
+ { 0,209},{ 4, 1},{ 2, 1},{ 0,183},{ 0,123},{ 2, 1}, // 300
+
+ { 0, 29},{ 0,210},{ 9, 1},{ 4, 1},{ 2, 1},{ 0, 45},
+ { 0,211},{ 2, 1},{ 0, 61},{ 0,198},{ 85,250},{ 4, 1}, // 306 -
+ { 2, 1},{ 0,108},{ 0,169},{ 2, 1},{ 0,154},{ 0,212},
+ { 32, 1},{ 16, 1},{ 8, 1},{ 4, 1},{ 2, 1},{ 0,184},
+ { 0,139},{ 2, 1},{ 0, 77},{ 0,199},{ 4, 1},{ 2, 1},
+ { 0,124},{ 0,213},{ 2, 1},{ 0, 93},{ 0,225},{ 8, 1},
+ { 4, 1},{ 2, 1},{ 0, 30},{ 0,226},{ 2, 1},{ 0,170},
+ { 0,185},{ 4, 1},{ 2, 1},{ 0,155},{ 0,227},{ 2, 1},
+ { 0,214},{ 0,109},{ 20, 1},{ 10, 1},{ 6, 1},{ 2, 1},
+ { 0, 62},{ 2, 1},{ 0, 46},{ 0, 78},{ 2, 1},{ 0,200}, // 360
+
+ { 0,140},{ 4, 1},{ 2, 1},{ 0,228},{ 0,215},{ 4, 1},
+ { 2, 1},{ 0,125},{ 0,171},{ 0,229},{ 10, 1},{ 4, 1},
+ { 2, 1},{ 0,186},{ 0, 94},{ 2, 1},{ 0,201},{ 2, 1},
+ { 0,156},{ 0,110},{ 8, 1},{ 2, 1},{ 0,230},{ 2, 1},
+ { 0, 13},{ 2, 1},{ 0,224},{ 0, 14},{ 4, 1},{ 2, 1},
+ { 0,216},{ 0,141},{ 2, 1},{ 0,187},{ 0,202},{ 74, 1},
+ { 2, 1},{ 0,255},{ 64, 1},{ 58, 1},{ 32, 1},{ 16, 1},
+ { 8, 1},{ 4, 1},{ 2, 1},{ 0,172},{ 0,231},{ 2, 1},
+ { 0,126},{ 0,217},{ 4, 1},{ 2, 1},{ 0,157},{ 0,232},
+ { 2, 1},{ 0,142},{ 0,203},{ 8, 1},{ 4, 1},{ 2, 1}, // 420
+
+ { 0,188},{ 0,218},{ 2, 1},{ 0,173},{ 0,233},{ 4, 1},
+ { 2, 1},{ 0,158},{ 0,204},{ 2, 1},{ 0,219},{ 0,189},
+ { 16, 1},{ 8, 1},{ 4, 1},{ 2, 1},{ 0,234},{ 0,174},
+ { 2, 1},{ 0,220},{ 0,205},{ 4, 1},{ 2, 1},{ 0,235},
+ { 0,190},{ 2, 1},{ 0,221},{ 0,236},{ 8, 1},{ 4, 1},
+ { 2, 1},{ 0,206},{ 0,237},{ 2, 1},{ 0,222},{ 0,238},
+ { 0, 15},{ 4, 1},{ 2, 1},{ 0,240},{ 0, 31},{ 0,241},
+ { 4, 1},{ 2, 1},{ 0,242},{ 0, 47},{ 2, 1},{ 0,243},
+ { 0, 63},{ 18, 1},{ 8, 1},{ 4, 1},{ 2, 1},{ 0,244},
+ { 0, 79},{ 2, 1},{ 0,245},{ 0, 95},{ 4, 1},{ 2, 1}, // 480
+
+ { 0,246},{ 0,111},{ 2, 1},{ 0,247},{ 2, 1},{ 0,127},
+ { 0,143},{ 10, 1},{ 4, 1},{ 2, 1},{ 0,248},{ 0,249},
+ { 4, 1},{ 2, 1},{ 0,159},{ 0,175},{ 0,250},{ 8, 1},
+ { 4, 1},{ 2, 1},{ 0,251},{ 0,191},{ 2, 1},{ 0,252},
+ { 0,207},{ 4, 1},{ 2, 1},{ 0,253},{ 0,223},{ 2, 1},
+ { 0,254},{ 0,239}},
+
+htd32[ 31][2]={{ 2, 1},{ 0, 0},{ 8, 1},{ 4, 1},{ 2, 1},{ 0, 8},
+ { 0, 4},{ 2, 1},{ 0, 1},{ 0, 2},{ 8, 1},{ 4, 1},
+ { 2, 1},{ 0, 12},{ 0, 10},{ 2, 1},{ 0, 3},{ 0, 6},
+ { 6, 1},{ 2, 1},{ 0, 9},{ 2, 1},{ 0, 5},{ 0, 7},
+ { 4, 1},{ 2, 1},{ 0, 14},{ 0, 13},{ 2, 1},{ 0, 15},
+ { 0, 11}},
+
+htd33[ 31][2]={{ 16, 1},{ 8, 1},{ 4, 1},{ 2, 1},{ 0, 0},{ 0, 1},
+ { 2, 1},{ 0, 2},{ 0, 3},{ 4, 1},{ 2, 1},{ 0, 4},
+ { 0, 5},{ 2, 1},{ 0, 6},{ 0, 7},{ 8, 1},{ 4, 1},
+ { 2, 1},{ 0, 8},{ 0, 9},{ 2, 1},{ 0, 10},{ 0, 11},
+ { 4, 1},{ 2, 1},{ 0, 12},{ 0, 13},{ 2, 1},{ 0, 14},
+ { 0, 15}};
+
+const ATTR_ALIGN(64) HUFFMANCODETABLE Mpegtoraw::ht[HTN]=
+{
+ { 0, 0-1, 0-1, 0, 0, htd33},
+ { 1, 2-1, 2-1, 0, 7,htd01},
+ { 2, 3-1, 3-1, 0, 17,htd02},
+ { 3, 3-1, 3-1, 0, 17,htd03},
+ { 4, 0-1, 0-1, 0, 0, htd33},
+ { 5, 4-1, 4-1, 0, 31,htd05},
+ { 6, 4-1, 4-1, 0, 31,htd06},
+ { 7, 6-1, 6-1, 0, 71,htd07},
+ { 8, 6-1, 6-1, 0, 71,htd08},
+ { 9, 6-1, 6-1, 0, 71,htd09},
+ {10, 8-1, 8-1, 0,127,htd10},
+ {11, 8-1, 8-1, 0,127,htd11},
+ {12, 8-1, 8-1, 0,127,htd12},
+ {13,16-1,16-1, 0,511,htd13},
+ {14, 0-1, 0-1, 0, 0, htd33},
+ {15,16-1,16-1, 0,511,htd15},
+ {16,16-1,16-1, 1,511,htd16},
+ {17,16-1,16-1, 2,511,htd16},
+ {18,16-1,16-1, 3,511,htd16},
+ {19,16-1,16-1, 4,511,htd16},
+ {20,16-1,16-1, 6,511,htd16},
+ {21,16-1,16-1, 8,511,htd16},
+ {22,16-1,16-1,10,511,htd16},
+ {23,16-1,16-1,13,511,htd16},
+ {24,16-1,16-1, 4,512,htd24},
+ {25,16-1,16-1, 5,512,htd24},
+ {26,16-1,16-1, 6,512,htd24},
+ {27,16-1,16-1, 7,512,htd24},
+ {28,16-1,16-1, 8,512,htd24},
+ {29,16-1,16-1, 9,512,htd24},
+ {30,16-1,16-1,11,512,htd24},
+ {31,16-1,16-1,13,512,htd24},
+ {32, 1-1,16-1, 0, 31,htd32},
+ {33, 1-1,16-1, 0, 31,htd33}
+};
diff --git a/mpeglib/lib/splay/mpeg2tables.h b/mpeglib/lib/splay/mpeg2tables.h
new file mode 100644
index 00000000..1430a123
--- /dev/null
+++ b/mpeglib/lib/splay/mpeg2tables.h
@@ -0,0 +1,432 @@
+
+#ifndef __MPEG2TABLES_H
+#define __MPEG2TABLES_H
+
+
+#define MAXTABLE 3
+
+
+// Tables for layer 2.
+
+// bitalloclengthtable :0,1 supported 2. 2 ot tested & disabled
+// this table merges the subbands to the longer one.
+// 8 < 12 , 27 < 30 but the "length" is the same
+
+static const int bitalloclengthtable[MAXTABLE][MAXSUBBAND]=
+{ {4,4,3,3,3,3,3,3,3,3,3,3,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ {4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3, 3,3,3,3,3,3,3,2,2,2,2,2,2,2,0,0},
+ {4,4,4,4,3,3,3,3,3,3,3,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0} };
+
+
+/*
+Orignal is:
+{ {4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3, 3,3,3,3,3,3,3,2,2,2,2,0,0,0,0,0},
+ {4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3, 3,3,3,3,3,3,3,2,2,2,2,2,2,2,0,0},
+ {4,4,3,3,3,3,3,3,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ {4,4,3,3,3,3,3,3,3,3,3,3,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ {4,4,4,4,3,3,3,3,3,3,3,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0} };
+
+*/
+
+
+
+
+
+static const REAL group5bits[27*3]=
+{
+ -2.0/3.0, -2.0/3.0, -2.0/3.0,
+ 0.0, -2.0/3.0, -2.0/3.0,
+ 2.0/3.0, -2.0/3.0, -2.0/3.0,
+ -2.0/3.0, 0.0, -2.0/3.0,
+ 0.0, 0.0, -2.0/3.0,
+ 2.0/3.0, 0.0, -2.0/3.0,
+ -2.0/3.0, 2.0/3.0, -2.0/3.0,
+ 0.0, 2.0/3.0, -2.0/3.0,
+ 2.0/3.0, 2.0/3.0, -2.0/3.0,
+ -2.0/3.0, -2.0/3.0, 0.0,
+ 0.0, -2.0/3.0, 0.0,
+ 2.0/3.0, -2.0/3.0, 0.0,
+ -2.0/3.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0,
+ 2.0/3.0, 0.0, 0.0,
+ -2.0/3.0, 2.0/3.0, 0.0,
+ 0.0, 2.0/3.0, 0.0,
+ 2.0/3.0, 2.0/3.0, 0.0,
+ -2.0/3.0, -2.0/3.0, 2.0/3.0,
+ 0.0, -2.0/3.0, 2.0/3.0,
+ 2.0/3.0, -2.0/3.0, 2.0/3.0,
+ -2.0/3.0, 0.0, 2.0/3.0,
+ 0.0, 0.0, 2.0/3.0,
+ 2.0/3.0, 0.0, 2.0/3.0,
+ -2.0/3.0, 2.0/3.0, 2.0/3.0,
+ 0.0, 2.0/3.0, 2.0/3.0,
+ 2.0/3.0, 2.0/3.0, 2.0/3.0
+};
+
+static const REAL group7bits[125*3]=
+{
+ -0.8,-0.8,-0.8, -0.4,-0.8,-0.8, 0.0,-0.8,-0.8, 0.4,-0.8,-0.8, 0.8,-0.8,-0.8,
+ -0.8,-0.4,-0.8, -0.4,-0.4,-0.8, 0.0,-0.4,-0.8, 0.4,-0.4,-0.8, 0.8,-0.4,-0.8,
+ -0.8, 0.0,-0.8, -0.4, 0.0,-0.8, 0.0, 0.0,-0.8, 0.4, 0.0,-0.8, 0.8, 0.0,-0.8,
+ -0.8, 0.4,-0.8, -0.4, 0.4,-0.8, 0.0, 0.4,-0.8, 0.4, 0.4,-0.8, 0.8, 0.4,-0.8,
+ -0.8, 0.8,-0.8, -0.4, 0.8,-0.8, 0.0, 0.8,-0.8, 0.4, 0.8,-0.8, 0.8, 0.8,-0.8,
+ -0.8,-0.8,-0.4, -0.4,-0.8,-0.4, 0.0,-0.8,-0.4, 0.4,-0.8,-0.4, 0.8,-0.8,-0.4,
+ -0.8,-0.4,-0.4, -0.4,-0.4,-0.4, 0.0,-0.4,-0.4, 0.4,-0.4,-0.4, 0.8,-0.4,-0.4,
+ -0.8, 0.0,-0.4, -0.4, 0.0,-0.4, 0.0, 0.0,-0.4, 0.4, 0.0,-0.4, 0.8, 0.0,-0.4,
+ -0.8, 0.4,-0.4, -0.4, 0.4,-0.4, 0.0, 0.4,-0.4, 0.4, 0.4,-0.4, 0.8, 0.4,-0.4,
+ -0.8, 0.8,-0.4, -0.4, 0.8,-0.4, 0.0, 0.8,-0.4, 0.4, 0.8,-0.4, 0.8, 0.8,-0.4,
+ -0.8,-0.8, 0.0, -0.4,-0.8, 0.0, 0.0,-0.8, 0.0, 0.4,-0.8, 0.0, 0.8,-0.8, 0.0,
+ -0.8,-0.4, 0.0, -0.4,-0.4, 0.0, 0.0,-0.4, 0.0, 0.4,-0.4, 0.0, 0.8,-0.4, 0.0,
+ -0.8, 0.0, 0.0, -0.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.4, 0.0, 0.0, 0.8, 0.0, 0.0,
+ -0.8, 0.4, 0.0, -0.4, 0.4, 0.0, 0.0, 0.4, 0.0, 0.4, 0.4, 0.0, 0.8, 0.4, 0.0,
+ -0.8, 0.8, 0.0, -0.4, 0.8, 0.0, 0.0, 0.8, 0.0, 0.4, 0.8, 0.0, 0.8, 0.8, 0.0,
+ -0.8,-0.8, 0.4, -0.4,-0.8, 0.4, 0.0,-0.8, 0.4, 0.4,-0.8, 0.4, 0.8,-0.8, 0.4,
+ -0.8,-0.4, 0.4, -0.4,-0.4, 0.4, 0.0,-0.4, 0.4, 0.4,-0.4, 0.4, 0.8,-0.4, 0.4,
+ -0.8, 0.0, 0.4, -0.4, 0.0, 0.4, 0.0, 0.0, 0.4, 0.4, 0.0, 0.4, 0.8, 0.0, 0.4,
+ -0.8, 0.4, 0.4, -0.4, 0.4, 0.4, 0.0, 0.4, 0.4, 0.4, 0.4, 0.4, 0.8, 0.4, 0.4,
+ -0.8, 0.8, 0.4, -0.4, 0.8, 0.4, 0.0, 0.8, 0.4, 0.4, 0.8, 0.4, 0.8, 0.8, 0.4,
+ -0.8,-0.8, 0.8, -0.4,-0.8, 0.8, 0.0,-0.8, 0.8, 0.4,-0.8, 0.8, 0.8,-0.8, 0.8,
+ -0.8,-0.4, 0.8, -0.4,-0.4, 0.8, 0.0,-0.4, 0.8, 0.4,-0.4, 0.8, 0.8,-0.4, 0.8,
+ -0.8, 0.0, 0.8, -0.4, 0.0, 0.8, 0.0, 0.0, 0.8, 0.4, 0.0, 0.8, 0.8, 0.0, 0.8,
+ -0.8, 0.4, 0.8, -0.4, 0.4, 0.8, 0.0, 0.4, 0.8, 0.4, 0.4, 0.8, 0.8, 0.4, 0.8,
+ -0.8, 0.8, 0.8, -0.4, 0.8, 0.8, 0.0, 0.8, 0.8, 0.4, 0.8, 0.8, 0.8, 0.8, 0.8
+};
+
+static const REAL group10bits[729*3]=
+{
+ -8.0/9.0,-8.0/9.0,-8.0/9.0, -6.0/9.0,-8.0/9.0,-8.0/9.0, -4.0/9.0,-8.0/9.0,-8.0/9.0,
+ -2.0/9.0,-8.0/9.0,-8.0/9.0, 0.0,-8.0/9.0,-8.0/9.0, 2.0/9.0,-8.0/9.0,-8.0/9.0,
+ 4.0/9.0,-8.0/9.0,-8.0/9.0, 6.0/9.0,-8.0/9.0,-8.0/9.0, 8.0/9.0,-8.0/9.0,-8.0/9.0,
+ -8.0/9.0,-6.0/9.0,-8.0/9.0, -6.0/9.0,-6.0/9.0,-8.0/9.0, -4.0/9.0,-6.0/9.0,-8.0/9.0,
+ -2.0/9.0,-6.0/9.0,-8.0/9.0, 0.0,-6.0/9.0,-8.0/9.0, 2.0/9.0,-6.0/9.0,-8.0/9.0,
+ 4.0/9.0,-6.0/9.0,-8.0/9.0, 6.0/9.0,-6.0/9.0,-8.0/9.0, 8.0/9.0,-6.0/9.0,-8.0/9.0,
+ -8.0/9.0,-4.0/9.0,-8.0/9.0, -6.0/9.0,-4.0/9.0,-8.0/9.0, -4.0/9.0,-4.0/9.0,-8.0/9.0,
+ -2.0/9.0,-4.0/9.0,-8.0/9.0, 0.0,-4.0/9.0,-8.0/9.0, 2.0/9.0,-4.0/9.0,-8.0/9.0,
+ 4.0/9.0,-4.0/9.0,-8.0/9.0, 6.0/9.0,-4.0/9.0,-8.0/9.0, 8.0/9.0,-4.0/9.0,-8.0/9.0,
+ -8.0/9.0,-2.0/9.0,-8.0/9.0, -6.0/9.0,-2.0/9.0,-8.0/9.0, -4.0/9.0,-2.0/9.0,-8.0/9.0,
+ -2.0/9.0,-2.0/9.0,-8.0/9.0, 0.0,-2.0/9.0,-8.0/9.0, 2.0/9.0,-2.0/9.0,-8.0/9.0,
+ 4.0/9.0,-2.0/9.0,-8.0/9.0, 6.0/9.0,-2.0/9.0,-8.0/9.0, 8.0/9.0,-2.0/9.0,-8.0/9.0,
+ -8.0/9.0, 0.0,-8.0/9.0, -6.0/9.0, 0.0,-8.0/9.0, -4.0/9.0, 0.0,-8.0/9.0,
+ -2.0/9.0, 0.0,-8.0/9.0, 0.0, 0.0,-8.0/9.0, 2.0/9.0, 0.0,-8.0/9.0,
+ 4.0/9.0, 0.0,-8.0/9.0, 6.0/9.0, 0.0,-8.0/9.0, 8.0/9.0, 0.0,-8.0/9.0,
+ -8.0/9.0, 2.0/9.0,-8.0/9.0, -6.0/9.0, 2.0/9.0,-8.0/9.0, -4.0/9.0, 2.0/9.0,-8.0/9.0,
+ -2.0/9.0, 2.0/9.0,-8.0/9.0, 0.0, 2.0/9.0,-8.0/9.0, 2.0/9.0, 2.0/9.0,-8.0/9.0,
+ 4.0/9.0, 2.0/9.0,-8.0/9.0, 6.0/9.0, 2.0/9.0,-8.0/9.0, 8.0/9.0, 2.0/9.0,-8.0/9.0,
+ -8.0/9.0, 4.0/9.0,-8.0/9.0, -6.0/9.0, 4.0/9.0,-8.0/9.0, -4.0/9.0, 4.0/9.0,-8.0/9.0,
+ -2.0/9.0, 4.0/9.0,-8.0/9.0, 0.0, 4.0/9.0,-8.0/9.0, 2.0/9.0, 4.0/9.0,-8.0/9.0,
+ 4.0/9.0, 4.0/9.0,-8.0/9.0, 6.0/9.0, 4.0/9.0,-8.0/9.0, 8.0/9.0, 4.0/9.0,-8.0/9.0,
+ -8.0/9.0, 6.0/9.0,-8.0/9.0, -6.0/9.0, 6.0/9.0,-8.0/9.0, -4.0/9.0, 6.0/9.0,-8.0/9.0,
+ -2.0/9.0, 6.0/9.0,-8.0/9.0, 0.0, 6.0/9.0,-8.0/9.0, 2.0/9.0, 6.0/9.0,-8.0/9.0,
+ 4.0/9.0, 6.0/9.0,-8.0/9.0, 6.0/9.0, 6.0/9.0,-8.0/9.0, 8.0/9.0, 6.0/9.0,-8.0/9.0,
+ -8.0/9.0, 8.0/9.0,-8.0/9.0, -6.0/9.0, 8.0/9.0,-8.0/9.0, -4.0/9.0, 8.0/9.0,-8.0/9.0,
+ -2.0/9.0, 8.0/9.0,-8.0/9.0, 0.0, 8.0/9.0,-8.0/9.0, 2.0/9.0, 8.0/9.0,-8.0/9.0,
+ 4.0/9.0, 8.0/9.0,-8.0/9.0, 6.0/9.0, 8.0/9.0,-8.0/9.0, 8.0/9.0, 8.0/9.0,-8.0/9.0,
+ -8.0/9.0,-8.0/9.0,-6.0/9.0, -6.0/9.0,-8.0/9.0,-6.0/9.0, -4.0/9.0,-8.0/9.0,-6.0/9.0,
+ -2.0/9.0,-8.0/9.0,-6.0/9.0, 0.0,-8.0/9.0,-6.0/9.0, 2.0/9.0,-8.0/9.0,-6.0/9.0,
+ 4.0/9.0,-8.0/9.0,-6.0/9.0, 6.0/9.0,-8.0/9.0,-6.0/9.0, 8.0/9.0,-8.0/9.0,-6.0/9.0,
+ -8.0/9.0,-6.0/9.0,-6.0/9.0, -6.0/9.0,-6.0/9.0,-6.0/9.0, -4.0/9.0,-6.0/9.0,-6.0/9.0,
+ -2.0/9.0,-6.0/9.0,-6.0/9.0, 0.0,-6.0/9.0,-6.0/9.0, 2.0/9.0,-6.0/9.0,-6.0/9.0,
+ 4.0/9.0,-6.0/9.0,-6.0/9.0, 6.0/9.0,-6.0/9.0,-6.0/9.0, 8.0/9.0,-6.0/9.0,-6.0/9.0,
+ -8.0/9.0,-4.0/9.0,-6.0/9.0, -6.0/9.0,-4.0/9.0,-6.0/9.0, -4.0/9.0,-4.0/9.0,-6.0/9.0,
+ -2.0/9.0,-4.0/9.0,-6.0/9.0, 0.0,-4.0/9.0,-6.0/9.0, 2.0/9.0,-4.0/9.0,-6.0/9.0,
+ 4.0/9.0,-4.0/9.0,-6.0/9.0, 6.0/9.0,-4.0/9.0,-6.0/9.0, 8.0/9.0,-4.0/9.0,-6.0/9.0,
+ -8.0/9.0,-2.0/9.0,-6.0/9.0, -6.0/9.0,-2.0/9.0,-6.0/9.0, -4.0/9.0,-2.0/9.0,-6.0/9.0,
+ -2.0/9.0,-2.0/9.0,-6.0/9.0, 0.0,-2.0/9.0,-6.0/9.0, 2.0/9.0,-2.0/9.0,-6.0/9.0,
+ 4.0/9.0,-2.0/9.0,-6.0/9.0, 6.0/9.0,-2.0/9.0,-6.0/9.0, 8.0/9.0,-2.0/9.0,-6.0/9.0,
+ -8.0/9.0, 0.0,-6.0/9.0, -6.0/9.0, 0.0,-6.0/9.0, -4.0/9.0, 0.0,-6.0/9.0,
+ -2.0/9.0, 0.0,-6.0/9.0, 0.0, 0.0,-6.0/9.0, 2.0/9.0, 0.0,-6.0/9.0,
+ 4.0/9.0, 0.0,-6.0/9.0, 6.0/9.0, 0.0,-6.0/9.0, 8.0/9.0, 0.0,-6.0/9.0,
+ -8.0/9.0, 2.0/9.0,-6.0/9.0, -6.0/9.0, 2.0/9.0,-6.0/9.0, -4.0/9.0, 2.0/9.0,-6.0/9.0,
+ -2.0/9.0, 2.0/9.0,-6.0/9.0, 0.0, 2.0/9.0,-6.0/9.0, 2.0/9.0, 2.0/9.0,-6.0/9.0,
+ 4.0/9.0, 2.0/9.0,-6.0/9.0, 6.0/9.0, 2.0/9.0,-6.0/9.0, 8.0/9.0, 2.0/9.0,-6.0/9.0,
+ -8.0/9.0, 4.0/9.0,-6.0/9.0, -6.0/9.0, 4.0/9.0,-6.0/9.0, -4.0/9.0, 4.0/9.0,-6.0/9.0,
+ -2.0/9.0, 4.0/9.0,-6.0/9.0, 0.0, 4.0/9.0,-6.0/9.0, 2.0/9.0, 4.0/9.0,-6.0/9.0,
+ 4.0/9.0, 4.0/9.0,-6.0/9.0, 6.0/9.0, 4.0/9.0,-6.0/9.0, 8.0/9.0, 4.0/9.0,-6.0/9.0,
+ -8.0/9.0, 6.0/9.0,-6.0/9.0, -6.0/9.0, 6.0/9.0,-6.0/9.0, -4.0/9.0, 6.0/9.0,-6.0/9.0,
+ -2.0/9.0, 6.0/9.0,-6.0/9.0, 0.0, 6.0/9.0,-6.0/9.0, 2.0/9.0, 6.0/9.0,-6.0/9.0,
+ 4.0/9.0, 6.0/9.0,-6.0/9.0, 6.0/9.0, 6.0/9.0,-6.0/9.0, 8.0/9.0, 6.0/9.0,-6.0/9.0,
+ -8.0/9.0, 8.0/9.0,-6.0/9.0, -6.0/9.0, 8.0/9.0,-6.0/9.0, -4.0/9.0, 8.0/9.0,-6.0/9.0,
+ -2.0/9.0, 8.0/9.0,-6.0/9.0, 0.0, 8.0/9.0,-6.0/9.0, 2.0/9.0, 8.0/9.0,-6.0/9.0,
+ 4.0/9.0, 8.0/9.0,-6.0/9.0, 6.0/9.0, 8.0/9.0,-6.0/9.0, 8.0/9.0, 8.0/9.0,-6.0/9.0,
+ -8.0/9.0,-8.0/9.0,-4.0/9.0, -6.0/9.0,-8.0/9.0,-4.0/9.0, -4.0/9.0,-8.0/9.0,-4.0/9.0,
+ -2.0/9.0,-8.0/9.0,-4.0/9.0, 0.0,-8.0/9.0,-4.0/9.0, 2.0/9.0,-8.0/9.0,-4.0/9.0,
+ 4.0/9.0,-8.0/9.0,-4.0/9.0, 6.0/9.0,-8.0/9.0,-4.0/9.0, 8.0/9.0,-8.0/9.0,-4.0/9.0,
+ -8.0/9.0,-6.0/9.0,-4.0/9.0, -6.0/9.0,-6.0/9.0,-4.0/9.0, -4.0/9.0,-6.0/9.0,-4.0/9.0,
+ -2.0/9.0,-6.0/9.0,-4.0/9.0, 0.0,-6.0/9.0,-4.0/9.0, 2.0/9.0,-6.0/9.0,-4.0/9.0,
+ 4.0/9.0,-6.0/9.0,-4.0/9.0, 6.0/9.0,-6.0/9.0,-4.0/9.0, 8.0/9.0,-6.0/9.0,-4.0/9.0,
+ -8.0/9.0,-4.0/9.0,-4.0/9.0, -6.0/9.0,-4.0/9.0,-4.0/9.0, -4.0/9.0,-4.0/9.0,-4.0/9.0,
+ -2.0/9.0,-4.0/9.0,-4.0/9.0, 0.0,-4.0/9.0,-4.0/9.0, 2.0/9.0,-4.0/9.0,-4.0/9.0,
+ 4.0/9.0,-4.0/9.0,-4.0/9.0, 6.0/9.0,-4.0/9.0,-4.0/9.0, 8.0/9.0,-4.0/9.0,-4.0/9.0,
+ -8.0/9.0,-2.0/9.0,-4.0/9.0, -6.0/9.0,-2.0/9.0,-4.0/9.0, -4.0/9.0,-2.0/9.0,-4.0/9.0,
+ -2.0/9.0,-2.0/9.0,-4.0/9.0, 0.0,-2.0/9.0,-4.0/9.0, 2.0/9.0,-2.0/9.0,-4.0/9.0,
+ 4.0/9.0,-2.0/9.0,-4.0/9.0, 6.0/9.0,-2.0/9.0,-4.0/9.0, 8.0/9.0,-2.0/9.0,-4.0/9.0,
+ -8.0/9.0, 0.0,-4.0/9.0, -6.0/9.0, 0.0,-4.0/9.0, -4.0/9.0, 0.0,-4.0/9.0,
+ -2.0/9.0, 0.0,-4.0/9.0, 0.0, 0.0,-4.0/9.0, 2.0/9.0, 0.0,-4.0/9.0,
+ 4.0/9.0, 0.0,-4.0/9.0, 6.0/9.0, 0.0,-4.0/9.0, 8.0/9.0, 0.0,-4.0/9.0,
+ -8.0/9.0, 2.0/9.0,-4.0/9.0, -6.0/9.0, 2.0/9.0,-4.0/9.0, -4.0/9.0, 2.0/9.0,-4.0/9.0,
+ -2.0/9.0, 2.0/9.0,-4.0/9.0, 0.0, 2.0/9.0,-4.0/9.0, 2.0/9.0, 2.0/9.0,-4.0/9.0,
+ 4.0/9.0, 2.0/9.0,-4.0/9.0, 6.0/9.0, 2.0/9.0,-4.0/9.0, 8.0/9.0, 2.0/9.0,-4.0/9.0,
+ -8.0/9.0, 4.0/9.0,-4.0/9.0, -6.0/9.0, 4.0/9.0,-4.0/9.0, -4.0/9.0, 4.0/9.0,-4.0/9.0,
+ -2.0/9.0, 4.0/9.0,-4.0/9.0, 0.0, 4.0/9.0,-4.0/9.0, 2.0/9.0, 4.0/9.0,-4.0/9.0,
+ 4.0/9.0, 4.0/9.0,-4.0/9.0, 6.0/9.0, 4.0/9.0,-4.0/9.0, 8.0/9.0, 4.0/9.0,-4.0/9.0,
+ -8.0/9.0, 6.0/9.0,-4.0/9.0, -6.0/9.0, 6.0/9.0,-4.0/9.0, -4.0/9.0, 6.0/9.0,-4.0/9.0,
+ -2.0/9.0, 6.0/9.0,-4.0/9.0, 0.0, 6.0/9.0,-4.0/9.0, 2.0/9.0, 6.0/9.0,-4.0/9.0,
+ 4.0/9.0, 6.0/9.0,-4.0/9.0, 6.0/9.0, 6.0/9.0,-4.0/9.0, 8.0/9.0, 6.0/9.0,-4.0/9.0,
+ -8.0/9.0, 8.0/9.0,-4.0/9.0, -6.0/9.0, 8.0/9.0,-4.0/9.0, -4.0/9.0, 8.0/9.0,-4.0/9.0,
+ -2.0/9.0, 8.0/9.0,-4.0/9.0, 0.0, 8.0/9.0,-4.0/9.0, 2.0/9.0, 8.0/9.0,-4.0/9.0,
+ 4.0/9.0, 8.0/9.0,-4.0/9.0, 6.0/9.0, 8.0/9.0,-4.0/9.0, 8.0/9.0, 8.0/9.0,-4.0/9.0,
+ -8.0/9.0,-8.0/9.0,-2.0/9.0, -6.0/9.0,-8.0/9.0,-2.0/9.0, -4.0/9.0,-8.0/9.0,-2.0/9.0,
+ -2.0/9.0,-8.0/9.0,-2.0/9.0, 0.0,-8.0/9.0,-2.0/9.0, 2.0/9.0,-8.0/9.0,-2.0/9.0,
+ 4.0/9.0,-8.0/9.0,-2.0/9.0, 6.0/9.0,-8.0/9.0,-2.0/9.0, 8.0/9.0,-8.0/9.0,-2.0/9.0,
+ -8.0/9.0,-6.0/9.0,-2.0/9.0, -6.0/9.0,-6.0/9.0,-2.0/9.0, -4.0/9.0,-6.0/9.0,-2.0/9.0,
+ -2.0/9.0,-6.0/9.0,-2.0/9.0, 0.0,-6.0/9.0,-2.0/9.0, 2.0/9.0,-6.0/9.0,-2.0/9.0,
+ 4.0/9.0,-6.0/9.0,-2.0/9.0, 6.0/9.0,-6.0/9.0,-2.0/9.0, 8.0/9.0,-6.0/9.0,-2.0/9.0,
+ -8.0/9.0,-4.0/9.0,-2.0/9.0, -6.0/9.0,-4.0/9.0,-2.0/9.0, -4.0/9.0,-4.0/9.0,-2.0/9.0,
+ -2.0/9.0,-4.0/9.0,-2.0/9.0, 0.0,-4.0/9.0,-2.0/9.0, 2.0/9.0,-4.0/9.0,-2.0/9.0,
+ 4.0/9.0,-4.0/9.0,-2.0/9.0, 6.0/9.0,-4.0/9.0,-2.0/9.0, 8.0/9.0,-4.0/9.0,-2.0/9.0,
+ -8.0/9.0,-2.0/9.0,-2.0/9.0, -6.0/9.0,-2.0/9.0,-2.0/9.0, -4.0/9.0,-2.0/9.0,-2.0/9.0,
+ -2.0/9.0,-2.0/9.0,-2.0/9.0, 0.0,-2.0/9.0,-2.0/9.0, 2.0/9.0,-2.0/9.0,-2.0/9.0,
+ 4.0/9.0,-2.0/9.0,-2.0/9.0, 6.0/9.0,-2.0/9.0,-2.0/9.0, 8.0/9.0,-2.0/9.0,-2.0/9.0,
+ -8.0/9.0, 0.0,-2.0/9.0, -6.0/9.0, 0.0,-2.0/9.0, -4.0/9.0, 0.0,-2.0/9.0,
+ -2.0/9.0, 0.0,-2.0/9.0, 0.0, 0.0,-2.0/9.0, 2.0/9.0, 0.0,-2.0/9.0,
+ 4.0/9.0, 0.0,-2.0/9.0, 6.0/9.0, 0.0,-2.0/9.0, 8.0/9.0, 0.0,-2.0/9.0,
+ -8.0/9.0, 2.0/9.0,-2.0/9.0, -6.0/9.0, 2.0/9.0,-2.0/9.0, -4.0/9.0, 2.0/9.0,-2.0/9.0,
+ -2.0/9.0, 2.0/9.0,-2.0/9.0, 0.0, 2.0/9.0,-2.0/9.0, 2.0/9.0, 2.0/9.0,-2.0/9.0,
+ 4.0/9.0, 2.0/9.0,-2.0/9.0, 6.0/9.0, 2.0/9.0,-2.0/9.0, 8.0/9.0, 2.0/9.0,-2.0/9.0,
+ -8.0/9.0, 4.0/9.0,-2.0/9.0, -6.0/9.0, 4.0/9.0,-2.0/9.0, -4.0/9.0, 4.0/9.0,-2.0/9.0,
+ -2.0/9.0, 4.0/9.0,-2.0/9.0, 0.0, 4.0/9.0,-2.0/9.0, 2.0/9.0, 4.0/9.0,-2.0/9.0,
+ 4.0/9.0, 4.0/9.0,-2.0/9.0, 6.0/9.0, 4.0/9.0,-2.0/9.0, 8.0/9.0, 4.0/9.0,-2.0/9.0,
+ -8.0/9.0, 6.0/9.0,-2.0/9.0, -6.0/9.0, 6.0/9.0,-2.0/9.0, -4.0/9.0, 6.0/9.0,-2.0/9.0,
+ -2.0/9.0, 6.0/9.0,-2.0/9.0, 0.0, 6.0/9.0,-2.0/9.0, 2.0/9.0, 6.0/9.0,-2.0/9.0,
+ 4.0/9.0, 6.0/9.0,-2.0/9.0, 6.0/9.0, 6.0/9.0,-2.0/9.0, 8.0/9.0, 6.0/9.0,-2.0/9.0,
+ -8.0/9.0, 8.0/9.0,-2.0/9.0, -6.0/9.0, 8.0/9.0,-2.0/9.0, -4.0/9.0, 8.0/9.0,-2.0/9.0,
+ -2.0/9.0, 8.0/9.0,-2.0/9.0, 0.0, 8.0/9.0,-2.0/9.0, 2.0/9.0, 8.0/9.0,-2.0/9.0,
+ 4.0/9.0, 8.0/9.0,-2.0/9.0, 6.0/9.0, 8.0/9.0,-2.0/9.0, 8.0/9.0, 8.0/9.0,-2.0/9.0,
+ -8.0/9.0,-8.0/9.0, 0.0, -6.0/9.0,-8.0/9.0, 0.0, -4.0/9.0,-8.0/9.0, 0.0,
+ -2.0/9.0,-8.0/9.0, 0.0, 0.0,-8.0/9.0, 0.0, 2.0/9.0,-8.0/9.0, 0.0,
+ 4.0/9.0,-8.0/9.0, 0.0, 6.0/9.0,-8.0/9.0, 0.0, 8.0/9.0,-8.0/9.0, 0.0,
+ -8.0/9.0,-6.0/9.0, 0.0, -6.0/9.0,-6.0/9.0, 0.0, -4.0/9.0,-6.0/9.0, 0.0,
+ -2.0/9.0,-6.0/9.0, 0.0, 0.0,-6.0/9.0, 0.0, 2.0/9.0,-6.0/9.0, 0.0,
+ 4.0/9.0,-6.0/9.0, 0.0, 6.0/9.0,-6.0/9.0, 0.0, 8.0/9.0,-6.0/9.0, 0.0,
+ -8.0/9.0,-4.0/9.0, 0.0, -6.0/9.0,-4.0/9.0, 0.0, -4.0/9.0,-4.0/9.0, 0.0,
+ -2.0/9.0,-4.0/9.0, 0.0, 0.0,-4.0/9.0, 0.0, 2.0/9.0,-4.0/9.0, 0.0,
+ 4.0/9.0,-4.0/9.0, 0.0, 6.0/9.0,-4.0/9.0, 0.0, 8.0/9.0,-4.0/9.0, 0.0,
+ -8.0/9.0,-2.0/9.0, 0.0, -6.0/9.0,-2.0/9.0, 0.0, -4.0/9.0,-2.0/9.0, 0.0,
+ -2.0/9.0,-2.0/9.0, 0.0, 0.0,-2.0/9.0, 0.0, 2.0/9.0,-2.0/9.0, 0.0,
+ 4.0/9.0,-2.0/9.0, 0.0, 6.0/9.0,-2.0/9.0, 0.0, 8.0/9.0,-2.0/9.0, 0.0,
+ -8.0/9.0, 0.0, 0.0, -6.0/9.0, 0.0, 0.0, -4.0/9.0, 0.0, 0.0,
+ -2.0/9.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0/9.0, 0.0, 0.0,
+ 4.0/9.0, 0.0, 0.0, 6.0/9.0, 0.0, 0.0, 8.0/9.0, 0.0, 0.0,
+ -8.0/9.0, 2.0/9.0, 0.0, -6.0/9.0, 2.0/9.0, 0.0, -4.0/9.0, 2.0/9.0, 0.0,
+ -2.0/9.0, 2.0/9.0, 0.0, 0.0, 2.0/9.0, 0.0, 2.0/9.0, 2.0/9.0, 0.0,
+ 4.0/9.0, 2.0/9.0, 0.0, 6.0/9.0, 2.0/9.0, 0.0, 8.0/9.0, 2.0/9.0, 0.0,
+ -8.0/9.0, 4.0/9.0, 0.0, -6.0/9.0, 4.0/9.0, 0.0, -4.0/9.0, 4.0/9.0, 0.0,
+ -2.0/9.0, 4.0/9.0, 0.0, 0.0, 4.0/9.0, 0.0, 2.0/9.0, 4.0/9.0, 0.0,
+ 4.0/9.0, 4.0/9.0, 0.0, 6.0/9.0, 4.0/9.0, 0.0, 8.0/9.0, 4.0/9.0, 0.0,
+ -8.0/9.0, 6.0/9.0, 0.0, -6.0/9.0, 6.0/9.0, 0.0, -4.0/9.0, 6.0/9.0, 0.0,
+ -2.0/9.0, 6.0/9.0, 0.0, 0.0, 6.0/9.0, 0.0, 2.0/9.0, 6.0/9.0, 0.0,
+ 4.0/9.0, 6.0/9.0, 0.0, 6.0/9.0, 6.0/9.0, 0.0, 8.0/9.0, 6.0/9.0, 0.0,
+ -8.0/9.0, 8.0/9.0, 0.0, -6.0/9.0, 8.0/9.0, 0.0, -4.0/9.0, 8.0/9.0, 0.0,
+ -2.0/9.0, 8.0/9.0, 0.0, 0.0, 8.0/9.0, 0.0, 2.0/9.0, 8.0/9.0, 0.0,
+ 4.0/9.0, 8.0/9.0, 0.0, 6.0/9.0, 8.0/9.0, 0.0, 8.0/9.0, 8.0/9.0, 0.0,
+ -8.0/9.0,-8.0/9.0, 2.0/9.0, -6.0/9.0,-8.0/9.0, 2.0/9.0, -4.0/9.0,-8.0/9.0, 2.0/9.0,
+ -2.0/9.0,-8.0/9.0, 2.0/9.0, 0.0,-8.0/9.0, 2.0/9.0, 2.0/9.0,-8.0/9.0, 2.0/9.0,
+ 4.0/9.0,-8.0/9.0, 2.0/9.0, 6.0/9.0,-8.0/9.0, 2.0/9.0, 8.0/9.0,-8.0/9.0, 2.0/9.0,
+ -8.0/9.0,-6.0/9.0, 2.0/9.0, -6.0/9.0,-6.0/9.0, 2.0/9.0, -4.0/9.0,-6.0/9.0, 2.0/9.0,
+ -2.0/9.0,-6.0/9.0, 2.0/9.0, 0.0,-6.0/9.0, 2.0/9.0, 2.0/9.0,-6.0/9.0, 2.0/9.0,
+ 4.0/9.0,-6.0/9.0, 2.0/9.0, 6.0/9.0,-6.0/9.0, 2.0/9.0, 8.0/9.0,-6.0/9.0, 2.0/9.0,
+ -8.0/9.0,-4.0/9.0, 2.0/9.0, -6.0/9.0,-4.0/9.0, 2.0/9.0, -4.0/9.0,-4.0/9.0, 2.0/9.0,
+ -2.0/9.0,-4.0/9.0, 2.0/9.0, 0.0,-4.0/9.0, 2.0/9.0, 2.0/9.0,-4.0/9.0, 2.0/9.0,
+ 4.0/9.0,-4.0/9.0, 2.0/9.0, 6.0/9.0,-4.0/9.0, 2.0/9.0, 8.0/9.0,-4.0/9.0, 2.0/9.0,
+ -8.0/9.0,-2.0/9.0, 2.0/9.0, -6.0/9.0,-2.0/9.0, 2.0/9.0, -4.0/9.0,-2.0/9.0, 2.0/9.0,
+ -2.0/9.0,-2.0/9.0, 2.0/9.0, 0.0,-2.0/9.0, 2.0/9.0, 2.0/9.0,-2.0/9.0, 2.0/9.0,
+ 4.0/9.0,-2.0/9.0, 2.0/9.0, 6.0/9.0,-2.0/9.0, 2.0/9.0, 8.0/9.0,-2.0/9.0, 2.0/9.0,
+ -8.0/9.0, 0.0, 2.0/9.0, -6.0/9.0, 0.0, 2.0/9.0, -4.0/9.0, 0.0, 2.0/9.0,
+ -2.0/9.0, 0.0, 2.0/9.0, 0.0, 0.0, 2.0/9.0, 2.0/9.0, 0.0, 2.0/9.0,
+ 4.0/9.0, 0.0, 2.0/9.0, 6.0/9.0, 0.0, 2.0/9.0, 8.0/9.0, 0.0, 2.0/9.0,
+ -8.0/9.0, 2.0/9.0, 2.0/9.0, -6.0/9.0, 2.0/9.0, 2.0/9.0, -4.0/9.0, 2.0/9.0, 2.0/9.0,
+ -2.0/9.0, 2.0/9.0, 2.0/9.0, 0.0, 2.0/9.0, 2.0/9.0, 2.0/9.0, 2.0/9.0, 2.0/9.0,
+ 4.0/9.0, 2.0/9.0, 2.0/9.0, 6.0/9.0, 2.0/9.0, 2.0/9.0, 8.0/9.0, 2.0/9.0, 2.0/9.0,
+ -8.0/9.0, 4.0/9.0, 2.0/9.0, -6.0/9.0, 4.0/9.0, 2.0/9.0, -4.0/9.0, 4.0/9.0, 2.0/9.0,
+ -2.0/9.0, 4.0/9.0, 2.0/9.0, 0.0, 4.0/9.0, 2.0/9.0, 2.0/9.0, 4.0/9.0, 2.0/9.0,
+ 4.0/9.0, 4.0/9.0, 2.0/9.0, 6.0/9.0, 4.0/9.0, 2.0/9.0, 8.0/9.0, 4.0/9.0, 2.0/9.0,
+ -8.0/9.0, 6.0/9.0, 2.0/9.0, -6.0/9.0, 6.0/9.0, 2.0/9.0, -4.0/9.0, 6.0/9.0, 2.0/9.0,
+ -2.0/9.0, 6.0/9.0, 2.0/9.0, 0.0, 6.0/9.0, 2.0/9.0, 2.0/9.0, 6.0/9.0, 2.0/9.0,
+ 4.0/9.0, 6.0/9.0, 2.0/9.0, 6.0/9.0, 6.0/9.0, 2.0/9.0, 8.0/9.0, 6.0/9.0, 2.0/9.0,
+ -8.0/9.0, 8.0/9.0, 2.0/9.0, -6.0/9.0, 8.0/9.0, 2.0/9.0, -4.0/9.0, 8.0/9.0, 2.0/9.0,
+ -2.0/9.0, 8.0/9.0, 2.0/9.0, 0.0, 8.0/9.0, 2.0/9.0, 2.0/9.0, 8.0/9.0, 2.0/9.0,
+ 4.0/9.0, 8.0/9.0, 2.0/9.0, 6.0/9.0, 8.0/9.0, 2.0/9.0, 8.0/9.0, 8.0/9.0, 2.0/9.0,
+ -8.0/9.0,-8.0/9.0, 4.0/9.0, -6.0/9.0,-8.0/9.0, 4.0/9.0, -4.0/9.0,-8.0/9.0, 4.0/9.0,
+ -2.0/9.0,-8.0/9.0, 4.0/9.0, 0.0,-8.0/9.0, 4.0/9.0, 2.0/9.0,-8.0/9.0, 4.0/9.0,
+ 4.0/9.0,-8.0/9.0, 4.0/9.0, 6.0/9.0,-8.0/9.0, 4.0/9.0, 8.0/9.0,-8.0/9.0, 4.0/9.0,
+ -8.0/9.0,-6.0/9.0, 4.0/9.0, -6.0/9.0,-6.0/9.0, 4.0/9.0, -4.0/9.0,-6.0/9.0, 4.0/9.0,
+ -2.0/9.0,-6.0/9.0, 4.0/9.0, 0.0,-6.0/9.0, 4.0/9.0, 2.0/9.0,-6.0/9.0, 4.0/9.0,
+ 4.0/9.0,-6.0/9.0, 4.0/9.0, 6.0/9.0,-6.0/9.0, 4.0/9.0, 8.0/9.0,-6.0/9.0, 4.0/9.0,
+ -8.0/9.0,-4.0/9.0, 4.0/9.0, -6.0/9.0,-4.0/9.0, 4.0/9.0, -4.0/9.0,-4.0/9.0, 4.0/9.0,
+ -2.0/9.0,-4.0/9.0, 4.0/9.0, 0.0,-4.0/9.0, 4.0/9.0, 2.0/9.0,-4.0/9.0, 4.0/9.0,
+ 4.0/9.0,-4.0/9.0, 4.0/9.0, 6.0/9.0,-4.0/9.0, 4.0/9.0, 8.0/9.0,-4.0/9.0, 4.0/9.0,
+ -8.0/9.0,-2.0/9.0, 4.0/9.0, -6.0/9.0,-2.0/9.0, 4.0/9.0, -4.0/9.0,-2.0/9.0, 4.0/9.0,
+ -2.0/9.0,-2.0/9.0, 4.0/9.0, 0.0,-2.0/9.0, 4.0/9.0, 2.0/9.0,-2.0/9.0, 4.0/9.0,
+ 4.0/9.0,-2.0/9.0, 4.0/9.0, 6.0/9.0,-2.0/9.0, 4.0/9.0, 8.0/9.0,-2.0/9.0, 4.0/9.0,
+ -8.0/9.0, 0.0, 4.0/9.0, -6.0/9.0, 0.0, 4.0/9.0, -4.0/9.0, 0.0, 4.0/9.0,
+ -2.0/9.0, 0.0, 4.0/9.0, 0.0, 0.0, 4.0/9.0, 2.0/9.0, 0.0, 4.0/9.0,
+ 4.0/9.0, 0.0, 4.0/9.0, 6.0/9.0, 0.0, 4.0/9.0, 8.0/9.0, 0.0, 4.0/9.0,
+ -8.0/9.0, 2.0/9.0, 4.0/9.0, -6.0/9.0, 2.0/9.0, 4.0/9.0, -4.0/9.0, 2.0/9.0, 4.0/9.0,
+ -2.0/9.0, 2.0/9.0, 4.0/9.0, 0.0, 2.0/9.0, 4.0/9.0, 2.0/9.0, 2.0/9.0, 4.0/9.0,
+ 4.0/9.0, 2.0/9.0, 4.0/9.0, 6.0/9.0, 2.0/9.0, 4.0/9.0, 8.0/9.0, 2.0/9.0, 4.0/9.0,
+ -8.0/9.0, 4.0/9.0, 4.0/9.0, -6.0/9.0, 4.0/9.0, 4.0/9.0, -4.0/9.0, 4.0/9.0, 4.0/9.0,
+ -2.0/9.0, 4.0/9.0, 4.0/9.0, 0.0, 4.0/9.0, 4.0/9.0, 2.0/9.0, 4.0/9.0, 4.0/9.0,
+ 4.0/9.0, 4.0/9.0, 4.0/9.0, 6.0/9.0, 4.0/9.0, 4.0/9.0, 8.0/9.0, 4.0/9.0, 4.0/9.0,
+ -8.0/9.0, 6.0/9.0, 4.0/9.0, -6.0/9.0, 6.0/9.0, 4.0/9.0, -4.0/9.0, 6.0/9.0, 4.0/9.0,
+ -2.0/9.0, 6.0/9.0, 4.0/9.0, 0.0, 6.0/9.0, 4.0/9.0, 2.0/9.0, 6.0/9.0, 4.0/9.0,
+ 4.0/9.0, 6.0/9.0, 4.0/9.0, 6.0/9.0, 6.0/9.0, 4.0/9.0, 8.0/9.0, 6.0/9.0, 4.0/9.0,
+ -8.0/9.0, 8.0/9.0, 4.0/9.0, -6.0/9.0, 8.0/9.0, 4.0/9.0, -4.0/9.0, 8.0/9.0, 4.0/9.0,
+ -2.0/9.0, 8.0/9.0, 4.0/9.0, 0.0, 8.0/9.0, 4.0/9.0, 2.0/9.0, 8.0/9.0, 4.0/9.0,
+ 4.0/9.0, 8.0/9.0, 4.0/9.0, 6.0/9.0, 8.0/9.0, 4.0/9.0, 8.0/9.0, 8.0/9.0, 4.0/9.0,
+ -8.0/9.0,-8.0/9.0, 6.0/9.0, -6.0/9.0,-8.0/9.0, 6.0/9.0, -4.0/9.0,-8.0/9.0, 6.0/9.0,
+ -2.0/9.0,-8.0/9.0, 6.0/9.0, 0.0,-8.0/9.0, 6.0/9.0, 2.0/9.0,-8.0/9.0, 6.0/9.0,
+ 4.0/9.0,-8.0/9.0, 6.0/9.0, 6.0/9.0,-8.0/9.0, 6.0/9.0, 8.0/9.0,-8.0/9.0, 6.0/9.0,
+ -8.0/9.0,-6.0/9.0, 6.0/9.0, -6.0/9.0,-6.0/9.0, 6.0/9.0, -4.0/9.0,-6.0/9.0, 6.0/9.0,
+ -2.0/9.0,-6.0/9.0, 6.0/9.0, 0.0,-6.0/9.0, 6.0/9.0, 2.0/9.0,-6.0/9.0, 6.0/9.0,
+ 4.0/9.0,-6.0/9.0, 6.0/9.0, 6.0/9.0,-6.0/9.0, 6.0/9.0, 8.0/9.0,-6.0/9.0, 6.0/9.0,
+ -8.0/9.0,-4.0/9.0, 6.0/9.0, -6.0/9.0,-4.0/9.0, 6.0/9.0, -4.0/9.0,-4.0/9.0, 6.0/9.0,
+ -2.0/9.0,-4.0/9.0, 6.0/9.0, 0.0,-4.0/9.0, 6.0/9.0, 2.0/9.0,-4.0/9.0, 6.0/9.0,
+ 4.0/9.0,-4.0/9.0, 6.0/9.0, 6.0/9.0,-4.0/9.0, 6.0/9.0, 8.0/9.0,-4.0/9.0, 6.0/9.0,
+ -8.0/9.0,-2.0/9.0, 6.0/9.0, -6.0/9.0,-2.0/9.0, 6.0/9.0, -4.0/9.0,-2.0/9.0, 6.0/9.0,
+ -2.0/9.0,-2.0/9.0, 6.0/9.0, 0.0,-2.0/9.0, 6.0/9.0, 2.0/9.0,-2.0/9.0, 6.0/9.0,
+ 4.0/9.0,-2.0/9.0, 6.0/9.0, 6.0/9.0,-2.0/9.0, 6.0/9.0, 8.0/9.0,-2.0/9.0, 6.0/9.0,
+ -8.0/9.0, 0.0, 6.0/9.0, -6.0/9.0, 0.0, 6.0/9.0, -4.0/9.0, 0.0, 6.0/9.0,
+ -2.0/9.0, 0.0, 6.0/9.0, 0.0, 0.0, 6.0/9.0, 2.0/9.0, 0.0, 6.0/9.0,
+ 4.0/9.0, 0.0, 6.0/9.0, 6.0/9.0, 0.0, 6.0/9.0, 8.0/9.0, 0.0, 6.0/9.0,
+ -8.0/9.0, 2.0/9.0, 6.0/9.0, -6.0/9.0, 2.0/9.0, 6.0/9.0, -4.0/9.0, 2.0/9.0, 6.0/9.0,
+ -2.0/9.0, 2.0/9.0, 6.0/9.0, 0.0, 2.0/9.0, 6.0/9.0, 2.0/9.0, 2.0/9.0, 6.0/9.0,
+ 4.0/9.0, 2.0/9.0, 6.0/9.0, 6.0/9.0, 2.0/9.0, 6.0/9.0, 8.0/9.0, 2.0/9.0, 6.0/9.0,
+ -8.0/9.0, 4.0/9.0, 6.0/9.0, -6.0/9.0, 4.0/9.0, 6.0/9.0, -4.0/9.0, 4.0/9.0, 6.0/9.0,
+ -2.0/9.0, 4.0/9.0, 6.0/9.0, 0.0, 4.0/9.0, 6.0/9.0, 2.0/9.0, 4.0/9.0, 6.0/9.0,
+ 4.0/9.0, 4.0/9.0, 6.0/9.0, 6.0/9.0, 4.0/9.0, 6.0/9.0, 8.0/9.0, 4.0/9.0, 6.0/9.0,
+ -8.0/9.0, 6.0/9.0, 6.0/9.0, -6.0/9.0, 6.0/9.0, 6.0/9.0, -4.0/9.0, 6.0/9.0, 6.0/9.0,
+ -2.0/9.0, 6.0/9.0, 6.0/9.0, 0.0, 6.0/9.0, 6.0/9.0, 2.0/9.0, 6.0/9.0, 6.0/9.0,
+ 4.0/9.0, 6.0/9.0, 6.0/9.0, 6.0/9.0, 6.0/9.0, 6.0/9.0, 8.0/9.0, 6.0/9.0, 6.0/9.0,
+ -8.0/9.0, 8.0/9.0, 6.0/9.0, -6.0/9.0, 8.0/9.0, 6.0/9.0, -4.0/9.0, 8.0/9.0, 6.0/9.0,
+ -2.0/9.0, 8.0/9.0, 6.0/9.0, 0.0, 8.0/9.0, 6.0/9.0, 2.0/9.0, 8.0/9.0, 6.0/9.0,
+ 4.0/9.0, 8.0/9.0, 6.0/9.0, 6.0/9.0, 8.0/9.0, 6.0/9.0, 8.0/9.0, 8.0/9.0, 6.0/9.0,
+ -8.0/9.0,-8.0/9.0, 8.0/9.0, -6.0/9.0,-8.0/9.0, 8.0/9.0, -4.0/9.0,-8.0/9.0, 8.0/9.0,
+ -2.0/9.0,-8.0/9.0, 8.0/9.0, 0.0,-8.0/9.0, 8.0/9.0, 2.0/9.0,-8.0/9.0, 8.0/9.0,
+ 4.0/9.0,-8.0/9.0, 8.0/9.0, 6.0/9.0,-8.0/9.0, 8.0/9.0, 8.0/9.0,-8.0/9.0, 8.0/9.0,
+ -8.0/9.0,-6.0/9.0, 8.0/9.0, -6.0/9.0,-6.0/9.0, 8.0/9.0, -4.0/9.0,-6.0/9.0, 8.0/9.0,
+ -2.0/9.0,-6.0/9.0, 8.0/9.0, 0.0,-6.0/9.0, 8.0/9.0, 2.0/9.0,-6.0/9.0, 8.0/9.0,
+ 4.0/9.0,-6.0/9.0, 8.0/9.0, 6.0/9.0,-6.0/9.0, 8.0/9.0, 8.0/9.0,-6.0/9.0, 8.0/9.0,
+ -8.0/9.0,-4.0/9.0, 8.0/9.0, -6.0/9.0,-4.0/9.0, 8.0/9.0, -4.0/9.0,-4.0/9.0, 8.0/9.0,
+ -2.0/9.0,-4.0/9.0, 8.0/9.0, 0.0,-4.0/9.0, 8.0/9.0, 2.0/9.0,-4.0/9.0, 8.0/9.0,
+ 4.0/9.0,-4.0/9.0, 8.0/9.0, 6.0/9.0,-4.0/9.0, 8.0/9.0, 8.0/9.0,-4.0/9.0, 8.0/9.0,
+ -8.0/9.0,-2.0/9.0, 8.0/9.0, -6.0/9.0,-2.0/9.0, 8.0/9.0, -4.0/9.0,-2.0/9.0, 8.0/9.0,
+ -2.0/9.0,-2.0/9.0, 8.0/9.0, 0.0,-2.0/9.0, 8.0/9.0, 2.0/9.0,-2.0/9.0, 8.0/9.0,
+ 4.0/9.0,-2.0/9.0, 8.0/9.0, 6.0/9.0,-2.0/9.0, 8.0/9.0, 8.0/9.0,-2.0/9.0, 8.0/9.0,
+ -8.0/9.0, 0.0, 8.0/9.0, -6.0/9.0, 0.0, 8.0/9.0, -4.0/9.0, 0.0, 8.0/9.0,
+ -2.0/9.0, 0.0, 8.0/9.0, 0.0, 0.0, 8.0/9.0, 2.0/9.0, 0.0, 8.0/9.0,
+ 4.0/9.0, 0.0, 8.0/9.0, 6.0/9.0, 0.0, 8.0/9.0, 8.0/9.0, 0.0, 8.0/9.0,
+ -8.0/9.0, 2.0/9.0, 8.0/9.0, -6.0/9.0, 2.0/9.0, 8.0/9.0, -4.0/9.0, 2.0/9.0, 8.0/9.0,
+ -2.0/9.0, 2.0/9.0, 8.0/9.0, 0.0, 2.0/9.0, 8.0/9.0, 2.0/9.0, 2.0/9.0, 8.0/9.0,
+ 4.0/9.0, 2.0/9.0, 8.0/9.0, 6.0/9.0, 2.0/9.0, 8.0/9.0, 8.0/9.0, 2.0/9.0, 8.0/9.0,
+ -8.0/9.0, 4.0/9.0, 8.0/9.0, -6.0/9.0, 4.0/9.0, 8.0/9.0, -4.0/9.0, 4.0/9.0, 8.0/9.0,
+ -2.0/9.0, 4.0/9.0, 8.0/9.0, 0.0, 4.0/9.0, 8.0/9.0, 2.0/9.0, 4.0/9.0, 8.0/9.0,
+ 4.0/9.0, 4.0/9.0, 8.0/9.0, 6.0/9.0, 4.0/9.0, 8.0/9.0, 8.0/9.0, 4.0/9.0, 8.0/9.0,
+ -8.0/9.0, 6.0/9.0, 8.0/9.0, -6.0/9.0, 6.0/9.0, 8.0/9.0, -4.0/9.0, 6.0/9.0, 8.0/9.0,
+ -2.0/9.0, 6.0/9.0, 8.0/9.0, 0.0, 6.0/9.0, 8.0/9.0, 2.0/9.0, 6.0/9.0, 8.0/9.0,
+ 4.0/9.0, 6.0/9.0, 8.0/9.0, 6.0/9.0, 6.0/9.0, 8.0/9.0, 8.0/9.0, 6.0/9.0, 8.0/9.0,
+ -8.0/9.0, 8.0/9.0, 8.0/9.0, -6.0/9.0, 8.0/9.0, 8.0/9.0, -4.0/9.0, 8.0/9.0, 8.0/9.0,
+ -2.0/9.0, 8.0/9.0, 8.0/9.0, 0.0, 8.0/9.0, 8.0/9.0, 2.0/9.0, 8.0/9.0, 8.0/9.0,
+ 4.0/9.0, 8.0/9.0, 8.0/9.0, 6.0/9.0, 8.0/9.0, 8.0/9.0, 8.0/9.0, 8.0/9.0, 8.0/9.0
+};
+
+
+static const REAL *grouptableA[16] =
+{ 0,group5bits,group7bits,group10bits,0,0,0,0,0,0,0,0,0,0,0,0};
+static const REAL *grouptableB1[16] =
+{ 0,group5bits,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
+static const REAL *grouptableB234[16] =
+{ 0,group5bits,group7bits,0,group10bits,0,0,0,0,0,0,0,0,0,0,0};
+
+static const int codelengthtableA[16] =
+{ 0, 5, 7, 10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+static const int codelengthtableB1[16] =
+{ 0, 5, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
+static const int codelengthtableB2[16] =
+{ 0, 5, 7, 3, 10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16 };
+static const int codelengthtableB3[8] = { 0, 5, 7, 3, 10, 4, 5, 16 };
+static const int codelengthtableB4[4] = { 0, 5, 7, 16 };
+
+
+static const REAL factortableA[16] =
+{ 0.0, 1.0/2.0, 1.0/4.0, 1.0/8.0,
+ 1.0/8.0, 1.0/16.0, 1.0/32.0, 1.0/64.0,
+ 1.0/128.0, 1.0/256.0, 1.0/512.0, 1.0/1024.0,
+ 1.0/2048.0, 1.0/4096.0, 1.0/8192.0, 1.0/16384.0 };
+static const REAL factortableB1[16] =
+{ 0.0, 1.0/2.0, 1.0/4.0, 1.0/8.0,
+ 1.0/16.0, 1.0/32.0, 1.0/64.0, 1.0/128.0,
+ 1.0/256.0, 1.0/512.0, 1.0/1024.0, 1.0/2048.0,
+ 1.0/4096.0, 1.0/8192.0, 1.0/16384.0, 1.0/32768.0 };
+static const REAL factortableB2[16] =
+{ 0.0, 1.0/2.0, 1.0/4.0, 1.0/4.0,
+ 1.0/8.0, 1.0/8.0, 1.0/16.0, 1.0/32.0,
+ 1.0/64.0, 1.0/128.0, 1.0/256.0, 1.0/512.0,
+ 1.0/1024.0, 1.0/2048.0, 1.0/4096.0, 1.0/32768.0 };
+static const REAL factortableB3[8] =
+{ 0.0, 1.0/2.0, 1.0/4.0, 1.0/4.0, 1.0/8.0, 1.0/8.0, 1.0/16.0, 1.0/32768.0 };
+static const REAL factortableB4[4] = { 0.0, 1.0/2.0, 1.0/4.0, 1.0/32768.0 };
+
+
+static const REAL ctableA[16]=
+{ 0.0, 1.33333333333, 1.60000000000, 1.77777777777,
+ 1.06666666666, 1.03225806452, 1.01587301587, 1.00787401575,
+ 1.00392156863, 1.00195694716, 1.00097751711, 1.00048851979,
+ 1.00024420024, 1.00012208522, 1.00006103888, 1.00003051851};
+static const REAL ctableB1[16]=
+{ 0.0, 1.33333333333, 1.14285714286, 1.06666666666,
+ 1.03225806452, 1.01587301587, 1.00787401575, 1.00392156863,
+ 1.00195694716, 1.00097751711, 1.00048851979, 1.00024420024,
+ 1.00012208522, 1.00006103888, 1.00003051851, 1.00001525902};
+static const REAL ctableB2[16] =
+{ 0.0, 1.33333333333, 1.60000000000, 1.14285714286,
+ 1.77777777777, 1.06666666666, 1.03225806452, 1.01587301587,
+ 1.00787401575, 1.00392156863, 1.00195694716, 1.00097751711,
+ 1.00048851979, 1.00024420024, 1.00012208522, 1.00001525902};
+static const REAL ctableB3[8] =
+{ 0.0, 1.33333333333, 1.60000000000, 1.14285714286,
+ 1.77777777777, 1.06666666666, 1.03225806452, 1.00001525902 };
+static const REAL ctableB4[4] =
+{ 0.0, 1.33333333333, 1.60000000000, 1.00001525902 };
+
+
+static const REAL dtableA[16]=
+{ 0.0, 0.50000000000, 0.50000000000, 0.50000000000,
+ 0.12500000000, 0.06250000000, 0.03125000000, 0.01562500000,
+ 0.00781250000, 0.00390625000, 0.00195312500, 0.00097656250,
+ 0.00048828125, 0.00024414063, 0.00012207031, 0.00006103516};
+
+static const REAL dtableB1[16]=
+{ 0.0, 0.50000000000, 0.25000000000, 0.12500000000,
+ 0.06250000000, 0.03125000000, 0.01562500000, 0.00781250000,
+ 0.00390625000, 0.00195312500, 0.00097656250, 0.00048828125,
+ 0.00024414063, 0.00012207031, 0.00006103516, 0.00003051758};
+
+static const REAL dtableB2[16]=
+{ 0.0, 0.50000000000, 0.50000000000, 0.25000000000,
+ 0.50000000000, 0.12500000000, 0.06250000000, 0.03125000000,
+ 0.01562500000, 0.00781250000, 0.00390625000, 0.00195312500,
+ 0.00097656250, 0.00048828125, 0.00024414063, 0.00003051758};
+
+static const REAL dtableB3[8]=
+{ 0.0, 0.50000000000, 0.50000000000, 0.25000000000,
+ 0.50000000000, 0.12500000000, 0.06250000000, 0.00003051758};
+
+static const REAL dtableB4[4]=
+{0.0, 0.50000000000, 0.50000000000, 0.00003051758};
+
+
+
+
+
+
+#endif
diff --git a/mpeglib/lib/splay/mpegAudioBitWindow.cpp b/mpeglib/lib/splay/mpegAudioBitWindow.cpp
new file mode 100644
index 00000000..5e63f1fc
--- /dev/null
+++ b/mpeglib/lib/splay/mpegAudioBitWindow.cpp
@@ -0,0 +1,41 @@
+/*
+ bitwindow 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 "mpegAudioBitWindow.h"
+
+
+#include <iostream>
+
+using namespace std;
+
+int MpegAudioBitWindow::getCanReadBits() {
+ int p=bitindex>>3;
+ int bytes=point - p;
+ int bits=bytes*8+(bitindex&7);
+ cout << "point:"<<point
+ << " p:"<<p
+ << " bytes:"<<bytes
+ <<" bitindex:"<<bitindex<<" can read:"<<bits<<endl;
+ return bits;
+}
+
+void MpegAudioBitWindow::wrap(void) {
+ int p=bitindex>>3;
+ point&=(WINDOWSIZE-1);
+
+ if(p>=point) {
+ for(register int i=4;i<point;i++)
+ buffer[WINDOWSIZE+i]=buffer[i];
+ }
+ *((int *)(buffer+WINDOWSIZE))=*((int *)buffer);
+}
diff --git a/mpeglib/lib/splay/mpegAudioBitWindow.h b/mpeglib/lib/splay/mpegAudioBitWindow.h
new file mode 100644
index 00000000..f7a2f64c
--- /dev/null
+++ b/mpeglib/lib/splay/mpegAudioBitWindow.h
@@ -0,0 +1,141 @@
+/*
+ bitwindow 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 __MPEGBITWINDOW_H
+#define __MPEGBITWINDOW_H
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef WORDS_BIGENDIAN
+#define _KEY 0
+#else
+#define _KEY 3
+#endif
+
+
+
+#define WINDOWSIZE 4096
+#define BITWINDOWSIZE (WINDOWSIZE*8)
+
+
+class MpegAudioBitWindow {
+
+ int point,bitindex;
+ char buffer[2*WINDOWSIZE];
+
+ public:
+ MpegAudioBitWindow(){bitindex=point=0;}
+
+ inline void initialize(void) {bitindex=point=0;}
+ inline int gettotalbit(void) const {return bitindex;}
+
+ inline void putbyte(int c) {buffer[point&(WINDOWSIZE-1)]=c;point++;}
+ void wrap(void);
+ inline void rewind(int bits) {bitindex-=bits;}
+ inline void forward(int bits) {bitindex+=bits;}
+
+ // returns number of bits which can safley read
+ int getCanReadBits();
+
+
+ //
+ // Ugly bitgetting inline functions for higher speed
+ //
+
+
+ inline int getbits(int bits) {
+ union
+ {
+ char store[4];
+ int current;
+ }u;
+ int bi;
+
+ if(!bits)return 0;
+
+ u.current=0;
+ bi=(bitindex&7);
+ u.store[_KEY]=buffer[(bitindex>>3)&(WINDOWSIZE-1)]<<bi;
+ //u.store[_KEY]=buffer[bitindex>>3]<<bi;
+ bi=8-bi;
+ bitindex+=bi;
+
+ while(bits) {
+ if(!bi) {
+ u.store[_KEY]=buffer[(bitindex>>3)&(WINDOWSIZE-1)];
+ //u.store[_KEY]=buffer[bitindex>>3];
+ bitindex+=8;
+ bi=8;
+ }
+
+ if(bits>=bi) {
+ u.current<<=bi;
+ bits-=bi;
+ bi=0;
+ }
+ else {
+ u.current<<=bits;
+ bi-=bits;
+ bits=0;
+ }
+ }
+ bitindex-=bi;
+
+ return (u.current>>8);
+ }
+
+
+ int getbit(void) {
+ register int r=(buffer[(bitindex>>3)&(WINDOWSIZE-1)]>>(7-(bitindex&7)))&1;
+ //register int r=(buffer[bitindex>>3]>>(7-(bitindex&7)))&1;
+ bitindex++;
+ return r;
+ }
+
+ // no range check version
+ inline int getbits9_f(int bits) {
+ register unsigned short a;
+ {
+ int offset=bitindex>>3;
+ a=(((unsigned char)buffer[offset])<<8)|((unsigned char)buffer[offset+1]);
+ }
+ a<<=(bitindex&7);
+ bitindex+=bits;
+ return (int)((unsigned int)(a>>(16-bits)));
+ }
+
+ // range check version
+ int getbits9(int bits) {
+ register unsigned short a;
+ {
+ int offset=(bitindex>>3)&(WINDOWSIZE-1);
+ a=(((unsigned char)buffer[offset])<<8)|((unsigned char)buffer[offset+1]);
+ }
+
+ a<<=(bitindex&7);
+ bitindex+=bits;
+ return (int)((unsigned int)(a>>(16-bits)));
+ }
+
+ int peek8() {
+ int offset = (bitindex>>3)&(WINDOWSIZE-1), a;
+ a=(((unsigned char)buffer[offset])<<8) | ((unsigned char)buffer[offset+1]);
+ return (a >> (8-(bitindex&7))) & 0xff;
+ }
+
+
+};
+#endif
diff --git a/mpeglib/lib/splay/mpegAudioFrame.cpp b/mpeglib/lib/splay/mpegAudioFrame.cpp
new file mode 100644
index 00000000..807a23a6
--- /dev/null
+++ b/mpeglib/lib/splay/mpegAudioFrame.cpp
@@ -0,0 +1,200 @@
+/*
+ converts raw mpeg audio stream data into mpeg I encoded audio frames/packets
+ 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 "mpegAudioFrame.h"
+
+#define MPEGAUDIOFRAMESIZE 4096
+
+#define FRAME_SYNC 0
+#define FRAME_CHECK_HEADER_1 1
+#define FRAME_CHECK_HEADER_2 2
+
+#include <iostream>
+
+using namespace std;
+
+MpegAudioFrame::MpegAudioFrame():Framer(MPEGAUDIOFRAMESIZE) {
+ mpegAudioHeader=new MpegAudioHeader();
+}
+
+
+MpegAudioFrame::~MpegAudioFrame() {
+ delete mpegAudioHeader;
+}
+
+
+void MpegAudioFrame::unsync(RawDataBuffer* store,int ) {
+ // invalidate header in buffer
+ unsigned char* start=store->ptr();
+ start[0]=0x0;
+ start[1]=0x0;
+ store->setpos(0);
+ find_frame_state=FRAME_SYNC;
+ framesize=0;
+}
+
+
+/**
+ here we parse byte by byte the raw input, first
+ we search for the magic bytes: 0xfffx, then
+ we read the remaining 2 bytes for the header,
+ check if they are "wrong" in a mpeg I audio special way.
+ If everything is fine, we continue with the next state.
+
+ Note: we can be sure here, that the "store" can at least
+ store 4 bytes.
+*/
+int MpegAudioFrame::find_frame(RawDataBuffer* input_buffer,
+ RawDataBuffer* store_buffer) {
+ unsigned char* store=store_buffer->current();
+ int back=false;
+
+ if (find_frame_state == FRAME_SYNC) {
+ if (store_buffer->pos() != 0) {
+ cout << "store buffer not at beginning MpegAudioFrame::find_frame"<<endl;
+ cout << "current state requires this"<<endl;
+ exit(0);
+ }
+ }
+
+ while(input_buffer->eof()==false) {
+ // search for sync bytes
+ unsigned char* input=input_buffer->current();
+ if (find_frame_state == FRAME_SYNC) {
+ while(input_buffer->eof() == false) {
+ input=input_buffer->current();
+ // shift
+ store[0]=store[1];
+ store[1]=input[0];
+ input_buffer->inc();
+
+ if (store[0] != 0xff) {
+ continue;
+ }
+ // upper 4 bit are syncword, except bit one
+ // which is layer 2.5 indicator.
+ if ( (store[1] & 0xe0) != 0xe0) {
+ continue;
+ }
+
+ // found header, now check if other info is ok, too.
+ store_buffer->setpos(2);
+ find_frame_state=FRAME_CHECK_HEADER_1;
+ break;
+ }
+ // back to "main loop"
+ continue;
+ }
+ // ok, try to read two other bytes and then validate the header
+ if (find_frame_state == FRAME_CHECK_HEADER_1) {
+ store[2]=input[0];
+ input_buffer->inc();
+ find_frame_state=FRAME_CHECK_HEADER_2;
+ // back to main loop
+ continue;
+ }
+ if (find_frame_state == FRAME_CHECK_HEADER_2) {
+ store[3]=input[0];
+ input_buffer->inc();
+ }
+
+ // ok, read 4 header bytes. Now check the validity of the
+ // header.
+ int lHeaderOk;
+ lHeaderOk=mpegAudioHeader->parseHeader(store);
+ if (lHeaderOk == false) {
+ find_frame_state=FRAME_SYNC;
+ store_buffer->setpos(0);
+ // go back to "sync for frame"
+ continue;
+ }
+ framesize=mpegAudioHeader->getFramesize();
+ // if framesize > max mepg framsize its an error
+ if (framesize+4 >= store_buffer->size()) {
+ find_frame_state=FRAME_SYNC;
+ store_buffer->setpos(0);
+ // go back to "sync for frame"
+ continue;
+ }
+ // don't allow stupid framesizes:
+ if (framesize <= 4) {
+ find_frame_state=FRAME_SYNC;
+ store_buffer->setpos(0);
+ continue;
+ }
+ // yup! found valid header. forward states
+ store_buffer->setpos(4);
+ back=true;
+ break;
+ }
+ return back;
+}
+
+
+/**
+ here we read data until len=framesize.
+ Then we go to the HAS_FRAME state.
+*/
+int MpegAudioFrame::read_frame(RawDataBuffer* input_buffer,
+ RawDataBuffer* store_buffer) {
+ unsigned char* store=store_buffer->current();
+
+ while(input_buffer->eof()==false) {
+ int has=store_buffer->pos();
+ int need=framesize-has;
+ if(need == 0) {
+ // yup! frame fully read. forward states.
+ // go to end state for main_state.
+ return true;
+ }
+ // try to do a memcpy for speed.
+ int can=input_buffer->untilend();
+ if(can > need) {
+ can=need;
+ }
+ unsigned char* input=input_buffer->current();
+ memcpy(store,input,can);
+ store_buffer->inc(can);
+ input_buffer->inc(can);
+ }
+ int need=framesize-store_buffer->pos();
+
+ if(need == 0) {
+ // yup! frame fully read. forward states.
+ // go to end state for main_state.
+ return true;
+ }
+ return false;
+}
+
+
+
+void MpegAudioFrame::printPrivateStates() {
+ cout << "MpegAudioFrame::printPrivateStates"<<endl;
+ switch(find_frame_state) {
+ case FRAME_SYNC:
+ cout << "frame_state: FRAME_SYNC"<<endl;
+ break;
+ case FRAME_CHECK_HEADER_1:
+ cout << "frame_state: FRAME_CHECK_HEADER_1"<<endl;
+ break;
+ case FRAME_CHECK_HEADER_2:
+ cout << "frame_state: FRAME_CHECK_HEADER_2"<<endl;
+ break;
+ default:
+ cout << "unknown illegal frame_state:"<<find_frame_state<<endl;
+ }
+
+
+}
+
diff --git a/mpeglib/lib/splay/mpegAudioFrame.h b/mpeglib/lib/splay/mpegAudioFrame.h
new file mode 100644
index 00000000..8b4f6c4f
--- /dev/null
+++ b/mpeglib/lib/splay/mpegAudioFrame.h
@@ -0,0 +1,66 @@
+/*
+ converts raw mpeg audio stream data into mpeg I encoded audio frames/packets
+ 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 __MPEGAUDIOFRAME_H
+#define __MPEGAUDIOFRAME_H
+
+#include "mpegAudioHeader.h"
+#include "../frame/framer.h"
+#include <kdemacros.h>
+
+/*
+ Here we are framing from raw to mpeg audio.
+*/
+
+
+
+
+class KDE_EXPORT MpegAudioFrame : public Framer {
+
+ // max size of buffer is:
+ // header: 4
+ // max bitrate: 448
+ // min freq: 22050
+ // padding: 1
+ // ------------------
+ // maxsize: 4+144000*max(bitrate)/min(freq)+1 ca: 2931 byte
+ // then we add a "sentinel" at the end these are 4 byte.
+ // so we should be ok, with a 4KB buffer.
+
+ // internal, how much data we need to read
+ int framesize;
+
+ // internall, for header searching
+ int find_frame_state;
+
+ // internal use for header parsing+validating
+ MpegAudioHeader* mpegAudioHeader;
+
+ public:
+ MpegAudioFrame();
+ ~MpegAudioFrame();
+
+
+ private:
+
+ int find_frame(RawDataBuffer* input,RawDataBuffer* store);
+ int read_frame(RawDataBuffer* input,RawDataBuffer* store);
+
+ void unsync(RawDataBuffer* store,int lReset);
+ void printPrivateStates();
+
+};
+
+
+#endif
diff --git a/mpeglib/lib/splay/mpegAudioHeader.cpp b/mpeglib/lib/splay/mpegAudioHeader.cpp
new file mode 100644
index 00000000..7e34b212
--- /dev/null
+++ b/mpeglib/lib/splay/mpegAudioHeader.cpp
@@ -0,0 +1,268 @@
+/*
+ stores information after we found a header.
+ 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 "mpegAudioHeader.h"
+
+#define DEBUG_HEADER(x)
+//#define DEBUG_HEADER(x) x
+
+
+#include <iostream>
+
+using namespace std;
+
+static const int frequencies[3][3]= {
+ {44100,48000,32000}, // MPEG 1
+ {22050,24000,16000}, // MPEG 2
+ {11025,12000,8000} // MPEG 2.5
+};
+
+static int translate[3][2][16] = { { { 2,0,0,2,2,2,3,3,3,3,3,3,3,3,3,2 } ,
+ { 2,0,0,0,0,0,0,2,2,2,3,3,3,3,3,2 } } ,
+ { { 2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2 } ,
+ { 2,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2 } } ,
+ { { 2,1,1,2,2,2,3,3,3,3,3,3,3,3,3,2 } ,
+ { 2,1,1,1,1,1,1,2,2,2,3,3,3,3,3,2 } } };
+
+
+static int sblims[5] = { 8 , 12 , 27, 30 , 30 };
+
+
+static const int bitrate[2][3][15]= {
+ // MPEG 1
+ {{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448},
+ {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384},
+ {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320}},
+
+ // MPEG 2
+ {{0,32,48,56,64,80,96,112,128,144,160,176,192,224,256},
+ {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160},
+ {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160}}
+};
+
+
+MpegAudioHeader::MpegAudioHeader() {
+
+}
+
+
+MpegAudioHeader::~MpegAudioHeader() {
+}
+
+
+int MpegAudioHeader::getChannelbitrate() {
+ cout << "getChannelbitrate not implemented"<<endl;
+ return 0;
+}
+
+int MpegAudioHeader::parseHeader(unsigned char* buf){
+
+ int c;
+ int mpeg25=false;
+
+
+ // Analyzing
+ header[0]=buf[0];
+ header[1]=buf[1];
+ header[2]=buf[2];
+ header[3]=buf[3];
+
+ c=buf[1];
+ lmpeg25=false;
+ if ( (c&0xf0) == 0xe0) {
+ lmpeg25=true;
+ }
+
+ c&=0xf;
+ protection=c&1;
+ layer=4-((c>>1)&3);
+ // we catch the layer==4 error later, for now go on with parsing
+ version=(int)(((c>>3)&1)^1);
+ if ((version==0) && lmpeg25) {
+ DEBUG_HEADER(cout << "wrong lsf/mpeg25 combination"<<endl;)
+ return false;
+ }
+ c=buf[2];
+
+ c=((c))>>1;
+ padding=(c&1);
+ c>>=1;
+ frequency=(int)(c&3);
+ c>>=2;
+ bitrateindex=(int)c;
+ if(bitrateindex>=15) {
+ DEBUG_HEADER(cout << "bitrateindex error"<<endl;)
+ return false;
+ }
+ c=buf[3];
+
+ c=((unsigned int)(c))>>4;
+ extendedmode=c&3;
+ mode=(int)(c>>2);
+
+
+ // Making information
+ inputstereo= (mode==_MODE_SINGLE)?0:1;
+
+ //
+ // frequency can be 0,1 or 2 but the mask above allows 3 as well
+ // check now.
+ if (frequency > 2) {
+ DEBUG_HEADER(cout << "frequency value out of range"<<endl;)
+ return false;
+ }
+
+ //
+ // does not belong here should be in the layer specific parts. [START]
+ //
+
+ switch(layer) {
+ case 3:
+ subbandnumber=0;
+ stereobound=0;
+ tableindex=0;
+ break;
+ case 2:
+ tableindex = translate[frequency][inputstereo][bitrateindex];
+ subbandnumber = sblims[tableindex];
+ stereobound = subbandnumber;
+ /*
+ Now merge the tableindex, for the bitalloclengthtable
+ */
+ tableindex=tableindex>>1;
+ if(mode==_MODE_SINGLE)stereobound=0;
+ if(mode==_MODE_JOINT)stereobound=(extendedmode+1)<<2;
+
+ break;
+ case 1:
+ subbandnumber=MAXSUBBAND;
+ stereobound=subbandnumber;
+ tableindex=0;
+ if(mode==_MODE_SINGLE)stereobound=0;
+ if(mode==_MODE_JOINT)stereobound=(extendedmode+1)<<2;
+ break;
+ default:
+ DEBUG_HEADER(cout <<"unknown layer"<<endl;)
+ return false;
+ }
+
+ //
+ // does not belong here should be in the layer specific parts. [END]
+ //
+ frequencyHz=frequencies[version+lmpeg25][frequency];
+ // framesize & slots
+ if(layer==1) {
+ if (frequencyHz <= 0) {
+ return false;
+ }
+ framesize=(12000*bitrate[version][0][bitrateindex])/frequencyHz;
+
+ if(frequency==_FREQUENCY_44100 && padding)framesize++;
+ framesize<<=2;
+ } else {
+ int freq=frequencyHz<<version;
+ if (freq <= 0) {
+ return false;
+ }
+ framesize=(144000*bitrate[version][layer-1][bitrateindex])/freq;
+
+ if(padding)framesize++;
+ if(layer==3) {
+ if(version)
+ layer3slots=framesize-((mode==_MODE_SINGLE)?9:17)
+ -(protection?0:2)
+ -4;
+ else
+ layer3slots=framesize-((mode==_MODE_SINGLE)?17:32)
+ -(protection?0:2)
+ -4;
+ }
+ }
+ if (framesize <= 0) {
+ DEBUG_HEADER(cout << "framesize negative"<<endl;)
+ return false;
+ }
+ return true;
+
+}
+
+
+int MpegAudioHeader::getpcmperframe() {
+ int s;
+
+ s=32;
+ if(layer==3) {
+ s*=18;
+ if(version==0)s*=2;
+ }
+ else {
+ s*=SCALEBLOCK;
+ if(layer==2)s*=3;
+ }
+
+ return s;
+}
+
+
+void MpegAudioHeader::copyTo(MpegAudioHeader* dest) {
+ dest->protection=protection;
+ dest->layer=layer;
+ dest->version=version;
+ dest->padding=padding;
+ dest->frequency=frequency;
+ dest->frequencyHz=frequencyHz;
+ dest->bitrateindex=bitrateindex;
+ dest->extendedmode=extendedmode;
+ dest->mode=mode;
+ dest->inputstereo=inputstereo;
+ dest->channelbitrate=channelbitrate;
+ dest->tableindex=tableindex;
+ dest->subbandnumber=subbandnumber;
+ dest->stereobound=stereobound;
+ dest->framesize=framesize;
+ dest->layer3slots=layer3slots;
+ dest->lmpeg25=lmpeg25;
+}
+
+
+void MpegAudioHeader::print(const char* name) {
+ cout << "MpegAudioHeader [START]:"<<name<<endl;
+ printf("header:%1x%1x%1x%1x\n",header[0],header[1],header[2],header[3]);
+ cout << "getProtection:"<<getProtection()<<endl;
+ cout << "getLayer:"<<getLayer()<<endl;
+ cout << "getVersion:"<<getVersion()<<endl;
+ cout << "getPadding:"<<getPadding()<<endl;
+ cout << "getFrequency:"<<getFrequency()<<endl;
+ cout << "getFrequencyHz:"<<getFrequencyHz()<<endl;
+ cout << "getBitrateindex:"<<getBitrateindex()<<endl;
+ cout << "getExtendedmode:"<<getExtendedmode()<<endl;
+ cout << "getMode():"<<getMode()<<endl;
+ cout << "getInputstereo:"<<getInputstereo()<<endl;
+ cout << "getChannelbitrate:"<<getChannelbitrate()<<endl;
+ cout << "getTableindex:"<<getTableindex()<<endl;
+ cout << "getSubbandnumber:"<<getSubbandnumber()<<endl;
+ cout << "getStereobound:"<<getStereobound()<<endl;
+ cout << "getFramesize:"<<getFramesize()<<endl;
+ cout << "getLayer3slots:"<<getLayer3slots()<<endl;
+ cout << "getpcmperframe:"<<getpcmperframe()<<endl;
+ cout << "MpegAudioHeader [END]:"<<name<<endl;
+
+}
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/splay/mpegAudioHeader.h b/mpeglib/lib/splay/mpegAudioHeader.h
new file mode 100644
index 00000000..ff5b885a
--- /dev/null
+++ b/mpeglib/lib/splay/mpegAudioHeader.h
@@ -0,0 +1,101 @@
+/*
+ stores information after we found a header.
+ 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 __MPEGHEADERINFO_H
+#define __MPEGHEADERINFO_H
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define _FREQUENCY_44100 0
+#define _FREQUENCY_48000 1
+#define _FREQUENCY_32000 2
+
+#define _MODE_FULLSTEREO 0
+#define _MODE_JOINT 1
+#define _MODE_DUAL 2
+#define _MODE_SINGLE 3
+
+#define _VERSION_1 0
+#define _VERSION_2 1
+
+
+#define MAXSUBBAND 32
+#define SCALEBLOCK 12
+
+
+
+class MpegAudioHeader {
+
+ int protection;
+ int layer;
+ int version;
+ int padding;
+ int frequency;
+ int frequencyHz;
+ int bitrateindex;
+ int extendedmode;
+ int mode;
+ int inputstereo;
+ int channelbitrate;
+ int tableindex;
+ int subbandnumber;
+ int stereobound;
+ int framesize;
+ int layer3slots;
+ int lmpeg25;
+ unsigned char header[4];
+
+ public:
+ MpegAudioHeader();
+ ~MpegAudioHeader();
+
+ int parseHeader(unsigned char* buf);
+
+ inline int getProtection() { return protection; }
+ inline int getLayer() { return layer; }
+ inline int getVersion() { return version; }
+ inline int getPadding() { return padding; }
+ inline int getFrequency() { return frequency; }
+ inline int getFrequencyHz() { return frequencyHz; }
+ inline int getBitrateindex() { return bitrateindex; }
+ inline int getExtendedmode() { return extendedmode; }
+ inline int getMode() { return mode; }
+ inline int getInputstereo() { return inputstereo; }
+ inline int getFramesize() { return framesize; }
+ inline int getLayer25() { return lmpeg25; }
+
+ // MPEG layer 2
+ inline int getTableindex() { return tableindex; }
+ // MPEG layer 1/2
+ inline int getSubbandnumber() { return subbandnumber; }
+ inline int getStereobound() { return stereobound; }
+ // MPEG layer 3
+ inline int getLayer3slots() { return layer3slots; }
+
+ int getChannelbitrate();
+
+
+ inline unsigned char* getHeader() { return header; }
+ int getpcmperframe();
+
+
+ void copyTo(MpegAudioHeader* dest);
+
+ void print(const char* name);
+ void printStates(const char* name);
+};
+#endif
diff --git a/mpeglib/lib/splay/mpegAudioInfo.cpp b/mpeglib/lib/splay/mpegAudioInfo.cpp
new file mode 100644
index 00000000..981b5bd6
--- /dev/null
+++ b/mpeglib/lib/splay/mpegAudioInfo.cpp
@@ -0,0 +1,262 @@
+/*
+ length detection etc.. for mpeg audio
+ 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 _FROM_SOURCE
+#define _FROM_SOURCE 1
+#endif
+#include "dxHead.h"
+#include <string.h>
+#include "mpegAudioInfo.h"
+#include "mpegAudioHeader.h"
+#include "mpegAudioStream.h"
+#include "mpegAudioFrame.h"
+
+#include <iostream>
+
+using namespace std;
+
+#define _NEED_LENGTH 1
+#define _NEED_ID3 2
+#define _NEED_NOTHING 3
+
+
+MpegAudioInfo::MpegAudioInfo(FileAccess* input) {
+ xHeadData=new XHEADDATA();
+ xHeadData->toc=new unsigned char[101];
+ lXingVBR=false;
+ id3=new ID3TAG();
+ this->input=input;
+ mpegAudioFrame =new MpegAudioFrame();
+ mpegAudioStream=new MpegAudioStream();
+ mpegAudioHeader=new MpegAudioHeader();
+ reset();
+}
+
+
+MpegAudioInfo::~MpegAudioInfo() {
+ delete[] (xHeadData->toc);
+ delete xHeadData;
+ delete id3;
+ delete mpegAudioStream;
+ delete mpegAudioHeader;
+ delete mpegAudioFrame;
+}
+
+
+int MpegAudioInfo::getByteDirect() {
+ unsigned char byte;
+ if (input->read((char*)&byte,1) != 1) {
+ leof=true;
+ return -1;
+ }
+ return (int)byte;
+}
+
+void MpegAudioInfo::reset() {
+ length=0;
+ initState=_NEED_LENGTH;
+ lNeedInit=true;
+}
+
+
+int MpegAudioInfo::getNeedInit() {
+ return lNeedInit;
+}
+
+void MpegAudioInfo::setNeedInit(int lNeedInit) {
+ this->lNeedInit=lNeedInit;
+}
+
+
+int MpegAudioInfo::initialize() {
+ long fileSize=input->getByteLength();
+ switch(initState) {
+ case _NEED_NOTHING:
+ return true;
+ break;
+ case _NEED_LENGTH:
+ if (initializeLength(fileSize) == true) {
+ initState=_NEED_ID3;
+ }
+ return false;
+ case _NEED_ID3:
+ if (initializeID3(fileSize) == true) {
+ initState=_NEED_NOTHING;
+ return true;
+ }
+ return false;
+ default:
+ cout << "unknown initState in MpegAudioInfo::initialize"<<endl;
+ exit(0);
+ }
+ // never happens
+ return true;
+}
+
+
+int MpegAudioInfo::initializeLength(long fileSize) {
+ // if we are streaming don't touch the stream for length detection
+ if (fileSize == 0) {
+ return true;
+ }
+ int back=getFrame(mpegAudioFrame);
+ if (back != true) {
+ return back;
+ }
+ // found a valid frame (back == true)
+ // store information in header.
+ if (mpegAudioHeader->parseHeader(mpegAudioFrame->outdata()) == false) {
+ cout << "parse header false"<<endl;
+ return false;
+ }
+ calculateLength(fileSize);
+ return back;
+}
+
+int MpegAudioInfo::initializeID3(long fileSize) {
+ int pos=input->getBytePosition();
+ if (input->seek(fileSize-128)<0) {
+ return true;
+ }
+ parseID3();
+ input->seek(pos);
+ return true;
+}
+
+
+long MpegAudioInfo::getLength() {
+ return length;
+}
+
+
+void MpegAudioInfo::calculateLength(long fileSize) {
+
+ int totalframe=0;
+ int framesize=mpegAudioHeader->getFramesize();
+ if (framesize > 0) {
+ totalframe=fileSize/framesize;
+
+ if (parseXing(mpegAudioFrame->outdata(),mpegAudioFrame->len()) == true) {
+ lXingVBR=true;
+ totalframe=xHeadData->frames;
+ }
+ }
+
+ float pcm=mpegAudioHeader->getpcmperframe();
+ float wavfilesize=(totalframe*pcm);
+ float frequence=(float)mpegAudioHeader->getFrequencyHz();
+ length=0;
+ if (frequence != 0) {
+ length=(int)(wavfilesize/frequence);
+ }
+}
+
+
+int MpegAudioInfo::parseXing(unsigned char* frame,int size) {
+
+ int back=false;
+ if (size < 152) {
+ return false;
+ }
+ back=GetXingHeader(xHeadData,(unsigned char*)frame);
+ return back;
+
+}
+
+
+
+long MpegAudioInfo::getSeekPosition(int second) {
+ float length=getLength();
+ long fileSize=input->getByteLength();
+ long pos=0;
+ if (length<1.0) {
+ return 0;
+ }
+ float percent=(float)second/length;
+
+ if (lXingVBR) {
+ pos=SeekPoint(xHeadData->toc,(int)fileSize,100.0*percent);
+ return pos;
+ }
+ pos=(long)(percent*(float)fileSize);
+ return pos;
+}
+
+
+void MpegAudioInfo::parseID3() {
+
+ id3->name [0]=0;
+ id3->artist [0]=0;
+ id3->album [0]=0;
+ id3->year [0]=0;
+ id3->comment [0]=0;
+ id3->genre =0;
+
+ leof=false;
+
+ while(leof == false) {
+ if(getByteDirect()==0x54)
+ if(getByteDirect()==0x41)
+ if(getByteDirect()==0x47) {
+ input->read((char*)&id3->name ,30);id3->name[30]=0;
+ input->read((char*)&id3->artist ,30);id3->artist[30]=0;
+ input->read((char*)&id3->album ,30);id3->album[30]=0;
+ input->read((char*)&id3->year , 4);id3->year[4]=0;
+ input->read((char*)&id3->comment ,30);id3->comment[30]=0;
+ input->read((char*)&id3->genre ,1);
+ return;
+ }
+ }
+}
+
+
+
+void MpegAudioInfo::print(const char* msg) {
+ cout << "MpegAudioInfo:"<<msg<<endl;
+ cout << "Length (sec):"<<length<<endl;
+ cout << "VBR:"<<lXingVBR<<endl;
+ cout << "ID3: Name:"<<id3->name<<endl;
+ cout << "ID3: Artist:"<<id3->artist<<endl;
+ cout << "ID3: Album:"<<id3->album<<endl;
+ cout << "ID3: year:"<<id3->year<<endl;
+ cout << "ID3: genre:"<<(int)(id3->genre)<<endl;
+ cout << "ID3: comment:"<<id3->comment<<endl;
+
+}
+
+
+int MpegAudioInfo::getFrame(MpegAudioFrame* frame) {
+ int state=frame->getState();
+ switch(state) {
+ case FRAME_NEED: {
+ int bytes=frame->canStore();
+ int read=input->read((char*)inputbuffer,bytes);
+ if (read <= 0) {
+ // read error. reset framer
+ frame->reset();
+ break;
+ }
+ frame->store(inputbuffer,bytes);
+ break;
+ }
+ case FRAME_WORK:
+ frame->work();
+ break;
+ case FRAME_HAS:
+ return true;
+ break;
+ default:
+ cout << "unknown state in mpeg audio framing"<<endl;
+ exit(0);
+ }
+ return false;
+}
diff --git a/mpeglib/lib/splay/mpegAudioInfo.h b/mpeglib/lib/splay/mpegAudioInfo.h
new file mode 100644
index 00000000..65298ca6
--- /dev/null
+++ b/mpeglib/lib/splay/mpegAudioInfo.h
@@ -0,0 +1,95 @@
+/*
+ length detection etc.. for mpeg audio
+ 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 __MPEGAUDIOINFO_H
+#define __MPEGAUDIOINFO_H
+
+#include "../util/file/fileAccess.h"
+
+class MpegAudioStream;
+class MpegAudioHeader;
+class MpegAudioFrame;
+
+typedef struct {
+ char name [30+1];
+ char artist [30+1];
+ char album [30+1];
+ char year [ 4+1];
+ char comment[30+1];
+ unsigned char genre;
+} ID3TAG;
+
+
+class MpegAudioInfo {
+
+ long length;
+ int lXingVBR;
+ ID3TAG* id3;
+ MpegAudioStream* mpegAudioStream;
+ MpegAudioHeader* mpegAudioHeader;
+ MpegAudioFrame * mpegAudioFrame;
+ FileAccess* input;
+ int leof;
+
+ int initState;
+ unsigned char inputbuffer[8192];
+ int lNeedInit;
+ public:
+ MpegAudioInfo(FileAccess* input);
+ ~MpegAudioInfo();
+
+ void reset();
+ int initialize();
+
+ // store info wheter init need or not here.(after reset its true)
+ int getNeedInit();
+ void setNeedInit(int lNeedInit);
+
+
+ // returns byte positions
+ long getSeekPosition(int second);
+ // returns length in seconds
+ long getLength();
+
+ // for id3 parsing you need to seek -128 bytes before the end of strem
+ // after parseID3 you must jump back to 0. This method is blocking
+ int initializeID3();
+ ID3TAG* getID3();
+
+ void print(const char* msg);
+
+ private:
+ // non-blocking init. return true,false,or -1==eof
+ int initializeLength(long fileSize);
+ int initializeID3(long fileSize);
+
+
+
+ void calculateLength(long fileSize);
+ int parseXing(unsigned char* frame,int size);
+
+ // used for seek
+ void parseID3();
+ int getByteDirect();
+
+ // extension for xing vbr
+#ifdef _FROM_SOURCE
+ XHEADDATA* xHeadData;
+#else
+ void* xHeadData;
+#endif
+
+ private:
+ int getFrame(MpegAudioFrame* frame);
+
+};
+#endif
diff --git a/mpeglib/lib/splay/mpegAudioStream.cpp b/mpeglib/lib/splay/mpegAudioStream.cpp
new file mode 100644
index 00000000..b3061224
--- /dev/null
+++ b/mpeglib/lib/splay/mpegAudioStream.cpp
@@ -0,0 +1,43 @@
+/*
+ initializer/resyncer/frame detection etc.. for mpeg audio
+ 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 "mpegAudioStream.h"
+
+#include <stdlib.h>
+
+MpegAudioStream::MpegAudioStream() {
+ buffer=NULL;
+}
+
+
+MpegAudioStream::~MpegAudioStream() {
+}
+
+
+
+void MpegAudioStream::setFrame(unsigned char* ptr,int len) {
+ this->buffer=(char*)ptr;
+ this->len=len;
+ bitindex=0;
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/splay/mpegAudioStream.h b/mpeglib/lib/splay/mpegAudioStream.h
new file mode 100644
index 00000000..9e4accc3
--- /dev/null
+++ b/mpeglib/lib/splay/mpegAudioStream.h
@@ -0,0 +1,139 @@
+/*
+ initializer/resyncer/frame detection etc.. for mpeg audio
+ 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 __MPEGAUDIOSTREAM_H
+#define __MPEGAUDIOSTREAM_H
+
+// we include this for the big_endian define
+
+#include "mpegAudioBitWindow.h"
+
+#define _MAX_MPEG_BUFFERSIZE 4096
+
+
+/**
+ Here we go from the frame to the bitlevel.
+
+
+*/
+
+class MpegAudioStream {
+
+ char* buffer;
+ int len;
+ int bitindex;
+
+ public:
+ MpegAudioStream();
+ ~MpegAudioStream();
+
+ void setFrame(unsigned char* prt,int len);
+
+ // Bit functions
+
+ inline char* getBuffer() { return buffer; }
+ inline int getBufferSize() { return _MAX_MPEG_BUFFERSIZE ;}
+ inline void sync() { bitindex=(bitindex+7)&0xFFFFFFF8; }
+ inline int issync() { return (bitindex&7);};
+
+ /**
+ Now follow ugly inline function. The performance gain is 1.5 %
+ on a 400 MHz AMD
+ */
+
+ inline int getbyte() {
+ int r=(unsigned char)buffer[bitindex>>3];
+ bitindex+=8;
+ return r;
+ }
+
+ inline int getbits9(int bits) {
+ register unsigned short a;
+ {
+ int offset=bitindex>>3;
+
+ a=(((unsigned char)buffer[offset])<<8) |
+ ((unsigned char)buffer[offset+1]);
+ }
+
+ a<<=(bitindex&7);
+ bitindex+=bits;
+ return (int)((unsigned int)(a>>(16-bits)));
+ }
+
+ inline int getbits8() {
+ register unsigned short a;
+
+ {
+ int offset=bitindex>>3;
+
+ a=(((unsigned char)buffer[offset])<<8) |
+ ((unsigned char)buffer[offset+1]);
+ }
+
+ a<<=(bitindex&7);
+ bitindex+=8;
+ return (int)((unsigned int)(a>>8));
+ }
+
+ inline int getbit() {
+ register int r=(buffer[bitindex>>3]>>(7-(bitindex&7)))&1;
+
+ bitindex++;
+ return r;
+ }
+
+ inline int getbits(int bits) {
+ union
+ {
+ char store[4];
+ int current;
+ }u;
+ int bi;
+
+ if(!bits)return 0;
+
+ u.current=0;
+ bi=(bitindex&7);
+ u.store[_KEY]=buffer[bitindex>>3]<<bi;
+ bi=8-bi;
+ bitindex+=bi;
+
+ while(bits) {
+ if(!bi) {
+ u.store[_KEY]=buffer[bitindex>>3];
+ bitindex+=8;
+ bi=8;
+ }
+ if(bits>=bi) {
+ u.current<<=bi;
+ bits-=bi;
+ bi=0;
+ } else {
+ u.current<<=bits;
+ bi-=bits;
+ bits=0;
+ }
+ }
+ bitindex-=bi;
+ return (u.current>>8);
+ }
+
+
+
+
+};
+
+
+#endif
diff --git a/mpeglib/lib/splay/mpeglayer1.cpp b/mpeglib/lib/splay/mpeglayer1.cpp
new file mode 100644
index 00000000..a32951c4
--- /dev/null
+++ b/mpeglib/lib/splay/mpeglayer1.cpp
@@ -0,0 +1,109 @@
+/* MPEG/WAVE Sound library
+
+ (C) 1997 by Jung woo-jae */
+
+// Mpeglayer1.cc
+// It's for MPEG Layer 1
+
+
+
+#include "mpegsound.h"
+#include "synthesis.h"
+
+// Tables for layer 1
+static const REAL factortable[15] =
+{
+ 0.0,
+ (1.0/2.0) * (4.0/3.0), (1.0/4.0) * (8.0/7.0),
+ (1.0/8.0) * (16.0/15.0), (1.0/16.0) * (32.0/31.0),
+ (1.0/32.0) * (64.0/63.0), (1.0/64.0) * (128.0/127.0),
+ (1.0/128.0) * (256.0/255.0), (1.0/256.0) * (512.0/511.0),
+ (1.0/512.0) * (1024.0/1023.0), (1.0/1024.0) * (2048.0/2047.0),
+ (1.0/2048.0) * (4096.0/4095.0), (1.0/4096.0) * (8192.0/8191.0),
+ (1.0/8192.0) * (16384.0/16383.0), (1.0/16384.0) * (32768.0/32767.0)
+};
+
+static const REAL offsettable[15] =
+{
+ 0.0,
+ ((1.0/2.0)-1.0) * (4.0/3.0), ((1.0/4.0)-1.0) * (8.0/7.0),
+ ((1.0/8.0)-1.0) * (16.0/15.0), ((1.0/16.0)-1.0) * (32.0/31.0),
+ ((1.0/32.0)-1.0) * (64.0/63.0), ((1.0/64.0)-1.0) * (128.0/127.0),
+ ((1.0/128.0)-1.0) * (256.0/255.0), ((1.0/256.0)-1.0) * (512.0/511.0),
+ ((1.0/512.0)-1.0) * (1024.0/1023.0), ((1.0/1024.0)-1.0) * (2048.0/2047.0),
+ ((1.0/2048.0)-1.0) * (4096.0/4095.0), ((1.0/4096.0)-1.0) * (8192.0/8191.0),
+ ((1.0/8192.0)-1.0) * (16384.0/16383.0), ((1.0/16384.0)-1.0) * (32768.0/32767.0)
+};
+
+// Mpeg layer 1
+void Mpegtoraw::extractlayer1(void)
+{
+ int inputstereo=mpegAudioHeader->getInputstereo();
+ int stereobound=mpegAudioHeader->getStereobound();
+ REAL fraction[MAXCHANNEL][MAXSUBBAND];
+ REAL scalefactor[MAXCHANNEL][MAXSUBBAND];
+
+ int bitalloc[MAXCHANNEL][MAXSUBBAND],
+ sample[MAXCHANNEL][MAXSUBBAND];
+
+ register int i,j;
+ int s=stereobound,l;
+
+
+// Bitalloc
+ for(i=0;i<s;i++)
+ {
+ bitalloc[LS][i]=getbits(4);
+ bitalloc[RS][i]=getbits(4);
+ }
+ for(;i<MAXSUBBAND;i++)
+ bitalloc[LS][i]=
+ bitalloc[RS][i]=getbits(4);
+
+// Scale index
+ if(inputstereo)
+ for(i=0;i<MAXSUBBAND;i++)
+ {
+ if(bitalloc[LS][i])scalefactor[LS][i]=scalefactorstable[getbits(6)];
+ if(bitalloc[RS][i])scalefactor[RS][i]=scalefactorstable[getbits(6)];
+ }
+ else
+ for(i=0;i<MAXSUBBAND;i++)
+ if(bitalloc[LS][i])scalefactor[LS][i]=scalefactorstable[getbits(6)];
+
+ for(l=0;l<SCALEBLOCK;l++)
+ {
+ // Sample
+ for(i=0;i<s;i++)
+ {
+ if((j=bitalloc[LS][i]))sample[LS][i]=getbits(j+1);
+ if((j=bitalloc[RS][i]))sample[RS][i]=getbits(j+1);
+ }
+ for(;i<MAXSUBBAND;i++)
+ if((j=bitalloc[LS][i]))sample[LS][i]=sample[RS][i]=getbits(j+1);
+
+
+ // Fraction
+ if(lOutputStereo)
+ for(i=0;i<MAXSUBBAND;i++)
+ {
+ if((j=bitalloc[LS][i]))
+ fraction[LS][i]=(REAL(sample[LS][i])*factortable[j]+offsettable[j])
+ *scalefactor[LS][i];
+ else fraction[LS][i]=0.0;
+ if((j=bitalloc[RS][i]))
+ fraction[RS][i]=(REAL(sample[RS][i])*factortable[j]+offsettable[j])
+ *scalefactor[RS][i];
+ else fraction[RS][i]=0.0;
+ }
+ else
+ for(i=0;i<MAXSUBBAND;i++)
+ if((j=bitalloc[LS][i]))
+ fraction[LS][i]=(REAL(sample[LS][i])*factortable[j]+offsettable[j])
+ *scalefactor[LS][i];
+ else fraction[LS][i]=0.0;
+
+ synthesis->doSynth(lDownSample,lOutputStereo,
+ fraction[LS],fraction[RS]);
+ }
+}
diff --git a/mpeglib/lib/splay/mpeglayer2.cpp b/mpeglib/lib/splay/mpeglayer2.cpp
new file mode 100644
index 00000000..4012ff27
--- /dev/null
+++ b/mpeglib/lib/splay/mpeglayer2.cpp
@@ -0,0 +1,449 @@
+/* MPEG/WAVE Sound library
+
+ (C) 1997 by Jung woo-jae */
+
+// Mpeglayer2.cc
+// It's for MPEG Layer 2
+
+
+#include "mpegsound.h"
+#include "synthesis.h"
+
+#include <iostream>
+
+using namespace std;
+
+#define BUGFIX
+#include "mpeg2tables.h"
+
+
+// workaround for buggy mpeg2 streams.
+// tested with 12 monkey cdi, worgked fine.
+// problem was: the stream produced ints
+// with access out of the tables
+// if we have such an access we set it to a zero entry
+#ifdef BUGFIX
+static int checkCodeRange(int code,const REAL* group) {
+ int back=0;
+ if (group == NULL) {
+ cout << "group null"<<endl;
+ return 0;
+ }
+ back=code;
+
+ if (group == group5bits) {
+ if (back > 27*3) {
+ // redirect to zero value
+ back=3;
+ }
+ return back;
+ }
+ if (group == group7bits) {
+ if (back > 125*3) {
+ back=6;
+ }
+ return back;
+ }
+ if (group == group10bits) {
+ if (back > 729*3) {
+ back=12;
+ }
+ return back;
+ }
+ DEBUG_LAYER(cout << "unknown group found!"<<endl;)
+ return -1;
+}
+
+
+#endif
+
+
+
+
+
+
+
+
+// Mpeg layer 2
+void Mpegtoraw::extractlayer2(void) {
+ int inputstereo=mpegAudioHeader->getInputstereo();
+ int tableindex=mpegAudioHeader->getTableindex();
+ int subbandnumber=mpegAudioHeader->getSubbandnumber();
+ int stereobound=mpegAudioHeader->getStereobound();
+
+ REAL fraction[MAXCHANNEL][3][MAXSUBBAND];
+ unsigned int bitalloc[MAXCHANNEL][MAXSUBBAND],
+ scaleselector[MAXCHANNEL][MAXSUBBAND];
+ REAL scalefactor[2][3][MAXSUBBAND];
+
+ const REAL *group[MAXCHANNEL][MAXSUBBAND];
+ unsigned int codelength[MAXCHANNEL][MAXSUBBAND];
+ REAL factor[MAXCHANNEL][MAXSUBBAND];
+ REAL c[MAXCHANNEL][MAXSUBBAND],d[MAXCHANNEL][MAXSUBBAND];
+
+ int s=stereobound,n=subbandnumber;
+
+
+ // Bitalloc
+ {
+ register int i;
+ register const int *t=bitalloclengthtable[tableindex];
+ for(i=0;i<s;i++,t++)
+ {
+ bitalloc[LS][i]=getbits(*t);
+ bitalloc[RS][i]=getbits(*t);
+ }
+ for(;i<n;i++,t++) {
+ bitalloc[LS][i]=bitalloc[RS][i]=getbits(*t);
+ }
+ }
+
+
+
+ // Scale selector
+ if(inputstereo)
+ for(register int i=0;i<n;i++)
+ {
+ if(bitalloc[LS][i])scaleselector[LS][i]=getbits(2);
+ if(bitalloc[RS][i])scaleselector[RS][i]=getbits(2);
+ }
+ else
+ for(register int i=0;i<n;i++)
+ if(bitalloc[LS][i])scaleselector[LS][i]=getbits(2);
+
+ // Scale index
+ {
+ register int i,j;
+
+
+ for(i=0;i<n;i++)
+ {
+ if((j=bitalloc[LS][i]))
+ {
+ if(!tableindex)
+ {
+ group[LS][i]=grouptableA[j];
+ codelength[LS][i]=codelengthtableA[j];
+ factor[LS][i]=factortableA[j];
+ c[LS][i]=ctableA[j];
+ d[LS][i]=dtableA[j];
+ }
+ else
+ {
+ if(i<=2)
+ {
+ group[LS][i]=grouptableB1[j];
+ codelength[LS][i]=codelengthtableB1[j];
+ factor[LS][i]=factortableB1[j];
+ c[LS][i]=ctableB1[j];
+ d[LS][i]=dtableB1[j];
+ }
+ else
+ {
+ group[LS][i]=grouptableB234[j];
+ if(i<=10)
+ {
+ codelength[LS][i]=codelengthtableB2[j];
+ factor[LS][i]=factortableB2[j];
+ c[LS][i]=ctableB2[j];
+ d[LS][i]=dtableB2[j];
+ }
+ else if(i<=22)
+ {
+ codelength[LS][i]=codelengthtableB3[j];
+ factor[LS][i]=factortableB3[j];
+ c[LS][i]=ctableB3[j];
+ d[LS][i]=dtableB3[j];
+ }
+ else
+ {
+ codelength[LS][i]=codelengthtableB4[j];
+ factor[LS][i]=factortableB4[j];
+ c[LS][i]=ctableB4[j];
+ d[LS][i]=dtableB4[j];
+ }
+ }
+ }
+
+
+ switch(scaleselector[LS][i])
+ {
+ case 0:scalefactor[LS][0][i]=scalefactorstable[getbits(6)];
+ scalefactor[LS][1][i]=scalefactorstable[getbits(6)];
+ scalefactor[LS][2][i]=scalefactorstable[getbits(6)];
+ break;
+ case 1:scalefactor[LS][0][i]=
+ scalefactor[LS][1][i]=scalefactorstable[getbits(6)];
+ scalefactor[LS][2][i]=scalefactorstable[getbits(6)];
+ break;
+ case 2:scalefactor[LS][0][i]=
+ scalefactor[LS][1][i]=
+ scalefactor[LS][2][i]=scalefactorstable[getbits(6)];
+ break;
+ case 3:scalefactor[LS][0][i]=scalefactorstable[getbits(6)];
+ scalefactor[LS][1][i]=
+ scalefactor[LS][2][i]=scalefactorstable[getbits(6)];
+ break;
+ default:
+ cout << "scaleselector left default never happens"<<endl;
+ break;
+ }
+ }
+
+
+ if(inputstereo && (j=bitalloc[RS][i]))
+ {
+ if(!tableindex)
+ {
+ group[RS][i]=grouptableA[j];
+ codelength[RS][i]=codelengthtableA[j];
+ factor[RS][i]=factortableA[j];
+ c[RS][i]=ctableA[j];
+ d[RS][i]=dtableA[j];
+ }
+ else
+ {
+ if(i<=2)
+ {
+ group[RS][i]=grouptableB1[j];
+ codelength[RS][i]=codelengthtableB1[j];
+ factor[RS][i]=factortableB1[j];
+ c[RS][i]=ctableB1[j];
+ d[RS][i]=dtableB1[j];
+ }
+ else
+ {
+ group[RS][i]=grouptableB234[j];
+ if(i<=10)
+ {
+ codelength[RS][i]=codelengthtableB2[j];
+ factor[RS][i]=factortableB2[j];
+ c[RS][i]=ctableB2[j];
+ d[RS][i]=dtableB2[j];
+ }
+ else if(i<=22)
+ {
+ codelength[RS][i]=codelengthtableB3[j];
+ factor[RS][i]=factortableB3[j];
+ c[RS][i]=ctableB3[j];
+ d[RS][i]=dtableB3[j];
+ }
+ else
+ {
+ codelength[RS][i]=codelengthtableB4[j];
+ factor[RS][i]=factortableB4[j];
+ c[RS][i]=ctableB4[j];
+ d[RS][i]=dtableB4[j];
+ }
+ }
+ }
+
+
+ switch(scaleselector[RS][i])
+ {
+ case 0 : scalefactor[RS][0][i]=scalefactorstable[getbits(6)];
+ scalefactor[RS][1][i]=scalefactorstable[getbits(6)];
+ scalefactor[RS][2][i]=scalefactorstable[getbits(6)];
+ break;
+ case 1 : scalefactor[RS][0][i]=
+ scalefactor[RS][1][i]=scalefactorstable[getbits(6)];
+ scalefactor[RS][2][i]=scalefactorstable[getbits(6)];
+ break;
+ case 2 : scalefactor[RS][0][i]=
+ scalefactor[RS][1][i]=
+ scalefactor[RS][2][i]=scalefactorstable[getbits(6)];
+ break;
+ case 3 : scalefactor[RS][0][i]=scalefactorstable[getbits(6)];
+ scalefactor[RS][1][i]=
+ scalefactor[RS][2][i]=scalefactorstable[getbits(6)];
+ break;
+ default:
+ cout << "scaleselector right default never happens"<<endl;
+ break;
+ }
+
+
+ }
+ }
+ }
+
+
+
+// Read Sample
+ {
+ register int i;
+
+ for(int l=0;l<SCALEBLOCK;l++)
+ {
+ // Read Sample
+ for(i=0;i<s;i++)
+ {
+ if(bitalloc[LS][i])
+ {
+ if(group[LS][i])
+ {
+ register const REAL *s;
+ int code=getbits(codelength[LS][i]);
+
+
+
+ code+=code<<1;
+#ifdef BUGFIX
+ // bugfix for bad streams
+ code=checkCodeRange(code,group[LS][i]);
+ if (code == -1) return;
+#endif
+ s=group[LS][i]+code;
+
+ fraction[LS][0][i]=s[0];
+ fraction[LS][1][i]=s[1];
+ fraction[LS][2][i]=s[2];
+ }
+ else
+ {
+ fraction[LS][0][i]=
+ REAL(getbits(codelength[LS][i]))*factor[LS][i]-1.0;
+ fraction[LS][1][i]=
+ REAL(getbits(codelength[LS][i]))*factor[LS][i]-1.0;
+ fraction[LS][2][i]=
+ REAL(getbits(codelength[LS][i]))*factor[LS][i]-1.0;
+ }
+ }
+ else fraction[LS][0][i]=fraction[LS][1][i]=fraction[LS][2][i]=0.0;
+
+
+ if(inputstereo && bitalloc[RS][i])
+ {
+ if(group[RS][i])
+ {
+ const REAL *s;
+ int code=getbits(codelength[RS][i]);
+
+ code+=code<<1;
+#ifdef BUGFIX
+ // bugfix for bad streams
+ code=checkCodeRange(code,group[RS][i]);
+ if (code == -1) return;
+#endif
+ s=group[RS][i]+code;
+
+ fraction[RS][0][i]=s[0];
+ fraction[RS][1][i]=s[1];
+ fraction[RS][2][i]=s[2];
+ }
+ else
+ {
+ fraction[RS][0][i]=
+ REAL(getbits(codelength[RS][i]))*factor[RS][i]-1.0;
+ fraction[RS][1][i]=
+ REAL(getbits(codelength[RS][i]))*factor[RS][i]-1.0;
+ fraction[RS][2][i]=
+ REAL(getbits(codelength[RS][i]))*factor[RS][i]-1.0;
+ }
+ }
+ else fraction[RS][0][i]=fraction[RS][1][i]=fraction[RS][2][i]=0.0;
+ }
+
+
+ for(;i<n;i++)
+ {
+ if(bitalloc[LS][i])
+ {
+ if(group[LS][i])
+ {
+ register const REAL *s;
+ int code=getbits(codelength[LS][i]);
+
+ code+=code<<1;
+#ifdef BUGFIX
+ // bugfix for bad streams
+ code=checkCodeRange(code,group[LS][i]);
+ if (code == -1) return;
+#endif
+ s=group[LS][i]+code;
+
+ fraction[LS][0][i]=fraction[RS][0][i]=s[0];
+ fraction[LS][1][i]=fraction[RS][1][i]=s[1];
+ fraction[LS][2][i]=fraction[RS][2][i]=s[2];
+ }
+ else
+ {
+ fraction[LS][0][i]=fraction[RS][0][i]=
+ REAL(getbits(codelength[LS][i]))*factor[LS][i]-1.0;
+ fraction[LS][1][i]=fraction[RS][1][i]=
+ REAL(getbits(codelength[LS][i]))*factor[LS][i]-1.0;
+ fraction[LS][2][i]=fraction[RS][2][i]=
+ REAL(getbits(codelength[LS][i]))*factor[LS][i]-1.0;
+ }
+ }
+ else fraction[LS][0][i]=fraction[LS][1][i]=fraction[LS][2][i]=
+ fraction[RS][0][i]=fraction[RS][1][i]=fraction[RS][2][i]=0.0;
+ }
+
+
+
+
+ //Fraction
+ if(lOutputStereo)
+ for(i=0;i<n;i++)
+ {
+ if(bitalloc[LS][i])
+ {
+ if(!group[LS][i])
+ {
+ fraction[LS][0][i]=(fraction[LS][0][i]+d[LS][i])*c[LS][i];
+ fraction[LS][1][i]=(fraction[LS][1][i]+d[LS][i])*c[LS][i];
+ fraction[LS][2][i]=(fraction[LS][2][i]+d[LS][i])*c[LS][i];
+ }
+
+ register REAL t=scalefactor[LS][l>>2][i];
+ fraction[LS][0][i]*=t;
+ fraction[LS][1][i]*=t;
+ fraction[LS][2][i]*=t;
+ }
+
+ if(bitalloc[RS][i])
+ {
+ if(!group[RS][i])
+ {
+ fraction[RS][0][i]=(fraction[RS][0][i]+d[RS][i])*c[LS][i];
+ fraction[RS][1][i]=(fraction[RS][1][i]+d[RS][i])*c[LS][i];
+ fraction[RS][2][i]=(fraction[RS][2][i]+d[RS][i])*c[LS][i];
+ }
+
+ register REAL t=scalefactor[RS][l>>2][i];
+ fraction[RS][0][i]*=t;
+ fraction[RS][1][i]*=t;
+ fraction[RS][2][i]*=t;
+ }
+ }
+ else
+ for(i=0;i<n;i++)
+ if(bitalloc[LS][i])
+ {
+ if(!group[LS][i])
+ {
+ fraction[LS][0][i]=(fraction[LS][0][i]+d[LS][i])*c[LS][i];
+ fraction[LS][1][i]=(fraction[LS][1][i]+d[LS][i])*c[LS][i];
+ fraction[LS][2][i]=(fraction[LS][2][i]+d[LS][i])*c[LS][i];
+ }
+
+ register REAL t=scalefactor[LS][l>>2][i];
+ fraction[LS][0][i]*=t;
+ fraction[LS][1][i]*=t;
+ fraction[LS][2][i]*=t;
+ }
+
+
+ for(;i<MAXSUBBAND;i++)
+ fraction[LS][0][i]=fraction[LS][1][i]=fraction[LS][2][i]=
+ fraction[RS][0][i]=fraction[RS][1][i]=fraction[RS][2][i]=0.0;
+
+ for(i=0;i<3;i++) {
+ synthesis->doSynth(lDownSample,lOutputStereo,
+ fraction[LS][i],fraction[RS][i]);
+ }
+
+ }
+ }
+}
diff --git a/mpeglib/lib/splay/mpeglayer3.cpp b/mpeglib/lib/splay/mpeglayer3.cpp
new file mode 100644
index 00000000..eeb09697
--- /dev/null
+++ b/mpeglib/lib/splay/mpeglayer3.cpp
@@ -0,0 +1,1761 @@
+/* MPEG/WAVE Sound library
+
+ (C) 1997 by Jung woo-jae */
+
+// Mpeglayer3.cc
+// It's for MPEG Layer 3
+// I've made array of superior functions for speed.
+// Extend TO_FOUR_THIRDS to negative.
+// Bug fix : maplay 1.2+ have wrong TO_FOUR_THIRDS ranges.
+// Force to mono!!
+// MPEG-2 is implemented
+// Speed up in fixstereo (maybe buggy)
+
+
+
+#include "mpegsound.h"
+#include "huffmanlookup.h"
+#include "dump.h"
+#include "synthesis.h"
+
+inline int Mpegtoraw::wgetbit (void) {return bitwindow.getbit (); }
+inline int Mpegtoraw::wgetbits9(int bits){return bitwindow.getbits9(bits);}
+inline int Mpegtoraw::wgetbits (int bits){return bitwindow.getbits (bits);}
+inline int Mpegtoraw::wgetCanReadBits () {return bitwindow.getCanReadBits();}
+
+
+#define MUL3(a) (((a)<<1)+(a))
+
+#define REAL0 0
+
+// 576
+#define ARRAYSIZE (SBLIMIT*SSLIMIT)
+#define REALSIZE (sizeof(REAL))
+
+
+#define MAPLAY_OPT 1
+
+
+#ifdef NATIVE_ASSEMBLY
+inline void long_memset(void * s,unsigned int c,int count)
+{
+__asm__ __volatile__(
+ "cld\n\t"
+ "rep ; stosl\n\t"
+ : /* no output */
+ :"a" (c), "c" (count/4), "D" ((long) s)
+ :"cx","di","memory");
+}
+#endif
+
+#define FOURTHIRDSTABLENUMBER (8250)
+static int initializedlayer3=false;
+
+static REAL two_to_negative_half_pow[70];
+static REAL TO_FOUR_THIRDSTABLE[FOURTHIRDSTABLENUMBER*2];
+static REAL POW2[256];
+static REAL POW2_1[8][2][16];
+static REAL ca[8],cs[8];
+
+
+
+
+typedef struct
+{
+ REAL l,r;
+}RATIOS;
+
+static RATIOS rat_1[16],rat_2[2][64];
+
+void Mpegtoraw::layer3initialize(void)
+{
+
+ int i,j,k,l;
+
+ //maplay opt.
+ nonzero[0] = nonzero[1] = nonzero[2]=ARRAYSIZE;
+
+ layer3framestart=0;
+ currentprevblock=0;
+
+ for(l=0;l<2;l++)
+ for(i=0;i<2;i++)
+ for(j=0;j<SBLIMIT;j++)
+ for(k=0;k<SSLIMIT;k++)
+ prevblck[l][i][j][k]=0.0f;
+
+ bitwindow.initialize();
+
+ if(initializedlayer3) {
+ return;
+ }
+
+
+
+ for(i=0;i<256;i++) {
+ POW2[i]=(REAL)pow((double)2.0,(0.25* (double) (i-210.0)));
+ }
+ REAL *TO_FOUR_THIRDS=TO_FOUR_THIRDSTABLE+FOURTHIRDSTABLENUMBER;
+
+ for(i=1;i<FOURTHIRDSTABLENUMBER;i++)
+ TO_FOUR_THIRDS[-i]=
+ -(TO_FOUR_THIRDS[i]=(REAL)pow((double)i,(double)4.0/3.0));
+ // now set the zero value for both (otherwise it would be -0.0)
+ TO_FOUR_THIRDS[0]=(REAL)0;
+
+
+ for(i=0;i<8;i++) {
+ static double Ci[8]= {-0.6,-0.535,-0.33,-0.185,
+ -0.095,-0.041,-0.0142,-0.0037};
+ double sq=sqrt(1.0f+Ci[i]*Ci[i]);
+ cs[i]=1.0f/sq;
+ ca[i]=Ci[i]/sq;
+ }
+
+ initialize_win();
+ initialize_dct12_dct36();
+ for(i=0;i<70;i++) {
+ two_to_negative_half_pow[i]=(REAL)pow(2.0,-0.5*(double)i);
+ }
+
+
+ for(i=0;i<8;i++)
+ for(j=0;j<2;j++)
+ for(k=0;k<16;k++)POW2_1[i][j][k]=pow(2.0,(-2.0*i)-(0.5*(1.0+j)*k));
+
+
+ /*
+
+ for(i=0;i<8;i++)
+ for(k=0;k<16;k++) {
+ for(j=0;j<2;j++) {
+ REAL base=pow(2.0,-0.25*(j+1.0));
+ REAL val=1.0;
+
+ if (k>0) {
+ if ( k & 1) {
+ val=pow(base,(k+1.0)*0.5);
+ } else {
+ val=pow(base,k*0.5);
+ }
+ }
+
+ POW2_MV[i][j][k]=val;
+ }
+ }
+
+ for(i=0;i<8;i++)
+ for(j=0;j<2;j++)
+ for(k=0;k<16;k++) {
+ REAL a=POW2_1[i][j][k];
+ REAL b=POW2_MV[i][j][k];
+ printf("i:%d j%d k%d",i,j,k);
+ if (a != b) {
+ cout << "a:"<<a<<" b:"<<b<<endl;
+ } else {
+ cout << "same:"<<a<<endl;
+ }
+ }
+ */
+
+
+ for(i=0;i<16;i++) {
+ double t = tan( (double) i * MY_PI / 12.0 );
+ rat_1[i].l=t / (1.0+t);
+ rat_1[i].r=1.0 /(1.0+t);
+ }
+
+
+#define IO0 ((double)0.840896415256)
+#define IO1 ((double)0.707106781188)
+ rat_2[0][0].l=rat_2[0][0].r=
+ rat_2[1][0].l=rat_2[1][0].r=1.;
+
+ for(i=1;i<64;i++) {
+ if((i%2)==1) {
+ rat_2[0][i].l=pow(IO0,(i+1)/2);
+ rat_2[1][i].l=pow(IO1,(i+1)/2);
+ rat_2[0][i].r=
+ rat_2[1][i].r=1.;
+ }
+ else {
+ rat_2[0][i].l=
+ rat_2[1][i].l=1.;
+ rat_2[0][i].r=pow(IO0,i/2);
+ rat_2[1][i].r=pow(IO1,i/2);
+ }
+ }
+
+ initializedlayer3=true;
+}
+
+bool Mpegtoraw::layer3getsideinfo(void) {
+ int inputstereo=mpegAudioHeader->getInputstereo();
+
+
+ sideinfo.main_data_begin=getbits(9);
+ if(!inputstereo)sideinfo.private_bits=getbits(5);
+ else sideinfo.private_bits=getbits(3);
+
+ sideinfo.ch[LS].scfsi[0]=getbit();
+ sideinfo.ch[LS].scfsi[1]=getbit();
+ sideinfo.ch[LS].scfsi[2]=getbit();
+ sideinfo.ch[LS].scfsi[3]=getbit();
+ if(inputstereo) {
+ sideinfo.ch[RS].scfsi[0]=getbit();
+ sideinfo.ch[RS].scfsi[1]=getbit();
+ sideinfo.ch[RS].scfsi[2]=getbit();
+ sideinfo.ch[RS].scfsi[3]=getbit();
+ }
+
+ for(int gr=0,ch;gr<2;gr++)
+ for(ch=0;;ch++) {
+ layer3grinfo *gi=&(sideinfo.ch[ch].gr[gr]);
+
+ gi->part2_3_length =getbits(12);
+ gi->big_values =getbits(9);
+ if(gi->big_values > 288) {
+ DEBUG_LAYER(fprintf(stderr,"big_values too large!\n");)
+ gi->big_values = 288;
+ return false;
+ }
+
+ gi->global_gain =getbits(8);
+ gi->scalefac_compress =getbits(4);
+ gi->window_switching_flag=getbit();
+ if(gi->window_switching_flag) {
+ gi->block_type =getbits(2);
+ gi->mixed_block_flag=getbit();
+
+ gi->table_select[0] =getbits(5);
+ gi->table_select[1] =getbits(5);
+
+ gi->subblock_gain[0]=getbits(3);
+ gi->subblock_gain[1]=getbits(3);
+ gi->subblock_gain[2]=getbits(3);
+
+ /* Set region_count parameters since they are implicit in this case. */
+ if(gi->block_type==0)
+ {
+ DEBUG_LAYER(printf("Side info bad: block_type==0 split block.\n");)
+ return false;
+ }
+ else if (gi->block_type==2 && gi->mixed_block_flag==0)
+ gi->region0_count=8; /* MI 9; */
+ else gi->region0_count=7; /* MI 8; */
+ gi->region1_count=20-(gi->region0_count);
+ }
+ else
+ {
+ gi->table_select[0] =getbits(5);
+ gi->table_select[1] =getbits(5);
+ gi->table_select[2] =getbits(5);
+ gi->region0_count =getbits(4);
+ gi->region1_count =getbits(3);
+ gi->block_type =0;
+ }
+ gi->preflag =getbit();
+ gi->scalefac_scale =getbit();
+ gi->count1table_select=getbit();
+
+ gi->generalflag=gi->window_switching_flag && (gi->block_type==2);
+
+ if(!inputstereo || ch)break;
+ }
+
+ return true;
+}
+
+bool Mpegtoraw::layer3getsideinfo_2(void) {
+ int inputstereo=mpegAudioHeader->getInputstereo();
+ sideinfo.main_data_begin=getbits(8);
+
+ if(!inputstereo)sideinfo.private_bits=getbit();
+ else sideinfo.private_bits=getbits(2);
+
+ for(int ch=0;;ch++)
+ {
+ layer3grinfo *gi=&(sideinfo.ch[ch].gr[0]);
+
+ gi->part2_3_length =getbits(12);
+ gi->big_values =getbits(9);
+ if(gi->big_values > 288) {
+ DEBUG_LAYER(fprintf(stderr,"big_values too large!\n");)
+ gi->big_values = 288;
+ return false;
+ }
+
+ gi->global_gain =getbits(8);
+ gi->scalefac_compress =getbits(9);
+ gi->window_switching_flag=getbit();
+ if(gi->window_switching_flag)
+ {
+ gi->block_type =getbits(2);
+ gi->mixed_block_flag=getbit();
+
+ gi->table_select[0] =getbits(5);
+ gi->table_select[1] =getbits(5);
+
+ gi->subblock_gain[0]=getbits(3);
+ gi->subblock_gain[1]=getbits(3);
+ gi->subblock_gain[2]=getbits(3);
+
+ /* Set region_count parameters since they are implicit in this case. */
+ if(gi->block_type==0)
+ {
+ DEBUG_LAYER(printf("Side info bad: block_type==0 split block.\n");)
+ return false;
+ }
+ else if (gi->block_type==2 && gi->mixed_block_flag==0)
+ gi->region0_count=8; /* MI 9; */
+ else gi->region0_count=7; /* MI 8; */
+ gi->region1_count=20-(gi->region0_count);
+ }
+ else
+ {
+ gi->table_select[0] =getbits(5);
+ gi->table_select[1] =getbits(5);
+ gi->table_select[2] =getbits(5);
+ gi->region0_count =getbits(4);
+ gi->region1_count =getbits(3);
+ gi->block_type =0;
+ }
+ gi->scalefac_scale =getbit();
+ gi->count1table_select=getbit();
+
+ gi->generalflag=gi->window_switching_flag && (gi->block_type==2);
+
+ if(!inputstereo || ch)break;
+ }
+
+ return true;
+}
+
+void Mpegtoraw::layer3getscalefactors(int ch,int gr)
+{
+ static int slen[2][16]={{0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4},
+ {0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3}};
+
+ layer3grinfo *gi=&(sideinfo.ch[ch].gr[gr]);
+ register layer3scalefactor *sf=(&scalefactors[ch]);
+ int l0,l1;
+
+ {
+ int scale_comp=gi->scalefac_compress;
+
+ l0=slen[0][scale_comp];
+ l1=slen[1][scale_comp];
+ }
+ /*
+ wgetCanReadBits();
+ cout << "lo:"<<l0<<" l1:"<<l1<<endl;
+ */
+ if(gi->generalflag)
+ {
+ if(gi->mixed_block_flag)
+ { /* MIXED */ /* NEW-ag 11/25 */
+ sf->l[0]=wgetbits9(l0);sf->l[1]=wgetbits9(l0);
+ sf->l[2]=wgetbits9(l0);sf->l[3]=wgetbits9(l0);
+ sf->l[4]=wgetbits9(l0);sf->l[5]=wgetbits9(l0);
+ sf->l[6]=wgetbits9(l0);sf->l[7]=wgetbits9(l0);
+
+ sf->s[0][ 3]=wgetbits9(l0);sf->s[1][ 3]=wgetbits9(l0);
+ sf->s[2][ 3]=wgetbits9(l0);
+ sf->s[0][ 4]=wgetbits9(l0);sf->s[1][ 4]=wgetbits9(l0);
+ sf->s[2][ 4]=wgetbits9(l0);
+ sf->s[0][ 5]=wgetbits9(l0);sf->s[1][ 5]=wgetbits9(l0);
+ sf->s[2][ 5]=wgetbits9(l0);
+
+ sf->s[0][ 6]=wgetbits9(l1);sf->s[1][ 6]=wgetbits9(l1);
+ sf->s[2][ 6]=wgetbits9(l1);
+ sf->s[0][ 7]=wgetbits9(l1);sf->s[1][ 7]=wgetbits9(l1);
+ sf->s[2][ 7]=wgetbits9(l1);
+ sf->s[0][ 8]=wgetbits9(l1);sf->s[1][ 8]=wgetbits9(l1);
+ sf->s[2][ 8]=wgetbits9(l1);
+ sf->s[0][ 9]=wgetbits9(l1);sf->s[1][ 9]=wgetbits9(l1);
+ sf->s[2][ 9]=wgetbits9(l1);
+ sf->s[0][10]=wgetbits9(l1);sf->s[1][10]=wgetbits9(l1);
+ sf->s[2][10]=wgetbits9(l1);
+ sf->s[0][11]=wgetbits9(l1);sf->s[1][11]=wgetbits9(l1);
+ sf->s[2][11]=wgetbits9(l1);
+
+ sf->s[0][12]=sf->s[1][12]=sf->s[2][12]=0;
+ }
+ else
+ { /* SHORT*/
+ sf->s[0][ 0]=wgetbits9(l0);sf->s[1][ 0]=wgetbits9(l0);
+ sf->s[2][ 0]=wgetbits9(l0);
+ sf->s[0][ 1]=wgetbits9(l0);sf->s[1][ 1]=wgetbits9(l0);
+ sf->s[2][ 1]=wgetbits9(l0);
+ sf->s[0][ 2]=wgetbits9(l0);sf->s[1][ 2]=wgetbits9(l0);
+ sf->s[2][ 2]=wgetbits9(l0);
+ sf->s[0][ 3]=wgetbits9(l0);sf->s[1][ 3]=wgetbits9(l0);
+ sf->s[2][ 3]=wgetbits9(l0);
+ sf->s[0][ 4]=wgetbits9(l0);sf->s[1][ 4]=wgetbits9(l0);
+ sf->s[2][ 4]=wgetbits9(l0);
+ sf->s[0][ 5]=wgetbits9(l0);sf->s[1][ 5]=wgetbits9(l0);
+ sf->s[2][ 5]=wgetbits9(l0);
+
+ sf->s[0][ 6]=wgetbits9(l1);sf->s[1][ 6]=wgetbits9(l1);
+ sf->s[2][ 6]=wgetbits9(l1);
+ sf->s[0][ 7]=wgetbits9(l1);sf->s[1][ 7]=wgetbits9(l1);
+ sf->s[2][ 7]=wgetbits9(l1);
+ sf->s[0][ 8]=wgetbits9(l1);sf->s[1][ 8]=wgetbits9(l1);
+ sf->s[2][ 8]=wgetbits9(l1);
+ sf->s[0][ 9]=wgetbits9(l1);sf->s[1][ 9]=wgetbits9(l1);
+ sf->s[2][ 9]=wgetbits9(l1);
+ sf->s[0][10]=wgetbits9(l1);sf->s[1][10]=wgetbits9(l1);
+ sf->s[2][10]=wgetbits9(l1);
+ sf->s[0][11]=wgetbits9(l1);sf->s[1][11]=wgetbits9(l1);
+ sf->s[2][11]=wgetbits9(l1);
+
+ sf->s[0][12]=sf->s[1][12]=sf->s[2][12]=0;
+ }
+ }
+ else
+ { /* LONG types 0,1,3 */
+ if(gr==0)
+ {
+ sf->l[ 0]=wgetbits9(l0);sf->l[ 1]=wgetbits9(l0);
+ sf->l[ 2]=wgetbits9(l0);sf->l[ 3]=wgetbits9(l0);
+ sf->l[ 4]=wgetbits9(l0);sf->l[ 5]=wgetbits9(l0);
+ sf->l[ 6]=wgetbits9(l0);sf->l[ 7]=wgetbits9(l0);
+ sf->l[ 8]=wgetbits9(l0);sf->l[ 9]=wgetbits9(l0);
+ sf->l[10]=wgetbits9(l0);
+ sf->l[11]=wgetbits9(l1);sf->l[12]=wgetbits9(l1);
+ sf->l[13]=wgetbits9(l1);sf->l[14]=wgetbits9(l1);
+ sf->l[15]=wgetbits9(l1);
+ sf->l[16]=wgetbits9(l1);sf->l[17]=wgetbits9(l1);
+ sf->l[18]=wgetbits9(l1);sf->l[19]=wgetbits9(l1);
+ sf->l[20]=wgetbits9(l1);
+ }
+ else
+ {
+ if(sideinfo.ch[ch].scfsi[0]==0)
+ {
+ sf->l[ 0]=wgetbits9(l0);sf->l[ 1]=wgetbits9(l0);
+ sf->l[ 2]=wgetbits9(l0);sf->l[ 3]=wgetbits9(l0);
+ sf->l[ 4]=wgetbits9(l0);sf->l[ 5]=wgetbits9(l0);
+ }
+ if(sideinfo.ch[ch].scfsi[1]==0)
+ {
+ sf->l[ 6]=wgetbits9(l0);sf->l[ 7]=wgetbits9(l0);
+ sf->l[ 8]=wgetbits9(l0);sf->l[ 9]=wgetbits9(l0);
+ sf->l[10]=wgetbits9(l0);
+ }
+ if(sideinfo.ch[ch].scfsi[2]==0)
+ {
+ sf->l[11]=wgetbits9(l1);sf->l[12]=wgetbits9(l1);
+ sf->l[13]=wgetbits9(l1);sf->l[14]=wgetbits9(l1);
+ sf->l[15]=wgetbits9(l1);
+ }
+ if(sideinfo.ch[ch].scfsi[3]==0)
+ {
+ sf->l[16]=wgetbits9(l1);sf->l[17]=wgetbits9(l1);
+ sf->l[18]=wgetbits9(l1);sf->l[19]=wgetbits9(l1);
+ sf->l[20]=wgetbits9(l1);
+ }
+ }
+ sf->l[21]=sf->l[22]=0;
+ }
+ /*
+ cout << "end parse:"<<endl;
+ wgetCanReadBits();
+ */
+}
+
+void Mpegtoraw::layer3getscalefactors_2(int ch)
+{
+ static int sfbblockindex[6][3][4]=
+ {
+ {{ 6, 5, 5, 5},{ 9, 9, 9, 9},{ 6, 9, 9, 9}},
+ {{ 6, 5, 7, 3},{ 9, 9,12, 6},{ 6, 9,12, 6}},
+ {{11,10, 0, 0},{18,18, 0, 0},{15,18, 0, 0}},
+ {{ 7, 7, 7, 0},{12,12,12, 0},{ 6,15,12, 0}},
+ {{ 6, 6, 6, 3},{12, 9, 9, 6},{ 6,12, 9, 6}},
+ {{ 8, 8, 5, 0},{15,12, 9, 0},{ 6,18, 9, 0}}
+ };
+
+ int sb[54];
+ int extendedmode=mpegAudioHeader->getExtendedmode();
+ layer3grinfo *gi=&(sideinfo.ch[ch].gr[0]);
+ register layer3scalefactor *sf=(&scalefactors[ch]);
+
+ {
+ int blocktypenumber,sc;
+ int blocknumber;
+ int slen[4];
+
+ if(gi->block_type==2)blocktypenumber=1+gi->mixed_block_flag;
+ else blocktypenumber=0;
+
+ sc=gi->scalefac_compress;
+ if(!((extendedmode==1 || extendedmode==3) && (ch==1)))
+ {
+ if(sc<400)
+ {
+ slen[0]=(sc>>4)/5;
+ slen[1]=(sc>>4)%5;
+ slen[2]=(sc%16)>>2;
+ slen[3]=(sc%4);
+ gi->preflag=0;
+ blocknumber=0;
+ }
+ else if(sc<500)
+ {
+ sc-=400;
+ slen[0]=(sc>>2)/5;
+ slen[1]=(sc>>2)%5;
+ slen[2]=sc%4;
+ slen[3]=0;
+ gi->preflag=0;
+ blocknumber=1;
+ }
+ else // if(sc<512)
+ {
+ sc-=500;
+ slen[0]=sc/3;
+ slen[1]=sc%3;
+ slen[2]=0;
+ slen[3]=0;
+ gi->preflag=1;
+ blocknumber=2;
+ }
+ }
+ else
+ {
+ sc>>=1;
+ if(sc<180)
+ {
+ slen[0]=sc/36;
+ slen[1]=(sc%36)/6;
+ slen[2]=(sc%36)%6;
+ slen[3]=0;
+ gi->preflag=0;
+ blocknumber=3;
+ }
+ else if(sc<244)
+ {
+ sc-=180;
+ slen[0]=(sc%64)>>4;
+ slen[1]=(sc%16)>>2;
+ slen[2]=sc%4;
+ slen[3]=0;
+ gi->preflag=0;
+ blocknumber=4;
+ }
+ else // if(sc<255)
+ {
+ sc-=244;
+ slen[0]=sc/3;
+ slen[1]=sc%3;
+ slen[2]=
+ slen[3]=0;
+ gi->preflag=0;
+ blocknumber=5;
+ }
+ }
+
+ {
+ int i,j,k,*si;
+
+ si=sfbblockindex[blocknumber][blocktypenumber];
+ for(i=0;i<45;i++)sb[i]=0;
+
+ for(k=i=0;i<4;i++)
+ for(j=0;j<si[i];j++,k++)
+ if(slen[i]==0)sb[k]=0;
+ else sb[k]=wgetbits(slen[i]);
+ }
+ }
+
+
+ {
+ int sfb,window;
+ int k=0;
+
+ if(gi->window_switching_flag && (gi->block_type==2))
+ {
+ if(gi->mixed_block_flag)
+ {
+ for(sfb=0;sfb<8;sfb++)sf->l[sfb]=sb[k++];
+ sfb=3;
+ }
+ else sfb=0;
+
+ for(;sfb<12;sfb++)
+ for(window=0;window<3;window++)
+ sf->s[window][sfb]=sb[k++];
+
+ sf->s[0][12]=sf->s[1][12]=sf->s[2][12]=0;
+ }
+ else
+ {
+ for(sfb=0;sfb<21;sfb++)
+ sf->l[sfb]=sb[k++];
+ sf->l[21]=sf->l[22]=0;
+ }
+ }
+}
+
+
+typedef unsigned int HUFFBITS;
+#define MXOFF 250
+
+/* do the huffman-decoding */
+/* note! for counta,countb -the 4 bit value is returned in y, discard x */
+// Huffman decoder for tablename<32
+inline void Mpegtoraw::huffmandecoder_1(const HUFFMANCODETABLE *h,int *x,int *y)
+{
+ HUFFBITS level=(1<<(sizeof(HUFFBITS)*8-1));
+ int point=0;
+
+ /* Lookup in Huffman table. */
+ for(;;)
+ {
+ if(h->val[point][0]==0)
+ { /*end of tree*/
+ int xx,yy;
+
+ xx=h->val[point][1]>>4;
+ yy=h->val[point][1]&0xf;
+
+ if(h->linbits)
+ {
+ if((h->xlen)==(unsigned)xx)xx+=wgetbits(h->linbits);
+ if(xx)if(wgetbit())xx=-xx;
+ if((h->ylen)==(unsigned)yy)yy+=wgetbits(h->linbits);
+ if(yy)if(wgetbit())yy=-yy;
+ }
+ else
+ {
+ if(xx)if(wgetbit())xx=-xx;
+ if(yy)if(wgetbit())yy=-yy;
+ }
+ *x=xx;*y=yy;
+ break;
+ }
+
+ point+=h->val[point][wgetbit()];
+
+ level>>=1;
+ if(!(level || ((unsigned)point<ht->treelen)))
+ {
+ register int xx,yy;
+
+ xx=(h->xlen<<1);// set x and y to a medium value as a simple concealment
+ yy=(h->ylen<<1);
+
+ // h->xlen and h->ylen can't be 1 under tablename 32
+ // if(xx)
+ if(wgetbit())xx=-xx;
+ // if(yy)
+ if(wgetbit())yy=-yy;
+
+ *x=xx;*y=yy;
+ break;
+ }
+ }
+}
+
+// Huffman decoder tablenumber>=32
+inline void Mpegtoraw::huffmandecoder_2(const HUFFMANCODETABLE *h,
+ int *x,int *y,int *v,int *w)
+{
+ HUFFBITS level=(1<<(sizeof(HUFFBITS)*8-1));
+ int point=0;
+
+ /* Lookup in Huffman table. */
+ for(;;)
+ {
+ if(h->val[point][0]==0)
+ { /*end of tree*/
+ register int t=h->val[point][1];
+
+ if(t&8)*v=1-(wgetbit()<<1); else *v=0;
+ if(t&4)*w=1-(wgetbit()<<1); else *w=0;
+ if(t&2)*x=1-(wgetbit()<<1); else *x=0;
+ if(t&1)*y=1-(wgetbit()<<1); else *y=0;
+ break;
+ }
+ point+=h->val[point][wgetbit()];
+ level>>=1;
+ if(!(level || ((unsigned)point<ht->treelen)))
+ {
+ *v=1-(wgetbit()<<1);
+ *w=1-(wgetbit()<<1);
+ *x=1-(wgetbit()<<1);
+ *y=1-(wgetbit()<<1);
+ break;
+ }
+ }
+}
+
+typedef struct
+{
+ int l[23];
+ int s[14];
+}SFBANDINDEX;
+
+static SFBANDINDEX sfBandIndextable[3][3]=
+{
+ // MPEG 1
+ {{{0,4,8,12,16,20,24,30,36,44,52,62,74,90,110,134,162,196,238,288,342,418,576},
+ {0,4,8,12,16,22,30,40,52,66,84,106,136,192}},
+ {{0,4,8,12,16,20,24,30,36,42,50,60,72,88,106,128,156,190,230,276,330,384,576},
+ {0,4,8,12,16,22,28,38,50,64,80,100,126,192}},
+ {{0,4,8,12,16,20,24,30,36,44,54,66,82,102,126,156,194,240,296,364,448,550,576},
+ {0,4,8,12,16,22,30,42,58,78,104,138,180,192}}},
+
+ // MPEG 2
+ {{{0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576},
+ {0,4,8,12,18,24,32,42,56,74,100,132,174,192}},
+ {{0,6,12,18,24,30,36,44,54,66,80,96,114,136,162,194,232,278,330,394,464,540,576},
+ {0,4,8,12,18,26,36,48,62,80,104,136,180,192}},
+ {{0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576},
+ {0,4,8,12,18,26,36,48,62,80,104,134,174,192}}},
+ // MPEG 2.5
+ {{{0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576},
+ {0,4,8,12,18,26,36,48,62,80,104,134,174,192}},
+ {{0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576},
+ {0,4,8,12,18,26,36,48,62,80,104,134,174,192}},
+ {{0,12,24,36,48,60,72,88,108,132,160,192,232,280,336,400,476,566,568,570,572,574,576},
+ {0,8,16,24,36,52,72,96,124,160,162,164,166,192}}}
+};
+
+
+void Mpegtoraw::layer3huffmandecode(int ch,int gr,int out[SBLIMIT][SSLIMIT])
+{
+ layer3grinfo *gi=&(sideinfo.ch[ch].gr[gr]);
+ int part2_3_end=layer3part2start+(gi->part2_3_length);
+ int region1Start,region2Start;
+ int i,e=gi->big_values<<1;
+ int version=mpegAudioHeader->getVersion();
+ int frequency=mpegAudioHeader->getFrequency();
+ int mpeg25=mpegAudioHeader->getLayer25();
+
+ /* Find region boundary for short block case. */
+ if(gi->generalflag) {
+ /* Region2. */
+ region1Start=
+ sfBandIndextable[mpeg25?2:version][frequency].s[3]*3;
+ /* MPEG1:sfb[9/3]*3=36 */
+ region2Start=576;/* No Region2 for short block case. */
+ } else {
+ /* Find region boundary for long block case. */
+ region1Start=
+ sfBandIndextable[mpeg25?2:version][frequency].l[gi->region0_count+1];
+ region2Start=
+ sfBandIndextable[mpeg25?2:version][frequency].l[gi->region0_count+
+ gi->region1_count+2];
+ }
+
+ /* Read bigvalues area. */
+ for(i=0;i<e;)
+ {
+ const HUFFMANCODETABLE *h;
+ register int end;
+
+ if (i<region1Start)
+ {
+ h=&ht[gi->table_select[0]];
+ if(region1Start>e)end=e; else end=region1Start;
+ }
+ else if(i<region2Start)
+ {
+ h=&ht[gi->table_select[1]];
+ if(region2Start>e)end=e; else end=region2Start;
+ }
+ else
+ {
+ h=&ht[gi->table_select[2]];
+ end=e;
+ }
+
+ if(h->treelen) {
+ while(i<end)
+ {
+
+ int skip = HuffmanLookup::decode(h->tablename, bitwindow.peek8(),
+ &out[0][i], &out[0][i+1]);
+
+ if(skip)
+ bitwindow.forward(skip);
+ else
+ huffmandecoder_1(h,&out[0][i],&out[0][i+1]);
+ i+=2;
+ }
+ } else {
+ for(;i<end;i+=2)
+ out[0][i] =
+ out[0][i+1]=0;
+ }
+ }
+
+ /* Read count1 area. */
+ const HUFFMANCODETABLE *h=&ht[gi->count1table_select+32];
+ while(bitwindow.gettotalbit()<part2_3_end)
+ {
+ huffmandecoder_2(h,&out[0][i+2],&out[0][i+3],
+ &out[0][i ],&out[0][i+1]);
+ i+=4;
+
+ if(i>=ARRAYSIZE)
+ {
+ break;
+ }
+ }
+
+ // nonzero is the _size_ of the array with the last nonzero value
+ if (i < ARRAYSIZE) {
+ nonzero[ch] = i;
+ } else {
+ // catch bugs
+ nonzero[ch] = ARRAYSIZE;
+ }
+
+ // debug start
+#ifndef MAPLAY_OPT
+ nonzero[ch]=ARRAYSIZE;
+ for(;i<ARRAYSIZE;i++)out[0][i]=0;
+#endif
+ // debug end
+
+ bitwindow.rewind(bitwindow.gettotalbit()-part2_3_end);
+}
+
+
+static int pretab[22]={0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,3,3,3,2,0};
+
+inline REAL Mpegtoraw::layer3twopow2(int scale,int preflag,
+ int pretab_offset,int l)
+{
+ int index=l;
+
+ if(preflag)index+=pretab_offset;
+
+ return(two_to_negative_half_pow[index<<scale]);
+}
+
+inline REAL Mpegtoraw::layer3twopow2_1(int a,int b,int c)
+{
+ return POW2_1[a][b][c];
+}
+
+
+void Mpegtoraw::layer3dequantizesample(int ch,int gr,
+ int in[SBLIMIT][SSLIMIT],
+ REAL out[SBLIMIT][SSLIMIT])
+{
+ int version=mpegAudioHeader->getVersion();
+ int frequency=mpegAudioHeader->getFrequency();
+ int mpeg25=mpegAudioHeader->getLayer25();
+ layer3grinfo *gi=&(sideinfo.ch[ch].gr[gr]);
+ SFBANDINDEX *sfBandIndex=&(sfBandIndextable[mpeg25?2:version][frequency]);
+ REAL globalgain=POW2[gi->global_gain];
+ REAL *TO_FOUR_THIRDS=TO_FOUR_THIRDSTABLE+FOURTHIRDSTABLENUMBER;
+ int arrayEnd=nonzero[ch];
+ /* choose correct scalefactor band per block type, initialize boundary */
+ /* and apply formula per block type */
+ if(!gi->generalflag) {
+ /* LONG blocks: 0,1,3 */
+ int next_cb_boundary;
+ int cb=-1,index=0;
+ REAL factor;
+
+
+ do
+ {
+
+ next_cb_boundary=sfBandIndex->l[(++cb)+1];
+ REAL val=layer3twopow2(gi->scalefac_scale,gi->preflag,
+ pretab[cb],scalefactors[ch].l[cb]);
+ factor=globalgain*val;
+ // maplay opt
+ if (arrayEnd < next_cb_boundary) {
+ next_cb_boundary=arrayEnd;
+ }
+
+ for(;index<next_cb_boundary;)
+ {
+ out[0][index]=factor*TO_FOUR_THIRDS[in[0][index]];index++;
+ out[0][index]=factor*TO_FOUR_THIRDS[in[0][index]];index++;
+ }
+
+ }while(index<arrayEnd);
+ } else if(!gi->mixed_block_flag) {
+ int cb=0,index=0;
+ int cb_width;
+ do
+ {
+ cb_width=(sfBandIndex->s[cb+1]-sfBandIndex->s[cb])>>1;
+
+ for(register int k=0;k<3;k++)
+ {
+ register REAL factor;
+ register int count=cb_width;
+ // maplay12 opt.
+ if(index+(count<<1) > arrayEnd) {
+ if (index >= arrayEnd) break;
+ count=(arrayEnd-index)>>1;
+ }
+
+ factor=globalgain*
+ layer3twopow2_1(gi->subblock_gain[k],gi->scalefac_scale,
+ scalefactors[ch].s[k][cb]);
+
+
+ do{
+ out[0][index]=factor*TO_FOUR_THIRDS[in[0][index]];index++;
+ out[0][index]=factor*TO_FOUR_THIRDS[in[0][index]];index++;
+ }while(--count);
+ }
+ cb++;
+ }while(index<arrayEnd);
+ } else {
+ int cb_begin=0,cb_width=0;
+ int cb=0;
+ int next_cb_boundary=sfBandIndex->l[1]; /* LONG blocks: 0,1,3 */
+ int index;
+ // I do not have an mp3 with this format,
+ // so we restore the "make rest of array zero"
+ // in this case
+ // to use the maplay opt here, we must make sure, that
+ // arrayEnd==ArraySize.
+ for(int i=arrayEnd;i<ARRAYSIZE;i++)in[0][i]=0;
+
+ /* Compute overall (global) scaling. */
+ {
+ for(int sb=0;sb<SBLIMIT;sb++)
+ {
+ int *i=in[sb];
+ REAL *o=out[sb];
+
+ o[ 0]=globalgain*TO_FOUR_THIRDS[i[ 0]];
+ o[ 1]=globalgain*TO_FOUR_THIRDS[i[ 1]];
+ o[ 2]=globalgain*TO_FOUR_THIRDS[i[ 2]];
+ o[ 3]=globalgain*TO_FOUR_THIRDS[i[ 3]];
+ o[ 4]=globalgain*TO_FOUR_THIRDS[i[ 4]];
+ o[ 5]=globalgain*TO_FOUR_THIRDS[i[ 5]];
+ o[ 6]=globalgain*TO_FOUR_THIRDS[i[ 6]];
+ o[ 7]=globalgain*TO_FOUR_THIRDS[i[ 7]];
+ o[ 8]=globalgain*TO_FOUR_THIRDS[i[ 8]];
+ o[ 9]=globalgain*TO_FOUR_THIRDS[i[ 9]];
+ o[10]=globalgain*TO_FOUR_THIRDS[i[10]];
+ o[11]=globalgain*TO_FOUR_THIRDS[i[11]];
+ o[12]=globalgain*TO_FOUR_THIRDS[i[12]];
+ o[13]=globalgain*TO_FOUR_THIRDS[i[13]];
+ o[14]=globalgain*TO_FOUR_THIRDS[i[14]];
+ o[15]=globalgain*TO_FOUR_THIRDS[i[15]];
+ o[16]=globalgain*TO_FOUR_THIRDS[i[16]];
+ o[17]=globalgain*TO_FOUR_THIRDS[i[17]];
+ }
+ }
+ for(index=0;index<SSLIMIT*2;index++)
+ {
+ if(index==next_cb_boundary)
+ {
+ if(index==sfBandIndex->l[8])
+ {
+ next_cb_boundary=sfBandIndex->s[4];
+ next_cb_boundary=MUL3(next_cb_boundary);
+ cb=3;
+ cb_width=sfBandIndex->s[4]-sfBandIndex->s[3];
+ cb_begin=sfBandIndex->s[3];
+ cb_begin=MUL3(cb_begin);
+ }
+ else if(index<sfBandIndex->l[8])
+ next_cb_boundary=sfBandIndex->l[(++cb)+1];
+ else
+ {
+ next_cb_boundary=sfBandIndex->s[(++cb)+1];
+ next_cb_boundary=MUL3(next_cb_boundary);
+ cb_begin=sfBandIndex->s[cb];
+ cb_width=sfBandIndex->s[cb+1]-cb_begin;
+ cb_begin=MUL3(cb_begin);
+ }
+ }
+ /* LONG block types 0,1,3 & 1st 2 subbands of switched blocks */
+ out[0][index]*=layer3twopow2(gi->scalefac_scale,gi->preflag,
+ pretab[cb],scalefactors[ch].l[cb]);
+
+ }
+
+ for(;index<ARRAYSIZE;index++) {
+ if(index==next_cb_boundary) {
+ if(index==sfBandIndex->l[8]) {
+ next_cb_boundary=sfBandIndex->s[4];
+ next_cb_boundary=MUL3(next_cb_boundary);
+ cb=3;
+ cb_width=sfBandIndex->s[4]-sfBandIndex->s[3];
+ cb_begin=sfBandIndex->s[3];
+ cb_begin=(cb_begin<<2)-cb_begin;
+ } else if(index<sfBandIndex->l[8])
+ next_cb_boundary=sfBandIndex->l[(++cb)+1];
+ else {
+ next_cb_boundary=sfBandIndex->s[(++cb)+1];
+ next_cb_boundary=MUL3(next_cb_boundary);
+ cb_begin=sfBandIndex->s[cb];
+ cb_width=sfBandIndex->s[cb+1]-cb_begin;
+ cb_begin=MUL3(cb_begin);
+ }
+ }
+ {
+ /**
+ Here we check if we do a division by zero
+ and if the resulting t_index points
+ outside the array. (Needed for better robustness
+ of the mp3 decoder)
+ */
+ unsigned int t_index=0;
+ if (cb_width) {
+ t_index=(unsigned int)((index-cb_begin)/cb_width);
+ if (t_index > 2) {
+ t_index=0;
+ }
+ }
+
+ out[0][index]*=layer3twopow2_1(gi->subblock_gain[t_index],
+ gi->scalefac_scale,
+ scalefactors[ch].s[t_index][cb]);
+ }
+ }
+ }
+ /*
+ int i;
+ for(i=arrayEnd;i<ARRAYSIZE;i++) {
+ out[0][i]=(REAL) 0.0;
+ }
+ */
+}
+// make the input to nonzero[2] zero
+inline void Mpegtoraw::adjustNonZero(REAL in[2][SBLIMIT][SSLIMIT]) {
+ if ((nonzero[0] == 0) && (nonzero[1]==0)) {
+ in[RS][0][0]=(REAL) 0.0;
+ in[LS][0][0]=(REAL) 0.0;
+ nonzero[0]=1;
+ nonzero[1]=1;
+ nonzero[2]=1;
+ return;
+ }
+
+ while(nonzero[0] > nonzero[1]) {
+ in[RS][0][nonzero[1]]=(REAL) 0.0;
+ nonzero[1]++;
+ }
+ while(nonzero[1] > nonzero[0]) {
+ in[LS][0][nonzero[0]]=(REAL) 0.0;
+ nonzero[0]++;
+ }
+ // now they are the same
+ // put this into the "max" var.
+ nonzero[2]=nonzero[1];
+
+}
+
+
+inline void Mpegtoraw::layer3fixtostereo(int gr,REAL in[2][SBLIMIT][SSLIMIT])
+{
+ int version=mpegAudioHeader->getVersion();
+ int frequency=mpegAudioHeader->getFrequency();
+ int extendedmode=mpegAudioHeader->getExtendedmode();
+ int mode=mpegAudioHeader->getMode();
+ int inputstereo=mpegAudioHeader->getInputstereo();
+ int mpeg25=mpegAudioHeader->getLayer25();
+ layer3grinfo *gi=&(sideinfo.ch[0].gr[gr]);
+ SFBANDINDEX *sfBandIndex=&(sfBandIndextable[mpeg25?2:version][frequency]);
+
+ int ms_stereo=(mode==_MODE_JOINT) && (extendedmode & 0x2);
+ int i_stereo =(mode==_MODE_JOINT) && (extendedmode & 0x1);
+
+
+ if(!inputstereo)
+ { /* mono , bypass xr[0][][] to lr[0][][]*/
+ // memcpy(out[0][0],in[0][0],ARRAYSIZE*REALSIZE);
+ for(int i=nonzero[0];i<ARRAYSIZE;i++) {
+ in[LS][0][i]=(REAL) 0.0;
+ }
+ return;
+ }
+ // maplay opt.
+ adjustNonZero(in);
+ int maxArray=nonzero[2];
+
+ if(i_stereo)
+ {
+
+ // not maplay optimised make defaults
+ int i;
+ for(i=maxArray;i<ARRAYSIZE;i++) {
+ in[LS][0][i]=in[RS][0][i]=(REAL) 0.0;
+ }
+
+
+ int is_pos[ARRAYSIZE];
+ RATIOS is_ratio[ARRAYSIZE];
+ RATIOS *ratios;
+ if(version)ratios=rat_2[gi->scalefac_compress%2];
+ else ratios=rat_1;
+
+ /* initialization */
+ for(i=0;i<ARRAYSIZE;i+=2)is_pos[i]=is_pos[i+1]=7;
+
+ if(gi->generalflag)
+ {
+ if(gi->mixed_block_flag) // Part I
+ {
+ int max_sfb=0;
+
+ for(int j=0;j<3;j++)
+ {
+ int sfb,sfbcnt=2;
+
+ for(sfb=12;sfb>=3;sfb--)
+ {
+ int lines;
+
+ i=sfBandIndex->s[sfb];
+ lines=sfBandIndex->s[sfb+1]-i;
+ i=MUL3(i)+(j+1)*lines-1;
+ for(;lines>0;lines--,i--)
+ if(in[1][0][i]!=0.0f)
+ {
+ sfbcnt=sfb;
+ sfb=0;break; // quit loop
+ }
+ }
+ sfb=sfbcnt+1;
+
+ if(sfb>max_sfb)max_sfb=sfb;
+
+ for(;sfb<12;sfb++)
+ {
+ int k,t;
+
+ t=sfBandIndex->s[sfb];
+ k=sfBandIndex->s[sfb+1]-t;
+ i=MUL3(t)+j*k;
+
+ t=scalefactors[1].s[j][sfb];
+ if(t!=7)
+ {
+ RATIOS r=ratios[t];
+
+ for(;k>0;k--,i++){
+ is_pos[i]=t;is_ratio[i]=r;}
+ }
+ else
+ for(;k>0;k--,i++)is_pos[i]=t;
+ }
+ sfb=sfBandIndex->s[10];
+ sfb=MUL3(sfb)+j*(sfBandIndex->s[11]-sfb);
+
+ {
+ int k,t;
+
+ t=sfBandIndex->s[11];
+ k=sfBandIndex->s[12]-t;
+ i=MUL3(t)+j*k;
+
+ t=is_pos[sfb];
+ if(t!=7)
+ {
+ RATIOS r=is_ratio[sfb];
+
+ for(;k>0;k--,i++){
+ is_pos[i]=t;is_ratio[i]=r;}
+ }
+ else
+ for(;k>0;k--,i++)is_pos[i]=t;
+ }
+ }
+
+ if(max_sfb<=3)
+ {
+ {
+ REAL temp;
+ int k;
+
+ temp=in[1][0][0];in[1][0][0]=1.0;
+ for(k=3*SSLIMIT-1;in[1][0][k]==0.0;k--);
+ in[1][0][0]=temp;
+ for(i=0;sfBandIndex->l[i]<=k;i++);
+ }
+ {
+ int sfb=i;
+
+ i=sfBandIndex->l[i];
+ for(;sfb<8;sfb++)
+ {
+ int t=scalefactors[1].l[sfb];
+ int k=sfBandIndex->l[sfb+1]-sfBandIndex->l[sfb];
+
+ if(t!=7)
+ {
+ RATIOS r=ratios[t];
+
+ for(;k>0;k--,i++){
+ is_pos[i]=t;is_ratio[i]=r;}
+ }
+ else for(;k>0;k--,i++)is_pos[i]=t;
+ }
+ }
+ }
+ }
+ else // Part II
+ {
+ for(int j=0;j<3;j++)
+ {
+ int sfbcnt=-1;
+ int sfb;
+ for(sfb=12;sfb>=0;sfb--)
+ {
+ int lines;
+
+ {
+ int t;
+
+ t=sfBandIndex->s[sfb];
+ lines=sfBandIndex->s[sfb+1]-t;
+ i=MUL3(t)+(j+1)*lines-1;
+ }
+
+ for(;lines>0;lines--,i--)
+ if(in[1][0][i]!=0.0f)
+ {
+ sfbcnt=sfb;
+ sfb=0;break; // quit loop
+ }
+ }
+
+ for(sfb=sfbcnt+1;sfb<12;sfb++)
+ {
+ int k,t;
+
+ t=sfBandIndex->s[sfb];
+ k=sfBandIndex->s[sfb+1]-t;
+ i=MUL3(t)+j*k;
+
+ t=scalefactors[1].s[j][sfb];
+ if(t!=7)
+ {
+ RATIOS r=ratios[t];
+
+ for(;k>0;k--,i++){
+ is_pos[i]=t;is_ratio[i]=r;}
+ }
+ else for(;k>0;k--,i++)is_pos[i]=t;
+ }
+
+ {
+ int t1=sfBandIndex->s[10],
+ t2=sfBandIndex->s[11];
+ int k,tt;
+
+ tt=MUL3(t1)+j*(t2-t1);
+ k =sfBandIndex->s[12]-t2;
+ if(is_pos[tt]!=7)
+ {
+ RATIOS r=is_ratio[tt];
+ int t=is_pos[tt];
+
+ i =MUL3(t1)+j*k;
+ for(;k>0;k--,i++){
+ is_pos[i]=t;is_ratio[i]=r;}
+ }
+ else
+ for(;k>0;k--,i++)is_pos[i]=7;
+ }
+ }
+ }
+ }
+ else // ms-stereo (Part III)
+ {
+ {
+ REAL temp;
+ int k;
+
+ temp=in[1][0][0];in[1][0][0]=1.0;
+ for(k=ARRAYSIZE-1;in[1][0][k]==0.0;k--);
+ in[1][0][0]=temp;
+ for(i=0;sfBandIndex->l[i]<=k;i++);
+ }
+
+ {
+ int sfb;
+
+ sfb=i;
+ i=sfBandIndex->l[i];
+ for(;sfb<21;sfb++)
+ {
+ int k,t;
+
+ k=sfBandIndex->l[sfb+1]-sfBandIndex->l[sfb];
+ t=scalefactors[1].l[sfb];
+ if(t!=7)
+ {
+ RATIOS r=ratios[t];
+
+ for(;k>0;k--,i++){
+ is_pos[i]=t;is_ratio[i]=r;}
+ }
+ else
+ for(;k>0;k--,i++)is_pos[i]=t;
+ }
+ }
+
+ {
+ int k,t,tt;
+
+ tt=sfBandIndex->l[20];
+ k=576-sfBandIndex->l[21];
+ t=is_pos[tt];
+ if(t!=7)
+ {
+ RATIOS r=is_ratio[tt];
+
+ for(;k>0;k--,i++){
+ is_pos[i]=t;is_ratio[i]=r;}
+ }
+ else
+ for(;k>0;k--,i++)is_pos[i]=t;
+ }
+ }
+
+ if(ms_stereo)
+ {
+ i=ARRAYSIZE-1;
+ do{
+ if(is_pos[i]==7)
+ {
+ register REAL t=in[LS][0][i];
+ in[LS][0][i]=(t+in[RS][0][i])*0.7071068f;
+ in[RS][0][i]=(t-in[RS][0][i])*0.7071068f;
+ }
+ else
+ {
+ in[RS][0][i]=in[LS][0][i]*is_ratio[i].r;
+ in[LS][0][i]*=is_ratio[i].l;
+ }
+ }while(i--);
+ }
+ else
+ {
+ i=ARRAYSIZE-1;
+ do{
+ if(is_pos[i]!=7)
+ {
+ in[RS][0][i]=in[LS][0][i]*is_ratio[i].r;
+ in[LS][0][i]*=is_ratio[i].l;
+ }
+ }while(i--);
+ }
+ }
+ else
+ {
+
+ if(ms_stereo)
+ {
+ int i=maxArray-1;
+ do{
+ register REAL t=in[LS][0][i];
+
+ in[LS][0][i]=(t+in[RS][0][i])*0.7071068f;
+ in[RS][0][i]=(t-in[RS][0][i])*0.7071068f;
+ }while(i--);
+ }
+ for(int i=maxArray;i<ARRAYSIZE;i++) {
+ in[LS][0][i]=in[RS][0][i]=(REAL) 0.0;
+ }
+
+ }
+
+
+ // channels==2
+}
+
+inline void layer3reorder_1(int version,int frequency,
+ REAL in[SBLIMIT][SSLIMIT],
+ REAL out[SBLIMIT][SSLIMIT])
+{
+ SFBANDINDEX *sfBandIndex=&(sfBandIndextable[version][frequency]);
+ int sfb,sfb_start,sfb_lines;
+
+ /* NO REORDER FOR LOW 2 SUBBANDS */
+ out[0][ 0]=in[0][ 0];out[0][ 1]=in[0][ 1];out[0][ 2]=in[0][ 2];
+ out[0][ 3]=in[0][ 3];out[0][ 4]=in[0][ 4];out[0][ 5]=in[0][ 5];
+ out[0][ 6]=in[0][ 6];out[0][ 7]=in[0][ 7];out[0][ 8]=in[0][ 8];
+ out[0][ 9]=in[0][ 9];out[0][10]=in[0][10];out[0][11]=in[0][11];
+ out[0][12]=in[0][12];out[0][13]=in[0][13];out[0][14]=in[0][14];
+ out[0][15]=in[0][15];out[0][16]=in[0][16];out[0][17]=in[0][17];
+
+ out[1][ 0]=in[1][ 0];out[1][ 1]=in[1][ 1];out[1][ 2]=in[1][ 2];
+ out[1][ 3]=in[1][ 3];out[1][ 4]=in[1][ 4];out[1][ 5]=in[1][ 5];
+ out[1][ 6]=in[1][ 6];out[1][ 7]=in[1][ 7];out[1][ 8]=in[1][ 8];
+ out[1][ 9]=in[1][ 9];out[1][10]=in[1][10];out[1][11]=in[1][11];
+ out[1][12]=in[1][12];out[1][13]=in[1][13];out[1][14]=in[1][14];
+ out[1][15]=in[1][15];out[1][16]=in[1][16];out[1][17]=in[1][17];
+
+
+ /* REORDERING FOR REST SWITCHED SHORT */
+ for(sfb=3,sfb_start=sfBandIndex->s[3],
+ sfb_lines=sfBandIndex->s[4]-sfb_start;
+ sfb<13;
+ sfb++,sfb_start=sfBandIndex->s[sfb],
+ (sfb_lines=sfBandIndex->s[sfb+1]-sfb_start))
+ {
+ for(int freq=0;freq<sfb_lines;freq++)
+ {
+ int src_line=sfb_start+(sfb_start<<1)+freq;
+ int des_line=src_line+(freq<<1);
+ out[0][des_line ]=in[0][src_line ];
+ out[0][des_line+1]=in[0][src_line+sfb_lines ];
+ out[0][des_line+2]=in[0][src_line+(sfb_lines<<1)];
+ }
+ }
+}
+
+inline void layer3reorder_2(int version,int frequency,REAL in[SBLIMIT][SSLIMIT],
+ REAL out[SBLIMIT][SSLIMIT])
+{
+ SFBANDINDEX *sfBandIndex=&(sfBandIndextable[version][frequency]);
+ int sfb,sfb_start,sfb_lines;
+
+ for(sfb=0,sfb_start=0,sfb_lines=sfBandIndex->s[1];
+ sfb<13;
+ sfb++,sfb_start=sfBandIndex->s[sfb],
+ (sfb_lines=sfBandIndex->s[sfb+1]-sfb_start))
+ {
+ for(int freq=0;freq<sfb_lines;freq++)
+ {
+ int src_line=sfb_start+(sfb_start<<1)+freq;
+ int des_line=src_line+(freq<<1);
+
+ out[0][des_line ]=in[0][src_line ];
+ out[0][des_line+1]=in[0][src_line+sfb_lines ];
+ out[0][des_line+2]=in[0][src_line+(sfb_lines<<1)];
+ }
+ }
+}
+
+
+inline void layer3antialias_1(REAL in[SBLIMIT][SSLIMIT])
+{
+ for(int ss=0;ss<8;ss++)
+ {
+ REAL bu,bd; /* upper and lower butterfly inputs */
+
+ bu=in[0][17-ss];bd=in[1][ss];
+ in[0][17-ss]=(bu*cs[ss])-(bd*ca[ss]);
+ in[1][ss] =(bd*cs[ss])+(bu*ca[ss]);
+ }
+}
+
+inline
+void layer3antialias_2(REAL in[SBLIMIT][SSLIMIT],
+ REAL out[SBLIMIT][SSLIMIT])
+{
+ out[0][0]=in[0][0];out[0][1]=in[0][1];
+ out[0][2]=in[0][2];out[0][3]=in[0][3];
+ out[0][4]=in[0][4];out[0][5]=in[0][5];
+ out[0][6]=in[0][6];out[0][7]=in[0][7];
+
+ for(int index=SSLIMIT;index<=(SBLIMIT-1)*SSLIMIT;index+=SSLIMIT)
+ {
+ for(int n=0;n<8;n++)
+ {
+ REAL bu,bd;
+
+ bu=in[0][index-n-1];bd=in[0][index+n];
+ out[0][index-n-1]=(bu*cs[n])-(bd*ca[n]);
+ out[0][index+n ]=(bd*cs[n])+(bu*ca[n]);
+ }
+ out[0][index-SSLIMIT+8]=in[0][index-SSLIMIT+8];
+ out[0][index-SSLIMIT+9]=in[0][index-SSLIMIT+9];
+ }
+
+ out[31][ 8]=in[31][ 8];out[31][ 9]=in[31][ 9];
+ out[31][10]=in[31][10];out[31][11]=in[31][11];
+ out[31][12]=in[31][12];out[31][13]=in[31][13];
+ out[31][14]=in[31][14];out[31][15]=in[31][15];
+ out[31][16]=in[31][16];out[31][17]=in[31][17];
+}
+
+void Mpegtoraw::layer3reorderandantialias(int ch,int gr,
+ REAL in[SBLIMIT][SSLIMIT],
+ REAL out[SBLIMIT][SSLIMIT])
+{
+ int version=mpegAudioHeader->getVersion();
+ int frequency=mpegAudioHeader->getFrequency();
+ int mpeg25=mpegAudioHeader->getLayer25();
+ register layer3grinfo *gi=&(sideinfo.ch[ch].gr[gr]);
+
+ if(gi->generalflag) {
+ if(gi->mixed_block_flag) {
+ layer3reorder_1 (mpeg25?2:version,frequency,in,out); // Not checked...
+ layer3antialias_1(out);
+ }
+ else {
+ layer3reorder_2(mpeg25?2:version,frequency,in,out);
+ }
+ }
+ else {
+
+ layer3antialias_2(in,out);
+
+ }
+}
+
+
+#include "dct36_12.cpp"
+#include "window.cpp"
+
+void Mpegtoraw::layer3hybrid(int ch,int gr,REAL in[SBLIMIT][SSLIMIT],
+ REAL out[SSLIMIT][SBLIMIT])
+{
+ layer3grinfo *gi=&(sideinfo.ch[ch].gr[gr]);
+ int bt1,bt2;
+ REAL *prev1,*prev2;
+
+ prev1=prevblck[ch][currentprevblock][0];
+ prev2=prevblck[ch][currentprevblock^1][0];
+
+ bt1 = gi->mixed_block_flag ? 0 : gi->block_type;
+ bt2 = gi->block_type;
+
+ {
+ REAL *ci=(REAL *)in,
+ *co=(REAL *)out;
+ int i;
+
+ if(lDownSample)i=(SBLIMIT/2)-2;
+ else i=SBLIMIT-2;
+
+
+ if(bt2==2)
+ {
+ if(!bt1)
+ {
+ dct36(ci,prev1,prev2,getSplayWindow(0),co);
+ ci+=SSLIMIT;prev1+=SSLIMIT;prev2+=SSLIMIT;co++;
+ dct36(ci,prev1,prev2,getSplayWindowINV(0),co);
+ }
+ else
+ {
+ dct12(ci,prev1,prev2,getSplayWindow(2),co);
+ ci+=SSLIMIT;prev1+=SSLIMIT;prev2+=SSLIMIT;co++;
+ dct12(ci,prev1,prev2,getSplayWindowINV(2),co);
+ }
+
+ do{
+ ci+=SSLIMIT;prev1+=SSLIMIT;prev2+=SSLIMIT;co++;
+ dct12(ci,prev1,prev2,getSplayWindow(2),co);
+ i--;
+ ci+=SSLIMIT;prev1+=SSLIMIT;prev2+=SSLIMIT;co++;
+ dct12(ci,prev1,prev2,getSplayWindowINV(2),co);
+ }while(--i);
+ }
+ else
+ {
+ dct36(ci,prev1,prev2,getSplayWindow(bt1),co);
+ ci+=SSLIMIT;prev1+=SSLIMIT;prev2+=SSLIMIT;co++;
+ dct36(ci,prev1,prev2,getSplayWindowINV(bt1),co);
+
+ do
+ {
+ ci+=SSLIMIT;prev1+=SSLIMIT;prev2+=SSLIMIT;co++;
+ dct36(ci,prev1,prev2,getSplayWindow(bt2),co);
+ i--;
+ ci+=SSLIMIT;prev1+=SSLIMIT;prev2+=SSLIMIT;co++;
+ dct36(ci,prev1,prev2,getSplayWindowINV(bt2),co);
+ }while(--i);
+ }
+ }
+}
+
+void Mpegtoraw::extractlayer3(void) {
+ int version=mpegAudioHeader->getVersion();
+ int inputstereo=mpegAudioHeader->getInputstereo();
+ int layer3slots=mpegAudioHeader->getLayer3slots();
+
+ if(version) {
+ extractlayer3_2();
+ return;
+ }
+
+ {
+ int main_data_end,flush_main;
+ int bytes_to_discard;
+ if (layer3getsideinfo() == false) {
+ return;
+ }
+ // read main data.
+ if(issync()) {
+ for(register int i=layer3slots;i>0;i--) {
+ bitwindow.putbyte(getbyte());
+ }
+ } else {
+ // read main data.
+ for(register int i=layer3slots;i>0;i--) {
+ bitwindow.putbyte(getbits8());
+ }
+ }
+
+ main_data_end=bitwindow.gettotalbit()>>3;// of previous frame
+ if (main_data_end < 0) {
+ DEBUG_LAYER(printf("main_data_end < 0\n");)
+ return;
+ }
+
+ if((flush_main=(bitwindow.gettotalbit() & 0x7))) {
+ bitwindow.forward(8-flush_main);
+ main_data_end++;
+ }
+
+ bytes_to_discard=layer3framestart-(main_data_end+sideinfo.main_data_begin);
+ if(main_data_end>WINDOWSIZE) {
+ layer3framestart-=WINDOWSIZE;
+ bitwindow.rewind(WINDOWSIZE*8);
+ }
+ layer3framestart+=layer3slots;
+ bitwindow.wrap();
+ if(bytes_to_discard<0) return;
+ bitwindow.forward(bytes_to_discard<<3);
+ }
+ for(int gr=0;gr<2;gr++) {
+ ATTR_ALIGN(64) union
+ {
+ int is [SBLIMIT][SSLIMIT];
+ REAL hin [2][SBLIMIT][SSLIMIT];
+ }b1;
+ ATTR_ALIGN(64) union
+ {
+ REAL ro [2][SBLIMIT][SSLIMIT];
+ REAL lr [2][SBLIMIT][SSLIMIT];
+ REAL hout [2][SSLIMIT][SBLIMIT];
+ }b2;
+
+ layer3part2start=bitwindow.gettotalbit();
+ layer3getscalefactors (LS,gr);
+
+ layer3huffmandecode (LS,gr ,b1.is);
+ layer3dequantizesample(LS,gr,b1.is,b2.ro[LS]);
+ //dump->dump(b2.ro[LS]);
+
+ if(inputstereo) {
+ layer3part2start=bitwindow.gettotalbit();
+ layer3getscalefactors (RS,gr);
+ layer3huffmandecode (RS,gr ,b1.is);
+ layer3dequantizesample(RS,gr,b1.is,b2.ro[RS]);
+ }
+ layer3fixtostereo(gr,b2.ro); // b2.ro -> b2.lr
+ currentprevblock^=1;
+
+
+ layer3reorderandantialias(LS,gr,b2.lr[LS],b1.hin[LS]);
+ //dump->dump(b1.hin[LS]);
+ layer3hybrid (LS,gr,b1.hin[LS],b2.hout[LS]);
+ //dump->dump(b2.hout[LS]);
+
+
+
+
+ if(lOutputStereo) {
+ layer3reorderandantialias(RS,gr,b2.lr[RS],b1.hin[RS]);
+ layer3hybrid (RS,gr,b1.hin[RS],b2.hout[RS]);
+
+ }
+ synthesis->doMP3Synth(lDownSample,lOutputStereo,b2.hout);
+ }
+}
+
+void Mpegtoraw::extractlayer3_2(void) {
+ int inputstereo=mpegAudioHeader->getInputstereo();
+ int layer3slots=mpegAudioHeader->getLayer3slots();
+
+ {
+ int main_data_end,flush_main;
+ int bytes_to_discard;
+ if (layer3getsideinfo_2() == false) {
+ return;
+ }
+ // read main data.
+ if(issync()) {
+ for(register int i=layer3slots;i>0;i--) {
+ bitwindow.putbyte(getbyte());
+ }
+ }
+ else {
+ // read main data.
+ for(register int i=layer3slots;i>0;i--) {
+ bitwindow.putbyte(getbits8());
+ }
+ }
+
+ //bitwindow.wrap();
+
+ main_data_end=bitwindow.gettotalbit()>>3;// of previous frame
+ if (main_data_end < 0) {
+ DEBUG_LAYER(printf("main_data_end < 0\n");)
+ return;
+ }
+
+ if((flush_main=(bitwindow.gettotalbit() & 0x7))) {
+ bitwindow.forward(8-flush_main);
+ main_data_end++;
+ }
+
+ bytes_to_discard=layer3framestart-(main_data_end+sideinfo.main_data_begin);
+ if(main_data_end>WINDOWSIZE) {
+ layer3framestart-=WINDOWSIZE;
+ bitwindow.rewind(WINDOWSIZE*8);
+ }
+ layer3framestart+=layer3slots;
+
+ bitwindow.wrap();
+ if(bytes_to_discard<0)return;
+ bitwindow.forward(bytes_to_discard<<3);
+ }
+
+ //for(int gr=0;gr<2;gr++) {
+ ATTR_ALIGN(64) union
+ {
+ int is [SBLIMIT][SSLIMIT];
+ REAL hin [2][SBLIMIT][SSLIMIT];
+ }b1;
+ ATTR_ALIGN(64) union
+ {
+ REAL ro [2][SBLIMIT][SSLIMIT];
+ REAL lr [2][SBLIMIT][SSLIMIT];
+ REAL hout [2][SSLIMIT][SBLIMIT];
+ }b2;
+
+
+ layer3part2start=bitwindow.gettotalbit();
+ layer3getscalefactors_2(LS);
+ //dump->dump(&scalefactors[LS]);
+
+ layer3huffmandecode (LS,0 ,b1.is);
+ //dump->dump(b1.is);
+ layer3dequantizesample (LS,0,b1.is,b2.ro[LS]);
+
+ if(inputstereo) {
+ layer3part2start=bitwindow.gettotalbit();
+ layer3getscalefactors_2(RS);
+ layer3huffmandecode (RS,0 ,b1.is);
+ layer3dequantizesample (RS,0,b1.is,b2.ro[RS]);
+ }
+
+ layer3fixtostereo(0,b2.ro); // b2.ro -> b2.lr
+ currentprevblock^=1;
+
+ layer3reorderandantialias(LS,0,b2.lr[LS],b1.hin[LS]);
+ layer3hybrid (LS,0,b1.hin[LS],b2.hout[LS]);
+ if(lOutputStereo) {
+ layer3reorderandantialias(RS,0,b2.lr[RS],b1.hin[RS]);
+ layer3hybrid (RS,0,b1.hin[RS],b2.hout[RS]);
+ }
+ synthesis->doMP3Synth(lDownSample,lOutputStereo,b2.hout);
+
+
+}
diff --git a/mpeglib/lib/splay/mpegsound.h b/mpeglib/lib/splay/mpegsound.h
new file mode 100644
index 00000000..cd0c3571
--- /dev/null
+++ b/mpeglib/lib/splay/mpegsound.h
@@ -0,0 +1,248 @@
+// MPEG/WAVE Sound library
+
+// (C) 1997 by Woo-jae Jung
+
+// Mpegsound.h
+// This is typeset for functions in MPEG/WAVE Sound library.
+// Now, it's for only linux-pc-?86
+
+/************************************/
+/* Include default library packages */
+/************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+
+#include "mpegAudioStream.h"
+#include "common.h"
+
+class Synthesis;
+class AudioFrame;
+
+
+#ifndef _L__SOUND__
+#define _L__SOUND__
+
+#include "mpegAudioHeader.h"
+#include "mpegAudioBitWindow.h"
+
+
+//#define DEBUG_LAYER(x) x
+#define DEBUG_LAYER(x)
+
+
+/**************************/
+/* Define values for MPEG */
+/**************************/
+#define SCALEBLOCK 12
+#define MAXSUBBAND 32
+#define MAXCHANNEL 2
+#define RAWDATASIZE (2*2*2*32*SSLIMIT)
+
+
+
+// Huffmancode
+#define HTN 34
+
+
+
+#define MODE_MONO 0
+#define MODE_STEREO 1
+
+/********************/
+/* Type definitions */
+/********************/
+
+typedef struct {
+ bool generalflag;
+ unsigned int part2_3_length;
+ unsigned int big_values;
+ unsigned int global_gain;
+ unsigned int scalefac_compress;
+ unsigned int window_switching_flag;
+ unsigned int block_type;
+ unsigned int mixed_block_flag;
+ unsigned int table_select[3];
+ unsigned int subblock_gain[3];
+ unsigned int region0_count;
+ unsigned int region1_count;
+ unsigned int preflag;
+ unsigned int scalefac_scale;
+ unsigned int count1table_select;
+}layer3grinfo;
+
+typedef struct {
+ unsigned main_data_begin;
+ unsigned private_bits;
+ struct {
+ unsigned scfsi[4];
+ layer3grinfo gr[2];
+ }ch[2];
+}layer3sideinfo;
+
+typedef struct {
+ int l[23]; /* [cb] */
+ int s[3][13]; /* [window][cb] */
+}layer3scalefactor; /* [ch] */
+
+typedef struct {
+ int tablename;
+ unsigned int xlen,ylen;
+ unsigned int linbits;
+ unsigned int treelen;
+ const unsigned int (*val)[2];
+}HUFFMANCODETABLE;
+
+
+
+
+
+
+
+class DCT;
+class Dump;
+
+// Class for converting mpeg format to raw format
+class Mpegtoraw {
+ /*****************************/
+ /* Constant tables for layer */
+ /*****************************/
+private:
+ static const int bitrate[2][3][15];
+ static const int frequencies[2][3];
+ static const REAL scalefactorstable[64];
+ static const ATTR_ALIGN(64) HUFFMANCODETABLE ht[HTN];
+
+
+ friend class HuffmanLookup;
+
+ /*************************/
+ /* MPEG header variables */
+ /*************************/
+
+ // comes from constructor, decoder works on them
+ MpegAudioStream* mpegAudioStream;
+ MpegAudioHeader* mpegAudioHeader;
+ AudioFrame* audioFrame;
+ Dump* dump;
+ Synthesis* synthesis;
+
+ /***************************************/
+ /* Interface for setting music quality */
+ /***************************************/
+
+ int lWantStereo;
+ int lOutputStereo;
+ int lDownSample;
+
+public:
+ Mpegtoraw(MpegAudioStream* mpegAudioStream,
+ MpegAudioHeader* mpegAudioHeader);
+
+
+ ~Mpegtoraw();
+ int decode(AudioFrame* audioFrame);
+
+
+ void setStereo(int lStereo);
+ int getStereo();
+
+ void setDownSample(int lDownSample);
+ int getDownSample();
+
+
+
+private:
+ void initialize();
+
+
+
+ /*****************************/
+ /* Loading MPEG-Audio stream */
+ /*****************************/
+
+ union
+ {
+ unsigned char store[4];
+ unsigned int current;
+ }u;
+
+
+ int getbyte() { return mpegAudioStream->getbyte(); }
+ int getbits(int bits) { return mpegAudioStream->getbits(bits); }
+ int getbits9(int bits) { return mpegAudioStream->getbits9(bits); }
+ int getbits8() { return mpegAudioStream->getbits8(); }
+ int getbit() { return mpegAudioStream->getbit(); }
+
+
+ void sync() { mpegAudioStream->sync(); }
+ bool issync() { return mpegAudioStream->issync(); }
+
+
+ /********************/
+ /* Global variables */
+ /********************/
+
+ // optimisation from maplay12+
+ // 0/1: nonzero for channel 0/1 2: max position for both
+ int nonzero[3];
+
+ // for Layer3
+
+ int layer3framestart;
+ int layer3part2start;
+
+ ATTR_ALIGN(64) REAL prevblck[2][2][SBLIMIT][SSLIMIT];
+ int currentprevblock;
+ ATTR_ALIGN(64) layer3sideinfo sideinfo;
+ ATTR_ALIGN(64) layer3scalefactor scalefactors[2];
+
+ ATTR_ALIGN(64) MpegAudioBitWindow bitwindow;
+ MpegAudioBitWindow lastValidBitwindow;
+
+ int wgetbit(void);
+ int wgetbits9(int bits);
+ int wgetbits(int bits);
+ int wgetCanReadBits();
+
+ /*************************************/
+ /* Decoding functions for each layer */
+ /*************************************/
+
+ // Extractor
+ void extractlayer1(void); // MPEG-1
+ void extractlayer2(void);
+ void extractlayer3(void);
+ void extractlayer3_2(void); // MPEG-2
+
+
+ // Functions for layer 3
+ void layer3initialize(void);
+ bool layer3getsideinfo(void);
+ bool layer3getsideinfo_2(void);
+ void layer3getscalefactors(int ch,int gr);
+ void layer3getscalefactors_2(int ch);
+ void layer3huffmandecode(int ch,int gr,int out[SBLIMIT][SSLIMIT]);
+ REAL layer3twopow2(int scale,int preflag,int pretab_offset,int l);
+ REAL layer3twopow2_1(int a,int b,int c);
+ void layer3dequantizesample(int ch,int gr,int in[SBLIMIT][SSLIMIT],
+ REAL out[SBLIMIT][SSLIMIT]);
+ void adjustNonZero(REAL in[2][SBLIMIT][SSLIMIT]);
+ void layer3fixtostereo(int gr,REAL in[2][SBLIMIT][SSLIMIT]);
+ void layer3reorderandantialias(int ch,int gr,REAL in[SBLIMIT][SSLIMIT],
+ REAL out[SBLIMIT][SSLIMIT]);
+
+ void layer3hybrid(int ch,int gr,REAL in[SBLIMIT][SSLIMIT],
+ REAL out[SSLIMIT][SBLIMIT]);
+
+ void huffmandecoder_1(const HUFFMANCODETABLE *h,int *x,int *y);
+ void huffmandecoder_2(const HUFFMANCODETABLE *h,int *x,int *y,int *v,int *w);
+
+};
+
+
+
+#endif
diff --git a/mpeglib/lib/splay/mpegtable.cpp b/mpeglib/lib/splay/mpegtable.cpp
new file mode 100644
index 00000000..be539ddd
--- /dev/null
+++ b/mpeglib/lib/splay/mpegtable.cpp
@@ -0,0 +1,35 @@
+/* MPEG/WAVE Sound library
+
+ (C) 1997 by Jung woo-jae */
+
+// Mpegtable.cc
+// It has tables for MPEG layer 1, 2 and a part of layer 3
+
+
+#include "mpegsound.h"
+
+
+
+// Mpeg general table
+const REAL Mpegtoraw::scalefactorstable[64] =
+{
+ 2.00000000000000, 1.58740105196820, 1.25992104989487, 1.00000000000000,
+ 0.79370052598410, 0.62996052494744, 0.50000000000000, 0.39685026299205,
+ 0.31498026247372, 0.25000000000000, 0.19842513149602, 0.15749013123686,
+ 0.12500000000000, 0.09921256574801, 0.07874506561843, 0.06250000000000,
+ 0.04960628287401, 0.03937253280921, 0.03125000000000, 0.02480314143700,
+ 0.01968626640461, 0.01562500000000, 0.01240157071850, 0.00984313320230,
+ 0.00781250000000, 0.00620078535925, 0.00492156660115, 0.00390625000000,
+ 0.00310039267963, 0.00246078330058, 0.00195312500000, 0.00155019633981,
+ 0.00123039165029, 0.00097656250000, 0.00077509816991, 0.00061519582514,
+ 0.00048828125000, 0.00038754908495, 0.00030759791257, 0.00024414062500,
+ 0.00019377454248, 0.00015379895629, 0.00012207031250, 0.00009688727124,
+ 0.00007689947814, 0.00006103515625, 0.00004844363562, 0.00003844973907,
+ 0.00003051757813, 0.00002422181781, 0.00001922486954, 0.00001525878906,
+ 0.00001211090890, 0.00000961243477, 0.00000762939453, 0.00000605545445,
+ 0.00000480621738, 0.00000381469727, 0.00000302772723, 0.00000240310869,
+ 0.00000190734863, 0.00000151386361, 0.00000120155435, 0.00000000000000
+};
+
+
+
diff --git a/mpeglib/lib/splay/mpegtoraw.cpp b/mpeglib/lib/splay/mpegtoraw.cpp
new file mode 100644
index 00000000..93143bbe
--- /dev/null
+++ b/mpeglib/lib/splay/mpegtoraw.cpp
@@ -0,0 +1,127 @@
+/* MPEG/WAVE Sound library
+
+ (C) 1997 by Jung woo-jae */
+
+// Mpegtoraw.cc
+// Server which get mpeg format and put raw format.
+
+
+#include "mpegsound.h"
+#include "synthesis.h"
+#include "dump.h"
+#include "../frame/audioFrame.h"
+
+#include <iostream>
+
+using namespace std;
+
+Mpegtoraw::Mpegtoraw(MpegAudioStream* mpegAudioStream,
+ MpegAudioHeader* mpegAudioHeader) {
+
+ this->mpegAudioStream=mpegAudioStream;
+ this->mpegAudioHeader=mpegAudioHeader;
+
+ this->lOutputStereo=true;
+ setStereo(true);
+ setDownSample(false);
+
+ dump=new Dump();
+ synthesis=new Synthesis();
+ initialize();
+
+}
+
+Mpegtoraw::~Mpegtoraw() {
+
+ delete synthesis;
+ delete dump;
+}
+
+
+
+
+
+
+
+void Mpegtoraw::setStereo(int flag) {
+ lWantStereo=flag;
+}
+
+void Mpegtoraw::setDownSample(int flag) {
+ lDownSample=flag;
+}
+
+int Mpegtoraw::getStereo() {
+ return lWantStereo;
+}
+
+int Mpegtoraw::getDownSample() {
+ return lDownSample;
+}
+
+
+
+
+
+
+
+// Convert mpeg to raw
+// Mpeg headder class
+void Mpegtoraw::initialize() {
+
+
+
+ layer3initialize();
+
+
+}
+
+
+
+
+
+// Convert mpeg to raw
+int Mpegtoraw::decode(AudioFrame* audioFrame) {
+ int back=true;
+
+ this->audioFrame=audioFrame;
+ if (audioFrame->getSize() < RAWDATASIZE) {
+ cout << "audioFrame needs at least:"<<RAWDATASIZE<<" size"<<endl;
+ exit(0);
+ }
+
+ audioFrame->clearrawdata();
+ synthesis->clearrawdata();
+
+ int layer=mpegAudioHeader->getLayer();
+ this->lOutputStereo=lWantStereo & mpegAudioHeader->getInputstereo();
+
+ if (mpegAudioHeader->getProtection()==false) {
+ mpegAudioStream->getbyte();
+ mpegAudioStream->getbyte();
+ }
+ switch(layer) {
+ case 3:
+ extractlayer3();
+ break;
+ case 2:
+ extractlayer2();
+ break;
+ case 1:
+ extractlayer1();
+ break;
+ default:
+ cout << "unknown layer:"<<layer<<endl;
+ back=false;
+ }
+
+ //
+ // Now put the frequencies/output etc.. in the frame
+ //
+ audioFrame->setFrameFormat(lOutputStereo,
+ mpegAudioHeader->getFrequencyHz()>>lDownSample);
+
+ audioFrame->putFloatData(synthesis->getOutputData(),synthesis->getLen());
+ return back;
+
+}
diff --git a/mpeglib/lib/splay/op.h b/mpeglib/lib/splay/op.h
new file mode 100644
index 00000000..a741e97b
--- /dev/null
+++ b/mpeglib/lib/splay/op.h
@@ -0,0 +1,96 @@
+/*
+ unrolled operations, for better Pentium FPU scheduling
+ 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 __OP_H
+#define __OP_H
+
+/**
+ The Pentium has two pipelined FPUs which makes it possible
+ to do two operations in one cycle.
+ (If you are lucky)
+
+*/
+
+#define PTR_DIST (1024)
+
+#define OS r1=vp1[0] * dp[0]; \
+ r2=vp1[PTR_DIST-0] * dp[0]; \
+ dp++;
+
+#define XX1 vp1+=15;dp++;
+
+#define XX2 r1+=vp1[0] * dp[-1]; \
+ r2+=vp1[PTR_DIST-0] * dp[-1];
+
+#define OP_END(val) vp1-=val;dp+=val;
+
+#define OP_END_1(vVal,dVal) vp1+=(vVal-dVal),dp+=dVal
+
+
+// this is OP_END(x);XX1; together:
+#define OP_END_2(vVal) vp1+=(15-vVal),dp+=vVal+1
+
+
+// check this to test pipelining
+
+#define SCHEDULE1(op,r1,r2) r1;op;r2;
+#define SCHEDULE2(op,r1,r2) op;r1;r2;
+
+#define SCHEDULE(a,b,c) SCHEDULE2(a,b,c);
+
+
+#define OP r1+=vp1[-1] * dp[0]; \
+ r2+=vp1[PTR_DIST-1] * dp[0];
+
+
+
+#define OP2 SCHEDULE(OP ,r1+=vp1[-2] * dp[1] ,r2+=vp1[PTR_DIST-2] *dp[1]);
+#define OP3 SCHEDULE(OP2 ,r1+=vp1[-3] * dp[2] ,r2+=vp1[PTR_DIST-3] *dp[2]);
+#define OP4 SCHEDULE(OP3 ,r1+=vp1[-4] * dp[3] ,r2+=vp1[PTR_DIST-4] *dp[3]);
+#define OP5 SCHEDULE(OP4 ,r1+=vp1[-5] * dp[4] ,r2+=vp1[PTR_DIST-5] *dp[4]);
+#define OP6 SCHEDULE(OP5 ,r1+=vp1[-6] * dp[5] ,r2+=vp1[PTR_DIST-6] *dp[5]);
+#define OP7 SCHEDULE(OP6 ,r1+=vp1[-7] * dp[6] ,r2+=vp1[PTR_DIST-7] *dp[6]);
+#define OP8 SCHEDULE(OP7 ,r1+=vp1[-8] * dp[7] ,r2+=vp1[PTR_DIST-8] *dp[7]);
+#define OP9 SCHEDULE(OP8 ,r1+=vp1[-9] * dp[8] ,r2+=vp1[PTR_DIST-9] *dp[8]);
+#define OP10 SCHEDULE(OP9 ,r1+=vp1[-10] * dp[9] ,r2+=vp1[PTR_DIST-10] *dp[9]);
+#define OP11 SCHEDULE(OP10,r1+=vp1[-11] * dp[10],r2+=vp1[PTR_DIST-11] *dp[10]);
+#define OP12 SCHEDULE(OP11,r1+=vp1[-12] * dp[11],r2+=vp1[PTR_DIST-12] *dp[11]);
+#define OP13 SCHEDULE(OP12,r1+=vp1[-13] * dp[12],r2+=vp1[PTR_DIST-13] *dp[12]);
+#define OP14 SCHEDULE(OP13,r1+=vp1[-14] * dp[13],r2+=vp1[PTR_DIST-14] *dp[13]);
+#define OP15 SCHEDULE(OP14,r1+=vp1[-15] * dp[14],r2+=vp1[PTR_DIST-15] *dp[14]);
+
+
+/*
+#define OP r1+=vp1[-1] * dp[0]; \
+ r2+=vp2[-1] * dp[0];
+
+
+
+#define OP2 SCHEDULE(OP ,r1+=vp1[-2] * dp[1] ,r2+=vp2[-2] * dp[1]);
+#define OP3 SCHEDULE(OP2 ,r1+=vp1[-3] * dp[2] ,r2+=vp2[-3] * dp[2]);
+#define OP4 SCHEDULE(OP3 ,r1+=vp1[-4] * dp[3] ,r2+=vp2[-4] * dp[3]);
+#define OP5 SCHEDULE(OP4 ,r1+=vp1[-5] * dp[4] ,r2+=vp2[-5] * dp[4]);
+#define OP6 SCHEDULE(OP5 ,r1+=vp1[-6] * dp[5] ,r2+=vp2[-6] * dp[5]);
+#define OP7 SCHEDULE(OP6 ,r1+=vp1[-7] * dp[6] ,r2+=vp2[-7] * dp[6]);
+#define OP8 SCHEDULE(OP7 ,r1+=vp1[-8] * dp[7] ,r2+=vp2[-8] * dp[7]);
+#define OP9 SCHEDULE(OP8 ,r1+=vp1[-9] * dp[8] ,r2+=vp2[-9] * dp[8]);
+#define OP10 SCHEDULE(OP9 ,r1+=vp1[-10] * dp[9] ,r2+=vp2[-10] * dp[9]);
+#define OP11 SCHEDULE(OP10,r1+=vp1[-11] * dp[10],r2+=vp2[-11] * dp[10]);
+#define OP12 SCHEDULE(OP11,r1+=vp1[-12] * dp[11],r2+=vp2[-12] * dp[11]);
+#define OP13 SCHEDULE(OP12,r1+=vp1[-13] * dp[12],r2+=vp2[-13] * dp[12]);
+#define OP14 SCHEDULE(OP13,r1+=vp1[-14] * dp[13],r2+=vp2[-14] * dp[13]);
+#define OP15 SCHEDULE(OP14,r1+=vp1[-15] * dp[14],r2+=vp2[-15] * dp[14]);
+*/
+
+#endif
diff --git a/mpeglib/lib/splay/sigsev.c b/mpeglib/lib/splay/sigsev.c
new file mode 100644
index 00000000..906d8cb9
--- /dev/null
+++ b/mpeglib/lib/splay/sigsev.c
@@ -0,0 +1,29 @@
+/*
+ No SegFault:
+
+ g++ -o sigsev.exe sigsevTest.cpp
+
+ SegFault:
+
+ g++ -o sigsev.exe -O6 sigsevTest.cpp
+ */
+
+#include <stdio.h>
+#undef __NO_MATH_INLINES // <<<< Add this line
+#define __NO_MATH_INLINES 1 // <<<< and this.
+#include <math.h>
+
+
+int main() {
+ printf("hello Martin test->main\n");
+
+ //pow(6.0,3.0);
+ float value;
+ value=cos(double(0));
+ printf("Wert: %f\n",value);
+ pow(6.0,3.0);
+
+ printf("hi:\n");
+ exit(0);
+}
+
diff --git a/mpeglib/lib/splay/splayDecoder.cpp b/mpeglib/lib/splay/splayDecoder.cpp
new file mode 100644
index 00000000..13d6de1b
--- /dev/null
+++ b/mpeglib/lib/splay/splayDecoder.cpp
@@ -0,0 +1,73 @@
+/*
+ decoder interface for the splay mp3 decoder.
+ 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
+
+ */
+
+#define _FROM_SOURCE
+#include "dxHead.h"
+#include "splayDecoder.h"
+#include "mpegsound.h"
+
+
+
+SplayDecoder::SplayDecoder() {
+ header = new MpegAudioHeader();
+ stream = new MpegAudioStream();
+ server = new Mpegtoraw(stream,header);
+
+ xHeadData=new XHEADDATA();
+ xHeadData->toc=new unsigned char[101];
+ dump=new Dump();
+}
+
+
+SplayDecoder::~SplayDecoder() {
+ delete [] xHeadData->toc;
+ delete xHeadData;
+
+ delete server;
+ delete header;
+ delete stream;
+ delete dump;
+}
+
+
+
+int SplayDecoder::decode(unsigned char* ptr, int len,AudioFrame* dest) {
+ int back;
+ // fist setup the stream and the 4 bytes header info;
+ //dump->dump((char*)ptr,len);
+ if (header->parseHeader(ptr) == false) {
+ return false;
+ }
+ // maybe a Xing Header?
+ if (len >= 152+4) {
+ int lXing=GetXingHeader(xHeadData,(unsigned char*)ptr);
+ if (lXing) {
+ return false;
+ }
+ }
+ stream->setFrame(ptr+4,len-4);
+ back=server->decode(dest);
+
+ return back;
+
+}
+
+
+void SplayDecoder::config(const char* key,const char* val,void* ) {
+ if (strcmp(key,"2")==0) {
+ server->setDownSample(atoi(val));
+ }
+ if (strcmp(key,"m")==0) {
+ server->setStereo(atoi(val));
+ }
+}
+
diff --git a/mpeglib/lib/splay/splayDecoder.h b/mpeglib/lib/splay/splayDecoder.h
new file mode 100644
index 00000000..acbfdbfc
--- /dev/null
+++ b/mpeglib/lib/splay/splayDecoder.h
@@ -0,0 +1,70 @@
+/*
+ decoder interface for the splay mp3 decoder.
+ 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 __SPLAYDECODER_H
+#define __SPLAYDECODER_H
+
+// state definitions for splay decoder
+
+#define _SPLAY_RESET 0
+#define _SPLAY_EOF 1
+#define _SPLAY_FIRSTINIT 2
+#define _SPLAY_REINIT 3
+#define _SPLAY_DECODE 4
+#define _SPLAY_FRAME 5
+
+
+#include "../frame/audioFrame.h"
+#include "dump.h"
+#include <string.h>
+#include <kdemacros.h>
+
+class Mpegtoraw;
+class MpegAudioStream;
+class MpegAudioHeader;
+
+
+/**
+ The decoder interface.
+ The decoder expects an mpeg audio frame.
+ The call to decode is "atomic", after that you have
+ a PCMFrame to play.
+
+*/
+
+
+
+class KDE_EXPORT SplayDecoder {
+
+ MpegAudioStream* stream;
+ MpegAudioHeader* header;
+ Mpegtoraw* server;
+ Dump* dump;
+#ifdef _FROM_SOURCE
+ XHEADDATA* xHeadData;
+#else
+ void* xHeadData;
+#endif
+
+
+ public:
+ SplayDecoder();
+ ~SplayDecoder();
+
+ int decode(unsigned char* ptr, int len,AudioFrame* dest);
+ void config(const char* key,const char* val,void* ret);
+
+};
+#endif
diff --git a/mpeglib/lib/splay/synth_Down.cpp b/mpeglib/lib/splay/synth_Down.cpp
new file mode 100644
index 00000000..fbe3887b
--- /dev/null
+++ b/mpeglib/lib/splay/synth_Down.cpp
@@ -0,0 +1,231 @@
+/*
+ downsample implementation
+ 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 "synthesis.h"
+#include "dct64_down.cpp"
+
+#include <iostream>
+
+using namespace std;
+
+
+void Synthesis::computebuffer_Down(REAL *fraction,
+ REAL buffer[2][CALCBUFFERSIZE]){
+ REAL *out1,*out2;
+
+ out1=buffer[currentcalcbuffer]+calcbufferoffset;
+ out2=buffer[currentcalcbuffer^1]+calcbufferoffset;
+ dct64_downsample(out1,out2,fraction);
+}
+
+
+
+#define SAVE putraw(r); \
+ dp+=16;vp+=15+(15-14)
+#define OS r=*vp * *dp++
+#define XX vp+=15;r+=*vp * *dp++
+#define OP r+=*--vp * *dp++
+
+inline void Synthesis::generatesingle_Down(void)
+{
+ int i;
+ register REAL r, *vp;
+ register const REAL *dp;
+
+ i=32/2;
+ dp=filter;
+ vp=calcbuffer[LS][currentcalcbuffer]+calcbufferoffset;
+// actual_v+actual_write_pos;
+
+ switch (calcbufferoffset)
+ {
+ case 0:for(;i;i--,vp+=15){
+ OS;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 1:for(;i;i--,vp+=15){
+ OS;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 2:for(;i;i--,vp+=15){
+ OS;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 3:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 4:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 5:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 6:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 7:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 8:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 9:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 10:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;
+ SAVE;}break;
+ case 11:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;
+ SAVE;}break;
+ case 12:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;
+ SAVE;}break;
+ case 13:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;
+ SAVE;}break;
+ case 14:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;
+ SAVE;}break;
+ case 15:for(;i;i--,vp+=31){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ }
+}
+
+#undef OS
+#undef XX
+#undef OP
+#undef SAVE
+
+#define SAVE \
+ putraw(r1); \
+ putraw(r2); \
+ dp+=16;vp1+=15+(15-14);vp2+=15+(15-14)
+#define OS r1=*vp1 * *dp; \
+ r2=*vp2 * *dp++
+#define XX vp1+=15;r1+=*vp1 * *dp; \
+ vp2+=15;r2+=*vp2 * *dp++
+#define OP r1+=*--vp1 * *dp; \
+ r2+=*--vp2 * *dp++
+
+
+inline void Synthesis::generate_Down(void)
+{
+ int i;
+ REAL r1,r2;
+ register REAL *vp1,*vp2;
+ register const REAL *dp;
+
+ dp=filter;
+ vp1=calcbuffer[LS][currentcalcbuffer]+calcbufferoffset;
+ vp2=calcbuffer[RS][currentcalcbuffer]+calcbufferoffset;
+// actual_v+actual_write_pos;
+
+ i=32/2;
+ switch (calcbufferoffset)
+ {
+ case 0:for(;i;i--,vp1+=15,vp2+=15){
+ OS;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 1:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 2:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 3:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 4:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 5:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 6:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 7:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 8:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 9:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 10:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;
+ SAVE;}break;
+ case 11:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;
+ SAVE;}break;
+ case 12:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;
+ SAVE;}break;
+ case 13:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;
+ SAVE;}break;
+ case 14:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;
+ SAVE;}break;
+ case 15:for(;i;i--,vp1+=31,vp2+=31){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ }
+}
+
+
+
+void Synthesis::synth_Down(int lOutputStereo,REAL *fractionL,REAL *fractionR) {
+ switch(lOutputStereo) {
+ case true:
+ computebuffer_Down(fractionL,calcbuffer[LS]);
+ computebuffer_Down(fractionR,calcbuffer[RS]);
+ generate_Down();
+ nextOffset();
+ break;
+ case false:
+ computebuffer_Down(fractionL,calcbuffer[LS]);
+ generatesingle_Down();
+ nextOffset();
+ break;
+ default:
+ cout << "unknown lOutputStereo in Synthesis::synth_Std"<<endl;
+ exit(0);
+ }
+}
+
+
+void Synthesis::synthMP3_Down(int lOutputStereo,
+ REAL hout [2][SSLIMIT][SBLIMIT]) {
+ int ss;
+ switch(lOutputStereo) {
+ case true:
+ for(ss=0;ss<SSLIMIT;ss++) {
+ computebuffer_Down(hout[LS][ss],calcbuffer[LS]);
+ computebuffer_Down(hout[RS][ss],calcbuffer[RS]);
+ generate_Down();
+ nextOffset();
+ }
+ break;
+ case false:
+ for(ss=0;ss<SSLIMIT;ss++) {
+ computebuffer_Down(hout[LS][ss],calcbuffer[LS]);
+ generatesingle_Down();
+ nextOffset();
+ }
+ break;
+ default:
+ cout << "unknown lOutputStereo in Synthesis::synth_Std"<<endl;
+ exit(0);
+ }
+}
diff --git a/mpeglib/lib/splay/synth_Std.cpp b/mpeglib/lib/splay/synth_Std.cpp
new file mode 100644
index 00000000..6ea1d027
--- /dev/null
+++ b/mpeglib/lib/splay/synth_Std.cpp
@@ -0,0 +1,330 @@
+/*
+ std synth implementation
+ 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 "synthesis.h"
+
+
+
+#include "dct64.cpp"
+
+#include <iostream>
+
+using namespace std;
+
+inline void Synthesis::computebuffer_Std(REAL *fraction,
+ REAL buffer[2][CALCBUFFERSIZE]) {
+ REAL *out1,*out2;
+ out1=buffer[currentcalcbuffer]+calcbufferoffset;
+ out2=buffer[currentcalcbuffer^1]+calcbufferoffset;
+ dct64(out1,out2,fraction);
+}
+
+
+#define SAVE putraw(r);
+#define OS r=*vp * *dp++
+#define XX vp+=15;r+=*vp * *dp++
+#define OP r+=*--vp * *dp++
+
+
+inline void Synthesis::generatesingle_Std(void) {
+ int i;
+ register REAL r, *vp;
+ register const REAL *dp;
+
+ i=32;
+ dp=filter;
+ vp=calcbuffer[LS][currentcalcbuffer]+calcbufferoffset;
+// actual_v+actual_write_pos;
+
+ switch (calcbufferoffset)
+ {
+ case 0:for(;i;i--,vp+=15){
+ OS;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 1:for(;i;i--,vp+=15){
+ OS;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 2:for(;i;i--,vp+=15){
+ OS;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 3:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 4:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 5:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 6:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 7:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 8:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 9:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 10:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;
+ SAVE;}break;
+ case 11:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;
+ SAVE;}break;
+ case 12:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;
+ SAVE;}break;
+ case 13:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;
+ SAVE;}break;
+ case 14:for(;i;i--,vp+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;
+ SAVE;}break;
+ case 15:for(;i;i--,vp+=31){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ }
+}
+
+#undef OS
+#undef XX
+#undef OP
+#undef SAVE
+
+
+#define SAVE putraw(r1); putraw(r2);
+
+#define OS r1=*vp1 * *dp; \
+ r2=*vp2 * *dp++
+#define XX vp1+=15;r1+=*vp1 * *dp; \
+ vp2+=15;r2+=*vp2 * *dp++
+#define OP r1+=*--vp1 * *dp; \
+ r2+=*--vp2 * *dp++
+
+/*
+inline void Synthesis::generate_old(void)
+{
+ int i;
+ REAL r1,r2;
+ register REAL *vp1,*vp2;
+ register const REAL *dp;
+
+ dp=filter;
+ vp1=calcbuffer[LS][currentcalcbuffer]+calcbufferoffset;
+ vp2=calcbuffer[RS][currentcalcbuffer]+calcbufferoffset;
+// actual_v+actual_write_pos;
+
+ i=32;
+ switch (calcbufferoffset)
+ {
+ case 0:for(;i;i--,vp1+=15,vp2+=15){
+ OS;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 1:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 2:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 3:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 4:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 5:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 6:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 7:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 8:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 9:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ case 10:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;OP;
+ SAVE;}break;
+ case 11:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;OP;
+ SAVE;}break;
+ case 12:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;OP;
+ SAVE;}break;
+ case 13:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;OP;
+ SAVE;}break;
+ case 14:for(;i;i--,vp1+=15,vp2+=15){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;XX;
+ SAVE;}break;
+ case 15:for(;i;i--,vp1+=31,vp2+=31){
+ OS;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;OP;
+ SAVE;}break;
+ }
+}
+*/
+#undef OS
+#undef XX
+#undef OP
+#undef SAVE
+
+#include "op.h"
+#define SAVE putraw(r1); putraw(r2);
+
+inline void Synthesis::generate_Std(void)
+{
+ int i;
+ REAL r1,r2;
+
+ register REAL *vp1;
+ register const REAL *dp;
+
+ dp=filter;
+ vp1=calcbuffer[LS][currentcalcbuffer]+calcbufferoffset;
+ // we calculate cp2 from vp1 because they are both
+ // in the same array. code was:
+ // register REAL* vp2
+ //vp2=calcbuffer[RS][currentcalcbuffer]+calcbufferoffset;
+
+ i=32;
+ switch (calcbufferoffset)
+ {
+ case 0:for(;i;i--,OP_END_1(15,14)){
+ OS;XX1;XX2;OP14;
+ SAVE;}break;
+ case 1:for(;i;i--,OP_END_1(15,13)){
+ OS;OP;OP_END_2(1);XX2;OP13;
+ SAVE;}break;
+ case 2:for(;i;i--,OP_END_1(15,12)){
+ OS;OP2;OP_END_2(2);XX2;OP12;
+ SAVE;}break;
+ case 3:for(;i;i--,OP_END_1(15,11)){
+ OS;OP3;OP_END_2(3);XX2;OP11;
+ SAVE;}break;
+ case 4:for(;i;i--,OP_END_1(15,10)){
+ OS;OP4;OP_END_2(4);XX2;OP10;
+ SAVE;}break;
+ case 5:for(;i;i--,OP_END_1(15,9)){
+ OS;OP5;OP_END_2(5);XX2;OP9;
+ SAVE;}break;
+ case 6:for(;i;i--,OP_END_1(15,8)){
+ OS;OP6;OP_END_2(6);XX2;OP8;
+ SAVE;}break;
+ case 7:for(;i;i--,OP_END_1(15,7)){
+ OS;OP7;OP_END_2(7);XX2;OP7;
+ SAVE;}break;
+ case 8:for(;i;i--,OP_END_1(15,6)){
+ OS;OP8;OP_END_2(8);XX2;OP6;
+ SAVE;}break;
+ case 9:for(;i;i--,OP_END_1(15,5)){
+ OS;OP9;OP_END_2(9);XX2;OP5;
+ SAVE;}break;
+ case 10:for(;i;i--,OP_END_1(15,4)){
+ OS;OP10;OP_END_2(10);XX2;OP4;
+ SAVE;}break;
+ case 11:for(;i;i--,OP_END_1(15,3)){
+ OS;OP11;OP_END_2(11);XX2;OP3;
+ SAVE;}break;
+ case 12:for(;i;i--,OP_END_1(15,2)){
+ OS;OP12;OP_END_2(12);XX2;OP2;
+ SAVE;}break;
+ case 13:for(;i;i--,OP_END_1(15,1)){
+ OS;OP13;OP_END_2(13);XX2;OP;
+ SAVE;}break;
+ case 14:for(;i;i--,vp1+=15){
+ OS;OP14;OP_END_2(14);XX2;
+ SAVE;}break;
+ case 15:for(;i;i--,OP_END_1(31,15)){
+ OS;OP15;
+ SAVE;}break;
+ }
+}
+#undef OP_END_1
+#undef OP_END_2
+#undef OP
+#undef OP1
+#undef OP2
+#undef OP3
+#undef OP4
+#undef OP5
+#undef OP6
+#undef OP7
+#undef OP8
+#undef OP9
+#undef OP10
+#undef OP11
+#undef OP12
+#undef OP13
+#undef OP14
+#undef OP15
+#undef OS
+#undef XX1
+#undef XX2
+#undef SCHEDULE
+#undef SCHEDULE1
+#undef SCHEDULE2
+#undef SAVE
+
+void Synthesis::synth_Std(int lOutputStereo,REAL *fractionL,REAL *fractionR) {
+ switch(lOutputStereo) {
+ case true:
+ computebuffer_Std(fractionL,calcbuffer[LS]);
+ computebuffer_Std(fractionR,calcbuffer[RS]);
+ generate_Std();
+ nextOffset();
+ break;
+ case false:
+ computebuffer_Std(fractionL,calcbuffer[LS]);
+ generatesingle_Std();
+ nextOffset();
+ break;
+ default:
+ cout << "unknown lOutputStereo in Synthesis::synth_Std"<<endl;
+ exit(0);
+ }
+}
+
+
+void Synthesis::synthMP3_Std(int lOutputStereo,
+ REAL hout [2][SSLIMIT][SBLIMIT]) {
+ int ss;
+ switch(lOutputStereo) {
+ case true:
+ for(ss=0;ss<SSLIMIT;ss++) {
+ computebuffer_Std(hout[LS][ss],calcbuffer[LS]);
+ computebuffer_Std(hout[RS][ss],calcbuffer[RS]);
+ generate_Std();
+ nextOffset();
+ }
+ break;
+ case false:
+ for(ss=0;ss<SSLIMIT;ss++) {
+ computebuffer_Std(hout[LS][ss],calcbuffer[LS]);
+ generatesingle_Std();
+ nextOffset();
+ }
+ break;
+ default:
+ cout << "unknown lOutputStereo in Synthesis::synth_Std"<<endl;
+ exit(0);
+ }
+}
diff --git a/mpeglib/lib/splay/synth_filter.cpp b/mpeglib/lib/splay/synth_filter.cpp
new file mode 100644
index 00000000..47455288
--- /dev/null
+++ b/mpeglib/lib/splay/synth_filter.cpp
@@ -0,0 +1,147 @@
+/*
+ filer definition
+ 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 "synthesis.h"
+
+
+ATTR_ALIGN(64) const REAL Synthesis::filter[512]=
+{
+ 0.000000000, -0.000442505, 0.003250122, -0.007003784,
+ 0.031082153, -0.078628540, 0.100311279, -0.572036743,
+ 1.144989014, 0.572036743, 0.100311279, 0.078628540,
+ 0.031082153, 0.007003784, 0.003250122, 0.000442505,
+ -0.000015259, -0.000473022, 0.003326416, -0.007919312,
+ 0.030517578, -0.084182739, 0.090927124, -0.600219727,
+ 1.144287109, 0.543823242, 0.108856201, 0.073059082,
+ 0.031478882, 0.006118774, 0.003173828, 0.000396729,
+ -0.000015259, -0.000534058, 0.003387451, -0.008865356,
+ 0.029785156, -0.089706421, 0.080688477, -0.628295898,
+ 1.142211914, 0.515609741, 0.116577148, 0.067520142,
+ 0.031738281, 0.005294800, 0.003082275, 0.000366211,
+ -0.000015259, -0.000579834, 0.003433228, -0.009841919,
+ 0.028884888, -0.095169067, 0.069595337, -0.656219482,
+ 1.138763428, 0.487472534, 0.123474121, 0.061996460,
+ 0.031845093, 0.004486084, 0.002990723, 0.000320435,
+ -0.000015259, -0.000625610, 0.003463745, -0.010848999,
+ 0.027801514, -0.100540161, 0.057617188, -0.683914185,
+ 1.133926392, 0.459472656, 0.129577637, 0.056533813,
+ 0.031814575, 0.003723145, 0.002899170, 0.000289917,
+ -0.000015259, -0.000686646, 0.003479004, -0.011886597,
+ 0.026535034, -0.105819702, 0.044784546, -0.711318970,
+ 1.127746582, 0.431655884, 0.134887695, 0.051132202,
+ 0.031661987, 0.003005981, 0.002792358, 0.000259399,
+ -0.000015259, -0.000747681, 0.003479004, -0.012939453,
+ 0.025085449, -0.110946655, 0.031082153, -0.738372803,
+ 1.120223999, 0.404083252, 0.139450073, 0.045837402,
+ 0.031387329, 0.002334595, 0.002685547, 0.000244141,
+ -0.000030518, -0.000808716, 0.003463745, -0.014022827,
+ 0.023422241, -0.115921021, 0.016510010, -0.765029907,
+ 1.111373901, 0.376800537, 0.143264771, 0.040634155,
+ 0.031005859, 0.001693726, 0.002578735, 0.000213623,
+ -0.000030518, -0.000885010, 0.003417969, -0.015121460,
+ 0.021575928, -0.120697021, 0.001068115, -0.791213989,
+ 1.101211548, 0.349868774, 0.146362305, 0.035552979,
+ 0.030532837, 0.001098633, 0.002456665, 0.000198364,
+ -0.000030518, -0.000961304, 0.003372192, -0.016235352,
+ 0.019531250, -0.125259399, -0.015228271, -0.816864014,
+ 1.089782715, 0.323318481, 0.148773193, 0.030609131,
+ 0.029937744, 0.000549316, 0.002349854, 0.000167847,
+ -0.000030518, -0.001037598, 0.003280640, -0.017349243,
+ 0.017257690, -0.129562378, -0.032379150, -0.841949463,
+ 1.077117920, 0.297210693, 0.150497437, 0.025817871,
+ 0.029281616, 0.000030518, 0.002243042, 0.000152588,
+ -0.000045776, -0.001113892, 0.003173828, -0.018463135,
+ 0.014801025, -0.133590698, -0.050354004, -0.866363525,
+ 1.063217163, 0.271591187, 0.151596069, 0.021179199,
+ 0.028533936, -0.000442505, 0.002120972, 0.000137329,
+ -0.000045776, -0.001205444, 0.003051758, -0.019577026,
+ 0.012115479, -0.137298584, -0.069168091, -0.890090942,
+ 1.048156738, 0.246505737, 0.152069092, 0.016708374,
+ 0.027725220, -0.000869751, 0.002014160, 0.000122070,
+ -0.000061035, -0.001296997, 0.002883911, -0.020690918,
+ 0.009231567, -0.140670776, -0.088775635, -0.913055420,
+ 1.031936646, 0.221984863, 0.151962280, 0.012420654,
+ 0.026840210, -0.001266479, 0.001907349, 0.000106812,
+ -0.000061035, -0.001388550, 0.002700806, -0.021789551,
+ 0.006134033, -0.143676758, -0.109161377, -0.935195923,
+ 1.014617920, 0.198059082, 0.151306152, 0.008316040,
+ 0.025909424, -0.001617432, 0.001785278, 0.000106812,
+ -0.000076294, -0.001480103, 0.002487183, -0.022857666,
+ 0.002822876, -0.146255493, -0.130310059, -0.956481934,
+ 0.996246338, 0.174789429, 0.150115967, 0.004394531,
+ 0.024932861, -0.001937866, 0.001693726, 0.000091553,
+ -0.000076294, -0.001586914, 0.002227783, -0.023910522,
+ -0.000686646, -0.148422241, -0.152206421, -0.976852417,
+ 0.976852417, 0.152206421, 0.148422241, 0.000686646,
+ 0.023910522, -0.002227783, 0.001586914, 0.000076294,
+ -0.000091553, -0.001693726, 0.001937866, -0.024932861,
+ -0.004394531, -0.150115967, -0.174789429, -0.996246338,
+ 0.956481934, 0.130310059, 0.146255493, -0.002822876,
+ 0.022857666, -0.002487183, 0.001480103, 0.000076294,
+ -0.000106812, -0.001785278, 0.001617432, -0.025909424,
+ -0.008316040, -0.151306152, -0.198059082, -1.014617920,
+ 0.935195923, 0.109161377, 0.143676758, -0.006134033,
+ 0.021789551, -0.002700806, 0.001388550, 0.000061035,
+ -0.000106812, -0.001907349, 0.001266479, -0.026840210,
+ -0.012420654, -0.151962280, -0.221984863, -1.031936646,
+ 0.913055420, 0.088775635, 0.140670776, -0.009231567,
+ 0.020690918, -0.002883911, 0.001296997, 0.000061035,
+ -0.000122070, -0.002014160, 0.000869751, -0.027725220,
+ -0.016708374, -0.152069092, -0.246505737, -1.048156738,
+ 0.890090942, 0.069168091, 0.137298584, -0.012115479,
+ 0.019577026, -0.003051758, 0.001205444, 0.000045776,
+ -0.000137329, -0.002120972, 0.000442505, -0.028533936,
+ -0.021179199, -0.151596069, -0.271591187, -1.063217163,
+ 0.866363525, 0.050354004, 0.133590698, -0.014801025,
+ 0.018463135, -0.003173828, 0.001113892, 0.000045776,
+ -0.000152588, -0.002243042, -0.000030518, -0.029281616,
+ -0.025817871, -0.150497437, -0.297210693, -1.077117920,
+ 0.841949463, 0.032379150, 0.129562378, -0.017257690,
+ 0.017349243, -0.003280640, 0.001037598, 0.000030518,
+ -0.000167847, -0.002349854, -0.000549316, -0.029937744,
+ -0.030609131, -0.148773193, -0.323318481, -1.089782715,
+ 0.816864014, 0.015228271, 0.125259399, -0.019531250,
+ 0.016235352, -0.003372192, 0.000961304, 0.000030518,
+ -0.000198364, -0.002456665, -0.001098633, -0.030532837,
+ -0.035552979, -0.146362305, -0.349868774, -1.101211548,
+ 0.791213989, -0.001068115, 0.120697021, -0.021575928,
+ 0.015121460, -0.003417969, 0.000885010, 0.000030518,
+ -0.000213623, -0.002578735, -0.001693726, -0.031005859,
+ -0.040634155, -0.143264771, -0.376800537, -1.111373901,
+ 0.765029907, -0.016510010, 0.115921021, -0.023422241,
+ 0.014022827, -0.003463745, 0.000808716, 0.000030518,
+ -0.000244141, -0.002685547, -0.002334595, -0.031387329,
+ -0.045837402, -0.139450073, -0.404083252, -1.120223999,
+ 0.738372803, -0.031082153, 0.110946655, -0.025085449,
+ 0.012939453, -0.003479004, 0.000747681, 0.000015259,
+ -0.000259399, -0.002792358, -0.003005981, -0.031661987,
+ -0.051132202, -0.134887695, -0.431655884, -1.127746582,
+ 0.711318970, -0.044784546, 0.105819702, -0.026535034,
+ 0.011886597, -0.003479004, 0.000686646, 0.000015259,
+ -0.000289917, -0.002899170, -0.003723145, -0.031814575,
+ -0.056533813, -0.129577637, -0.459472656, -1.133926392,
+ 0.683914185, -0.057617188, 0.100540161, -0.027801514,
+ 0.010848999, -0.003463745, 0.000625610, 0.000015259,
+ -0.000320435, -0.002990723, -0.004486084, -0.031845093,
+ -0.061996460, -0.123474121, -0.487472534, -1.138763428,
+ 0.656219482, -0.069595337, 0.095169067, -0.028884888,
+ 0.009841919, -0.003433228, 0.000579834, 0.000015259,
+ -0.000366211, -0.003082275, -0.005294800, -0.031738281,
+ -0.067520142, -0.116577148, -0.515609741, -1.142211914,
+ 0.628295898, -0.080688477, 0.089706421, -0.029785156,
+ 0.008865356, -0.003387451, 0.000534058, 0.000015259,
+ -0.000396729, -0.003173828, -0.006118774, -0.031478882,
+ -0.073059082, -0.108856201, -0.543823242, -1.144287109,
+ 0.600219727, -0.090927124, 0.084182739, -0.030517578,
+ 0.007919312, -0.003326416, 0.000473022, 0.000015259
+};
diff --git a/mpeglib/lib/splay/synthesis.cpp b/mpeglib/lib/splay/synthesis.cpp
new file mode 100644
index 00000000..699037c9
--- /dev/null
+++ b/mpeglib/lib/splay/synthesis.cpp
@@ -0,0 +1,73 @@
+/*
+ header for synthesis
+ 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 "synthesis.h"
+
+
+#include <iostream>
+
+using namespace std;
+
+Synthesis::Synthesis() {
+
+ int i;
+ outpos=0;
+ calcbufferoffset=15;
+ currentcalcbuffer=0;
+
+ for(i=CALCBUFFERSIZE-1;i>=0;i--)
+ calcbuffer[LS][0][i]=calcbuffer[LS][1][i]=
+ calcbuffer[RS][0][i]=calcbuffer[RS][1][i]=0.0;
+
+ initialize_dct64();
+ initialize_dct64_downsample();
+}
+
+
+Synthesis::~Synthesis() {
+}
+
+
+void Synthesis::doSynth(int lDownSample,int lOutputStereo,
+ REAL *fractionL,REAL *fractionR) {
+ switch(lDownSample) {
+ case false:
+ synth_Std(lOutputStereo,fractionL,fractionR);
+ break;
+ case true:
+ synth_Down(lOutputStereo,fractionL,fractionR);
+ break;
+ default:
+ cout << "unknown downsample parameter"<<lDownSample<<endl;
+ exit(0);
+ }
+}
+
+
+void Synthesis::doMP3Synth(int lDownSample,int lOutputStereo,
+ REAL in[2][SSLIMIT][SBLIMIT]) {
+
+ switch(lDownSample) {
+ case false:
+ synthMP3_Std(lOutputStereo,in);
+ break;
+ case true:
+ synthMP3_Down(lOutputStereo,in);
+ break;
+ default:
+ cout << "unknown downsample parameter:"<<lDownSample<<endl;
+ exit(0);
+ }
+}
+
+
diff --git a/mpeglib/lib/splay/synthesis.h b/mpeglib/lib/splay/synthesis.h
new file mode 100644
index 00000000..801d658e
--- /dev/null
+++ b/mpeglib/lib/splay/synthesis.h
@@ -0,0 +1,95 @@
+/*
+ header for synthesis
+ 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 __SYNTHESIS_H
+#define __SYNTHESIS_H
+
+#include "common.h"
+#include "dct.h"
+
+#define CALCBUFFERSIZE 512
+// AIX seems to have FRAMESIZE defined
+#undef FRAMESIZE
+
+#define FRAMESIZE (2*2*2*32*18)
+
+
+class Synthesis {
+
+ //
+ // Subbandsynthesis two calcbuffers for every channel, and two channels.
+ // calcbufferL[0]=calcbuffer[0]
+ // calcbufferL[1]=calcbuffer[1]
+ // calcbufferR[0]=calcbuffer[2]
+ // calcbufferR[1]=calcbuffer[3]
+ ATTR_ALIGN(64) REAL calcbuffer[2][2][CALCBUFFERSIZE];
+ ATTR_ALIGN(64) int currentcalcbuffer,calcbufferoffset;
+ static ATTR_ALIGN(64) const REAL filter[512];
+ ATTR_ALIGN(64) REAL out[FRAMESIZE];
+ int outpos;
+
+ public:
+ Synthesis();
+ ~Synthesis();
+
+ // mpeg1,2
+ void doSynth(int lDownSample,int lOutputStereo,
+ REAL *fractionL,REAL *fractionR);
+
+ void doMP3Synth(int lDownSample,int lOutputStereo,
+ REAL in[2][SSLIMIT][SBLIMIT]);
+
+ // put mpeg to raw
+ inline void putraw(REAL val) {
+ out[outpos++]=val;
+ }
+
+ inline REAL* getOutputData() { return out; }
+ inline void clearrawdata() { outpos=0; }
+ inline int getLen() { return outpos; }
+
+
+ private:
+ void synth_Down(int lOutputStereo,REAL *fractionL,REAL *fractionR);
+ void synth_Std(int lOutputStereo,REAL *fractionL,REAL *fractionR);
+
+ void synthMP3_Down(int lOutputStereo,REAL hout [2][SSLIMIT][SBLIMIT]);
+ void synthMP3_Std(int lOutputStereo,REAL hout [2][SSLIMIT][SBLIMIT]);
+
+ inline void nextOffset() {
+ calcbufferoffset++;
+ calcbufferoffset&=0xf;
+ /*
+ if (calcbufferoffset<15) {
+ calcbufferoffset++;
+ } else {
+ calcbufferoffset=0;
+ }
+ */
+ currentcalcbuffer^=1;
+ }
+
+
+ void computebuffer_Std(REAL *fraction,REAL buffer[2][CALCBUFFERSIZE]);
+ void generate_Std(void);
+ void generatesingle_Std(void);
+
+ void computebuffer_Down(REAL *fraction,REAL buffer[2][CALCBUFFERSIZE]);
+ void generate_Down(void);
+ void generatesingle_Down(void);
+
+
+};
+
+#endif
diff --git a/mpeglib/lib/splay/window.cpp b/mpeglib/lib/splay/window.cpp
new file mode 100644
index 00000000..b95dbdcf
--- /dev/null
+++ b/mpeglib/lib/splay/window.cpp
@@ -0,0 +1,70 @@
+/*
+ wrapper for window functions
+ 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 "mpegsound.h"
+
+
+static int windowInit=0;
+
+ATTR_ALIGN(64) REAL win[4][36];
+ATTR_ALIGN(64) REAL winINV[4][36];
+
+
+void initialize_win() {
+ if (windowInit==true) {
+ return;
+ }
+ windowInit=true;
+
+ int i;
+
+ for(i=0;i<18;i++) {
+ /*
+ win[0][i]=win[1][i]=0.5*sin(PI_72*(double)(2*i+1))/
+ cos(PI_72*(double)(2*i+19));
+ */
+ win[0][i]=win[1][i]=0.5*sin(PI_72*(double)(2*(i+0)+1))/cos(MY_PI * (double) (2*(i+0) +19) / 72.0 );
+ win[0][i+18] = win[3][i+18] = 0.5 * sin( MY_PI / 72.0 * (double) (2*(i+18)+1) ) / cos ( MY_PI * (double) (2*(i+18)+19) / 72.0 );
+ }
+ /*
+ for(;i<36;i++) {
+ win[0][i]=win[3][i]=0.5*sin(PI_72*(double)(2*i+1))/cos(PI_72*(double)(2*i+19));
+
+ }
+ */
+ for(i=0;i<6;i++) {
+ win[1][i+18]=0.5/cos(MY_PI*(double)(2*(i+18)+19)/72.0);
+ win[3][i+12]=0.5/cos(MY_PI*(double)(2*(i+12)+19)/72.0);
+ win[1][i+24]=0.5*sin(PI_24*(double)(2*i+13))/cos(MY_PI*(double)(2*(i+24)+19)/72.0);
+ win[1][i+30]=win[3][i]=0.0;
+ win[3][i+6 ]=0.5*sin(PI_24*(double)(2*i+1))/cos(MY_PI*(double)(2*(i+6)+19)/72.0);
+ }
+ for(i=0;i<12;i++)
+ win[2][i]=0.5*sin(PI_24*(double)(2*i+1))/cos(MY_PI*(double)(2*i+7)/24.0);
+
+ int j;
+
+ for(j=0;j<4;j++) {
+ int len[4] = { 36,36,12,36 };
+ for(i=0;i<len[j];i+=2)
+ winINV[j][i] = + win[j][i];
+ for(i=1;i<len[j];i+=2)
+ winINV[j][i] = - win[j][i];
+ }
+
+
+}
+
+
+inline REAL* getSplayWindow(int nr) { return win[nr]; }
+inline REAL* getSplayWindowINV(int nr) { return winINV[nr]; }
diff --git a/mpeglib/lib/tplay/CHANGES b/mpeglib/lib/tplay/CHANGES
new file mode 100644
index 00000000..aad2446d
--- /dev/null
+++ b/mpeglib/lib/tplay/CHANGES
@@ -0,0 +1,154 @@
+Version 0.1, 2.4.1997:
+
+ - the first released version
+
+5.4.1997:
+
+ - audio sync added before changing parameters
+
+Version 0.2, 9.4.1997:
+
+ - it was useless to start producer as a thread;
+ it was made that way just for historical reasons.
+ only consumer is threaded now. this may result
+ as more robust behaviour.
+
+ - there are min and max sizes for block now. i'm
+ not sure yet what size for a block and the audio
+ buffer would be good. needs more research.
+
+ - fill_buffer function. fills the audio buffer
+ before use.
+
+Version 0.2.1, 15.4.1997:
+
+ - signal() seems to be a bad idea in a threaded
+ application like this. causes kernel oops in
+ the sound driver function audio_write (sometimes).
+ let's have faith on the kernel and remove it.
+
+Version 0.2.2, 17.4.1997 morning:
+
+ - the last block was written from very wrong point.
+
+ - block counting added. this makes stream ending
+ simpler and (hopefully) more robust.
+
+ - first lines for handling underflow (buffer empty)
+ situation.
+
+Version 0.3, 17.4.1997 afternoon:
+
+ - underflow handling should work now.
+
+ - function buffer_usage added. returns buffer usage
+ in percents. nowhere used yet.
+
+ - minimum block size increased to 16k.
+
+Version 0.3.1, 19.4.1997:
+
+ - GNU style options.
+
+ - option -v (or --version) added.
+
+ - buffer usage option -u (or --usage) added.
+
+Version 0.4, 2.5.1997:
+
+ - support for RIFF/WAVE (WAV) and Sun audio
+ (AU) files.
+
+ - swap endianness flag -x (or --swap) added.
+
+ - verbose mode flag -V (or --verbose) added.
+
+ - force raw flag -r (or --raw) added. WAV- or
+ AU-file headers are ignored if this flag is set.
+
+Version 0.4.1, 3.5.1997:
+
+ - sun header gives odd aligned starting point
+ for sample. temporary fix.
+
+ - read_big_endian_long returned wrong value if
+ sampling rate was 44100. this caused tplay
+ not to work with that speed when playing sun
+ audio or wav file. fixed now.
+
+Version 0.4.2, 7.5.1997:
+
+ - read_big_endian_long and similar functions:
+ parameter's type was char* and that was a bug.
+ changed to byte* (unsigned char *). conversion
+ should also be saner now.
+
+ - force playing -f (or --force) flag added. this
+ makes tplay to ignore sound driver's results
+ when changing parameters.
+
+Version 0.4.3, 12.5.1997:
+
+ - binary is statically linked to LinuxThreads
+ version 0.6 now.
+
+ - print sun header comment if verbose is requested.
+
+ - sun audio file's data stream starting pointer
+ is read and set from the header.
+
+ - to avoid rounding errors when playing 16bit
+ and/or stereo (au or wav) sample, data section
+ is moved now to the beginning of buffer before
+ playing.
+
+Version 0.5, 23.10.1997:
+
+ - set_audio_parameters() partly rewritten and
+ changes to open_audio().
+
+ - in some WAV-files, data-portion is not started
+ with 'data'-magic but 'INFO' instead. some
+ players don't even check that so tplay prints
+ just a warning message now if neither of these
+ magics exists.
+
+Version 0.5.1, 25.10.1997:
+
+ - printing of buffer usage changed from producer
+ to consumer. this makes this silly feature a bit
+ more informative as it is still active after the
+ producer has stopped. underflow situation (when
+ the big buffer needs to be refilled) is also
+ possible to show now.
+
+Version 0.5.2, 9.5.1998:
+
+ - Jerko Golubovic <jerko.golubovic@public.srce.hr>
+ kindly modified the code to support those soundcards
+ that may result slightly different sampling rate
+ than requested. he also provided RPM of tplay.
+
+ - added -D (or --device=DEVICE) flag for setting
+ audio device to be used.
+
+ - added feature to -B (or --buffer-size=SIZE) flag.
+ buffer size can be given in seconds now, too.
+
+Version 0.5.3, 11.5.1998:
+
+ - rewrite of playing routine to support multiple
+ sound samples from command line.
+
+Version 0.5.4, 19.5.1998:
+
+ - added -l (or --loop) flag to support looping sound
+ samples.
+
+ - sun port.
+
+Version 0.5.5, 24.5.1998:
+
+ - added environment variable TPLAYDEV, which sets the
+ audio device to be used. decoding of command line
+ options is moved from main() to another function.
diff --git a/mpeglib/lib/tplay/Makefile.am b/mpeglib/lib/tplay/Makefile.am
new file mode 100644
index 00000000..c83b25ea
--- /dev/null
+++ b/mpeglib/lib/tplay/Makefile.am
@@ -0,0 +1,15 @@
+# libtplay - Makefile.am
+
+
+EXTRA_DIST = CHANGES README
+
+INCLUDES = $(all_includes)
+
+
+noinst_LTLIBRARIES = libtplay.la
+
+noinst_HEADERS = tplayfunctions.h
+
+libtplay_la_SOURCES = au.cpp \
+ tplayfunctions.cpp wav.cpp
+
diff --git a/mpeglib/lib/tplay/README b/mpeglib/lib/tplay/README
new file mode 100644
index 00000000..275d6a9f
--- /dev/null
+++ b/mpeglib/lib/tplay/README
@@ -0,0 +1,95 @@
+This is a buffered audio player for Linux. POSIX-thread library is
+used. This is still considered BETA software and may not work as
+expected. Please mail me for bug reports, opinions or suggestions.
+
+This is primarily made for use with MPEG-decoders. They typically
+consume lots of CPU-time and some kind of audio buffer is needed to
+reduce cutting while writing to audio device. You can also play any
+audio files with tplay or use it with any program that writes audio
+data to standard out.
+
+RIFF/WAVE (WAV) and Sun audio (AU) file headers are recognized by
+now.
+
+Binary:
+
+In the source tree there is a readily compiled binary that is build
+under Linux/ELF 2.0.30 with libc 5.4.20 and LinuxThreads 0.6 (the
+thread library is statically linked).
+
+Command line options:
+
+ tplay [-hvVmuxrf] [-s Hz] [-b 8|16] [-B kilobytes] [filename]
+
+ -h, --help Print help, then exit
+ -v, --version Print version, then exit
+ -V, --verbose Print useful information about the sample
+ -x, --swap Swap endianness
+ -r, --raw Force raw audio format. Ignore headers.
+ -f, --force Force playing with any parameters
+ -m, --mono Mono sample
+ -u, --usage Print buffer usage while playing
+ -s, --speed=SPEED Sample speed (Hz)
+ -b, --bytes=BYTES Bytes in a sample
+ -B, --buffer-size=SIZE Buffer size in (kB)
+
+Buffer size is defaulted to 512k. It is about 3 seconds CD audio
+(44100Hz/sample, 16bytes, stereo). If filename is not given, standard
+input is used. If -x (or --swap) flag is set, the byte order of
+audio sample is swapped before playing. The default is Intel little-
+endian which is mostly used in x86 machines. The world outside Intel
+is big-endian.
+Option -r (or --raw) forces tplay to handle the sample as an raw
+PCM audio sample. Sun audio or WAV headers are ignored.
+
+Requirements:
+
+ - Linux 2.0 or newer with audio card support
+ - POSIX thread library
+ - Audio card
+
+There are several POSIX thread libraries available. I used
+LinuxThreads by Xavier Leroy (Xavier.Leroy@inria.fr). LinuxThreads
+library use clone() that is provided by Linux 2.0 kernel.
+
+The code:
+
+tplay starts one thread, named consumer, that reads circular audio
+buffer and writes it to audio device. The producer is a function that
+runs in parallel with the consumer and its task is to read the sample
+file or standard input and write this data to audio buffer to meet
+consumer's needs. Usually, the buffer is full but on the times when
+CPU-time is suddenly needed for other processes (usually: disk
+read/write), the producer can't write fast enough and consumer can use
+the buffer to keep audio stream uninterrupted. If the buffer is used
+and the producer is still unable to feed it fast enough, underflow
+situation is met and consumer waits for awhile (typically: one second)
+for the producer to fill the buffer again.
+
+Building:
+
+If you want to link tplay with static libpthread library, edit
+Makefile and uncomment preferred LIBS-setting there. Type:
+
+ - make
+ - make install
+ - make install.man
+
+Thanks:
+
+Jerko Golubovic <jerko.golubovic@public.srce.hr>
+Jukka Palviainen <oh3kjt@ele.tut.fi>
+
+TODO:
+
+Find out the best sizes for the audio buffer and one block.
+Better documentation.
+Better RIFF/WAVE checking.
+
+Ilkka Karvinen
+ik@iki.fi
+
+
+
+
+
diff --git a/mpeglib/lib/tplay/au.cpp b/mpeglib/lib/tplay/au.cpp
new file mode 100644
index 00000000..8880515f
--- /dev/null
+++ b/mpeglib/lib/tplay/au.cpp
@@ -0,0 +1,100 @@
+/*
+ * tplay - buffered audio player
+ *
+ * (c) 1997 ilkka karvinen <ik@iki.fi>
+ *
+ * Copyright under the GNU GENERAL PUBLIC LICENSE
+ * (see the file COPYING in this directory)
+ *
+ *
+ * SunOS audio file header functions.
+ * Reference: http://www.wotsit.org
+ */
+
+#include "tplayfunctions.h"
+
+/* read_au returns zero if Sun audio file format is found. */
+int read_au(struct info_struct* info,char * buffer) {
+ DWORD magic, start, end, encoding, speed, channels;
+ int bits;
+
+
+ /* If '.snd'-header exits, this should be an au-file */
+ magic = read_big_endian_long(buffer);
+ if (magic != SUN_MAGIC)
+ return (1);
+
+ start = read_big_endian_long(buffer + 0x04);
+ end = read_big_endian_long(buffer + 0x08);
+ encoding = read_big_endian_long(buffer + 0x0C);
+ speed = read_big_endian_long(buffer + 0x10);
+ channels = read_big_endian_long(buffer + 0x14);
+
+#ifdef DEBUG
+ printf("Sun audio file.\nspeed: %ld, start: %ld, end: %ld, \
+encoding: %X, channels: %ld\n",
+ speed, start, end, encoding, channels);
+ fflush(stdout);
+#endif
+
+ bits = DEFAULT_BITS;
+ switch (encoding) {
+ case 1:
+ die("8-bit ISDN u-law Sun audio file not supported");
+ break;
+ case 2:
+ bits = 8;
+ break;
+ case 3:
+ bits = 16;
+ break;
+ case 4:
+ die("24-bit linear PCM Sun audio file not supported");
+ break;
+ case 5:
+ die("32-bit linear PCM Sun audio file not supported");
+ break;
+ case 6:
+ die("32-bit IEEE floating point Sun audio file not supported");
+ break;
+ case 7:
+ die("64-bit IEEE floating point Sun audio file not supported");
+ break;
+ case 23:
+ die("8-bit ISDN u-law compressed(G.721 ADPCM) Sun audio file \
+not supported");
+ break;
+ default:
+ errdie("Unknown Sun audio file");
+ break;
+ }
+
+ info->filetype = SUN_FILE;
+
+ /* Set audio parameters */
+ info->speed = (int) speed;
+ info->bits = bits;
+ info->channels = (int) channels;
+
+ if (info->verbose) {
+ printf("Sun audio file: %ld samples/s, %d bits, %d channel(s).\n",
+ info->speed, info->bits, info->channels);
+ /*
+ if ((comment_size = start - SUN_HDRSIZE) > 0) {
+ printf("Header info: ");
+ for (i = 0; i < comment_size; i++)
+ nice_fputc((int) buffer[SUN_HDRSIZE + i], stdout);
+ printf("\n");
+ }
+ */
+ }
+
+ /* Move data to start from the beginning of the buffer. */
+ /* This is to ensure the correct behaviour of rounding when 16bits */
+ /* and/or stereo sample is to be played. */
+ memmove(buffer, buffer + (start + 1), info->blocksize - start - 1);
+
+ info->headerskip = (int) (start + 1);
+
+ return (0);
+}
diff --git a/mpeglib/lib/tplay/tplayfunctions.cpp b/mpeglib/lib/tplay/tplayfunctions.cpp
new file mode 100644
index 00000000..c105f4a2
--- /dev/null
+++ b/mpeglib/lib/tplay/tplayfunctions.cpp
@@ -0,0 +1,84 @@
+/*
+ * tplay - buffered audio player
+ *
+ * (c) 1997 ilkka karvinen <ik@iki.fi>
+ *
+ * Copyright under the GNU GENERAL PUBLIC LICENSE
+ * (see the file COPYING in this directory)
+ *
+ *
+ * common functions
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "tplayfunctions.h"
+
+DWORD read_big_endian_long(char * buf)
+{
+ DWORD byte0, byte1, byte2, byte3;
+ unsigned char* buffer=(unsigned char*) buf;
+
+ byte0 = (DWORD) buffer[0];
+ byte1 = (DWORD) buffer[1];
+ byte2 = (DWORD) buffer[2];
+ byte3 = (DWORD) buffer[3];
+ return (byte0 << 24 | byte1 << 16 | byte2 << 8 | byte3);
+}
+
+void write_big_endian_long(char * buf, DWORD value)
+{
+ unsigned char* buffer=(unsigned char*) buf;
+ buffer[0] = (unsigned char) (value >> 24 & 0xFF);
+ buffer[1] = (unsigned char) (value >> 16 & 0xFF);
+ buffer[2] = (unsigned char) (value >> 8 & 0xFF);
+ buffer[3] = (unsigned char) (value & 0xFF);
+}
+
+DWORD read_little_endian_long(char* buf) {
+ DWORD byte0, byte1, byte2, byte3;
+ unsigned char* buffer=(unsigned char*) buf;
+
+ byte0 = (DWORD) buffer[0];
+ byte1 = (DWORD) buffer[1];
+ byte2 = (DWORD) buffer[2];
+ byte3 = (DWORD) buffer[3];
+ return (byte3 << 24 | byte2 << 16 | byte1 << 8 | byte0);
+}
+
+WORD read_little_endian_word(char * buf)
+{
+ WORD byte0, byte1;
+ unsigned char* buffer=(unsigned char*) buf;
+
+ byte0 = (WORD) buffer[0];
+ byte1 = (WORD) buffer[1];
+ return (byte1 << 8 | byte0);
+}
+
+void errprintf(char *fmt,...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+}
+
+
+
+void die(const char *str)
+{
+ fprintf(stderr, "%s: \n", str);
+ exit(-1);
+}
+
+void errdie(const char *str)
+{
+ fprintf(stderr, "Error: %s\n", str);
+ exit(-1);
+}
+
+
+
diff --git a/mpeglib/lib/tplay/tplayfunctions.h b/mpeglib/lib/tplay/tplayfunctions.h
new file mode 100644
index 00000000..0c159847
--- /dev/null
+++ b/mpeglib/lib/tplay/tplayfunctions.h
@@ -0,0 +1,128 @@
+/*
+ * tplay - buffered audio player header file
+ *
+ * (c) 1997 ilkka karvinen <ik@iki.fi>
+ *
+ * Copyright under the GNU GENERAL PUBLIC LICENSE
+ * (see the file COPYING in this directory)
+ *
+ */
+
+#ifndef __TPLAYCONTROL_H
+#define __TPLAYCONTROL_H
+
+extern "C" {
+#include <stdio.h>
+#include <string.h>
+}
+
+/* tplay version */
+#define MAJOR_VERSION 0
+#define MINOR_VERSION 5
+#define PATCHLEVEL 5
+
+/* Default audio parameters */
+#define DEFAULT_BITS 16
+#define DEFAULT_SPEED 44100
+#define DEFAULT_CHANNELS 2
+
+/* Audio memory pool. 512k is the default. */
+#define BUFFER_SIZE 0x80000
+
+/* The minimum and maximum buffer block sizes. */
+#if 0
+#define MIN_BLOCK_SIZE 0x4000 /* 16k */
+#else
+#define MIN_BLOCK_SIZE 4096
+#endif
+#define MAX_BLOCK_SIZE 0x10000 /* 64k */
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+/* The maximum retry count for buffer fill tries. */
+#define RETRY_COUNT 5
+
+/* Magics. Little-endian. */
+#define RIFF_MAGIC 0x46464952 /* ASCII: 'RIFF' */
+#define WAVE_MAGIC 0x45564157 /* ASCII: 'WAVE' */
+#define DATA_MAGIC 0x61746164 /* ASCII: 'data' */
+#define INFO_MAGIC 0x4f464e49 /* ASCII: 'INFO' */
+#define SUN_MAGIC 0x2e736e64 /* ASCII: '.snd' */
+
+/* Magics. Big-endian. */
+#define SUN_INV_MAGIC 0x646e732e /* ASCII: '.snd' */
+
+/* Sun headersize */
+#define SUN_HDRSIZE 24
+
+/* File types */
+#define UNKNOWN_FILE 0
+#define RIFF_FILE 1
+#define SUN_FILE 2
+
+typedef unsigned long DWORD;
+typedef unsigned short WORD;
+
+/* Circular buffer info structure of audio data blocks. */
+/* declared in tplay.c */
+struct info_struct {
+ char *buffer; /* the audio data */
+ char *firstblock; /* pointer to the first block */
+ int readblock, writeblock; /* reading and writing block number */
+ long readcount, writecount;
+ int alldone;
+ int in_seconds;
+ double seconds;
+ int blocksize; /* size of one block */
+ int buffer_size; /* size of the buffer */
+ int number_of_blocks;
+ int last_block; /* -1 if not the last block */
+ int bytes_on_last_block;
+ int overflow;
+ int underflow;
+ int swap;
+ int forceraw;
+ int force;
+ int filetype;
+ int headerskip;
+ int audioset;
+ int show_usage;
+ DWORD speed;
+ int channels;
+ int bits;
+ char *progname;
+ char *device; /* Audio device name */
+ int loop;
+ int verbose;
+ int optind;
+};
+
+/* au.c */
+ int read_au(struct info_struct* info, char * buffer);
+
+/* wav.c */
+ int read_wav(struct info_struct* info, char * buffer);
+
+/* common.c */
+ DWORD read_big_endian_long(char * buffer);
+ void write_big_endian_long(char * buffer, DWORD value);
+ DWORD read_little_endian_long(char * buffer);
+ WORD read_little_endian_word(char * buffer);
+ void errprintf(char *fmt,...);
+ void warning(char *str);
+ void warning2(char *str1, char *str2);
+ void die(const char *str);
+ void errdie(const char *str);
+ void open_audio();
+ void set_audio_parameters();
+ void sync_audio(void);
+ void reset_audio(void);
+ void post_audio(void);
+ void destroy_buffer(void);
+ void nice_fputc(int c, FILE * fp);
+
+
+#endif
diff --git a/mpeglib/lib/tplay/wav.cpp b/mpeglib/lib/tplay/wav.cpp
new file mode 100644
index 00000000..ca284c37
--- /dev/null
+++ b/mpeglib/lib/tplay/wav.cpp
@@ -0,0 +1,91 @@
+/*
+ * tplay - buffered audio player
+ *
+ * (c) 1997 ilkka karvinen <ik@iki.fi>
+ *
+ * Copyright under the GNU GENERAL PUBLIC LICENSE
+ * (see the file COPYING in this directory)
+ *
+ *
+ * RIFF/WAVE file header checking.
+ * check_wav returns zero if RIFF/WAVE file format is found.
+ * Reference: http://www.wotsit.demon.co.uk/formats/wav/wav.txt
+ */
+
+#include "tplayfunctions.h"
+
+#include <iostream>
+
+using namespace std;
+
+int read_wav(struct info_struct* info, char * buffer) {
+ WORD format, channels, bits;
+ DWORD magic, samples_per_second, length, data_length;
+
+ magic = read_little_endian_long(buffer);
+ if (magic != RIFF_MAGIC) /* RIFF file? */
+ return (1);
+ magic = read_little_endian_long(buffer + 0x08);
+ if (magic != WAVE_MAGIC) /* WAVE file? */
+ return (1);
+ magic = read_little_endian_long(buffer + 0x24);
+ if ((magic != DATA_MAGIC) && (magic != INFO_MAGIC)) { /* data-portion there? */
+ cout << "Unknown WAV-header magic. Continuing anyway."<<endl;
+ }
+
+ length = read_little_endian_long(buffer + 0x10);
+
+ /* Subchunk length should be 16 here */
+ if (length != 16)
+ errdie("Unknown RIFF/WAVE header");
+
+ format = read_little_endian_word(buffer + 0x14);
+
+ switch (format) {
+ case 0x0001: /* PCM format */
+ break;
+ case 0x0101: /* mu-law */
+ die("Mu-law RIFF/WAVE audio file not supported");
+ break;
+ case 0x0102: /* a-law */
+ die("A-law RIFF/WAVE audio file not supported");
+ break;
+ case 0x0103: /* ADPCM */
+ die("ADPCM RIFF/WAVE audio file not supported");
+ break;
+ default:
+ errdie("Unknown RIFF/WAVE audio file format");
+ break;
+ }
+
+ info->filetype = RIFF_FILE;
+
+ channels = read_little_endian_word(buffer + 0x16);
+ samples_per_second = read_little_endian_long(buffer + 0x18);
+ cout << "samples_per_second:"<<samples_per_second<<endl;
+ bits = read_little_endian_word(buffer + 0x22);
+
+ if (bits == 12)
+ die("12 bits per sample not supported");
+
+ data_length = read_little_endian_long(buffer + 0x28);
+
+ /* Set audio parameters */
+ info->speed = (int) samples_per_second;
+ info->bits = (int) bits;
+ info->channels = (int) channels;
+
+ if (info->verbose)
+ printf("RIFF/WAVE audio file: %ld samples/s, %d bits, %d channel(s).\n",
+ info->speed, info->bits, info->channels);
+
+ /* Move data to start from the beginning of the buffer. */
+ /* This is to ensure the correct behaviour of rounding when 16bits */
+ /* and/or stereo sample is to be played. */
+ memmove(buffer, buffer + 0x2c, info->blocksize - 0x2c);
+
+ /* Save audio sample starting point */
+ info->headerskip = 0x2c;
+
+ return (0);
+}
diff --git a/mpeglib/lib/util/Makefile.am b/mpeglib/lib/util/Makefile.am
new file mode 100644
index 00000000..c73de2cc
--- /dev/null
+++ b/mpeglib/lib/util/Makefile.am
@@ -0,0 +1,61 @@
+# player - Makefile.am
+
+SUBDIRS = mmx abstract audio file render
+
+
+INCLUDES = $(all_includes)
+
+
+
+THIS_EXTRALIBS = abstract/libutilabstract.la \
+ audio/libaudio.la \
+ file/libsimplefile.la \
+ render/libutilrender.la \
+ mmx/libmmx.la
+
+
+noinst_LTLIBRARIES = libutil.la
+
+noinst_HEADERS = syncClockMPEG.h
+
+kmpgincludedir = $(includedir)/$(THIS_LIB_NAME)/util
+
+kmpginclude_HEADERS = timeStamp.h dynBuffer.h \
+ timeStampArray.h syncClock.h timeWrapper.h
+
+
+
+libutil_la_SOURCES = timeStamp.cpp \
+ timeStampArray.cpp \
+ dynBuffer.cpp syncClock.cpp \
+ syncClockMPEG.cpp timeWrapper.cpp
+
+libutil_la_LIBADD = $(THIS_EXTRALIBS)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/util/abstract/Makefile.am b/mpeglib/lib/util/abstract/Makefile.am
new file mode 100644
index 00000000..a5c49d6b
--- /dev/null
+++ b/mpeglib/lib/util/abstract/Makefile.am
@@ -0,0 +1,14 @@
+# player - Makefile.am
+
+
+INCLUDES = $(all_includes)
+
+noinst_LTLIBRARIES = libutilabstract.la
+
+kmpgincludedir = $(includedir)/$(THIS_LIB_NAME)/util/abstract
+
+kmpginclude_HEADERS = abs_thread.h threadQueue.h
+
+
+libutilabstract_la_SOURCES = abs_thread_sdl.cpp threadQueue.cpp
+
diff --git a/mpeglib/lib/util/abstract/abs_thread.h b/mpeglib/lib/util/abstract/abs_thread.h
new file mode 100644
index 00000000..f65445d8
--- /dev/null
+++ b/mpeglib/lib/util/abstract/abs_thread.h
@@ -0,0 +1,123 @@
+/*
+ abstraction for threads
+ 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 __ABS_THREAD_H
+#define __ABS_THREAD_H
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/**
+ This passed alle pthread_xxx calls to this interface, thus
+ it can be easier replaced with other thread "layers"
+
+ All posix pthread calls are conveterd to abs_thread.
+*/
+
+extern "C" {
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+}
+
+#define _ABS_BUSY EBUSY
+
+#ifndef SDL_WRAPPER
+// definitions for direct pthread support
+#include <pthread.h>
+
+typedef pthread_mutex_t abs_thread_mutex_t;
+typedef pthread_cond_t abs_thread_cond_t;
+typedef pthread_t abs_thread_t;
+
+
+
+#define abs_thread_cond_init(cond) pthread_cond_init(cond,NULL)
+#define abs_thread_cond_destroy(cond) pthread_cond_destroy(cond)
+#define abs_thread_cond_signal(cond) pthread_cond_signal(cond)
+#define abs_thread_cond_wait(cond,mutex) pthread_cond_wait(cond,mutex)
+
+// CREATE / JOIN THREAD
+
+#define abs_thread_create(thread,func,arg) pthread_create(thread,NULL,func,arg)
+#define abs_thread_join(th,thread_return) pthread_join(th,thread_return)
+
+// MUTEX FUNCTIONS
+
+#define abs_thread_mutex_lock(mutex) pthread_mutex_lock(mutex)
+#define abs_thread_mutex_unlock(mutex) pthread_mutex_unlock(mutex)
+#define abs_thread_mutex_init(mutex) pthread_mutex_init(mutex,NULL)
+#define abs_thread_mutex_destroy(mutex) pthread_mutex_destroy(mutex)
+
+#endif
+// not SDL_WRAPPER
+
+#ifdef SDL_WRAPPER
+
+
+// SDL SUPPORT DISABLED
+
+#if defined WIN32
+ #include <SDL_thread.h>
+ #include <SDL_mutex.h>
+#else
+ #include <SDL/SDL_thread.h>
+ #include <SDL/SDL_mutex.h>
+#endif
+
+
+typedef SDL_mutex* abs_thread_mutex_t;
+typedef SDL_cond* abs_thread_cond_t;
+typedef SDL_Thread* abs_thread_t;
+
+// SIGNAL FUNCTIONS
+// note we have _no_ cond attribut (not needed)
+int abs_thread_cond_init(abs_thread_cond_t* cond);
+int abs_thread_cond_destroy(abs_thread_cond_t *cond);
+
+int abs_thread_cond_signal(abs_thread_cond_t* cond);
+
+int abs_thread_cond_wait(abs_thread_cond_t* cond,
+ abs_thread_mutex_t *mutex);
+// CREATE / JOIN THREAD
+// Note: we have thread attribute
+int abs_thread_create(abs_thread_t* thread,
+ void * (*start_routine)(void *), void * arg);
+
+int abs_thread_join(abs_thread_t th,
+ void **thread_return);
+
+
+// MUTEX FUNCTIONS
+
+int abs_thread_mutex_lock(abs_thread_mutex_t *mutex);
+int abs_thread_mutex_trylock(abs_thread_mutex_t *mutex);
+int abs_thread_mutex_unlock(abs_thread_mutex_t *mutex);
+// not attribute!
+int abs_thread_mutex_init(abs_thread_mutex_t *mutex);
+
+int abs_thread_mutex_destroy(abs_thread_mutex_t *mutex);
+
+
+
+#endif
+//SDL_WRAPPER
+
+
+
+#endif
+
+
diff --git a/mpeglib/lib/util/abstract/abs_thread_sdl.cpp b/mpeglib/lib/util/abstract/abs_thread_sdl.cpp
new file mode 100644
index 00000000..13c9ce6c
--- /dev/null
+++ b/mpeglib/lib/util/abstract/abs_thread_sdl.cpp
@@ -0,0 +1,89 @@
+/*
+ abstraction for threads
+ 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 "abs_thread.h"
+
+
+// START SDL
+
+
+#ifdef SDL_WRAPPER
+
+
+
+int abs_thread_cond_init(abs_thread_cond_t* cond) {
+ *cond=SDL_CreateCond();
+ return (*cond != NULL);
+}
+
+int abs_thread_cond_destroy(abs_thread_cond_t *cond) {
+ SDL_DestroyCond(*cond);
+ return true;
+}
+
+
+int abs_thread_cond_signal(abs_thread_cond_t* cond) {
+
+ return SDL_CondSignal(*cond);
+}
+
+
+int abs_thread_cond_wait(abs_thread_cond_t* cond,
+ abs_thread_mutex_t* mutex) {
+ SDL_CondWait(*cond,*mutex);
+ return true;
+}
+
+
+// CREATE / JOIN THREAD
+int abs_thread_create(abs_thread_t* thread,
+ void * (*start_routine)(void *), void * arg) {
+ int (*func)(void *);
+ func=(int (*)(void *))start_routine;
+ *thread=SDL_CreateThread(func,arg);
+ return (*thread != NULL);
+}
+
+int abs_thread_join(abs_thread_t th,
+ void **thread_return) {
+ SDL_WaitThread(th,(int*)*thread_return);
+ return true;
+}
+
+
+// MUTEX FUNCTIONS
+
+int abs_thread_mutex_lock(abs_thread_mutex_t *mutex) {
+ return SDL_LockMutex(*mutex);
+}
+
+
+int abs_thread_mutex_unlock(abs_thread_mutex_t *mutex) {
+ return SDL_UnlockMutex(*mutex);
+}
+
+
+int abs_thread_mutex_init(abs_thread_mutex_t *mutex) {
+ *mutex=SDL_CreateMutex();
+ return true;
+}
+
+
+int abs_thread_mutex_destroy(abs_thread_mutex_t *mutex) {
+ SDL_DestroyMutex(*mutex);
+ return true;
+}
+
+
+
+#endif
diff --git a/mpeglib/lib/util/abstract/threadQueue.cpp b/mpeglib/lib/util/abstract/threadQueue.cpp
new file mode 100644
index 00000000..1b130ba9
--- /dev/null
+++ b/mpeglib/lib/util/abstract/threadQueue.cpp
@@ -0,0 +1,108 @@
+/*
+ fifo waitqueue for threads.(Multi-in, single out)
+ 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 "threadQueue.h"
+
+#define _MAX_THREAD_IN_QUEUE 5
+
+#include <iostream>
+
+using namespace std;
+
+//
+// WaitThreadEntry class [START]
+//
+
+WaitThreadEntry::WaitThreadEntry() {
+ abs_thread_cond_init(&waitCond);
+}
+
+
+WaitThreadEntry::~WaitThreadEntry() {
+ abs_thread_cond_destroy(&waitCond);
+}
+
+//
+// WaitThreadEntry class [END]
+//
+
+
+ThreadQueue::ThreadQueue() {
+ waitThreadEntries=new WaitThreadEntry* [_MAX_THREAD_IN_QUEUE];
+ int i;
+ for(i=0;i<_MAX_THREAD_IN_QUEUE;i++) {
+ waitThreadEntries[i]=new WaitThreadEntry();
+ }
+ abs_thread_mutex_init(&queueMut);
+ insertPos=0;
+ removePos=0;
+ size=0;
+}
+
+
+ThreadQueue::~ThreadQueue() {
+ abs_thread_mutex_lock(&queueMut);
+ if (size != 0) {
+ cout << "Aieee! Make sure that all threads are out of ThreadQueue"<<endl;
+ exit(0);
+ }
+ int i;
+ for(i=0;i<_MAX_THREAD_IN_QUEUE;i++) {
+ delete waitThreadEntries[i];
+ }
+ delete [] waitThreadEntries;
+ abs_thread_mutex_unlock(&queueMut);
+ abs_thread_mutex_destroy(&queueMut);
+}
+
+
+void ThreadQueue::waitForExclusiveAccess() {
+ abs_thread_mutex_lock(&queueMut);
+ if (size == 0) {
+ abs_thread_mutex_unlock(&queueMut);
+ return;
+ }
+ // wait
+ size++;
+ if (size == _MAX_THREAD_IN_QUEUE) {
+ cout << "Aieee! ThreadQueue can only buffer:"<<_MAX_THREAD_IN_QUEUE<<endl;
+ exit(0);
+ }
+ abs_thread_cond_t* waitCond=&(waitThreadEntries[insertPos]->waitCond);
+ insertPos++;
+ // wrap counter
+ if (insertPos == _MAX_THREAD_IN_QUEUE) {
+ insertPos=0;
+ }
+ abs_thread_cond_wait(waitCond,&queueMut);
+ abs_thread_mutex_unlock(&queueMut);
+}
+
+
+void ThreadQueue::releaseExclusiveAccess() {
+ abs_thread_mutex_lock(&queueMut);
+ if (size == 0) {
+ abs_thread_mutex_unlock(&queueMut);
+ return;
+ }
+ // wake up next thread
+ abs_thread_cond_t* waitCond=&(waitThreadEntries[removePos]->waitCond);
+ removePos++;
+ // wrap counter
+ if (removePos == _MAX_THREAD_IN_QUEUE) {
+ removePos=0;
+ }
+ size--;
+ abs_thread_cond_signal(waitCond);
+ abs_thread_mutex_unlock(&queueMut);
+}
+
diff --git a/mpeglib/lib/util/abstract/threadQueue.h b/mpeglib/lib/util/abstract/threadQueue.h
new file mode 100644
index 00000000..4c650e21
--- /dev/null
+++ b/mpeglib/lib/util/abstract/threadQueue.h
@@ -0,0 +1,74 @@
+/*
+ fifo waitqueue for threads.(Multi-in, single out)
+ 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 __THREADQUEUE_H
+#define __THREADQUEUE_H
+
+
+#include "abs_thread.h"
+
+class WaitThreadEntry {
+ public:
+ WaitThreadEntry();
+ ~WaitThreadEntry();
+
+ abs_thread_cond_t waitCond;
+};
+
+/**
+ This class can be used as a general purpuse wrapper to
+ make C++ classes thread safe.
+ Mpeglib uses for every decoder a single thread which
+ reads from the input and write to one output type (video/audio)
+ To make the input and output classes thread safe you have
+ two solutions. First you can try to do it in every class
+ itsself, this is much work and needs understanding of
+ threads or you can use this wrapper class.
+ Normally you don't need two threads in one class, only
+ for the audio/video sync this is necessary, but for
+ the inputstream (file,http,..) this not necessary.
+ For the output this is the same.
+ This class offers two methods. waitForExclusiceAcess()
+ and releaseExlusiveAcess. Internally the thread who
+ calls waitFor.. in enqueued (if it does not get the exclusive
+ access) the thread who have the exclusive access calls
+ sometimes release.. with then pass the exclusive access
+ to the next thread.
+ Why it is needed?
+ Because we access the input/output streams from different
+ threads. A user of mpeglib may want to set mpeg video
+ in fullscreen mode, this means two threads call
+ methods in the output classes including: closing windows,
+ resizing windows ... now this is safley possible when
+ the threadSafeInputStream / threadSafeoutputStream wrappers
+ are used, which forward the calls to the real classes.
+*/
+
+class ThreadQueue {
+
+ abs_thread_mutex_t queueMut;
+ int insertPos;
+ int removePos;
+ int size;
+ WaitThreadEntry** waitThreadEntries;
+
+ public:
+ ThreadQueue();
+ ~ThreadQueue();
+
+ void waitForExclusiveAccess();
+ void releaseExclusiveAccess();
+
+};
+
+#endif
diff --git a/mpeglib/lib/util/audio/Makefile.am b/mpeglib/lib/util/audio/Makefile.am
new file mode 100644
index 00000000..968d1d46
--- /dev/null
+++ b/mpeglib/lib/util/audio/Makefile.am
@@ -0,0 +1,18 @@
+
+# ---- @OS_TYPE@/@ARCH_TYPE@ ----
+
+INCLUDES = $(all_includes)
+
+EXTRA_DIST = audioIO_AIX.cpp audioIO_BeOS.cpp \
+ audioIO_HPUX.cpp \
+ audioIO_IRIX.cpp audioIO_Linux.cpp \
+ audioIO_SunOS.cpp audioIO_SDL.cpp
+
+noinst_HEADERS = audioIO.h dspWrapper.h
+
+noinst_LTLIBRARIES = libaudio.la
+
+libaudio_la_SOURCES = audioIO.cpp dspWrapper.cpp
+
+
+
diff --git a/mpeglib/lib/util/audio/audioIO.cpp b/mpeglib/lib/util/audio/audioIO.cpp
new file mode 100644
index 00000000..d066210f
--- /dev/null
+++ b/mpeglib/lib/util/audio/audioIO.cpp
@@ -0,0 +1,49 @@
+
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef SDL_WRAPPER
+
+ #include "audioIO_SDL.cpp"
+
+//
+// If native sound is defined compiled for that
+//
+
+#else
+
+
+#ifdef OS_AIX
+ #include "audioIO_AIX.cpp"
+#endif
+
+#ifdef OS_Linux
+ #include "audioIO_Linux.cpp"
+#endif
+
+#ifdef OS_BSD
+ #include "audioIO_Linux.cpp"
+#endif
+
+#if defined(OS_IRIX) || defined(OS_IRIX64)
+ #include "audioIO_IRIX.cpp"
+#endif
+
+#ifdef OS_HPUX
+ #include "audioIO_HPUX.cpp"
+#endif
+
+#ifdef OS_SunOS
+ #include "audioIO_SunOS.cpp"
+#endif
+
+#ifdef __BEOS__
+ #include "audioIO_BeOS.cpp"
+#endif
+
+
+#endif
diff --git a/mpeglib/lib/util/audio/audioIO.h b/mpeglib/lib/util/audio/audioIO.h
new file mode 100644
index 00000000..41e1ceb2
--- /dev/null
+++ b/mpeglib/lib/util/audio/audioIO.h
@@ -0,0 +1,80 @@
+
+
+#ifndef __AUDIOIO_H
+#define __AUDIOIO_H
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+
+extern "C" {
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+}
+
+/* AUSUZ should be the amount of data your audio device will accept after it
+ * has said it is ready to receive data. ie when the device is ready
+ * for data it
+ * will accept it without blocking. It must also be a multiple of 128
+ */
+
+#ifdef OS_AIX
+ #define AUSIZ 32768
+#endif
+
+#ifdef OS_Linux
+ extern int AUSIZ;
+#endif
+
+#ifdef OS_BSD
+ #define AUSIZ 32768
+#endif
+
+#if defined(OS_IRIX) || defined(OS_IRIX64)
+ #define AUSIZ 32768
+#endif
+
+#ifdef OS_HPUX
+ #define AUSIZ 4096
+#endif
+
+#ifdef OS_SunOS
+ #define AUSIZ 4096
+#endif
+
+
+#ifdef DEBUG
+ #define DB(type,cmd) if (debugFlags.type) { cmd ; }
+#else
+ #define DB(type,cmd)
+#endif
+
+
+
+
+//Prototypes:
+
+int audioConstruct();
+void audioDestruct();
+
+
+
+int audioOpen();
+void audioClose();
+void audioInit(int sampleSize,int frequency, int stereo,int sign, int bigendian);
+
+
+int mixerOpen();
+void mixerClose();
+void mixerSetVolume(int volumeLeft,int volumeRight);
+
+int audioWrite(char *buffer, int count);
+int getAudioFd();
+int getAudioBufferSize();
+
+#endif
diff --git a/mpeglib/lib/util/audio/audioIO_AIX.cpp b/mpeglib/lib/util/audio/audioIO_AIX.cpp
new file mode 100644
index 00000000..15316852
--- /dev/null
+++ b/mpeglib/lib/util/audio/audioIO_AIX.cpp
@@ -0,0 +1,533 @@
+/*
+ * AIX audio - griff@acm.org 02aug2000
+ * tested on 43P 260 with builtin audio
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+/* A conflict within AIX 4.3.3 <sys/> headers and probably others as well.
+ * I guess nobody ever uses audio... Shame over AIX header files. */
+#include <sys/machine.h>
+#undef BIG_ENDIAN
+#include <sys/audio.h>
+
+static int audio_fd;
+
+static void debugUpdate( unsigned long& flags, long& bsize );
+
+#ifndef AUDIO_BIG_ENDIAN
+#define AUDIO_BIG_ENDIAN BIG_ENDIAN
+#endif
+
+
+
+int audioConstruct() {
+ printf("audioConstruct AIX ********\n");
+ audio_fd=-1;
+ return true;
+}
+
+
+void audioDestruct() {
+
+}
+
+int audioOpen()
+{
+ char devname[14];
+ for ( int dev=0; dev<4; dev++ )
+ {
+ for ( int chan=1; chan<8; chan++ )
+ {
+ sprintf(devname,"/dev/paud%d/%d",dev,chan);
+ audio_fd = open (devname, O_WRONLY, 0);
+ if ( audio_fd >= 0 )
+ {
+ return 1;
+ }
+ sprintf(devname,"/dev/baud%d/%d",dev,chan);
+ audio_fd = open (devname, O_WRONLY, 0);
+ if ( audio_fd >= 0 )
+ {
+ return 1;
+ }
+ }
+ }
+
+ fprintf(stderr, "Could not open AIX audio device, faking\n" );
+ return 1;
+}
+
+int getAudioBufferSize()
+{
+ audio_buffer paud_bufinfo;
+
+ if( audio_fd < 0 ) return 1024*65;
+
+ if ( ioctl(audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0 )
+ {
+ perror("ioctl getAudioBufferSize using default");
+ return 1024*65;
+ }
+
+ /*
+ * Do you need the total capacity or the current capacity?
+ * This is the total capacity:
+ */
+ return paud_bufinfo.write_buf_cap;
+ /*
+ * This is the current capacity:
+ * return (paud_bufinfo.write_buf_cap - paud_bufinfo.write_buf_size);
+ */
+}
+
+void audioInit(int sampleSize,int frequency, int stereo, int sign, int bigendian )
+{
+ // int format;
+ int bytes_per_sample;
+ audio_init paud_init;
+ audio_buffer paud_bufinfo;
+ // audio_status paud_status;
+ audio_control paud_control;
+ audio_change paud_change;
+
+ if( audio_fd < 0 ) return;
+
+ /*
+ * We can't set the buffer size - just ask the device for the maximum
+ * that we can have.
+ */
+ if ( ioctl(audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0 )
+ {
+ perror("Couldn't get audio buffer information");
+ return;
+ }
+
+ /*
+ * Fields in the audio_init structure:
+ *
+ * Ignored by us:
+ *
+ * paud.loadpath[LOAD_PATH]; * DSP code to load, MWave chip only?
+ * paud.slot_number; * slot number of the adapter
+ * paud.device_id; * adapter identification number
+ *
+ * Input:
+ *
+ * paud.srate; * the sampling rate in Hz
+ * paud.bits_per_sample; * 8, 16, 32, ...
+ * paud.bsize; * block size for this rate
+ * paud.mode; * ADPCM, PCM, MU_LAW, A_LAW, SOURCE_MIX
+ * paud.channels; * 1=mono, 2=stereo
+ * paud.flags; * FIXED - fixed length data
+ * * LEFT_ALIGNED, RIGHT_ALIGNED (var len only)
+ * * TWOS_COMPLEMENT - 2's complement data
+ * * SIGNED - signed? comment seems wrong in sys/audio.h
+ * * BIG_ENDIAN
+ * paud.operation; * PLAY, RECORD
+ *
+ * Output:
+ *
+ * paud.flags; * PITCH - pitch is supported
+ * * INPUT - input is supported
+ * * OUTPUT - output is supported
+ * * MONITOR - monitor is supported
+ * * VOLUME - volume is supported
+ * * VOLUME_DELAY - volume delay is supported
+ * * BALANCE - balance is supported
+ * * BALANCE_DELAY - balance delay is supported
+ * * TREBLE - treble control is supported
+ * * BASS - bass control is supported
+ * * BESTFIT_PROVIDED - best fit returned
+ * * LOAD_CODE - DSP load needed
+ * paud.rc; * NO_PLAY - DSP code can't do play requests
+ * * NO_RECORD - DSP code can't do record requests
+ * * INVALID_REQUEST - request was invalid
+ * * CONFLICT - conflict with open's flags
+ * * OVERLOADED - out of DSP MIPS or memory
+ * paud.position_resolution; * smallest increment for position
+ */
+
+ paud_init.srate = frequency;
+ paud_init.mode = PCM;
+ paud_init.operation = PLAY;
+ paud_init.channels = (stereo?2:1);
+
+ /*
+ * options in AIX:
+ * paud_init.bits_per_sample: 8 | 16
+ * paud_init.flags: AUDIO_BIG_ENDIAN (not used here)
+ * SIGNED (always used here)
+ * TWOS_COMPLEMENT (always on for Linux dsp porting?)
+ * FIXED <- that's right for SDL
+ * or LEFT_ALIGNED <- that's right for mpeglib
+ * or RIGHT_ALIGNED
+ * paud_init.bsize: sample byte size,
+ * bits_per_sample * (stereo?2:1) - for SDL
+ * bits_per_sample * (stereo?2:1) * 2 - for mpeglib
+ */
+ if ( sampleSize == 8 )
+ {
+ /* AFMT_S8 in linux dsp */
+ bytes_per_sample = 2; // why not 1 ?
+ paud_init.bits_per_sample = 8;
+ paud_init.flags = TWOS_COMPLEMENT | LEFT_ALIGNED;
+ }
+ else
+ {
+ /* AFMT_S16_LE in linux dsp */
+ bytes_per_sample = 4; // why not 2 ?
+ paud_init.bits_per_sample = 16;
+ paud_init.flags = TWOS_COMPLEMENT | LEFT_ALIGNED;
+ }
+ if( sign ) paud_init.flags |= SIGNED;
+ if( bigendian ) paud_init.flags |= AUDIO_BIG_ENDIAN;
+
+ paud_init.bsize = bytes_per_sample * (stereo?2:1);
+
+#if 0
+ debugUpdate(paud_init.flags, paud_init.bsize);
+
+ printf("CG: sampleSize = %d\n", sampleSize);
+ printf("CG: frequency = %d\n", frequency);
+ printf("CG: stereo = %s\n", (stereo)?"y":"n");
+ printf("CG: mode = %s\n", "PCM");
+ printf("CG: channels = %d\n", paud_init.channels);
+ printf("CG: bsize = %d\n", paud_init.bsize);
+ printf("CG: bits_per_sample = %d\n", paud_init.bits_per_sample);
+ printf("CG: flags & BIG_ENDIAN = %s\n", ((paud_init.flags&AUDIO_BIG_ENDIAN)?"y":"n"));
+ printf("CG: flags & SIGNED = %s\n", ((paud_init.flags&SIGNED)?"y":"n"));
+ printf("CG: flags & TWOS_COMPLEMENT = %s\n", ((paud_init.flags&TWOS_COMPLEMENT)?"y":"n"));
+ printf("CG: flags & FIXED = %s\n", ((paud_init.flags&FIXED)?"y":"n"));
+ printf("CG: flags & LEFT_ALIGNED = %s\n", ((paud_init.flags&LEFT_ALIGNED)?"y":"n"));
+ printf("CG: flags & RIGHT_ALIGNED = %s\n", ((paud_init.flags&RIGHT_ALIGNED)?"y":"n"));
+#endif
+
+ /*
+ * We know the buffer size and the max number of subsequent writes
+ * that can be pending. If more than one can pend, allow the application
+ * to do something like double buffering between our write buffer and
+ * the device's own buffer that we are filling with write() anyway.
+ *
+ * We can calculate the number of samples that fit into the audio
+ * device buffer if that is necessary:
+ *
+ * samples_capacity = paud_bufinfo.write_buf_cap
+ * / bytes_per_sample
+ * / (stereo?2:1);
+ * if ( paud_bufinfo.request_buf_cap != 1 ) samples_capacity /= 2;
+ */
+
+ /*
+ * The AIX paud device init can't modify the values of the audio_init
+ * structure that we pass to it. So we don't need any recalculation
+ * of this stuff and no reinit call as in linux SDL dsp and dma code.
+ *
+ * /dev/paud supports all of the encoding formats, so we don't need
+ * to do anything like reopening the device, either.
+ */
+ if ( ioctl(audio_fd, AUDIO_INIT, &paud_init) < 0 )
+ {
+ switch ( paud_init.rc )
+ {
+ case 1 :
+ perror("Couldn't set audio format: DSP can't do play requests");
+ return;
+ break;
+ case 2 :
+ perror("Couldn't set audio format: DSP can't do record requests");
+ return;
+ break;
+ case 4 :
+ perror("Couldn't set audio format: request was invalid");
+ return;
+ break;
+ case 5 :
+ perror("Couldn't set audio format: conflict with open's flags");
+ return;
+ break;
+ case 6 :
+ perror("Couldn't set audio format: out of DSP MIPS or memory");
+ return;
+ break;
+ default :
+ perror("Couldn't set audio format: not documented in sys/audio.h");
+ return;
+ break;
+ }
+ }
+
+ /*
+ * Set some parameters: full volume, first speaker that we can find.
+ * Ignore the other settings for now.
+ */
+ paud_change.input = AUDIO_IGNORE; /* the new input source */
+ paud_change.output = OUTPUT_1;
+ /* EXTERNAL_SPEAKER,
+ * INTERNAL_SPEAKER,
+ * OUTPUT_1 */
+ paud_change.monitor = AUDIO_IGNORE; /* the new monitor state */
+ paud_change.volume = 0x7fffffff; /* volume level [0-0x7fffffff] */
+ paud_change.volume_delay = AUDIO_IGNORE; /* the new volume delay */
+ paud_change.balance = 0x3fffffff; /* the new balance */
+ paud_change.balance_delay = AUDIO_IGNORE; /* the new balance delay */
+ paud_change.treble = AUDIO_IGNORE; /* the new treble state */
+ paud_change.bass = AUDIO_IGNORE; /* the new bass state */
+ paud_change.pitch = AUDIO_IGNORE; /* the new pitch state */
+
+ paud_control.ioctl_request = AUDIO_CHANGE;
+ paud_control.request_info = (char*)&paud_change;
+ if ( ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0 )
+ {
+ perror("Can't change audio display settings (ignoring)" );
+ }
+
+ /*
+ * Tell the device to expect data. Actual start will wait for
+ * the first write() call.
+ */
+ paud_control.ioctl_request = AUDIO_START;
+ paud_control.position = 0;
+ if ( ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0 )
+ {
+ perror("Can't start audio play");
+ return;
+ }
+}
+
+
+void audioSetVolume(int volume)
+{
+ long vol = (long)(volume/100.0) * 0x7fffffff;
+ if( audio_fd < 0 ) return;
+
+ audio_control paud_control;
+ audio_change paud_change;
+
+ paud_change.input = AUDIO_IGNORE; /* the new input source */
+ paud_change.output = OUTPUT_1; /* EXTERNAL_SPEAKER,INTERNAL_SPEAKER,
+ OUTPUT_1 */
+ paud_change.monitor = AUDIO_IGNORE; /* the new monitor state */
+ paud_change.volume = vol; /* volume level [0-0x7fffffff] */
+ paud_change.volume_delay = AUDIO_IGNORE; /* the new volume delay */
+ paud_change.balance = AUDIO_IGNORE; /* the new balance */
+ paud_change.balance_delay = AUDIO_IGNORE; /* the new balance delay */
+ paud_change.treble = AUDIO_IGNORE; /* the new treble state */
+ paud_change.bass = AUDIO_IGNORE; /* the new bass state */
+ paud_change.pitch = AUDIO_IGNORE; /* the new pitch state */
+
+ paud_control.ioctl_request = AUDIO_CHANGE;
+ paud_control.request_info = (char*)&paud_change;
+
+ if ( ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0 )
+ {
+ perror("Change audio volume failed");
+ }
+}
+
+void audioFlush()
+{
+ if( audio_fd < 0 ) return;
+
+ if ( ioctl(audio_fd, AUDIO_WAIT, NULL) < 0 )
+ {
+ perror("Flush audio buffers failed");
+ }
+}
+
+void audioClose()
+{
+ if( audio_fd < 0 ) return;
+
+ if ( ioctl(audio_fd, AUDIO_WAIT, NULL) < 0 )
+ {
+ perror("Flush audio buffers failed");
+ }
+ close(audio_fd);
+}
+
+int audioWrite(char *buffer, int count)
+{
+ int written = write(audio_fd, buffer, count);
+ if( written < count )
+ {
+ return count;
+ }
+
+ return written;
+}
+
+int
+getAudioFd()
+{
+ return audio_fd;
+}
+
+int mixerOpen()
+{
+ return true;
+}
+
+void mixerClose()
+{
+}
+
+void mixerSetVolume(int leftVolume,int rightVolume)
+{
+ long balance;
+
+ if( audio_fd < 0 ) return;
+
+ balance = 2 * (leftVolume-rightVolume) / (leftVolume+rightVolume);
+ balance = 0x3fffffff + balance*0x3fffffff;
+
+ audio_control paud_control;
+ audio_change paud_change;
+
+ paud_change.input = AUDIO_IGNORE; /* the new input source */
+ paud_change.output = OUTPUT_1; /* EXTERNAL_SPEAKER,INTERNAL_SPEAKER,
+ OUTPUT_1 */
+ paud_change.monitor = AUDIO_IGNORE; /* the new monitor state */
+ paud_change.volume = AUDIO_IGNORE; /* volume level [0-0x7fffffff] */
+ paud_change.volume_delay = AUDIO_IGNORE; /* the new volume delay */
+ paud_change.balance = balance; /* the new balance */
+ paud_change.balance_delay = AUDIO_IGNORE; /* the new balance delay */
+ paud_change.treble = AUDIO_IGNORE; /* the new treble state */
+ paud_change.bass = AUDIO_IGNORE; /* the new bass state */
+ paud_change.pitch = AUDIO_IGNORE; /* the new pitch state */
+
+ paud_control.ioctl_request = AUDIO_CHANGE;
+ paud_control.request_info = (char*)&paud_change;
+
+ if ( ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0 )
+ {
+ perror("Change audio volume failed");
+ }
+}
+
+static void debugUpdate( unsigned long& flags, long& bsize )
+{
+ const char* g;
+
+ g = getenv("AUDIO_BIG_ENDIAN");
+ if ( g )
+ {
+ int i = atoi(g);
+ if ( i == 1 )
+ {
+ flags |= AUDIO_BIG_ENDIAN;
+ }
+ else if ( i == 0 )
+ {
+ flags &= ~AUDIO_BIG_ENDIAN;
+ }
+ else
+ {
+ printf("CG: bad AUDIO_BIG_ENDIAN env variable %s\n", g);
+ }
+ }
+
+ g = getenv("SIGNED");
+ if ( g )
+ {
+ int i = atoi(g);
+ if ( i == 1 )
+ {
+ flags |= SIGNED;
+ }
+ else if ( i == 0 )
+ {
+ flags &= ~SIGNED;
+ }
+ else
+ {
+ printf("CG: bad SIGNED env variable %s\n", g);
+ }
+ }
+
+ g = getenv("TWOS_COMPLEMENT");
+ if ( g )
+ {
+ int i = atoi(g);
+ if ( i == 1 )
+ {
+ flags |= TWOS_COMPLEMENT;
+ }
+ else if ( i == 0 )
+ {
+ flags &= ~TWOS_COMPLEMENT;
+ }
+ else
+ {
+ printf("CG: bad TWOS_COMPLEMENT env variable %s\n", g);
+ }
+ }
+
+ g = getenv("FIXED");
+ if ( g )
+ {
+ int i = atoi(g);
+ if ( i == 1 )
+ {
+ flags |= FIXED;
+ }
+ else if ( i == 0 )
+ {
+ flags &= ~FIXED;
+ }
+ else
+ {
+ printf("CG: bad FIXED env variable %s\n", g);
+ }
+ }
+
+ g = getenv("LEFT_ALIGNED");
+ if ( g )
+ {
+ int i = atoi(g);
+ if ( i == 1 )
+ {
+ flags |= LEFT_ALIGNED;
+ }
+ else if ( i == 0 )
+ {
+ flags &= ~LEFT_ALIGNED;
+ }
+ else
+ {
+ printf("CG: bad LEFT_ALIGNED env variable %s\n", g);
+ }
+ }
+
+ g = getenv("RIGHT_ALIGNED");
+ if ( g )
+ {
+ int i = atoi(g);
+ if ( i == 1 )
+ {
+ flags |= RIGHT_ALIGNED;
+ }
+ else if ( i == 0 )
+ {
+ flags &= ~RIGHT_ALIGNED;
+ }
+ else
+ {
+ printf("CG: bad RIGHT_ALIGNED env variable %s\n", g);
+ }
+ }
+
+ g = getenv("BSIZE");
+ if ( g )
+ {
+ bsize = atoi(g);
+ }
+}
+
diff --git a/mpeglib/lib/util/audio/audioIO_BeOS.cpp b/mpeglib/lib/util/audio/audioIO_BeOS.cpp
new file mode 100644
index 00000000..ae4cf5a1
--- /dev/null
+++ b/mpeglib/lib/util/audio/audioIO_BeOS.cpp
@@ -0,0 +1,227 @@
+//
+// BeOS code for amp-0.7.4, (C) 1997 Andy Lo A Foe
+//
+
+
+#include <MediaKit.h>
+#include <KernelKit.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "transform.h"
+#include "audioIO.h"
+#include "audio.h"
+
+// Define the streambuf size here. streambuf is used
+// as a simple fit buffer.
+
+#define STREAMBUF_SIZE (32*1152)
+
+long bytes_in_streambuf;
+
+// streambuf definition and base indicator
+
+BSubscriber *the_sub;
+BDACStream *the_stream;
+
+sem_id ok_to_read;
+sem_id ok_to_write;
+
+
+char streambuf[STREAMBUF_SIZE];
+char *readbase;
+
+static int au_vol = 100;
+
+// Define our own printout function since we are
+// first writing in the streambuf (not needed, I think,
+// but I don't know if the DACStream accepts a buffer
+// size of 1152. Try it...
+
+void printout(void)
+{
+if (A_WRITE_TO_FILE) {
+#ifndef NO_BYTE_SWAPPING
+int i,j;
+short *ptr;
+
+ if (nch==2) {
+ ptr=(short*)stereo_samples;
+ i=j=32 * 18 * 2;
+ } else {
+ ptr=(short*)mono_samples;
+ i=j=32 * 18;
+ }
+
+ for (;i>=0;--i)
+ ptr[i] = ptr[i] << 8 | ptr[i] >> 8;
+#endif
+
+ if (nch==2)
+ fwrite(stereo_samples,1,sizeof stereo_samples,out_file);
+ else
+ fwrite(mono_samples,1,sizeof mono_samples,out_file);
+}
+
+
+ if (A_AUDIO_PLAY) {
+ static char au_buf[STREAMBUF_SIZE];
+ static int au_ptr =0, avail = 0;
+ static int num_smp;
+ static char *readbase = &au_buf[0];
+
+ // Write amount of samples to copy somewhere
+ num_smp = (nch == 2 ? sizeof stereo_samples : sizeof mono_samples);
+
+ // Copy samples in the fit buffer
+ memcpy(au_buf+au_ptr,(nch == 2 ? (char *)stereo_samples : (char *)mono_samples),
+ num_smp);
+
+ // Increase fit buffer pointer and available sample count
+ au_ptr+=num_smp;
+ avail+=num_smp;
+
+ if (avail >= 4096) { // Are there enough smps to feed the stream?
+ audioWrite((char*)readbase,4096); // Feed it!
+ readbase+=4096; // Increase readbase
+ avail-=4096; // Decrease avail smps count
+ if (au_ptr == STREAMBUF_SIZE) { // At end of fit buffer?
+ au_ptr=0; // Reset all pointers
+ readbase=&au_buf[0];
+ }
+ }
+ }
+
+}
+
+
+// Fake Buffer functions, just to keep the sources clean,
+// buffer.c should not be included in the link process...
+
+int AUDIO_BUFFER_SIZE;
+
+int
+audioBufferOpen(int frequency, int stereo, int volume)
+{
+ audioOpen(frequency, stereo, volume);
+}
+
+
+inline void
+audioBufferWrite(char *buf,int bytes)
+{
+ audioWrite(buf, bytes);
+}
+
+
+void
+audioBufferClose()
+{
+ audioClose();
+}
+
+
+int audioRead(char *buffer, int count)
+{
+ //printf("acquiring ok_to_read (%d bytes)\n", count);
+ if (acquire_sem(ok_to_read)==B_NO_ERROR) {
+ for (register int i=0; i < count;i++) {
+ *(buffer++)+=*(readbase++);
+ }
+ bytes_in_streambuf-=count;
+
+ if (bytes_in_streambuf <= 0) {
+ release_sem(ok_to_write);
+ bytes_in_streambuf = 0;
+ } else {
+ release_sem(ok_to_read);
+ }
+ }
+ return (0);
+}
+
+
+bool stream_func(void *arg, char *buf, size_t count, void *header)
+{
+ audioRead(buf, count);
+ return TRUE;
+}
+
+void audioOpen() {
+ readbase = &streambuf[0];
+
+ bytes_in_streambuf = 0;
+
+ the_sub = new BSubscriber("amp DAC writer");
+ the_stream = new BDACStream();
+
+ the_sub->Subscribe(the_stream);
+
+ the_stream->SetSamplingRate(frequency);
+
+ // Create semaphores
+ ok_to_read = create_sem(0, "read sem");
+ ok_to_write = create_sem(1, "write sem");
+
+}
+
+void audioInit(int sampleSize,int frequency, int stereo)
+{
+
+ // Initialize the streambuf
+ bytes_in_streambuf = 0;
+ memset(&streambuf, 0, STREAMBUF_SIZE);
+
+
+ // Enter the stream
+ the_sub->EnterStream(NULL, TRUE, NULL, stream_func, NULL, TRUE);
+}
+
+
+void audioSetVolume(int volume)
+{
+ if (volume > 128) // This allows for a modest volume boost
+ volume = 128;
+ au_vol = volume;
+}
+
+
+void audioClose()
+{
+ the_sub->ExitStream(TRUE);
+ the_sub->Unsubscribe();
+
+ delete_sem(ok_to_read);
+ delete_sem(ok_to_write);
+
+ delete the_sub;
+ delete the_stream;
+}
+
+
+// audioWrite is called from the player thread
+
+int audioWrite(char *buffer, int count)
+{
+ //printf("acquiring ok_to_write (%d bytes)\n", count);
+ if(acquire_sem(ok_to_write)==B_NO_ERROR)
+ {
+ memcpy(&streambuf, buffer, count);
+
+ if (au_vol != 100) { // Handle volume scaling here
+ short *b=(short *)&streambuf;
+ for (int i=0; i < count/2; i++) {
+ int v=((int)b[i]*au_vol)/100;
+ b[i]=(v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
+ }
+ }
+
+ bytes_in_streambuf = count;
+ readbase = &streambuf[0];
+
+ release_sem(ok_to_read);
+ }
+ return 0;
+}
+
diff --git a/mpeglib/lib/util/audio/audioIO_HPUX.cpp b/mpeglib/lib/util/audio/audioIO_HPUX.cpp
new file mode 100644
index 00000000..ae07a148
--- /dev/null
+++ b/mpeglib/lib/util/audio/audioIO_HPUX.cpp
@@ -0,0 +1,190 @@
+/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
+
+ Origional code by: Lutz Vieweg
+ Modified by:
+ * Andrew Richards - moved code from audio.c
+
+ */
+
+
+#include <sys/audio.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/lock.h>
+#include <unistd.h>
+#include <stdio.h>
+#include "audioIO.h"
+
+/* declare these static to effectively isolate the audio device */
+
+static int audio_fd;
+
+
+/* audioOpen() */
+/* should open the audio device, perform any special initialization */
+/* Set the frequency, no of channels and volume. Volume is only set if */
+/* it is not -1 */
+
+void audioOpen() {
+ if ((audio_fd = open("/dev/audio",O_RDWR))==-1)
+ die(" unable to open the audio device\n");
+
+ DB(audio, msg("Audio device opened on %d\n",audio_fd); )
+ }
+
+
+void
+audioInit(int sampleSize,int frequency, int stereo)
+{
+ int flags;
+ int failed = 0;
+ int volume=100;
+
+ if ((flags = fcntl (audio_fd, F_GETFL, 0)) < 0) {
+ die("unable to set non-blocking mode for /dev/audio\n");
+ }
+ flags |= O_NDELAY;
+ if (fcntl (audio_fd, F_SETFL, flags) < 0) {
+ die("unable to set non-blocking mode for /dev/audio\n");
+ }
+
+ if ( ioctl(audio_fd, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_LINEAR16BIT) < 0 ||
+ ioctl(audio_fd, AUDIO_SET_CHANNELS, stereo ? 2 : 1) < 0 ||
+ ioctl(audio_fd, AUDIO_SET_OUTPUT, AUDIO_OUT_SPEAKER | AUDIO_OUT_HEADPHONE
+ | AUDIO_OUT_LINE) < 0 ||
+ ioctl(audio_fd, AUDIO_SET_SAMPLE_RATE, frequency) < 0) {
+ failed = -1;
+ }
+ if (volume != -1) {
+ struct audio_describe description;
+ struct audio_gains gains;
+ float fvolume = (float)volume / 100.0f;
+ if (ioctl(audio_fd, AUDIO_DESCRIBE, &description)) {
+ failed = -1;
+ }
+ if (ioctl (audio_fd, AUDIO_GET_GAINS, &gains)) {
+ failed = -1;
+ }
+
+ gains.transmit_gain = (int)((float)description.min_transmit_gain +
+ (float)(description.max_transmit_gain
+ - description.min_transmit_gain)
+ * fvolume);
+
+ /* gains.monitor_gain = description.min_monitor_gain; */ /* don't monitor ! */
+
+ if (ioctl (audio_fd, AUDIO_SET_GAINS, &gains)) {
+ failed = -1;
+ }
+ }
+
+ if (ioctl(audio_fd, AUDIO_SET_TXBUFSIZE, 4096 * 8)) {
+ failed = -1;
+ }
+ if (failed)
+ die(" unable to setup /dev/audio\n");
+}
+
+
+/* audioSetVolume - only code this if your system can change the volume while */
+/* playing. sets the output volume 0-100 */
+
+void
+audioSetVolume(int volume)
+{
+ struct audio_describe description;
+ struct audio_gains gains;
+ int failed = 0;
+ float fvolume = ((float)volume) / 100.0f;
+ if (ioctl(audio_fd, AUDIO_DESCRIBE, &description)) {
+ failed = -1;
+ }
+ if (ioctl (audio_fd, AUDIO_GET_GAINS, &gains)) {
+ failed = -1;
+}
+
+ gains.transmit_gain = (int)((float)description.min_transmit_gain +
+ (float)(description.max_transmit_gain
+ - description.min_transmit_gain)
+ * fvolume);
+ if (ioctl (audio_fd, AUDIO_SET_GAINS, &gains)) {
+ failed = -1;
+ }
+
+ /* could evaluate "failed" here - but who cares? */
+
+ DB(audio, msg("volume set to %d%%\n",volume); )
+
+}
+
+/* audioFlush() */
+/* should flush the audio device */
+
+inline void
+audioFlush()
+{
+ DB(audio, msg("audio: flush %d\n",audio_fd) );
+}
+
+
+/* audioClose() */
+/* should close the audio device and perform any special shutdown */
+
+void
+audioClose()
+{
+ close(audio_fd);
+ DB(audio, msg("audio: closed %d\n",audio_fd) );
+}
+
+
+/* audioWrite */
+/* writes count bytes from buffer to the audio device */
+/* returns the number of bytes actually written */
+
+int audioWrite(char *buffer, int count)
+{
+ DB(audio, msg("audio: Writing %d bytes to audio descriptor %d\n",count,getAudioFd()) );
+ return(write(audio_fd,buffer,count));
+}
+
+
+/* Let buffer.c have the audio descriptor so it can select on it. This means */
+/* that the program is dependent on an file descriptor to work. Should really */
+/* move the select's etc (with inlines of course) in here so that this is the */
+/* ONLY file which has hardware dependent audio stuff in it */
+
+int
+getAudioFd()
+{
+ return(audio_fd);
+}
+
+/*
+ Try to set the priority of this process to a value which
+ allows us to play without buffering, thus saving memory
+ and avoiding cache-misses.
+ If we cannot get any priority high enough to allow for
+ undisturbed replay (because we don't have sufficient
+ privilege), return a zero, otherwise, return a one.
+*/
+int audioSetPriority(void) {
+
+ /* try to lock process in physical memory, just ignore if this fails */
+ plock(PROCSHLIBLOCK);
+
+ /* try to set a realtime-priority of 64 */
+ if (-1 != rtprio(0, 64)) {
+ DB(audio, msg("using real-time priority\n"); )
+ return 1;
+ }
+
+ /* try to set a nice-level of -20 */
+ if (-1 != nice(-20)) {
+ DB(audio, msg("using nice-level -20\n"); )
+ return 1;
+ }
+
+ DB(audio, msg("using buffered output\n"); )
+ return 0; /* need to use a buffer */
+}
diff --git a/mpeglib/lib/util/audio/audioIO_IRIX.cpp b/mpeglib/lib/util/audio/audioIO_IRIX.cpp
new file mode 100644
index 00000000..8498a487
--- /dev/null
+++ b/mpeglib/lib/util/audio/audioIO_IRIX.cpp
@@ -0,0 +1,157 @@
+/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
+
+ Origional code by: Karl Anders Oygard
+ Modified by:
+ * Andrew Richards - moved code from audio.c
+
+ */
+#include <assert.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <dmedia/audio.h>
+#include "audioIO.h"
+
+/* declare these static to effectively isolate the audio device */
+
+static ALport audioport;
+static ALconfig audioconfig;
+
+
+/* audioOpen() */
+/* should open the audio device, perform any special initialization */
+/* Set the frequency, no of channels and volume. Volume is only set if */
+/* it is not -1 */
+
+
+void audioOpen() {
+ printf("sorry. The audio part for irix must be fixed. \n");
+}
+
+void
+audioInit(int sampleSize,int frequency, int stereo)
+{
+ ALconfig audioconfig;
+ audioconfig = ALnewconfig();
+
+ if (!audioconfig)
+ die("out of memory\n");
+ else {
+ long pvbuf[] = { AL_OUTPUT_COUNT, 0, AL_MONITOR_CTL, 0, AL_OUTPUT_RATE, 0};
+
+ if (ALgetparams(AL_DEFAULT_DEVICE, pvbuf, 6) < 0)
+ if (oserror() == AL_BAD_DEVICE_ACCESS)
+ die("couldn't access audio device\n");
+
+ if (pvbuf[1] == 0 && pvbuf[3] == AL_MONITOR_OFF) {
+ long al_params[] = { AL_OUTPUT_RATE, 0};
+
+ al_params[1] = frequency;
+ ALsetparams(AL_DEFAULT_DEVICE, al_params, 2);
+ } else
+ if (pvbuf[5] != frequency)
+ die("audio device is already in use with wrong sample output rate\n");
+
+ /* ALsetsampfmt(audioconfig, AL_SAMPFMT_TWOSCOMP); this is the default */
+ /* ALsetwidth(audioconfig, AL_SAMPLE_16); this is the default */
+
+ if (!stereo) ALsetchannels(audioconfig, AL_MONO);
+ /* else ALsetchannels(audioconfig, AL_STEREO); this is the default */
+
+ ALsetqueuesize(audioconfig, AUSIZ * 2);
+
+ audioport = ALopenport("amp", "w", audioconfig);
+ if (audioport == (ALport) 0) {
+ switch (oserror()) {
+ case AL_BAD_NO_PORTS:
+ die("system is out of ports\n");
+
+ case AL_BAD_DEVICE_ACCESS:
+ die("couldn't access audio device\n");
+
+ case AL_BAD_OUT_OF_MEM:
+ die("out of memory\n");
+ }
+ exit(-1);
+ }
+ ALsetfillpoint(audioport, AUSIZ);
+ }
+}
+
+
+/* audioSetVolume - only code this if your system can change the volume while */
+/* playing. sets the output volume 0-100 */
+
+void
+audioSetVolume(int volume)
+{
+ long al_params[] = { AL_LEFT_SPEAKER_GAIN, 0, AL_RIGHT_SPEAKER_GAIN, 0};
+
+ al_params[1] = al_params[3] = volume * 100 / 255;
+
+ ALsetparams(AL_DEFAULT_DEVICE, al_params, 4);
+}
+
+
+/* audioFlush() */
+/* should flush the audio device */
+
+void
+audioFlush()
+{
+ DB(audio, msg("audio: flush %d\n",audio_fd) );
+}
+
+
+/* audioClose() */
+/* should close the audio device and perform any special shutdown */
+
+void
+audioClose()
+{
+int write_fd;
+
+ /* wait for all samples to be played */
+
+ write_fd = ALgetfd(audioport);
+ if (write_fd >= 0) {
+ fd_set write_fds;
+
+ FD_ZERO(&write_fds);
+ FD_SET(write_fd, &write_fds);
+
+ ALsetfillpoint(audioport, AUSIZ * 2);
+ select(write_fd + 1, NULL, &write_fds, NULL, NULL);
+ }
+
+ /* now close it */
+
+ ALcloseport(audioport);
+ DB(audio, msg("audio: closed %d\n",audio_fd) );
+}
+
+
+/* audioWrite */
+/* writes count bytes from buffer to the audio device */
+/* returns the number of bytes actually written */
+
+int audioWrite(char *buffer, int count)
+{
+ if (ALwritesamps(audioport, buffer, count / 2) == 0) {
+ ALsetfillpoint(audioport, AUSIZ);
+ return(count);
+ } else
+ return 0;
+}
+
+/* Let buffer.c have the audio descriptor so it can select on it. This
+ means that the program is dependent on an file descriptor to
+ work. Should really move the select's etc (with inlines of course) in
+ here so that this is the ONLY file which has hardware dependent audio
+ stuff in it. */
+
+int
+getAudioFd()
+{
+ return ALgetfd(audioport);
+}
+
diff --git a/mpeglib/lib/util/audio/audioIO_Linux.cpp b/mpeglib/lib/util/audio/audioIO_Linux.cpp
new file mode 100644
index 00000000..5ca9231c
--- /dev/null
+++ b/mpeglib/lib/util/audio/audioIO_Linux.cpp
@@ -0,0 +1,220 @@
+/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
+
+ Origional code by: tomislav uzelac
+ Modified by:
+ * Dan Nelson - BSD mods.
+ * Andrew Richards - moved code from audio.c and added mixer support etc
+ * Martin Vogt
+ */
+
+/* Support for Linux and BSD sound devices */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include "audioIO.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+//
+// Why all these different system cannot make a standard where this
+// soundcard.h file is ?
+//
+#if defined(HAVE_SYS_SOUNDCARD_H)
+ #undef AUSIZ
+ #undef HAVE_SYS_SOUNDCARD_H
+ #include <sys/soundcard.h>
+#elif defined(HAVE_MACHINE_SOUNDCARD_H)
+ #undef AUSIZ
+ #include <machine/soundcard.h>
+#elif defined(__NetBSD__)
+ #undef AUSIZ
+ #include <soundcard.h>
+#else
+ // fallback:
+ #include <linux/soundcard.h>
+#endif
+
+
+/* optimal fragment size */
+
+int AUSIZ = 0;
+
+// declare these static to effectively isolate the audio device
+
+static int audio_fd;
+static int mixer_fd;
+static int volumeIoctl;
+
+
+
+int audioConstruct() {
+ audio_fd=-1;
+ mixer_fd=-1;
+ return true;
+}
+
+
+void audioDestruct() {
+
+}
+
+
+
+/*
+ should open the audio device, perform any special initialization
+*/
+int audioOpen() {
+ audio_fd = open ("/dev/dsp", O_WRONLY, 0);
+ if (audio_fd < 0) {
+ perror("Unable to open the audio");
+ }
+
+ // Ok here something important if your programm forks:
+ if (audio_fd > 0) {
+ if (fcntl(audio_fd,F_SETFD,true) < 0) {
+ perror("fcntl socket");exit(1);
+ }
+ }
+
+ return (audio_fd > 0);
+}
+
+inline void audioFlush() {
+ if (ioctl(audio_fd, SNDCTL_DSP_RESET, 0) == -1)
+ perror("Unable to reset audio device\n");
+}
+
+/*
+ should close the audio device and perform any special shutdown
+*/
+void audioClose() {
+ audioFlush();
+ if (close(audio_fd) < 0) {
+ perror("error close audiodevice:");
+ }
+}
+
+
+void audioInit(int sampleSize,int frequency, int stereo, int sign, int big) {
+ if( sign == 0 )
+ {
+ fprintf(stderr,
+ "%s, %d: expecting signed audio data, "
+ "initialized unsigned (ignored)\n",
+ __FILE__, __LINE__ );
+ }
+ if( big != 0 )
+ {
+ fprintf(stderr,
+ "%s, %d: expecting little endian audio data, "
+ "initialized big endian (ignored)\n",
+ __FILE__, __LINE__ );
+ }
+
+ int play_format=AFMT_S16_LE;
+
+ if (sampleSize == 8) {
+ play_format=AFMT_S8;
+ }
+ ioctl(audio_fd,SNDCTL_DSP_RESET,NULL);
+
+ if (ioctl(audio_fd, SNDCTL_DSP_SETFMT,&play_format) < 0) {
+ perror("Unable to set required audio format\n");
+ }
+
+ /* Set 1 or 2 channels */
+ stereo=(stereo ? 1 : 0);
+
+ if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) < 0) {
+ perror("Unable to set stereo/mono\n");
+ exit(0);
+ }
+
+ /* Set the output frequency */
+ if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &frequency) < 0) {
+ perror("Unable to set frequency");
+ exit(0);
+ }
+
+ if (ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &AUSIZ) == -1) {
+ perror("Unable to get fragment size\n");
+ exit(0);
+ }
+}
+
+
+int getAudioBufferSize() {
+ struct audio_buf_info buf_info;
+ int buf=1024*65;
+ if (ioctl(audio_fd,SNDCTL_DSP_GETOSPACE,&buf_info) == -1) {
+ perror("ioctl getAudioBufferSize using default");
+ } else {
+ buf=buf_info.bytes;
+ }
+ return buf;
+}
+
+
+int mixerOpen() {
+ int supportedMixers;
+
+ if ((mixer_fd=open("/dev/mixer",O_RDWR)) == -1) {
+ perror("Unable to open mixer device");
+ }
+
+ // Ok here something important if your programm forks:
+ if (mixer_fd > 0) {
+ if (fcntl(mixer_fd,F_SETFD,true) < 0) {
+ perror("fcntl socket");exit(1);
+ }
+ }
+
+ if (ioctl(mixer_fd, SOUND_MIXER_READ_DEVMASK, &supportedMixers) == -1){
+ perror("Unable to get mixer info assuming master volume");
+ volumeIoctl=SOUND_MIXER_WRITE_VOLUME;
+ } else {
+ if ((supportedMixers & SOUND_MASK_PCM) != 0)
+ volumeIoctl=SOUND_MIXER_WRITE_PCM;
+ else
+ volumeIoctl=0;
+ }
+
+ return (mixer_fd > 0);
+}
+
+
+void mixerClose() {
+ if (mixer_fd != -1) {
+ close(mixer_fd);
+ }
+}
+
+/*
+ only code this if your system can change the volume while
+ playing
+*/
+void mixerSetVolume(int leftVolume,int rightVolume) {
+ int volume;
+
+ volume=leftVolume+(rightVolume<<8);
+ if ((mixer_fd != -1) && (volumeIoctl!=0)) {
+ if (ioctl(mixer_fd, volumeIoctl, &volume) < 0) {
+ perror("Unable to set sound volume");
+ }
+ }
+}
+
+
+
+int audioWrite(char *buffer, int count) {
+ return(write(audio_fd,buffer,count));
+}
+
+
+int getAudioFd() {
+ return(audio_fd);
+}
diff --git a/mpeglib/lib/util/audio/audioIO_SDL.cpp b/mpeglib/lib/util/audio/audioIO_SDL.cpp
new file mode 100644
index 00000000..782fa388
--- /dev/null
+++ b/mpeglib/lib/util/audio/audioIO_SDL.cpp
@@ -0,0 +1,164 @@
+/*
+ audio wrapper for SDL
+ 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 "../../input/bufferInputStream.h"
+#include <assert.h>
+#include <iostream.h>
+#if defined WIN32
+#include <SDL.h>
+#include <SDL_audio.h>
+#else
+#include <SDL/SDL.h>
+#include <SDL/SDL_audio.h>
+#endif
+
+//static SDL_AudioSpec actual;
+static BufferInputStream* audioRing;
+static TimeStamp* dummy;
+static int lOpen=false;
+
+
+
+int audioConstruct() {
+ cout << "audioConstruct ********* SDL"<<endl;
+ if ( SDL_Init(SDL_INIT_AUDIO) < 0 ) {
+ fprintf(stderr, "Warning: Couldn't init SDL audio: %s\n",
+ SDL_GetError());
+ exit(0);
+ }
+ atexit(SDL_Quit);
+ audioRing=new BufferInputStream(1024*65,1024*8,"audioSDL");
+ audioRing->open("audioSDL");
+ dummy=new TimeStamp();
+ lOpen=false;
+ return true;
+}
+
+
+void audioDestruct() {
+ delete audioRing;
+ delete dummy;
+}
+
+
+
+
+int audioOpen() {
+ return true;
+}
+
+
+void audioClose() {
+ lOpen=false;
+ SDL_CloseAudio();
+}
+
+
+void audioCallback(void *, Uint8 *stream, int len) {
+ char* startPtr;
+ TimeStamp* start;
+ int bytePos;
+
+ int read=audioRing->readRemote(&startPtr,len);
+ SDL_MixAudio(stream, (Uint8*) startPtr, read, SDL_MIX_MAXVOLUME);
+
+ audioRing->forwardReadPtr(read);
+ // dequeue time stamps
+ bytePos=audioRing->getBytePosition();
+ start=audioRing->getTimeStamp(bytePos);
+
+}
+
+
+
+void audioInit(int sampleSize,int frequency, int stereo, int sign, int big) {
+ if( sign == 0 )
+ {
+ fprintf(stderr,
+ "%s, %d: expecting signed audio data, "
+ "initialized unsigned (ignored)\n",
+ __FILE__, __LINE__ );
+ }
+ if( big != 0 )
+ {
+ fprintf(stderr,
+ "%s, %d: expecting little endian audio data, "
+ "initialized big endian (ignored)\n",
+ __FILE__, __LINE__ );
+ }
+
+ cout << "SDL audioInit: "
+ << " sampleSize:"<<sampleSize
+ << " frequency:"<<frequency
+ << " stereo:"<<stereo<<endl;
+ if (lOpen==true) {
+ cout << "SDL is buggy, because open != init -> return"<<endl;
+ return;
+ }
+ lOpen=true;
+ SDL_AudioSpec wanted;
+ //SDL_AudioSpec actual;
+ if (sampleSize == 16) {
+ wanted.format= AUDIO_S16LSB;
+ } else {
+ wanted.format= AUDIO_S8;
+ }
+
+ wanted.freq=frequency;
+ wanted.channels=stereo+1;
+ wanted.samples = 1024;
+ wanted.callback = audioCallback;
+ wanted.userdata = NULL;
+
+ int err=SDL_OpenAudio(&wanted, NULL);
+ if (err != 0) {
+ cout << "SDL_OpenAudio not ok"<<endl;
+ cout << "error is:"<<SDL_GetError()<<endl;
+ exit(0);
+ }
+ SDL_PauseAudio(0);
+
+}
+
+
+int mixerOpen() {
+ return true;
+}
+
+
+void mixerClose() {
+}
+
+
+void mixerSetVolume(int volumeLeft,int volumeRight) {
+ cout << "volumeLeft:"<<volumeLeft
+ << " volumeRight:"<<volumeRight<<endl;
+}
+
+
+int audioWrite(char *buffer, int count) {
+
+ audioRing->write(buffer,count,dummy);
+
+
+ return count;
+}
+
+
+int getAudioFd() {
+ return false;
+}
+
+
+int getAudioBufferSize() {
+ int buf=1024*65;
+ return buf;
+}
diff --git a/mpeglib/lib/util/audio/audioIO_SunOS.cpp b/mpeglib/lib/util/audio/audioIO_SunOS.cpp
new file mode 100644
index 00000000..4e9958a1
--- /dev/null
+++ b/mpeglib/lib/util/audio/audioIO_SunOS.cpp
@@ -0,0 +1,167 @@
+/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
+
+ Origional code by: tomislav uzelac
+ Modified by:
+ * Andrew Richards - moved code from audio.c
+ * Jim Crumley - ported some code from other audioIO_'s
+
+ */
+
+#include <sys/types.h>
+#include <sys/stropts.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/audioio.h>
+#include "audioIO.h"
+#include <iostream.h>
+
+/* declare these static to effectively isolate the audio device */
+
+static int audio_fd;
+static audio_info_t auinfo;
+
+
+int audioConstruct(){
+ audio_fd=-1;
+ return true;
+}
+
+void audioDestruct() {
+
+}
+
+
+/* audioOpen() */
+/* should open the audio device and perform any special initialization */
+/* returns the file descriptior of the audio device */
+
+int audioOpen() {
+ AUDIO_INITINFO(&auinfo);
+
+ if ((audio_fd = open("/dev/audio",O_RDWR))==-1) {
+ perror("unable to open the audio device");
+ }
+ // Ok here something important if your programm forks:
+ if (audio_fd > 0) {
+ if (fcntl(audio_fd,F_SETFD,true) < 0) {
+ perror("fcntl socket");exit(1);
+ }
+ }
+
+ DB(audio, msg("Audio device opened on %d\n",audio_fd) );
+ return (audio_fd > 0);
+}
+
+/* audioFlush() */
+/* should flush the audio device */
+
+inline void audioFlush() {
+ DB(audio, msg("audio: flush %d\n",audio_fd) );
+}
+
+
+/* audioClose() */
+/* should close the audio device and perform any special shutdown */
+
+void audioClose() {
+ close(audio_fd);
+}
+
+
+/**
+ Audio init assumes that the audiodevice is open. It initializes
+ it to the given values
+*/
+
+void audioInit(int sampleSize ,int frequency, int stereo,int sign, int big){
+
+ if (ioctl(audio_fd,AUDIO_GETINFO,&auinfo)<0)
+ perror("Unable to get audio info");
+
+ auinfo.play.precision=sampleSize;
+ auinfo.play.encoding=AUDIO_ENCODING_LINEAR;
+ auinfo.play.channels=(stereo ? 2 : 1);
+ DB(audio, msg("setting sample rate to %d Hz",frequency) );
+ auinfo.play.sample_rate=frequency;
+ if (ioctl(audio_fd,AUDIO_SETINFO,&auinfo)<0)
+ perror("Unable to set audio info");
+
+}
+
+/*
+ only code this if your system can change the volume while
+ playing
+*/
+
+
+int getAudioBufferSize() {
+ int buf;
+ if (ioctl(audio_fd,AUDIO_GETINFO,&auinfo) == -1) {
+ perror("ioctl getAudioBufferSize using default");
+ buf=1024*65;
+ } else {
+ buf=auinfo.play.buffer_size;
+ }
+ return buf;
+}
+
+
+void mixerSetVolume(int leftVolume,int rightVolume) {
+ int volume;
+
+ volume=(leftVolume+rightVolume)/2;
+ auinfo.play.gain=(volume*255)/100;
+
+ // now normalize to values 0...32
+ leftVolume=(32*leftVolume)/100;
+ rightVolume=(32*rightVolume)/100;
+
+ // eg : leftVolume=32, rightVolume=32 => balance=32
+ // eg : leftVolume=0, rightVolume=32 => balance=64
+ // eg : leftVolume=32, rightVolume=0 => balance=0
+
+ //cout << "leftVolume:"<<leftVolume<<endl;
+ //cout << "rightVolume:"<<rightVolume<<endl;
+ int balance=leftVolume-rightVolume+32;
+ //cout << "balance:"<<balance<<endl;
+ //someone should fix the volume on solaris
+ balance=0;
+
+ auinfo.play.balance=(uchar_t)balance;
+ if (ioctl(audio_fd,AUDIO_SETINFO,&auinfo)<0)
+ perror("Unable to set sound volume");
+}
+
+
+
+
+int mixerOpen() {
+ return true;
+}
+
+void mixerClose() {
+}
+
+
+
+
+/* audioWrite */
+/* writes count bytes from buffer to the audio device */
+/* returns the number of bytes actually written */
+
+int audioWrite(char *buffer, int count)
+{
+ return(write(audio_fd,buffer,count));
+}
+
+/* Let buffer.c have the audio descriptor so it can select on it. This means */
+/* that the program is dependent on an file descriptor to work. Should really */
+/* move the select's etc (with inlines of course) in here so that this is the */
+/* ONLY file which has hardware dependent audio stuff in it */
+
+int
+getAudioFd()
+{
+ return(audio_fd);
+}
diff --git a/mpeglib/lib/util/audio/dspWrapper.cpp b/mpeglib/lib/util/audio/dspWrapper.cpp
new file mode 100644
index 00000000..cd9afa57
--- /dev/null
+++ b/mpeglib/lib/util/audio/dspWrapper.cpp
@@ -0,0 +1,193 @@
+/*
+ a wrapper for the audioDevice.
+ Copyright (C) 1998 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 "dspWrapper.h"
+#include "audioIO.h"
+
+
+#include "../../frame/pcmFrame.h"
+#include "../../frame/floatFrame.h"
+
+#include <iostream>
+
+using namespace std;
+
+DSPWrapper::DSPWrapper() {
+ currentFormat=new PCMFrame(0);
+ lopenDevice=false;
+ lopenMixer=false;
+
+ audioConstruct();
+}
+
+DSPWrapper::~DSPWrapper() {
+ if (lopenDevice) {
+ audioClose();
+ }
+ if (lopenMixer) {
+ mixerClose();
+ }
+ audioDestruct();
+ delete currentFormat;
+}
+
+
+int DSPWrapper::isOpenDevice() {
+ return lopenDevice;
+}
+
+int DSPWrapper::openDevice() {
+ if (lopenDevice==true) {
+ return true;
+ }
+ lopenDevice=audioOpen();
+ return lopenDevice;
+}
+
+int DSPWrapper::closeDevice() {
+ if (isOpenDevice() == true) {
+ audioClose();
+ currentFormat->setFrameFormat(-1,-1);
+ lopenDevice=false;
+ }
+ return true;
+}
+
+
+int DSPWrapper::isOpenMixer() {
+ return lopenMixer;
+}
+
+
+int DSPWrapper::getAudioBufferSize() {
+ return ::getAudioBufferSize();
+}
+
+
+int DSPWrapper::openMixer() {
+ lopenMixer=mixerOpen();
+ return lopenMixer;
+}
+
+int DSPWrapper::closeMixer() {
+ if (isOpenMixer() == true) {
+ mixerClose();
+ lopenMixer=false;
+ }
+ return true;
+}
+
+
+int DSPWrapper::audioPlay(char *buf, int len) {
+ return audioWrite(buf,len);
+}
+
+int DSPWrapper::audioSetup(int stereo,int sampleSize,int lSigned,
+ int lBigEndian,int freq) {
+
+
+ if (isOpenDevice()==false) {
+ cout << "device not open"<<endl;
+ exit(-1);
+ }
+ /*
+ cout << "sampleSize:"<<sampleSize<<endl;
+ cout << "freq:"<<freq<<endl;
+ cout << "stereo:"<<stereo<<endl;
+ cout << "lSigned:"<<lSigned<<endl;
+ cout << "lBigEndian:"<<lBigEndian<<endl;
+ */
+ audioInit(sampleSize,freq,stereo,lSigned,lBigEndian);
+ if (currentFormat->getSampleSize() != sampleSize) {
+ cout << "FIXME: pcmFrame with sampleSize:"<<sampleSize<<endl;
+ }
+ currentFormat->setFrameFormat(stereo,freq);
+ return true;
+}
+
+int DSPWrapper::audioSetup(AudioFrame* audioFrame) {
+ if (audioFrame == NULL) {
+ cout << "audioFrame NULL: DSPWrapper:audioSetup"<<endl;
+ exit(0);
+ }
+ if(audioFrame->isFormatEqual(currentFormat)==false) {
+ audioSetup(audioFrame->getStereo(),audioFrame->getSampleSize(),
+ audioFrame->getSigned(),audioFrame->getBigEndian(),
+ audioFrame->getFrequenceHZ());
+ }
+ return true;
+}
+
+
+int DSPWrapper::audioPlay(PCMFrame* pcmFrame) {
+ if (pcmFrame == NULL) {
+ cout << "pcmFrame NULL: DSPWrapper:audioPlay"<<endl;
+ exit(0);
+ }
+ if(pcmFrame->isFormatEqual(currentFormat)==false) {
+ audioSetup(pcmFrame->getStereo(),pcmFrame->getSampleSize(),
+ pcmFrame->getSigned(),pcmFrame->getBigEndian(),
+ pcmFrame->getFrequenceHZ());
+ }
+ int len=pcmFrame->getLen()*2;
+ int played=audioPlay((char*)pcmFrame->getData(),len);
+ return (len == played);
+}
+
+
+//
+// Misuse our internal currentFormat for the float->int conversion.
+//
+
+int DSPWrapper::audioPlay(FloatFrame* floatFrame) {
+ if (floatFrame == NULL) {
+ cout << "floatFrame NULL: DSPWrapper:audioPlay"<<endl;
+ exit(0);
+ }
+ if(floatFrame->isFormatEqual(currentFormat)==false) {
+ audioSetup(floatFrame->getStereo(),floatFrame->getSampleSize(),
+ floatFrame->getSigned(),floatFrame->getBigEndian(),
+ floatFrame->getFrequenceHZ());
+ }
+
+ int tmpLen=currentFormat->getLen();
+ if (tmpLen < floatFrame->getLen()) {
+ delete currentFormat;
+ currentFormat=new PCMFrame(floatFrame->getLen());
+ floatFrame->copyFormat(currentFormat);
+ }
+ currentFormat->clearrawdata();
+ currentFormat->putFloatData(floatFrame->getData(),floatFrame->getLen());
+ return audioPlay(currentFormat);
+}
+
+void DSPWrapper::audioFlush() {
+ closeDevice();
+}
+
+
+void DSPWrapper::setVolume(float leftPercent,float rightPercent) {
+ if (isOpenMixer()) {
+ mixerSetVolume((int)leftPercent,(int)rightPercent);
+ } else {
+ cout << "cannot set Mixer settings:not open!"<<endl;
+ }
+}
+
+
+void DSPWrapper::print() {
+ cout<<"lopenDevice:"<<lopenDevice<<endl;
+ cout<<"lopenMixer:"<<lopenMixer<<endl;
+ currentFormat->print("currentFormat");
+
+}
diff --git a/mpeglib/lib/util/audio/dspWrapper.h b/mpeglib/lib/util/audio/dspWrapper.h
new file mode 100644
index 00000000..f323096d
--- /dev/null
+++ b/mpeglib/lib/util/audio/dspWrapper.h
@@ -0,0 +1,75 @@
+/*
+ a wrapper for the audioDevice.
+ Copyright (C) 1998 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 _DSPWRAPPER_H
+#define _DSPWRAPPER_H
+
+class AudioFrame;
+class PCMFrame;
+class FloatFrame;
+#include <kdemacros.h>
+
+/**
+ This class wraps the platform specific /dev/dsp implementation.
+ The only unusal thing is, that it supports each order of
+ init/open.
+ i) you can first init the device and the open
+ ii) you can first open the device and the init it
+ The implementation takes care that the calls are forwarded
+ in the right order to the /dev/dsp implementation.
+ (means: before the init it, we need to open it)
+ But a caller can do it in both orders.
+*/
+
+class KDE_EXPORT DSPWrapper {
+
+ int lopenDevice;
+ int lopenMixer;
+ PCMFrame* currentFormat;
+
+
+ public:
+ DSPWrapper();
+ ~DSPWrapper();
+
+ int openDevice();
+ int closeDevice();
+ int isOpenDevice();
+
+ int openMixer();
+ int closeMixer();
+ int isOpenMixer();
+
+ int getAudioBufferSize();
+ void setVolume(float leftPercent,float rightPercent);
+
+ int audioSetup(int stereo,int sampleSize,int lSigned,
+ int lBigEndian,int freq);
+ int audioSetup(AudioFrame* audioFrame);
+
+ int audioPlay(char *buffer, int size);
+ int audioPlay(PCMFrame* pcmFrame);
+ int audioPlay(FloatFrame* floatFrame);
+ void audioFlush();
+
+ int isEqual(int samplesize,int speed,int stereo,int lSigned,int lBigEndian);
+ int write(char* buf,int len);
+ void print();
+};
+
+#endif
+
+
+
+
diff --git a/mpeglib/lib/util/dynBuffer.cpp b/mpeglib/lib/util/dynBuffer.cpp
new file mode 100644
index 00000000..c93d5381
--- /dev/null
+++ b/mpeglib/lib/util/dynBuffer.cpp
@@ -0,0 +1,166 @@
+/*
+ This class implements a dynamic string buffer
+ Copyright (C) 1998 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 "dynBuffer.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+DynBuffer::DynBuffer(int size) {
+ nSize=size;
+ msg=(char*) malloc(sizeof(char)*(nSize+1));
+ msg[nSize]='\0';
+ clear();
+
+}
+
+
+DynBuffer::~DynBuffer() {
+ free (msg);
+}
+
+
+void DynBuffer::clear() {
+ msg[0]='\0';
+}
+
+void DynBuffer::append(int value) {
+ DynBuffer buf(30);
+ sprintf(buf.getData(),"%d",value);
+ append(buf.getData());
+}
+
+
+
+
+void DynBuffer::append(char* appendMsg) {
+ if (appendMsg == msg) {
+ cout << "cannot append to self"<<endl;
+ exit(0);
+ }
+ char* appendPos=getAppendPos();
+ int nlen=strlen(appendMsg);
+ if (appendPos == NULL) return;
+
+ append(appendMsg,nlen);
+}
+
+
+void DynBuffer::append(const char* appendMsg) {
+ append((char*)appendMsg);
+}
+
+
+void DynBuffer::append(char* buffer,int buflen) {
+ int nlen=len();
+ int nBedarf;
+ if (buffer == msg) {
+ cout << "cannot append to self"<<endl;
+ exit(0);
+ }
+ if (buflen+nlen <= nSize) {
+ char* appendPos=getAppendPos();
+ strncpy(appendPos,buffer,buflen);
+ appendPos[buflen]='\0';
+ return;
+ }
+ nBedarf=(nlen+buflen)-nSize;
+ grow(nBedarf);
+ append(buffer,buflen);
+}
+
+char* DynBuffer::getAppendPos() {
+ int i;
+ // this Array has nSize+1 entries!
+ // and it *is* granted that msg[nSize]=0; (think so)
+ for (i=0;i<=nSize;i++) {
+ if (msg[i] == '\0') return &(msg[i]);
+ }
+ // should never reach this point
+ return NULL;
+}
+
+
+void DynBuffer::setData(char* msg) {
+ if (strlen(msg) == 0) {
+ clear();
+ return;
+ }
+ clear();
+ append(msg);
+}
+
+char* DynBuffer::getData() {
+ return msg;
+}
+
+
+int DynBuffer::len() {
+ return strlen(msg);
+}
+
+int DynBuffer::getSize() {
+ return nSize;
+}
+
+void DynBuffer::grow(int size) {
+ int i;
+ int newSize=nSize+size;
+ char* tmp=(char*) malloc(sizeof(char)*(newSize+1));
+ tmp[newSize]='\0';
+ for(i=0;i<=nSize;i++) {
+ tmp[i]=msg[i];
+ }
+
+ nSize=newSize;
+ free(msg);
+ msg=tmp;
+
+}
+
+
+int DynBuffer::find(char zeichen) {
+ int i;
+ int nlen=len();
+ for(i=0;i<nlen;i++) {
+ if (msg[i] == zeichen) return i;
+ }
+ return -1;
+}
+
+
+
+void DynBuffer::forward(int bytes) {
+ int i;
+ int aktPos;
+ int nlen=len();
+ if (bytes > nlen) {
+ bytes=nlen;
+ }
+ i=0;
+ aktPos=bytes;
+ while(aktPos <= nlen) {
+ msg[i]=msg[aktPos];
+ i++;
+ aktPos++;
+ }
+}
+
+
+
+void DynBuffer::print() {
+ printf("DynBuffer:%s\n",msg);
+}
diff --git a/mpeglib/lib/util/dynBuffer.h b/mpeglib/lib/util/dynBuffer.h
new file mode 100644
index 00000000..7ba99d42
--- /dev/null
+++ b/mpeglib/lib/util/dynBuffer.h
@@ -0,0 +1,63 @@
+/*
+ This class implements a static string buffer
+ Copyright (C) 1998 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 __DYNBUFFER_H
+#define __DYNBUFFER_H
+
+
+extern "C" {
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+ }
+
+class DynBuffer {
+
+ char* msg;
+ int nSize;
+
+ public:
+ DynBuffer(int size);
+ ~DynBuffer();
+
+ void clear();
+ void append(int value); // appends values as string
+ void append(char* msg);
+ void append(const char* msg);
+
+ void append(char* buffer,int buflen);
+
+ int find(char zeichen);
+ int len();
+
+ void setData(char* msg);
+ char* getData();
+
+ int getSize();
+ void grow(int size);
+
+ void forward(int bytes);
+ void print();
+ private:
+ char* getAppendPos();
+ void read(FILE stream);
+
+};
+
+
+#endif
+
+
+
diff --git a/mpeglib/lib/util/file/Makefile.am b/mpeglib/lib/util/file/Makefile.am
new file mode 100644
index 00000000..96b16fff
--- /dev/null
+++ b/mpeglib/lib/util/file/Makefile.am
@@ -0,0 +1,25 @@
+# libsplay - Makefile.am
+
+
+INCLUDES = $(all_includes)
+
+noinst_LTLIBRARIES = libsimplefile.la
+
+noinst_HEADERS = fileAccess.h
+
+kmpgincludedir = $(includedir)/$(THIS_LIB_NAME)/util/file
+
+kmpginclude_HEADERS = fileAccess.h
+
+
+libsimplefile_la_SOURCES = fileAccess.cpp
+
+
+
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/util/file/fileAccess.cpp b/mpeglib/lib/util/file/fileAccess.cpp
new file mode 100644
index 00000000..8eab864f
--- /dev/null
+++ b/mpeglib/lib/util/file/fileAccess.cpp
@@ -0,0 +1,95 @@
+/*
+ simple file access interface.
+ 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 "fileAccess.h"
+
+
+FileAccess::FileAccess() {
+ file=NULL;
+ length=0;
+}
+
+
+FileAccess::~FileAccess() {
+ close();
+}
+
+
+int FileAccess::open(const char* path) {
+ close();
+ file=fopen(path,"rb");
+ length=calcByteLength();
+ return (file != NULL);
+}
+
+
+void FileAccess::close() {
+ if (file != NULL) {
+ fclose(file);
+ file=NULL;
+ length=0;
+ }
+}
+
+
+int FileAccess::read(char* dest,int len) {
+ int back=0;
+ if (file != NULL) {
+ back=fread(dest,1,len,file);
+ } else {
+ printf("FileAccess::read not open\n");
+ }
+ return back;
+}
+
+int FileAccess::eof() {
+ int back=true;
+ if (file != NULL) {
+ back=feof(file);
+ }
+ return back;
+}
+
+
+int FileAccess::seek(long pos) {
+ if (file == NULL) {
+ return -1;
+ }
+ return fseek(file,pos,SEEK_SET);
+}
+
+
+long FileAccess::getBytePosition() {
+ if (file == NULL) {
+ return 0;
+ }
+ return ftell(file);
+}
+
+
+long FileAccess::getByteLength() {
+ return length;
+}
+
+long FileAccess::calcByteLength() {
+ if (file == NULL) {
+ return 0;
+ }
+ long pos=getBytePosition();
+ fseek(file,0,SEEK_END);
+ long back=getBytePosition();
+ fseek(file,pos,SEEK_SET);
+ return back;
+}
+
diff --git a/mpeglib/lib/util/file/fileAccess.h b/mpeglib/lib/util/file/fileAccess.h
new file mode 100644
index 00000000..d9bf9e2e
--- /dev/null
+++ b/mpeglib/lib/util/file/fileAccess.h
@@ -0,0 +1,46 @@
+/*
+ simple file access interface.
+ 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 __FILEACCESS_H
+#define __FILEACCESS_H
+
+
+#include "stdio.h"
+
+/**
+ Extension to the normal "read" function.
+ This interface is useful for the AudioInfo.
+*/
+
+class FileAccess {
+
+ FILE* file;
+ long length;
+
+ public:
+ FileAccess();
+ virtual ~FileAccess();
+
+ virtual int open(const char* file);
+ virtual void close();
+ virtual int read(char* dest,int len);
+ virtual int eof();
+ virtual int seek(long pos);
+ virtual long getBytePosition();
+ virtual long getByteLength();
+
+ private:
+ long calcByteLength();
+
+};
+#endif
+
diff --git a/mpeglib/lib/util/mmx/Makefile.am b/mpeglib/lib/util/mmx/Makefile.am
new file mode 100644
index 00000000..ce8875e0
--- /dev/null
+++ b/mpeglib/lib/util/mmx/Makefile.am
@@ -0,0 +1,46 @@
+# ---- @OS_TYPE@/@ARCH_TYPE@ ----
+
+# For cpu_accel compile we cannot have ansi
+# (I dont have debugged why)
+
+INCLUDES = $(all_includes)
+
+noinst_LTLIBRARIES = libmmx.la
+noinst_HEADERS =
+
+kmpgincludedir = $(includedir)/$(THIS_LIB_NAME)/util/mmx
+
+kmpginclude_HEADERS = mmx.h mmx_asm.h mm_accel.h
+
+libmmx_la_SOURCES = cpu_accel.c mmx.c
+
+AM_ASFLAGS = $(DEFS) $(DEFAULT_INCLUDES) $(all_includes)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/util/mmx/attribute.h b/mpeglib/lib/util/mmx/attribute.h
new file mode 100644
index 00000000..4dfd3e1e
--- /dev/null
+++ b/mpeglib/lib/util/mmx/attribute.h
@@ -0,0 +1,33 @@
+/*
+ align attribut definition (g++)
+ 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 __ATTRIBUTE_H
+#define __ATTRIBUTE_H
+
+
+
+#include "vidi/vidi_config.h"
+
+
+/* use gcc attribs to align critical data structures */
+
+#ifdef ATTRIBUTE_ALIGNED_MAX
+#define ATTR_ALIGN(align) __attribute__ \
+ ((__aligned__ ((ATTRIBUTE_ALIGNED_MAX <align) ? \
+ ATTRIBUTE_ALIGNED_MAX : align)))
+#else
+#define ATTR_ALIGN(align)
+#endif
+
+
+#endif
diff --git a/mpeglib/lib/util/mmx/cpu_accel.c b/mpeglib/lib/util/mmx/cpu_accel.c
new file mode 100644
index 00000000..8f138308
--- /dev/null
+++ b/mpeglib/lib/util/mmx/cpu_accel.c
@@ -0,0 +1,162 @@
+/*
+ * cpu_accel.c
+ * Copyright (C) 2000-2001 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
+ * See http://libmpeg2.sourceforge.net/ for updates.
+ *
+ * mpeg2dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mpeg2dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+
+#if defined(MMX_SUPPORT) || defined(INTEL)
+#define ARCH_X86 1
+#endif
+
+#include <inttypes.h>
+
+#include "mm_accel.h"
+
+#ifdef ARCH_X86
+static uint32_t arch_accel (void)
+{
+ uint32_t eax, ebx, ecx, edx;
+ int AMD;
+ uint32_t caps;
+
+#ifndef PIC
+#define cpuid(op,eax,ebx,ecx,edx) \
+ __asm__ ("cpuid" \
+ : "=a" (eax), \
+ "=b" (ebx), \
+ "=c" (ecx), \
+ "=d" (edx) \
+ : "a" (op) \
+ : "cc")
+#else /* PIC version : save ebx */
+#define cpuid(op,eax,ebx,ecx,edx) \
+ __asm__ ("pushl %%ebx\n\t" \
+ "cpuid\n\t" \
+ "movl %%ebx,%1\n\t" \
+ "popl %%ebx" \
+ : "=a" (eax), \
+ "=r" (ebx), \
+ "=c" (ecx), \
+ "=d" (edx) \
+ : "a" (op) \
+ : "cc")
+#endif
+
+ __asm__ ("pushfl\n\t"
+ "pushfl\n\t"
+ "popl %0\n\t"
+ "movl %0,%1\n\t"
+ "xorl $0x200000,%0\n\t"
+ "pushl %0\n\t"
+ "popfl\n\t"
+ "pushfl\n\t"
+ "popl %0\n\t"
+ "popfl"
+ : "=r" (eax),
+ "=r" (ebx)
+ :
+ : "cc");
+
+ if (eax == ebx) /* no cpuid */
+ return 0;
+
+ cpuid (0x00000000, eax, ebx, ecx, edx);
+ if (!eax) /* vendor string only */
+ return 0;
+
+ AMD = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65);
+
+ cpuid (0x00000001, eax, ebx, ecx, edx);
+ if (! (edx & 0x00800000)) /* no MMX */
+ return 0;
+
+ caps = MM_ACCEL_X86_MMX;
+ if (edx & 0x02000000) /* SSE - identical to AMD MMX extensions */
+ caps = MM_ACCEL_X86_MMX | MM_ACCEL_X86_MMXEXT;
+
+ cpuid (0x80000000, eax, ebx, ecx, edx);
+ if (eax < 0x80000001) /* no extended capabilities */
+ return caps;
+
+ cpuid (0x80000001, eax, ebx, ecx, edx);
+
+ if (edx & 0x80000000)
+ caps |= MM_ACCEL_X86_3DNOW;
+
+ if (AMD && (edx & 0x00400000)) /* AMD MMX extensions */
+ caps |= MM_ACCEL_X86_MMXEXT;
+
+ return caps;
+}
+#endif /* ARCH_X86 */
+
+#ifdef ARCH_PPC
+#include <signal.h>
+#include <setjmp.h>
+
+static sigjmp_buf jmpbuf;
+static volatile sig_atomic_t canjump = 0;
+
+static RETSIGTYPE sigill_handler (int sig)
+{
+ if (!canjump) {
+ signal (sig, SIG_DFL);
+ raise (sig);
+ }
+
+ canjump = 0;
+ siglongjmp (jmpbuf, 1);
+}
+
+static uint32_t arch_accel (void)
+{
+ signal (SIGILL, sigill_handler);
+ if (sigsetjmp (jmpbuf, 1)) {
+ signal (SIGILL, SIG_DFL);
+ return 0;
+ }
+
+ canjump = 1;
+
+ __asm__ volatile ("mtspr 256,%0" :: "r" (-1));
+
+ signal (SIGILL, SIG_DFL);
+ return MM_ACCEL_PPC_ALTIVEC;
+}
+#endif /* ARCH_PPC */
+
+uint32_t mm_accel (void)
+{
+#if defined (ARCH_X86) || defined (ARCH_PPC)
+ static int got_accel = 0;
+ static uint32_t accel;
+
+ if (!got_accel) {
+ got_accel = 1;
+ accel = arch_accel ();
+ }
+
+ return accel;
+#else
+ return 0;
+#endif
+}
diff --git a/mpeglib/lib/util/mmx/mm_accel.h b/mpeglib/lib/util/mmx/mm_accel.h
new file mode 100644
index 00000000..e0690804
--- /dev/null
+++ b/mpeglib/lib/util/mmx/mm_accel.h
@@ -0,0 +1,58 @@
+/*
+ * mm_accel.h
+ * Copyright (C) 2000-2001 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
+ * See http://libmpeg2.sourceforge.net/ for updates.
+ *
+ * mpeg2dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mpeg2dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef MM_ACCEL_H
+#define MM_ACCEL_H
+
+#include <inttypes.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+
+/* generic accelerations */
+#define MM_ACCEL_MLIB 0x00000001
+
+/* x86 accelerations */
+#define MM_ACCEL_X86_MMX 0x80000000
+#define MM_ACCEL_X86_3DNOW 0x40000000
+#define MM_ACCEL_X86_MMXEXT 0x20000000
+
+/* powerpc accelerations */
+#define MM_ACCEL_PPC_ALTIVEC 0x80000000
+
+/* detailed SIMD info */
+uint32_t mm_accel (void);
+
+/* true if MMX support */
+int mm_support();
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif
+/* MM_ACCEL_H */
diff --git a/mpeglib/lib/util/mmx/mmx.c b/mpeglib/lib/util/mmx/mmx.c
new file mode 100644
index 00000000..4ac3d6b8
--- /dev/null
+++ b/mpeglib/lib/util/mmx/mmx.c
@@ -0,0 +1,73 @@
+/*
+ wrapper for MMX calls
+ 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 "mmx.h"
+
+static int mmSupport=-1;
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(MMX_SUPPORT) || defined(INTEL)
+#define HAVE_ACCEL
+#endif
+
+
+#ifndef HAVE_ACCEL
+int emms() {
+ printf("urgs! emms() never should happen\n");
+ exit(0);
+}
+
+int mm_support() {
+ return 0;
+}
+
+#endif
+
+
+#ifdef HAVE_ACCEL
+#include <inttypes.h>
+#include "mm_accel.h"
+
+
+
+
+int emms() {
+ __asm__ ("emms");
+ return 1;
+}
+
+
+int mm_support() {
+
+ int val;
+
+ if (mmSupport == -1) {
+
+ val=mm_accel();
+ if (val & MM_ACCEL_X86_MMX) {
+ mmSupport=1;
+ } else {
+ mmSupport=0;
+ }
+
+ }
+ /* Return */
+ return(mmSupport);
+}
+
+
+#endif
diff --git a/mpeglib/lib/util/mmx/mmx.h b/mpeglib/lib/util/mmx/mmx.h
new file mode 100644
index 00000000..c4b8340d
--- /dev/null
+++ b/mpeglib/lib/util/mmx/mmx.h
@@ -0,0 +1,26 @@
+
+
+
+#ifndef __MMX_H
+#define __MMX_H
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+
+extern int emms();
+extern int mm_support();
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif
diff --git a/mpeglib/lib/util/mmx/mmx_asm.h b/mpeglib/lib/util/mmx/mmx_asm.h
new file mode 100644
index 00000000..8717eff5
--- /dev/null
+++ b/mpeglib/lib/util/mmx/mmx_asm.h
@@ -0,0 +1,258 @@
+/*
+ * mmx.h
+ * Copyright (C) 1997-2001 H. Dietz and R. Fisher
+ *
+ * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
+ *
+ * mpeg2dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+/*
+ * The type of an value that fits in an MMX register (note that long
+ * long constant values MUST be suffixed by LL and unsigned long long
+ * values by ULL, lest they be truncated by the compiler)
+ */
+
+#ifndef __MMX_ASM_H
+#define __MMX_ASM_H
+
+#include "attribute.h"
+
+
+typedef union {
+ long long q; /* Quadword (64-bit) value */
+ unsigned long long uq; /* Unsigned Quadword */
+ int d[2]; /* 2 Doubleword (32-bit) values */
+ unsigned int ud[2]; /* 2 Unsigned Doubleword */
+ short w[4]; /* 4 Word (16-bit) values */
+ unsigned short uw[4]; /* 4 Unsigned Word */
+ char b[8]; /* 8 Byte (8-bit) values */
+ unsigned char ub[8]; /* 8 Unsigned Byte */
+ float s[2]; /* Single-precision (32-bit) value */
+} ATTR_ALIGN(8) mmx_t; /* On an 8-byte (64-bit) boundary */
+
+
+#define mmx_i2r(op,imm,reg) \
+ __asm__ __volatile__ (#op " %0, %%" #reg \
+ : /* nothing */ \
+ : "X" (imm) )
+
+#define mmx_m2r(op,mem,reg) \
+ __asm__ __volatile__ (#op " %0, %%" #reg \
+ : /* nothing */ \
+ : "X" (mem))
+
+#define mmx_r2m(op,reg,mem) \
+ __asm__ __volatile__ (#op " %%" #reg ", %0" \
+ : "=X" (mem) \
+ : /* nothing */ )
+
+#define mmx_r2r(op,regs,regd) \
+ __asm__ __volatile__ (#op " %" #regs ", %" #regd)
+
+
+#define emms() __asm__ __volatile__ ("emms")
+
+#define movd_m2r(var,reg) mmx_m2r (movd, var, reg)
+#define movd_r2m(reg,var) mmx_r2m (movd, reg, var)
+#define movd_r2r(regs,regd) mmx_r2r (movd, regs, regd)
+
+#define movq_m2r(var,reg) mmx_m2r (movq, var, reg)
+#define movq_r2m(reg,var) mmx_r2m (movq, reg, var)
+#define movq_r2r(regs,regd) mmx_r2r (movq, regs, regd)
+
+#define packssdw_m2r(var,reg) mmx_m2r (packssdw, var, reg)
+#define packssdw_r2r(regs,regd) mmx_r2r (packssdw, regs, regd)
+#define packsswb_m2r(var,reg) mmx_m2r (packsswb, var, reg)
+#define packsswb_r2r(regs,regd) mmx_r2r (packsswb, regs, regd)
+
+#define packuswb_m2r(var,reg) mmx_m2r (packuswb, var, reg)
+#define packuswb_r2r(regs,regd) mmx_r2r (packuswb, regs, regd)
+
+#define paddb_m2r(var,reg) mmx_m2r (paddb, var, reg)
+#define paddb_r2r(regs,regd) mmx_r2r (paddb, regs, regd)
+#define paddd_m2r(var,reg) mmx_m2r (paddd, var, reg)
+#define paddd_r2r(regs,regd) mmx_r2r (paddd, regs, regd)
+#define paddw_m2r(var,reg) mmx_m2r (paddw, var, reg)
+#define paddw_r2r(regs,regd) mmx_r2r (paddw, regs, regd)
+
+#define paddsb_m2r(var,reg) mmx_m2r (paddsb, var, reg)
+#define paddsb_r2r(regs,regd) mmx_r2r (paddsb, regs, regd)
+#define paddsw_m2r(var,reg) mmx_m2r (paddsw, var, reg)
+#define paddsw_r2r(regs,regd) mmx_r2r (paddsw, regs, regd)
+
+#define paddusb_m2r(var,reg) mmx_m2r (paddusb, var, reg)
+#define paddusb_r2r(regs,regd) mmx_r2r (paddusb, regs, regd)
+#define paddusw_m2r(var,reg) mmx_m2r (paddusw, var, reg)
+#define paddusw_r2r(regs,regd) mmx_r2r (paddusw, regs, regd)
+
+#define pand_m2r(var,reg) mmx_m2r (pand, var, reg)
+#define pand_r2r(regs,regd) mmx_r2r (pand, regs, regd)
+
+#define pandn_m2r(var,reg) mmx_m2r (pandn, var, reg)
+#define pandn_r2r(regs,regd) mmx_r2r (pandn, regs, regd)
+
+#define pcmpeqb_m2r(var,reg) mmx_m2r (pcmpeqb, var, reg)
+#define pcmpeqb_r2r(regs,regd) mmx_r2r (pcmpeqb, regs, regd)
+#define pcmpeqd_m2r(var,reg) mmx_m2r (pcmpeqd, var, reg)
+#define pcmpeqd_r2r(regs,regd) mmx_r2r (pcmpeqd, regs, regd)
+#define pcmpeqw_m2r(var,reg) mmx_m2r (pcmpeqw, var, reg)
+#define pcmpeqw_r2r(regs,regd) mmx_r2r (pcmpeqw, regs, regd)
+
+#define pcmpgtb_m2r(var,reg) mmx_m2r (pcmpgtb, var, reg)
+#define pcmpgtb_r2r(regs,regd) mmx_r2r (pcmpgtb, regs, regd)
+#define pcmpgtd_m2r(var,reg) mmx_m2r (pcmpgtd, var, reg)
+#define pcmpgtd_r2r(regs,regd) mmx_r2r (pcmpgtd, regs, regd)
+#define pcmpgtw_m2r(var,reg) mmx_m2r (pcmpgtw, var, reg)
+#define pcmpgtw_r2r(regs,regd) mmx_r2r (pcmpgtw, regs, regd)
+
+#define pmaddwd_m2r(var,reg) mmx_m2r (pmaddwd, var, reg)
+#define pmaddwd_r2r(regs,regd) mmx_r2r (pmaddwd, regs, regd)
+
+#define pmulhw_m2r(var,reg) mmx_m2r (pmulhw, var, reg)
+#define pmulhw_r2r(regs,regd) mmx_r2r (pmulhw, regs, regd)
+
+#define pmullw_m2r(var,reg) mmx_m2r (pmullw, var, reg)
+#define pmullw_r2r(regs,regd) mmx_r2r (pmullw, regs, regd)
+
+#define por_m2r(var,reg) mmx_m2r (por, var, reg)
+#define por_r2r(regs,regd) mmx_r2r (por, regs, regd)
+
+#define pslld_i2r(imm,reg) mmx_i2r (pslld, imm, reg)
+#define pslld_m2r(var,reg) mmx_m2r (pslld, var, reg)
+#define pslld_r2r(regs,regd) mmx_r2r (pslld, regs, regd)
+#define psllq_i2r(imm,reg) mmx_i2r (psllq, imm, reg)
+#define psllq_m2r(var,reg) mmx_m2r (psllq, var, reg)
+#define psllq_r2r(regs,regd) mmx_r2r (psllq, regs, regd)
+#define psllw_i2r(imm,reg) mmx_i2r (psllw, imm, reg)
+#define psllw_m2r(var,reg) mmx_m2r (psllw, var, reg)
+#define psllw_r2r(regs,regd) mmx_r2r (psllw, regs, regd)
+
+#define psrad_i2r(imm,reg) mmx_i2r (psrad, imm, reg)
+#define psrad_m2r(var,reg) mmx_m2r (psrad, var, reg)
+#define psrad_r2r(regs,regd) mmx_r2r (psrad, regs, regd)
+#define psraw_i2r(imm,reg) mmx_i2r (psraw, imm, reg)
+#define psraw_m2r(var,reg) mmx_m2r (psraw, var, reg)
+#define psraw_r2r(regs,regd) mmx_r2r (psraw, regs, regd)
+
+#define psrld_i2r(imm,reg) mmx_i2r (psrld, imm, reg)
+#define psrld_m2r(var,reg) mmx_m2r (psrld, var, reg)
+#define psrld_r2r(regs,regd) mmx_r2r (psrld, regs, regd)
+#define psrlq_i2r(imm,reg) mmx_i2r (psrlq, imm, reg)
+#define psrlq_m2r(var,reg) mmx_m2r (psrlq, var, reg)
+#define psrlq_r2r(regs,regd) mmx_r2r (psrlq, regs, regd)
+#define psrlw_i2r(imm,reg) mmx_i2r (psrlw, imm, reg)
+#define psrlw_m2r(var,reg) mmx_m2r (psrlw, var, reg)
+#define psrlw_r2r(regs,regd) mmx_r2r (psrlw, regs, regd)
+
+#define psubb_m2r(var,reg) mmx_m2r (psubb, var, reg)
+#define psubb_r2r(regs,regd) mmx_r2r (psubb, regs, regd)
+#define psubd_m2r(var,reg) mmx_m2r (psubd, var, reg)
+#define psubd_r2r(regs,regd) mmx_r2r (psubd, regs, regd)
+#define psubw_m2r(var,reg) mmx_m2r (psubw, var, reg)
+#define psubw_r2r(regs,regd) mmx_r2r (psubw, regs, regd)
+
+#define psubsb_m2r(var,reg) mmx_m2r (psubsb, var, reg)
+#define psubsb_r2r(regs,regd) mmx_r2r (psubsb, regs, regd)
+#define psubsw_m2r(var,reg) mmx_m2r (psubsw, var, reg)
+#define psubsw_r2r(regs,regd) mmx_r2r (psubsw, regs, regd)
+
+#define psubusb_m2r(var,reg) mmx_m2r (psubusb, var, reg)
+#define psubusb_r2r(regs,regd) mmx_r2r (psubusb, regs, regd)
+#define psubusw_m2r(var,reg) mmx_m2r (psubusw, var, reg)
+#define psubusw_r2r(regs,regd) mmx_r2r (psubusw, regs, regd)
+
+#define punpckhbw_m2r(var,reg) mmx_m2r (punpckhbw, var, reg)
+#define punpckhbw_r2r(regs,regd) mmx_r2r (punpckhbw, regs, regd)
+#define punpckhdq_m2r(var,reg) mmx_m2r (punpckhdq, var, reg)
+#define punpckhdq_r2r(regs,regd) mmx_r2r (punpckhdq, regs, regd)
+#define punpckhwd_m2r(var,reg) mmx_m2r (punpckhwd, var, reg)
+#define punpckhwd_r2r(regs,regd) mmx_r2r (punpckhwd, regs, regd)
+
+#define punpcklbw_m2r(var,reg) mmx_m2r (punpcklbw, var, reg)
+#define punpcklbw_r2r(regs,regd) mmx_r2r (punpcklbw, regs, regd)
+#define punpckldq_m2r(var,reg) mmx_m2r (punpckldq, var, reg)
+#define punpckldq_r2r(regs,regd) mmx_r2r (punpckldq, regs, regd)
+#define punpcklwd_m2r(var,reg) mmx_m2r (punpcklwd, var, reg)
+#define punpcklwd_r2r(regs,regd) mmx_r2r (punpcklwd, regs, regd)
+
+#define pxor_m2r(var,reg) mmx_m2r (pxor, var, reg)
+#define pxor_r2r(regs,regd) mmx_r2r (pxor, regs, regd)
+
+
+/* 3DNOW extensions */
+
+#define pavgusb_m2r(var,reg) mmx_m2r (pavgusb, var, reg)
+#define pavgusb_r2r(regs,regd) mmx_r2r (pavgusb, regs, regd)
+
+
+/* AMD MMX extensions - also available in intel SSE */
+
+
+#define mmx_m2ri(op,mem,reg,imm) \
+ __asm__ __volatile__ (#op " %1, %0, %%" #reg \
+ : /* nothing */ \
+ : "X" (mem), "X" (imm))
+#define mmx_r2ri(op,regs,regd,imm) \
+ __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \
+ : /* nothing */ \
+ : "X" (imm) )
+
+#define mmx_fetch(mem,hint) \
+ __asm__ __volatile__ ("prefetch" #hint " %0" \
+ : /* nothing */ \
+ : "X" (mem))
+
+
+#define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg)
+
+#define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var)
+
+#define pavgb_m2r(var,reg) mmx_m2r (pavgb, var, reg)
+#define pavgb_r2r(regs,regd) mmx_r2r (pavgb, regs, regd)
+#define pavgw_m2r(var,reg) mmx_m2r (pavgw, var, reg)
+#define pavgw_r2r(regs,regd) mmx_r2r (pavgw, regs, regd)
+
+#define pextrw_r2r(mmreg,reg,imm) mmx_r2ri (pextrw, mmreg, reg, imm)
+
+#define pinsrw_r2r(reg,mmreg,imm) mmx_r2ri (pinsrw, reg, mmreg, imm)
+
+#define pmaxsw_m2r(var,reg) mmx_m2r (pmaxsw, var, reg)
+#define pmaxsw_r2r(regs,regd) mmx_r2r (pmaxsw, regs, regd)
+
+#define pmaxub_m2r(var,reg) mmx_m2r (pmaxub, var, reg)
+#define pmaxub_r2r(regs,regd) mmx_r2r (pmaxub, regs, regd)
+
+#define pminsw_m2r(var,reg) mmx_m2r (pminsw, var, reg)
+#define pminsw_r2r(regs,regd) mmx_r2r (pminsw, regs, regd)
+
+#define pminub_m2r(var,reg) mmx_m2r (pminub, var, reg)
+#define pminub_r2r(regs,regd) mmx_r2r (pminub, regs, regd)
+
+#define pmovmskb(mmreg,reg) \
+ __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg)
+
+#define pmulhuw_m2r(var,reg) mmx_m2r (pmulhuw, var, reg)
+#define pmulhuw_r2r(regs,regd) mmx_r2r (pmulhuw, regs, regd)
+
+#define prefetcht0(mem) mmx_fetch (mem, t0)
+#define prefetcht1(mem) mmx_fetch (mem, t1)
+#define prefetcht2(mem) mmx_fetch (mem, t2)
+#define prefetchnta(mem) mmx_fetch (mem, nta)
+
+#define psadbw_m2r(var,reg) mmx_m2r (psadbw, var, reg)
+#define psadbw_r2r(regs,regd) mmx_r2r (psadbw, regs, regd)
+
+#define pshufw_m2r(var,reg,imm) mmx_m2ri(pshufw, var, reg, imm)
+#define pshufw_r2r(regs,regd,imm) mmx_r2ri(pshufw, regs, regd, imm)
+
+#define sfence() __asm__ __volatile__ ("sfence\n\t")
+
+
+#endif
+
+
diff --git a/mpeglib/lib/util/render/Makefile.am b/mpeglib/lib/util/render/Makefile.am
new file mode 100644
index 00000000..24bc691f
--- /dev/null
+++ b/mpeglib/lib/util/render/Makefile.am
@@ -0,0 +1,59 @@
+# player - Makefile.am
+
+SUBDIRS = dither dither2YUV x11 sdl
+
+INCLUDES = $(all_includes)
+
+THIS_EXTRALIBS = dither/libdither.la \
+ dither2YUV/libdivxutil_dither.la \
+ x11/libutilx11.la
+
+
+noinst_LTLIBRARIES = libutilrender.la
+
+noinst_HEADERS = imageBase.h \
+ renderMachine.h surface.h
+
+
+kmpgincludedir = $(includedir)/$(THIS_LIB_NAME)/util/render
+
+kmpginclude_HEADERS = yuvPicture.h pictureArray.h
+
+
+libutilrender_la_SOURCES = yuvPicture.cpp imageBase.cpp \
+ renderMachine.cpp surface.cpp \
+ pictureArray.cpp
+
+libutilrender_la_LIBADD = $(THIS_EXTRALIBS)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/util/render/dither/Makefile.am b/mpeglib/lib/util/render/dither/Makefile.am
new file mode 100644
index 00000000..166d5ca3
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/Makefile.am
@@ -0,0 +1,40 @@
+# liboutplugin - Makefile.am
+
+INCLUDES = $(all_includes)
+
+EXTRA_DIST = ditherDef.h ditherMMX.h \
+ ditherer_mmx16.cpp dither32mmx.cpp
+
+noinst_LTLIBRARIES = libdither.la
+
+noinst_HEADERS = ditherWrapper.h \
+ dither8Bit.h colorTable8Bit.h \
+ colorTableHighBit.h dither16Bit.h \
+ dither32Bit.h ditherRGB_flipped.h \
+ ditherRGB.h
+
+libdither_la_SOURCES = ditherWrapper.cpp \
+ dither8Bit.cpp \
+ colorTable8Bit.cpp colorTableHighBit.cpp \
+ dither16Bit.cpp dither32Bit.cpp \
+ ditherRGB_flipped.cpp ditherRGB.cpp \
+ ditherer_mmx16.cpp dither32mmx.cpp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/util/render/dither/colorTable8Bit.cpp b/mpeglib/lib/util/render/dither/colorTable8Bit.cpp
new file mode 100644
index 00000000..57c533de
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/colorTable8Bit.cpp
@@ -0,0 +1,147 @@
+/*
+ colorTables for 8 Bit depth
+ 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 "colorTable8Bit.h"
+
+
+ColorTable8Bit::ColorTable8Bit() {
+
+ lum_values = new int[LUM_RANGE];
+ cr_values = new int[CR_RANGE];
+ cb_values = new int[CB_RANGE];
+
+
+ /* We can exploit cache by allocating contiguous blocks */
+
+ colortab = new TABTYPE[5*256];
+
+ Cr_r_tab = &colortab[0*256];
+ Cr_g_tab = &colortab[1*256];
+ Cb_g_tab = &colortab[2*256];
+ Cb_b_tab = &colortab[3*256];
+ L_tab = &colortab[4*256];
+
+ init8BitColor();
+}
+
+
+ColorTable8Bit::~ColorTable8Bit() {
+ delete lum_values;
+ delete cr_values;
+ delete cb_values;
+ delete colortab;
+}
+
+
+void ColorTable8Bit::init8BitColor() {
+ int i;
+
+
+
+ for (i=0; i<LUM_RANGE; i++) {
+ lum_values[i] = ((i * 256) / (LUM_RANGE)) + (256/(LUM_RANGE*2));
+ L_tab[i] = lum_values[i];
+ if (gammaCorrectFlag) {
+ L_tab[i] = GAMMA_CORRECTION(L_tab[i]);
+ }
+
+ }
+
+
+ for (i=0; i<CR_RANGE; i++) {
+ register double tmp;
+ if (chromaCorrectFlag) {
+ tmp = ((i * 256) / (CR_RANGE)) + (256/(CR_RANGE*2));
+ Cr_r_tab[i]=(TABTYPE) ((0.419/0.299)*CHROMA_CORRECTION128D(tmp-128.0));
+ Cr_g_tab[i]=(TABTYPE) (-(0.299/0.419)*CHROMA_CORRECTION128D(tmp-128.0));
+ cr_values[i] = CHROMA_CORRECTION256(tmp);
+ } else {
+ tmp = ((i * 256) / (CR_RANGE)) + (256/(CR_RANGE*2));
+ Cr_r_tab[i] = (TABTYPE) ((0.419/0.299) * (tmp - 128.0));
+ Cr_g_tab[i] = (TABTYPE) (-(0.299/0.419) * (tmp - 128.0));
+ cr_values[i] = (int) tmp;
+ }
+ }
+
+
+ for (i=0; i<CB_RANGE; i++) {
+ register double tmp;
+ if (chromaCorrectFlag) {
+ tmp = ((i * 256) / (CB_RANGE)) + (256/(CB_RANGE*2));
+ Cb_g_tab[i]=(TABTYPE) (-(0.114/0.331)*CHROMA_CORRECTION128D(tmp-128.0));
+ Cb_b_tab[i]=(TABTYPE) ((0.587/0.331)*CHROMA_CORRECTION128D(tmp-128.0));
+ cb_values[i] = CHROMA_CORRECTION256(tmp);
+ } else {
+ tmp = ((i * 256) / (CB_RANGE)) + (256/(CB_RANGE*2));
+ Cb_g_tab[i] = (TABTYPE) (-(0.114/0.331) * (tmp - 128.0));
+ Cb_b_tab[i] = (TABTYPE) ((0.587/0.331) * (tmp - 128.0));
+ cb_values[i] = (int) tmp;
+ }
+ }
+}
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ConvertColor --
+ *
+ * Given a l, cr, cb tuple, converts it to r,g,b.
+ *
+ * Results:
+ * r,g,b values returned in pointers passed as parameters.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+void ColorTable8Bit::ConvertColor(unsigned int l, unsigned int cr,
+ unsigned int cb, unsigned char* r,
+ unsigned char* g, unsigned char* b) {
+
+ double fl, fr, fg, fb;
+
+ /*
+ * Old method w/o lookup table
+ *
+ * fl = 1.164*(((double) l)-16.0);
+ * fcr = ((double) cr) - 128.0;
+ * fcb = ((double) cb) - 128.0;
+ *
+ * fr = fl + (1.366 * fcr);
+ * fg = fl - (0.700 * fcr) - (0.334 * fcb);
+ * fb = fl + (1.732 * fcb);
+ */
+
+ fl = L_tab[l];
+
+ fr = fl + Cr_r_tab[cr];
+ fg = fl + Cr_g_tab[cr] + Cb_g_tab[cb];
+ fb = fl + Cb_b_tab[cb];
+
+ if (fr < 0.0) fr = 0.0;
+ else if (fr > 255.0) fr = 255.0;
+
+ if (fg < 0.0) fg = 0.0;
+ else if (fg > 255.0) fg = 255.0;
+
+ if (fb < 0.0) fb = 0.0;
+ else if (fb > 255.0) fb = 255.0;
+
+ *r = (unsigned char) fr;
+ *g = (unsigned char) fg;
+ *b = (unsigned char) fb;
+
+}
diff --git a/mpeglib/lib/util/render/dither/colorTable8Bit.h b/mpeglib/lib/util/render/dither/colorTable8Bit.h
new file mode 100644
index 00000000..6d873d1d
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/colorTable8Bit.h
@@ -0,0 +1,57 @@
+/*
+ colorTables for 8 Bit depth
+ 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 __COLORTABLE8BIT_H
+#define __COLORTABLE8BIT_H
+
+#include "ditherDef.h"
+
+
+class ColorTable8Bit {
+
+ // Arrays holding quantized value ranged for lum, cr, and cb.
+ // (used for 8 Bit)
+
+ int* lum_values;
+ int* cr_values;
+ int* cb_values;
+
+
+
+
+ TABTYPE *L_tab;
+ TABTYPE *Cr_r_tab;
+ TABTYPE *Cr_g_tab;
+ TABTYPE *Cb_g_tab;
+ TABTYPE *Cb_b_tab;
+ TABTYPE *colortab;
+
+
+ public:
+ ColorTable8Bit();
+ ~ColorTable8Bit();
+
+ inline int* getLumValues() { return lum_values; }
+ inline int* getCrValues() { return cr_values; }
+ inline int* getCbValues() { return cb_values; }
+
+ void ConvertColor(unsigned int l, unsigned int cr, unsigned int cb,
+ unsigned char* r, unsigned char* g, unsigned char* b);
+
+
+ private:
+ void init8BitColor();
+
+
+};
+#endif
diff --git a/mpeglib/lib/util/render/dither/colorTableHighBit.cpp b/mpeglib/lib/util/render/dither/colorTableHighBit.cpp
new file mode 100644
index 00000000..171f4e97
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/colorTableHighBit.cpp
@@ -0,0 +1,248 @@
+/*
+ colorTables for 16,32 Bit depth
+ 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 "colorTableHighBit.h"
+
+//#define INTERPOLATE
+
+
+/*
+ * Erik Corry's multi-byte dither routines.
+ *
+ * The basic idea is that the Init generates all the necessary tables.
+ * The tables incorporate the information about the layout of pixels
+ * in the XImage, so that it should be able to cope with 15-bit, 16-bit
+ * 24-bit (non-packed) and 32-bit (10-11 bits per color!) screens.
+ * At present it cannot cope with 24-bit packed mode, since this involves
+ * getting down to byte level again. It is assumed that the bits for each
+ * color are contiguous in the longword.
+ *
+ * Writing to memory is done in shorts or ints. (Unfortunately, short is not
+ * very fast on Alpha, so there is room for improvement here). There is no
+ * dither time check for overflow - instead the tables have slack at
+ * each end. This is likely to be faster than an 'if' test as many modern
+ * architectures are really bad at ifs. Potentially, each '&&' causes a
+ * pipeline flush!
+ *
+ * There is no shifting and fixed point arithmetic, as I really doubt you
+ * can see the difference, and it costs. This may be just my bias, since I
+ * heard that Intel is really bad at shifting.
+ */
+
+
+/*
+ * How many 1 bits are there in the PIXVALword.
+ * Low performance, do not call often.
+ */
+static int number_of_bits_set(unsigned PIXVAL a) {
+ if(!a) return 0;
+ if(a & 1) return 1 + number_of_bits_set(a >> 1);
+ return(number_of_bits_set(a >> 1));
+}
+
+
+
+/*
+ * How many 0 bits are there at most significant end of PIXVALword.
+ * Low performance, do not call often.
+ */
+static int free_bits_at_top(unsigned PIXVAL a) {
+ /* assume char is 8 bits */
+ if(!a) return sizeof(unsigned PIXVAL) * 8;
+ /* assume twos complement */
+ if(((PIXVAL)a) < 0l) return 0;
+ return 1 + free_bits_at_top ( a << 1);
+}
+
+/*
+ * How many 0 bits are there at least significant end of PIXVALword.
+ * Low performance, do not call often.
+ */
+static int free_bits_at_bottom(unsigned PIXVAL a) {
+ /* assume char is 8 bits */
+ if(!a) return sizeof(unsigned PIXVAL) * 8;
+ if(((PIXVAL)a) & 1l) return 0;
+ return 1 + free_bits_at_bottom ( a >> 1);
+}
+
+
+
+ColorTableHighBit::ColorTableHighBit(int bpp,unsigned int redMask,
+ unsigned int greenMask,
+ unsigned int blueMask) {
+ this->bpp=bpp;
+ this->redMask=redMask;
+ this->greenMask=greenMask;
+ this->blueMask=blueMask;
+
+ colortab = new TABTYPE[5*256];
+
+ Cr_r_tab = &colortab[0*256];
+ Cr_g_tab = &colortab[1*256];
+ Cb_g_tab = &colortab[2*256];
+ Cb_b_tab = &colortab[3*256];
+ L_tab = &colortab[4*256];
+
+ rgb_2_pix = new PIXVAL [3*768];
+
+ r_2_pix_alloc = &rgb_2_pix[0*768];
+ g_2_pix_alloc = &rgb_2_pix[1*768];
+ b_2_pix_alloc = &rgb_2_pix[2*768];
+
+ initHighColor(bpp>=24,redMask,greenMask,blueMask);
+
+}
+
+
+ColorTableHighBit::~ColorTableHighBit() {
+ delete colortab;
+ delete rgb_2_pix;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * InitColor16Dither --
+ *
+ * To get rid of the multiply and other conversions in color
+ * dither, we use a lookup table.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The lookup tables are initialized.
+ *
+ *--------------------------------------------------------------
+ */
+
+void ColorTableHighBit::initHighColor(int thirty2,unsigned int redMask,
+ unsigned int greenMask,
+ unsigned int blueMask) {
+
+ unsigned PIXVAL red_mask = redMask;
+ unsigned PIXVAL green_mask =greenMask;
+ unsigned PIXVAL blue_mask = blueMask;
+
+ int CR, CB, i;
+
+
+ for (i=0; i<256; i++) {
+ L_tab[i] = i;
+ if (gammaCorrectFlag) {
+ L_tab[i] = (TABTYPE)GAMMA_CORRECTION(i);
+ }
+
+ CB = CR = i;
+
+ if (chromaCorrectFlag) {
+ CB -= 128;
+ CB = CHROMA_CORRECTION128(CB);
+ CR -= 128;
+ CR = CHROMA_CORRECTION128(CR);
+ } else {
+ CB -= 128; CR -= 128;
+ }
+/* was
+ Cr_r_tab[i] = 1.596 * CR;
+ Cr_g_tab[i] = -0.813 * CR;
+ Cb_g_tab[i] = -0.391 * CB;
+ Cb_b_tab[i] = 2.018 * CB;
+ but they were just messed up.
+ Then was (_Video Deymstified_):
+ Cr_r_tab[i] = 1.366 * CR;
+ Cr_g_tab[i] = -0.700 * CR;
+ Cb_g_tab[i] = -0.334 * CB;
+ Cb_b_tab[i] = 1.732 * CB;
+ but really should be:
+ (from ITU-R BT.470-2 System B, G and SMPTE 170M )
+*/
+ Cr_r_tab[i] = (TABTYPE) ( (0.419/0.299) * CR );
+ Cr_g_tab[i] = (TABTYPE) ( -(0.299/0.419) * CR );
+ Cb_g_tab[i] = (TABTYPE) ( -(0.114/0.331) * CB );
+ Cb_b_tab[i] = (TABTYPE) ( (0.587/0.331) * CB );
+
+/*
+ though you could argue for:
+ SMPTE 240M
+ Cr_r_tab[i] = (0.445/0.212) * CR;
+ Cr_g_tab[i] = -(0.212/0.445) * CR;
+ Cb_g_tab[i] = -(0.087/0.384) * CB;
+ Cb_b_tab[i] = (0.701/0.384) * CB;
+ FCC
+ Cr_r_tab[i] = (0.421/0.30) * CR;
+ Cr_g_tab[i] = -(0.30/0.421) * CR;
+ Cb_g_tab[i] = -(0.11/0.331) * CB;
+ Cb_b_tab[i] = (0.59/0.331) * CB;
+ ITU-R BT.709
+ Cr_r_tab[i] = (0.454/0.2125) * CR;
+ Cr_g_tab[i] = -(0.2125/0.454) * CR;
+ Cb_g_tab[i] = -(0.0721/0.386) * CB;
+ Cb_b_tab[i] = (0.7154/0.386) * CB;
+*/
+ }
+
+ /*
+ * Set up entries 0-255 in rgb-to-pixel value tables.
+ */
+ for (i = 0; i < 256; i++) {
+ r_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(red_mask));
+ r_2_pix_alloc[i + 256] <<= free_bits_at_bottom(red_mask);
+ g_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(green_mask));
+ g_2_pix_alloc[i + 256] <<= free_bits_at_bottom(green_mask);
+ b_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(blue_mask));
+ b_2_pix_alloc[i + 256] <<= free_bits_at_bottom(blue_mask);
+ /*
+ * If we have 16-bit output depth, then we double the value
+ * in the top word. This means that we can write out both
+ * pixels in the pixel doubling mode with one op. It is
+ * harmless in the normal case as storing a 32-bit value
+ * through a short pointer will lose the top bits anyway.
+ * A similar optimisation for Alpha for 64 bit has been
+ * prepared for, but is not yet implemented.
+ */
+ if(!thirty2) {
+ r_2_pix_alloc[i + 256] |= (r_2_pix_alloc[i + 256]) << 16;
+ g_2_pix_alloc[i + 256] |= (g_2_pix_alloc[i + 256]) << 16;
+ b_2_pix_alloc[i + 256] |= (b_2_pix_alloc[i + 256]) << 16;
+
+ }
+#ifdef SIXTYFOUR_BIT
+ if(thirty2) {
+
+ r_2_pix_alloc[i + 256] |= (r_2_pix_alloc[i + 256]) << 32;
+ g_2_pix_alloc[i + 256] |= (g_2_pix_alloc[i + 256]) << 32;
+ b_2_pix_alloc[i + 256] |= (b_2_pix_alloc[i + 256]) << 32;
+
+ }
+#endif
+ }
+
+ /*
+ * Spread out the values we have to the rest of the array so that
+ * we do not need to check for overflow.
+ */
+ for (i = 0; i < 256; i++) {
+ r_2_pix_alloc[i] = r_2_pix_alloc[256];
+ r_2_pix_alloc[i+ 512] = r_2_pix_alloc[511];
+ g_2_pix_alloc[i] = g_2_pix_alloc[256];
+ g_2_pix_alloc[i+ 512] = g_2_pix_alloc[511];
+ b_2_pix_alloc[i] = b_2_pix_alloc[256];
+ b_2_pix_alloc[i+ 512] = b_2_pix_alloc[511];
+ }
+
+ r_2_pix = r_2_pix_alloc + 256;
+ g_2_pix = g_2_pix_alloc + 256;
+ b_2_pix = b_2_pix_alloc + 256;
+}
diff --git a/mpeglib/lib/util/render/dither/colorTableHighBit.h b/mpeglib/lib/util/render/dither/colorTableHighBit.h
new file mode 100644
index 00000000..9945414d
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/colorTableHighBit.h
@@ -0,0 +1,73 @@
+/*
+ colorTables for 16,32 Bit depth
+ 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 __COLORTABLEHIGHBIT_H
+#define __COLORTABLEHIGHBIT_H
+
+#include "ditherDef.h"
+
+
+
+
+class ColorTableHighBit {
+
+ TABTYPE *L_tab;
+ TABTYPE *Cr_r_tab;
+ TABTYPE *Cr_g_tab;
+ TABTYPE *Cb_g_tab;
+ TABTYPE *Cb_b_tab;
+ TABTYPE *colortab;
+
+
+ PIXVAL *r_2_pix;
+ PIXVAL *g_2_pix;
+ PIXVAL *b_2_pix;
+ PIXVAL *rgb_2_pix;
+
+ PIXVAL *r_2_pix_alloc;
+ PIXVAL *g_2_pix_alloc;
+ PIXVAL *b_2_pix_alloc;
+
+
+
+ // init stuff
+ int bpp;
+ // colorMask
+ unsigned int redMask;
+ unsigned int greenMask;
+ unsigned int blueMask;
+
+ public:
+ ColorTableHighBit(int bpp,unsigned int redMask,
+ unsigned int greenMask,unsigned int blueMask);
+ ~ColorTableHighBit();
+
+ inline TABTYPE* getL_tab() { return L_tab ; }
+ inline TABTYPE* getCr_r_tab() { return Cr_r_tab ; }
+ inline TABTYPE* getCr_g_tab() { return Cr_g_tab ; }
+ inline TABTYPE* getCb_g_tab() { return Cb_g_tab ; }
+ inline TABTYPE* getCb_b_tab() { return Cb_b_tab ; }
+
+
+ inline PIXVAL* getr_2_pix() { return r_2_pix ; }
+ inline PIXVAL* getg_2_pix() { return g_2_pix ; }
+ inline PIXVAL* getb_2_pix() { return b_2_pix ; }
+
+
+
+ private:
+ void initHighColor(int thirty2,unsigned int redMask,
+ unsigned int greenMask,unsigned int blueMask);
+
+};
+#endif
diff --git a/mpeglib/lib/util/render/dither/dither16Bit.cpp b/mpeglib/lib/util/render/dither/dither16Bit.cpp
new file mode 100644
index 00000000..0a843ee9
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/dither16Bit.cpp
@@ -0,0 +1,300 @@
+/*
+ dither 16 bit depth yuv images
+ 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 "dither16Bit.h"
+
+
+Dither16Bit::Dither16Bit(unsigned int redMask,
+ unsigned int greenMask,unsigned int blueMask) {
+
+
+ colorTableHighBit=new ColorTableHighBit(16,redMask,greenMask,blueMask);
+ L_tab=colorTableHighBit->getL_tab();
+ Cr_r_tab=colorTableHighBit->getCr_r_tab();
+ Cr_g_tab=colorTableHighBit->getCr_g_tab();
+ Cb_g_tab=colorTableHighBit->getCb_g_tab();
+ Cb_b_tab=colorTableHighBit->getCb_b_tab();
+
+ r_2_pix=colorTableHighBit->getr_2_pix();
+ g_2_pix=colorTableHighBit->getg_2_pix();
+ b_2_pix=colorTableHighBit->getb_2_pix();
+
+}
+
+
+Dither16Bit::~Dither16Bit() {
+ delete colorTableHighBit;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Color16DitherImage --
+ *
+ * Converts image into 16 bit color.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void Dither16Bit::ditherImageColor16(unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,
+ unsigned char* out,
+ int rows,
+ int cols,
+ int offset) {
+
+ int L, CR, CB;
+ unsigned short *row1, *row2;
+ unsigned char *lum2;
+ int x, y;
+ int cr_r;
+ int cr_g;
+ int cb_g;
+ int cb_b;
+ int cols_2 = cols/2;
+
+ row1 = (unsigned short *)out;
+ row2=row1+cols_2+cols_2+offset; // start of second row
+
+ offset=2*offset+cols_2+cols_2;
+
+ lum2 = lum + cols_2 + cols_2;
+
+
+ for (y=0; y<rows; y+=2) {
+ for (x=0; x<cols_2; x++) {
+ int R, G, B;
+
+ CR = *cr++;
+ CB = *cb++;
+ cr_r = Cr_r_tab[CR];
+ cr_g = Cr_g_tab[CR];
+ cb_g = Cb_g_tab[CB];
+ cb_b = Cb_b_tab[CB];
+
+ L = L_tab[(int) *lum++];
+
+ R = L + cr_r;
+ G = L + cr_g + cb_g;
+ B = L + cb_b;
+
+ *row1++ = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
+
+
+#ifdef INTERPOLATE
+ if(x != cols_2 - 1) {
+ CR = (CR + *cr) >> 1;
+ CB = (CB + *cb) >> 1;
+ cr_r = Cr_r_tab[CR];
+ cr_g = Cr_g_tab[CR];
+ cb_g = Cb_g_tab[CB];
+ cb_b = Cb_b_tab[CB];
+ }
+#endif
+
+ L = L_tab[(int) *lum++];
+
+ R = L + cr_r;
+ G = L + cr_g + cb_g;
+ B = L + cb_b;
+
+ *row1++ = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
+
+ /*
+ * Now, do second row.
+ */
+#ifdef INTERPOLATE
+ if(y != rows - 2) {
+ CR = (CR + *(cr + cols_2 - 1)) >> 1;
+ CB = (CB + *(cb + cols_2 - 1)) >> 1;
+ cr_r = Cr_r_tab[CR];
+ cr_g = Cr_g_tab[CR];
+ cb_g = Cb_g_tab[CB];
+ cb_b = Cb_b_tab[CB];
+ }
+#endif
+
+ L = L_tab[(int) *lum2++];
+ R = L + cr_r;
+ G = L + cr_g + cb_g;
+ B = L + cb_b;
+
+ *row2++ = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
+
+ L = L_tab[(int) *lum2++];
+ R = L + cr_r;
+ G = L + cr_g + cb_g;
+ B = L + cb_b;
+
+ *row2++ = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
+ }
+ /*
+ * These values are at the start of the next line, (due
+ * to the ++'s above),but they need to be at the start
+ * of the line after that.
+ */
+ lum += cols_2 + cols_2;
+ lum2 += cols_2 + cols_2;
+ row1 += offset;
+ row2 += offset;
+ }
+}
+
+
+/*
+ * Erik Corry's pixel doubling routines for 15/16/24/32 bit screens.
+ */
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Twox2Color16DitherImage --
+ *
+ * Converts image into 16 bit color at double size.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+/*
+ * In this function I make use of a nasty trick. The tables have the lower
+ * 16 bits replicated in the upper 16. This means I can write ints and get
+ * the horisontal doubling for free (almost).
+ */
+
+void Dither16Bit::ditherImageTwox2Color16(unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,
+ unsigned char* out,
+ int rows,
+ int cols,
+ int mod) {
+ int L, CR, CB;
+ unsigned int *row1 = (unsigned int *)out;
+ unsigned int *row2 = row1 + cols + mod/2;
+ unsigned int *row3 = row2 + cols + mod/2;
+ unsigned int *row4 = row3 + cols + mod/2;
+ unsigned char *lum2;
+ int x, y;
+ int cr_r;
+ int cr_g;
+ int cb_g;
+ int cb_b;
+ int cols_2 = cols/2;
+
+ lum2 = lum + cols_2 + cols_2;
+ for (y=0; y<rows; y+=2) {
+ for (x=0; x<cols_2; x++) {
+ int R, G, B;
+ int t;
+
+ CR = *cr++;
+ CB = *cb++;
+ cr_r = Cr_r_tab[CR];
+ cr_g = Cr_g_tab[CR];
+ cb_g = Cb_g_tab[CB];
+ cb_b = Cb_b_tab[CB];
+
+ L = L_tab[(int) *lum++];
+
+ R = L + cr_r;
+ G = L + cr_g + cb_g;
+ B = L + cb_b;
+
+ t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
+ row1[0] = t;
+ row1++;
+ row2[0] = t;
+ row2++;
+
+ // INTERPOLATE
+ if(x != cols_2 - 1) {
+ CR = (CR + *cr) >> 1;
+ CB = (CB + *cb) >> 1;
+ cr_r = Cr_r_tab[CR];
+ cr_g = Cr_g_tab[CR];
+ cb_g = Cb_g_tab[CB];
+ cb_b = Cb_b_tab[CB];
+ }
+ // end
+
+ L = L_tab[(int) *lum++];
+
+ R = L + cr_r;
+ G = L + cr_g + cb_g;
+ B = L + cb_b;
+
+ t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
+ row1[0] = t;
+ row1++;
+ row2[0] = t;
+ row2++;
+
+ /*
+ * Now, do second row.
+ */
+ // INTERPOLATE
+ if(y != rows - 2) {
+ CR = (CR + *(cr + cols_2 - 1)) >> 1;
+ CB = (CB + *(cb + cols_2 - 1)) >> 1;
+ cr_r = Cr_r_tab[CR];
+ cr_g = Cr_g_tab[CR];
+ cb_g = Cb_g_tab[CB];
+ cb_b = Cb_b_tab[CB];
+ }
+ // end
+
+ L = L_tab[(int) *lum2++];
+ R = L + cr_r;
+ G = L + cr_g + cb_g;
+ B = L + cb_b;
+
+ t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
+ row3[0] = t;
+ row3++;
+ row4[0] = t;
+ row4++;
+
+ L = L_tab[(int) *lum2++];
+ R = L + cr_r;
+ G = L + cr_g + cb_g;
+ B = L + cb_b;
+
+ t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
+ row3[0] = t;
+ row3++;
+ row4[0] = t;
+ row4++;
+ }
+ lum += cols_2 + cols_2;
+ lum2 += cols_2 + cols_2;
+ row1 += 6 * cols_2 + 2*mod;
+ row3 += 6 * cols_2 + 2*mod;
+ row2 += 6 * cols_2 + 2*mod;
+ row4 += 6 * cols_2 + 2*mod;
+ }
+}
diff --git a/mpeglib/lib/util/render/dither/dither16Bit.h b/mpeglib/lib/util/render/dither/dither16Bit.h
new file mode 100644
index 00000000..2e47c01c
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/dither16Bit.h
@@ -0,0 +1,55 @@
+/*
+ dither 16 bit depth yuv images
+ 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 __DITHER16Bit_H
+#define __DITHER16Bit_H
+
+#include "colorTableHighBit.h"
+
+class Dither16Bit {
+
+ ColorTableHighBit* colorTableHighBit;
+
+ TABTYPE *L_tab;
+ TABTYPE *Cr_r_tab;
+ TABTYPE *Cr_g_tab;
+ TABTYPE *Cb_g_tab;
+ TABTYPE *Cb_b_tab;
+
+ PIXVAL *r_2_pix;
+ PIXVAL *g_2_pix;
+ PIXVAL *b_2_pix;
+
+ public:
+ Dither16Bit(unsigned int redMask,
+ unsigned int greenMask,unsigned int blueMask);
+ ~Dither16Bit();
+
+ void ditherImageColor16(unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,
+ unsigned char* out,
+ int rows,
+ int cols,
+ int offset);
+
+ void ditherImageTwox2Color16(unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,
+ unsigned char* out,
+ int rows,
+ int cols,
+ int mod);
+
+};
+
+#endif
diff --git a/mpeglib/lib/util/render/dither/dither32Bit.cpp b/mpeglib/lib/util/render/dither/dither32Bit.cpp
new file mode 100644
index 00000000..61a1d2dc
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/dither32Bit.cpp
@@ -0,0 +1,253 @@
+/*
+ dither 32 bit depth yuv images
+ 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 "dither32Bit.h"
+
+
+#define doRow(row,Lum) *row++=(local_r_2_pix[Lum] | \
+ local_g_2_pix[Lum] | local_b_2_pix[Lum])
+
+
+Dither32Bit::Dither32Bit(unsigned int redMask,
+ unsigned int greenMask,unsigned int blueMask) {
+
+
+ colorTableHighBit=new ColorTableHighBit(32,redMask,greenMask,blueMask);
+ L_tab=colorTableHighBit->getL_tab();
+ Cr_r_tab=colorTableHighBit->getCr_r_tab();
+ Cr_g_tab=colorTableHighBit->getCr_g_tab();
+ Cb_g_tab=colorTableHighBit->getCb_g_tab();
+ Cb_b_tab=colorTableHighBit->getCb_b_tab();
+
+ r_2_pix=colorTableHighBit->getr_2_pix();
+ g_2_pix=colorTableHighBit->getg_2_pix();
+ b_2_pix=colorTableHighBit->getb_2_pix();
+
+}
+
+
+Dither32Bit::~Dither32Bit() {
+ delete colorTableHighBit;
+}
+
+
+void Dither32Bit::ditherImageColor32(unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,
+ unsigned char* out,
+ int rows,
+ int cols,
+ int mod) {
+
+ int L;
+ int n;
+ int rowWork;
+ int colWork;
+
+ unsigned int *row1, *row2;
+ unsigned char *lum2;
+ PIXVAL* local_r_2_pix;
+ PIXVAL* local_g_2_pix;
+ PIXVAL* local_b_2_pix;
+
+ row1 = (unsigned int *)out;
+
+ row2 = row1+cols+mod;
+ lum2 = lum+cols;
+
+ // because the width/height are a multiply of a macroblocksize
+ // cols/rows always are even
+ colWork=cols>>1;
+ rowWork=rows>>1;
+ mod=cols+2*mod;
+
+ while(rowWork--) {
+ n=colWork;
+ while(n--) {
+
+ local_r_2_pix=r_2_pix+Cr_r_tab[*cr];
+ local_g_2_pix=g_2_pix+Cr_g_tab[*cr++] + Cb_g_tab[*cb];
+ local_b_2_pix=b_2_pix+Cb_b_tab[*cb++];
+
+ L = L_tab[*lum++];
+ doRow(row1,L);
+
+ L = L_tab[*lum++];
+ doRow(row1,L);
+
+ L = L_tab [*lum2++];
+ doRow(row2,L);
+
+ L = L_tab [*lum2++];
+ doRow(row2,L);
+
+
+ }
+ row2 += mod;
+ lum += cols;
+ lum2 += cols;
+ row1 += mod;
+
+ }
+
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Twox2Color32 --
+ *
+ * Converts image into 24/32 bit color.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void Dither32Bit::ditherImageTwox2Color32(unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,
+ unsigned char* out,
+ int rows,
+ int cols,
+ int mod) {
+ int L, CR, CB;
+ unsigned PIXVAL *row1 = (unsigned PIXVAL *)out;
+ unsigned PIXVAL *row2 = row1 + cols * ONE_TWO + mod;
+ unsigned PIXVAL *row3 = row2 + cols * ONE_TWO + mod;
+ unsigned PIXVAL *row4 = row3 + cols * ONE_TWO + mod;
+ unsigned char *lum2;
+ int x, y;
+ int cr_r;
+ int cr_g;
+ int cb_g;
+ int cb_b;
+ int cols_2 = cols/2;
+ int loffset = ONE_TWO * 6 *cols_2 + 4*mod ;
+
+ lum2 = lum + cols_2 + cols_2;
+ for (y=0; y<rows; y+=2) {
+ for (x=0; x<cols_2; x++) {
+ int R, G, B;
+ PIXVAL t;
+
+ CR = *cr++;
+ CB = *cb++;
+ cr_r = Cr_r_tab[CR];
+ cr_g = Cr_g_tab[CR];
+ cb_g = Cb_g_tab[CB];
+ cb_b = Cb_b_tab[CB];
+
+ L = L_tab[ (int) *lum++];
+
+ R = L + cr_r;
+ G = L + cr_g + cb_g;
+ B = L + cb_b;
+
+ t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
+ row1[0] = t;
+ row2[0] = t;
+#ifndef SIXTYFOUR_BIT
+ row1[1] = t;
+ row2[1] = t;
+#endif
+ row1 += ONE_TWO;
+ row2 += ONE_TWO;
+
+ /* INTERPOLATE is now standard */
+ // INTERPOLATE
+ if(x != cols_2 - 1) {
+ CR = (CR + *cr) >> 1;
+ CB = (CB + *cb) >> 1;
+ cr_r = Cr_r_tab[CR];
+ cr_g = Cr_g_tab[CR];
+ cb_g = Cb_g_tab[CB];
+ cb_b = Cb_b_tab[CB];
+ }
+ // end
+ /* end INTERPOLATE */
+
+ L = L_tab[ (int) *lum++];
+
+ R = L + cr_r;
+ G = L + cr_g + cb_g;
+ B = L + cb_b;
+
+ t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
+ row1[0] = t;
+ row2[0] = t;
+#ifndef SIXTYFOUR_BIT
+ row1[1] = t;
+ row2[1] = t;
+#endif
+ row1 += ONE_TWO;
+ row2 += ONE_TWO;
+
+ /*
+ * Now, do second row.
+ */
+ /* INTERPOLATE is now standard */
+ // INTERPOLATE
+ if(y != rows - 2) {
+ CR = (unsigned int) (CR + *(cr + cols_2 - 1)) >> 1;
+ CB = (unsigned int) (CB + *(cb + cols_2 - 1)) >> 1;
+ cr_r = Cr_r_tab[CR];
+ cr_g = Cr_g_tab[CR];
+ cb_g = Cb_g_tab[CB];
+ cb_b = Cb_b_tab[CB];
+ }
+ // end
+ /* endif */
+ L = L_tab[ (int) *lum2++];
+ R = L + cr_r;
+ G = L + cr_g + cb_g;
+ B = L + cb_b;
+
+ t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
+ row3[0] = t;
+ row4[0] = t;
+#ifndef SIXTYFOUR_BIT
+ row3[1] = t;
+ row4[1] = t;
+#endif
+ row3 += ONE_TWO;
+ row4 += ONE_TWO;
+
+ L = L_tab[(int) *lum2++];
+ R = L + cr_r;
+ G = L + cr_g + cb_g;
+ B = L + cb_b;
+
+ t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
+ row3[0] = t;
+ row4[0] = t;
+#ifndef SIXTYFOUR_BIT
+ row3[1] = t;
+ row4[1] = t;
+#endif
+ row3 += ONE_TWO;
+ row4 += ONE_TWO;
+ }
+ lum += cols_2 + cols_2;
+ lum2 += cols_2 + cols_2;
+
+ row1 += loffset;
+ row3 += loffset;
+ row2 += loffset;
+ row4 += loffset;
+ }
+}
diff --git a/mpeglib/lib/util/render/dither/dither32Bit.h b/mpeglib/lib/util/render/dither/dither32Bit.h
new file mode 100644
index 00000000..440d021a
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/dither32Bit.h
@@ -0,0 +1,55 @@
+/*
+ dither 32 bit depth yuv images
+ 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 __DITHER32Bit_H
+#define __DITHER32Bit_H
+
+#include "colorTableHighBit.h"
+
+class Dither32Bit {
+
+ ColorTableHighBit* colorTableHighBit;
+
+ TABTYPE *L_tab;
+ TABTYPE *Cr_r_tab;
+ TABTYPE *Cr_g_tab;
+ TABTYPE *Cb_g_tab;
+ TABTYPE *Cb_b_tab;
+
+ PIXVAL *r_2_pix;
+ PIXVAL *g_2_pix;
+ PIXVAL *b_2_pix;
+
+ public:
+ Dither32Bit(unsigned int redMask,
+ unsigned int greenMask,unsigned int blueMask);
+ ~Dither32Bit();
+
+ void ditherImageColor32(unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,
+ unsigned char* out,
+ int rows,
+ int cols,
+ int offset);
+
+ void ditherImageTwox2Color32(unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,
+ unsigned char* out,
+ int rows,
+ int cols,
+ int mod);
+
+};
+
+#endif
diff --git a/mpeglib/lib/util/render/dither/dither32mmx.cpp b/mpeglib/lib/util/render/dither/dither32mmx.cpp
new file mode 100644
index 00000000..b5fa4807
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/dither32mmx.cpp
@@ -0,0 +1,272 @@
+/*
+ MMX ditherer for 32 bit displays
+ 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 "ditherMMX.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+#ifndef INTEL
+ void dither32_mmx(unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,
+ unsigned char* out,
+ int rows,
+ int cols,
+ int mod) {
+ printf("urgs! dither32_mmx \n");
+ printf("never should happen!\n");
+ exit(0);
+}
+
+#else
+
+
+static unsigned long MMX32_80w[] = {0x00800080, 0x00800080};
+static unsigned long MMX32_10w[] = {0x00100010, 0x00100010};
+static unsigned long MMX32_00FFw[] = {0x00ff00ff, 0x00ff00ff};
+static unsigned long MMX32_FF00w[] = {0xff00ff00, 0xff00ff00};
+static unsigned short MMX32_Ycoeff[] = {0x4a, 0x4a, 0x4a, 0x4a};
+static unsigned short MMX32_Vredcoeff[] = {0x59, 0x59, 0x59, 0x59};
+static unsigned short MMX32_Ubluecoeff[] = {0x72, 0x72, 0x72, 0x72};
+static unsigned short MMX32_Ugrncoeff[] = {0xffea,0xffea,0xffea,0xffea};
+static unsigned short MMX32_Vgrncoeff[] = {0xffd2,0xffd2,0xffd2,0xffd2};
+
+void dummy_dithermmx32() {
+ cout << "MMX32_10w:"<<MMX32_10w<<endl;
+ cout << "MMX32_80w:"<<MMX32_80w<<endl;
+ cout << "MMX32_Ubluecoeff:"<<MMX32_Ubluecoeff<<endl;
+ cout << "MMX32_Vredcoeff:"<<MMX32_Vredcoeff<<endl;
+ cout << "MMX32_Ugrncoeff:"<<MMX32_Ugrncoeff<<endl;
+ cout << "MMX32_Vgrncoeff:"<<MMX32_Vgrncoeff<<endl;
+ cout << "MMX32_Ycoeff:"<<MMX32_Ycoeff<<endl;
+ cout << "MMX32_00FFw:"<<MMX32_00FFw<<endl;
+ cout << "MMX32_FF00w:"<<MMX32_FF00w<<endl;
+}
+
+
+/**
+ This MMX assembler is my first assembler/MMX program ever.
+ Thus it maybe buggy.
+ Send patches to:
+ mvogt@rhrk.uni-kl.de
+
+ After it worked fine I have "obfuscated" the code a bit to have
+ more parallism in the MMX units. This means I moved
+ initilisation around and delayed other instruction.
+ Performance measurement did not show that this brought any advantage
+ but in theory it _should_ be faster this way.
+
+ The overall performanve gain to the C based dither was 30%-40%.
+ The MMX routine calculates 256bit=8RGB values in each cycle
+ (4 for row1 & 4 for row2)
+
+ The red/green/blue.. coefficents are taken from the mpeg_play
+ player. They look nice, but I dont know if you can have
+ better values, to avoid integer rounding errors.
+
+
+ IMPORTANT:
+ ==========
+
+ It is a requirement that the cr/cb/lum are 8 byte aligned and
+ the out are 16byte aligned or you will/may get segfaults
+
+*/
+
+void dither32_mmx(unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,
+ unsigned char* out,
+ int rows,
+ int cols,
+ int mod) {
+
+
+
+ unsigned int *row1;
+ unsigned int *row2;
+ row1 = (unsigned int *)out; // 32 bit target
+
+ unsigned char* end = lum +cols*rows; // Pointer to the end
+ int x=cols;
+ row2=row1+cols+mod; // start of second row
+ mod=4*cols+8*mod; // increment for row1 in byte
+
+ // buffer for asm function
+ int buf[6];
+ buf[0]=(int)(lum+cols); // lum2 pointer
+ buf[1]=(int)end;
+ buf[2]=x;
+ buf[3]=mod;
+ buf[4]=0; //tmp0;
+ buf[5]=cols;
+
+
+ __asm__ __volatile__ (
+ ".align 32\n"
+ "1:\n"
+
+ // create Cr (result in mm1)
+ "movd (%0), %%mm1\n" // 0 0 0 0 v3 v2 v1 v0
+ "pxor %%mm7,%%mm7\n" // 00 00 00 00 00 00 00 00
+ "movd (%2), %%mm2\n" // 0 0 0 0 l3 l2 l1 l0
+ "punpcklbw %%mm7,%%mm1\n" // 0 v3 0 v2 00 v1 00 v0
+ "punpckldq %%mm1,%%mm1\n" // 00 v1 00 v0 00 v1 00 v0
+ "psubw MMX32_80w,%%mm1\n" // mm1-128:r1 r1 r0 r0 r1 r1 r0 r0
+
+ // create Cr_g (result in mm0)
+ "movq %%mm1,%%mm0\n" // r1 r1 r0 r0 r1 r1 r0 r0
+ "pmullw MMX32_Vgrncoeff,%%mm0\n" // red*-46dec=0.7136*64
+ "pmullw MMX32_Vredcoeff,%%mm1\n" // red*89dec=1.4013*64
+ "psraw $6, %%mm0\n" // red=red/64
+ "psraw $6, %%mm1\n" // red=red/64
+
+
+ // create L1 L2 (result in mm2,mm4)
+ // L2=lum2
+ "movl %2,16%5\n" // store register in tmp0
+ "movl %5,%2\n" // lum2->register
+ "movd (%2),%%mm3\n" // 0 0 0 0 L3 L2 L1 L0
+ "movl 16%5,%2\n" // tmp0->register
+ "punpckldq %%mm3,%%mm2\n" // L3 L2 L1 L0 l3 l2 l1 l0
+ "movq %%mm2,%%mm4\n" // L3 L2 L1 L0 l3 l2 l1 l0
+ "pand MMX32_FF00w, %%mm2\n" // L3 0 L1 0 l3 0 l1 0
+ "pand MMX32_00FFw, %%mm4\n" // 0 L2 0 L0 0 l2 0 l0
+ "psrlw $8,%%mm2\n" // 0 L3 0 L1 0 l3 0 l1
+
+
+
+ // create R (result in mm6)
+ "movq %%mm2,%%mm5\n" // 0 L3 0 L1 0 l3 0 l1
+ "movq %%mm4,%%mm6\n" // 0 L2 0 L0 0 l2 0 l0
+ "paddsw %%mm1, %%mm5\n" // lum1+red:x R3 x R1 x r3 x r1
+ "paddsw %%mm1, %%mm6\n" // lum1+red:x R2 x R0 x r2 x r0
+ "packuswb %%mm5,%%mm5\n" // R3 R1 r3 r1 R3 R1 r3 r1
+ "packuswb %%mm6,%%mm6\n" // R2 R0 r2 r0 R2 R0 r2 r0
+ "pxor %%mm7,%%mm7\n" // 00 00 00 00 00 00 00 00
+ "punpcklbw %%mm5,%%mm6\n" // R3 R2 R1 R0 r3 r2 r1 r0
+
+
+ // create Cb (result in mm1)
+ "movd (%1), %%mm1\n" // 0 0 0 0 u3 u2 u1 u0
+ "punpcklbw %%mm7,%%mm1\n" // 0 u3 0 u2 00 u1 00 u0
+ "punpckldq %%mm1,%%mm1\n" // 00 u1 00 u0 00 u1 00 u0
+ "psubw MMX32_80w,%%mm1\n" // mm1-128:u1 u1 u0 u0 u1 u1 u0 u0
+ // create Cb_g (result in mm5)
+ "movq %%mm1,%%mm5\n" // u1 u1 u0 u0 u1 u1 u0 u0
+ "pmullw MMX32_Ugrncoeff,%%mm5\n" // blue*-109dec=1.7129*64
+ "pmullw MMX32_Ubluecoeff,%%mm1\n" // blue*114dec=1.78125*64
+ "psraw $6, %%mm5\n" // blue=red/64
+ "psraw $6, %%mm1\n" // blue=blue/64
+
+
+ // create G (result in mm7)
+ "movq %%mm2,%%mm3\n" // 0 L3 0 L1 0 l3 0 l1
+ "movq %%mm4,%%mm7\n" // 0 L2 0 L0 0 l2 0 l1
+ "paddsw %%mm5, %%mm3\n" // lum1+Cb_g:x G3t x G1t x g3t x g1t
+ "paddsw %%mm5, %%mm7\n" // lum1+Cb_g:x G2t x G0t x g2t x g0t
+ "paddsw %%mm0, %%mm3\n" // lum1+Cr_g:x G3 x G1 x g3 x g1
+ "paddsw %%mm0, %%mm7\n" // lum1+blue:x G2 x G0 x g2 x g0
+ "packuswb %%mm3,%%mm3\n" // G3 G1 g3 g1 G3 G1 g3 g1
+ "packuswb %%mm7,%%mm7\n" // G2 G0 g2 g0 G2 G0 g2 g0
+ "punpcklbw %%mm3,%%mm7\n" // G3 G2 G1 G0 g3 g2 g1 g0
+
+
+ // create B (result in mm5)
+ "movq %%mm2,%%mm3\n" // 0 L3 0 L1 0 l3 0 l1
+ "movq %%mm4,%%mm5\n" // 0 L2 0 L0 0 l2 0 l1
+ "paddsw %%mm1, %%mm3\n" // lum1+blue:x B3 x B1 x b3 x b1
+ "paddsw %%mm1, %%mm5\n" // lum1+blue:x B2 x B0 x b2 x b0
+ "packuswb %%mm3,%%mm3\n" // B3 B1 b3 b1 B3 B1 b3 b1
+ "packuswb %%mm5,%%mm5\n" // B2 B0 b2 b0 B2 B0 b2 b0
+ "punpcklbw %%mm3,%%mm5\n" // B3 B2 B1 B0 b3 b2 b1 b0
+
+
+ // fill destination row1 (needed are mm6=Rr,mm7=Gg,mm5=Bb)
+
+ "pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0
+ "pxor %%mm4,%%mm4\n" // 0 0 0 0 0 0 0 0
+ "movq %%mm6,%%mm1\n" // R3 R2 R1 R0 r3 r2 r1 r0
+ "movq %%mm5,%%mm3\n" // B3 B2 B1 B0 b3 b2 b1 b0
+ // process lower lum
+ "punpcklbw %%mm4,%%mm1\n" // 0 r3 0 r2 0 r1 0 r0
+ "punpcklbw %%mm4,%%mm3\n" // 0 b3 0 b2 0 b1 0 b0
+ "movq %%mm1,%%mm2\n" // 0 r3 0 r2 0 r1 0 r0
+ "movq %%mm3,%%mm0\n" // 0 b3 0 b2 0 b1 0 b0
+ "punpcklwd %%mm1,%%mm3\n" // 0 r1 0 b1 0 r0 0 b0
+ "punpckhwd %%mm2,%%mm0\n" // 0 r3 0 b3 0 r2 0 b2
+
+ "pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0
+ "movq %%mm7,%%mm1\n" // G3 G2 G1 G0 g3 g2 g1 g0
+ "punpcklbw %%mm1,%%mm2\n" // g3 0 g2 0 g1 0 g0 0
+ "punpcklwd %%mm4,%%mm2\n" // 0 0 g1 0 0 0 g0 0
+ "por %%mm3, %%mm2\n" // 0 r1 g1 b1 0 r0 g0 b0
+ "movq %%mm2,(%3)\n" // wrote out ! row1
+
+ "pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0
+ "punpcklbw %%mm1,%%mm4\n" // g3 0 g2 0 g1 0 g0 0
+ "punpckhwd %%mm2,%%mm4\n" // 0 0 g3 0 0 0 g2 0
+ "por %%mm0, %%mm4\n" // 0 r3 g3 b3 0 r2 g2 b2
+ "movq %%mm4,8(%3)\n" // wrote out ! row1
+
+ // fill destination row2 (needed are mm6=Rr,mm7=Gg,mm5=Bb)
+ // this can be done "destructive"
+ "pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0
+ "punpckhbw %%mm2,%%mm6\n" // 0 R3 0 R2 0 R1 0 R0
+ "punpckhbw %%mm1,%%mm5\n" // G3 B3 G2 B2 G1 B1 G0 B0
+ "movq %%mm5,%%mm1\n" // G3 B3 G2 B2 G1 B1 G0 B0
+ "punpcklwd %%mm6,%%mm1\n" // 0 R1 G1 B1 0 R0 G0 B0
+ "movq %%mm1,(%4)\n" // wrote out ! row2
+ "punpckhwd %%mm6,%%mm5\n" // 0 R3 G3 B3 0 R2 G2 B2
+ "movq %%mm5,8(%4)\n" // wrote out ! row2
+
+ "addl $4,%2\n" // lum+4
+ "addl $4,%5\n" // lum2+4
+ "leal 16(%3),%3\n" // row1+16
+ "leal 16(%4),%4\n" // row2+16
+ "addl $2, %0\n" // cr+2
+ "addl $2, %1\n" // cb+2
+
+ "subl $4,8%5\n" // x+4 x is buf[2]
+ "cmpl $0,8%5\n"
+
+ "jne 1b\n"
+ "addl 20%5, %2\n" // lum += cols
+ "movl %2,16%5\n" // store register in tmp0
+ "movl 20%5,%2\n" // cols->register
+
+ "addl %2, %5\n" // lum2 += cols
+ "addl 12%5, %3\n" // row1+= mod is buf[0]
+ "addl 12%5, %4\n" // row2+= mod is buf[0]
+
+ "movl %2, 8%5\n" // x=cols
+ "movl 16%5,%2\n" // store tmp0 in register
+
+ "cmpl 4%5, %2\n" // buf[1] is end
+ "jl 1b\n"
+ "emms\n"
+ :
+ : "r" (cr), "r"(cb),"r"(lum),
+ "r"(row1),"r"(row2),"m"(buf[0])
+ );
+
+
+
+}
+
+
+#endif
diff --git a/mpeglib/lib/util/render/dither/dither8Bit.cpp b/mpeglib/lib/util/render/dither/dither8Bit.cpp
new file mode 100644
index 00000000..4f85d3fb
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/dither8Bit.cpp
@@ -0,0 +1,306 @@
+/*
+ dither 8 bit depth yuv images
+ 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 "dither8Bit.h"
+
+
+Dither8Bit::Dither8Bit(unsigned char pixel[256]) {
+
+ int i;
+ for(i=0;i<256;i++) {
+ this->pixel[i]=pixel[i];
+ }
+ colorTable8Bit=new ColorTable8Bit();
+
+ lum_values = colorTable8Bit->getLumValues();
+ cr_values = colorTable8Bit->getCrValues();
+ cb_values = colorTable8Bit->getCbValues();
+
+
+
+ initOrderedDither();
+
+}
+
+
+Dither8Bit::~Dither8Bit() {
+ int i;
+ for (i=0; i<DITH_SIZE; i++) {
+ delete cb_darrays[i];
+ delete l_darrays[i];
+ delete cr_darrays[i];
+ }
+}
+
+
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * InitOrderedDither--
+ *
+ * Structures initialized for ordered dithering.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+void Dither8Bit::initOrderedDither() {
+ int i, j, k, err_range, threshval;
+ unsigned char *lmark, *cmark;
+
+ for (i=0; i<DITH_SIZE; i++) {
+ lmark = l_darrays[i] = new unsigned char[256];
+ for (j=0; j<lum_values[0]; j++) {
+ *lmark++ = 0;
+ }
+ for (j=0; j<(LUM_RANGE-1); j++) {
+ err_range = lum_values[j+1] - lum_values[j];
+ threshval = ((i * err_range) / DITH_SIZE)+lum_values[j];
+
+ for (k=lum_values[j]; k<lum_values[j+1]; k++) {
+ if (k > threshval) {
+ *lmark++ = ((j+1) * (CR_RANGE * CB_RANGE));
+ }
+ else {
+ *lmark++ = (j * (CR_RANGE * CB_RANGE));
+ }
+ }
+ }
+ for (j=lum_values[LUM_RANGE-1]; j<256; j++) {
+ *lmark++ = (LUM_RANGE-1)*(CR_RANGE * CB_RANGE);
+ }
+ }
+ for (i=0; i<DITH_SIZE; i++) {
+ cmark = cr_darrays[i] = new unsigned char[256];
+
+ for (j=0; j<cr_values[0]; j++) {
+ *cmark++ = 0;
+ }
+
+ for (j=0; j<(CR_RANGE-1); j++) {
+ err_range = cr_values[j+1] - cr_values[j];
+ threshval = ((i * err_range) / DITH_SIZE)+cr_values[j];
+
+ for (k=cr_values[j]; k<cr_values[j+1]; k++) {
+ if (k > threshval) {
+ *cmark++ = ((j+1) * CB_RANGE);
+ }
+ else {
+ *cmark++ = (j * CB_RANGE);
+ }
+ }
+ }
+
+ for (j=cr_values[CR_RANGE-1]; j<256; j++) {
+ *cmark++ = (CR_RANGE-1)*(CB_RANGE);
+ }
+ }
+
+ for (i=0; i<DITH_SIZE; i++) {
+ cmark = cb_darrays[i] = new unsigned char[256];
+
+ for (j=0; j<cb_values[0]; j++) {
+ *cmark++ = 0;
+ }
+
+ for (j=0; j<(CB_RANGE-1); j++) {
+ err_range = cb_values[j+1] - cb_values[j];
+ threshval = ((i * err_range) / DITH_SIZE)+cb_values[j];
+
+ for (k=cb_values[j]; k<cb_values[j+1]; k++) {
+ if (k > threshval) {
+ *cmark++ = j+1;
+ }
+ else {
+ *cmark++ = j;
+ }
+ }
+ }
+
+ for (j=cb_values[CB_RANGE-1]; j<256; j++) {
+ *cmark++ = CB_RANGE-1;
+ }
+ }
+}
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * OrderedDitherImage --
+ *
+ * Dithers an image using an ordered dither.
+ * Assumptions made:
+ * 1) The color space is allocated y:cr:cb = 8:4:4
+ * 2) The spatial resolution of y:cr:cb is 4:1:1
+ * The channels are dithered based on the standard
+ * ordered dither pattern for a 4x4 area.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void Dither8Bit::ditherImageOrdered (unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,
+ unsigned char* out,
+ int h,
+ int w) {
+ unsigned char *l, *r, *b, *o1, *o2;
+ unsigned char *l2;
+ unsigned char L, R, B;
+ int i, j;
+
+ l = lum;
+ l2 = lum+w;
+ r = cr;
+ b = cb;
+ o1 = out;
+ o2 = out+w;
+
+
+ for (i=0; i<h; i+=4) {
+
+ for (j=0; j<w; j+=8) {
+
+ R = r[0]; B = b[0];
+
+ L = l[0];
+ o1[0] = pixel[(l_darrays[0][L] + cr_darrays[0][R] + cb_darrays[0][B])];
+ L = l[1];
+ o1[1] = pixel[(l_darrays[8][L] + cr_darrays[8][R] + cb_darrays[8][B])];
+ L = l2[0];
+ o2[0] = pixel[(l_darrays[12][L] + cr_darrays[12][R] + cb_darrays[12][B])];
+ L = l2[1];
+ o2[1] = pixel[(l_darrays[4][L] + cr_darrays[4][R] + cb_darrays[4][B])];
+
+ R = r[1]; B = b[1];
+
+ L = l[2];
+ o1[2] = pixel[(l_darrays[2][L] + cr_darrays[2][R] + cb_darrays[2][B])];
+ L = l[3];
+ o1[3] = pixel[(l_darrays[10][L] + cr_darrays[10][R] + cb_darrays[10][B])];
+ L = l2[2];
+ o2[2] = pixel[(l_darrays[14][L] + cr_darrays[14][R] + cb_darrays[14][B])];
+ L = l2[3];
+ o2[3] = pixel[(l_darrays[6][L] + cr_darrays[6][R] + cb_darrays[6][B])];
+
+ R = r[2]; B = b[2];
+
+ L = l[4];
+ o1[4] = pixel[(l_darrays[0][L] + cr_darrays[0][R] + cb_darrays[0][B])];
+ L = l[5];
+ o1[5] = pixel[(l_darrays[8][L] + cr_darrays[8][R] + cb_darrays[8][B])];
+ L = l2[4];
+ o2[4] = pixel[(l_darrays[12][L] + cr_darrays[12][R] + cb_darrays[12][B])];
+ L = l2[5];
+ o2[5] = pixel[(l_darrays[4][L] + cr_darrays[4][R] + cb_darrays[4][B])];
+
+ R = r[3]; B = b[3];
+
+ L = l[6];
+ o1[6] = pixel[(l_darrays[2][L] + cr_darrays[2][R] + cb_darrays[2][B])];
+ L = l[7];
+ o1[7] = pixel[(l_darrays[10][L] + cr_darrays[10][R] + cb_darrays[10][B])];
+ L = l2[6];
+ o2[6] = pixel[(l_darrays[14][L] + cr_darrays[14][R] + cb_darrays[14][B])];
+ L = l2[7];
+ o2[7] = pixel[(l_darrays[6][L] + cr_darrays[6][R] + cb_darrays[6][B])];
+
+ l += 8;
+ l2 += 8;
+ r += 4;
+ b += 4;
+ o1 += 8;
+ o2 += 8;
+ }
+
+ l += w;
+ l2 += w;
+ o1 += w;
+ o2 += w;
+
+ for (j=0; j<w; j+=8) {
+
+ R = r[0]; B = b[0];
+
+ L = l[0];
+ o1[0] = pixel[(l_darrays[3][L] + cr_darrays[3][R] + cb_darrays[3][B])];
+ L = l[1];
+ o1[1] = pixel[(l_darrays[11][L] + cr_darrays[11][R] + cb_darrays[11][B])];
+ L = l2[0];
+ o2[0] = pixel[(l_darrays[15][L] + cr_darrays[15][R] + cb_darrays[15][B])];
+ L = l2[1];
+ o2[1] = pixel[(l_darrays[7][L] + cr_darrays[7][R] + cb_darrays[7][B])];
+
+ R = r[1]; B = b[1];
+
+ L = l[2];
+ o1[2] = pixel[(l_darrays[1][L] + cr_darrays[1][R] + cb_darrays[1][B])];
+ L = l[3];
+ o1[3] = pixel[(l_darrays[9][L] + cr_darrays[9][R] + cb_darrays[9][B])];
+ L = l2[2];
+ o2[2] = pixel[(l_darrays[13][L] + cr_darrays[13][R] + cb_darrays[13][B])];
+ L = l2[3];
+ o2[3] = pixel[(l_darrays[5][L] + cr_darrays[5][R] + cb_darrays[5][B])];
+
+ R = r[2]; B = b[2];
+
+ L = l[4];
+ o1[4] = pixel[(l_darrays[3][L] + cr_darrays[3][R] + cb_darrays[3][B])];
+ L = l[5];
+ o1[5] = pixel[(l_darrays[11][L] + cr_darrays[11][R] + cb_darrays[11][B])];
+ L = l2[4];
+ o2[4] = pixel[(l_darrays[15][L] + cr_darrays[15][R] + cb_darrays[15][B])];
+ L = l2[5];
+ o2[5] = pixel[(l_darrays[7][L] + cr_darrays[7][R] + cb_darrays[7][B])];
+
+ R = r[3]; B = b[3];
+
+ L = l[6];
+ o1[6] = pixel[(l_darrays[1][L] + cr_darrays[1][R] + cb_darrays[1][B])];
+ L = l[7];
+ o1[7] = pixel[(l_darrays[9][L] + cr_darrays[9][R] + cb_darrays[9][B])];
+ L = l2[6];
+ o2[6] = pixel[(l_darrays[13][L] + cr_darrays[13][R] + cb_darrays[13][B])];
+ L = l2[7];
+ o2[7] = pixel[(l_darrays[5][L] + cr_darrays[5][R] + cb_darrays[5][B])];
+
+ l += 8;
+ l2 += 8;
+ r += 4;
+ b += 4;
+ o1 += 8;
+ o2 += 8;
+ }
+
+ l += w;
+ l2 += w;
+ o1 += w;
+ o2 += w;
+ }
+}
+
diff --git a/mpeglib/lib/util/render/dither/dither8Bit.h b/mpeglib/lib/util/render/dither/dither8Bit.h
new file mode 100644
index 00000000..7bdd4d8f
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/dither8Bit.h
@@ -0,0 +1,63 @@
+/*
+ dither 8 bit depth yuv images
+ 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 __DITHER_8BIT_H
+#define __DITHER_8BIT_H
+
+
+#include "colorTable8Bit.h"
+
+#define DITH_SIZE 16
+
+
+class Dither8Bit {
+
+ /* Structures used to implement hybrid ordered dither/floyd-steinberg
+ dither algorithm.
+ */
+
+ unsigned char *l_darrays[DITH_SIZE];
+ unsigned char *cr_darrays[DITH_SIZE];
+ unsigned char *cb_darrays[DITH_SIZE];
+
+ // private colormap
+ unsigned char pixel[256];
+
+ ColorTable8Bit* colorTable8Bit;
+
+ // Arrays holding quantized value ranged for lum, cr, and cb.
+ // (used for 8 Bit)
+
+ int* lum_values;
+ int* cr_values;
+ int* cb_values;
+
+
+ public:
+ Dither8Bit(unsigned char pixel[256]);
+ ~Dither8Bit();
+
+ void ditherImageOrdered (unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,
+ unsigned char* out,
+ int h,
+ int w);
+
+ private:
+ void initOrderedDither();
+};
+
+#endif
+
diff --git a/mpeglib/lib/util/render/dither/ditherDef.h b/mpeglib/lib/util/render/dither/ditherDef.h
new file mode 100644
index 00000000..2e8d7d0e
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/ditherDef.h
@@ -0,0 +1,100 @@
+/*
+ global definitions for dithering
+ 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 __DITHERDEF_H
+#define __DITHERDEF_H
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+extern "C" {
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+}
+
+
+#ifdef __GNUC__
+#if (__GNUC__ < 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ < 91 ) )
+#ifndef _AIX
+#warning "inline code disabled! (buggy egcs version)"
+#undef __NO_MATH_INLINES
+#define __NO_MATH_INLINES 1
+#endif
+#endif
+#endif
+#include <math.h>
+
+
+
+/* Gamma correction stuff */
+extern int gammaCorrectFlag;
+extern double gammaCorrect;
+
+/* Chroma correction stuff */
+extern int chromaCorrectFlag;
+extern double chromaCorrect;
+
+
+#define CB_BASE 1
+#define CR_BASE (CB_BASE*CB_RANGE)
+#define LUM_BASE (CR_BASE*CR_RANGE)
+
+#define TABTYPE short
+
+#ifdef SIXTYFOUR_BIT
+#define PIXVAL long
+#else
+#define PIXVAL int
+#endif
+
+#ifdef SIXTYFOUR_BIT
+#define ONE_TWO 1
+#else
+#define ONE_TWO 2
+#endif
+
+
+
+#define Min(x,y) (((x) < (y)) ? (x) : (y))
+#define Max(x,y) (((x) > (y)) ? (x) : (y))
+
+#define CHROMA_CORRECTION128(x) ((x) >= 0 \
+ ? Min(127, (int)(((x) * chromaCorrect))) \
+ : Max(-128, (int)(((x) * chromaCorrect))))
+#define CHROMA_CORRECTION256D(x) ((x) >= 128 \
+ ? 128.0 + Min(127.0, (((x)-128.0) * chromaCorrect)) \
+ : 128.0 - Min(128.0, (((128.0-(x))* chromaCorrect))))
+
+
+
+#define GAMMA_CORRECTION(x) ((int)(pow((x) / 255.0, 1.0/gammaCorrect)* 255.0))
+
+#define CHROMA_CORRECTION128D(x) ((x) >= 0 \
+ ? Min(127.0, ((x) * chromaCorrect)) \
+ : Max(-128.0, ((x) * chromaCorrect)))
+
+#define CHROMA_CORRECTION256(x) ((x) >= 128 \
+ ? 128 + Min(127, (int)(((x)-128.0) * chromaCorrect)) \
+ : 128 - Min(128, (int)((128.0-(x)) * chromaCorrect)))
+
+// Range values for lum, cr, cb.
+#define LUM_RANGE 8
+#define CR_RANGE 4
+#define CB_RANGE 4
+
+
+#endif
diff --git a/mpeglib/lib/util/render/dither/ditherMMX.h b/mpeglib/lib/util/render/dither/ditherMMX.h
new file mode 100644
index 00000000..2f08b689
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/ditherMMX.h
@@ -0,0 +1,38 @@
+/*
+ mmx ditherer
+ 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 __DITHERMMX_H
+#define __DITHERMMX_H
+
+#include "ditherDef.h"
+
+
+// The mmx dither routine come from NIST
+// NIST is an mpeg2/dvd player
+// more: http://home.germany.net/100-5083/
+extern void ditherBlock(unsigned char *lum,
+ unsigned char *cr,
+ unsigned char *cb,
+ unsigned char *out,
+ int rows, int cols, int mod);
+
+extern void dither32_mmx(unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,
+ unsigned char* out,
+ int rows,
+ int cols,
+ int mod);
+
+
+#endif
diff --git a/mpeglib/lib/util/render/dither/ditherRGB.cpp b/mpeglib/lib/util/render/dither/ditherRGB.cpp
new file mode 100644
index 00000000..1bcdb2ff
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/ditherRGB.cpp
@@ -0,0 +1,230 @@
+/*
+ copys RGB images to a destination
+ 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 "ditherRGB.h"
+
+#include <iostream>
+
+using namespace std;
+
+DitherRGB::DitherRGB() {
+}
+
+
+DitherRGB::~DitherRGB() {
+}
+
+
+int DitherRGB::getDepth(int pixel) {
+ int byteDepth=0;
+
+ switch(pixel) {
+ case 8:
+ byteDepth=1;
+ break;
+ case 15:
+ case 16:
+ byteDepth=2;
+ break;
+ case 24:
+ case 32:
+ byteDepth=4;
+ break;
+ default:
+ cout << "unknown byteDepth:"<<pixel
+ << " in DitherRGB_flipped::flipRGBImage"<<endl;
+ }
+ return byteDepth;
+
+}
+
+void DitherRGB::ditherRGBImage(unsigned char* dest,unsigned char* src,
+ int depth,int width,int height,int offset) {
+ int byteDepth=getDepth(depth);
+ if (byteDepth == 0) {
+ return;
+ }
+
+
+ if (offset==0) {
+ int bytes=height*width*byteDepth;
+ memcpy(dest,src,bytes);
+ return;
+ }
+
+ int i;
+ int lineSize=width*byteDepth;
+
+ offset=offset*byteDepth+lineSize;
+
+ for (i=0;i<height;i++) {
+ memcpy(dest,src,lineSize);
+ src+=lineSize;
+ dest+=offset;
+ }
+
+
+}
+
+void DitherRGB::ditherRGBImage_x2(unsigned char* dest,unsigned char* src,
+ int depth,int width,int height,int offset) {
+
+ int byteDepth=getDepth(depth);
+ if (byteDepth == 0) {
+ return;
+ }
+
+ switch(byteDepth) {
+ case 1:
+ ditherRGB1Byte_x2(dest,src,1,width, height,offset);
+ break;
+ case 2:
+ ditherRGB2Byte_x2(dest,src,2,width, height,offset);
+ break;
+ case 4:
+ ditherRGB4Byte_x2(dest,src,4,width, height,offset);
+ break;
+ default:
+ cout <<"ditherRGBImage_x2 byteDepth:"<<byteDepth
+ <<" not supported"<<endl;
+ }
+}
+
+
+void DitherRGB::ditherRGB1Byte_x2(unsigned char* dest,unsigned char* src,
+ int depth,int width,int height,int offset) {
+
+ //
+ // dest destr
+ // destd destrd
+
+ int lineInc=2*width+offset;
+ unsigned char* destr=dest+1;
+ unsigned char* destd=dest+lineInc;
+ unsigned char* destrd=destd+1;
+
+ int row;
+ int col;
+ //
+ // We copy byte by byte this is slow, but works for
+ // all byteDepth
+ // this memcpy can be optimized with MMX very i) good ii) easily
+
+ for(row=0;row<height;row++) {
+ for(col=0;col<width;col++) {
+ *dest++=*src;
+ *destr++=*src;
+ *destd++=*src;
+ *destrd++=*src;
+ dest++;
+ destr++;
+ destd++;
+ destrd++;
+
+ src++;
+ }
+ dest+=lineInc;
+ destr+=lineInc;
+ destd+=lineInc;
+ destrd+=lineInc;
+ }
+}
+
+
+void DitherRGB::ditherRGB2Byte_x2(unsigned char* destination,
+ unsigned char* source,
+ int depth,int width,int height,int offset) {
+ //
+ // dest destr
+ // destd destrd
+
+ unsigned short int* src=(unsigned short int*) source;
+ unsigned short int* dest=(unsigned short int*) destination;
+
+ int lineInc=2*width+offset;
+ unsigned short int* destr=dest+1;
+ unsigned short int* destd=dest+lineInc;
+ unsigned short int* destrd=destd+1;
+
+ int row;
+ int col;
+ //
+ // We copy byte by byte this is slow, but works for
+ // all byteDepth
+ // this memcpy can be optimized with MMX very i) good ii) easily
+
+ for(row=0;row<height;row++) {
+ for(col=0;col<width;col++) {
+ *dest++=*src;
+ *destr++=*src;
+ *destd++=*src;
+ *destrd++=*src;
+ dest++;
+ destr++;
+ destd++;
+ destrd++;
+
+ src++;
+ }
+ dest+=lineInc;
+ destr+=lineInc;
+ destd+=lineInc;
+ destrd+=lineInc;
+ }
+}
+
+
+void DitherRGB::ditherRGB4Byte_x2(unsigned char* destination,
+ unsigned char* source,
+ int depth,int width,int height,int offset) {
+
+ //
+ // dest destr
+ // destd destrd
+
+ unsigned int* src=(unsigned int*) source;
+ unsigned int* dest=(unsigned int*) destination;
+
+ int lineInc=2*width+offset;
+ unsigned int* destr=dest+1;
+ unsigned int* destd=dest+lineInc;
+ unsigned int* destrd=destd+1;
+
+ int row;
+ int col;
+ //
+ // We copy byte by byte this is slow, but works for
+ // all byteDepth
+ // this memcpy can be optimized with MMX very i) good ii) easily
+
+ for(row=0;row<height;row++) {
+ for(col=0;col<width;col++) {
+ *dest++=*src;
+ *destr++=*src;
+ *destd++=*src;
+ *destrd++=*src;
+ dest++;
+ destr++;
+ destd++;
+ destrd++;
+
+ src++;
+ }
+ dest+=lineInc;
+ destr+=lineInc;
+ destd+=lineInc;
+ destrd+=lineInc;
+ }
+
+}
+
diff --git a/mpeglib/lib/util/render/dither/ditherRGB.h b/mpeglib/lib/util/render/dither/ditherRGB.h
new file mode 100644
index 00000000..6f24cd8c
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/ditherRGB.h
@@ -0,0 +1,45 @@
+/*
+ copys RGB images to a destination
+ 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 __DITHERRGB_H
+#define __DITHERRGB_H
+
+#include "colorTableHighBit.h"
+
+class DitherRGB {
+
+ int flipSize;
+ unsigned char* flipSpace;
+
+ public:
+ DitherRGB();
+ ~DitherRGB();
+
+ // Note: this methods swaps the image
+ // itsself
+ void ditherRGBImage(unsigned char* dest,unsigned char* src,
+ int depth,int width,int height,int offset);
+ void ditherRGBImage_x2(unsigned char* dest,unsigned char* src,
+ int depth,int width,int height,int offset);
+ private:
+ int getDepth(int pixel);
+ // depth is here in byte!
+ void ditherRGB1Byte_x2(unsigned char* dest,unsigned char* src,
+ int depth,int width,int height,int offset);
+ void ditherRGB2Byte_x2(unsigned char* dest,unsigned char* src,
+ int depth,int width,int height,int offset);
+ void ditherRGB4Byte_x2(unsigned char* dest,unsigned char* src,
+ int depth,int width,int height,int offset);
+
+};
+
+#endif
diff --git a/mpeglib/lib/util/render/dither/ditherRGB_flipped.cpp b/mpeglib/lib/util/render/dither/ditherRGB_flipped.cpp
new file mode 100644
index 00000000..ba177675
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/ditherRGB_flipped.cpp
@@ -0,0 +1,82 @@
+/*
+ flips RGB images
+ 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 "ditherRGB_flipped.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+DitherRGB_flipped::DitherRGB_flipped() {
+ flipSpace=NULL;
+ flipSize=0;
+}
+
+DitherRGB_flipped::~DitherRGB_flipped() {
+ if (flipSpace != NULL) {
+ delete flipSpace;
+ }
+}
+
+
+
+
+void DitherRGB_flipped::flipRGBImage(unsigned char* dest,unsigned char* src,
+ int depth,int width,int height,int ) {
+
+ int byteDepth;
+
+ switch(depth) {
+ case 8:
+ byteDepth=1;
+ break;
+ case 15:
+ case 16:
+ byteDepth=2;
+ break;
+ case 24:
+ case 32:
+ byteDepth=4;
+ break;
+ default:
+ cout << "unknown byteDepth:"<<depth
+ << " in DitherRGB_flipped::flipRGBImage"<<endl;
+ return;
+ }
+
+
+ int spaceNeeded=width*height*byteDepth;
+
+ if (spaceNeeded > flipSize) {
+ if (flipSpace != NULL) {
+ delete flipSpace;
+ }
+ cout << "flipSpace:"<<spaceNeeded<<endl;
+ flipSpace=new unsigned char[spaceNeeded+64];
+ flipSize=spaceNeeded;
+ }
+
+ int i;
+ int lineSize=width*byteDepth;
+ unsigned char* end=dest+lineSize*(height-1);
+
+ for (i=0;i<height;i++) {
+ memcpy(end,src,lineSize);
+ src+=lineSize;
+ end-=lineSize;
+ }
+
+}
+
+
diff --git a/mpeglib/lib/util/render/dither/ditherRGB_flipped.h b/mpeglib/lib/util/render/dither/ditherRGB_flipped.h
new file mode 100644
index 00000000..1d99f7f6
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/ditherRGB_flipped.h
@@ -0,0 +1,34 @@
+/*
+ flips RGB images
+ 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 __DITHERRGB_FLIPPED_H
+#define __DITHERRGB_FLIPPED_H
+
+#include "colorTableHighBit.h"
+
+class DitherRGB_flipped {
+
+ int flipSize;
+ unsigned char* flipSpace;
+
+ public:
+ DitherRGB_flipped();
+ ~DitherRGB_flipped();
+
+ // Note: this methods swaps the image
+ // itsself
+ void flipRGBImage(unsigned char* dest,unsigned char* src,
+ int depth,int width,int height,int offset);
+
+};
+
+#endif
diff --git a/mpeglib/lib/util/render/dither/ditherWrapper.cpp b/mpeglib/lib/util/render/dither/ditherWrapper.cpp
new file mode 100644
index 00000000..c6c37a79
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/ditherWrapper.cpp
@@ -0,0 +1,246 @@
+/*
+ wrapper for X11 Window
+ 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 "ditherWrapper.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+/*
+ Flag for gamma correction
+ Makes images brighter/darker.
+ It's in the source but not activated (for now)
+*/
+int gammaCorrectFlag = 0;
+double gammaCorrect = 1.0;
+
+/*
+ Flag for chroma correction.
+ reduce the color intensity..
+ It's in the source but not activated (for now)
+*/
+int chromaCorrectFlag = 0;
+double chromaCorrect = 1.0;
+
+
+
+DitherWrapper::DitherWrapper(int bpp,unsigned int redMask,
+ unsigned int greenMask,unsigned int blueMask,
+ unsigned char pixel[256]) {
+
+ this->bpp=bpp;
+ this->redMask=redMask;
+ this->greenMask=greenMask;
+ this->blueMask=blueMask;
+
+
+ dither8Bit=new Dither8Bit(pixel);
+ dither16Bit=new Dither16Bit(redMask,greenMask,blueMask);
+ dither32Bit=new Dither32Bit(redMask,greenMask,blueMask);
+ ditherRGB_flipped=new DitherRGB_flipped();
+ ditherRGB=new DitherRGB();
+
+
+#ifdef INTEL
+ lmmx=mm_support();
+#else
+ lmmx=false;
+#endif
+
+
+}
+
+
+DitherWrapper::~DitherWrapper(){
+ delete dither16Bit;
+ delete dither8Bit;
+ delete dither32Bit;
+ delete ditherRGB_flipped;
+ delete ditherRGB;
+}
+
+
+
+
+
+void DitherWrapper::doDither(YUVPicture* pic,int depth,int imageMode,
+ unsigned char* dest,int offset) {
+
+
+ //
+ // according to the input imageType and the output area
+ // handle different dither methods
+ //
+
+ int inputType=pic->getImageType();
+
+ if ( (inputType == PICTURE_YUVMODE_CR_CB) ||
+ (inputType == PICTURE_YUVMODE_CB_CR) ) {
+ doDitherYUV(pic,depth,imageMode,dest,offset);
+ return;
+ }
+
+ if ( (inputType == PICTURE_RGB) ||
+ (inputType == PICTURE_RGB_FLIPPED) ){
+ doDitherRGB(pic,depth,imageMode,dest,offset);
+ return;
+ }
+
+ cout << "unknown inputType:"<<inputType
+ << " in DitherWrapper::doDither"<<endl;
+}
+
+
+void DitherWrapper::doDitherRGB(YUVPicture* pic,int depth,int imageMode,
+ unsigned char* dest,int offset) {
+
+ int inputType=pic->getImageType();
+
+ switch(inputType) {
+ case PICTURE_RGB:
+ doDitherRGB_NORMAL(pic,depth,imageMode,dest,offset);
+ break;
+ case PICTURE_RGB_FLIPPED:
+ doDitherRGB_FLIPPED(pic,depth,imageMode,dest,offset);
+ break;
+ default:
+ cout << "unknown RGB type:"<<inputType<<" in DitherWrapper"<<endl;
+ exit(0);
+ }
+}
+
+
+void DitherWrapper::doDitherRGB_NORMAL(YUVPicture* pic,
+ int depth,int imageMode,
+ unsigned char* dest,int offset) {
+
+ int w=pic->getWidth();
+ int h=pic->getHeight();
+
+ unsigned char* src=pic->getImagePtr();
+
+ if (imageMode & _IMAGE_DOUBLE) {
+ ditherRGB->ditherRGBImage_x2(dest,src,depth,w,h,offset);
+ } else {
+ ditherRGB->ditherRGBImage(dest,src,depth,w,h,offset);
+ }
+}
+
+void DitherWrapper::doDitherRGB_FLIPPED(YUVPicture* pic,
+ int depth,int imageMode,
+ unsigned char* dest,int offset) {
+
+ int w=pic->getWidth();
+ int h=pic->getHeight();
+
+ unsigned char* src=pic->getImagePtr();
+
+ ditherRGB_flipped->flipRGBImage(dest,src,depth,w,h,offset);
+}
+
+
+
+void DitherWrapper::doDitherYUV(YUVPicture* pic,int depth,int imageMode,
+ unsigned char* dest,int offset) {
+
+ if (imageMode & _IMAGE_DOUBLE) {
+ doDither_x2(pic,depth,dest,offset);
+ } else {
+ doDither_std(pic,depth,dest,offset);
+ }
+}
+
+
+void DitherWrapper::doDither_std(YUVPicture* pic,int depth,
+ unsigned char* dest,int offset){
+
+ int h=pic->getHeight();
+ int w=pic->getWidth();
+ unsigned char* lum=pic->getLuminancePtr();
+ unsigned char* cr=pic->getCrPtr();
+ unsigned char* cb=pic->getCbPtr();
+
+
+ switch (depth) {
+ case 8:
+ dither8Bit->ditherImageOrdered(lum, cr, cb,dest , h, w);
+ break;
+ case 16:
+ if (lmmx) {
+ ditherBlock(lum,cr,cb,dest,h,w,offset);
+ } else {
+ dither16Bit->ditherImageColor16(lum,cr,cb,dest,h,w,offset);
+ }
+
+ break;
+ case 24:
+ case 32:
+ if (lmmx) {
+ dither32_mmx(lum, cr, cb,dest ,h,w,offset);
+ } else {
+ dither32Bit->ditherImageColor32(lum, cr, cb,dest ,h,w,offset);
+ }
+
+
+ break;
+ default:
+ cout << "cannot dither depth:"<<depth<<endl;
+ }
+
+}
+
+
+void DitherWrapper::doDither_x2(YUVPicture* pic,int depth,
+ unsigned char* dest,int offset){
+
+ int h=pic->getHeight();
+ int w=pic->getWidth();
+ unsigned char* lum=pic->getLuminancePtr();
+ unsigned char* cr=pic->getCrPtr();
+ unsigned char* cb=pic->getCbPtr();
+
+
+ switch (depth) {
+ case 8: {
+ // we do dither with the 8Bit std YUV ditherer to RGB
+ // and then we do the double part with the
+ // RGB ditherer. Its obviously much slower but at
+ // least it works. To not allocate memory twice
+ // we are a bit tricky. We know that the image
+ // has space for doubls size. We but the not double size
+ // image at the bottom of the dest. Maybe that
+ // the last line gets overwritten
+ int memPos=3*h*w;
+ dither8Bit->ditherImageOrdered(lum, cr, cb,dest+memPos, h, w);
+ unsigned char* src=dest+memPos;
+ ditherRGB->ditherRGBImage_x2(dest,src,depth,w,h,0);
+ break;
+ }
+ case 16:
+ dither16Bit->ditherImageTwox2Color16(lum,cr,cb,dest,h,w,offset);
+ break;
+ case 24:
+ case 32:
+ if (lmmx) {
+ //dither32x2_mmx(lum, cr, cb,dest ,h,w,offset);
+ dither32Bit->ditherImageTwox2Color32(lum,cr,cb,dest,h,w,offset);
+ } else {
+ dither32Bit->ditherImageTwox2Color32(lum,cr,cb,dest,h,w,offset);
+ }
+ break;
+ default:
+ cout << "cannot dither depth:" << depth << endl;
+ }
+}
diff --git a/mpeglib/lib/util/render/dither/ditherWrapper.h b/mpeglib/lib/util/render/dither/ditherWrapper.h
new file mode 100644
index 00000000..b01abff8
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/ditherWrapper.h
@@ -0,0 +1,80 @@
+/*
+ wrapper for X11 Window
+ 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 __DITHERWRAPPER_H
+#define __DITHERWRAPPER_H
+
+
+#include "../../mmx/mmx.h"
+
+#include "../yuvPicture.h"
+#include "../imageBase.h"
+#include <stdlib.h>
+#include "ditherMMX.h"
+#include "dither8Bit.h"
+#include "dither16Bit.h"
+#include "dither32Bit.h"
+#include "ditherRGB_flipped.h"
+#include "ditherRGB.h"
+
+
+/**
+ Wraps all calls to software ditherer and the different
+ resolutions,mmx enhancements, and doublesize ditherers.
+*/
+
+
+class DitherWrapper {
+
+ int lmmx;
+
+ int bpp;
+ // colorMask
+ unsigned int redMask;
+ unsigned int greenMask;
+ unsigned int blueMask;
+
+ Dither8Bit* dither8Bit;
+ Dither16Bit* dither16Bit;
+ Dither32Bit* dither32Bit;
+ DitherRGB_flipped* ditherRGB_flipped;
+ DitherRGB* ditherRGB;
+
+ public:
+ DitherWrapper(int bpp,unsigned int redMask,
+ unsigned int greenMask,unsigned int blueMask,
+ unsigned char pixel[256]);
+ ~DitherWrapper();
+
+/* int getDitherSize(); */
+/* void setDitherSize(int ditherMode); */
+
+ void doDither(YUVPicture* pic,int depth,int imageMode,
+ unsigned char* dest,int offset);
+
+
+ private:
+ void doDitherYUV(YUVPicture* pic,int depth,int imageMode,
+ unsigned char* dest,int offset);
+ void doDitherRGB(YUVPicture* pic,int depth,int imageMode,
+ unsigned char* dest,int offset);
+ void doDitherRGB_NORMAL(YUVPicture* pic,int depth,int imageMode,
+ unsigned char* dest,int offset);
+ void doDitherRGB_FLIPPED(YUVPicture* pic,int depth,int imageMode,
+ unsigned char* dest,int offset);
+
+ void doDither_std(YUVPicture* pic,int depth,unsigned char* dest,int offset);
+ void doDither_x2(YUVPicture* pic,int depth,unsigned char* dest,int offset);
+};
+
+#endif
diff --git a/mpeglib/lib/util/render/dither/ditherer_mmx16.cpp b/mpeglib/lib/util/render/dither/ditherer_mmx16.cpp
new file mode 100644
index 00000000..757f0676
--- /dev/null
+++ b/mpeglib/lib/util/render/dither/ditherer_mmx16.cpp
@@ -0,0 +1,256 @@
+
+#include "ditherMMX.h"
+
+#include <iostream>
+
+using namespace std;
+
+#ifndef INTEL
+// nothing
+void ditherBlock(unsigned char *lum, unsigned char *cr, unsigned char *cb,
+ unsigned char *out,
+ int cols, int rows, int screen_width) {
+ printf("call to ditherBlock. this should never happen\n");
+ printf("check mmx detection routine.\n");
+ exit(0);
+}
+#else
+
+
+static long long MMX16_0 = 0L;
+static unsigned long MMX16_10w[] = {0x00100010, 0x00100010};
+static unsigned long MMX16_80w[] = {0x00800080, 0x00800080};
+static unsigned long MMX16_00FFw[] = {0x00ff00ff, 0x00ff00ff};
+static unsigned short MMX16_Ublucoeff[] = {0x81, 0x81, 0x81, 0x81};
+static unsigned short MMX16_Vredcoeff[] = {0x66, 0x66, 0x66, 0x66};
+static unsigned short MMX16_Ugrncoeff[] = {0xffe8, 0xffe8, 0xffe8, 0xffe8};
+static unsigned short MMX16_Vgrncoeff[] = {0xffcd, 0xffcd, 0xffcd, 0xffcd};
+static unsigned short MMX16_Ycoeff[] = {0x4a, 0x4a, 0x4a, 0x4a};
+static unsigned short MMX16_redmask[] = {0xf800, 0xf800, 0xf800, 0xf800};
+static unsigned short MMX16_grnmask[] = {0x7e0, 0x7e0, 0x7e0, 0x7e0};
+
+void dummy_dithermmx16() {
+ cout << "MMX16_0"<<MMX16_0<<endl;
+ cout << "MMX16_10w:"<<MMX16_10w<<endl;
+ cout << "MMX16_80w:"<<MMX16_80w<<endl;
+ cout << "MMX16_Ublucoeff:"<<MMX16_Ublucoeff<<endl;
+ cout << "MMX16_Vredcoeff:"<<MMX16_Vredcoeff<<endl;
+ cout << "MMX16_Ugrncoeff:"<<MMX16_Ugrncoeff<<endl;
+ cout << "MMX16_Vgrncoeff:"<<MMX16_Vgrncoeff<<endl;
+ cout << "MMX16_Ycoeff:"<<MMX16_Ycoeff<<endl;
+ cout << "MMX16_redmask:"<<MMX16_redmask<<endl;
+ cout << "MMX16_grnmask:"<<MMX16_grnmask<<endl;
+ cout << "MMX16_00FFw:"<<MMX16_00FFw<<endl;
+}
+
+
+void ditherBlock(unsigned char *lum,
+ unsigned char *cr,
+ unsigned char *cb,
+ unsigned char *out,
+ int rows,
+ int cols,
+ int mod) {
+
+ unsigned short *row1;
+ unsigned short *row2;
+ row1 = (unsigned short* )out; // 16 bit target
+
+ unsigned char* end = lum +cols*rows; // Pointer to the end
+ int x=cols;
+ row2=row1+mod+cols; // start of second row
+ mod=2*cols+4*mod; // increment for row1 in byte
+
+ // buffer for asm function
+ int buf[6];
+ buf[0]=(int)(lum+cols); // lum2 pointer
+ buf[1]=(int)end;
+ buf[2]=x;
+ buf[3]=mod;
+ buf[4]=0; //tmp0;
+ buf[5]=cols;
+
+
+
+ __asm__ __volatile__(
+ ".align 32\n"
+ "1:\n"
+ "movd (%1), %%mm0\n" // 4 Cb 0 0 0 0 u3 u2 u1 u0
+ "pxor %%mm7, %%mm7\n"
+ "movd (%0), %%mm1\n" // 4 Cr 0 0 0 0 v3 v2 v1 v0
+ "punpcklbw %%mm7, %%mm0\n" // 4 W cb 0 u3 0 u2 0 u1 0 u0
+ "punpcklbw %%mm7, %%mm1\n" // 4 W cr 0 v3 0 v2 0 v1 0 v0
+ "psubw MMX16_80w, %%mm0\n"
+ "psubw MMX16_80w, %%mm1\n"
+ "movq %%mm0, %%mm2\n" // Cb 0 u3 0 u2 0 u1 0 u0
+ "movq %%mm1, %%mm3\n" // Cr
+ "pmullw MMX16_Ugrncoeff, %%mm2\n" // Cb2green 0 R3 0 R2 0 R1 0 R0
+ "movq (%2), %%mm6\n" // L1 l7 L6 L5 L4 L3 L2 L1 L0
+ "pmullw MMX16_Ublucoeff, %%mm0\n" // Cb2blue
+ "pand MMX16_00FFw, %%mm6\n" // L1 00 L6 00 L4 00 L2 00 L0
+ "pmullw MMX16_Vgrncoeff, %%mm3\n" // Cr2green
+ "movq (%2), %%mm7\n" // L2
+ "pmullw MMX16_Vredcoeff, %%mm1\n" // Cr2red
+ // "psubw MMX16_10w, %%mm6\n"
+ "psrlw $8, %%mm7\n" // L2 00 L7 00 L5 00 L3 00 L1
+ "pmullw MMX16_Ycoeff, %%mm6\n" // lum1
+ // "psubw MMX16_10w, %%mm7\n" // L2
+ "paddw %%mm3, %%mm2\n" // Cb2green + Cr2green == green
+ "pmullw MMX16_Ycoeff, %%mm7\n" // lum2
+
+ "movq %%mm6, %%mm4\n" // lum1
+ "paddw %%mm0, %%mm6\n" // lum1 +blue 00 B6 00 B4 00 B2 00 B0
+ "movq %%mm4, %%mm5\n" // lum1
+ "paddw %%mm1, %%mm4\n" // lum1 +red 00 R6 00 R4 00 R2 00 R0
+ "paddw %%mm2, %%mm5\n" // lum1 +green 00 G6 00 G4 00 G2 00 G0
+ "psraw $6, %%mm4\n" // R1 0 .. 64
+ "movq %%mm7, %%mm3\n" // lum2 00 L7 00 L5 00 L3 00 L1
+ "psraw $6, %%mm5\n" // G1 - .. +
+ "paddw %%mm0, %%mm7\n" // Lum2 +blue 00 B7 00 B5 00 B3 00 B1
+ "psraw $6, %%mm6\n" // B1 0 .. 64
+ "packuswb %%mm4, %%mm4\n" // R1 R1
+ "packuswb %%mm5, %%mm5\n" // G1 G1
+ "packuswb %%mm6, %%mm6\n" // B1 B1
+ "punpcklbw %%mm4, %%mm4\n"
+ "punpcklbw %%mm5, %%mm5\n"
+
+ "pand MMX16_redmask, %%mm4\n"
+ "psllw $3, %%mm5\n" // GREEN 1
+ "punpcklbw %%mm6, %%mm6\n"
+ "pand MMX16_grnmask, %%mm5\n"
+ "pand MMX16_redmask, %%mm6\n"
+ "por %%mm5, %%mm4\n" //
+ "psrlw $11, %%mm6\n" // BLUE 1
+ "movq %%mm3, %%mm5\n" // lum2
+ "paddw %%mm1, %%mm3\n" // lum2 +red 00 R7 00 R5 00 R3 00 R1
+ "paddw %%mm2, %%mm5\n" // lum2 +green 00 G7 00 G5 00 G3 00 G1
+ "psraw $6, %%mm3\n" // R2
+ "por %%mm6, %%mm4\n" // MM4
+ "psraw $6, %%mm5\n" // G2
+
+ "movl %2,16%5\n" // store register in tmp0
+ "movl %5,%2\n" // lum2->register
+ "movq (%2),%%mm6\n" // 0 0 0 0 L3 L2 L1 L0 (load lum2)
+
+
+ //"movq (%2, %5), %%mm6\n" // L3 load lum2
+ "psraw $6, %%mm7\n"
+ "packuswb %%mm3, %%mm3\n"
+ "packuswb %%mm5, %%mm5\n"
+ "packuswb %%mm7, %%mm7\n"
+ "pand MMX16_00FFw, %%mm6\n" // L3
+ "punpcklbw %%mm3, %%mm3\n"
+ // "psubw MMX16_10w, %%mm6\n" // L3
+ "punpcklbw %%mm5, %%mm5\n"
+ "pmullw MMX16_Ycoeff, %%mm6\n" // lum3
+ "punpcklbw %%mm7, %%mm7\n"
+ "psllw $3, %%mm5\n" // GREEN 2
+ "pand MMX16_redmask, %%mm7\n"
+ "pand MMX16_redmask, %%mm3\n"
+ "psrlw $11, %%mm7\n" // BLUE 2
+ "pand MMX16_grnmask, %%mm5\n"
+ "por %%mm7, %%mm3\n"
+
+ "movq (%2), %%mm7\n" // L4 load lum2
+ "movl 16%5,%2\n" // tmp0->register
+
+ "por %%mm5, %%mm3\n" //
+ "psrlw $8, %%mm7\n" // L4
+ "movq %%mm4, %%mm5\n"
+ // "psubw MMX16_10w, %%mm7\n" // L4
+ "punpcklwd %%mm3, %%mm4\n"
+ "pmullw MMX16_Ycoeff, %%mm7\n" // lum4
+ "punpckhwd %%mm3, %%mm5\n"
+
+ "movq %%mm4, (%3)\n" // write row1
+ "movq %%mm5, 8(%3)\n" // write row1
+
+ "movq %%mm6, %%mm4\n" // Lum3
+ "paddw %%mm0, %%mm6\n" // Lum3 +blue
+
+ "movq %%mm4, %%mm5\n" // Lum3
+ "paddw %%mm1, %%mm4\n" // Lum3 +red
+ "paddw %%mm2, %%mm5\n" // Lum3 +green
+ "psraw $6, %%mm4\n"
+ "movq %%mm7, %%mm3\n" // Lum4
+ "psraw $6, %%mm5\n"
+ "paddw %%mm0, %%mm7\n" // Lum4 +blue
+ "psraw $6, %%mm6\n" // Lum3 +blue
+ "movq %%mm3, %%mm0\n" // Lum4
+ "packuswb %%mm4, %%mm4\n"
+ "paddw %%mm1, %%mm3\n" // Lum4 +red
+ "packuswb %%mm5, %%mm5\n"
+ "paddw %%mm2, %%mm0\n" // Lum4 +green
+ "packuswb %%mm6, %%mm6\n"
+ "punpcklbw %%mm4, %%mm4\n"
+ "punpcklbw %%mm5, %%mm5\n"
+ "punpcklbw %%mm6, %%mm6\n"
+ "psllw $3, %%mm5\n" // GREEN 3
+ "pand MMX16_redmask, %%mm4\n"
+ "psraw $6, %%mm3\n" // psr 6
+ "psraw $6, %%mm0\n"
+ "pand MMX16_redmask, %%mm6\n" // BLUE
+ "pand MMX16_grnmask, %%mm5\n"
+ "psrlw $11, %%mm6\n" // BLUE 3
+ "por %%mm5, %%mm4\n"
+ "psraw $6, %%mm7\n"
+ "por %%mm6, %%mm4\n"
+ "packuswb %%mm3, %%mm3\n"
+ "packuswb %%mm0, %%mm0\n"
+ "packuswb %%mm7, %%mm7\n"
+ "punpcklbw %%mm3, %%mm3\n"
+ "punpcklbw %%mm0, %%mm0\n"
+ "punpcklbw %%mm7, %%mm7\n"
+ "pand MMX16_redmask, %%mm3\n"
+ "pand MMX16_redmask, %%mm7\n" // BLUE
+ "psllw $3, %%mm0\n" // GREEN 4
+ "psrlw $11, %%mm7\n"
+ "pand MMX16_grnmask, %%mm0\n"
+ "por %%mm7, %%mm3\n"
+ "por %%mm0, %%mm3\n"
+
+ "movq %%mm4, %%mm5\n"
+
+ "punpcklwd %%mm3, %%mm4\n"
+ "punpckhwd %%mm3, %%mm5\n"
+
+ "movq %%mm4, (%4)\n"
+ "movq %%mm5, 8(%4)\n"
+
+ "subl $8, 8%5\n" // x-=8
+ "addl $8, %5\n" // lum2+8
+ "addl $8, %2\n"
+ "addl $4, %0\n"
+ "addl $4, %1\n"
+ "cmpl $0, 8%5\n"
+ "leal 16(%3), %3\n"
+ "leal 16(%4), %4\n" // row2+16
+
+
+ "jne 1b\n"
+ "addl 20%5, %2\n" // lum += cols
+
+ "movl %2,16%5\n" // store register in tmp0
+ "movl 20%5,%2\n" // cols->register
+
+ "addl %2, %5\n" // lum2 += cols
+ "addl 12%5, %3\n" // row1+= mod
+ "addl 12%5, %4\n" // row2+= mod
+ "movl %2, 8%5\n" // x=cols
+ "movl 16%5,%2\n" // store tmp0 in register
+
+ "cmpl 4%5, %2\n"
+ "jl 1b\n"
+
+ :
+ :"r" (cr), "r"(cb),"r"(lum),
+ "r"(row1),"r"(row2),"m"(buf[0])
+
+ );
+ __asm__ (
+ "emms\n"
+ );
+
+ }
+
+#endif
diff --git a/mpeglib/lib/util/render/dither2YUV/Makefile.am b/mpeglib/lib/util/render/dither2YUV/Makefile.am
new file mode 100644
index 00000000..374658a3
--- /dev/null
+++ b/mpeglib/lib/util/render/dither2YUV/Makefile.am
@@ -0,0 +1,22 @@
+# libdivxplugin - Makefile.am
+
+EXTRA_DIST = README
+
+INCLUDES = -I.. $(all_includes)
+
+
+noinst_LTLIBRARIES = libdivxutil_dither.la
+
+noinst_HEADERS = dither2YUV.h rgb2yuvdefs.h rgb2yuv16.h \
+ rgb2yuv32.h
+
+libdivxutil_dither_la_SOURCES = dither2YUV.cpp rgb2yuv16.cpp \
+ rgb2yuv32.cpp
+
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/util/render/dither2YUV/README b/mpeglib/lib/util/render/dither2YUV/README
new file mode 100644
index 00000000..66246c13
--- /dev/null
+++ b/mpeglib/lib/util/render/dither2YUV/README
@@ -0,0 +1,13 @@
+
+
+* we have a Dither2Yuv base class. Currently this is not derived
+ from a basic ditherWrapper class because we don not have this
+ in mpeglib yet.
+ TODO: change in mpeglib DitherWrapper->Dither2RGB and
+ make DitherWrapper pure virtual and derive Dither2YUV
+ Dither2RGB from this class.
+
+* Note we do not support 8 Bit here, thus the constructor looks
+ dofferent.
+
+
diff --git a/mpeglib/lib/util/render/dither2YUV/dither2YUV.cpp b/mpeglib/lib/util/render/dither2YUV/dither2YUV.cpp
new file mode 100644
index 00000000..db4a3288
--- /dev/null
+++ b/mpeglib/lib/util/render/dither2YUV/dither2YUV.cpp
@@ -0,0 +1,124 @@
+/*
+ this class dithery RGB picture to yuv12
+ 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 "dither2YUV.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+Dither2YUV::Dither2YUV() {
+
+
+ lmmx=mm_support();
+
+}
+
+
+Dither2YUV::~Dither2YUV(){
+}
+
+
+
+
+
+
+void Dither2YUV::doDither(YUVPicture* pic,int depth,int ditherSize,
+ unsigned char* dest,int offset) {
+
+ int inputType=pic->getImageType();
+
+ switch(inputType) {
+ case PICTURE_RGB:
+ doDitherRGB_NORMAL(pic,depth,ditherSize,dest,offset);
+ break;
+ default:
+ std::cout << "unknown RGB type:"<<inputType<<" in Dither2YUV"<<std::endl;
+ exit(0);
+ }
+}
+
+
+void Dither2YUV::doDitherRGB_NORMAL(YUVPicture* rgbPic,
+ int depth,int ditherSize,
+ unsigned char* dest,int offset) {
+
+ switch (ditherSize) {
+ case _SIZE_NORMAL:
+ doDither2YUV_std(rgbPic,depth,dest,offset);
+ break;
+ case _SIZE_DOUBLE:
+ std::cout << "double not supported for RGB"<<std::endl;
+ break;
+ default:
+ std::cout << "unknown size:"<<ditherSize<<" in Dither2YUV"<<std::endl;
+ exit(0);
+ }
+}
+
+
+void Dither2YUV::doDither2YUV_std(YUVPicture* rgbPic,int depth,
+ unsigned char* dest,int offset){
+
+ int h=rgbPic->getHeight();
+ int w=rgbPic->getWidth();
+ int lumLength=w * h;
+ int colorLength=(w * h) / 4;
+
+ unsigned char* lum=dest;
+ unsigned char* cr=lum+lumLength;
+ unsigned char* cb=cr+colorLength;
+ unsigned char* rgbSource=rgbPic->getImagePtr();
+
+
+ switch (depth) {
+ case 8:
+ std::cout << "8 bit dither to yuv not supported"<<std::endl;
+ exit(0);
+ break;
+ case 16:
+ if (lmmx) {
+#ifdef INTEL
+ rgb2yuv16bit_mmx(rgbSource,lum,cr,cb,h,w);
+#endif
+ } else {
+ rgb2yuv16bit(rgbSource,lum,cr,cb,h,w);
+ }
+
+ break;
+ case 24:
+ if (lmmx) {
+#ifdef INTEL
+ rgb2yuv24bit_mmx(rgbSource,lum,cr,cb,h,w);
+#endif
+ } else {
+ rgb2yuv24bit(rgbSource,lum,cr,cb,h,w);
+ }
+ break;
+ case 32:
+ if (lmmx) {
+#ifdef INTEL
+ rgb2yuv32bit_mmx(rgbSource,lum,cr,cb,h,w);
+#endif
+ } else {
+ rgb2yuv32bit(rgbSource,lum,cr,cb,h,w);
+ }
+ break;
+ default:
+ std::cout << "cannot dither depth:"<<depth<<std::endl;
+ }
+
+}
+
+
diff --git a/mpeglib/lib/util/render/dither2YUV/dither2YUV.h b/mpeglib/lib/util/render/dither2YUV/dither2YUV.h
new file mode 100644
index 00000000..5ef26b2b
--- /dev/null
+++ b/mpeglib/lib/util/render/dither2YUV/dither2YUV.h
@@ -0,0 +1,64 @@
+/*
+ this class dithery RGB picture to yuv12
+ 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 __DITHER2YUV_H
+#define __DITHER2YUV_H
+
+
+#include "../../mmx/mmx.h"
+#include "../yuvPicture.h"
+
+
+#include <stdlib.h>
+#include "rgb2yuv16.h"
+#include "rgb2yuv32.h"
+
+#define _SIZE_NONE 0
+#define _SIZE_NORMAL 1
+#define _SIZE_DOUBLE 2
+
+
+/**
+ Wraps all calls to software ditherer and the different
+ resolutions,mmx enhancements, and doublesize ditherers.
+*/
+
+
+class Dither2YUV {
+
+ int lmmx;
+
+ int bpp;
+
+
+ public:
+ Dither2YUV();
+ ~Dither2YUV();
+
+ int getDitherSize();
+ void setDitherSize(int ditherSize);
+
+ void doDither(YUVPicture* pic,int depth,int ditherSize,
+ unsigned char* dest,int offset);
+
+
+ private:
+ void doDitherRGB_NORMAL(YUVPicture* pic,int depth,int ditherSize,
+ unsigned char* dest,int offset);
+
+ void doDither2YUV_std(YUVPicture* pic,int depth,
+ unsigned char* dest,int offset);
+
+};
+
+#endif
diff --git a/mpeglib/lib/util/render/dither2YUV/rgb2yuv16.cpp b/mpeglib/lib/util/render/dither2YUV/rgb2yuv16.cpp
new file mode 100644
index 00000000..e0d7fc86
--- /dev/null
+++ b/mpeglib/lib/util/render/dither2YUV/rgb2yuv16.cpp
@@ -0,0 +1,916 @@
+/***************************************************************************
+ rgb2yuv16.c - description
+ -------------------
+ begin : Tue Nov 2 2000
+ copyright : (C) 2000 by Christian Gerlach
+ email : cgerlach@rhrk.uni-kl.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "rgb2yuv16.h"
+#include <iostream>
+
+static unsigned short KEEPR[4] = { 63488, 63488, 63488, 63488 };
+unsigned short KEEPG[4] = { 2016, 2016, 2016, 2016 };
+unsigned short KEEPB[4] = { 31, 31, 31, 31 };
+
+short Y_RED[4] = { 307, 307, 307, 307 };
+short Y_GREEN[4] = { 302, 302, 302, 302 };
+short Y_BLUE[4] = { 117, 117, 117, 117 };
+
+short U_RED[4] = { -150, -150, -150, -150 };
+short U_GREEN[4] = { -147, -147, -147, -147 };
+short U_BLUE[4] = { 444, 444, 444, 444 };
+
+short V_RED[4] = { 632, 632, 632, 632 };
+short V_GREEN[4] = { -265, -265, -265, -265 };
+short V_BLUE[4] = { -102, -102, -102, -102 };
+
+
+// how to avoid these nasty compiler warinings?
+// heres one (maybe bad) method
+void dummyRGB2YUV16Bit() {
+
+ printf("%p\n",KEEPR);
+ printf("%p\n",KEEPG);
+ printf("%p\n",KEEPB);
+ printf("%p\n",Y_RED);
+ printf("%p\n",Y_GREEN);
+ printf("%p\n",Y_BLUE);
+ printf("%p\n",U_RED);
+ printf("%p\n",U_GREEN);
+ printf("%p\n",U_BLUE);
+ printf("%p\n",V_RED);
+ printf("%p\n",V_GREEN);
+ printf("%p\n",V_BLUE);
+}
+
+
+#ifndef INTEL
+void rgb2yuv16bit_mmx(unsigned char* ,unsigned char* ,unsigned char* ,
+ unsigned char* ,int , int ) {
+ std::cout << "RGB->YUV not compiled with INTEL" << std::endl;
+ exit(0);
+}
+
+void rgb2yuv16bit_mmx_fast(unsigned char* ,unsigned char* ,unsigned char* ,
+ unsigned char* ,int , int ) {
+ std::cout << "RGB->YUV not compiled with INTEL" << std::endl;
+ exit(0);
+}
+#endif
+
+
+void rgb2yuv16(unsigned char* rgbSource, unsigned char* dest)
+{
+ int rgb = *((unsigned short*) rgbSource++ );
+ int r = RED(rgb);
+ int g = GREEN(rgb);
+ int b = BLUE(rgb);
+
+ dest[0] = Y_RGB(r, g, b);
+ dest[1] = U_RGB(r, g, b);
+ dest[2] = V_RGB(r, g, b);
+}
+
+void rgb2yuv16bit(unsigned char* rgbSource,
+ unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,int height, int width) {
+
+ int height2 = height / 2;
+ int width2 = width / 2;
+ int r, g, b, row, col, rgb;
+
+ for (row=0 ; row<height2 ; row++) {
+ for (col=0 ; col<width2 ; col++) {
+ rgb = *((unsigned short*) rgbSource++ );
+ r = RED(rgb);
+ g = GREEN(rgb);
+ b = BLUE(rgb);
+
+ *lum++ = Y_RGB(r, g, b);
+ *cr++ = U_RGB(r, g, b);
+ *cb++ = V_RGB(r, g, b);
+
+ rgb = *((unsigned short*) rgbSource++ );
+ r = RED(rgb);
+ g = GREEN(rgb);
+ b = BLUE(rgb);
+
+ *lum++ = Y_RGB(r, g, b);
+ }
+ for (col=0 ; col<width ; col++) {
+ rgb = *((unsigned short*) rgbSource++ );
+ r = RED(rgb);
+ g = GREEN(rgb);
+ b = BLUE(rgb);
+
+ *lum++ = Y_RGB(r, g, b);
+ }
+ }
+}
+
+
+#ifdef INTEL
+
+void rgb2yuv16bit_mmx(unsigned char* rgbSource,
+ unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,int height, int width) {
+ int height2 = height / 2;
+ int width2 = width / 2;
+ int bytesPerLine = width * 2;
+
+ for (int row=0 ; row<height2 ; row++) {
+ rgb2yuv16bit_mmx422_row(rgbSource, lum, cr, cb, width);
+ rgbSource += bytesPerLine;
+ lum += width;
+ cr += width2;
+ cb += width2;
+
+ rgb2y16bit_mmx_row(rgbSource, lum, width);
+ rgbSource += bytesPerLine;
+ lum += width;
+ }
+}
+
+void rgb2yuv16bit_mmx_fast(unsigned char* rgbSource,
+ unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,int height, int width) {
+
+ int height2 = height / 2;
+ int width2 = width / 2;
+ int bytesPerLine = width * 2;
+
+ for (int row=0 ; row<height2 ; row++) {
+ rgb2yuv16bit_mmx422_row_fast(rgbSource, lum, cr, cb, width);
+ rgbSource += bytesPerLine;
+ lum += width;
+ cr += width2;
+ cb += width2;
+
+ rgb2y16bit_mmx_row_fast(rgbSource, lum, width);
+ rgbSource += bytesPerLine;
+ lum += width;
+ }
+}
+
+void rgb2yuv16bit_mmx422_row(unsigned char* rgb,
+ unsigned char* lum, unsigned char* cr,
+ unsigned char* cb, int pixel) {
+ unsigned int buf[17];
+
+ // 36%5 = TEMP0
+ // 44%5 = TEMPY
+ // 52%5 = TEMPU
+ // 60%5 = TEMPV
+
+ __asm__ __volatile__ (
+ "1:\n"
+
+ // unpack hicolor ( pixel 1 - 4)
+ "movq (%0), %%mm0\n"
+
+ "movq %%mm0, %%mm1\n"
+ "pand KEEPR, %%mm1\n"
+ "psrlq $8, %%mm1\n" // B3B2B1B0 -> mm1
+ "movq %%mm0, %%mm2\n"
+ "pand KEEPG, %%mm2\n"
+ "psrlq $3, %%mm2\n" // G3G2G1G0 -> mm2
+ "movq %%mm0, %%mm3\n"
+ "pand KEEPB, %%mm3\n"
+ "psllq $3, %%mm3\n" // G3G2G1G0 -> mm3
+
+ "movq %%mm2, %%mm0\n"
+ "punpcklbw %%mm1, %%mm2\n"
+ "punpckhbw %%mm1, %%mm0\n"
+
+ "pxor %%mm5, %%mm5\n"
+ "movq %%mm3, %%mm4\n"
+ "punpcklbw %%mm5, %%mm3\n"
+ "punpckhbw %%mm5, %%mm4\n"
+
+ "psllq $8, %%mm2\n"
+ "por %%mm2, %%mm3\n" // 0B1G1R10B0G0G0 -> mm3
+ "psllq $8, %%mm0\n"
+ "por %%mm0, %%mm4\n" // 0B3G3R30B2G2G2 -> mm4
+
+ "movq %%mm3, %5\n"
+ "movq %%mm4, 8%5\n"
+
+ // next 4 pixels ------------------------------
+
+ "movq 8(%0), %%mm0\n"
+
+ "movq %%mm0, %%mm1\n"
+ "pand KEEPR, %%mm1\n"
+ "psrlq $8, %%mm1\n" // B3B2B1B0 -> mm1
+ "movq %%mm0, %%mm2\n"
+ "pand KEEPG, %%mm2\n"
+ "psrlq $3, %%mm2\n" // G3G2G1G0 -> mm2
+ "movq %%mm0, %%mm3\n"
+ "pand KEEPB, %%mm3\n"
+ "psllq $3, %%mm3\n" // G3G2G1G0 -> mm3
+
+ "movq %%mm2, %%mm0\n"
+ "punpcklbw %%mm1, %%mm2\n"
+ "punpckhbw %%mm1, %%mm0\n"
+
+ "pxor %%mm5, %%mm5\n"
+ "movq %%mm3, %%mm4\n"
+ "punpcklbw %%mm5, %%mm3\n"
+ "punpckhbw %%mm5, %%mm4\n"
+
+ "psllq $8, %%mm2\n"
+ "por %%mm2, %%mm3\n" // 0B1G1R10B0G0G0 -> mm3
+ "psllq $8, %%mm0\n"
+ "por %%mm0, %%mm4\n" // 0B3G3R30B2G2G2 -> mm4
+
+ "movq %%mm3, 16%5\n"
+ "movq %%mm4, 24%5\n"
+
+ "add $16, %0\n"
+
+ // standard algorithm --------------------------------------------------
+
+ // pack rgb
+ // was: "movq (%0), %%mm1\n" // load G2R2B1G1R1B0G0R0
+ // ------------------------------
+ // (uses: mm0, mm1)
+ "movd 8%5, %%mm0\n"
+ "psllq $24, %%mm0\n"
+ "movd 4%5, %%mm1\n"
+ "por %%mm1, %%mm0\n"
+ "psllq $24, %%mm0\n"
+ "movd %5, %%mm1\n"
+ "por %%mm0, %%mm1\n"
+ // ------------------------------
+
+ "pxor %%mm6, %%mm6\n" // 0 -> mm6
+ "movq %%mm1, %%mm0\n" // G2R2B1G1R1B0G0R0 -> mm0
+ "psrlq $16, %%mm1\n" // 00G2R2B1G1R1B0 -> mm1
+ "punpcklbw ZEROSX, %%mm0\n" // R1B0G0R0 -> mm0
+ "movq %%mm1, %%mm7\n" // 00G2R2B1G1R1B0 -> mm7
+ "punpcklbw ZEROSX, %%mm1\n" // B1G1R1B0 -> mm1
+ "movq %%mm0, %%mm2\n" // R1B0G0R0 -> mm2
+ "pmaddwd YR0GRX, %%mm0\n" // yrR1,ygG0+yrR0 -> mm0
+
+ "movq %%mm1, %%mm3\n" // B1G1R1B0 -> mm3
+ "pmaddwd YBG0BX, %%mm1\n" // ybB1+ygG1,ybB0 -> mm1
+ "movq %%mm2, %%mm4\n" // R1B0G0R0 -> mm4
+ "pmaddwd UR0GRX, %%mm2\n" // urR1,ugG0+urR0 -> mm2
+ "movq %%mm3, %%mm5\n" // B1G1R1B0 -> mm5
+ "pmaddwd UBG0BX, %%mm3\n" // ubB1+ugG1,ubB0 -> mm3
+ "punpckhbw %%mm6, %%mm7\n" // 00G2R2 -> mm7
+ "pmaddwd VR0GRX, %%mm4\n" // vrR1,vgG0+vrR0 -> mm4
+ "paddd %%mm1, %%mm0\n" // Y1Y0 -> mm0
+
+ "pmaddwd VBG0BX, %%mm5\n" // vbB1+vgG1,vbB0 -> mm5
+
+ // pack rgb
+ // was: "movq 8(%0),%%mm1\n" // R5B4G4R4B3G3R3B2 -> mm1
+ // ------------------------------
+ // (uses: mm1, mm6)
+ "movd 20%5, %%mm1\n"
+ "psllq $24, %%mm1\n"
+ "movd 16%5, %%mm6\n"
+ "por %%mm6, %%mm1\n"
+ "psllq $24, %%mm1\n"
+ "movd 12%5, %%mm6\n"
+ "por %%mm6, %%mm1\n"
+ "psllq $8, %%mm1\n"
+ "movd 8%5, %%mm6\n"
+ "psrlq $16, %%mm6\n"
+ "por %%mm6, %%mm1\n"
+ // ------------------------------
+
+ "paddd %%mm3, %%mm2\n" // U1U0 -> mm2
+
+ "movq %%mm1, %%mm6\n" // R5B4G4R4B3G3R3B2 -> mm6
+ "punpcklbw ZEROSX, %%mm1\n" // B3G3R3B2 -> mm1
+ "paddd %%mm5, %%mm4\n" // V1V0 -> mm4
+
+ //----------------------------------------------------------------------
+
+ "movq %%mm1, %%mm5\n" // B3G3R3B2 -> mm5
+ "psllq $32, %%mm1\n" // R3B200 -> mm1
+
+ "paddd %%mm7, %%mm1\n" // R3B200+00G2R2=R3B2G2R2->mm1
+
+ "punpckhbw ZEROSX, %%mm6\n" // R5B4G4R3 -> mm6
+ "movq %%mm1, %%mm3\n" // R3B2G2R2 -> mm3
+
+ "pmaddwd YR0GRX, %%mm1\n" // yrR3,ygG2+yrR2 -> mm1
+ "movq %%mm5, %%mm7\n" // B3G3R3B2 -> mm7
+
+ "pmaddwd YBG0BX, %%mm5\n" // ybB3+ygG3,ybB2 -> mm5
+ "psrad $15, %%mm0\n" // 32-bit scaled Y1Y0 -> mm0
+
+ "movq %%mm6, 36%5\n" // R5B4G4R4 -> TEMP0
+ "movq %%mm3, %%mm6\n" // R3B2G2R2 -> mm6
+ "pmaddwd UR0GRX, %%mm6\n" // urR3,ugG2+urR2 -> mm6
+ "psrad $15, %%mm2\n" // 32-bit scaled U1U0 -> mm2
+
+ "paddd %%mm5, %%mm1\n" // Y3Y2 -> mm1
+ "movq %%mm7, %%mm5\n" // B3G3R3B2 -> mm5
+ "pmaddwd UBG0BX, %%mm7\n" // ubB3+ugG3,ubB2
+ "psrad $15, %%mm1\n" // 32-bit scaled Y3Y2 -> mm1
+
+ "pmaddwd VR0GRX, %%mm3\n" // vrR3,vgG2+vgR2
+ "packssdw %%mm1, %%mm0\n" // Y3Y2Y1Y0 -> mm0
+
+ "pmaddwd VBG0BX, %%mm5\n" // vbB3+vgG3,vbB2 -> mm5
+ "psrad $15, %%mm4\n" // 32-bit scaled V1V0 -> mm4
+
+ //----------------------------------------------------------------------
+
+ "paddd %%mm7, %%mm6\n" // U3U2 -> mm6
+
+ // pack rgb
+ // was: "movq 16(%0), %%mm1\n" // B7G7R7B6G6R6B5G5 -> mm1
+ // ------------------------------
+ // (uses: mm1, mm7)
+ "movd 28%5, %%mm1\n"
+ "psllq $24, %%mm1\n"
+ "movd 24%5, %%mm7\n"
+ "por %%mm7, %%mm1\n"
+ "psllq $16, %%mm1\n"
+ "movd 20%5, %%mm7\n"
+ "psrlq $8, %%mm7\n"
+ "por %%mm7, %%mm1\n"
+ // ------------------------------
+
+ "movq %%mm1, %%mm7\n" // B7G7R7B6G6R6B5G5 -> mm1
+ "psrad $15, %%mm6\n" // 32-bit scaled U3U2 -> mm6
+
+ "paddd %%mm5, %%mm3\n" // V3V2 -> mm3
+ "psllq $16, %%mm7\n" // R7B6G6R6B5G500 -> mm7
+
+ "movq %%mm7, %%mm5\n" // R7B6G6R6B5G500 -> mm5
+ "psrad $15, %%mm3\n" // 32-bit scaled V3V2 -> mm3
+
+ "movq %%mm0, 44%5\n" // 32-bit scaled Y3Y2Y1Y0 -> TEMPY
+
+ "packssdw %%mm6, %%mm2\n" // 32-bit scaled U3U2U1U0 -> mm2
+
+ "movq 36%5, %%mm0\n" // R5B4G4R4 -> mm0
+
+ "punpcklbw ZEROSX, %%mm7\n" // B5G500 -> mm7
+ "movq %%mm0, %%mm6\n" // R5B4G4R4 -> mm6
+
+ "movq %%mm2, 52%5\n" // 32-bit scaled U3U2U1U0 -> TEMPU
+ "psrlq $32, %%mm0\n" // 00R5B4 -> mm0
+
+ "paddw %%mm0, %%mm7\n" // B5G5R5B4 -> mm7
+ "movq %%mm6, %%mm2\n" // B5B4G4R4 -> mm2
+
+ "pmaddwd YR0GRX, %%mm2\n" // yrR5,ygG4+yrR4 -> mm2
+ "movq %%mm7, %%mm0\n" // B5G5R5B4 -> mm0
+
+ "pmaddwd YBG0BX, %%mm7\n" // ybB5+ygG5,ybB4 -> mm7
+ "packssdw %%mm3, %%mm4\n" // 32-bit scaled V3V2V1V0 -> mm4
+
+ //----------------------------------------------------------------------
+
+ "movq %%mm4, 60%5\n" // (V3V2V1V0)/256 -> mm4
+
+ "movq %%mm6, %%mm4\n" // B5B4G4R4 -> mm4
+
+ "pmaddwd UR0GRX, %%mm6\n" // urR5,ugG4+urR4
+ "movq %%mm0, %%mm3\n" // B5G5R5B4 -> mm0
+
+ "pmaddwd UBG0BX, %%mm0\n" // ubB5+ugG5,ubB4
+ "paddd %%mm7, %%mm2\n" // Y5Y4 -> mm2
+
+ //----------------------------------------------------------------------
+
+ "pmaddwd VR0GRX, %%mm4\n" // vrR5,vgG4+vrR4 -> mm4
+ "pxor %%mm7, %%mm7\n" // 0 -> mm7
+
+ "pmaddwd VBG0BX, %%mm3\n" // vbB5+vgG5,vbB4 -> mm3
+ "punpckhbw %%mm7, %%mm1\n" // B7G7R7B6 -> mm1
+
+ "paddd %%mm6, %%mm0\n" // U5U4 -> mm0
+ "movq %%mm1, %%mm6\n" // B7G7R7B6 -> mm6
+
+ "pmaddwd YBG0BX, %%mm6\n" // ybB7+ygG7,ybB6 -> mm6
+ "punpckhbw %%mm7, %%mm5\n" // R7B6G6R6 -> mm5
+
+ "movq %%mm5, %%mm7\n" // R7B6G6R6 -> mm7
+ "paddd %%mm4, %%mm3\n" // V5V4 -> mm3
+
+ "pmaddwd YR0GRX, %%mm5\n" // yrR7,ygG6+yrR6 -> mm5
+ "movq %%mm1, %%mm4\n" // B7G7R7B6 -> mm4
+
+ "pmaddwd UBG0BX, %%mm4\n" // ubB7+ugG7,ubB6 -> mm4
+ "psrad $15, %%mm0\n" // 32-bit scaled U5U4 -> %%mm0
+
+ //----------------------------------------------------------------------
+
+ "paddd OFFSETWX, %%mm0\n" // add offset to U5U4 -> mm0
+ "psrad $15, %%mm2\n" // 32-bit scaled Y5Y4 -> mm2
+
+ "paddd %%mm5, %%mm6\n" // Y7Y6 -> mm6
+ "movq %%mm7, %%mm5\n" // R7B6G6R6 -> mm5
+
+ "pmaddwd UR0GRX, %%mm7\n" // urR7,ugG6+ugR6 -> mm7
+ "psrad $15, %%mm3\n" // 32-bit scaled V5V4 -> mm3
+
+ "pmaddwd VBG0BX, %%mm1\n" // vbB7+vgG7,vbB6 -> mm1
+ "psrad $15, %%mm6\n" // 32-bit scaled Y7Y6 -> mm6
+
+ "paddd OFFSETDX, %%mm4\n" // add offset to U7U6
+ "packssdw %%mm6, %%mm2\n" // Y7Y6Y5Y4 -> mm2
+
+ "pmaddwd VR0GRX, %%mm5\n" // vrR7,vgG6+vrR6 -> mm5
+ "paddd %%mm4, %%mm7\n" // U7U6 -> mm7
+
+ "psrad $15, %%mm7\n" // 32-bit scaled U7U6 -> mm7
+
+ //----------------------------------------------------------------------
+
+ "movq 44%5, %%mm6\n" // 32-bit scaled Y3Y2Y1Y0 -> mm6
+ "packssdw %%mm7, %%mm0\n" // 32-bit scaled U7U6U5U4 -> mm0
+
+ "movq 52%5, %%mm4\n" // 32-bit scaled U3U2U1U0 -> mm4
+ "packuswb %%mm2, %%mm6\n" // all 8 Y values -> mm6
+
+ "movq OFFSETBX, %%mm7\n" // 128,128,128,128 -> mm7
+ "paddd %%mm5, %%mm1\n" // V7V6 -> mm1
+
+ "paddw %%mm7, %%mm4\n" // add offset to U3U2U1U0/256
+ "psrad $15, %%mm1\n" // 32-bit scaled V7V6 -> mm1
+
+ //----------------------------------------------------------------------
+
+ "movq %%mm6, (%1)\n" // store Y
+
+ "packuswb %%mm0, %%mm4\n" // all 8 U values -> mm4
+ "movq 60%5, %%mm5\n" // 32-bit scaled V3V2V1V0 -> mm5
+
+ "packssdw %%mm1, %%mm3\n" // V7V6V5V4 -> mm3
+ "paddw %%mm7, %%mm5\n" // add offset to V3V2V1V0
+ "paddw %%mm7, %%mm3\n" // add offset to V7V6V5V4
+
+ "packuswb %%mm3, %%mm5\n" // ALL 8 V values -> mm5
+
+ "movq CLEARX, %%mm2\n"
+ "pand %%mm2, %%mm4\n"
+ "pand %%mm2, %%mm5\n"
+
+ "packuswb %%mm5, %%mm4\n"
+
+ "movd %%mm4, (%2)\n"
+ "psrlq $32, %%mm4\n"
+ "movd %%mm4, (%3)\n"
+
+ "add $8, %1\n"
+ "add $4, %2\n"
+ "add $4, %3\n"
+
+ "sub $8, %4\n"
+ "jnz 1b\n"
+
+ "emms\n"
+
+ :
+ : "r" (rgb), "r" (lum), "r" (cr), "r" (cb),
+ "m" (pixel), "m" (buf[0])
+
+ );
+}
+
+void rgb2yuv16bit_mmx422_row_fast(unsigned char* rgb,
+ unsigned char* lum, unsigned char* cr,
+ unsigned char* cb, int pixel)
+{
+ __asm__ __volatile__ (
+ "1:\n"
+
+ // unpack hicolor ( pixel 0 - 3)
+ "movq (%0), %%mm0\n"
+
+ "movq %%mm0, %%mm1\n"
+ "pand KEEPR, %%mm1\n"
+ "psrlq $11, %%mm1\n" // B3B2B1B0 -> mm1
+
+ "movq %%mm0, %%mm2\n"
+ "pand KEEPG, %%mm2\n"
+ "psrlq $5, %%mm2\n" // G3G2G1G0 -> mm2
+
+ "movq %%mm0, %%mm3\n"
+ "pand KEEPB, %%mm3\n" // R3R2R1R0 -> mm3
+
+ // unpack hicolor ( pixel 4 - 7)
+ "movq 8(%0), %%mm0\n"
+
+ "movq %%mm0, %%mm4\n"
+ "pand KEEPR, %%mm4\n"
+ "psrlq $11, %%mm4\n" // B7B6B5B4 -> mm4
+
+ "movq %%mm0, %%mm5\n"
+ "pand KEEPG, %%mm5\n"
+ "psrlq $5, %%mm5\n" // G7G6G5G4 -> mm5
+
+ "movq %%mm0, %%mm6\n"
+ "pand KEEPB, %%mm6\n" // R7R6R5R4 -> mm6
+
+ // calculate Y
+ "movq %%mm6, %%mm7\n"
+ "pmullw Y_RED, %%mm7\n"
+
+ "movq %%mm5, %%mm0\n"
+ "pmullw Y_GREEN, %%mm0\n"
+ "paddw %%mm0, %%mm7\n"
+
+ "movq %%mm4, %%mm0\n"
+ "pmullw Y_BLUE, %%mm0\n"
+ "paddw %%mm0, %%mm7\n"
+
+ "psrlw $7, %%mm7\n" // Y3Y2Y1Y0 -> mm7
+
+ "pxor %%mm0, %%mm0\n"
+ "packuswb %%mm0, %%mm7\n"
+ "movd %%mm7, 4(%1)\n" // Y3Y2Y1Y0 -> lum
+
+ // --------
+
+ "movq %%mm3, %%mm7\n"
+ "pmullw Y_RED, %%mm7\n"
+
+ "movq %%mm2, %%mm0\n"
+ "pmullw Y_GREEN, %%mm0\n"
+ "paddw %%mm0, %%mm7\n"
+
+ "movq %%mm1, %%mm0\n"
+ "pmullw Y_BLUE, %%mm0\n"
+ "paddw %%mm0, %%mm7\n"
+
+ "psrlw $7, %%mm7\n" // Y7Y6Y5Y4 -> mm7
+
+ "pxor %%mm0, %%mm0\n"
+ "packuswb %%mm0, %%mm7\n"
+ "movd %%mm7, (%1)\n" // Y7Y6Y5Y4 -> lum
+ "add $8, %1\n"
+
+ // pack RGB
+ "packuswb %%mm4, %%mm1\n"
+ "pand CLEARX, %%mm1\n" // B6B4B2B0 -> mm1
+ "packuswb %%mm5, %%mm2\n"
+ "pand CLEARX, %%mm2\n" // GRG4G2G0 -> mm2
+ "packuswb %%mm6, %%mm3\n"
+ "pand CLEARX, %%mm3\n" // R6R4R2R0 -> mm3
+
+ // calculate U
+ "movq %%mm3, %%mm7\n"
+ "pmullw U_RED, %%mm7\n"
+
+ "movq %%mm2, %%mm0\n"
+ "pmullw U_GREEN, %%mm0\n"
+ "paddw %%mm0, %%mm7\n"
+
+ "movq %%mm1, %%mm0\n"
+ "pmullw U_BLUE, %%mm0\n"
+ "paddw %%mm0, %%mm7\n"
+
+ "psrlw $7, %%mm7\n" // U3U2U1U0 -> mm7
+ "paddw OFFSETBX,%%mm7\n"
+ "pand CLEARX, %%mm7\n"
+
+ "pxor %%mm0, %%mm0\n"
+ "packuswb %%mm0, %%mm7\n"
+ "movd %%mm7, (%2)\n" // U3U2U1U0 -> lum
+ "add $4, %2\n"
+
+ // calculate V
+ "movq %%mm3, %%mm7\n"
+ "pmullw V_RED, %%mm7\n"
+
+ "movq %%mm2, %%mm0\n"
+ "pmullw V_GREEN, %%mm0\n"
+ "paddw %%mm0, %%mm7\n"
+
+ "movq %%mm1, %%mm0\n"
+ "pmullw V_BLUE, %%mm0\n"
+ "paddw %%mm0, %%mm7\n"
+
+ "psrlw $7, %%mm7\n" // V3V2V1V0 -> mm7
+ "paddw OFFSETBX,%%mm7\n"
+ "pand CLEARX, %%mm7\n"
+
+ "pxor %%mm0, %%mm0\n"
+ "packuswb %%mm0, %%mm7\n"
+ "movd %%mm7, (%3)\n" // V3V2V1V0 -> lum
+ "add $4, %3\n"
+
+ "add $16, %0\n"
+
+ "sub $8, %4\n"
+ "jnz 1b\n"
+
+ "emms\n"
+
+ :
+ : "r" (rgb), "r" (lum), "r" (cr), "r" (cb), "m" (pixel)
+
+ );
+}
+
+void rgb2y16bit_mmx_row(unsigned char* rgbSource,
+ unsigned char* lum, int pixel)
+{
+ unsigned int buf[16];
+
+ // 36%3 = TEMP0
+ // 44%3 = TEMPY
+
+ __asm__ __volatile__ (
+ "1:\n"
+
+ // unpack hicolor ( pixel 1 - 4)
+ "movq (%0), %%mm0\n"
+
+ "movq %%mm0, %%mm1\n"
+ "pand KEEPR, %%mm1\n"
+ "psrlq $8, %%mm1\n" // B3B2B1B0 -> mm1
+ "movq %%mm0, %%mm2\n"
+ "pand KEEPG, %%mm2\n"
+ "psrlq $3, %%mm2\n" // G3G2G1G0 -> mm2
+ "movq %%mm0, %%mm3\n"
+ "pand KEEPB, %%mm3\n"
+ "psllq $3, %%mm3\n" // G3G2G1G0 -> mm3
+
+ "movq %%mm2, %%mm0\n"
+ "punpcklbw %%mm1, %%mm2\n"
+ "punpckhbw %%mm1, %%mm0\n"
+
+ "pxor %%mm5, %%mm5\n"
+ "movq %%mm3, %%mm4\n"
+ "punpcklbw %%mm5, %%mm3\n"
+ "punpckhbw %%mm5, %%mm4\n"
+
+ "psllq $8, %%mm2\n"
+ "por %%mm2, %%mm3\n" // 0B1G1R10B0G0G0 -> mm3
+ "psllq $8, %%mm0\n"
+ "por %%mm0, %%mm4\n" // 0B3G3R30B2G2G2 -> mm4
+
+ "movq %%mm3, %3\n"
+ "movq %%mm4, 8%3\n"
+
+ // next 4 pixels ------------------------------
+
+ "movq 8(%0), %%mm0\n"
+
+ "movq %%mm0, %%mm1\n"
+ "pand KEEPR, %%mm1\n"
+ "psrlq $8, %%mm1\n" // B3B2B1B0 -> mm1
+ "movq %%mm0, %%mm2\n"
+ "pand KEEPG, %%mm2\n"
+ "psrlq $3, %%mm2\n" // G3G2G1G0 -> mm2
+ "movq %%mm0, %%mm3\n"
+ "pand KEEPB, %%mm3\n"
+ "psllq $3, %%mm3\n" // G3G2G1G0 -> mm3
+
+ "movq %%mm2, %%mm0\n"
+ "punpcklbw %%mm1, %%mm2\n"
+ "punpckhbw %%mm1, %%mm0\n"
+
+ "pxor %%mm5, %%mm5\n"
+ "movq %%mm3, %%mm4\n"
+ "punpcklbw %%mm5, %%mm3\n"
+ "punpckhbw %%mm5, %%mm4\n"
+
+ "psllq $8, %%mm2\n"
+ "por %%mm2, %%mm3\n" // 0B1G1R10B0G0G0 -> mm3
+ "psllq $8, %%mm0\n"
+ "por %%mm0, %%mm4\n" // 0B3G3R30B2G2G2 -> mm4
+
+ "movq %%mm3, 16%3\n"
+ "movq %%mm4, 24%3\n"
+
+ "add $16, %0\n"
+
+ // standard algorithm --------------------------------------------------
+
+ // pack rgb
+ // was: "movq (%0), %%mm1\n" // load G2R2B1G1R1B0G0R0
+ // ------------------------------
+ // (uses: mm0, mm1)
+ "movd 8%3, %%mm0\n"
+ "psllq $24, %%mm0\n"
+ "movd 4%3, %%mm1\n"
+ "por %%mm1, %%mm0\n"
+ "psllq $24, %%mm0\n"
+ "movd %3, %%mm1\n"
+ "por %%mm0, %%mm1\n"
+ // ------------------------------
+
+ "pxor %%mm6, %%mm6\n" // 0 -> mm6
+ "movq %%mm1, %%mm0\n" // G2R2B1G1R1B0G0R0 -> mm0
+ "psrlq $16, %%mm1\n" // 00G2R2B1G1R1B0 -> mm1
+ "punpcklbw ZEROSX, %%mm0\n" // R1B0G0R0 -> mm0
+ "movq %%mm1, %%mm7\n" // 00G2R2B1G1R1B0 -> mm7
+ "punpcklbw ZEROSX, %%mm1\n" // B1G1R1B0 -> mm1
+ "movq %%mm0, %%mm2\n" // R1B0G0R0 -> mm2
+ "pmaddwd YR0GRX, %%mm0\n" // yrR1,ygG0+yrR0 -> mm0
+ "movq %%mm1, %%mm3\n" // B1G1R1B0 -> mm3
+ "pmaddwd YBG0BX, %%mm1\n" // ybB1+ygG1,ybB0 -> mm1
+ "movq %%mm2, %%mm4\n" // R1B0G0R0 -> mm4
+ "movq %%mm3, %%mm5\n" // B1G1R1B0 -> mm5
+ "punpckhbw %%mm6, %%mm7\n" // 00G2R2 -> mm7
+ "paddd %%mm1, %%mm0\n" // Y1Y0 -> mm0
+
+ // pack rgb
+ // was: "movq 8(%0),%%mm1\n" // R5B4G4R4B3G3R3B2 -> mm1
+ // ------------------------------
+ // (uses: mm1, mm6)
+ "movd 20%3, %%mm1\n"
+ "psllq $24, %%mm1\n"
+ "movd 16%3, %%mm6\n"
+ "por %%mm6, %%mm1\n"
+ "psllq $24, %%mm1\n"
+ "movd 12%3, %%mm6\n"
+ "por %%mm6, %%mm1\n"
+ "psllq $8, %%mm1\n"
+ "movd 8%3, %%mm6\n"
+ "psrlq $16, %%mm6\n"
+ "por %%mm6, %%mm1\n"
+ // ------------------------------
+
+ "movq %%mm1, %%mm6\n" // R5B4G4R4B3G3R3B2 -> mm6
+ "punpcklbw ZEROSX, %%mm1\n" // B3G3R3B2 -> mm1
+
+ //----------------------------------------------------------------------
+
+ "movq %%mm1, %%mm5\n" // B3G3R3B2 -> mm5
+ "psllq $32, %%mm1\n" // R3B200 -> mm1
+
+ "paddd %%mm7, %%mm1\n" // R3B200+00G2R2=R3B2G2R2->mm1
+
+ "punpckhbw ZEROSX, %%mm6\n" // R5B4G4R3 -> mm6
+ "movq %%mm1, %%mm3\n" // R3B2G2R2 -> mm3
+
+ "pmaddwd YR0GRX, %%mm1\n" // yrR3,ygG2+yrR2 -> mm1
+ "movq %%mm5, %%mm7\n" // B3G3R3B2 -> mm7
+
+ "pmaddwd YBG0BX, %%mm5\n" // ybB3+ygG3,ybB2 -> mm5
+ "psrad $15, %%mm0\n" // 32-bit scaled Y1Y0 -> mm0
+
+ "movq %%mm6, 36%3\n" // R5B4G4R4 -> TEMP0
+ "movq %%mm3, %%mm6\n" // R3B2G2R2 -> mm6
+
+ "paddd %%mm5, %%mm1\n" // Y3Y2 -> mm1
+ "movq %%mm7, %%mm5\n" // B3G3R3B2 -> mm5
+ "psrad $15, %%mm1\n" // 32-bit scaled Y3Y2 -> mm1
+
+ "packssdw %%mm1, %%mm0\n" // Y3Y2Y1Y0 -> mm0
+
+ //----------------------------------------------------------------------
+
+ // pack rgb
+ // was: "movq 16(%0), %%mm1\n" // B7G7R7B6G6R6B5G5 -> mm1
+ // ------------------------------
+ // (uses: mm1, mm7)
+ "movd 28%3, %%mm1\n"
+ "psllq $24, %%mm1\n"
+ "movd 24%3, %%mm7\n"
+ "por %%mm7, %%mm1\n"
+ "psllq $16, %%mm1\n"
+ "movd 20%3, %%mm7\n"
+ "psrlq $8, %%mm7\n"
+ "por %%mm7, %%mm1\n"
+ // ------------------------------
+
+ "movq %%mm1, %%mm7\n" // B7G7R7B6G6R6B5G5 -> mm1
+
+ "psllq $16, %%mm7\n" // R7B6G6R6B5G500 -> mm7
+
+ "movq %%mm7, %%mm5\n" // R7B6G6R6B5G500 -> mm5
+
+ "movq %%mm0, 44%3\n" // 32-bit scaled Y3Y2Y1Y0 -> TEMPY
+
+ "movq 36%3, %%mm0\n" // R5B4G4R4 -> mm0
+
+ "punpcklbw ZEROSX, %%mm7\n" // B5G500 -> mm7
+ "movq %%mm0, %%mm6\n" // R5B4G4R4 -> mm6
+
+ "psrlq $32, %%mm0\n" // 00R5B4 -> mm0
+
+ "paddw %%mm0, %%mm7\n" // B5G5R5B4 -> mm7
+ "movq %%mm6, %%mm2\n" // B5B4G4R4 -> mm2
+
+ "pmaddwd YR0GRX, %%mm2\n" // yrR5,ygG4+yrR4 -> mm2
+
+ "pmaddwd YBG0BX, %%mm7\n" // ybB5+ygG5,ybB4 -> mm7
+
+ //----------------------------------------------------------------------
+ "paddd %%mm7, %%mm2\n" // Y5Y4 -> mm2
+
+ //----------------------------------------------------------------------
+
+ "pxor %%mm7, %%mm7\n" // 0 -> mm7
+
+ "punpckhbw %%mm7, %%mm1\n" // B7G7R7B6 -> mm1
+
+ "movq %%mm1, %%mm6\n" // B7G7R7B6 -> mm6
+
+ "pmaddwd YBG0BX, %%mm6\n" // ybB7+ygG7,ybB6 -> mm6
+ "punpckhbw %%mm7, %%mm5\n" // R7B6G6R6 -> mm5
+
+ "pmaddwd YR0GRX, %%mm5\n" // yrR7,ygG6+yrR6 -> mm5
+
+ //----------------------------------------------------------------------
+
+ "psrad $15, %%mm2\n" // 32-bit scaled Y5Y4 -> mm2
+
+ "paddd %%mm5, %%mm6\n" // Y7Y6 -> mm6
+ "psrad $15, %%mm6\n" // 32-bit scaled Y7Y6 -> mm6
+
+ "packssdw %%mm6, %%mm2\n" // Y7Y6Y5Y4 -> mm2
+
+ //----------------------------------------------------------------------
+
+ "movq 44%3, %%mm6\n" // 32-bit scaled Y3Y2Y1Y0 -> mm6
+ "packuswb %%mm2, %%mm6\n" // all 8 Y values -> mm6
+
+ //----------------------------------------------------------------------
+
+ "movq %%mm6, (%1)\n" // store Y
+
+ "add $8, %1\n"
+
+ "sub $8, %2\n"
+ "jnz 1b\n"
+ "emms\n"
+
+ :
+ : "r" (rgbSource), "r" (lum), "m" (pixel), "m" (buf[0])
+
+ );
+}
+
+void rgb2y16bit_mmx_row_fast(unsigned char* rgb, unsigned char* lum, int pixel)
+{
+ __asm__ __volatile__ (
+ "1:\n"
+
+ // unpack hicolor ( pixel 1 - 4)
+ "movq (%0), %%mm0\n"
+
+ "movq %%mm0, %%mm1\n"
+ "pand KEEPR, %%mm1\n"
+ "psrlq $11, %%mm1\n" // B3B2B1B0 -> mm1
+
+ "movq %%mm0, %%mm2\n"
+ "pand KEEPG, %%mm2\n"
+ "psrlq $5, %%mm2\n" // G3G2G1G0 -> mm2
+ "movq %%mm0, %%mm3\n"
+ "pand KEEPB, %%mm3\n" // R3R2R1R0 -> mm3
+
+ // calculate Y
+ "movq %%mm3, %%mm4\n"
+ "pmullw Y_RED, %%mm4\n"
+
+ "movq %%mm2, %%mm5\n"
+ "pmullw Y_GREEN, %%mm5\n"
+ "paddw %%mm5, %%mm4\n"
+
+ "movq %%mm1, %%mm6\n"
+ "pmullw Y_BLUE, %%mm6\n"
+ "paddw %%mm6, %%mm4\n"
+
+ "psrlw $7, %%mm4\n" // Y3Y2Y1Y0 -> mm4
+
+ "pxor %%mm5, %%mm5\n"
+ "packuswb %%mm5, %%mm4\n"
+
+ "movd %%mm4, (%1)\n"
+ "add $4, %1\n"
+
+ "add $8, %0\n"
+
+ "sub $4, %2\n"
+ "jnz 1b\n"
+
+ "emms\n"
+
+ :
+ : "r" (rgb), "r" (lum), "m" (pixel)
+ );
+}
+
+
+#endif
+// INTEL
+
+
diff --git a/mpeglib/lib/util/render/dither2YUV/rgb2yuv16.h b/mpeglib/lib/util/render/dither2YUV/rgb2yuv16.h
new file mode 100644
index 00000000..7e4d6508
--- /dev/null
+++ b/mpeglib/lib/util/render/dither2YUV/rgb2yuv16.h
@@ -0,0 +1,74 @@
+/***************************************************************************
+ rgb2yuv16.h - description
+ -------------------
+ begin : Tue Nov 2 2000
+ copyright : (C) 2000 by Christian Gerlach
+ email : cgerlach@rhrk.uni-kl.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __RGB2YUV16_H
+#define __RGB2YUV16_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "../yuvPicture.h"
+#include "rgb2yuvdefs.h"
+
+// slow C implementation
+void rgb2yuv16bit(unsigned char* rgbSource,
+ unsigned char* destLum,
+ unsigned char* destCr,
+ unsigned char* destCb,int height, int width);
+
+
+
+//
+// We compile with MMX if we are on INTEL arch
+// (this does not mean that we really support MMX,
+// this is a seperate/runtime check)
+//
+
+#ifdef INTEL
+
+void rgb2yuv16bit_mmx(unsigned char* rgbSource,
+ unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,int height, int width);
+
+void rgb2yuv16bit_mmx_fast(unsigned char* rgbSource,
+ unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,int height, int width);
+
+void rgb2yuv16bit_mmx422_row(unsigned char* rgb,
+ unsigned char* lum, unsigned char* cr,
+ unsigned char* cb, int pixel);
+
+void rgb2y16bit_mmx_row(unsigned char* rgbSource,
+ unsigned char* lum, int pixel);
+
+void rgb2yuv16bit_mmx422_row_fast(unsigned char* rgb,
+ unsigned char* lum, unsigned char* cr,
+ unsigned char* cb, int pixel);
+
+void rgb2y16bit_mmx_row_fast(unsigned char* rgb,
+ unsigned char* lum, int pixel);
+
+
+#endif
+// INTEL
+
+
+
+#endif
diff --git a/mpeglib/lib/util/render/dither2YUV/rgb2yuv32.cpp b/mpeglib/lib/util/render/dither2YUV/rgb2yuv32.cpp
new file mode 100644
index 00000000..3e246e25
--- /dev/null
+++ b/mpeglib/lib/util/render/dither2YUV/rgb2yuv32.cpp
@@ -0,0 +1,1143 @@
+/***************************************************************************
+ rgb2yuv32.cpp - description
+ -------------------
+ begin : Tue Nov 2 2000
+ copyright : (C) 2000 by Christian Gerlach
+ email : cgerlach@rhrk.uni-kl.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "rgb2yuv32.h"
+#include <iostream>
+
+void rgb2yuv32(unsigned char* rgb, unsigned char* dest)
+{
+ dest[0] = Y_RGB(rgb[0], rgb[1], rgb[2]);
+ dest[1] = U_RGB(rgb[0], rgb[1], rgb[2]);
+ dest[2] = V_RGB(rgb[0], rgb[1], rgb[2]);
+}
+
+void rgb2yuv24bit(unsigned char* rgbSource,
+ unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,int height, int width) {
+ int width2 = width / 2;
+ int height2 = height / 2;
+ int r, g, b, row, col;
+
+ for (row=0 ; row<height2 ; row++) {
+ for (col=0 ; col<width2 ; col++) {
+ r = *rgbSource++;
+ g = *rgbSource++;
+ b = *rgbSource++;
+
+ *lum++ = Y_RGB(r, g, b);
+ *cr++ = U_RGB(r, g, b);
+ *cb++ = V_RGB(r, g, b);
+
+ r = *rgbSource++;
+ g = *rgbSource++;
+ b = *rgbSource++;
+
+ *lum++ = Y_RGB(r, g, b);
+ }
+ for (col=0 ; col<width ; col++) {
+ r = *rgbSource++;
+ g = *rgbSource++;
+ b = *rgbSource++;
+
+ *lum++ = Y_RGB(r, g, b);
+ }
+ }
+}
+
+void rgb2yuv32bit(unsigned char* rgbSource,
+ unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,int height, int width) {
+
+ int width2 = width / 2;
+ int height2 = height / 2;
+ int r, g, b, row, col;
+
+ for (row=0 ; row<height2 ; row++) {
+ for (col=0 ; col<width2 ; col++) {
+ r = *rgbSource++;
+ g = *rgbSource++;
+ b = *rgbSource++;
+ rgbSource ++;
+
+ *lum++ = Y_RGB(r, g, b);
+ *cr++ = U_RGB(r, g, b);
+ *cb++ = V_RGB(r, g, b);
+
+ r = *rgbSource++;
+ g = *rgbSource++;
+ b = *rgbSource++;
+ rgbSource++;
+
+ *lum++ = Y_RGB(r, g, b);
+ }
+ for (col=0 ; col<width ; col++) {
+ r = *rgbSource++;
+ g = *rgbSource++;
+ b = *rgbSource++;
+ rgbSource ++;
+
+ *lum++ = Y_RGB(r, g, b);
+ }
+ }
+}
+
+#ifndef INTEL
+void rgb2yuv24bit_mmx(unsigned char* rgbSource,
+ unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,int height, int width) {
+ std::cout << "RGB->YUV render not compiled for INTEL"<<std::endl;
+ exit(0);
+}
+
+void rgb2yuv32bit_mmx(unsigned char* rgbSource,
+ unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,int height, int width) {
+ std::cout << "RGB->YUV render not compiled for INTEL"<<std::endl;
+ exit(0);
+}
+
+#endif
+
+#ifdef INTEL
+
+void rgb2yuv24bit_mmx(unsigned char* rgbSource,
+ unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,int height, int width) {
+ int width2 = width / 2;
+ int height2 = height / 2;
+ int row;
+ int bytesPerLine = width * 3;
+
+ for (row=0 ; row<height2 ; row++) {
+ rgb2yuv24bit_mmx422_row(rgbSource, lum, cr, cb, width);
+ rgbSource += bytesPerLine;
+ lum += width;
+ cr += width2;
+ cb += width2;
+
+ rgb2y24bit_mmx_row(rgbSource, lum, width);
+ rgbSource += bytesPerLine;
+ lum += width;
+ }
+}
+
+void rgb2yuv32bit_mmx(unsigned char* rgbSource,
+ unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,int height, int width) {
+
+
+ int width2 = width / 2;
+ int height2 = height / 2;
+ int bytesPerLine = width * 4;
+
+ for (int row=0 ; row<height2 ; row++) {
+ rgb2yuv32bit_mmx422_row(rgbSource, lum,cr, cb, width);
+ rgbSource += bytesPerLine;
+ lum += width;
+ cr += width2;
+ cb += width2;
+
+ rgb2y32bit_mmx_row(rgbSource, lum, width);
+ rgbSource += bytesPerLine;
+ lum += width;
+ }
+}
+
+void rgb2yuv24bit_mmx444_row(unsigned char* rgb, unsigned char* lum, unsigned char* cr,
+ unsigned char* cb, int pixel)
+{
+ unsigned int buf[8];
+
+ // %5 = TEMP0
+ // 8%5 = TEMPY
+ // 16%5 = TEMPU
+ // 24%5 = TEMPV
+
+ __asm__ __volatile__ (
+ "1:\n"
+
+ "movq (%0), %%mm1\n" // load G2R2B1G1R1B0G0R0
+ "pxor %%mm6, %%mm6\n" // 0 -> mm6
+ "movq %%mm1, %%mm0\n" // G2R2B1G1R1B0G0R0 -> mm0
+ "psrlq $16, %%mm1\n" // 00G2R2B1G1R1B0 -> mm1
+ "punpcklbw ZEROSX, %%mm0\n" // R1B0G0R0 -> mm0
+ "movq %%mm1, %%mm7\n" // 00G2R2B1G1R1B0 -> mm7
+ "punpcklbw ZEROSX, %%mm1\n" // B1G1R1B0 -> mm1
+ "movq %%mm0, %%mm2\n" // R1B0G0R0 -> mm2
+ "pmaddwd YR0GRX, %%mm0\n" // yrR1,ygG0+yrR0 -> mm0
+ "movq %%mm1, %%mm3\n" // B1G1R1B0 -> mm3
+ "pmaddwd YBG0BX, %%mm1\n" // ybB1+ygG1,ybB0 -> mm1
+ "movq %%mm2, %%mm4\n" // R1B0G0R0 -> mm4
+ "pmaddwd UR0GRX, %%mm2\n" // urR1,ugG0+urR0 -> mm2
+ "movq %%mm3, %%mm5\n" // B1G1R1B0 -> mm5
+ "pmaddwd UBG0BX, %%mm3\n" // ubB1+ugG1,ubB0 -> mm3
+ "punpckhbw %%mm6, %%mm7\n" // 00G2R2 -> mm7
+ "pmaddwd VR0GRX, %%mm4\n" // vrR1,vgG0+vrR0 -> mm4
+ "paddd %%mm1, %%mm0\n" // Y1Y0 -> mm0
+
+ "pmaddwd VBG0BX, %%mm5\n" // vbB1+vgG1,vbB0 -> mm5
+
+ "movq 8(%0),%%mm1\n" // load G2R2B1G1R1B0G0R0
+ "paddd %%mm3, %%mm2\n" // U1U0 -> mm2
+
+ "movq %%mm1, %%mm6\n" // R5B4G4R4B3G3R3B2 -> mm6
+ "punpcklbw ZEROSX, %%mm1\n" // B3G3R3B2 -> mm1
+ "paddd %%mm5, %%mm4\n" // V1V0 -> mm4
+
+ //----------------------------------------------------------------------
+
+ "movq %%mm1, %%mm5\n" // B3G3R3B2 -> mm5
+ "psllq $32, %%mm1\n" // R3B200 -> mm1
+
+ "paddd %%mm7, %%mm1\n" // R3B200+00G2R2=R3B2G2R2->mm1
+
+ "punpckhbw ZEROSX, %%mm6\n" // R5B4G4R3 -> mm6
+ "movq %%mm1, %%mm3\n" // R3B2G2R2 -> mm3
+
+ "pmaddwd YR0GRX, %%mm1\n" // yrR3,ygG2+yrR2 -> mm1
+ "movq %%mm5, %%mm7\n" // B3G3R3B2 -> mm7
+
+ "pmaddwd YBG0BX, %%mm5\n" // ybB3+ygG3,ybB2 -> mm5
+ "psrad $15, %%mm0\n" // 32-bit scaled Y1Y0 -> mm0
+
+ "movq %%mm6, %5\n" // R5B4G4R4 -> TEMP0
+ "movq %%mm3, %%mm6\n" // R3B2G2R2 -> mm6
+ "pmaddwd UR0GRX, %%mm6\n" // urR3,ugG2+urR2 -> mm6
+ "psrad $15, %%mm2\n" // 32-bit scaled U1U0 -> mm2
+
+ "paddd %%mm5, %%mm1\n" // Y3Y2 -> mm1
+ "movq %%mm7, %%mm5\n" // B3G3R3B2 -> mm5
+ "pmaddwd UBG0BX, %%mm7\n" // ubB3+ugG3,ubB2
+ "psrad $15, %%mm1\n" // 32-bit scaled Y3Y2 -> mm1
+
+ "pmaddwd VR0GRX, %%mm3\n" // vrR3,vgG2+vgR2
+ "packssdw %%mm1, %%mm0\n" // Y3Y2Y1Y0 -> mm0
+
+ "pmaddwd VBG0BX, %%mm5\n" // vbB3+vgG3,vbB2 -> mm5
+ "psrad $15, %%mm4\n" // 32-bit scaled V1V0 -> mm4
+
+ //----------------------------------------------------------------------
+
+ "movq 16(%0), %%mm1\n" // B7G7R7B6G6R6B5G5 -> mm7
+ "paddd %%mm7, %%mm6\n" // U3U2 -> mm6
+
+ "movq %%mm1, %%mm7\n" // B7G7R7B6G6R6B5G5 -> mm1
+ "psrad $15, %%mm6\n" // 32-bit scaled U3U2 -> mm6
+
+ "paddd %%mm5, %%mm3\n" // V3V2 -> mm3
+ "psllq $16, %%mm7\n" // R7B6G6R6B5G500 -> mm7
+
+ "movq %%mm7, %%mm5\n" // R7B6G6R6B5G500 -> mm5
+ "psrad $15, %%mm3\n" // 32-bit scaled V3V2 -> mm3
+
+ "movq %%mm0, 8%5\n" // 32-bit scaled Y3Y2Y1Y0 -> TEMPY
+ "packssdw %%mm6, %%mm2\n" // 32-bit scaled U3U2U1U0 -> mm2
+
+ "movq %5, %%mm0\n" // R5B4G4R4 -> mm0
+
+ "punpcklbw ZEROSX, %%mm7\n" // B5G500 -> mm7
+ "movq %%mm0, %%mm6\n" // R5B4G4R4 -> mm6
+
+ "movq %%mm2, 16%5\n" // 32-bit scaled U3U2U1U0 -> TEMPU
+ "psrlq $32, %%mm0\n" // 00R5B4 -> mm0
+
+ "paddw %%mm0, %%mm7\n" // B5G5R5B4 -> mm7
+ "movq %%mm6, %%mm2\n" // B5B4G4R4 -> mm2
+
+ "pmaddwd YR0GRX, %%mm2\n" // yrR5,ygG4+yrR4 -> mm2
+ "movq %%mm7, %%mm0\n" // B5G5R5B4 -> mm0
+
+ "pmaddwd YBG0BX, %%mm7\n" // ybB5+ygG5,ybB4 -> mm7
+ "packssdw %%mm3, %%mm4\n" // 32-bit scaled V3V2V1V0 -> mm4
+
+ //----------------------------------------------------------------------
+
+ "movq %%mm4, 24%5\n" // (V3V2V1V0)/256 -> mm4
+
+ "movq %%mm6, %%mm4\n" // B5B4G4R4 -> mm4
+
+ "pmaddwd UR0GRX, %%mm6\n" // urR5,ugG4+urR4
+ "movq %%mm0, %%mm3\n" // B5G5R5B4 -> mm0
+
+ "pmaddwd UBG0BX, %%mm0\n" // ubB5+ugG5,ubB4
+ "paddd %%mm7, %%mm2\n" // Y5Y4 -> mm2
+
+ //----------------------------------------------------------------------
+
+ "pmaddwd VR0GRX, %%mm4\n" // vrR5,vgG4+vrR4 -> mm4
+ "pxor %%mm7, %%mm7\n" // 0 -> mm7
+
+ "pmaddwd VBG0BX, %%mm3\n" // vbB5+vgG5,vbB4 -> mm3
+ "punpckhbw %%mm7, %%mm1\n" // B7G7R7B6 -> mm1
+
+ "paddd %%mm6, %%mm0\n" // U5U4 -> mm0
+ "movq %%mm1, %%mm6\n" // B7G7R7B6 -> mm6
+
+ "pmaddwd YBG0BX, %%mm6\n" // ybB7+ygG7,ybB6 -> mm6
+ "punpckhbw %%mm7, %%mm5\n" // R7B6G6R6 -> mm5
+
+ "movq %%mm5, %%mm7\n" // R7B6G6R6 -> mm7
+ "paddd %%mm4, %%mm3\n" // V5V4 -> mm3
+
+ "pmaddwd YR0GRX, %%mm5\n" // yrR7,ygG6+yrR6 -> mm5
+ "movq %%mm1, %%mm4\n" // B7G7R7B6 -> mm4
+
+ "pmaddwd UBG0BX, %%mm4\n" // ubB7+ugG7,ubB6 -> mm4
+ "psrad $15, %%mm0\n" // 32-bit scaled U5U4 -> %%mm0
+
+ //----------------------------------------------------------------------
+
+ "paddd OFFSETWX, %%mm0\n" // add offset to U5U4 -> mm0
+ "psrad $15, %%mm2\n" // 32-bit scaled Y5Y4 -> mm2
+
+ "paddd %%mm5, %%mm6\n" // Y7Y6 -> mm6
+ "movq %%mm7, %%mm5\n" // R7B6G6R6 -> mm5
+
+ "pmaddwd UR0GRX, %%mm7\n" // urR7,ugG6+ugR6 -> mm7
+ "psrad $15, %%mm3\n" // 32-bit scaled V5V4 -> mm3
+
+ "pmaddwd VBG0BX, %%mm1\n" // vbB7+vgG7,vbB6 -> mm1
+ "psrad $15, %%mm6\n" // 32-bit scaled Y7Y6 -> mm6
+
+ "paddd OFFSETDX, %%mm4\n" // add offset to U7U6
+ "packssdw %%mm6, %%mm2\n" // Y7Y6Y5Y4 -> mm2
+
+ "pmaddwd VR0GRX, %%mm5\n" // vrR7,vgG6+vrR6 -> mm5
+ "paddd %%mm4, %%mm7\n" // U7U6 -> mm7
+
+ "psrad $15, %%mm7\n" // 32-bit scaled U7U6 -> mm7
+
+ //----------------------------------------------------------------------
+
+ "movq 8%5, %%mm6\n" // 32-bit scaled Y3Y2Y1Y0 -> mm6
+ "packssdw %%mm7, %%mm0\n" // 32-bit scaled U7U6U5U4 -> mm0
+
+ "movq 16%5, %%mm4\n" // 32-bit scaled U3U2U1U0 -> mm4
+ "packuswb %%mm2, %%mm6\n" // all 8 Y values -> mm6
+
+ "movq OFFSETBX, %%mm7\n" // 128,128,128,128 -> mm7
+ "paddd %%mm5, %%mm1\n" // V7V6 -> mm1
+
+ "paddw %%mm7, %%mm4\n" // add offset to U3U2U1U0/256
+ "psrad $15, %%mm1\n" // 32-bit scaled V7V6 -> mm1
+
+ //----------------------------------------------------------------------
+
+ "movq %%mm6, (%1)\n" // store Y
+ "packuswb %%mm0, %%mm4\n" // all 8 U values -> mm4
+
+ "movq 24%5, %%mm5\n" // 32-bit scaled V3V2V1V0 -> mm5
+ "packssdw %%mm1, %%mm3\n" // V7V6V5V4 -> mm3
+ "paddw %%mm7, %%mm5\n" // add offset to V3V2V1V0
+ "paddw %%mm7, %%mm3\n" // add offset to V7V6V5V4
+
+ "movq %%mm4, (%2)\n" // store U
+ "packuswb %%mm3, %%mm5\n" // ALL 8 V values -> mm5
+
+ "movq %%mm5, (%3)\n" // store V
+
+ "sub $8, %4\n"
+ "jnz 1b\n"
+ "emms\n"
+
+ :
+ : "r" (rgb), "r" (lum), "r" (cr), "r" (cb), "m" (pixel), "m" (buf[0])
+ );
+}
+
+void rgb2yuv24bit_mmx422_row(unsigned char* rgb, unsigned char* lum, unsigned char* cr,
+ unsigned char* cb, int pixel)
+{
+ unsigned int buf[8];
+
+ // %5 = TEMP0
+ // 8%5 = TEMPY
+ // 16%5 = TEMPU
+ // 24%5 = TEMPV
+
+ __asm__ __volatile__ (
+ "1:\n"
+
+ "movq (%0), %%mm1\n" // load G2R2B1G1R1B0G0R0
+ "pxor %%mm6, %%mm6\n" // 0 -> mm6
+ "movq %%mm1, %%mm0\n" // G2R2B1G1R1B0G0R0 -> mm0
+ "psrlq $16, %%mm1\n" // 00G2R2B1G1R1B0 -> mm1
+ "punpcklbw ZEROSX, %%mm0\n" // R1B0G0R0 -> mm0
+ "movq %%mm1, %%mm7\n" // 00G2R2B1G1R1B0 -> mm7
+ "punpcklbw ZEROSX, %%mm1\n" // B1G1R1B0 -> mm1
+ "movq %%mm0, %%mm2\n" // R1B0G0R0 -> mm2
+ "pmaddwd YR0GRX, %%mm0\n" // yrR1,ygG0+yrR0 -> mm0
+
+ "movq %%mm1, %%mm3\n" // B1G1R1B0 -> mm3
+ "pmaddwd YBG0BX, %%mm1\n" // ybB1+ygG1,ybB0 -> mm1
+ "movq %%mm2, %%mm4\n" // R1B0G0R0 -> mm4
+ "pmaddwd UR0GRX, %%mm2\n" // urR1,ugG0+urR0 -> mm2
+ "movq %%mm3, %%mm5\n" // B1G1R1B0 -> mm5
+ "pmaddwd UBG0BX, %%mm3\n" // ubB1+ugG1,ubB0 -> mm3
+ "punpckhbw %%mm6, %%mm7\n" // 00G2R2 -> mm7
+ "pmaddwd VR0GRX, %%mm4\n" // vrR1,vgG0+vrR0 -> mm4
+ "paddd %%mm1, %%mm0\n" // Y1Y0 -> mm0
+
+ "pmaddwd VBG0BX, %%mm5\n" // vbB1+vgG1,vbB0 -> mm5
+
+ "movq 8(%0),%%mm1\n" // load G2R2B1G1R1B0G0R0
+ "paddd %%mm3, %%mm2\n" // U1U0 -> mm2
+
+ "movq %%mm1, %%mm6\n" // R5B4G4R4B3G3R3B2 -> mm6
+ "punpcklbw ZEROSX, %%mm1\n" // B3G3R3B2 -> mm1
+ "paddd %%mm5, %%mm4\n" // V1V0 -> mm4
+
+ //----------------------------------------------------------------------
+
+ "movq %%mm1, %%mm5\n" // B3G3R3B2 -> mm5
+ "psllq $32, %%mm1\n" // R3B200 -> mm1
+
+ "paddd %%mm7, %%mm1\n" // R3B200+00G2R2=R3B2G2R2->mm1
+
+ "punpckhbw ZEROSX, %%mm6\n" // R5B4G4R3 -> mm6
+ "movq %%mm1, %%mm3\n" // R3B2G2R2 -> mm3
+
+ "pmaddwd YR0GRX, %%mm1\n" // yrR3,ygG2+yrR2 -> mm1
+ "movq %%mm5, %%mm7\n" // B3G3R3B2 -> mm7
+
+ "pmaddwd YBG0BX, %%mm5\n" // ybB3+ygG3,ybB2 -> mm5
+ "psrad $15, %%mm0\n" // 32-bit scaled Y1Y0 -> mm0
+
+ "movq %%mm6, %5\n" // R5B4G4R4 -> TEMP0
+ "movq %%mm3, %%mm6\n" // R3B2G2R2 -> mm6
+ "pmaddwd UR0GRX, %%mm6\n" // urR3,ugG2+urR2 -> mm6
+ "psrad $15, %%mm2\n" // 32-bit scaled U1U0 -> mm2
+
+ "paddd %%mm5, %%mm1\n" // Y3Y2 -> mm1
+ "movq %%mm7, %%mm5\n" // B3G3R3B2 -> mm5
+ "pmaddwd UBG0BX, %%mm7\n" // ubB3+ugG3,ubB2
+ "psrad $15, %%mm1\n" // 32-bit scaled Y3Y2 -> mm1
+
+ "pmaddwd VR0GRX, %%mm3\n" // vrR3,vgG2+vgR2
+ "packssdw %%mm1, %%mm0\n" // Y3Y2Y1Y0 -> mm0
+
+ "pmaddwd VBG0BX, %%mm5\n" // vbB3+vgG3,vbB2 -> mm5
+ "psrad $15, %%mm4\n" // 32-bit scaled V1V0 -> mm4
+
+ //----------------------------------------------------------------------
+
+ "movq 16(%0), %%mm1\n" // B7G7R7B6G6R6B5G5 -> mm7
+ "paddd %%mm7, %%mm6\n" // U3U2 -> mm6
+
+ "movq %%mm1, %%mm7\n" // B7G7R7B6G6R6B5G5 -> mm1
+ "psrad $15, %%mm6\n" // 32-bit scaled U3U2 -> mm6
+
+ "paddd %%mm5, %%mm3\n" // V3V2 -> mm3
+ "psllq $16, %%mm7\n" // R7B6G6R6B5G500 -> mm7
+
+ "movq %%mm7, %%mm5\n" // R7B6G6R6B5G500 -> mm5
+ "psrad $15, %%mm3\n" // 32-bit scaled V3V2 -> mm3
+
+ "movq %%mm0, 8%5\n" // 32-bit scaled Y3Y2Y1Y0 -> TEMPY
+ "packssdw %%mm6, %%mm2\n" // 32-bit scaled U3U2U1U0 -> mm2
+
+ "movq %5, %%mm0\n" // R5B4G4R4 -> mm0
+
+ "punpcklbw ZEROSX, %%mm7\n" // B5G500 -> mm7
+ "movq %%mm0, %%mm6\n" // R5B4G4R4 -> mm6
+
+ "movq %%mm2, 16%5\n" // 32-bit scaled U3U2U1U0 -> TEMPU
+ "psrlq $32, %%mm0\n" // 00R5B4 -> mm0
+
+ "paddw %%mm0, %%mm7\n" // B5G5R5B4 -> mm7
+ "movq %%mm6, %%mm2\n" // B5B4G4R4 -> mm2
+
+ "pmaddwd YR0GRX, %%mm2\n" // yrR5,ygG4+yrR4 -> mm2
+ "movq %%mm7, %%mm0\n" // B5G5R5B4 -> mm0
+
+ "pmaddwd YBG0BX, %%mm7\n" // ybB5+ygG5,ybB4 -> mm7
+ "packssdw %%mm3, %%mm4\n" // 32-bit scaled V3V2V1V0 -> mm4
+
+ //----------------------------------------------------------------------
+
+ "movq %%mm4, 24%5\n" // (V3V2V1V0)/256 -> mm4
+
+ "movq %%mm6, %%mm4\n" // B5B4G4R4 -> mm4
+
+ "pmaddwd UR0GRX, %%mm6\n" // urR5,ugG4+urR4
+ "movq %%mm0, %%mm3\n" // B5G5R5B4 -> mm0
+
+ "pmaddwd UBG0BX, %%mm0\n" // ubB5+ugG5,ubB4
+ "paddd %%mm7, %%mm2\n" // Y5Y4 -> mm2
+
+ //----------------------------------------------------------------------
+
+ "pmaddwd VR0GRX, %%mm4\n" // vrR5,vgG4+vrR4 -> mm4
+ "pxor %%mm7, %%mm7\n" // 0 -> mm7
+
+ "pmaddwd VBG0BX, %%mm3\n" // vbB5+vgG5,vbB4 -> mm3
+ "punpckhbw %%mm7, %%mm1\n" // B7G7R7B6 -> mm1
+
+ "paddd %%mm6, %%mm0\n" // U5U4 -> mm0
+ "movq %%mm1, %%mm6\n" // B7G7R7B6 -> mm6
+
+ "pmaddwd YBG0BX, %%mm6\n" // ybB7+ygG7,ybB6 -> mm6
+ "punpckhbw %%mm7, %%mm5\n" // R7B6G6R6 -> mm5
+
+ "movq %%mm5, %%mm7\n" // R7B6G6R6 -> mm7
+ "paddd %%mm4, %%mm3\n" // V5V4 -> mm3
+
+ "pmaddwd YR0GRX, %%mm5\n" // yrR7,ygG6+yrR6 -> mm5
+ "movq %%mm1, %%mm4\n" // B7G7R7B6 -> mm4
+
+ "pmaddwd UBG0BX, %%mm4\n" // ubB7+ugG7,ubB6 -> mm4
+ "psrad $15, %%mm0\n" // 32-bit scaled U5U4 -> %%mm0
+
+ //----------------------------------------------------------------------
+
+ "paddd OFFSETWX, %%mm0\n" // add offset to U5U4 -> mm0
+ "psrad $15, %%mm2\n" // 32-bit scaled Y5Y4 -> mm2
+
+ "paddd %%mm5, %%mm6\n" // Y7Y6 -> mm6
+ "movq %%mm7, %%mm5\n" // R7B6G6R6 -> mm5
+
+ "pmaddwd UR0GRX, %%mm7\n" // urR7,ugG6+ugR6 -> mm7
+ "psrad $15, %%mm3\n" // 32-bit scaled V5V4 -> mm3
+
+ "pmaddwd VBG0BX, %%mm1\n" // vbB7+vgG7,vbB6 -> mm1
+ "psrad $15, %%mm6\n" // 32-bit scaled Y7Y6 -> mm6
+
+ "paddd OFFSETDX, %%mm4\n" // add offset to U7U6
+ "packssdw %%mm6, %%mm2\n" // Y7Y6Y5Y4 -> mm2
+
+ "pmaddwd VR0GRX, %%mm5\n" // vrR7,vgG6+vrR6 -> mm5
+ "paddd %%mm4, %%mm7\n" // U7U6 -> mm7
+
+ "psrad $15, %%mm7\n" // 32-bit scaled U7U6 -> mm7
+
+ //----------------------------------------------------------------------
+
+ "movq 8%5, %%mm6\n" // 32-bit scaled Y3Y2Y1Y0 -> mm6
+ "packssdw %%mm7, %%mm0\n" // 32-bit scaled U7U6U5U4 -> mm0
+
+ "movq 16%5, %%mm4\n" // 32-bit scaled U3U2U1U0 -> mm4
+ "packuswb %%mm2, %%mm6\n" // all 8 Y values -> mm6
+
+ "movq OFFSETBX, %%mm7\n" // 128,128,128,128 -> mm7
+ "paddd %%mm5, %%mm1\n" // V7V6 -> mm1
+
+ "paddw %%mm7, %%mm4\n" // add offset to U3U2U1U0/256
+ "psrad $15, %%mm1\n" // 32-bit scaled V7V6 -> mm1
+
+ //----------------------------------------------------------------------
+
+ "movq %%mm6, (%1)\n" // store Y
+ "packuswb %%mm0, %%mm4\n" // all 8 U values -> mm4
+
+ "movq 24%5, %%mm5\n" // 32-bit scaled V3V2V1V0 -> mm5
+ "packssdw %%mm1, %%mm3\n" // V7V6V5V4 -> mm3
+ "paddw %%mm7, %%mm5\n" // add offset to V3V2V1V0
+ "paddw %%mm7, %%mm3\n" // add offset to V7V6V5V4
+
+ "packuswb %%mm3, %%mm5\n" // ALL 8 V values -> mm5
+
+ // pack U and V
+ "movq CLEARX, %%mm2\n"
+ "pand %%mm2, %%mm4\n"
+ "pand %%mm2, %%mm5\n"
+
+ "packuswb %%mm5, %%mm4\n"
+
+ "movd %%mm4, (%2)\n"
+ "psrlq $32, %%mm4\n"
+ "movd %%mm4, (%3)\n"
+
+ "add $24, %0\n"
+ "add $8, %1\n"
+ "add $4, %2\n"
+ "add $4, %3\n"
+
+ "sub $8, %4\n"
+ "jnz 1b\n"
+ "emms\n"
+
+ :
+ : "r" (rgb), "r" (lum), "r" (cr), "r" (cb), "m" (pixel), "m" (buf[0])
+ );
+}
+
+void rgb2yuv32bit_mmx422_row(unsigned char* rgb, unsigned char* lum, unsigned char* cr,
+ unsigned char* cb, int pixel)
+{
+ unsigned int buf[8];
+
+ // %5 = TEMP0
+ // 8%5 = TEMPY
+ // 16%5 = TEMPU
+ // 24%5 = TEMPV
+
+ __asm__ __volatile__ (
+ "1:\n"
+
+ // pack rgb
+ // was: "movq (%0), %%mm1\n" // load G2R2B1G1R1B0G0R0
+ // ------------------------------
+ // (uses: mm0, mm1)
+ "movd 8(%0), %%mm0\n"
+ "psllq $24, %%mm0\n"
+ "movd 4(%0), %%mm1\n"
+ "por %%mm1, %%mm0\n"
+ "psllq $24, %%mm0\n"
+ "movd (%0), %%mm1\n"
+ "por %%mm0, %%mm1\n"
+ // ------------------------------
+
+ "pxor %%mm6, %%mm6\n" // 0 -> mm6
+ "movq %%mm1, %%mm0\n" // G2R2B1G1R1B0G0R0 -> mm0
+ "psrlq $16, %%mm1\n" // 00G2R2B1G1R1B0 -> mm1
+ "punpcklbw ZEROSX, %%mm0\n" // R1B0G0R0 -> mm0
+ "movq %%mm1, %%mm7\n" // 00G2R2B1G1R1B0 -> mm7
+ "punpcklbw ZEROSX, %%mm1\n" // B1G1R1B0 -> mm1
+ "movq %%mm0, %%mm2\n" // R1B0G0R0 -> mm2
+ "pmaddwd YR0GRX, %%mm0\n" // yrR1,ygG0+yrR0 -> mm0
+
+ "movq %%mm1, %%mm3\n" // B1G1R1B0 -> mm3
+ "pmaddwd YBG0BX, %%mm1\n" // ybB1+ygG1,ybB0 -> mm1
+ "movq %%mm2, %%mm4\n" // R1B0G0R0 -> mm4
+ "pmaddwd UR0GRX, %%mm2\n" // urR1,ugG0+urR0 -> mm2
+ "movq %%mm3, %%mm5\n" // B1G1R1B0 -> mm5
+ "pmaddwd UBG0BX, %%mm3\n" // ubB1+ugG1,ubB0 -> mm3
+ "punpckhbw %%mm6, %%mm7\n" // 00G2R2 -> mm7
+ "pmaddwd VR0GRX, %%mm4\n" // vrR1,vgG0+vrR0 -> mm4
+ "paddd %%mm1, %%mm0\n" // Y1Y0 -> mm0
+
+ "pmaddwd VBG0BX, %%mm5\n" // vbB1+vgG1,vbB0 -> mm5
+
+ // pack rgb
+ // was: "movq 8(%0),%%mm1\n" // R5B4G4R4B3G3R3B2 -> mm1
+ // ------------------------------
+ // (uses: mm1, mm6)
+ "movd 20(%0), %%mm1\n"
+ "psllq $24, %%mm1\n"
+ "movd 16(%0), %%mm6\n"
+ "por %%mm6, %%mm1\n"
+ "psllq $24, %%mm1\n"
+ "movd 12(%0), %%mm6\n"
+ "por %%mm6, %%mm1\n"
+ "psllq $8, %%mm1\n"
+ "movd 8(%0), %%mm6\n"
+ "psrlq $16, %%mm6\n"
+ "por %%mm6, %%mm1\n"
+ // ------------------------------
+
+ "paddd %%mm3, %%mm2\n" // U1U0 -> mm2
+
+ "movq %%mm1, %%mm6\n" // R5B4G4R4B3G3R3B2 -> mm6
+ "punpcklbw ZEROSX, %%mm1\n" // B3G3R3B2 -> mm1
+ "paddd %%mm5, %%mm4\n" // V1V0 -> mm4
+
+ //----------------------------------------------------------------------
+
+ "movq %%mm1, %%mm5\n" // B3G3R3B2 -> mm5
+ "psllq $32, %%mm1\n" // R3B200 -> mm1
+
+ "paddd %%mm7, %%mm1\n" // R3B200+00G2R2=R3B2G2R2->mm1
+
+ "punpckhbw ZEROSX, %%mm6\n" // R5B4G4R3 -> mm6
+ "movq %%mm1, %%mm3\n" // R3B2G2R2 -> mm3
+
+ "pmaddwd YR0GRX, %%mm1\n" // yrR3,ygG2+yrR2 -> mm1
+ "movq %%mm5, %%mm7\n" // B3G3R3B2 -> mm7
+
+ "pmaddwd YBG0BX, %%mm5\n" // ybB3+ygG3,ybB2 -> mm5
+ "psrad $15, %%mm0\n" // 32-bit scaled Y1Y0 -> mm0
+
+ "movq %%mm6, %5\n" // R5B4G4R4 -> TEMP0
+ "movq %%mm3, %%mm6\n" // R3B2G2R2 -> mm6
+ "pmaddwd UR0GRX, %%mm6\n" // urR3,ugG2+urR2 -> mm6
+ "psrad $15, %%mm2\n" // 32-bit scaled U1U0 -> mm2
+
+ "paddd %%mm5, %%mm1\n" // Y3Y2 -> mm1
+ "movq %%mm7, %%mm5\n" // B3G3R3B2 -> mm5
+ "pmaddwd UBG0BX, %%mm7\n" // ubB3+ugG3,ubB2
+ "psrad $15, %%mm1\n" // 32-bit scaled Y3Y2 -> mm1
+
+ "pmaddwd VR0GRX, %%mm3\n" // vrR3,vgG2+vgR2
+ "packssdw %%mm1, %%mm0\n" // Y3Y2Y1Y0 -> mm0
+
+ "pmaddwd VBG0BX, %%mm5\n" // vbB3+vgG3,vbB2 -> mm5
+ "psrad $15, %%mm4\n" // 32-bit scaled V1V0 -> mm4
+
+ //----------------------------------------------------------------------
+
+ "paddd %%mm7, %%mm6\n" // U3U2 -> mm6
+
+ // pack rgb
+ // was: "movq 16(%0), %%mm1\n" // B7G7R7B6G6R6B5G5 -> mm1
+ // ------------------------------
+ // (uses: mm1, mm7)
+ "movd 28(%0), %%mm1\n"
+ "psllq $24, %%mm1\n"
+ "movd 24(%0), %%mm7\n"
+ "por %%mm7, %%mm1\n"
+ "psllq $16, %%mm1\n"
+ "movd 20(%0), %%mm7\n"
+ "psrlq $8, %%mm7\n"
+ "por %%mm7, %%mm1\n"
+ // ------------------------------
+
+ "movq %%mm1, %%mm7\n" // B7G7R7B6G6R6B5G5 -> mm1
+ "psrad $15, %%mm6\n" // 32-bit scaled U3U2 -> mm6
+
+ "paddd %%mm5, %%mm3\n" // V3V2 -> mm3
+ "psllq $16, %%mm7\n" // R7B6G6R6B5G500 -> mm7
+
+ "movq %%mm7, %%mm5\n" // R7B6G6R6B5G500 -> mm5
+ "psrad $15, %%mm3\n" // 32-bit scaled V3V2 -> mm3
+
+ "movq %%mm0, 8%5\n" // 32-bit scaled Y3Y2Y1Y0 -> TEMPY
+
+ "packssdw %%mm6, %%mm2\n" // 32-bit scaled U3U2U1U0 -> mm2
+
+ "movq %5, %%mm0\n" // R5B4G4R4 -> mm0
+
+ "punpcklbw ZEROSX, %%mm7\n" // B5G500 -> mm7
+ "movq %%mm0, %%mm6\n" // R5B4G4R4 -> mm6
+
+ "movq %%mm2, 16%5\n" // 32-bit scaled U3U2U1U0 -> TEMPU
+ "psrlq $32, %%mm0\n" // 00R5B4 -> mm0
+
+ "paddw %%mm0, %%mm7\n" // B5G5R5B4 -> mm7
+ "movq %%mm6, %%mm2\n" // B5B4G4R4 -> mm2
+
+ "pmaddwd YR0GRX, %%mm2\n" // yrR5,ygG4+yrR4 -> mm2
+ "movq %%mm7, %%mm0\n" // B5G5R5B4 -> mm0
+
+ "pmaddwd YBG0BX, %%mm7\n" // ybB5+ygG5,ybB4 -> mm7
+ "packssdw %%mm3, %%mm4\n" // 32-bit scaled V3V2V1V0 -> mm4
+
+ //----------------------------------------------------------------------
+
+ "movq %%mm4, 24%5\n" // (V3V2V1V0)/256 -> mm4
+
+ "movq %%mm6, %%mm4\n" // B5B4G4R4 -> mm4
+
+ "pmaddwd UR0GRX, %%mm6\n" // urR5,ugG4+urR4
+ "movq %%mm0, %%mm3\n" // B5G5R5B4 -> mm0
+
+ "pmaddwd UBG0BX, %%mm0\n" // ubB5+ugG5,ubB4
+ "paddd %%mm7, %%mm2\n" // Y5Y4 -> mm2
+
+ //----------------------------------------------------------------------
+
+ "pmaddwd VR0GRX, %%mm4\n" // vrR5,vgG4+vrR4 -> mm4
+ "pxor %%mm7, %%mm7\n" // 0 -> mm7
+
+ "pmaddwd VBG0BX, %%mm3\n" // vbB5+vgG5,vbB4 -> mm3
+ "punpckhbw %%mm7, %%mm1\n" // B7G7R7B6 -> mm1
+
+ "paddd %%mm6, %%mm0\n" // U5U4 -> mm0
+ "movq %%mm1, %%mm6\n" // B7G7R7B6 -> mm6
+
+ "pmaddwd YBG0BX, %%mm6\n" // ybB7+ygG7,ybB6 -> mm6
+ "punpckhbw %%mm7, %%mm5\n" // R7B6G6R6 -> mm5
+
+ "movq %%mm5, %%mm7\n" // R7B6G6R6 -> mm7
+ "paddd %%mm4, %%mm3\n" // V5V4 -> mm3
+
+ "pmaddwd YR0GRX, %%mm5\n" // yrR7,ygG6+yrR6 -> mm5
+ "movq %%mm1, %%mm4\n" // B7G7R7B6 -> mm4
+
+ "pmaddwd UBG0BX, %%mm4\n" // ubB7+ugG7,ubB6 -> mm4
+ "psrad $15, %%mm0\n" // 32-bit scaled U5U4 -> %%mm0
+
+ //----------------------------------------------------------------------
+
+ "paddd OFFSETWX, %%mm0\n" // add offset to U5U4 -> mm0
+ "psrad $15, %%mm2\n" // 32-bit scaled Y5Y4 -> mm2
+
+ "paddd %%mm5, %%mm6\n" // Y7Y6 -> mm6
+ "movq %%mm7, %%mm5\n" // R7B6G6R6 -> mm5
+
+ "pmaddwd UR0GRX, %%mm7\n" // urR7,ugG6+ugR6 -> mm7
+ "psrad $15, %%mm3\n" // 32-bit scaled V5V4 -> mm3
+
+ "pmaddwd VBG0BX, %%mm1\n" // vbB7+vgG7,vbB6 -> mm1
+ "psrad $15, %%mm6\n" // 32-bit scaled Y7Y6 -> mm6
+
+ "paddd OFFSETDX, %%mm4\n" // add offset to U7U6
+ "packssdw %%mm6, %%mm2\n" // Y7Y6Y5Y4 -> mm2
+
+ "pmaddwd VR0GRX, %%mm5\n" // vrR7,vgG6+vrR6 -> mm5
+ "paddd %%mm4, %%mm7\n" // U7U6 -> mm7
+
+ "psrad $15, %%mm7\n" // 32-bit scaled U7U6 -> mm7
+
+ //----------------------------------------------------------------------
+
+ "movq 8%5, %%mm6\n" // 32-bit scaled Y3Y2Y1Y0 -> mm6
+ "packssdw %%mm7, %%mm0\n" // 32-bit scaled U7U6U5U4 -> mm0
+
+ "movq 16%5, %%mm4\n" // 32-bit scaled U3U2U1U0 -> mm4
+ "packuswb %%mm2, %%mm6\n" // all 8 Y values -> mm6
+
+ "movq OFFSETBX, %%mm7\n" // 128,128,128,128 -> mm7
+ "paddd %%mm5, %%mm1\n" // V7V6 -> mm1
+
+ "paddw %%mm7, %%mm4\n" // add offset to U3U2U1U0/256
+ "psrad $15, %%mm1\n" // 32-bit scaled V7V6 -> mm1
+
+ //----------------------------------------------------------------------
+
+ "movq %%mm6, (%1)\n" // store Y
+
+ "packuswb %%mm0, %%mm4\n" // all 8 U values -> mm4
+ "movq 24%5, %%mm5\n" // 32-bit scaled V3V2V1V0 -> mm5
+
+ "packssdw %%mm1, %%mm3\n" // V7V6V5V4 -> mm3
+ "paddw %%mm7, %%mm5\n" // add offset to V3V2V1V0
+ "paddw %%mm7, %%mm3\n" // add offset to V7V6V5V4
+
+ "packuswb %%mm3, %%mm5\n" // ALL 8 V values -> mm5
+
+ "movq CLEARX, %%mm2\n"
+ "pand %%mm2, %%mm4\n"
+ "pand %%mm2, %%mm5\n"
+
+ "packuswb %%mm5, %%mm4\n"
+
+ "movd %%mm4, (%2)\n"
+ "psrlq $32, %%mm4\n"
+ "movd %%mm4, (%3)\n"
+
+ "add $32, %0\n"
+ "add $8, %1\n"
+ "add $4, %2\n"
+ "add $4, %3\n"
+
+ "sub $8, %4\n"
+ "jnz 1b\n"
+
+ "emms\n"
+
+ :
+ : "r" (rgb), "r" (lum), "r" (cr), "r" (cb), "m" (pixel), "m" (buf[0])
+
+ );
+}
+
+void rgb2y24bit_mmx_row(unsigned char* rgbSource, unsigned char* lum, int pixel)
+{
+ unsigned int buf[4];
+
+ // %3 = TEMP0
+ // 8%3 = TEMPY
+
+ __asm__ __volatile__ (
+ "1:\n"
+
+ "movq (%0), %%mm1\n" // load G2R2B1G1R1B0G0R0
+ "pxor %%mm6, %%mm6\n" // 0 -> mm6
+ "movq %%mm1, %%mm0\n" // G2R2B1G1R1B0G0R0 -> mm0
+ "psrlq $16, %%mm1\n" // 00G2R2B1G1R1B0 -> mm1
+ "punpcklbw ZEROSX, %%mm0\n" // R1B0G0R0 -> mm0
+ "movq %%mm1, %%mm7\n" // 00G2R2B1G1R1B0 -> mm7
+ "punpcklbw ZEROSX, %%mm1\n" // B1G1R1B0 -> mm1
+ "movq %%mm0, %%mm2\n" // R1B0G0R0 -> mm2
+ "pmaddwd YR0GRX, %%mm0\n" // yrR1,ygG0+yrR0 -> mm0
+ "movq %%mm1, %%mm3\n" // B1G1R1B0 -> mm3
+ "pmaddwd YBG0BX, %%mm1\n" // ybB1+ygG1,ybB0 -> mm1
+ "movq %%mm2, %%mm4\n" // R1B0G0R0 -> mm4
+ "movq %%mm3, %%mm5\n" // B1G1R1B0 -> mm5
+ "punpckhbw %%mm6, %%mm7\n" // 00G2R2 -> mm7
+ "paddd %%mm1, %%mm0\n" // Y1Y0 -> mm0
+
+ "movq 8(%0),%%mm1\n" // load G2R2B1G1R1B0G0R0
+
+ "movq %%mm1, %%mm6\n" // R5B4G4R4B3G3R3B2 -> mm6
+ "punpcklbw ZEROSX, %%mm1\n" // B3G3R3B2 -> mm1
+
+ //----------------------------------------------------------------------
+
+ "movq %%mm1, %%mm5\n" // B3G3R3B2 -> mm5
+ "psllq $32, %%mm1\n" // R3B200 -> mm1
+
+ "paddd %%mm7, %%mm1\n" // R3B200+00G2R2=R3B2G2R2->mm1
+
+ "punpckhbw ZEROSX, %%mm6\n" // R5B4G4R3 -> mm6
+ "movq %%mm1, %%mm3\n" // R3B2G2R2 -> mm3
+
+ "pmaddwd YR0GRX, %%mm1\n" // yrR3,ygG2+yrR2 -> mm1
+ "movq %%mm5, %%mm7\n" // B3G3R3B2 -> mm7
+
+ "pmaddwd YBG0BX, %%mm5\n" // ybB3+ygG3,ybB2 -> mm5
+ "psrad $15, %%mm0\n" // 32-bit scaled Y1Y0 -> mm0
+
+ "movq %%mm6, %3\n" // R5B4G4R4 -> TEMP0
+ "movq %%mm3, %%mm6\n" // R3B2G2R2 -> mm6
+
+ "paddd %%mm5, %%mm1\n" // Y3Y2 -> mm1
+ "movq %%mm7, %%mm5\n" // B3G3R3B2 -> mm5
+ "psrad $15, %%mm1\n" // 32-bit scaled Y3Y2 -> mm1
+
+ "packssdw %%mm1, %%mm0\n" // Y3Y2Y1Y0 -> mm0
+
+ //----------------------------------------------------------------------
+
+ "movq 16(%0), %%mm1\n" // B7G7R7B6G6R6B5G5 -> mm7
+
+ "movq %%mm1, %%mm7\n" // B7G7R7B6G6R6B5G5 -> mm1
+
+ "psllq $16, %%mm7\n" // R7B6G6R6B5G500 -> mm7
+
+ "movq %%mm7, %%mm5\n" // R7B6G6R6B5G500 -> mm5
+
+ "movq %%mm0, 8%3\n" // 32-bit scaled Y3Y2Y1Y0 -> TEMPY
+
+ "movq %3, %%mm0\n" // R5B4G4R4 -> mm0
+
+ "punpcklbw ZEROSX, %%mm7\n" // B5G500 -> mm7
+ "movq %%mm0, %%mm6\n" // R5B4G4R4 -> mm6
+
+ "psrlq $32, %%mm0\n" // 00R5B4 -> mm0
+
+ "paddw %%mm0, %%mm7\n" // B5G5R5B4 -> mm7
+ "movq %%mm6, %%mm2\n" // B5B4G4R4 -> mm2
+
+ "pmaddwd YR0GRX, %%mm2\n" // yrR5,ygG4+yrR4 -> mm2
+
+ "pmaddwd YBG0BX, %%mm7\n" // ybB5+ygG5,ybB4 -> mm7
+
+ //----------------------------------------------------------------------
+ "paddd %%mm7, %%mm2\n" // Y5Y4 -> mm2
+
+ //----------------------------------------------------------------------
+
+ "pxor %%mm7, %%mm7\n" // 0 -> mm7
+
+ "punpckhbw %%mm7, %%mm1\n" // B7G7R7B6 -> mm1
+
+ "movq %%mm1, %%mm6\n" // B7G7R7B6 -> mm6
+
+ "pmaddwd YBG0BX, %%mm6\n" // ybB7+ygG7,ybB6 -> mm6
+ "punpckhbw %%mm7, %%mm5\n" // R7B6G6R6 -> mm5
+
+ "pmaddwd YR0GRX, %%mm5\n" // yrR7,ygG6+yrR6 -> mm5
+
+ //----------------------------------------------------------------------
+
+ "psrad $15, %%mm2\n" // 32-bit scaled Y5Y4 -> mm2
+
+ "paddd %%mm5, %%mm6\n" // Y7Y6 -> mm6
+ "psrad $15, %%mm6\n" // 32-bit scaled Y7Y6 -> mm6
+
+ "packssdw %%mm6, %%mm2\n" // Y7Y6Y5Y4 -> mm2
+
+ //----------------------------------------------------------------------
+
+ "movq 8%3, %%mm6\n" // 32-bit scaled Y3Y2Y1Y0 -> mm6
+ "packuswb %%mm2, %%mm6\n" // all 8 Y values -> mm6
+
+ //----------------------------------------------------------------------
+
+ "movq %%mm6, (%1)\n" // store Y
+
+ "add $24, %0\n"
+ "add $8, %1\n"
+
+ "sub $8, %2\n"
+ "jnz 1b\n"
+ "emms\n"
+
+ :
+ : "r" (rgbSource), "r" (lum), "m" (pixel), "m" (buf[0])
+
+ );
+}
+
+void rgb2y32bit_mmx_row(unsigned char* rgbSource, unsigned char* lum, int pixel)
+{
+ unsigned int buf[4];
+
+ // %3 = TEMP0
+ // 8%3 = TEMPY
+
+ __asm__ __volatile__ (
+ "1:\n"
+
+ // pack rgb
+ // was: "movq (%0), %%mm1\n" // load G2R2B1G1R1B0G0R0
+ // ------------------------------
+ // (uses: mm0, mm1)
+ "movd 8(%0), %%mm0\n"
+ "psllq $24, %%mm0\n"
+ "movd 4(%0), %%mm1\n"
+ "por %%mm1, %%mm0\n"
+ "psllq $24, %%mm0\n"
+ "movd (%0), %%mm1\n"
+ "por %%mm0, %%mm1\n"
+ // ------------------------------
+
+ "pxor %%mm6, %%mm6\n" // 0 -> mm6
+ "movq %%mm1, %%mm0\n" // G2R2B1G1R1B0G0R0 -> mm0
+ "psrlq $16, %%mm1\n" // 00G2R2B1G1R1B0 -> mm1
+ "punpcklbw ZEROSX, %%mm0\n" // R1B0G0R0 -> mm0
+ "movq %%mm1, %%mm7\n" // 00G2R2B1G1R1B0 -> mm7
+ "punpcklbw ZEROSX, %%mm1\n" // B1G1R1B0 -> mm1
+ "movq %%mm0, %%mm2\n" // R1B0G0R0 -> mm2
+ "pmaddwd YR0GRX, %%mm0\n" // yrR1,ygG0+yrR0 -> mm0
+ "movq %%mm1, %%mm3\n" // B1G1R1B0 -> mm3
+ "pmaddwd YBG0BX, %%mm1\n" // ybB1+ygG1,ybB0 -> mm1
+ "movq %%mm2, %%mm4\n" // R1B0G0R0 -> mm4
+ "movq %%mm3, %%mm5\n" // B1G1R1B0 -> mm5
+ "punpckhbw %%mm6, %%mm7\n" // 00G2R2 -> mm7
+ "paddd %%mm1, %%mm0\n" // Y1Y0 -> mm0
+
+ // pack rgb
+ // was: "movq 8(%0),%%mm1\n" // R5B4G4R4B3G3R3B2 -> mm1
+ // ------------------------------
+ // (uses: mm1, mm6)
+ "movd 20(%0), %%mm1\n"
+ "psllq $24, %%mm1\n"
+ "movd 16(%0), %%mm6\n"
+ "por %%mm6, %%mm1\n"
+ "psllq $24, %%mm1\n"
+ "movd 12(%0), %%mm6\n"
+ "por %%mm6, %%mm1\n"
+ "psllq $8, %%mm1\n"
+ "movd 8(%0), %%mm6\n"
+ "psrlq $16, %%mm6\n"
+ "por %%mm6, %%mm1\n"
+ // ------------------------------
+
+ "movq %%mm1, %%mm6\n" // R5B4G4R4B3G3R3B2 -> mm6
+ "punpcklbw ZEROSX, %%mm1\n" // B3G3R3B2 -> mm1
+
+ //----------------------------------------------------------------------
+
+ "movq %%mm1, %%mm5\n" // B3G3R3B2 -> mm5
+ "psllq $32, %%mm1\n" // R3B200 -> mm1
+
+ "paddd %%mm7, %%mm1\n" // R3B200+00G2R2=R3B2G2R2->mm1
+
+ "punpckhbw ZEROSX, %%mm6\n" // R5B4G4R3 -> mm6
+ "movq %%mm1, %%mm3\n" // R3B2G2R2 -> mm3
+
+ "pmaddwd YR0GRX, %%mm1\n" // yrR3,ygG2+yrR2 -> mm1
+ "movq %%mm5, %%mm7\n" // B3G3R3B2 -> mm7
+
+ "pmaddwd YBG0BX, %%mm5\n" // ybB3+ygG3,ybB2 -> mm5
+ "psrad $15, %%mm0\n" // 32-bit scaled Y1Y0 -> mm0
+
+ "movq %%mm6, %3\n" // R5B4G4R4 -> TEMP0
+ "movq %%mm3, %%mm6\n" // R3B2G2R2 -> mm6
+
+ "paddd %%mm5, %%mm1\n" // Y3Y2 -> mm1
+ "movq %%mm7, %%mm5\n" // B3G3R3B2 -> mm5
+ "psrad $15, %%mm1\n" // 32-bit scaled Y3Y2 -> mm1
+
+ "packssdw %%mm1, %%mm0\n" // Y3Y2Y1Y0 -> mm0
+
+ //----------------------------------------------------------------------
+
+ // pack rgb
+ // was: "movq 16(%0), %%mm1\n" // B7G7R7B6G6R6B5G5 -> mm1
+ // ------------------------------
+ // (uses: mm1, mm7)
+ "movd 28(%0), %%mm1\n"
+ "psllq $24, %%mm1\n"
+ "movd 24(%0), %%mm7\n"
+ "por %%mm7, %%mm1\n"
+ "psllq $16, %%mm1\n"
+ "movd 20(%0), %%mm7\n"
+ "psrlq $8, %%mm7\n"
+ "por %%mm7, %%mm1\n"
+ // ------------------------------
+
+ "movq %%mm1, %%mm7\n" // B7G7R7B6G6R6B5G5 -> mm1
+
+ "psllq $16, %%mm7\n" // R7B6G6R6B5G500 -> mm7
+
+ "movq %%mm7, %%mm5\n" // R7B6G6R6B5G500 -> mm5
+
+ "movq %%mm0, 8%3\n" // 32-bit scaled Y3Y2Y1Y0 -> TEMPY
+
+ "movq %3, %%mm0\n" // R5B4G4R4 -> mm0
+
+ "punpcklbw ZEROSX, %%mm7\n" // B5G500 -> mm7
+ "movq %%mm0, %%mm6\n" // R5B4G4R4 -> mm6
+
+ "psrlq $32, %%mm0\n" // 00R5B4 -> mm0
+
+ "paddw %%mm0, %%mm7\n" // B5G5R5B4 -> mm7
+ "movq %%mm6, %%mm2\n" // B5B4G4R4 -> mm2
+
+ "pmaddwd YR0GRX, %%mm2\n" // yrR5,ygG4+yrR4 -> mm2
+
+ "pmaddwd YBG0BX, %%mm7\n" // ybB5+ygG5,ybB4 -> mm7
+
+ //----------------------------------------------------------------------
+ "paddd %%mm7, %%mm2\n" // Y5Y4 -> mm2
+
+ //----------------------------------------------------------------------
+
+ "pxor %%mm7, %%mm7\n" // 0 -> mm7
+
+ "punpckhbw %%mm7, %%mm1\n" // B7G7R7B6 -> mm1
+
+ "movq %%mm1, %%mm6\n" // B7G7R7B6 -> mm6
+
+ "pmaddwd YBG0BX, %%mm6\n" // ybB7+ygG7,ybB6 -> mm6
+ "punpckhbw %%mm7, %%mm5\n" // R7B6G6R6 -> mm5
+
+ "pmaddwd YR0GRX, %%mm5\n" // yrR7,ygG6+yrR6 -> mm5
+
+ //----------------------------------------------------------------------
+
+ "psrad $15, %%mm2\n" // 32-bit scaled Y5Y4 -> mm2
+
+ "paddd %%mm5, %%mm6\n" // Y7Y6 -> mm6
+ "psrad $15, %%mm6\n" // 32-bit scaled Y7Y6 -> mm6
+
+ "packssdw %%mm6, %%mm2\n" // Y7Y6Y5Y4 -> mm2
+
+ //----------------------------------------------------------------------
+
+ "movq 8%3, %%mm6\n" // 32-bit scaled Y3Y2Y1Y0 -> mm6
+ "packuswb %%mm2, %%mm6\n" // all 8 Y values -> mm6
+
+ //----------------------------------------------------------------------
+
+ "movq %%mm6, (%1)\n" // store Y
+
+ "add $32, %0\n"
+ "add $8, %1\n"
+
+ "sub $8, %2\n"
+ "jnz 1b\n"
+ "emms\n"
+
+ :
+ : "r" (rgbSource), "r" (lum), "r" (pixel), "m" (buf[0])
+
+ );
+}
+
+#endif
+// INTEL
+
diff --git a/mpeglib/lib/util/render/dither2YUV/rgb2yuv32.h b/mpeglib/lib/util/render/dither2YUV/rgb2yuv32.h
new file mode 100644
index 00000000..75fea27f
--- /dev/null
+++ b/mpeglib/lib/util/render/dither2YUV/rgb2yuv32.h
@@ -0,0 +1,93 @@
+/***************************************************************************
+ rgb2yuv32.h - description
+ -------------------
+ begin : Tue Nov 2 2000
+ copyright : (C) 2000 by Christian Gerlach
+ email : cgerlach@rhrk.uni-kl.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef _RGB2YUV32_H_
+#define _RGB2YUV32_H_
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "../yuvPicture.h"
+#include "rgb2yuvdefs.h"
+
+void rgb2yuv32(unsigned char* rgb, unsigned char* dest);
+
+// slow C rountines
+void rgb2yuv24bit(unsigned char* rgbSource,
+ unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,int height, int width);
+
+void rgb2yuv32bit(unsigned char* rgbSource,
+ unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,int height, int width);
+
+
+
+
+#ifndef INTEL
+void rgb2yuv24bit_mmx(unsigned char* rgbSource,
+ unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,int height, int width);
+
+void rgb2yuv32bit_mmx(unsigned char* rgbSource,
+ unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,int height, int width);
+#endif
+
+
+#ifdef INTEL
+
+void rgb2yuv24bit_mmx(unsigned char* rgbSource,
+ unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,int height, int width);
+
+void rgb2yuv32bit_mmx(unsigned char* rgbSource,
+ unsigned char* lum,
+ unsigned char* cr,
+ unsigned char* cb,int height, int width);
+
+
+void rgb2yuv24bit_mmx444_row(unsigned char* rgb,
+ unsigned char* lum, unsigned char* cr,
+ unsigned char* cb, int pixel);
+
+
+void rgb2yuv24bit_mmx422_row(unsigned char* rgb,
+ unsigned char* lum, unsigned char* cr,
+ unsigned char* cb, int pixel);
+
+void rgb2yuv32bit_mmx422_row(unsigned char* rgb,
+ unsigned char* lum, unsigned char* cr,
+ unsigned char* cb, int pixel);
+
+void rgb2y24bit_mmx_row(unsigned char* rgbSource,
+ unsigned char* lum, int pixel);
+
+void rgb2y32bit_mmx_row(unsigned char* rgbSource,
+ unsigned char* lum, int pixel);
+
+#endif
+//INTEL
+
+
+#endif
diff --git a/mpeglib/lib/util/render/dither2YUV/rgb2yuvdefs.h b/mpeglib/lib/util/render/dither2YUV/rgb2yuvdefs.h
new file mode 100644
index 00000000..5c7ae574
--- /dev/null
+++ b/mpeglib/lib/util/render/dither2YUV/rgb2yuvdefs.h
@@ -0,0 +1,74 @@
+/***************************************************************************
+ rgb2yuvdefs.h - description
+ -------------------
+ begin : Tue Nov 2 2000
+ copyright : (C) 2000 by Christian Gerlach
+ email : cgerlach@rhrk.uni-kl.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __RGB2YUVDEFS_H
+#define __RGB2YUVDEFS_H
+
+/* gcc 3.3.1 and later optimise the "not used" (only in asm code)
+ symbols away. So we need to mark them as used. */
+#if defined(__GNUC_PREREQ__) && !defined(__GNUC_PREREQ)
+#define __GNUC_PREREQ __GNUC_PREREQ__
+#endif
+#ifdef __GNUC_PREREQ
+#if __GNUC_PREREQ (3,1)
+# define __attribute_used__ __attribute__ ((__used__))
+#else
+# define __attribute_used__
+#endif
+#else
+# define __attribute_used__
+#endif
+
+// hicolor mode (16 bit) with r(5) g(6) b(5) bits (reverse order b, g, r)
+#define RED(rgb) (unsigned char) ((rgb) << 3)
+#define GREEN(rgb) (((rgb) & 0x7e0) >> 3)
+#define BLUE(rgb) (((rgb) & 0xf800) >> 8)
+
+#define YUV_SHIFT 15
+#define YUV_HALF (1<<(YUV_SHIFT-1))
+#define YUV_ONE (1<<YUV_SHIFT)
+#define Y_R ((int)( 0.299 * YUV_ONE ))
+#define Y_G ((int)( 0.587 * YUV_ONE ))
+#define Y_B ((int)( 0.114 * YUV_ONE ))
+#define U_R ((int)(-0.146 * YUV_ONE ))
+#define U_G ((int)(-0.288 * YUV_ONE ))
+#define U_B ((int)( 0.434 * YUV_ONE ))
+#define V_R ((int)( 0.617 * YUV_ONE ))
+#define V_G ((int)(-0.517 * YUV_ONE ))
+#define V_B ((int)(-0.100 * YUV_ONE ))
+
+#define Y_RGB(R,G,B) (( Y_R * (R) + Y_G * (G) + Y_B * (B)) >> YUV_SHIFT)
+#define U_RGB(R,G,B) ((( U_R * (R) + U_G * (G) + U_B * (B)) >> YUV_SHIFT) + 128)
+#define V_RGB(R,G,B) ((( V_R * (R) + V_G * (G) + V_B * (B)) >> YUV_SHIFT) + 128)
+
+static unsigned char __attribute_used__ CLEARX[8] = { 255, 0, 255, 0, 255, 0, 255, 0 };
+static short __attribute_used__ ZEROSX[4] = { 0, 0, 0, 0 };
+
+static short __attribute_used__ OFFSETDX[4] = { 0, 64, 0, 64 };
+static short __attribute_used__ OFFSETWX[4] = { 128, 0, 128, 0 };
+static short __attribute_used__ OFFSETBX[4] = { 128, 128, 128, 128 };
+
+static short __attribute_used__ YR0GRX[4] = { Y_R, Y_G, 0, Y_R };
+static short __attribute_used__ YBG0BX[4] = { Y_B, 0, Y_G, Y_B };
+
+static short __attribute_used__ UR0GRX[4] = { U_R, U_G, 0, U_R };
+static short __attribute_used__ UBG0BX[4] = { U_B, 0, U_G, U_B };
+
+static short __attribute_used__ VR0GRX[4] = { V_R, V_G, 0, V_R };
+static short __attribute_used__ VBG0BX[4] = { V_B, 0, V_G, V_B };
+
+#endif
diff --git a/mpeglib/lib/util/render/imageBase.cpp b/mpeglib/lib/util/render/imageBase.cpp
new file mode 100644
index 00000000..040486ea
--- /dev/null
+++ b/mpeglib/lib/util/render/imageBase.cpp
@@ -0,0 +1,76 @@
+/*
+ base clase for X11 images (stores important parameters and dither pic)
+ 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 "imageBase.h"
+
+#include <iostream>
+
+using namespace std;
+
+ImageBase::ImageBase() {
+ identifier = NULL;
+}
+
+
+ImageBase::~ImageBase() {
+ if (identifier != NULL)
+ delete [] identifier;
+}
+
+void ImageBase::init(XWindow* xWindow, YUVPicture*)
+{
+ cout << "direct virtual call: ImageBase::init "<<endl;
+}
+
+int ImageBase::support() {
+ cout << "direct virtual call: ImageBase::support "<<endl;
+ return false;
+}
+
+int ImageBase::openImage(int) {
+ cout << "direct virtual call: ImageBase::openImage "<<endl;
+ return false;
+}
+
+
+int ImageBase::closeImage(){
+ cout << "direct virtual call: ImageBase::closeImage "<<endl;
+ return false;
+}
+
+void ImageBase::ditherImage(YUVPicture*) {
+ cout << "direct virtual call: ImageBase::ditherImage "<<endl;
+}
+
+
+void ImageBase::putImage() {
+ cout << "direct virtual call: ImageBase::putImage "<<endl;
+}
+
+void ImageBase::putImage(int ,int ) {
+ cout << "direct virtual call: ImageBase::putImage(w,h) "<<endl;
+}
+
+void ImageBase::setIdentifier(const char *id)
+{
+ if (identifier != NULL)
+ delete [] identifier;
+
+ identifier = new char [strlen(id) + 1];
+ strcpy(identifier, id);
+}
+
+char *ImageBase::getIdentifier()
+{
+ return identifier;
+}
diff --git a/mpeglib/lib/util/render/imageBase.h b/mpeglib/lib/util/render/imageBase.h
new file mode 100644
index 00000000..e1f7ae8c
--- /dev/null
+++ b/mpeglib/lib/util/render/imageBase.h
@@ -0,0 +1,140 @@
+/*
+ base clase for X11 images (stores important parameters and dither pic)
+ 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 __IMAGEBASE_H
+#define __IMAGEBASE_H
+
+
+#include <stdio.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include "yuvPicture.h"
+#include "dither/ditherWrapper.h"
+
+
+
+#define _IMAGE_NONE 0
+#define _IMAGE_DESK 1
+#define _IMAGE_FULL 2
+#define _IMAGE_DOUBLE 4
+#define _IMAGE_RESIZE 8
+#define _IMAGE_DISABLED 16
+
+
+#define HAS_DESK(image) ((((image)->supportedModes) & _IMAGE_DESK) > 0)
+#define HAS_FULL(image) ((((image)->supportedModes) & _IMAGE_FULL) > 0)
+#define HAS_DOUBLE(image) ((((image)->supportedModes) & _IMAGE_DOUBLE) > 0)
+#define HAS_RESIZE(image) ((((image)->supportedModes) & _IMAGE_RESIZE) > 0)
+#define IS_DISABLED(image) ((((image)->supportedModes) & _IMAGE_DISABLED) > 0)
+
+#define IS_DESK(mode) (((mode) & _IMAGE_DESK) > 0)
+#define IS_FULL(mode) (((mode) & _IMAGE_FULL) > 0)
+#define IS_DOUBLE(mode) (((mode) & _IMAGE_DOUBLE) > 0)
+#define IS_RESIZEABLE(mode) (((mode) & _IMAGE_RESIZE) > 0)
+
+
+/**
+ This class creates from a given X11 Window a special image to
+ display.
+ An image has some characteristics, like startadress, width height,
+ if each row has a terminating modifier etc...
+
+ The image is resposible for the conversion from the yuv
+ format to the destination.
+
+ It is initialized with the constructed x11Window.
+ During a mode-switch (which is handled by x11window) the following
+ sequence is called:
+
+ support() ->true/false if this image type is supported
+ (switching to it is allowed)
+
+ openImage() called once when we switch to this
+ image type
+
+ ditherImage(..) for the conversion from yuv->rgb
+ obviously called for every image
+ putImage(..) time for display it
+
+ closeImage() called once, when we leave this image type
+
+
+ This sequence is necessary, because the user likey to switch
+ form desktop display to dga fullscreen.
+
+ The following image classes seems to be useful:
+
+ imageDeskX11 : standard ximage, maybe with shared mem support
+ full software rendering
+ imageDeskXV : image with hardware yuv->rgb rendering
+
+ imageDGAFull : dga 2.0 full software rendering (needs root)
+ imageXVFull : fullscreen hardware yuv->rgb rendering
+
+ The hierarchy is as follows:
+
+ (desk mode)
+ imageStdX11 : fallback, should work everywhere
+ imageStdXV : if supported imageStdX11 is disabled
+
+ (fullscreen mode)
+ imageDGAFull :
+ imageXVFull :
+
+ The supported switches between the modes are
+
+
+ desktop <-> fullscreen mode.
+
+
+*/
+
+
+class XWindow;
+
+class ImageBase {
+ private:
+ char *identifier;
+
+ public:
+ unsigned int supportedModes;
+
+ public:
+ ImageBase();
+ virtual ~ImageBase();
+
+ virtual void init(XWindow* xWindow, YUVPicture* pic = NULL);
+
+ virtual int support();
+
+ virtual int openImage(int imageMode);
+ virtual int closeImage();
+
+ virtual void ditherImage(YUVPicture* pic);
+ virtual void putImage();
+ virtual void putImage(int w,int h);
+
+ virtual int active() { return true; }
+
+ void setIdentifier(const char *id);
+ char *getIdentifier();
+
+};
+
+#endif
+
diff --git a/mpeglib/lib/util/render/pictureArray.cpp b/mpeglib/lib/util/render/pictureArray.cpp
new file mode 100644
index 00000000..71381ea0
--- /dev/null
+++ b/mpeglib/lib/util/render/pictureArray.cpp
@@ -0,0 +1,101 @@
+/*
+ nice try of an X11 output 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 "pictureArray.h"
+
+
+
+PictureArray::PictureArray(int width, int height) {
+ int i;
+ pictureCallback=NULL;
+ imageType=PICTURE_NO_TYPE;
+
+ for (i=0;i<_PICTURE_ARRAY_SIZE;i++) {
+ pictureArray[i]=new YUVPicture(width,height);
+ imageType=pictureArray[i]->getImageType();
+ }
+
+ /* Find a pict image structure in ring buffer not currently locked. */
+ /* Set current pict image structure to the one just found in ring. */
+
+ current=pictureArray[0];
+ past=pictureArray[1];
+ future=pictureArray[2];
+
+ picPerSec=0.0;
+ this->width=width;
+ this->height=height;
+
+}
+
+
+PictureArray::~PictureArray() {
+ int i;
+ for (i=0;i<_PICTURE_ARRAY_SIZE;i++) {
+ if (pictureArray[i] != NULL) {
+ delete pictureArray[i];
+ pictureArray[i]=NULL;
+ }
+
+ }
+}
+
+
+
+
+
+void PictureArray::setPicturePerSecond(double val) {
+ picPerSec=val;
+}
+
+
+double PictureArray::getPicturePerSecond() {
+ return picPerSec;
+}
+
+
+
+
+void PictureArray::forward() {
+ /* Update past and future references if needed. */
+
+ YUVPicture* tmp=past;
+
+ past = future;
+ future = current;
+ current = tmp;
+
+
+}
+
+
+
+
+YUVPicture* PictureArray::getYUVPictureCallback() {
+ return pictureCallback;
+}
+
+
+void PictureArray::setYUVPictureCallback(YUVPicture* pic) {
+ this->pictureCallback=pic;
+}
+
+
+void PictureArray::setImageType(int imageType) {
+ int i;
+ this->imageType=imageType;
+ for (i=0;i<_PICTURE_ARRAY_SIZE;i++) {
+ pictureArray[i]->setImageType(imageType);
+ }
+}
+
diff --git a/mpeglib/lib/util/render/pictureArray.h b/mpeglib/lib/util/render/pictureArray.h
new file mode 100644
index 00000000..6a7e731c
--- /dev/null
+++ b/mpeglib/lib/util/render/pictureArray.h
@@ -0,0 +1,76 @@
+/*
+ nice try of an X11 output 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 __VIDEOOUTPUTX11_H
+#define __VIDEOOUTPUTX11_H
+
+
+#include "yuvPicture.h"
+#include <stdlib.h>
+
+#define _PICTURE_ARRAY_SIZE 5
+
+class PictureArray {
+
+ class YUVPicture* pictureArray[_PICTURE_ARRAY_SIZE];
+
+ class YUVPicture* past; /* Past predictive frame. */
+ class YUVPicture* future; /* Future predictive frame. */
+ class YUVPicture* current; /* Current frame. */
+
+ double picPerSec;
+ int width;
+ int height;
+
+ int imageType;
+
+ public:
+ PictureArray(int width, int height);
+ ~PictureArray();
+
+ inline YUVPicture* getPast() {return past;}
+ inline YUVPicture* getFuture() {return future;}
+ inline YUVPicture* getCurrent() {return current;}
+
+
+ inline void setPast(YUVPicture* pic) {past=pic;}
+ inline void setFuture(YUVPicture* pic) {future=pic;}
+ inline void setCurrent(YUVPicture* pic) {current=pic;}
+ inline int getWidth() { return width; }
+ inline int getWidth_Half() { return width/2; }
+
+ // attention with these!
+ // these are shares pointer
+ // only call after mpegVidRsrc and then set them back to NULL
+ YUVPicture* getYUVPictureCallback();
+ void setYUVPictureCallback(YUVPicture* pic);
+
+
+ void forward();
+
+ void setPicturePerSecond(double val);
+ double getPicturePerSecond();
+
+ // use these to swap the yuv Mode
+ inline int getImageType() { return imageType; }
+ void setImageType(int mode);
+
+
+ private:
+ YUVPicture* pictureCallback;
+
+
+};
+#endif
+
diff --git a/mpeglib/lib/util/render/renderMachine.cpp b/mpeglib/lib/util/render/renderMachine.cpp
new file mode 100644
index 00000000..c6327930
--- /dev/null
+++ b/mpeglib/lib/util/render/renderMachine.cpp
@@ -0,0 +1,205 @@
+ /*
+ puts the yuv images onto a surface
+ 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 "renderMachine.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+RenderMachine::RenderMachine() {
+
+#ifndef SDL_WRAPPER
+ surface=new X11Surface();
+#endif
+#ifdef SDL_WRAPPER
+ surface=new SDLSurface();
+#endif
+
+
+ pictureArray=NULL;
+
+ startTime=new TimeStamp();
+ endTime=new TimeStamp();
+
+ initialMode = _IMAGE_DESK;
+}
+
+
+RenderMachine::~RenderMachine() {
+
+
+ closeWindow();
+ delete surface;
+
+ delete startTime;
+ delete endTime;
+
+}
+
+
+
+
+
+
+void RenderMachine::waitRestTime() {
+ endTime->gettimeofday();
+ startTime->minus(endTime,endTime);
+ endTime->waitForIt();
+
+}
+
+int RenderMachine::x11WindowId()
+{
+ return surface->x11WindowId();
+}
+
+
+int RenderMachine::openWindow(int width,
+ int height,const char *title) {
+if (surface->open(width,height,title)) {
+ pictureArray=new PictureArray(width, height);
+
+ return switchToMode(initialMode);
+ }
+ return false;
+}
+
+
+void RenderMachine::closeWindow() {
+
+ if (surface->isOpen()==false) {
+ return;
+ }
+ if (pictureArray != NULL) {
+ delete pictureArray;
+ pictureArray=NULL;
+ }
+ surface->close();
+}
+
+/**
+ important method. This is our only way to switch from
+ fullscreen back to the desktop screen.
+ This method is called if the video end (normal or by user request)
+ We dont have a callback, thus after the image stops, we would
+ never get events.
+*/
+void RenderMachine::flushWindow() {
+
+ // we always switch back to desk mode.
+ if (IS_FULL(surface->getImageMode())) {
+ switchToMode(surface->getImageMode() ^ _IMAGE_DESK ^ _IMAGE_FULL);
+ }
+
+
+}
+
+
+
+
+void RenderMachine::putImage(YUVPicture* pic,
+ TimeStamp* waitTime,
+ TimeStamp* ) {
+ if (pic == NULL) {
+ cout << "pic is null"<<endl;
+ return;
+ }
+ startTime->gettimeofday();
+ startTime->addOffset(waitTime);
+
+ // need dither?
+ surface->dither(pic);
+
+ int nextMode;
+ if (surface->checkEvent(&nextMode) == true) {
+ switchToMode(nextMode);
+ }
+ surface->putImage(pic);
+ waitRestTime();
+}
+
+
+int RenderMachine::switchToMode(int mode) {
+ if (surface->getImageMode() != mode) {
+ surface->closeImage();
+ if (mode != _IMAGE_NONE) {
+ surface->openImage(mode);
+ }
+
+ else {
+ cout << "no imageMode, no open, that's life"<<endl;
+ return false;
+ }
+ }
+ return true;
+}
+
+
+
+PictureArray* RenderMachine::lockPictureArray() {
+ return pictureArray;
+}
+
+
+void RenderMachine::unlockPictureArray(PictureArray* pictureArray) {
+
+ // chance to switch mode
+
+
+ // put picture out
+ if (surface->getImageMode() != _IMAGE_NONE) {
+ YUVPicture* pic=pictureArray->getYUVPictureCallback();
+ if (pic != NULL) {
+ TimeStamp* waitTime=pic->getWaitTime();
+ TimeStamp* earlyTime=pic->getEarlyTime();
+ putImage(pic,waitTime,earlyTime);
+ }
+ } else {
+ cout << "no mode selected"<<endl;
+ }
+}
+
+
+void RenderMachine::config(const char* key,
+ const char* value,void* user_data) {
+ if (strcmp(key,"getDepth")==0) {
+ int* val=(int*)user_data;
+ *val=surface->getDepth();
+ }
+ if (surface != NULL) {
+ int mode = surface->getImageMode();
+ if (strcmp(key,"toggleFullscreen")==0) {
+ if (surface->findImage(mode ^ _IMAGE_FULL) != NULL) {
+ if (surface->isOpen())
+ switchToMode(mode ^ _IMAGE_FULL);
+ else
+ initialMode = _IMAGE_FULL;
+ }
+ }
+ if (strcmp(key,"toggleDouble")==0) {
+ if (surface->findImage(mode ^ _IMAGE_DOUBLE) != NULL) {
+ if (surface->isOpen())
+ switchToMode(mode ^ _IMAGE_DOUBLE);
+ else
+ initialMode = _IMAGE_DOUBLE;
+ }
+ }
+ }
+
+ surface->config(key,value,user_data);
+}
+
+
+
diff --git a/mpeglib/lib/util/render/renderMachine.h b/mpeglib/lib/util/render/renderMachine.h
new file mode 100644
index 00000000..728a6740
--- /dev/null
+++ b/mpeglib/lib/util/render/renderMachine.h
@@ -0,0 +1,90 @@
+/*
+ puts the yuv images onto a surface
+ 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 __RENDERMACHINE_H
+#define __RENDERMACHINE_H
+
+
+
+
+/**
+ RenderMachine. We still have the problem, because of performance,
+ that we cannot have a yuv picture format in the decoder
+ and one in the output to x11. they must be shared.
+ XV support then directly works on them and SDL images
+ can be exported to the decoder as well.
+
+ Another point is : mode switch. User want desktop->fullscreen switch.
+ Due to the threaded nature, we must have a single synchronization
+ point, when we know that the decoder currently does _not_ decode
+ so that we can switch the imaged and free the memory.
+
+ Some points are currently unclear, for example how to handle
+ applications, which want to redirect the image into their own
+ buffers, but hey, there are that many classes and layers
+ I really think it should be doable somehow
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef SDL_WRAPPER
+#include "x11/x11Surface.h"
+#endif
+
+#ifdef SDL_WRAPPER
+#include "sdl/sdlSurface.h"
+#endif
+
+#include "pictureArray.h"
+#include "../abstract/abs_thread.h"
+
+class RenderMachine {
+
+
+ Surface* surface;
+ PictureArray* pictureArray;
+
+
+ TimeStamp* startTime;
+ TimeStamp* endTime;
+
+ int initialMode;
+
+ public:
+ RenderMachine();
+ ~RenderMachine();
+
+ int openWindow(int width, int height,const char *title);
+ int x11WindowId();
+ void closeWindow();
+ void flushWindow();
+
+
+ PictureArray* lockPictureArray();
+ void unlockPictureArray(PictureArray* pictureArray);
+
+ void config(const char* key, const char* value,void* user_data);
+
+ private:
+ void waitRestTime();
+ void putImage(YUVPicture* pic,TimeStamp* waitTime,TimeStamp* earlyTime);
+
+ int switchToMode(int mode);
+
+};
+#endif
diff --git a/mpeglib/lib/util/render/sdl/Makefile.am b/mpeglib/lib/util/render/sdl/Makefile.am
new file mode 100644
index 00000000..1a4b85eb
--- /dev/null
+++ b/mpeglib/lib/util/render/sdl/Makefile.am
@@ -0,0 +1,43 @@
+# player - Makefile.am
+
+INCLUDES = $(all_includes)
+
+
+noinst_LTLIBRARIES = libutilsdl.la
+
+noinst_HEADERS = imageDeskSDL.h sdlSurface.h
+
+libutilsdl_la_SOURCES = imageDeskSDL.cpp sdlSurface.cpp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/util/render/sdl/imageDeskSDL.cpp b/mpeglib/lib/util/render/sdl/imageDeskSDL.cpp
new file mode 100644
index 00000000..b1ff9a7c
--- /dev/null
+++ b/mpeglib/lib/util/render/sdl/imageDeskSDL.cpp
@@ -0,0 +1,110 @@
+/*
+ SDL surface output
+ 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 "imageDeskSDL.h"
+
+#ifdef SDL_WRAPPER
+
+
+ImageDeskSDL::ImageDeskSDL() {
+
+ this->surface=NULL;
+ this->rect=NULL;
+ imageMode=_IMAGE_NONE;
+ lSupport=true;
+ image=NULL;
+}
+
+
+ImageDeskSDL::~ImageDeskSDL() {
+ closeImage();
+ cout << "SDL destry needed"<<endl;
+}
+
+
+
+int ImageDeskSDL::support() {
+ return lSupport;
+}
+
+
+void ImageDeskSDL::init(XWindow* xWindow, YUVPicture* pic) {
+ cout << "ImageDeskSDL::init"<<endl;
+ this->surface=(SDL_Surface*)xWindow;
+ this->rect=(SDL_Rect*)pic;
+}
+
+int ImageDeskSDL::openImage(int imageMode) {
+ int w=rect->w;
+ int h=rect->h;
+ this->imageMode=imageMode;
+ /* Create a YV12 image (Y + V + U) */
+ cout << "CreateYUVOverlay -s"<<imageMode<<" w:"<<w<<" h:"<<h<<endl;
+ image = SDL_CreateYUVOverlay(w,h,
+ SDL_YV12_OVERLAY,
+ surface);
+ if (image == NULL) {
+ cout << "error creating image"<<endl;
+ exit(0);
+ }
+ cout << "CreateYUVOverlay -e"<<endl;
+ return true;
+}
+
+
+int ImageDeskSDL::closeImage() {
+ if (image != NULL) {
+ cout << "FreeYUVOverlay -s"<<endl;
+ SDL_FreeYUVOverlay(image);
+ // otherwise test of NULL will fail
+ image = NULL;
+ cout << "FreeYUVOverlay -e"<<endl;
+ }
+ return true;
+}
+
+
+
+void ImageDeskSDL::ditherImage(YUVPicture* pic) {
+
+ int w=pic->getWidth();
+ int h=pic->getHeight();
+ int size=w*h+(w*h)/2;
+ SDL_LockYUVOverlay(image);
+ memcpy(*((char**)image->pixels),pic->getLuminancePtr(),size);
+ SDL_UnlockYUVOverlay(image);
+
+}
+
+
+void ImageDeskSDL::putImage(int w, int h) {
+ SDL_Rect dest;
+ dest.x=0;
+ dest.y=0;
+ dest.w=rect->w;
+ dest.h=rect->h;
+ if (imageMode & _IMAGE_RESIZE) {
+ dest.w = w;
+ dest.h = h;
+ }
+
+ if (imageMode & _IMAGE_DOUBLE) {
+ dest.w*=2;
+ dest.h*=2;
+ }
+ SDL_DisplayYUVOverlay(image,&dest);
+
+}
+
+#endif
+
diff --git a/mpeglib/lib/util/render/sdl/imageDeskSDL.h b/mpeglib/lib/util/render/sdl/imageDeskSDL.h
new file mode 100644
index 00000000..1bccb94a
--- /dev/null
+++ b/mpeglib/lib/util/render/sdl/imageDeskSDL.h
@@ -0,0 +1,65 @@
+/*
+ SDL surface output
+ 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 __IMAGEDESKSDL_H
+#define __IMAGEDESKSDL_H
+
+#include "../imageBase.h"
+
+
+
+#ifndef SDL_WRAPPER
+ class ImageDeskSDL : public ImageBase {
+ };
+#endif
+
+#ifdef SDL_WRAPPER
+
+#if defined WIN32
+#include <SDL.h>
+#include <SDL_video.h>
+#else
+#include <SDL/SDL.h>
+#include <SDL/SDL_video.h>
+#endif
+
+class ImageDeskSDL : public ImageBase {
+
+ int lSupport;
+ SDL_Overlay *image;
+
+ SDL_Surface* surface;
+ SDL_Rect* rect;
+ int imageMode;
+
+ public:
+ ImageDeskSDL();
+ ~ImageDeskSDL();
+
+ int support();
+ void init(XWindow* xWindow, YUVPicture* pic=NULL);
+
+
+ int openImage(int imageMode);
+ int closeImage();
+
+ void ditherImage(YUVPicture* pic);
+
+ void putImage(int w, int h);
+
+
+
+};
+#endif
+
+#endif
diff --git a/mpeglib/lib/util/render/sdl/sdlSurface.cpp b/mpeglib/lib/util/render/sdl/sdlSurface.cpp
new file mode 100644
index 00000000..86ef41bb
--- /dev/null
+++ b/mpeglib/lib/util/render/sdl/sdlSurface.cpp
@@ -0,0 +1,219 @@
+/*
+ surface wrapper for SDL
+ 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 "sdlSurface.h"
+
+
+#ifdef SDL_WRAPPER
+
+
+SDLSurface::SDLSurface() {
+ surface=NULL;
+ lOpen=false;
+ imageMode=_IMAGE_NONE;
+ lSDLInit=false;
+ imageDeskSDL=new ImageDeskSDL();
+}
+
+
+SDLSurface::~SDLSurface() {
+ close();
+ if (imageCurrent != NULL) {
+ imageCurrent->closeImage();
+ delete imageCurrent;
+ // otherwise test of NULL will fail
+ imageCurrent = NULL;
+ }
+}
+
+
+int SDLSurface::isOpen() {
+ return lOpen;
+}
+
+int SDLSurface::getImageMode() {
+ return imageMode;
+}
+
+int SDLSurface::open(int width, int height,const char *title,bool border) {
+ cout << "SDL openImage:"<<title<<endl;
+
+ sdlinit();
+
+ rect.x = 0;
+ rect.y = 0;
+ rect.w = width;
+ rect.h = height;
+
+ return true;
+}
+
+
+int SDLSurface::close() {
+ if (isOpen()==false) {
+ cout << "WindowOut::closeWindow already closed"<<endl;
+ return true;
+ }
+ if(surface) {
+ SDL_FreeSurface(surface);
+ surface = NULL;
+ }
+
+ lOpen=false;
+ return true;
+}
+
+
+int SDLSurface::getHeight() {
+ return rect.h;
+}
+
+
+int SDLSurface::getWidth() {
+ return rect.w;
+}
+
+
+int SDLSurface::getDepth() {
+ return video_bpp;
+}
+
+int SDLSurface::putImage(YUVPicture* ) {
+ return true;
+}
+
+
+int SDLSurface::openImage(int imageMode, YUVPicture* pic) {
+ if (this->imageMode != _IMAGE_NONE) {
+ cout << "bad open error X11Surface::openImage"<<endl;
+ exit(0);
+ }
+ cout << "************* openImage SDL"<<imageMode<<endl;
+ this->imageMode=imageMode;
+ imageCurrent=NULL;
+ int w=getWidth();
+ int h=getHeight();
+ if(imageMode & _IMAGE_RESIZE) {
+ w=resize_rect.w;
+ h=resize_rect.h;
+ }
+
+ if (imageMode & _IMAGE_DOUBLE) {
+ w=rect.w*2;
+ h=rect.h*2;
+ }
+
+ if (imageMode & _IMAGE_DESK) {
+ if (imageDeskSDL->support()) {
+ imageCurrent=imageDeskSDL;
+ int video_flags = SDL_SWSURFACE;
+ video_flags |= SDL_ASYNCBLIT;
+ video_flags |= SDL_RESIZABLE;
+ if(surface)
+ SDL_FreeSurface(surface);
+ surface = SDL_SetVideoMode(w, h, video_bpp, video_flags);
+
+ }
+ }
+ if (imageMode & _IMAGE_FULL) {
+ if (imageDeskSDL->support()) {
+ imageCurrent=imageDeskSDL;
+ int video_flags = SDL_FULLSCREEN;
+ video_flags |= SDL_ASYNCBLIT;
+ video_flags |= SDL_HWSURFACE;
+ if(surface)
+ SDL_FreeSurface(surface);
+ surface = SDL_SetVideoMode(w, h, video_bpp, video_flags);
+ }
+ }
+ if (imageCurrent != NULL) {
+ cout << "surface:"<<surface<<endl;
+ imageCurrent->init((XWindow*)surface,(YUVPicture*)&rect);
+ imageCurrent->openImage(imageMode);
+ }
+ return (imageCurrent != NULL);
+}
+
+
+int SDLSurface::closeImage() {
+ this->imageMode = _IMAGE_NONE;
+ if (imageCurrent != NULL) {
+ imageCurrent->closeImage();
+ }
+ imageCurrent=NULL;
+ return true;
+}
+
+int SDLSurface::checkEvent(int* newMode) {
+ int back=false;
+ SDL_Event event;
+ SDL_PollEvent(&event);
+ switch (event.type) {
+ case SDL_MOUSEBUTTONDOWN: {
+ int button=event.button.button;
+ if (button == 1) {
+ *newMode = imageMode ^ _IMAGE_DOUBLE;
+ back=true;
+ }
+ if (button == 3) {
+ *newMode = imageMode ^ _IMAGE_DESK ^ _IMAGE_FULL;
+ back=true;
+ }
+ break;
+ }
+ case SDL_VIDEORESIZE : {
+ resize_rect.w = event.resize.w;
+ resize_rect.h = event.resize.h;
+ *newMode = imageMode | _IMAGE_RESIZE;
+ back = true;
+ break;
+ }
+
+ }
+ return back;
+}
+
+int SDLSurface::dither(YUVPicture* pic) {
+ if (imageCurrent != NULL) {
+ imageCurrent->ditherImage(pic);
+ if(imageMode & _IMAGE_RESIZE) {
+ imageCurrent->putImage(resize_rect.w, resize_rect.h);
+ } else {
+ imageCurrent->putImage(rect.w, rect.h);
+ }
+ }
+ return true;
+}
+
+void SDLSurface::sdlinit() {
+ if (lSDLInit == false) {
+ if (SDL_Init(SDL_INIT_VIDEO) < 0 ) {
+ fprintf(stderr, "Warning: Couldn't init SDL video: %s\n",
+ SDL_GetError());
+ fprintf(stderr, "Will ignore video stream\n");
+ exit(0);
+ }
+ atexit(SDL_Quit);
+ cout << "****************** SDL VIDEO System **********"<<endl;
+ /* Get the "native" video mode */
+ video_info=SDL_GetVideoInfo();
+ video_bpp=video_info->vfmt->BitsPerPixel;
+ imageMode=_IMAGE_NONE;
+
+ imageCurrent=NULL;
+ }
+ lSDLInit=true;
+}
+
+#endif
diff --git a/mpeglib/lib/util/render/sdl/sdlSurface.h b/mpeglib/lib/util/render/sdl/sdlSurface.h
new file mode 100644
index 00000000..aca5f293
--- /dev/null
+++ b/mpeglib/lib/util/render/sdl/sdlSurface.h
@@ -0,0 +1,78 @@
+/*
+ surface wrapper for SDL
+ 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 __SDLSURFACE_H
+#define __SDLSURFACE_H
+
+
+#include "../surface.h"
+#include "imageDeskSDL.h"
+
+
+
+#ifndef SDL_WRAPPER
+ class SDLSurface : public Surface {
+ };
+#endif
+
+#ifdef SDL_WRAPPER
+#if defined WIN32
+#include <SDL.h>
+#include <SDL_video.h>
+#else
+#include <SDL/SDL.h>
+#include <SDL/SDL_video.h>
+#endif
+
+
+class SDLSurface : public Surface {
+
+ int lOpen;
+ int imageMode;
+ int lSDLInit;
+ int video_bpp;
+ SDL_Surface* surface;
+ SDL_Rect rect;
+ SDL_Rect resize_rect;
+ const SDL_VideoInfo *video_info;
+
+ ImageBase* imageCurrent;
+
+ ImageDeskSDL* imageDeskSDL;
+
+ public:
+ SDLSurface();
+ ~SDLSurface();
+
+ int isOpen();
+ int open(int width, int height,const char *title, bool border=false);
+ int close();
+ int getHeight();
+ int getWidth();
+ int getDepth();
+ int getImageMode();
+ int checkEvent(int* mode);
+
+ int openImage(int imageMode, YUVPicture* pic = NULL);
+ int closeImage();
+ int dither(YUVPicture* pic);
+ int putImage(YUVPicture* pic);
+
+
+ private:
+ void sdlinit();
+};
+#endif
+
+#endif
diff --git a/mpeglib/lib/util/render/surface.cpp b/mpeglib/lib/util/render/surface.cpp
new file mode 100644
index 00000000..12a15410
--- /dev/null
+++ b/mpeglib/lib/util/render/surface.cpp
@@ -0,0 +1,117 @@
+/*
+ surface 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 "surface.h"
+
+#include <iostream>
+
+using namespace std;
+
+Surface::Surface() {
+}
+
+
+Surface::~Surface() {
+}
+
+
+int Surface::isOpen() {
+ cout << "direct virtual call Surface::isOpen "<<endl;
+ return false;
+}
+
+
+int Surface::open(int width, int height,const char *title, bool border) {
+ cout << "direct virtual call Surface::open "<<endl;
+ cout << "width:"<<width<<" height:"<<height
+ << " title:"<<title<<endl;
+ return false;
+}
+
+
+int Surface::close() {
+ cout << "direct virtual call Surface::close "<<endl;
+ return true;
+}
+
+
+int Surface::getHeight() {
+ cout << "direct virtual call Surface::getHeight "<<endl;
+ return 0;
+}
+
+
+int Surface::getWidth() {
+ cout << "direct virtual call Surface::getWidth "<<endl;
+ return 0;
+}
+
+
+int Surface::getDepth() {
+ cout << "direct virtual call Surface::getDepth "<<endl;
+ return 0;
+}
+
+int Surface::getImageMode() {
+ cout << "direct virtual call Surface::getImageMode "<<endl;
+ return 0;
+}
+
+int Surface::x11WindowId() {
+ cout << "direct virtual call Surface::x11WindowId " << endl;
+ return -1;
+}
+
+ImageBase *Surface::findImage(int)
+{
+ cout << "direct virtual call: Surface::findImage "<<endl;
+ return NULL;
+}
+
+int Surface::openImage(int mode, YUVPicture*) {
+ cout << "direct virtual call Surface::openImage "<<endl;
+ cout << "imageMode:"<<mode<<endl;
+ return false;
+}
+
+
+int Surface::closeImage() {
+ cout << "direct virtual call Surface::closeImage "<<endl;
+ return true;
+}
+
+
+int Surface::dither(YUVPicture* pic) {
+ cout << "direct virtual call Surface::dither "<<endl;
+ pic->print("Surface::dither");
+ return false;
+}
+
+
+int Surface::putImage(YUVPicture* pic) {
+ cout << "direct virtual call Surface::putImage "<<endl;
+ pic->print("Surface::putImage");
+ return false;
+}
+
+int Surface::checkEvent(int*) {
+ cout << "direct virtual call Surface::checkEvent "<<endl;
+ return false;
+}
+
+void Surface::config(const char* ,
+ const char* ,void* ) {
+ cout << "direct virtual call Surface::config"<<endl;
+}
+
diff --git a/mpeglib/lib/util/render/surface.h b/mpeglib/lib/util/render/surface.h
new file mode 100644
index 00000000..84de996a
--- /dev/null
+++ b/mpeglib/lib/util/render/surface.h
@@ -0,0 +1,55 @@
+/*
+ surface 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 __SURFACE_H
+#define __SURFACE_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "yuvPicture.h"
+
+class ImageBase;
+
+class Surface {
+
+ public:
+ Surface();
+ virtual ~Surface();
+
+ virtual int isOpen();
+ virtual int open(int width, int height,const char *title, bool border=false);
+ virtual int close();
+ virtual int getHeight();
+ virtual int getWidth();
+ virtual int getDepth();
+ virtual int getImageMode();
+ virtual int x11WindowId();
+
+ virtual ImageBase *findImage(int imageMode);
+
+ virtual int openImage(int mode, YUVPicture* pic = NULL);
+ virtual int closeImage();
+ virtual int dither(YUVPicture* pic);
+ virtual int putImage(YUVPicture* pic);
+
+ virtual int checkEvent(int* mode);
+
+ // config surface
+ virtual void config(const char* key,
+ const char* value,void* user_data);
+
+
+};
+#endif
diff --git a/mpeglib/lib/util/render/x11/Makefile.am b/mpeglib/lib/util/render/x11/Makefile.am
new file mode 100644
index 00000000..97ab0d67
--- /dev/null
+++ b/mpeglib/lib/util/render/x11/Makefile.am
@@ -0,0 +1,48 @@
+# player - Makefile.am
+
+INCLUDES = $(all_includes)
+
+
+noinst_LTLIBRARIES = libutilx11.la
+
+
+noinst_HEADERS = initDisplay.h \
+ imageDeskX11.h imageDGAFull.h \
+ imageXVDesk.h x11Surface.h xinit.h
+
+libutilx11_la_SOURCES = initDisplay.cpp \
+ imageDeskX11.cpp \
+ imageDGAFull.cpp imageXVDesk.cpp \
+ x11Surface.cpp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/util/render/x11/imageDGAFull.cpp b/mpeglib/lib/util/render/x11/imageDGAFull.cpp
new file mode 100644
index 00000000..6e07b658
--- /dev/null
+++ b/mpeglib/lib/util/render/x11/imageDGAFull.cpp
@@ -0,0 +1,289 @@
+/*
+ xfree 4.0 dga fullscreen mode
+ Copyright (C) 2000 Martin Vogt, Christian Gerlach
+
+ 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 "imageDGAFull.h"
+
+#include <iostream>
+
+using namespace std;
+
+ImageDGAFull::ImageDGAFull() {
+
+ m_iMode = -1;
+ m_bIsActive = false;
+ lSupport=false;
+ m_pxWindow = NULL;
+ m_iImageMode = _IMAGE_NONE;
+ ditherWrapper=NULL;
+ supportedModes = _IMAGE_NONE;
+ setIdentifier("DGA");
+}
+
+
+ImageDGAFull::~ImageDGAFull() {
+ if (ditherWrapper != NULL) {
+ delete ditherWrapper;
+ }
+}
+
+void ImageDGAFull::init(XWindow *xWindow, YUVPicture*)
+{
+ int uid;
+
+ m_pxWindow = xWindow;
+ if (ditherWrapper == NULL) {
+ ditherWrapper=new DitherWrapper(xWindow->depth,
+ xWindow->redMask,
+ xWindow->greenMask,
+ xWindow->blueMask,
+ xWindow->pixel);
+ }
+
+#ifndef X11_DGA2
+ return;
+#endif
+
+#ifdef X11_DGA2
+ m_pDGAModes=NULL;
+ m_iNumberModes = 0;
+
+ m_iVideoWidth = xWindow->width;
+ m_iVideoHeight = xWindow->height;
+ uid=getuid();
+ if (uid != 0) {
+ //cout << "you are :"<<uid<<" and not root(0). DGA 2.0 needs root"<<endl;
+ return;
+ }
+
+ if ((m_pDisplay =xWindow->display)==NULL ) {
+ fprintf( stderr, " cannot connect to X server %s\n", XDisplayName(NULL));
+ return;
+ }
+
+ m_iScreen = DefaultScreen(xWindow->display);
+
+
+ if (!XF86DGAQueryVersion(xWindow->display,
+ &m_iMajorVersion, &m_iMinorVersion)) {
+ fprintf(stderr, "Unable to query video extension version\n");
+ return ;
+ }
+ printf("DGA version %d.%d detected!\n", m_iMajorVersion, m_iMinorVersion);
+
+ // Fail if the extension version in the server is too old
+ if (m_iMajorVersion < DGA_MINMAJOR ||
+ (m_iMajorVersion == DGA_MINMAJOR && m_iMinorVersion < DGA_MINMINOR)) {
+ fprintf(stderr, "Xserver is running an old XFree86-DGA version"
+ " (%d.%d)\n", m_iMajorVersion, m_iMinorVersion);
+ fprintf(stderr, "Minimum required version is %d.%d\n",
+ DGA_MINMAJOR, DGA_MINMINOR);
+ return ;
+ }
+
+ if (!XF86DGAQueryExtension(m_pDisplay, &m_iEventBase, &m_iErrorBase)) {
+ fprintf(stderr, "Unable to query video extension information\n");
+ return ;
+ }
+ printf("Event base %d\n", m_iEventBase);
+ printf("Error base %d\n", m_iErrorBase);
+
+ lSupport=true;
+ supportedModes = _IMAGE_FULL;
+#endif
+}
+
+int ImageDGAFull::support() {
+ return lSupport;
+}
+
+
+int ImageDGAFull::openImage(int mode) {
+#ifdef X11_DGA2
+ int width, bank, ram;
+ m_bAllowZoom = IS_DOUBLE(mode);
+ m_iImageMode = mode;
+
+ /* Open access to the framebuffer */
+ if ( ! XDGAOpenFramebuffer(m_pDisplay,m_iScreen) ) {
+ return(false);
+ }
+
+ findMode(m_pxWindow->width, m_pxWindow->height, m_pxWindow->depth);
+ m_pDevice = XDGASetMode(m_pDisplay, m_iScreen, m_pDGAModes[m_iMode].num);
+
+
+ XDGASelectInput(m_pDisplay, m_iScreen,
+ KeyPressMask | ButtonPressMask | PointerMotionMask);
+
+ XF86DGAGetVideo(m_pDisplay,m_iScreen,&m_pAddr,&width,&bank,&ram);
+
+
+ if(bank < (ram * 1024)) {
+ XF86DGASetVidPage(m_pxWindow->display,
+ DefaultScreen(m_pxWindow->display), 0);
+ }
+
+ XF86DGASetViewPort(m_pxWindow->display,
+ DefaultScreen(m_pxWindow->display),0,0);
+
+
+ printf("Offset:%8x\n",m_iOffsetScreen);
+ m_pStartAddr = m_pAddr + m_iOffsetScreen;
+ m_iOffsetLine = (m_iBytesPerLine - m_iBytesPerRow) / m_iBytesPerPixel;
+ cout << "LineOffset: " << m_iOffsetLine << endl;
+
+ // Clear the screen
+ memset(m_pAddr, 0, m_iBytesPerLine * m_iScreenHeight);
+ /* char *pos = m_pStartAddr;
+ int end = (m_bZoom) ? 2*m_iVideoHeight : m_iVideoHeight;
+ for (int line=0 ; line<end ; line++) {
+ memset(pos, 80, m_iBytesPerRow);
+ pos += m_iBytesPerRow + m_iOffsetLine * m_iBytesPerPixel;
+ }
+ sleep(2);*/
+
+ m_bIsActive = true;
+#endif
+ return true;
+}
+
+
+int ImageDGAFull::closeImage() {
+#ifdef X11_DGA2
+ m_bIsActive = false;
+ stop();
+
+ // delete resources
+ if (m_pDGAModes != NULL) {
+ delete m_pDGAModes;
+ m_pDGAModes=NULL;
+ }
+#endif
+ return true;
+}
+
+
+unsigned char* ImageDGAFull::address() {
+ return (unsigned char*) m_pStartAddr;
+}
+
+
+int ImageDGAFull::offset() {
+ return m_iOffsetLine;
+}
+
+
+void ImageDGAFull::ditherImage(YUVPicture* pic) {
+
+ int useMode = (m_bZoom) ? m_iImageMode : m_iImageMode & (!_IMAGE_DOUBLE);
+
+ ditherWrapper->doDither(pic,m_pxWindow->depth,useMode,
+ address(),offset());
+}
+
+
+void ImageDGAFull::putImage() {
+
+ if (event())
+ closeImage();
+}
+
+
+int ImageDGAFull::findMode(int width, int height, int bpp) {
+#ifdef X11_DGA2
+ int minBorder = INT_MAX;
+ int yBorder=0;
+ int border;
+
+ // TODO: also check the y-axis
+
+ m_iMode = -1;
+ m_iNumberModes = 0;
+ m_pDGAModes = XDGAQueryModes(m_pDisplay, m_iScreen, &m_iNumberModes);
+ printf("Number modes: %d\n", m_iNumberModes);
+
+ for (int count=0 ; count<m_iNumberModes ; count++) {
+
+
+ if (m_pDGAModes[count].depth != bpp)
+ continue;
+
+ printf("Mode: %d %dx%d \t bpp %d\n",
+ count,
+ m_pDGAModes[count].viewportWidth,
+ m_pDGAModes[count].viewportHeight,
+ m_pDGAModes[count].bitsPerPixel);
+
+ // test normal video
+ border = m_pDGAModes[count].viewportWidth - width;
+ if ((border >= 0) && (border < minBorder)) {
+ minBorder = border;
+ m_iMode = count;
+ m_bZoom = false;
+ yBorder = m_pDGAModes[count].viewportHeight - height;
+ }
+
+ // test zoomed video
+ if (m_bAllowZoom) {
+ border = m_pDGAModes[count].viewportWidth - 2 * width;
+ if ((border >= 0) && (border < minBorder)) {
+ minBorder = border;
+ m_iMode = count;
+ m_bZoom = true;
+ yBorder = m_pDGAModes[count].viewportHeight-2*height;
+ }
+ }
+ }
+
+ if (m_iMode != -1) {
+ m_iScreenWidth = m_pDGAModes[m_iMode].viewportWidth;
+ m_iScreenHeight = m_pDGAModes[m_iMode].viewportHeight;
+
+ m_iBytesPerPixel = m_pDGAModes[m_iMode].bitsPerPixel / 8;
+ m_iBytesPerLine = m_pDGAModes[m_iMode].bytesPerScanline;
+ m_iBytesPerRow = width * m_iBytesPerPixel;
+ if (m_bZoom) {
+ m_iBytesPerRow += m_iBytesPerRow;
+ }
+
+ m_iOffsetScreen = minBorder * (m_iBytesPerPixel / 2) +
+ (yBorder / 2) * m_iBytesPerLine;
+ }
+
+ cout << "Best Mode: " << m_iMode << endl;
+ cout << "Border Size: " << minBorder / 2 << endl;
+ cout << "Zoom: " << m_bZoom << endl;
+ cout << "Bytes per Line: " << m_iBytesPerLine << endl;
+ cout << "Bytes per Row: " << m_iBytesPerRow << endl;
+ cout << "Bytes per Pixel:" << m_iBytesPerPixel << endl;
+ cout << "Total offset: " << m_iOffsetScreen << endl;
+#endif
+ return (m_iMode != -1);
+}
+
+
+
+int ImageDGAFull::event() {
+ XEvent event;
+ return XCheckTypedEvent(m_pDisplay, ButtonPress + m_iEventBase, &event);
+}
+
+void ImageDGAFull::stop() {
+#ifdef X11_DGA2
+ m_bIsActive = false;
+ XF86DGADirectVideo(m_pDisplay, m_iScreen, 0);
+
+ XUngrabPointer(m_pDisplay, CurrentTime);
+ XUngrabKeyboard(m_pDisplay, CurrentTime);
+#endif
+}
diff --git a/mpeglib/lib/util/render/x11/imageDGAFull.h b/mpeglib/lib/util/render/x11/imageDGAFull.h
new file mode 100644
index 00000000..ddb8f493
--- /dev/null
+++ b/mpeglib/lib/util/render/x11/imageDGAFull.h
@@ -0,0 +1,131 @@
+/*
+ xfree 4.0 dga fullscreen mode
+ Copyright (C) 2000 Martin Vogt, Christian Gerlach
+
+ 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 __IMAGEDGAFULL_H
+#define __IMAGEDGAFULL_H
+#include "xinit.h"
+
+#include "../imageBase.h"
+
+
+
+#include <stdio.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/types.h>
+
+
+
+
+#define DGA_MINMAJOR 2
+#define DGA_MINMINOR 0
+
+
+
+
+/**
+
+ Displays and renders X11 images in software with the help
+ of the ditherWrapper class. It switches to xfree 4.0 dga 2.0
+ and needs root priviliges for that
+
+*/
+
+
+class ImageDGAFull : public ImageBase {
+
+
+ XWindow* m_pxWindow;
+
+ // DGA status
+ int m_iMajorVersion;
+ int m_iMinorVersion;
+ int m_iEventBase;
+ int m_iErrorBase;
+
+ int m_iScreen;
+
+ Display *m_pDisplay;
+
+ int m_iNumberModes;
+
+#ifdef X11_DGA2
+ XDGAMode *m_pDGAModes;
+ XDGADevice *m_pDevice;
+#endif
+
+ int m_iScreenWidth;
+ int m_iScreenHeight;
+
+ char *m_pAddr; // Base address of the screen
+
+ // DGA parameter
+ int m_iVideoWidth;
+ int m_iVideoHeight;
+
+ int m_iBytesPerLine;
+ int m_iBytesPerRow; // Size of one image line
+ int m_iBytesPerPixel;
+ int m_iOffsetScreen;
+ int m_iOffsetLine;
+ char *m_pStartAddr; // Start address for a centered image
+
+ int m_iImageMode;
+ int m_iMode;
+ bool m_bZoom;
+ bool m_bAllowZoom;
+
+ bool m_bIsActive;
+
+ int lSupport;
+ DitherWrapper* ditherWrapper;
+
+
+ public:
+ ImageDGAFull();
+ ~ImageDGAFull();
+
+ void init(XWindow *xWindow, YUVPicture* pic = NULL);
+
+ int support();
+
+ int openImage(int mode);
+ int closeImage();
+
+ void ditherImage(YUVPicture* pic);
+ void putImage();
+
+ int active() { return m_bIsActive; }
+
+ private:
+
+ // Tries to find a fullscreen-mode which matches the resolution best
+ int findMode(int width, int height, int bpp);
+
+ // Returns TRUE if an event is waiting
+ int event();
+
+ // Returns the start address of the upper left corner of the video frame
+ unsigned char *address();
+
+ // Number of bytes from the end of a row to the beginning of next one
+ int offset();
+
+ // Disables DGA-View (performs a mode-switch if neccesary)
+ void stop();
+
+
+
+};
+
+#endif
diff --git a/mpeglib/lib/util/render/x11/imageDeskX11.cpp b/mpeglib/lib/util/render/x11/imageDeskX11.cpp
new file mode 100644
index 00000000..9607d749
--- /dev/null
+++ b/mpeglib/lib/util/render/x11/imageDeskX11.cpp
@@ -0,0 +1,439 @@
+/*
+ standard and shared mem X11 images
+ 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 "imageDeskX11.h"
+
+#include <iostream>
+
+using namespace std;
+
+static int lXerror;
+
+static int dummy(Display* , XErrorEvent*) {
+ lXerror=true;
+ return true;
+}
+
+
+
+ImageDeskX11::ImageDeskX11() {
+ lSupport=true;
+ supportedModes = _IMAGE_DESK | _IMAGE_DOUBLE | _IMAGE_FULL;
+ setIdentifier("Standard X11");
+ xWindow = NULL;
+ ditherWrapper=NULL;
+#ifdef X11_XVIDMODE
+ iOldMode = -1;
+ vm_modelines = NULL;
+#endif
+}
+
+
+ImageDeskX11::~ImageDeskX11() {
+ destroyImage();
+ if (ditherWrapper != NULL) {
+ delete ditherWrapper;
+ }
+}
+
+
+void ImageDeskX11::init(XWindow* xWindow, YUVPicture*)
+{
+ videoaccesstype=VIDEO_XI_NONE;
+ this->xWindow=xWindow;
+ virtualscreen=NULL;
+ ximage=NULL;
+ imageMode=_IMAGE_NONE;
+ if (ditherWrapper == NULL) {
+ ditherWrapper=new DitherWrapper(xWindow->depth,
+ xWindow->redMask,
+ xWindow->greenMask,
+ xWindow->blueMask,
+ xWindow->pixel);
+ }
+
+#ifdef X11_SHARED_MEM
+ shmseginfo=NULL;
+#endif
+}
+
+int ImageDeskX11::support() {
+ return lSupport;
+}
+
+
+int ImageDeskX11::openImage(int mode) {
+
+ if (xWindow == NULL) {
+ cout << "ImageDeskX11::openImage - call init before open!" << endl;
+ return false;
+ }
+
+ closeImage();
+ imageMode = mode;
+ int err;
+
+ if ((err=createImage(VIDEO_XI_SHMSTD,imageMode)) != ERR_XI_OK) {
+ printf("\nX initialisation error:\n *** %s\n",ERR_XI_STR[err]);
+ printf("check ipcs and delete resources with ipcrm\n");
+ if ((err=createImage(VIDEO_XI_STANDARD,imageMode)) != ERR_XI_OK) {
+ printf("\nX initialisation error:\n *** %s\n",ERR_XI_STR[err]);
+ videoaccesstype=VIDEO_XI_NONE;
+ } else {
+ lSupport=true;
+ }
+ } else {
+ lSupport=true;
+ }
+ switch(videoaccesstype) {
+ case VIDEO_XI_STANDARD:
+ //printf(" # using conventional Xlib calls.\n\n");
+ break;
+ case VIDEO_XI_SHMSTD:
+ //printf(" # Using Xlib shared memory extension %d.%d\n\n",
+ //XShmMajor,XShmMinor);
+ break;
+ default:
+ cout << "could not create image->no video output possible"<<endl;
+
+ }
+
+ iOffsetX = iOffsetY = 0;
+ int w = xWindow->width;
+ int h = xWindow->height;
+ if (IS_FULL(imageMode)) {
+ switchMode(xWindow->width, xWindow->height, IS_DOUBLE(imageMode));
+ iOffsetX = (iWidth - w) / 2;
+ iOffsetY = (iHeight - h) / 2;
+ if (bZoom) {
+ iOffsetX -= w / 2;
+ iOffsetY -= h / 2;
+ }
+ XResizeWindow(xWindow->display, xWindow->window, iWidth, iHeight);
+ } else if (IS_DOUBLE(imageMode)) {
+ XResizeWindow(xWindow->display, xWindow->window,
+ xWindow->width * 2, xWindow->height * 2);
+ }
+
+ if (lSupport==true) {
+ return true;
+ }
+ return false;
+}
+
+
+int ImageDeskX11::closeImage() {
+ destroyImage();
+
+#ifdef X11_XVIDMODE
+ if (iOldMode != -1) {
+ cout << "switch back to original videomode" << endl;
+ XF86VidModeSwitchToMode(xWindow->display,XDefaultScreen(xWindow->display),
+ vm_modelines[iOldMode]);
+ XFlush(xWindow->display);
+ iOldMode=-1;
+ }
+#endif
+
+ return true;
+}
+
+
+void ImageDeskX11::ditherImage(YUVPicture* pic) {
+ if (xWindow == NULL) {
+ cout << "ImageDeskX11::ditherImage - you have to call init first!" << endl;
+ return;
+ }
+
+ ditherWrapper->doDither(pic,xWindow->depth,imageMode,
+ virtualscreen,0);
+}
+
+
+void ImageDeskX11::putImage(){
+ if (xWindow == NULL) {
+ cout << "ImageDeskX11::putImage - you have to call init first!" << endl;
+ return;
+ }
+
+
+ int height=xWindow->height;
+ int width=xWindow->width;
+
+ if (imageMode & _IMAGE_DOUBLE) {
+ height=2*height;
+ width=2*width;
+ }
+
+#ifdef X11_SHARED_MEM
+ switch(videoaccesstype) {
+ case VIDEO_XI_SHMSTD:
+ XShmPutImage(xWindow->display,xWindow->window,
+ xWindow->gc,ximage,
+ 0, 0, iOffsetX, iOffsetY, width, height, False);
+ XSync(xWindow->display,false); /* true not needed, done by XPending */
+ break;
+
+
+ case VIDEO_XI_STANDARD:
+#endif
+ XPutImage(xWindow->display,xWindow->window,
+ xWindow->gc, ximage,
+ 0, 0, iOffsetX, iOffsetY, width, height);
+ XSync(xWindow->display,false); /* true not needed, done by XPending */
+#ifdef X11_SHARED_MEM
+ break;
+ }
+#endif
+}
+
+
+
+int ImageDeskX11::createImage(int createType,int mode) {
+
+ if (xWindow == NULL) {
+ cout << "ImageDeskX11::createImage - you have to call init first!" << endl;
+ return false;
+ }
+
+ videoaccesstype=VIDEO_XI_NONE;
+
+#ifdef X11_SHARED_MEM
+ if(XShmQueryVersion(xWindow->display,&XShmMajor,&XShmMinor,&XShmPixmaps)) {
+ if (XShmPixmaps==True) {
+ if (createType & VIDEO_XI_SHMSTD) {
+ videoaccesstype=VIDEO_XI_SHMSTD;
+ }
+ }
+ } else {
+ if (createType & VIDEO_XI_SHMSTD) {
+ return ERR_XI_NOSHAREDMEMORY;
+ }
+ }
+#endif
+ if (videoaccesstype == VIDEO_XI_NONE) {
+ videoaccesstype=createType;
+ }
+
+ switch(videoaccesstype)
+ {
+#ifdef X11_SHARED_MEM
+
+
+ case VIDEO_XI_SHMSTD:
+
+ lXerror=false;
+ XSetErrorHandler(dummy);
+
+ shmseginfo=(XShmSegmentInfo *)malloc(sizeof(XShmSegmentInfo));
+ if(!shmseginfo)
+ return ERR_XI_SHMALLOC;
+
+ memset(shmseginfo,0, sizeof(XShmSegmentInfo));
+
+ if (imageMode & _IMAGE_DOUBLE) {
+ ximage=XShmCreateImage(xWindow->display,xWindow->visual,
+ xWindow->depth,
+ ZPixmap,NULL,shmseginfo,2*xWindow->width,
+ 2*xWindow->height);
+ } else {
+ ximage=XShmCreateImage(xWindow->display,xWindow->visual,
+ xWindow->depth,
+ ZPixmap,NULL,shmseginfo,xWindow->width,
+ xWindow->height);
+ }
+
+ if(!ximage)
+ return ERR_XI_SHMXIMAGE;
+
+ shmseginfo->shmid=shmget(IPC_PRIVATE,
+ ximage->bytes_per_line*
+ ximage->height,IPC_CREAT|0777);
+
+ if(shmseginfo->shmid<0)
+ return ERR_XI_SHMSEGINFO;
+
+ shmseginfo->shmaddr=(char*)shmat(shmseginfo->shmid,NULL,0);
+ ximage->data=shmseginfo->shmaddr;
+ virtualscreen=(unsigned char *)ximage->data;
+
+ if(!virtualscreen)
+ return ERR_XI_SHMVIRTALLOC;
+
+ shmseginfo->readOnly=False;
+
+ XShmAttach(xWindow->display,shmseginfo);
+ XSync(xWindow->display, False);
+ XSetErrorHandler(NULL);
+ XFlush(xWindow->display);
+ if (lXerror) {
+ cout << "ERR_XI_SHMATTACH -2"<<endl;
+ return ERR_XI_SHMATTACH;
+ }
+
+ break;
+#endif
+
+ case VIDEO_XI_STANDARD:
+ if (mode & _IMAGE_DOUBLE) {
+ virtualscreen=(unsigned char *)
+ malloc(xWindow->screensize*sizeof(char)*4);
+
+ if(virtualscreen==NULL)
+ return ERR_XI_VIRTALLOC;
+
+ ximage=XCreateImage(xWindow->display,xWindow->visual,
+ xWindow->depth,ZPixmap,
+ 0,(char*)virtualscreen,
+ 2*xWindow->width,2*xWindow->height,
+ 32,2*xWindow->width*xWindow->pixelsize);
+ } else {
+ virtualscreen=(unsigned char *)
+ malloc(xWindow->screensize*sizeof(char));
+
+ if(virtualscreen==NULL)
+ return ERR_XI_VIRTALLOC;
+
+ ximage=XCreateImage(xWindow->display,xWindow->visual,
+ xWindow->depth,ZPixmap,
+ 0,(char*)virtualscreen,
+ xWindow->width,xWindow->height,
+ 32,xWindow->width*xWindow->pixelsize);
+ }
+
+ if(!ximage)
+ return ERR_XI_XIMAGE;
+ break;
+
+ default:
+ return ERR_XI_FAILURE;
+
+ }
+
+ if ( (videoaccesstype == VIDEO_XI_STANDARD) ||
+ (videoaccesstype == VIDEO_XI_SHMSTD) ) {
+#ifndef WORDS_BIGENDIAN
+ ximage->byte_order = LSBFirst;
+ ximage->bitmap_bit_order = LSBFirst;
+#else
+ ximage->byte_order = MSBFirst;
+ ximage->bitmap_bit_order = MSBFirst;
+#endif
+
+ }
+ return ERR_XI_OK;
+}
+
+
+
+int ImageDeskX11::destroyImage() {
+ if(xWindow && xWindow->display && xWindow->window) {
+ switch(videoaccesstype) {
+#ifdef X11_SHARED_MEM
+ case VIDEO_XI_SHMSTD:
+ if (shmseginfo) {
+ XShmDetach(xWindow->display,shmseginfo);
+ if(ximage) {
+ XDestroyImage(ximage);
+ ximage=NULL;
+ }
+ if(shmseginfo->shmaddr) {
+ shmdt(shmseginfo->shmaddr);
+ shmseginfo->shmaddr=NULL;
+ }
+ if(shmseginfo->shmid>=0)
+ shmctl(shmseginfo->shmid,IPC_RMID,NULL);
+
+ free(shmseginfo);
+ }
+ shmseginfo=NULL;
+ break;
+
+#endif
+ case VIDEO_XI_STANDARD:
+ if(ximage) {
+ XDestroyImage(ximage);
+ ximage=NULL;
+ /*
+ XDestroyImage function calls frees both the image structure
+ and the data pointed to by the image structure.
+ */
+ virtualscreen=NULL;
+ }
+ break;
+
+ default:
+ // cout << "no open window to close"<<endl;
+ break;
+ }
+ }
+ videoaccesstype=VIDEO_XI_NONE;
+ imageMode=_IMAGE_NONE;
+ return true;
+}
+
+
+bool ImageDeskX11::switchMode(int width, int , bool zoom)
+{
+ iWidth = xWindow->screenptr->width;
+ iHeight = xWindow->screenptr->height;
+
+#ifdef X11_XVIDMODE
+ iOldMode = -1;
+ int vm_count,i;
+
+ cout << "Find best matching videomode ..." << endl;
+
+ if (!XF86VidModeGetAllModeLines(xWindow->display,XDefaultScreen(xWindow->display),
+ &vm_count,&vm_modelines)) {
+ return false;
+ }
+
+ int bestMode = -1;
+ int border, minBorder = INT_MAX;
+
+ for (i = 0; i < vm_count; i++) {
+ printf("mode %d: %dx%d\n",i, vm_modelines[i]->hdisplay,vm_modelines[i]->vdisplay);
+
+ if (xWindow->screenptr->width == vm_modelines[i]->hdisplay)
+ iOldMode = i;
+
+ border = vm_modelines[i]->hdisplay - width;
+ if ((border > 0) && (border < minBorder)) {
+ bestMode = i;
+ minBorder = border;
+ bZoom = false;
+ }
+ if (zoom) {
+ border = vm_modelines[i]->hdisplay - 2 * width;
+ if ((border > 0) && (border < minBorder)) {
+ bestMode = i;
+ minBorder = border;
+ bZoom = true;
+ }
+ }
+ }
+ cout << "best mode: " << bestMode << endl;
+
+ iWidth = vm_modelines[bestMode]->hdisplay;
+ iHeight = vm_modelines[bestMode]->vdisplay;
+
+ if (XF86VidModeSwitchToMode(xWindow->display,XDefaultScreen(xWindow->display),
+ vm_modelines[bestMode])) {
+ XF86VidModeSetViewPort(xWindow->display,XDefaultScreen(xWindow->display), 0, 0);
+ XFlush(xWindow->display);
+ return true;
+ }
+#endif
+ return false;
+}
diff --git a/mpeglib/lib/util/render/x11/imageDeskX11.h b/mpeglib/lib/util/render/x11/imageDeskX11.h
new file mode 100644
index 00000000..efbd4e90
--- /dev/null
+++ b/mpeglib/lib/util/render/x11/imageDeskX11.h
@@ -0,0 +1,85 @@
+/*
+ standard and shared mem X11 images
+ 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 __IMAGEDESKX11_H
+#define __IMAGEDESKX11_H
+#include <limits.h>
+#include "xinit.h"
+
+#include "../imageBase.h"
+
+#define VIDEO_XI_NONE 0x00 /* No access defined */
+#define VIDEO_XI_STANDARD 0x01 /* Use standard Xlib calls */
+#define VIDEO_XI_SHMSTD 0X02 /* Use Xlib shared memory extension */
+
+/**
+
+ Displays and renders X11 images in software with the help
+ of the ditherWrapper class.
+*/
+
+
+class ImageDeskX11 : public ImageBase {
+
+#ifdef X11_SHARED_MEM
+ XShmSegmentInfo *shmseginfo;
+#endif
+
+ unsigned char *virtualscreen;
+ int videoaccesstype;
+ XImage *ximage;
+ int lSupport;
+
+ int XShmMajor,XShmMinor;
+ Bool XShmPixmaps;
+
+ XWindow* xWindow;
+ int imageMode;
+ DitherWrapper* ditherWrapper;
+
+ int iOffsetX;
+ int iOffsetY;
+ int iWidth;
+ int iHeight;
+
+#ifdef X11_XVIDMODE
+ XF86VidModeModeInfo **vm_modelines;
+
+ int iOldMode;
+#endif
+
+ bool bZoom;
+
+ public:
+ ImageDeskX11();
+ ~ImageDeskX11();
+
+ void init(XWindow* xWindow, YUVPicture* pic = NULL);
+
+ int support();
+
+ int openImage(int ditherSize);
+ int closeImage();
+
+ void ditherImage(YUVPicture* pic);
+ void putImage();
+
+ private:
+ int createImage(int createType,int size);
+ int destroyImage();
+
+ bool switchMode(int width, int height, bool zoom);
+
+};
+
+#endif
diff --git a/mpeglib/lib/util/render/x11/imageXVDesk.cpp b/mpeglib/lib/util/render/x11/imageXVDesk.cpp
new file mode 100644
index 00000000..e087ba40
--- /dev/null
+++ b/mpeglib/lib/util/render/x11/imageXVDesk.cpp
@@ -0,0 +1,405 @@
+/*
+ xfree 4.0 XV extension desk mode
+ 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 "imageXVDesk.h"
+
+#include <iostream>
+
+using namespace std;
+
+ImageXVDesk::ImageXVDesk() {
+
+ lSupport=false;
+
+ ditherWrapper=NULL;
+ supportedModes = _IMAGE_NONE;
+ setIdentifier("XV");
+
+ xWindow = NULL;
+
+#ifdef X11_XV
+ keepRatio = false;
+
+#endif
+}
+
+
+ImageXVDesk::~ImageXVDesk() {
+ if (ditherWrapper != NULL) {
+ delete ditherWrapper;
+ }
+ freeImage();
+}
+
+void ImageXVDesk::init(XWindow* xWindow, YUVPicture*)
+{
+#ifdef X11_XV
+ this->xWindow=xWindow;
+
+ xv_port=-1;
+ shmem_flag = 0;
+ yuv_image=NULL;
+ yuv_shminfo.shmaddr=NULL;
+ yuv_shminfo.shmid=-1;
+
+ if (XShmQueryExtension(xWindow->display)) shmem_flag = 1;
+ if (!shmem_flag) {
+ printf("no shmem available.\n");
+ return;
+ }
+
+
+ if (haveXVSupport(xWindow)==true) {
+ supportedModes = _IMAGE_DESK | _IMAGE_DOUBLE | _IMAGE_FULL | _IMAGE_RESIZE;
+ lSupport=true;
+ } else {
+ return;
+ }
+
+ if (ditherWrapper == NULL) {
+ ditherWrapper=new Dither2YUV();
+ }
+ imageID = -1;
+#endif
+}
+
+int ImageXVDesk::support() {
+ return lSupport;
+}
+
+int ImageXVDesk::openImage(int imageMode) {
+
+
+ if (imageMode & _IMAGE_FULL) {
+ XResizeWindow(xWindow->display, xWindow->window,
+ xWindow->screenptr->width, xWindow->screenptr->height);
+ setKeepRatio(true);
+ } else if (imageMode & _IMAGE_DOUBLE) {
+ XResizeWindow(xWindow->display, xWindow->window,
+ xWindow->width * 2, xWindow->height * 2);
+ setKeepRatio(false);
+ } else {
+ setKeepRatio(false);
+ }
+
+ return true;
+}
+
+
+int ImageXVDesk::closeImage() {
+ freeImage();
+ return true;
+}
+
+void ImageXVDesk::ditherImage(YUVPicture* pic) {
+
+#ifdef X11_XV
+ int x_return;
+ int y_return;
+ int height, dy;
+ unsigned int border_width_return;
+ unsigned int depth_return;
+ unsigned int _w;
+ unsigned int _h;
+ Window _dw;
+
+ if (xWindow == NULL) {
+ cout << "ImageXVDesk::ditherImage - you have to call before dithering an image!" << endl;
+ return;
+ }
+
+ // check for not supported formats and if possible convert them
+ int inputType=pic->getImageType();
+ if (inputType == PICTURE_RGB_FLIPPED) {
+ cout << "xv for flipped rgb not implemented"<<endl;
+ return;
+ }
+
+ // create xv image
+ int id;
+ if (imageID != pic->getImageType()) {
+ imageID = pic->getImageType();
+ switch (imageID) {
+ case PICTURE_YUVMODE_CR_CB:
+ case PICTURE_YUVMODE_CB_CR:
+ case PICTURE_RGB:
+ id = GUID_YUV12_PLANAR;
+ break;
+ case PICTURE_YUVMODE_YUY2:
+ id = GUID_YUY2_PACKED;
+ break;
+ case PICTURE_YUVMODE_UYVY:
+ id = GUID_UYVY_PACKED;
+ break;
+ default:
+ cout << "unknown type for yuv image!" << endl;
+ return;
+ }
+ freeImage();
+
+ createImage(id);
+ }
+
+ XGetGeometry(xWindow->display,(Drawable)xWindow->window,
+ &_dw, &x_return, &y_return, &_w, &_h,
+ &border_width_return, &depth_return);
+
+ // now dither the image
+
+ // we (currently) cannot create yuvPicture _in_
+ // the shared segment here we copy it
+
+ unsigned char* image=pic->getImagePtr();
+ if (inputType == PICTURE_RGB) {
+ ditherWrapper->doDither(pic,
+ DefaultDepth(xWindow->display,xWindow->screennum),
+ _SIZE_NORMAL, (unsigned char*) yuv_image->data, 0);
+ } else {
+ memcpy(yuv_image->data,image,pic->getImageSize());
+ }
+
+ if (keepRatio) {
+ height = (_w * yuv_image->height) / yuv_image->width;
+ dy = (((int) _h) - height + 1) / 2;
+ XvShmPutImage(xWindow->display, xv_port,xWindow->window,
+ xWindow->gc, yuv_image,
+ 0, 0, yuv_image->width, yuv_image->height,
+ 0, dy, _w, height, False);
+ if (dy > 0) {
+ XFillRectangle(xWindow->display, xWindow->window,xWindow->gc,
+ 0, 0, _w, dy);
+ XFillRectangle(xWindow->display, xWindow->window,xWindow->gc,
+ 0, height+dy-1, _w, dy+1);
+ }
+ } else {
+ XvShmPutImage(xWindow->display, xv_port,xWindow->window,
+ xWindow->gc, yuv_image,
+ 0, 0, yuv_image->width, yuv_image->height,
+ 0, 0, _w, _h, False);
+ }
+#endif
+}
+
+
+void ImageXVDesk::putImage() {
+
+ //XFlush(xWindow->display);
+ XSync(xWindow->display, false);
+}
+
+void ImageXVDesk::setKeepRatio(bool enable)
+{
+#ifdef X11_XV
+ keepRatio = enable;
+#endif
+}
+
+
+int ImageXVDesk::haveXVSupport(XWindow* xWindow) {
+#ifdef X11_XV
+ int ret;
+ unsigned int p_version=0;
+ unsigned int p_release=0;
+ unsigned int p_request_base=0;
+ unsigned int p_event_base=0;
+ unsigned int p_error_base=0;
+
+ unsigned int p_num_adaptors=0;
+
+ /**------------------------------- XV ------------------------------------*/
+
+ /** query and print Xvideo properties */
+
+ ret = XvQueryExtension(xWindow->display,
+ &p_version, &p_release, &p_request_base,
+ &p_event_base, &p_error_base);
+ if (ret != Success) {
+ if (ret == XvBadExtension) {
+ printf("XvBadExtension returned at XvQueryExtension.\n");
+ } else if (ret == XvBadAlloc) {
+ printf("XvBadAlloc returned at XvQueryExtension.\n");
+ } else {
+ printf("other error happened at XvQueryExtension.\n");
+ }
+ return false;
+ }
+ /*
+ printf("========================================\n");
+ printf("XvQueryExtension returned the following:\n");
+ printf("p_version : %u\n", p_version);
+ printf("p_release : %u\n", p_release);
+ printf("p_request_base : %u\n", p_request_base);
+ printf("p_event_base : %u\n", p_event_base);
+ printf("p_error_base : %u\n", p_error_base);
+ printf("========================================\n");
+ */
+
+ ret = XvQueryAdaptors(xWindow->display, DefaultRootWindow(xWindow->display),
+ &p_num_adaptors, &ai);
+
+ if (ret != Success) {
+ if (ret == XvBadExtension) {
+ printf("XvBadExtension returned at XvQueryExtension.\n");
+ } else if (ret == XvBadAlloc) {
+ printf("XvBadAlloc returned at XvQueryExtension.\n");
+ } else {
+ printf("other error happaned at XvQueryAdaptors.\n");
+ }
+ return false;
+ }
+ /*
+ printf("=======================================\n");
+ printf("XvQueryAdaptors returned the following:\n");
+ printf("%d adaptors available.\n", p_num_adaptors);
+ */
+ if (p_num_adaptors == 0) {
+ //cout << "no adaptors found. XV not possible"<<endl;
+ return false;
+ }
+
+ unsigned int i;
+ unsigned int j;
+
+ for (i = 0; i < p_num_adaptors; i++) {
+ /*
+ printf(" name: %s\n"
+ " type: %s%s%s%s%s\n"
+ " ports: %ld\n"
+ " first port: %ld\n",
+ ai[i].name,
+ (ai[i].type & XvInputMask) ? "input | " : "",
+ (ai[i].type & XvOutputMask) ? "output | " : "",
+ (ai[i].type & XvVideoMask) ? "video | " : "",
+ (ai[i].type & XvStillMask) ? "still | " : "",
+ (ai[i].type & XvImageMask) ? "image | " : "",
+ ai[i].num_ports,
+ ai[i].base_id);
+ */
+ xv_port = ai[i].base_id;
+
+ //printf("adaptor %d ; format list:\n", i);
+ for (j = 0; j < ai[i].num_formats; j++) {
+ /*
+ printf(" depth=%d, visual=%ld\n",
+ ai[i].formats[j].depth,
+ ai[i].formats[j].visual_id);
+ */
+ }
+ unsigned int p;
+ unsigned int encodings;
+ int attributes;
+ int formats;
+
+ for (p = ai[i].base_id; p < ai[i].base_id+ai[i].num_ports; p++) {
+
+ //printf(" encoding list for port %d\n", p);
+ if (XvQueryEncodings(xWindow->display, p, &encodings, &ei) != Success) {
+ //printf("XvQueryEncodings failed.\n");
+ continue;
+ }
+ for (j = 0; j < encodings; j++) {
+ /*
+ printf(" id=%ld, name=%s, size=%ldx%ld, numerator=%d, denominator=%d\n",
+ ei[j].encoding_id, ei[j].name, ei[j].width, ei[j].height,
+ ei[j].rate.numerator, ei[j].rate.denominator);
+ */
+ }
+ XvFreeEncodingInfo(ei);
+ int k;
+ //printf(" attribute list for port %d\n", p);
+ at = XvQueryPortAttributes(xWindow->display, p, &attributes);
+ for (k = 0; k < attributes; k++) {
+ /*
+ printf(" name: %s\n"
+ " flags: %s%s\n"
+ " min_color: %i\n"
+ " max_color: %i\n",
+ at[k].name,
+ (at[k].flags & XvGettable) ? " get" : "",
+ (at[k].flags & XvSettable) ? " set" : "",
+ at[k].min_value, at[k].max_value);
+ */
+ }
+ if (at)
+ XFree(at);
+
+ //printf(" image format list for port %d\n", p);
+ fo = XvListImageFormats(xWindow->display, p, &formats);
+ for (k = 0; k < formats; k++) {
+ /*
+ printf(" 0x%x (%4.4s) %s\n",
+ fo[k].id,
+ (char *)&fo[k].id,
+ (fo[k].format == XvPacked) ? "packed" : "planar");
+ */
+ }
+ if (fo)
+ XFree(fo);
+ }
+ printf("\n");
+ }
+ if (p_num_adaptors > 0)
+ XvFreeAdaptorInfo(ai);
+ if (xv_port == -1) {
+ return false;
+ }
+#endif
+ return true;
+
+}
+
+
+void ImageXVDesk::freeImage() {
+#ifdef X11_XV
+ if (xWindow == NULL) {
+ return;
+ }
+ if (yuv_shminfo.shmid >=0) {
+ XShmDetach(xWindow->display,&yuv_shminfo);
+ if(yuv_shminfo.shmaddr) {
+ shmdt(yuv_shminfo.shmaddr);
+ XFree(yuv_image);
+ yuv_shminfo.shmaddr=NULL;
+ }
+ XSync(xWindow->display, False);
+ yuv_shminfo.shmid=-1;
+ }
+#endif
+}
+
+
+void ImageXVDesk::createImage(int id) {
+#ifdef X11_XV
+ if (xWindow == NULL) {
+ cout << "ImageXVDesk::freeImage - you have to call init before creating an image!" << endl;
+ return;
+ }
+
+ yuv_image = XvShmCreateImage(xWindow->display, xv_port,
+ id, 0,
+ xWindow->width,
+ xWindow->height, &yuv_shminfo);
+
+ yuv_shminfo.shmid = shmget(IPC_PRIVATE,
+ yuv_image->data_size, IPC_CREAT | 0777);
+ yuv_shminfo.shmaddr = yuv_image->data =
+ (char*)shmat(yuv_shminfo.shmid, 0, 0);
+ yuv_shminfo.readOnly = False;
+
+ if (!XShmAttach(xWindow->display, &yuv_shminfo)) {
+ printf("XShmAttach failed !\n");
+ lSupport=false;
+ return;
+ }
+ shmctl(yuv_shminfo.shmid, IPC_RMID, 0);
+#endif
+}
diff --git a/mpeglib/lib/util/render/x11/imageXVDesk.h b/mpeglib/lib/util/render/x11/imageXVDesk.h
new file mode 100644
index 00000000..44124428
--- /dev/null
+++ b/mpeglib/lib/util/render/x11/imageXVDesk.h
@@ -0,0 +1,88 @@
+/*
+ xfree 4.0 XV extension desk mode
+ 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 __IMAGEXVDESK_H
+#define __IMAGEXVDESK_H
+
+#include "xinit.h"
+
+#include "../imageBase.h"
+#include "../dither2YUV/dither2YUV.h"
+
+#include <stdio.h>
+
+#if !defined(__NetBSD__)
+#include <semaphore.h>
+#endif
+
+//#undef X11_XV
+
+#define GUID_YUV12_PLANAR 0x32315659
+#define GUID_I420_PLANAR 0x30323449
+#define GUID_YUY2_PACKED 0x32595559
+#define GUID_UYVY_PACKED 0x59565955
+
+/**
+ The XV extension dither yuv images in hardware and allows
+ scaling of images.
+ But its currently not supported by many drivers.
+
+*/
+
+
+class ImageXVDesk : public ImageBase {
+
+#ifdef X11_XV
+ XvAdaptorInfo *ai;
+ XvEncodingInfo *ei;
+ XvAttribute *at;
+ XvImageFormatValues *fo;
+
+ XvImage *yuv_image;
+ bool keepRatio;
+
+ int xv_port;
+ int imageID;
+
+ int shmem_flag;
+ XShmSegmentInfo yuv_shminfo;
+#endif
+ Dither2YUV* ditherWrapper;
+
+ int lSupport;
+ XWindow* xWindow;
+
+ public:
+ ImageXVDesk();
+ ~ImageXVDesk();
+
+ void init(XWindow* xWindow, YUVPicture* pic = NULL);
+
+ int support();
+
+ int openImage(int imageMode);
+ int closeImage();
+
+ void ditherImage(YUVPicture* pic);
+ void putImage();
+
+ void setKeepRatio(bool enable);
+
+ private:
+ int haveXVSupport(XWindow* xWindow);
+ void freeImage();
+ void createImage(int id);
+
+};
+
+#endif
diff --git a/mpeglib/lib/util/render/x11/initDisplay.cpp b/mpeglib/lib/util/render/x11/initDisplay.cpp
new file mode 100644
index 00000000..d0029eb6
--- /dev/null
+++ b/mpeglib/lib/util/render/x11/initDisplay.cpp
@@ -0,0 +1,255 @@
+/*
+ here are the different initialisation routines for different displays
+ 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 "initDisplay.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+
+static unsigned long wpixel[256];
+
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * InitColorDisplay --
+ *
+ * Initialized display for full color output.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void initColorDisplay(XWindow* xwindow) {
+ XWindowAttributes winattr;
+
+
+ XGetWindowAttributes(xwindow->display, xwindow->window, &winattr);
+
+ xwindow->redMask = winattr.visual->red_mask;
+ xwindow->greenMask = winattr.visual->green_mask;
+ xwindow->blueMask = winattr.visual->blue_mask;
+}
+
+
+
+
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * FindFullColorVisual
+ *
+ * Returns a pointer to a full color bit visual on the display
+ *
+ * Results:
+ * See above.
+ *
+ * Side effects:
+ * Unknown.
+ *
+ *--------------------------------------------------------------
+ */
+Visual* FindFullColorVisual (Display* dpy,int* depth) {
+ XVisualInfo vinfo;
+ XVisualInfo *vinfo_ret;
+ int numitems, maxdepth;
+
+#if defined(__cplusplus) || defined(c_plusplus)
+ vinfo.c_class = TrueColor;
+#else
+ vinfo.class = TrueColor;
+#endif
+
+ vinfo_ret = XGetVisualInfo(dpy, VisualClassMask, &vinfo, &numitems);
+
+ if (numitems == 0) return NULL;
+
+ maxdepth = 0;
+ while(numitems > 0) {
+ if (vinfo_ret[numitems-1].depth > maxdepth) {
+ maxdepth = vinfo_ret[numitems-1 ].depth;
+ }
+ numitems--;
+ }
+ XFree((void *) vinfo_ret);
+
+ if (maxdepth < 16) return NULL;
+
+ if (XMatchVisualInfo(dpy, DefaultScreen(dpy), maxdepth,
+ TrueColor, &vinfo)) {
+ *depth = maxdepth;
+ return vinfo.visual;
+ }
+
+ return NULL;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CreateFullColorWindow
+ *
+ * Creates a window capable of handling 32 bit color.
+ *
+ * Results:
+ * See above.
+ *
+ * Side effects:
+ * Unknown.
+ *
+ *--------------------------------------------------------------
+ */
+void CreateFullColorWindow (XWindow* xwindow) {
+ int depth;
+ Visual *visual;
+ XSetWindowAttributes xswa;
+ unsigned long mask;
+ unsigned int c_class;
+ int screen;
+ Display *dpy=xwindow->display;
+ /*
+ int x = xinfo->hints.x,
+ y = xinfo->hints.y;
+ unsigned int w = xinfo->hints.width,
+ h = xinfo->hints.height;
+ */
+ screen = XDefaultScreen(dpy);
+ c_class = InputOutput; /* Could be InputOnly */
+ if (xwindow->visual == NULL) {
+ xwindow->visual = visual = FindFullColorVisual (dpy, &depth);
+ xwindow->depth = depth;
+ } else {
+ visual=xwindow->visual;
+ depth=xwindow->depth;
+ }
+
+ if (visual == NULL) {
+ cout << "visual is null"<<endl;
+ return;
+ }
+ mask = CWBackPixel | CWColormap | CWBorderPixel;
+ if (xwindow->colormap==0) {
+ xswa.colormap = XCreateColormap(dpy,
+ XRootWindow(dpy, screen),
+ visual, AllocNone);
+ } else xswa.colormap = xwindow->colormap;
+ xswa.background_pixel = BlackPixel(dpy, DefaultScreen(dpy));
+ xswa.border_pixel = WhitePixel(dpy, DefaultScreen(dpy));
+ XSetWindowColormap(xwindow->display,xwindow->window,xwindow->colormap);
+
+
+ /*
+ xwindow->window = XCreateWindow(dpy, RootWindow(dpy, screen), x, y, w, h,
+ (unsigned int) 1, depth, c_class,
+ visual, mask, &xswa);
+ */
+}
+
+
+
+
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * InitSimpleDisplay --
+ *
+ * Initialized display, sets up colormap, etc. Use for 8 Bit color
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void initSimpleDisplay(XWindow* xwindow) {
+ int ncolors = LUM_RANGE*CB_RANGE*CR_RANGE;
+ XColor xcolor;
+ int i, lum_num, cr_num, cb_num;
+ unsigned char r, g, b;
+ Colormap dcmap;
+ Display *display;
+ ColorTable8Bit colorTable8Bit;
+
+ display = xwindow->display;
+
+
+ xwindow->colormap = XDefaultColormap(display, DefaultScreen(display));
+ dcmap = xwindow->colormap;
+
+ xcolor.flags = DoRed | DoGreen | DoBlue;
+
+
+ //if (xinfo->owncmFlag) goto create_map;
+
+retry_alloc_colors:
+ for (i=0; i<ncolors; i++) {
+
+ lum_num = (i / (CR_RANGE*CB_RANGE))%LUM_RANGE;
+ cr_num = (i / CB_RANGE)%CR_RANGE;
+ cb_num = i % CB_RANGE;
+
+ colorTable8Bit.ConvertColor(lum_num, cr_num, cb_num, &r, &g, &b);
+
+ xcolor.red = r * 256;
+ xcolor.green = g * 256;
+ xcolor.blue = b * 256;
+
+ if ((XAllocColor(display,xwindow->colormap , &xcolor) == 0
+ && xwindow->colormap == dcmap)) {
+ int j;
+ unsigned long tmp_pixel;
+ XWindowAttributes xwa;
+
+ // Free colors.
+ for (j = 0; j < i; j ++) {
+ tmp_pixel = wpixel[j];
+ XFreeColors(display,xwindow->colormap , &tmp_pixel, 1, 0);
+ }
+
+
+ //create_map:
+ XGetWindowAttributes(display, xwindow->window, &xwa);
+ xwindow->colormap = XCreateColormap(display, xwindow->window,
+ xwa.visual, AllocNone);
+ XSetWindowColormap(display, xwindow->window,xwindow->colormap );
+
+ goto retry_alloc_colors;
+ }
+ xwindow->pixel[i]=xcolor.pixel;
+ wpixel[i] = xcolor.pixel;
+ }
+
+}
+
+
diff --git a/mpeglib/lib/util/render/x11/initDisplay.h b/mpeglib/lib/util/render/x11/initDisplay.h
new file mode 100644
index 00000000..62841f19
--- /dev/null
+++ b/mpeglib/lib/util/render/x11/initDisplay.h
@@ -0,0 +1,34 @@
+/*
+ here are the different initialisation routines for different displays
+ 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 __INITDISPLAY_H
+#define __INITDISPLAY_H
+
+#include "math.h"
+#include "xinit.h"
+#include "../dither/colorTable8Bit.h"
+
+
+
+extern void initColorDisplay(XWindow* xwindow);
+extern void initSimpleDisplay(XWindow* xwindow);
+
+// helper functions
+Visual *FindFullColorVisual (Display *dpy ,int *depth);
+void CreateFullColorWindow (XWindow* xwindow);
+
+
+
+#endif
diff --git a/mpeglib/lib/util/render/x11/x11Surface.cpp b/mpeglib/lib/util/render/x11/x11Surface.cpp
new file mode 100644
index 00000000..d7b8f052
--- /dev/null
+++ b/mpeglib/lib/util/render/x11/x11Surface.cpp
@@ -0,0 +1,389 @@
+/*
+ surface wrapper for X11 Window
+ 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 "x11Surface.h"
+
+#include <iostream>
+
+using namespace std;
+
+const char *ERR_XI_STR[] = {
+ "X initialisation OK!",
+ "No Shared Memory available",
+ "cannot open Display",
+ "bad color depth",
+ "can't create Window",
+ "can't alloc memory for virtual screen",
+ "cannot create XImage",
+ "can't alloc memory for Shared memory segment info",
+ "cannot create Shared Memory XImage",
+ "Shared memory segment info error",
+ "Shared memory virtual screen allocation failed",
+ "cannot attach Shared Memory segment to display"
+};
+
+
+#ifndef KDE_USE_FINAL
+static int dummy(Display* , XErrorEvent*) {
+ cout << "received x11 error!"<<endl;
+ return true;
+}
+#endif
+
+X11Surface::X11Surface() {
+ xWindow=(XWindow *)malloc(sizeof(XWindow));
+ xWindow->lOpen=false;
+ xWindow->x = xWindow->y = 0;
+ xWindow->window = 0;
+ m_windowIdAvailable = false;
+
+ imageMode=_IMAGE_NONE;
+
+ imageCurrent=NULL;
+ xWindow->lOpen=false;
+
+
+ xWindow->display=XOpenDisplay(NULL);
+ if (xWindow->display)
+ XFlush(xWindow->display);
+ xWindow->redMask=0;
+ xWindow->greenMask=0;
+ xWindow->blueMask=0;
+ lXVAllow=true;
+
+ images=0;
+ imageList = new ImageBase* [4];
+ imageList[images++] = new ImageXVDesk();
+ imageList[images++] = new ImageDGAFull();
+ imageList[images++] = new ImageDeskX11();
+ imageList[images] = NULL;
+}
+
+
+X11Surface::~X11Surface() {
+ close();
+ if (xWindow->display)
+ XCloseDisplay(xWindow->display);
+ free(xWindow);
+
+ for (int count=0 ; count<images ; count++) {
+ if (imageList[count] != NULL)
+ delete imageList[count];
+ }
+ delete [] imageList;
+}
+
+
+int X11Surface::getHeight() {
+ return xWindow->height;
+}
+
+
+int X11Surface::getWidth() {
+ return xWindow->width;
+}
+
+int X11Surface::isOpen() {
+ return xWindow->lOpen;
+}
+
+int X11Surface::x11WindowId() {
+ if(m_windowIdAvailable)
+ return xWindow->window;
+ else
+ return -1;
+}
+
+int X11Surface::open(int width, int height,const char *title, bool border) {
+
+ close();
+ xWindow->width=width;
+ xWindow->height=height;
+
+ if(!xWindow->display) {
+ printf("\nX initialisation error:\n *** %s\n",ERR_XI_STR[ERR_XI_DISPLAY]);
+ printf("check ipcs and delete resources with ipcrm\n");
+ exit(0);
+ }
+
+ xWindow->screennum=DefaultScreen(xWindow->display);
+ xWindow->screenptr=DefaultScreenOfDisplay(xWindow->display);
+ xWindow->visual=DefaultVisualOfScreen(xWindow->screenptr);
+ xWindow->depth=DefaultDepth(xWindow->display,xWindow->screennum);
+
+ switch(xWindow->depth) {
+ case 8:
+ xWindow->pixelsize=1;
+ break;
+ case 16:
+ xWindow->pixelsize=2;
+ break;
+ case 24:
+ xWindow->pixelsize=4;
+ break;
+ case 32:
+ xWindow->pixelsize=4;
+ break;
+ default:
+ cout << "unknown pixelsize for depth:"<<xWindow->depth<<endl;
+ exit(0);
+ }
+
+ XColor background, ignored;
+ XAllocNamedColor (xWindow->display,
+ DefaultColormap (xWindow->display, xWindow->screennum),
+ "black", &background, &ignored);
+
+ XSetWindowAttributes attributes;
+ attributes.background_pixel=background.pixel;
+ attributes.backing_store=NotUseful;
+ attributes.override_redirect=True;
+
+ xWindow->window=XCreateWindow(xWindow->display,
+ RootWindowOfScreen(xWindow->screenptr),
+ 0,0,
+ xWindow->width,
+ xWindow->height,0,
+ xWindow->depth,
+ InputOutput, xWindow->visual,
+ (border) ? CWBackingStore : CWBackPixel|CWOverrideRedirect,
+ &attributes);
+
+ m_windowIdAvailable = true;
+ if(!xWindow->window) {
+ printf("\nX initialisation error:\n *** %s\n",ERR_XI_STR[ERR_XI_WINDOW]);
+ printf("check ipcs and delete resources with ipcrm\n");
+ return false;
+ }
+
+ WM_DELETE_WINDOW = XInternAtom(xWindow->display, "WM_DELETE_WINDOW", False);
+ XSetWMProtocols(xWindow->display, xWindow->window, &WM_DELETE_WINDOW, 1);
+
+ XSetErrorHandler(dummy);
+
+ XStoreName(xWindow->display,xWindow->window,title);
+ XSelectInput(xWindow->display,xWindow->window,
+ ExposureMask|KeyPressMask|KeyReleaseMask|ButtonPressMask);
+ xWindow->gc=XCreateGC(xWindow->display,xWindow->window,0,NULL);
+ XMapRaised(xWindow->display,xWindow->window);
+
+ if (xWindow->depth >= 16) {
+ initColorDisplay(xWindow);
+
+ } else {
+ // depth is <= 8
+ // allocate memory for dithertables
+ // gets the rgb masks
+ initColorDisplay(xWindow);
+ // create 8 bit dithertables
+ // create private colormap
+ initSimpleDisplay(xWindow);
+
+ }
+
+ xWindow->palette=NULL;
+ xWindow->screensize=xWindow->height*xWindow->width*xWindow->pixelsize;
+ xWindow->lOpen=true;
+
+ for (int count=0 ; count<images ; count++) {
+ if (imageList[count] != NULL)
+ imageList[count]->init(xWindow);
+ }
+
+ return true;
+}
+
+
+int X11Surface::close() {
+ if (isOpen()==false) {
+ return true;
+ }
+ closeImage();
+
+ XFreeGC(xWindow->display,xWindow->gc);
+ XDestroyWindow(xWindow->display,xWindow->window);
+
+ xWindow->lOpen=false;
+
+
+ return true;
+}
+
+ImageBase *X11Surface::findImage(int mode) {
+ for (int count=0 ; count<images ; count++) {
+ if ((imageList[count] == NULL) || (IS_DISABLED(imageList[count])))
+ continue;
+
+ if (imageList[count]->supportedModes & mode)
+ return imageList[count];
+ }
+ return NULL;
+}
+
+ImageBase **X11Surface::getModes() {
+ return imageList;
+}
+
+void X11Surface::setModes(ImageBase **modes) {
+ imageList = modes;
+}
+
+int X11Surface::openImage(int mode, YUVPicture*) {
+ if (imageMode != _IMAGE_NONE) {
+ cout << "bad open error X11Surface::openImage"<<endl;
+ return false;
+ }
+ if (mode == _IMAGE_NONE) {
+ cout << "X11Surface::openImage - no valid mode specified"<<endl;
+ return false;
+ }
+
+ ImageBase *newImage=findImage(mode);
+
+ if (newImage == NULL) {
+ cout << " X11Surface::openImage - no matching image found"<<endl;
+ imageMode=_IMAGE_NONE;
+ } else {
+ /*
+ printf("Best image found: %s\n", newImage->getIdentifier());
+ printf("\tsupported modes: desk=%d, double=%d, full=%d, resize=%d\n",
+ HAS_DESK(newImage),
+ HAS_DOUBLE(newImage),
+ HAS_FULL(newImage),
+ HAS_RESIZE(newImage));
+ */
+
+ open(xWindow->width, xWindow->height, "mpeglib", !(mode & _IMAGE_FULL));
+ newImage->openImage(mode);
+ if (!IS_FULL(mode)) {
+ XMoveWindow(xWindow->display, xWindow->window,
+ xWindow->x, xWindow->y);
+
+ XSizeHints hints;
+ hints.flags = PMaxSize;
+ if (HAS_RESIZE(newImage)) {
+ hints.max_width = INT_MAX;
+ hints.max_height = INT_MAX;
+ } else {
+ hints.max_width = xWindow->width;
+ hints.max_height = xWindow->height;
+ }
+ XSetWMNormalHints(xWindow->display, xWindow->window, &hints);
+ }
+
+ imageMode=mode;
+ }
+ imageCurrent = newImage;
+ XSync(xWindow->display,true);
+ return (imageCurrent != NULL);
+}
+
+
+int X11Surface::closeImage() {
+
+ if ((imageMode == _IMAGE_NONE) || (!xWindow->lOpen))
+ return false;
+
+ ImageBase *old = imageCurrent;
+ imageCurrent=NULL;
+
+ XWindowAttributes attr;
+ Window junkwin;
+
+ if (!IS_FULL(imageMode)) {
+ if (!XGetWindowAttributes(xWindow->display, xWindow->window, &attr))
+ cout << "Can't get window attributes." << endl;
+
+ XTranslateCoordinates (xWindow->display, xWindow->window, attr.root,
+ -attr.border_width,
+ -attr.border_width,
+ &xWindow->x, &xWindow->y, &junkwin);
+ }
+
+ imageMode=_IMAGE_NONE;
+ old->closeImage();
+
+ return true;
+}
+
+
+int X11Surface::dither(YUVPicture* pic) {
+ if (imageCurrent != NULL) {
+ imageCurrent->ditherImage(pic);
+ }
+ return true;
+}
+
+
+int X11Surface::putImage(YUVPicture* ) {
+ if (imageCurrent != NULL) {
+ imageCurrent->putImage();
+ }
+ return true;
+}
+
+
+int X11Surface::getDepth() {
+ return xWindow->depth;
+}
+
+int X11Surface::getImageMode() {
+ return imageMode;
+}
+
+int X11Surface::checkEvent(int* newMode) {
+ XEvent event;
+
+ if (isOpen()==false)
+ return false;
+
+ // check if we forward the call to the FULLSCREEN mode
+ if (!imageCurrent->active()) {
+ if (IS_FULL(imageMode)) {
+ *newMode=imageMode ^ _IMAGE_FULL;
+ return true;
+ }
+ }
+
+ // normal X11 images use the X11 event queue
+ if (XCheckTypedWindowEvent(xWindow->display,
+ xWindow->window,ButtonPress,&event)) {
+ if (event.xbutton.button == Button1) {
+ if (findImage(_IMAGE_DOUBLE) != NULL)
+ *newMode = imageMode ^ _IMAGE_DOUBLE;
+ } else if (event.xbutton.button == Button3) {
+ if (findImage(_IMAGE_FULL) != NULL)
+ *newMode = imageMode ^ _IMAGE_DESK ^ _IMAGE_FULL;
+ }
+ return true;
+ }
+ // now check if there are unneeded events in the queue,
+ // then delete them
+ int eventCnt=XPending(xWindow->display);
+ if (eventCnt > 10) {
+ XSync(xWindow->display,true);
+ }
+ return false;
+
+
+}
+
+
+
+void X11Surface::config(const char* key,
+ const char* value, void* ) {
+ if (strcmp(key,"xvAllow")==0) {
+ lXVAllow=atoi(value);
+ }
+}
+
diff --git a/mpeglib/lib/util/render/x11/x11Surface.h b/mpeglib/lib/util/render/x11/x11Surface.h
new file mode 100644
index 00000000..54a6582d
--- /dev/null
+++ b/mpeglib/lib/util/render/x11/x11Surface.h
@@ -0,0 +1,79 @@
+/*
+ surface wrapper for X11 Window
+ 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 __X11SURFACE_H
+#define __X11SURFACE_H
+
+#include <limits.h>
+#include "xinit.h"
+#include "../surface.h"
+#include "initDisplay.h"
+#include "../dither/ditherWrapper.h"
+#include "imageDeskX11.h"
+#include "imageDGAFull.h"
+#include "imageXVDesk.h"
+
+
+
+class X11Surface : public Surface {
+
+ int lOpen;
+ int imageMode;
+
+ XWindow* xWindow;
+
+ ImageBase** imageList;
+ int images;
+
+ ImageBase* imageCurrent;
+
+ Atom WM_DELETE_WINDOW;
+ Atom WM_RESIZE_WINDOW;
+ int lXVAllow;
+
+ public:
+ X11Surface();
+ ~X11Surface();
+
+ int isOpen();
+ int open(int width, int height,const char *title, bool border = false);
+ int close();
+ int getHeight();
+ int getWidth();
+ int getDepth();
+ int getImageMode();
+ int x11WindowId();
+
+ ImageBase *findImage(int mode);
+
+ // these functions grant access to the supported images. be careful when changing
+ // entries, because these are no copies. they are the original values!
+ ImageBase **getModes();
+ void setModes(ImageBase **modes);
+
+ int openImage(int mode, YUVPicture* pic = NULL);
+ int closeImage();
+ int dither(YUVPicture* pic);
+ int putImage(YUVPicture* pic);
+
+ int checkEvent(int* mode);
+
+ void config(const char* key,
+ const char* value,void* user_data);
+
+
+ private:
+ int initX11();
+ bool m_windowIdAvailable;
+};
+#endif
diff --git a/mpeglib/lib/util/render/x11/xinit.h b/mpeglib/lib/util/render/x11/xinit.h
new file mode 100644
index 00000000..c42c290f
--- /dev/null
+++ b/mpeglib/lib/util/render/x11/xinit.h
@@ -0,0 +1,99 @@
+
+#ifndef __XINIT_H__
+#define __XINIT_H__
+
+#define __USE_X_SHAREDMEMORY__
+
+#include <pthread.h>
+
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+
+
+
+#ifdef X11_SHARED_MEM
+#include <X11/extensions/XShm.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif
+
+
+#ifdef X11_XV
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/XShm.h>
+#endif
+
+#ifdef X11_XVIDMODE
+#include <X11/extensions/xf86vmode.h>
+#endif
+
+#ifdef X11_DGA2
+#include <X11/extensions/xf86dga.h>
+#endif
+
+#define ERR_XI_FAILURE 0xFF
+#define ERR_XI_OK 0x00
+#define ERR_XI_NOSHAREDMEMORY 0x01
+#define ERR_XI_DISPLAY 0x02
+#define ERR_XI_BADDEPTH 0x03
+#define ERR_XI_WINDOW 0x04
+#define ERR_XI_VIRTALLOC 0x05
+#define ERR_XI_XIMAGE 0x06
+#define ERR_XI_SHMALLOC 0x07
+#define ERR_XI_SHMXIMAGE 0x08
+#define ERR_XI_SHMSEGINFO 0x09
+#define ERR_XI_SHMVIRTALLOC 0x0A
+#define ERR_XI_SHMATTACH 0x0B
+
+
+
+
+#define PIXEL unsigned long
+
+extern const char *ERR_XI_STR[];
+
+struct XWindow {
+
+ Display *display;
+ Window window;
+ Screen *screenptr;
+ int screennum;
+ Visual *visual;
+ GC gc;
+
+ Colormap colormap;
+ PIXEL *palette;
+ int colorcells;
+
+ int x;
+ int y;
+ int width;
+ int height;
+ int depth;
+ int pixelsize;
+ int screensize;
+ int lOpen;
+
+ // colorMask
+ unsigned int redMask;
+ unsigned int greenMask;
+ unsigned int blueMask;
+
+ // colortable for 8 bit colormap
+ // (created with interference by the XServer)
+ unsigned char pixel[256];
+
+};
+
+
+#endif /* __XINIT_H__ */
diff --git a/mpeglib/lib/util/render/yuvPicture.cpp b/mpeglib/lib/util/render/yuvPicture.cpp
new file mode 100644
index 00000000..e79d3bde
--- /dev/null
+++ b/mpeglib/lib/util/render/yuvPicture.cpp
@@ -0,0 +1,253 @@
+/*
+ describes a picture in yuv format
+ 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 "yuvPicture.h"
+
+#include <iostream>
+
+using namespace std;
+
+static int instanceCnt=0;
+
+YUVPicture::YUVPicture(int width,int height) {
+ this->width=width;
+ this->height=height;
+
+ instance=instanceCnt;
+ instanceCnt++;
+ imagePtr=NULL;
+
+ setImageType(PICTURE_YUVMODE_CR_CB);
+
+
+ startTimeStamp=new TimeStamp();
+ waitTime=new TimeStamp();
+ earlyTime=new TimeStamp();
+ mpegType=-1;
+
+}
+
+
+YUVPicture::~YUVPicture() {
+ delete imagePtr;
+ delete earlyTime;
+ delete startTimeStamp;
+ delete waitTime;
+}
+
+
+
+int YUVPicture::getHeight() {
+ return height;
+}
+
+
+int YUVPicture::getWidth() {
+ return width;
+}
+
+
+
+int YUVPicture::getLumLength() {
+ return lumLength;
+}
+
+
+int YUVPicture::getColorLength() {
+ return colorLength;
+}
+
+int YUVPicture::getImageSize() {
+ return imageSize;
+}
+
+
+
+
+
+
+
+void YUVPicture::print(const char* title) {
+ cout << title <<":";
+ printf(" instance:%d ",instance);
+ printf(" width:%d ",width);
+ printf(" height:%d ",height);
+ cout <<" picPerSec:"<<picPerSec;
+ switch(mpegType) {
+ case 1:
+ printf("I_FRAME ");
+ break;
+ case 2:
+ printf("P_FRAME ");
+ break;
+ case 3:
+ printf("B_FRAME ");
+ break;
+ case 4:
+ printf("D_FRAME ");
+ break;
+ default:
+ printf("<unknown> ");
+ }
+ printf("\n");
+
+
+}
+
+
+void YUVPicture::setPicturePerSecond(float val) {
+ this->picPerSec=val;
+}
+
+
+float YUVPicture::getPicturePerSecond() {
+ return picPerSec;
+}
+
+
+void YUVPicture::setStartTimeStamp(TimeStamp* aStamp) {
+ aStamp->copyTo(startTimeStamp);
+}
+
+
+TimeStamp* YUVPicture::getStartTimeStamp() {
+ return startTimeStamp;
+}
+
+void YUVPicture::setWaitTime(TimeStamp* aStamp) {
+ aStamp->copyTo(waitTime);
+}
+
+
+TimeStamp* YUVPicture::getWaitTime() {
+ return waitTime;
+}
+
+void YUVPicture::setEarlyTime(TimeStamp* earlyTime) {
+ this->earlyTime=earlyTime;
+}
+
+
+TimeStamp* YUVPicture::getEarlyTime() {
+ return earlyTime;
+}
+
+
+
+void YUVPicture::setMpegPictureType(int type) {
+ this->mpegType=type;
+}
+
+
+int YUVPicture::getMpegPictureType() {
+ return mpegType;
+}
+
+
+void YUVPicture::setImageType(int imageType) {
+
+
+ //
+ // Reset everything
+ //
+
+ if (imagePtr != NULL) {
+ delete [] imagePtr;
+ imagePtr=NULL;
+ }
+ this->imageType=imageType;
+
+ lumLength=0;
+ colorLength=0;
+ Cr_mode=NULL;
+ Cb_mode=NULL;
+ luminance_mode=NULL;
+
+
+ //
+ // YUV Images
+ //
+ if ( (imageType == PICTURE_YUVMODE_CR_CB) ||
+ (imageType == PICTURE_YUVMODE_CB_CR) ) {
+
+
+ lumLength=width * height;
+ colorLength=width * height / 4;
+ imageSize=lumLength+colorLength+colorLength;
+
+ // the 64 is some "security" space
+ imagePtr=new unsigned char[imageSize+64];
+
+ if (imagePtr == NULL) {
+ cout << "cannot create image"<<endl;
+ exit(0);
+ }
+
+ // now caculate pointers to start addresses of lum/Cr/Cb blocks
+ // we need the yuvPtr for direct dither in hardware
+ // this should save a memcpy
+
+ luminance = imagePtr;
+ Cr = imagePtr+lumLength;
+ Cb = imagePtr+lumLength+colorLength;
+
+
+ if ( (luminance == NULL) ||
+ (Cr == NULL) ||
+ (Cb == NULL) ) {
+ cout << "allocation luminance/Cr/Cb error"<<endl;
+ exit(0);
+ }
+
+ switch(imageType) {
+ case PICTURE_YUVMODE_CR_CB:
+ Cr_mode=Cr;
+ Cb_mode=Cb;
+ luminance_mode=imagePtr;
+ break;
+ case PICTURE_YUVMODE_CB_CR:
+ Cr_mode=Cb;
+ Cb_mode=Cr;
+ luminance_mode=imagePtr;
+ break;
+ default:
+ cout << "unknown yuv mode:"<<imageType<<endl;
+ }
+ }
+ else if ( (imageType == PICTURE_YUVMODE_YUY2) ||
+ (imageType == PICTURE_YUVMODE_UYVY) ) {
+ // these yuv-modes are packed
+
+ imageSize=width * height * 2;
+
+ // the 64 is some "security" space
+ imagePtr=new unsigned char[imageSize+64];
+
+ if (imagePtr == NULL) {
+ cout << "cannot create image"<<endl;
+ exit(0);
+ }
+ }
+
+ //
+ // RGB Imcdages
+ //
+
+ if ( (imageType == PICTURE_RGB) ||
+ (imageType == PICTURE_RGB_FLIPPED) ){
+ imageSize=width*height*4;
+ imagePtr=new unsigned char[imageSize];
+ }
+ memset(imagePtr,0,imageSize);
+}
diff --git a/mpeglib/lib/util/render/yuvPicture.h b/mpeglib/lib/util/render/yuvPicture.h
new file mode 100644
index 00000000..1995b473
--- /dev/null
+++ b/mpeglib/lib/util/render/yuvPicture.h
@@ -0,0 +1,110 @@
+/*
+ describes a picture in yuv format
+ 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 __YUVPICTURE_H
+#define __YUVPICTURE_H
+
+
+extern "C" {
+#include <stdio.h>
+#include <string.h>
+}
+
+#include "../timeStamp.h"
+
+#define PICTURE_NO_TYPE -1
+
+#define PICTURE_YUVMODE_CR_CB 1
+#define PICTURE_YUVMODE_CB_CR 2
+#define PICTURE_RGB 3
+#define PICTURE_RGB_FLIPPED 4
+#define PICTURE_YUVMODE_YUY2 5
+#define PICTURE_YUVMODE_UYVY 6
+
+class YUVPicture {
+
+ unsigned char* imagePtr; /* Pointer to complete yuv image */
+
+ unsigned char* luminance; /* Luminance plane. */
+ unsigned char* Cr; /* Cr plane. */
+ unsigned char* Cb; /* Cb plane. */
+
+
+ int width;
+ int height;
+
+ float picPerSec;
+ int lumLength;
+ int colorLength;
+ int imageSize;
+
+ TimeStamp* startTimeStamp;
+ TimeStamp* waitTime;
+ TimeStamp* earlyTime;
+
+ int mpegType;
+ int instance;
+ int imageType;
+
+ unsigned char* image_mode; /* start Pointer to complete image */
+ unsigned char* luminance_mode; /* Luminace plane. */
+ unsigned char* Cr_mode; /* Cr plane. */
+ unsigned char* Cb_mode; /* Cb plane. */
+
+ public:
+ YUVPicture(int width,int height);
+ ~YUVPicture();
+
+ //
+ // For YUV Images
+ //
+ inline unsigned char* getLuminancePtr() {return luminance_mode;}
+ inline unsigned char* getCrPtr() {return Cr_mode;}
+ inline unsigned char* getCbPtr() {return Cb_mode;}
+
+ // general
+ inline unsigned char* getImagePtr() {return imagePtr;}
+
+ // use these to swap the image Types
+ inline int getImageType() { return imageType; }
+ void setImageType(int mode);
+
+
+ int getHeight();
+ int getWidth();
+
+ int getLumLength();
+ int getColorLength();
+ int getImageSize();
+
+ void setPicturePerSecond(float val);
+ float getPicturePerSecond();
+
+
+ void setStartTimeStamp(TimeStamp* timeStamp);
+ TimeStamp* getStartTimeStamp();
+
+ void setWaitTime(TimeStamp* waitTime);
+ TimeStamp* getWaitTime();
+
+ void setEarlyTime(TimeStamp* earlyTime);
+ TimeStamp* getEarlyTime();
+
+ void setMpegPictureType(int type);
+ int getMpegPictureType();
+
+
+ void print(const char* title);
+};
+#endif
diff --git a/mpeglib/lib/util/syncClock.cpp b/mpeglib/lib/util/syncClock.cpp
new file mode 100644
index 00000000..6e03bc4b
--- /dev/null
+++ b/mpeglib/lib/util/syncClock.cpp
@@ -0,0 +1,59 @@
+/*
+ basic synchronisation Classs
+ 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 "syncClock.h"
+
+#include <iostream>
+
+using namespace std;
+
+SyncClock::SyncClock() {
+}
+
+
+SyncClock::~SyncClock() {
+}
+
+
+
+int SyncClock::getSyncMode() {
+ cout << "direct virtual call SyncClock::getSyncMode"<<endl;
+ return __SYNC_NONE;
+}
+
+
+void SyncClock::setSyncMode(int) {
+ cout << "direct virtual call SyncClock::setSyncMode"<<endl;
+}
+
+
+
+int SyncClock::syncAudio(double ,double ) {
+ cout << "direct virtual call SyncClock::syncAudio"<<endl;
+ return true;
+}
+
+
+int SyncClock::syncVideo(double,double,
+ TimeStamp*,
+ TimeStamp*) {
+ cout << "direct virtual call SyncClock::syncVideo"<<endl;
+ return true;
+}
+
+
+
+void SyncClock::print(char*) {
+ cout << "direct virtual call print"<<endl;
+}
+
diff --git a/mpeglib/lib/util/syncClock.h b/mpeglib/lib/util/syncClock.h
new file mode 100644
index 00000000..4b6bc2bb
--- /dev/null
+++ b/mpeglib/lib/util/syncClock.h
@@ -0,0 +1,61 @@
+/*
+ basic synchronisation Classs
+ 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 __SYNCCLOCK_H
+#define __SYNCCLOCK_H
+
+#include "timeWrapper.h"
+#include "abstract/abs_thread.h"
+#include "timeStamp.h"
+#include <errno.h>
+
+#define __SYNC_NONE 0
+#define __SYNC_AUDIO 1
+#define __SYNC_VIDEO 2
+#define __SYNC_BOTH 3
+
+
+/**
+ The idea is similar to this:
+ We start a clock and selext a synchronisation mode.
+ (AUDIO,VIDEO,BOTH,NONE)
+ Assume we select AUDIO. When the audio thread delivers an SCR
+ and an PTS, we set the SCR from this set, as the new
+ time reference fo rthis clock.
+ If a video thread enters the class, with an SCR,PTS we wait,
+ or directly return if the PTS is in time or out of time,
+ but we never set the SCR.
+*/
+
+class SyncClock {
+
+
+ public:
+ SyncClock();
+ virtual ~SyncClock();
+
+ virtual int getSyncMode();
+ virtual void setSyncMode(int syncMode);
+
+
+ virtual int syncAudio(double pts,double scr);
+ virtual int syncVideo(double pts,double scr,
+ class TimeStamp* earlyTime,
+ class TimeStamp* waitTime);
+
+ virtual void print(char* text);
+
+
+};
+#endif
diff --git a/mpeglib/lib/util/syncClockMPEG.cpp b/mpeglib/lib/util/syncClockMPEG.cpp
new file mode 100644
index 00000000..53ae7e2d
--- /dev/null
+++ b/mpeglib/lib/util/syncClockMPEG.cpp
@@ -0,0 +1,221 @@
+/*
+ synchronisation of audio/video (PTS) against system clock stamps (SCR)
+ 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 "syncClockMPEG.h"
+
+
+#include <iostream>
+
+using namespace std;
+
+
+SyncClockMPEG::SyncClockMPEG() {
+ syncMode=__SYNC_NONE;
+ abs_thread_mutex_init(&scrMut);
+ abs_thread_mutex_init(&changeMut);
+ lastSCR=0.0;
+ lastPTS=0.0;
+ jitter=0.0;
+ oldjitter=0.0;
+
+ TimeWrapper::gettimeofday(&lastPTS_time);
+
+
+}
+
+
+SyncClockMPEG::~SyncClockMPEG() {
+ abs_thread_mutex_destroy(&changeMut);
+ abs_thread_mutex_destroy(&scrMut);
+}
+
+
+
+int SyncClockMPEG::getSyncMode() {
+ return syncMode;
+}
+
+
+void SyncClockMPEG::setSyncMode(int syncMode) {
+ this->syncMode=syncMode;
+}
+
+
+
+int SyncClockMPEG::syncAudio(double pts,double scr) {
+ switch(syncMode) {
+ case __SYNC_AUDIO:
+ markLastPTSTime(scr,pts);
+ break;
+ default:
+ cout << "syncMode not implemented:"<<syncMode<<endl;
+ }
+ return true;
+}
+
+
+int SyncClockMPEG::syncVideo(double pts,double scr,
+ TimeStamp* earlyTime,
+ TimeStamp* waitTime) {
+ int back;
+ switch(syncMode) {
+ case __SYNC_AUDIO:
+ back=gowait(scr,pts,earlyTime,waitTime);
+ return back;
+ break;
+ case __SYNC_NONE:
+ return true;
+ default:
+ cout << "syncMode not implemented"<<endl;
+ }
+ return true;
+}
+
+
+void SyncClockMPEG::lockSyncClock() {
+ abs_thread_mutex_lock(&changeMut);
+ abs_thread_mutex_lock(&scrMut);
+ abs_thread_mutex_unlock(&changeMut);
+
+}
+
+
+void SyncClockMPEG::unlockSyncClock() {
+ abs_thread_mutex_unlock(&scrMut);
+}
+
+
+double SyncClockMPEG::getPTSTime(double* window) {
+ lockSyncClock();
+ double currentPTS;
+ timeval_t current_time;
+ timeval_t passed_time;
+ TimeWrapper::gettimeofday(&current_time);
+
+ a_Minus_b_Is_C(&current_time,&lastPTS_time,&passed_time);
+ currentPTS=lastPTS+timeval2Double(&passed_time);
+ *window=jitter+oldjitter;
+
+
+ unlockSyncClock();
+ return currentPTS;
+}
+
+
+void SyncClockMPEG::markLastPTSTime(double ,double pts) {
+ double tmp;
+ double expect_time=getPTSTime(&tmp);
+
+ lockSyncClock();
+ oldjitter=jitter;
+ jitter=expect_time-pts;
+
+ TimeWrapper::gettimeofday(&lastPTS_time);
+ lastPTS=pts;
+
+
+ unlockSyncClock();
+ /*
+ cout << "(audio) pts stream:"<<pts
+ << " expect:"<<expect_time<<" jitter:"<<jitter<<endl;
+ */
+
+}
+
+
+int SyncClockMPEG::a_Minus_b_Is_C(timeval_t* a,timeval_t* b,timeval_t* c){
+ c->tv_usec=a->tv_usec;
+ c->tv_sec=a->tv_sec;
+
+ c->tv_usec-=b->tv_usec;
+ c->tv_sec-=b->tv_sec;
+
+ if (c->tv_usec <= 0) {
+ c->tv_usec=c->tv_usec+1000000;
+ c->tv_sec--;
+ }
+ if (c->tv_usec >= 1000000) {
+ c->tv_usec=c->tv_usec-1000000;
+ c->tv_sec++;
+ }
+ return true;
+}
+
+
+double SyncClockMPEG::timeval2Double(timeval_t* a) {
+ return (double)a->tv_sec+(double)(a->tv_usec)/1000000.0;
+}
+
+
+void SyncClockMPEG::double2Timeval(double a,timeval_t* dest) {
+ dest->tv_sec=(int)a;
+ dest->tv_usec=(int)(1000000.0*(double)(a-(double)dest->tv_sec));
+}
+
+
+int SyncClockMPEG::gowait(double ,double pts,
+ TimeStamp* earlyTime,TimeStamp* ) {
+ double window;
+ double currentPTS=getPTSTime(&window);
+ double diff_time;
+
+ // in window we have the jitter
+ // diff_time is positive when we are in the future
+ diff_time=pts-(currentPTS+window);
+
+
+
+ // tolerate one frame (for 25 frames/s) in the future
+ // but wait a bit
+ if (diff_time > 0.0) {
+ diff_time=diff_time/4.0;
+
+ double2Timeval(diff_time,earlyTime->getTime());
+ if (diff_time > 1) {
+ // cannot be, we assume stange clock error
+ earlyTime->set(1,0);
+ }
+
+ return true;
+ }
+
+ earlyTime->set(0,0);
+ // one frame late, display it, without waiting
+ // and hope we catch up
+ if (diff_time > -0.04) {
+ return true;
+ }
+ /*
+ cout << "(video) pts stream:"<<pts
+ << " pts expect:"<<currentPTS
+ << " window:"<<window<<endl;
+ */
+ return false;
+}
+
+
+void SyncClockMPEG::printTime(timeval_t* a,char* text) {
+ cout << text
+ << "time(sec):"<<a->tv_sec
+ << "time(usec)"<<a->tv_usec<<endl;
+}
+
+void SyncClockMPEG::print(char* text) {
+ cout << text
+ << " lastPTS:"<<lastPTS
+ << " lastSCR:"<<lastSCR
+ << " jitter:"<<jitter;
+ printTime(&lastPTS_time,(char*)"lastPTS_time");
+ printTime(&lastSCR_time,(char*)"lastSCR_time");
+}
diff --git a/mpeglib/lib/util/syncClockMPEG.h b/mpeglib/lib/util/syncClockMPEG.h
new file mode 100644
index 00000000..1a812c45
--- /dev/null
+++ b/mpeglib/lib/util/syncClockMPEG.h
@@ -0,0 +1,77 @@
+/*
+ synchronisation of audio/video (PTS) against system clock stamps (SCR)
+ 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 __SYNCCLOCKMPEG_H
+#define __SYNCCLOCKMPEG_H
+
+
+#include "syncClock.h"
+
+/**
+ The idea is similar to this:
+ We start a clock and selext a synchronisation mode.
+ (AUDIO,VIDEO,BOTH,NONE)
+ Assume we select AUDIO. When the audio thread delivers an SCR
+ and an PTS, we set the SCR from this set, as the new
+ time reference fo rthis clock.
+ If a video thread enters the class, with an SCR,PTS we wait,
+ or directly return if the PTS is in time or out of time,
+ but we never set the SCR.
+*/
+
+class SyncClockMPEG : public SyncClock {
+
+ int syncMode;
+ double lastSCR;
+ double lastPTS;
+ double jitter;
+ double oldjitter;
+ timeval_t lastSCR_time;
+ timeval_t lastPTS_time;
+ timeval_t drift_time;
+
+ public:
+ SyncClockMPEG();
+ ~SyncClockMPEG();
+
+ int getSyncMode();
+ void setSyncMode(int syncMode);
+
+
+ int syncAudio(double pts,double scr);
+ int syncVideo(double pts,double scr,
+ class TimeStamp* earlyTime,class TimeStamp* waitTime);
+
+ void print(char* text);
+
+ double getPTSTime(double* window);
+ private:
+
+ void printTime(timeval_t* a,char* text);
+ void markLastPTSTime(double scr,double pts);
+ int gowait(double scr,double pts,
+ class TimeStamp* earlyTime,class TimeStamp* waitTime);
+ int a_Minus_b_Is_C(timeval_t* a,timeval_t* b,timeval_t* c);
+ double timeval2Double(timeval_t* a);
+ void double2Timeval(double a,timeval_t* dest);
+
+ void lockSyncClock();
+ void unlockSyncClock();
+
+ abs_thread_mutex_t scrMut;
+ abs_thread_mutex_t changeMut;
+
+
+};
+#endif
+
diff --git a/mpeglib/lib/util/timeStamp.cpp b/mpeglib/lib/util/timeStamp.cpp
new file mode 100644
index 00000000..2804cc5b
--- /dev/null
+++ b/mpeglib/lib/util/timeStamp.cpp
@@ -0,0 +1,273 @@
+/*
+ class for managing byte positions and associated time positions
+ 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 "timeStamp.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+TimeStamp::TimeStamp() {
+ key=0;
+ keylen=0;
+ time.tv_sec=0;
+ time.tv_usec=0;
+
+ ptsTimeStamp=0.0;
+ scrTimeStamp=0.0;
+ videoFrameCounter=0;
+ dtsTimeStamp=0.0;
+ lPTSFlag=false;
+
+}
+
+
+TimeStamp::~TimeStamp() {
+}
+
+
+void TimeStamp::copyTo(TimeStamp* dest) {
+ dest->setKey(key,keylen);
+ dest->setTime(&time);
+ dest->setPTSTimeStamp(ptsTimeStamp);
+ dest->setVideoFrameCounter(videoFrameCounter);
+
+ dest->setSCRTimeStamp(scrTimeStamp);
+ dest->setDTSTimeStamp(dtsTimeStamp);
+ dest->setSyncClock(syncClock);
+ dest->setPTSFlag(lPTSFlag);
+}
+
+
+long TimeStamp::getKey() {
+ return key;
+}
+
+int TimeStamp::getKeyLen() {
+ return keylen;
+}
+
+void TimeStamp::setKey(long key,int len) {
+ this->key=key;
+ this->keylen=len;
+}
+
+
+void TimeStamp::setTime(timeval_t* newTime) {
+ time.tv_sec=newTime->tv_sec;
+ time.tv_usec=newTime->tv_usec;
+}
+
+
+void TimeStamp::gettimeofday() {
+ TimeWrapper::gettimeofday(&time);
+}
+
+
+timeval_t* TimeStamp::getTime() {
+ return &time;
+}
+
+
+void TimeStamp::waitForIt() {
+ timeval_t waitTime;
+
+ waitTime.tv_sec=time.tv_sec;
+ waitTime.tv_usec=time.tv_usec;
+
+ if (isPositive()) {
+ //cout << "wait:"<<waitTime.tv_sec<<" usec:"<<waitTime.tv_usec<<endl;
+ TimeWrapper::usleep(&waitTime);
+ }
+
+}
+
+void TimeStamp::addOffset(TimeStamp* stamp) {
+ addOffset(stamp->time.tv_sec,stamp->time.tv_usec);
+}
+
+void TimeStamp::addOffset(int sec,long usec) {
+ time.tv_sec=time.tv_sec+sec;
+ time.tv_usec=time.tv_usec+usec;
+ if (time.tv_usec >= 1000000) {
+ time.tv_usec-=1000000;
+ time.tv_sec++;
+ }
+ if (time.tv_usec < 0) {
+ time.tv_usec+=1000000;
+ time.tv_sec--;
+ }
+}
+
+void TimeStamp::minus(int sec,long usec) {
+
+ time.tv_usec-=usec;
+ time.tv_sec-=sec;
+ if (time.tv_usec <= 0) {
+ time.tv_usec=time.tv_usec+1000000;
+ time.tv_sec--;
+ }
+ if (time.tv_usec >= 1000000) {
+ time.tv_usec=time.tv_usec-1000000;
+ time.tv_sec++;
+ }
+
+}
+
+void TimeStamp::minus(TimeStamp* stamp,TimeStamp* dest) {
+
+ long sec=time.tv_sec;
+ long usec=time.tv_usec;
+
+ minus(stamp->time.tv_sec,stamp->time.tv_usec);
+
+ dest->set(time.tv_sec,time.tv_usec);
+ if (dest != this) {
+ time.tv_sec=sec;
+ time.tv_usec=usec;
+ }
+}
+
+
+int TimeStamp::lessThan(TimeStamp* stamp) {
+ return lessThan(stamp->time.tv_sec,stamp->time.tv_usec);
+}
+
+
+int TimeStamp::lessThan(int sec,long usec) {
+ int back=false;
+ if (time.tv_sec < sec) {
+ back=true;
+ } else {
+ if (time.tv_sec == sec) {
+ if (time.tv_usec < usec) {
+ back=true;
+ }
+ }
+ }
+ return back;
+}
+
+void TimeStamp::set(long sec,long usec) {
+ time.tv_sec=sec;
+ time.tv_usec=usec;
+}
+
+
+
+void TimeStamp::print(const char* name) {
+ cout << name
+ <<" lPTS:"<<lPTSFlag
+ <<" pts:"<<ptsTimeStamp
+ <<" dts:"<<dtsTimeStamp
+ <<" scr:"<<scrTimeStamp
+ <<" key:"<<key
+ <<" sec:"<<time.tv_sec
+ <<" usec:"<<time.tv_usec
+ <<" v-Minor:"<<videoFrameCounter<<endl;
+
+
+}
+
+
+
+
+
+int TimeStamp::isPositive() {
+ if ((time.tv_sec == 0) && (time.tv_usec == 0)) {
+ return false;
+ }
+ return ((time.tv_sec >= 0) && (time.tv_usec >= 0));
+}
+
+
+int TimeStamp::isNegative() {
+ if (time.tv_sec < 0) {
+ return true;
+ }
+ if (time.tv_usec < 0) {
+ return true;
+ }
+ return false;
+}
+
+
+int TimeStamp::getPTSFlag() {
+ return lPTSFlag;
+}
+
+void TimeStamp::setPTSFlag(int lPTSFlag) {
+ this->lPTSFlag=lPTSFlag;
+}
+
+double TimeStamp::getPTSTimeStamp() {
+ return ptsTimeStamp;
+}
+
+
+void TimeStamp::setPTSTimeStamp(double ptsTimeStamp) {
+ this->ptsTimeStamp=ptsTimeStamp;
+}
+
+
+double TimeStamp::getSCRTimeStamp() {
+ return scrTimeStamp;
+}
+
+
+void TimeStamp::setSCRTimeStamp(double scrTimeStamp) {
+ this->scrTimeStamp=scrTimeStamp;
+}
+
+
+double TimeStamp::getDTSTimeStamp() {
+ return dtsTimeStamp;
+}
+
+
+void TimeStamp::setDTSTimeStamp(double dtsTimeStamp) {
+ this->dtsTimeStamp=dtsTimeStamp;
+}
+
+int TimeStamp::getVideoFrameCounter() {
+ return videoFrameCounter;
+}
+
+
+void TimeStamp::setVideoFrameCounter(int nr) {
+ this->videoFrameCounter=nr;
+}
+
+
+
+double TimeStamp::getAsSeconds() {
+ return (double)time.tv_sec+(double)time.tv_usec/(double)1000000;
+}
+
+
+
+SyncClock* TimeStamp::getSyncClock() {
+ return syncClock;
+}
+
+void TimeStamp::setSyncClock(SyncClock* syncClock) {
+ this->syncClock=syncClock;
+}
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/util/timeStamp.h b/mpeglib/lib/util/timeStamp.h
new file mode 100644
index 00000000..a45bb582
--- /dev/null
+++ b/mpeglib/lib/util/timeStamp.h
@@ -0,0 +1,92 @@
+/*
+ class for managing byte positions and associated time positions
+ 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 __TIMESTAMP_H
+#define __TIMESTAMP_H
+
+
+#include "syncClock.h"
+
+
+class TimeStamp {
+
+ long key;
+ int keylen;
+
+ int videoFrameCounter;
+
+ timeval_t time;
+
+ int lPTSFlag;
+
+ double ptsTimeStamp;
+ double scrTimeStamp;
+ double dtsTimeStamp;
+
+ class SyncClock* syncClock;
+
+ public:
+ TimeStamp();
+ ~TimeStamp();
+
+ void gettimeofday();
+ void set(long sec,long usec);
+
+ void addOffset(TimeStamp* stamp);
+ void addOffset(int sec,long usec);
+ void copyTo(TimeStamp* dest);
+
+ long getKey();
+ int getKeyLen();
+ void setKey(long key,int keylen);
+
+ int getPTSFlag();
+ void setPTSFlag(int lPTSFlag);
+
+
+ double getPTSTimeStamp();
+ void setPTSTimeStamp(double ptsTimeStamp);
+
+ double getDTSTimeStamp();
+ void setDTSTimeStamp(double dtsTimeStamp);
+
+ double getSCRTimeStamp();
+ void setSCRTimeStamp(double scrTimeStamp);
+
+ int getVideoFrameCounter();
+ void setVideoFrameCounter(int nr);
+
+ SyncClock* getSyncClock();
+ void setSyncClock(class SyncClock* syncClock);
+
+
+ void print(const char* name);
+ void minus(TimeStamp* stamp,TimeStamp* dest);
+ void minus(int sec,long usec);
+ int lessThan(TimeStamp* stamp);
+ int lessThan(int sec,long usec);
+ double getAsSeconds();
+
+ void waitForIt();
+ timeval_t* getTime();
+
+ int isPositive();
+ int isNegative();
+
+ private:
+ void setTime(timeval_t* newTime);
+ void normalize();
+
+
+};
+#endif
diff --git a/mpeglib/lib/util/timeStampArray.cpp b/mpeglib/lib/util/timeStampArray.cpp
new file mode 100644
index 00000000..730dc280
--- /dev/null
+++ b/mpeglib/lib/util/timeStampArray.cpp
@@ -0,0 +1,178 @@
+/*
+ class for managing byte positions and associated time positions
+ 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 <iostream>
+
+#include "timeStampArray.h"
+
+using namespace std;
+
+
+TimeStampArray::TimeStampArray(char* aName,int entries) {
+
+ writePos=0;
+ readPos=0;
+ fillgrade=0;
+ lastWritePos=0;
+ this->entries=entries;
+ if (entries < 1) {
+ cout << "TimeStampArray entries must be >= 1";
+ exit(0);
+ }
+
+
+ abs_thread_mutex_init(&writeInMut);
+ abs_thread_mutex_init(&changeMut);
+
+
+
+ name=strdup(aName);
+ int i;
+ tStampArray=new TimeStamp*[entries];
+
+ for(i=0;i<entries;i++) {
+ tStampArray[i]=new TimeStamp();
+ }
+
+}
+
+
+TimeStampArray::~TimeStampArray() {
+
+ int i;
+ for(i=0;i<entries;i++) {
+ delete tStampArray[i];
+ }
+ delete [] tStampArray;
+ if (name != NULL) {
+ free(name); // allocated with strdup
+ }
+ abs_thread_mutex_destroy(&writeInMut);
+ abs_thread_mutex_destroy(&changeMut);
+}
+
+TimeStamp* TimeStampArray::getReadTimeStamp() {
+ return tStampArray[readPos];
+}
+
+
+int TimeStampArray::getFillgrade() {
+ return fillgrade;
+}
+
+int TimeStampArray::insertTimeStamp(TimeStamp* src,long key,int len) {
+ if (src == NULL) {
+ return true;
+ }
+ lockStampArray();
+ int back=true;
+ src->copyTo(tStampArray[writePos]);
+ tStampArray[writePos]->setKey(key,len);
+ /*
+ if (fillgrade > 0) {
+ if (tStampArray[lastWritePos]->getKey() == key) {
+ unlockStampArray();
+ return;
+ }
+ }
+ */
+
+ lastWritePos=writePos;
+ writePos++;
+ fillgrade++;
+ if (writePos == entries) {
+ writePos=0;
+ }
+ if (fillgrade == entries) {
+ cout << name<<" TimeStampArray::array overfull forward"<<endl;
+ internalForward();
+ back=false;
+ }
+ unlockStampArray();
+ return back;
+}
+
+
+int TimeStampArray::bytesUntilNext(long key) {
+ lockStampArray();
+ TimeStamp* current=tStampArray[readPos];
+ int back=current->getKey()-key;
+ unlockStampArray();
+ return back;
+}
+
+TimeStamp* TimeStampArray::getTimeStamp(long key) {
+ lockStampArray();
+ TimeStamp* back=tStampArray[readPos];
+ if (key > back->getKey()+back->getKeyLen()) {
+ if (fillgrade > 1) {
+ internalForward();
+ unlockStampArray();
+ return getTimeStamp(key);
+ }
+ }
+
+ /*
+ if (back->getKey() > key) {
+ cout << "key "<<key<<" too big"<<back->getKey()-key<<endl;
+ back->print("key access");
+ }
+ */
+ unlockStampArray();
+ /* maybe we should return NULL here to indicate
+ that there is no valid timestamp */
+ /* This would need a check for every getTimeStamp call
+ I think returning the last available stamp is ok
+ */
+ return back;
+}
+
+
+void TimeStampArray::forward() {
+ lockStampArray();
+ internalForward();
+ unlockStampArray();
+}
+
+
+
+void TimeStampArray::clear() {
+ lockStampArray();
+ writePos=0;
+ readPos=0;
+ fillgrade=0;
+ unlockStampArray();
+}
+
+
+void TimeStampArray::lockStampArray() {
+
+ abs_thread_mutex_lock(&changeMut);
+ abs_thread_mutex_lock(&writeInMut);
+ abs_thread_mutex_unlock(&changeMut);
+
+}
+
+
+void TimeStampArray::unlockStampArray() {
+ abs_thread_mutex_unlock(&writeInMut);
+}
+
+
+void TimeStampArray::internalForward() {
+ readPos++;
+ fillgrade--;
+ if (readPos == entries) {
+ readPos=0;
+ }
+}
diff --git a/mpeglib/lib/util/timeStampArray.h b/mpeglib/lib/util/timeStampArray.h
new file mode 100644
index 00000000..8b117652
--- /dev/null
+++ b/mpeglib/lib/util/timeStampArray.h
@@ -0,0 +1,85 @@
+/*
+ class for managing byte positions and associated time positions
+ 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 __TIMESTAMPARRAY_H
+#define __TIMESTAMPARRAY_H
+
+#include "abstract/abs_thread.h"
+#include "timeStamp.h"
+
+
+/**
+ This class deals with the problem to sync audio and video.
+ Both streams are decoded in different threads, sometimes
+ the video is decoded faster than the audio and sometimes
+ not.
+ <p>
+ You need a general mechanism to decide, which is faster.
+ It works like this:
+ <p>
+ When the mpeg stream is split in video/audio part the split thread
+ writes the video/audio data to the inputInterface.
+ Additionally it writes a timestamp to the interface.
+ The interface counts the bytes and forward the bytes/timeStamp
+ pait to this class.
+ Later when the threads write to the outputInterface the ask
+ this class (with the bytePostions) which timestamp it
+ has and hass the data and the timestamp to the outputInterface.
+ There we can decide what to do with the data.
+ <p>
+ 1) audio faster than video = drop video picture
+ <p>
+ 2) video faster than audio - wait for audio.
+*/
+
+
+
+class TimeStampArray {
+
+ TimeStamp** tStampArray;
+
+ int lastWritePos;
+ int writePos;
+ int readPos;
+ int fillgrade;
+ char* name;
+ int entries;
+
+ abs_thread_mutex_t writeInMut;
+ abs_thread_mutex_t changeMut;
+
+
+ public:
+ TimeStampArray(char* name,int entries);
+ ~TimeStampArray();
+
+
+ int insertTimeStamp(TimeStamp* src,long key,int len);
+ TimeStamp* getReadTimeStamp();
+ TimeStamp* getTimeStamp(long key);
+ int getFillgrade();
+ void forward();
+ void clear();
+
+ int bytesUntilNext(long key);
+
+ private:
+ void lockStampArray();
+ void unlockStampArray();
+ void internalForward();
+
+
+
+};
+#endif
+
diff --git a/mpeglib/lib/util/timeWrapper.cpp b/mpeglib/lib/util/timeWrapper.cpp
new file mode 100644
index 00000000..adf87681
--- /dev/null
+++ b/mpeglib/lib/util/timeWrapper.cpp
@@ -0,0 +1,77 @@
+/*
+ wrapps calls to usleep, gettimeofday,...
+ 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 "timeWrapper.h"
+
+#if defined WIN32
+// usec goes from 0 -> 1000000 (one Million) under Unix
+int gettimeofday(struct timeval *tv, struct timezone *tz) {
+ if(tv) {
+ struct _timeb tb;
+ _ftime(&tb);
+ tv->tv_sec=tb.time;
+ tv->tv_usec=1000*tb.millitm;
+ }
+ return(0);
+}
+
+void abs_usleep(const timeval* tm) {
+ _sleep((tm->tv_usec / 1000) + (tm->tv_sec * 1000));
+}
+#endif
+
+#ifndef WIN32
+
+void abs_usleep(struct timeval* tm) {
+ select(0,NULL,NULL,NULL,tm);
+}
+
+#endif
+
+TimeWrapper::TimeWrapper() {
+}
+
+
+TimeWrapper::~TimeWrapper() {
+}
+
+void TimeWrapper::sleep(int sec) {
+ timeval_t time;
+ time.tv_sec=sec;
+ time.tv_usec=0;
+ TimeWrapper::usleep(&time);
+}
+
+void TimeWrapper::usleep(unsigned long usec) {
+ timeval_t time;
+ time.tv_sec=0;
+ time.tv_usec=usec;
+ TimeWrapper::usleep(&time);
+}
+
+void TimeWrapper::usleep(timeval_t* time) {
+ struct timeval waitTime;
+ waitTime.tv_sec=time->tv_sec;
+ waitTime.tv_usec=time->tv_usec;
+ /*Threads and usleep does not work, select is very portable*/
+ ::abs_usleep(&waitTime);
+}
+
+
+void TimeWrapper::gettimeofday(timeval_t* time) {
+ struct timeval waitTime;
+ ::gettimeofday(&waitTime,NULL);
+ time->tv_sec=waitTime.tv_sec;
+ time->tv_usec=waitTime.tv_usec;
+}
diff --git a/mpeglib/lib/util/timeWrapper.h b/mpeglib/lib/util/timeWrapper.h
new file mode 100644
index 00000000..608d5bd0
--- /dev/null
+++ b/mpeglib/lib/util/timeWrapper.h
@@ -0,0 +1,44 @@
+/*
+ wrapps calls to usleep, gettimeofday,...
+ 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 __TIMEWRAPPER_H
+#define __TIMEWRAPPER_H
+
+#if defined WIN32
+#include <winsock.h>
+#include <sys/timeb.h>
+#else
+#include <unistd.h>
+#include <sys/time.h>
+#include <strings.h>
+#endif
+
+#include <kdemacros.h>
+
+typedef struct timeval_s {
+ long tv_sec; /* seconds */
+ long tv_usec; /* microseconds */
+} timeval_t;
+
+class KDE_EXPORT TimeWrapper {
+
+ public:
+ TimeWrapper();
+ ~TimeWrapper();
+ static void sleep(int sec);
+ static void usleep(unsigned long usec);
+ static void usleep(timeval_t* time);
+ static void gettimeofday(timeval_t* time);
+
+};
+#endif
diff --git a/mpeglib/lib/yuv/Makefile.am b/mpeglib/lib/yuv/Makefile.am
new file mode 100644
index 00000000..b8d7155d
--- /dev/null
+++ b/mpeglib/lib/yuv/Makefile.am
@@ -0,0 +1,28 @@
+# libplayerplugin - Makefile.am
+
+INCLUDES = $(all_includes)
+
+noinst_LTLIBRARIES = libyuvPlugin.la
+
+
+noinst_HEADERS =
+
+kmpgincludedir = $(includedir)/$(THIS_LIB_NAME)/decoder
+
+kmpginclude_HEADERS = yuvPlugin.h
+
+libyuvPlugin_la_SOURCES = yuvPlugin.cpp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/yuv/yuvPlugin.cpp b/mpeglib/lib/yuv/yuvPlugin.cpp
new file mode 100644
index 00000000..94697aa8
--- /dev/null
+++ b/mpeglib/lib/yuv/yuvPlugin.cpp
@@ -0,0 +1,158 @@
+/*
+ raw yuv stream player
+ 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 "yuvPlugin.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+YUVPlugin::YUVPlugin() {
+ init();
+}
+
+
+YUVPlugin::~YUVPlugin() {
+}
+
+
+void YUVPlugin::init() {
+ lCalcLength=false;
+ nWidth=0;
+ nHeight=0;
+ imageType=PICTURE_YUVMODE_CR_CB;
+ picPerSec=1.0;
+}
+
+
+void YUVPlugin::decoder_loop() {
+
+
+
+ cout << "YUVPlugin::decoder_loop() 1"<<endl;
+ if (input == NULL) {
+ cout << "YUVPlugin::decoder_loop input is NULL"<<endl;
+ exit(0);
+ }
+ if (output == NULL) {
+ cout << "YUVPlugin::decoder_loop output is NULL"<<endl;
+ exit(0);
+ }
+
+
+ PictureArray* pictureArray;
+
+
+ int bytes=nWidth*nHeight;
+
+ if ( (imageType == PICTURE_YUVMODE_CR_CB) ||
+ (imageType == PICTURE_YUVMODE_CB_CR) ) {
+ bytes=bytes+bytes/2;
+ }
+ if ( (imageType == PICTURE_RGB) ||
+ (imageType == PICTURE_RGB_FLIPPED) ) {
+ bytes=bytes*4;
+ }
+
+
+
+
+ // decode loop
+ while(runCheck()) {
+ switch(streamState) {
+ case _STREAM_STATE_FIRST_INIT :
+ output->openWindow(nWidth,nHeight,(char*)"yuv Viewer");
+ pictureArray=output->lockPictureArray();
+ cout << "pictureArray->setImageType"<<endl;
+ pictureArray->setImageType(imageType);
+
+ setStreamState(_STREAM_STATE_INIT);
+ break;
+ case _STREAM_STATE_INIT :
+ setStreamState(_STREAM_STATE_PLAY);
+ break;
+ case _STREAM_STATE_PLAY : {
+ // we read from input raw yuv bytes
+ // and display them.
+ pictureArray=output->lockPictureArray();
+ // now we have the color info
+ YUVPicture* pic=pictureArray->getPast();
+ unsigned char* dest=pic->getImagePtr();
+ input->read((char*)dest,bytes);
+ pic->setPicturePerSecond(picPerSec);
+ // now inform subsystem about the frame to display
+ pictureArray->setYUVPictureCallback(pic);
+ // display it
+ output->unlockPictureArray(pictureArray);
+
+ pictureArray->setYUVPictureCallback(NULL);
+ break;
+ }
+ case _STREAM_STATE_WAIT_FOR_END:
+ // exit while loop
+ lDecoderLoop=false;
+ cout << "mpegplugin _STREAM_STATE_WAIT_FOR_END"<<endl;
+ break;
+ default:
+ cout << "unknown stream state:"<<streamState<<endl;
+ }
+ }
+
+ cout << "*********mpegPLugin exit"<<endl;
+
+ output->flushWindow();
+ // copy sequence back if needed
+
+ cout << "delete mpegVideoStream"<<endl;
+
+}
+
+
+
+
+
+// here we can config our decoder with special flags
+void YUVPlugin::config(const char* key,const char* value,void* user_data) {
+ if (strcmp(key,"-c")==0) {
+ lCalcLength=false;
+ }
+
+ if (strcmp(key,"height")==0) {
+ nHeight=atoi(value);
+ }
+ if (strcmp(key,"width")==0) {
+ nWidth=atoi(value);
+ }
+ if (strcmp(key,"imageType")==0) {
+ imageType=atoi(value);
+ cout << "imageType:"<<imageType<<endl;
+ }
+ if (strcmp(key,"picPerSec")==0) {
+ picPerSec=atoi(value);
+ }
+ DecoderPlugin::config(key,value,user_data);
+}
+
+
+
+int YUVPlugin::getSongLength() {
+ int back=0;
+ return back;
+}
+
+
+
+
+
+
diff --git a/mpeglib/lib/yuv/yuvPlugin.h b/mpeglib/lib/yuv/yuvPlugin.h
new file mode 100644
index 00000000..4a5dc72b
--- /dev/null
+++ b/mpeglib/lib/yuv/yuvPlugin.h
@@ -0,0 +1,47 @@
+/*
+ raw yuv stream player
+ 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 __YUVPLUGIN_H
+#define __YUVPLUGIN_H
+
+#include "../decoder/decoderPlugin.h"
+#include <kdemacros.h>
+
+class KDE_EXPORT YUVPlugin : public DecoderPlugin {
+
+ int lCalcLength;
+ int nWidth;
+ int nHeight;
+ int imageType;
+ float picPerSec;
+
+ public:
+ YUVPlugin();
+ ~YUVPlugin();
+
+ void decoder_loop();
+ void config(const char* key,const char* value,void* user_data);
+
+
+ private:
+ void init();
+
+ int getSongLength();
+
+
+};
+
+#endif